Javascript React Intl如何从变量切换区域设置和消息

Javascript React Intl如何从变量切换区域设置和消息,javascript,reactjs,ecmascript-6,create-react-app,react-intl,Javascript,Reactjs,Ecmascript 6,Create React App,React Intl,我正试图找出如何使用React-Intl更改语言。这是我的第一个React应用程序,它是用create React应用程序制作的,我没有使用Redux或Flux 在我的index.js中,我有以下代码: import React from 'react'; import ReactDOM from 'react-dom'; import TodoApp from './components/TodoApp'; import registerServiceWorker from './regist

我正试图找出如何使用React-Intl更改语言。这是我的第一个React应用程序,它是用create React应用程序制作的,我没有使用Redux或Flux

在我的index.js中,我有以下代码:

import React from 'react';
import ReactDOM from 'react-dom';
import TodoApp from './components/TodoApp';
import registerServiceWorker from './registerServiceWorker';
import './index.css';

// Bootstrap CSS libraries
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/css/bootstrap-theme.css';

import { IntlProvider, addLocaleData } from 'react-intl';
import intlEN from 'react-intl/locale-data/en';
import intlES from 'react-intl/locale-data/es';
import intlMessagesES from './i18n/locales/es.json';
import intlMessagesEN from './i18n/locales/en.json';

addLocaleData([...intlEN, ...intlES]);

/* Define your translations */
let i18nConfig = {
    locale: 'es',
    messages: intlMessagesES
};

let changeLanguage = (lang) => {
    i18nConfig = { locale: lang, messages: intlMessagesEN };
    return i18nConfig;
}

ReactDOM.render(
    <IntlProvider locale={ i18nConfig.locale } key={ i18nConfig.locale } messages={ i18nConfig.messages }>
        <TodoApp onChangeLanguage={changeLanguage} />
    </IntlProvider>,
    document.getElementById('root'));
registerServiceWorker();

你知道我的代码遗漏了什么吗??也许我对React-Intl有些不太了解。任何建议都会很有帮助,谢谢。

如果您从根目录中删除所有:

ReactDOM.render(<TodoApp />, document.getElementById('root'));
2) 更改changeLanguage函数(这次称为“onChangeLanguage”),此函数从子组件语言选择器接收“lang”:

onChangeLanguage(lang) {
        switch (lang) {
            case 'ES': i18nConfig.messages = intlMessagesES; break;
            case 'EN': i18nConfig.messages = intlMessagesEN; break;
            default: i18nConfig.messages = intlMessagesEN; break;
        }
        this.setState({ locale: lang });
        i18nConfig.locale = lang;
}
最后呈现:

render() {
        return (
            <IntlProvider key={ i18nConfig.locale } locale={ i18nConfig.locale }  messages={ i18nConfig.messages }>
                <div>
                    <Header onChangeLanguage={this.onChangeLanguage} />
                    // Other components ...
                </div>
            </IntlProvider>
        );
    }
render(){
返回(
//其他组件。。。
);
}

如果有人根本不明白,请发表评论!感谢@TomásEhrich

您可以使用redux管理您的区域设置和区域设置消息。只需在IntlProvider中添加一个密钥

import React,{Component}来自'React';
从'react intl'导入{IntlProvider};
类内部扩展组件{
render(){
让{locale,localeMessage,children}=this.props;
返回(
{儿童}
)
}
};
出口违约互换使用一个新的React,这很容易做到。创建包装器:

import React from "react";
import Types from "prop-types";
import { IntlProvider, addLocaleData } from "react-intl";
import en from "react-intl/locale-data/en";
import de from "react-intl/locale-data/de";
import deTranslation from "../../lang/de";
import enTranslation from "../../lang/en";

addLocaleData([...en, ...de]);

const Context = React.createContext();

class IntlProviderWrapper extends React.Component {
  constructor(...args) {
    super(...args);

    this.switchToEnglish = () =>
      this.setState({ locale: "en", messages: enTranslation });

    this.switchToDeutsch = () =>
      this.setState({ locale: "de", messages: deTranslation });

    // pass everything in state to avoid creating object inside render method (like explained in the documentation)
    this.state = {
      locale: "en",
      messages: enTranslation,
      switchToEnglish: this.switchToEnglish, 
      switchToDeutsch: this.switchToDeutsch 
    };
  }

  render() {
    const { children } = this.props;
    const { locale, messages } = this.state;
    return (
      <Context.Provider value={this.state}>
        <IntlProvider
          key={locale}
          locale={locale}
          messages={messages}
          defaultLocale="en"
        >
          {children}
        </IntlProvider>
      </Context.Provider>
    );
  }
}

