Reactjs React intl多语言应用程序:更改语言和翻译存储

Reactjs React intl多语言应用程序:更改语言和翻译存储,reactjs,internationalization,formatjs,react-intl,Reactjs,Internationalization,Formatjs,React Intl,我有react路由器应用程序,希望添加i18n。在IntlProvider中包装的react intl根组件中: ReactDOM.render( <IntlProvider locale="en"> <App /> </IntlProvider>, document.getElementById('container') ReactDOM.render( , document.getElementById('容器') )) 但只有一个地区。如何更

我有react路由器应用程序,希望添加i18n。在IntlProvider中包装的react intl根组件中:

ReactDOM.render(
<IntlProvider locale="en">
    <App />
</IntlProvider>,
document.getElementById('container')
ReactDOM.render(
,
document.getElementById('容器')
))


但只有一个地区。如何更新应用程序以添加其他语言,以及存储翻译的最佳方式是什么

我也遇到了同样的问题,我发现:

为了改变语言,我使用了提供的解决方案,该解决方案基本上是使用Connect函数将IntlProvider绑定到ReduxStore。另外,不要忘记在语言更改时包含重新渲染组件的键。这基本上就是所有代码:

这是ConnectedIntlProvider.js,仅绑定默认IntlProvider(注意github上原始注释中缺少的密钥属性)

从'react redux'导入{connect};
从'react intl'导入{IntlProvider};
//此函数将当前redux状态映射到它“连接”到的组件的道具。
//当redux存储区的状态发生变化时,如果从
//如果此函数不同,则将重新渲染包裹的组件。
函数MapStateTops(状态){
const{lang,messages}=state.locales;
返回{locale:lang,key:lang,messages};
}
导出默认连接(MapStateTops)(IntlProvider);
然后在入口点文件中:

//index.js(您的顶级文件)
从“ConnectedIntlProvider”导入ConnectedIntlProvider;
conststore=applyMiddleware(thunkMiddleware)(createStore)(reducers);
ReactDOM.render((
{routes}
),document.getElementById(APP_DOM_CONTAINER));
接下来要做的就是实现用于管理区域设置的reducer,并让动作创建者根据需要更改语言

至于存储翻译的最佳方式——我发现关于这个话题的许多讨论和情况似乎都很混乱,老实说,react intl的制作者如此关注日期和数字格式而忘记了翻译,我感到非常困惑。所以,我不知道绝对正确的处理方法,但我就是这么做的:

创建文件夹“locales”,并在其中创建一组文件,如“en.js”、“fi.js”、“ru.js”等。基本上所有语言都可以使用。
在每个文件中,导出json对象并进行如下转换:

export const ENGLISH\u STATE={
朗:"嗯",,
信息:{
'app.header.title':'Awesome site',
'app.header.subtitle':'签出',
'app.header.about':'about',
'app.header.services':'services',
“app.header.shipping”:“shipping&Payment”,
}
}
其他文件具有完全相同的结构,但其中包含已翻译的字符串。
然后,在负责语言更改的reducer中,从这些文件导入所有状态,并在发送更改语言的操作后立即将其加载到redux存储中。在上一步中创建的组件将把更改传播到IntlProvider,并将发生新的区域设置。使用
intl.formatMessage({id:'app.header.title'})在页面上输出它
,在他们的github wiki上阅读更多关于它的内容。

他们有一些DefineMessages函数,但老实说,我找不到任何关于如何使用它的好信息,基本上你可以忘记它,一切正常。

有了新的上下文API,我相信现在不需要使用redux:

IntlContext.jsx

import React from "react";
import { IntlProvider, addLocaleData } from "react-intl";
import en from "react-intl/locale-data/en";
import de from "react-intl/locale-data/de";

const deTranslation = { 
  //... 
};
const enTranslation = { 
  //... 
};

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 };
import React from "react";
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;
从“react intl”导入{IntlProvider,addLocaleData};
从“react intl/locale data/en”导入en;
从“react intl/locale data/de”导入de;
常量反翻译={
//... 
};
常数夹带={
//... 
};
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};
App.jsx组件:

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(){
返回(
...
);
}
}
LanguageSwitch.jsx

import React from "react";
import { IntlProvider, addLocaleData } from "react-intl";
import en from "react-intl/locale-data/en";
import de from "react-intl/locale-data/de";

const deTranslation = { 
  //... 
};
const enTranslation = { 
  //... 
};

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 };
import React from "react";
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;
从“/IntlContext”导入{IntlContext};
常量语言开关=()=>(
{({switchToEnglish,switchToDeutsch})=>(
英语
德国
)}
);
//带挂钩:
常量语言开关2=()=>{
const{switchToEnglish,switchToDeutsch}=React.useContext(IntlContext);
返回(
英语
德国
);
};
导出默认语言开关;
我已经创建了一个演示这个想法的模型。
而且。

它与redux完美配合。我用阿波罗号试过这种方法,但就是不起作用。我很绝望,效果很好。我只是好奇是否可以用useContext来代替。所以你可以使用上下文(IntlContext)并将switchToEnglish等附加到上下文中?@Dac0d3r当然,这只需要导出整个上下文,检查编辑并链接到codesandbox。非常感谢。看起来很棒,正是我需要的!!这应该是我接受的答案。:-)托马斯一世