export { IntlProviderWrapper, Context as IntlContext };
从“React”导入React;
从“道具类型”导入类型;
从“react intl”导入{IntlProvider,addLocaleData};
从“react intl/locale data/en”导入en;
从“react intl/locale data/de”导入de;
从“../../lang/de”导入反翻译;
从“../../lang/en”导入夹带;
addLocaleData([…en,…de]);
const Context=React.createContext();
类IntlProviderWrapper扩展了React.Component{
构造函数(…参数){
超级(…args);
this.switchToEnglish=()=>
this.setState({locale:“en”,messages:entransation});
this.switchToDeutsch=()=>
this.setState({locale:“de”,messages:deTranslation});
//以状态传递所有内容以避免在渲染方法内创建对象(如文档中所述)
此.state={
地点:“恩”,
信息:陷阱,
转学英语:这个,转学英语,
switchToDeutsch:this.switchToDeutsch
};
}
render(){
const{children}=this.props;
const{locale,messages}=this.state;
返回(
{儿童}
);
}
}
导出{IntlProviderWrapper,上下文为IntlContext};
然后使用该提供者和使用者:

import { Provider } from "react-redux";
import {  IntlProviderWrapper } from "./IntlContext";

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <IntlProviderWrapper>
          ...
        </IntlProviderWrapper>
      </Provider>
    );
  }
}
从“react redux”导入{Provider};
从“/IntlContext”导入{IntlProviderWrapper};
类应用程序扩展组件{
render(){
返回(
...
);
}
}
应用程序中的某个地方:

import React from "react";
import { Text, Button } from "native-base";
import { IntlContext } from "../IntlContext";

const LanguageSwitch = () => (
  <IntlContext.Consumer>
    {({ switchToEnglish, switchToDeutsch }) => (
      <React.Fragment>
        <button onClick={switchToEnglish}>
          English
        </button>
        <button onClick={switchToDeutsch}>
          Deutsch
        </button>
      </React.Fragment>
    )}
  </IntlContext.Consumer>
);

// with hooks
const LanguageSwitch2 = () => {
  const { switchToEnglish, switchToDeutsch } = React.useContext(IntlContext);
  return (
    <>
      <button onClick={switchToEnglish}>English</button>
      <button onClick={switchToDeutsch}>Deutsch</button>
    </>
  );
};

export default LanguageSwitch;
从“React”导入React;
从“本机基”导入{Text,Button};
从“./IntlContext”导入{IntlContext};
常量语言开关=()=>(
{({switchToEnglish,switchToDeutsch})=>(
英语
德国
)}
);
//用钩子
常量语言开关2=()=>{
const{switchToEnglish,switchToDeutsch}=React.useContext(IntlContext);
返回(
英语
德国
);
};
导出默认语言开关;
榜样

下面是一个更一般的解决方案


注意:目前react intl仍在使用旧的上下文API,但在未来的解决方案中,类似这样的解决方案可能会开箱即用。

这可能会有所帮助:谢谢@Calvin,不幸的是,其中一个用于Redux:(你往下看了吗?提到使用
道具。我想我一点也不明白,
IntlProvider
必须更改吗?如果
i18nConfig.locale
已经更改,不应该也更改
吗?谢谢@TomásEhrlich!!现在它工作了!!我会用我的解决方案发布一个答案。嗨,@tomaszmularczyk我尝试使用上面的代码和repo,但是添加时,我得到一个错误,说“type是无效的:--expected…但是get:undefined。”有什么办法可以帮上忙吗?@jae.phoenix你使用react version>=16.3吗?感觉你忘了从文件中导出它了。嗨,@tomaszmularczyk,是的,16.4.2。我使用了你的repo,它就是从那里导出的。在阅读文档时,一开始状态下传递更新程序函数
switchToEnglish
似乎很糟糕它变得更清楚了。Link但是如何在上下文本身上附加switchToEnglish,这样您就可以通过useContext(intlContext)在useEffect中访问它。switchToEnglish()?谢谢,但不幸的是,这个问题背后的想法是不使用Redux。它很有魅力,但是渲染方法中有一个小的修改:{this.onChangeLanguage.bind(this)}我知道这个问题很老了,但我也遇到了同样的问题。它几乎可以工作了,调用了onChangeLanguage方法,但没有更新翻译。
import { Provider } from "react-redux";
import {  IntlProviderWrapper } from "./IntlContext";

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <IntlProviderWrapper>
          ...
        </IntlProviderWrapper>
      </Provider>
    );
  }
}
import React from "react";
import { Text, Button } from "native-base";
import { IntlContext } from "../IntlContext";

const LanguageSwitch = () => (
  <IntlContext.Consumer>
    {({ switchToEnglish, switchToDeutsch }) => (
      <React.Fragment>
        <button onClick={switchToEnglish}>
          English
        </button>
        <button onClick={switchToDeutsch}>
          Deutsch
        </button>
      </React.Fragment>
    )}
  </IntlContext.Consumer>
);

// with hooks
const LanguageSwitch2 = () => {
  const { switchToEnglish, switchToDeutsch } = React.useContext(IntlContext);
  return (
    <>
      <button onClick={switchToEnglish}>English</button>
      <button onClick={switchToDeutsch}>Deutsch</button>
    </>
  );
};

export default LanguageSwitch;