React-intl 多语言应用程序:更改语言和翻译存储
Posted
技术标签:
【中文标题】React-intl 多语言应用程序:更改语言和翻译存储【英文标题】:React-intl multi language app: changing languages and translations storage 【发布时间】:2016-06-17 01:03:09 【问题描述】:我有 react-router 应用程序并想添加 i18n。在 react-intl example 根组件中包裹在 IntlProvider 中:
ReactDOM.render(
<IntlProvider locale="en">
<App />
</IntlProvider>,
document.getElementById('container')
);
但是只有一种语言环境。如何更新应用程序以添加其他语言以及存储翻译的最佳方式是什么?
【问题讨论】:
【参考方案1】:我遇到了同样的问题,这就是我发现的:
为了更改语言,我使用了here 提供的解决方案,它基本上是通过 Connect 函数将 IntlProvider 绑定到 ReduxStore。另外不要忘记在语言更改时包含重新渲染组件的键。这基本上是所有代码:
这是ConnectedIntlProvider.js,只是绑定了默认的IntlProvider(注意github原始评论中缺少的key prop)
import connect from 'react-redux';
import IntlProvider from 'react-intl';
// This function will map the current redux state to the props for the component that it is "connected" to.
// When the state of the redux store changes, this function will be called, if the props that come out of
// this function are different, then the component that is wrapped is re-rendered.
function mapStateToProps(state)
const lang, messages = state.locales;
return locale: lang, key: lang, messages ;
export default connect(mapStateToProps)(IntlProvider);
然后在你的入口点文件中:
// index.js (your top-level file)
import ConnectedIntlProvider from 'ConnectedIntlProvider';
const store = applyMiddleware(thunkMiddleware)(createStore)(reducers);
ReactDOM.render((
<Provider store=store>
<ConnectedIntlProvider>
<Router history=createHistory()>routes</Router>
</ConnectedIntlProvider>
</Provider>
), document.getElementById( APP_DOM_CONTAINER ));
接下来要做的就是实现 reducer 来管理语言环境,并让动作创建者按需更改语言。
至于存储翻译的最佳方式 - 我发现很多关于这个主题的讨论和情况似乎很混乱,老实说,我很困惑 react-intl 的制造商如此关注日期和数字格式而忘记了翻译.所以,我不知道绝对正确的处理方法,但这就是我所做的:
创建文件夹“locales”并在其中创建一堆文件,如“en.js”、“fi.js”、“ru.js”等。基本上所有您使用的语言。 在每个文件中导出 json 对象,翻译如下:
export const ENGLISH_STATE =
lang: 'en',
messages:
'app.header.title': 'Awesome site',
'app.header.subtitle': 'check it out',
'app.header.about': 'About',
'app.header.services': 'services',
'app.header.shipping': 'Shipping & Payment',
其他文件具有完全相同的结构,但内部包含已翻译的字符串。
然后在负责语言更改的 reducer 中,从这些文件中导入所有状态,并在调度更改语言的操作后立即将它们加载到 redux 存储中。您在上一步中创建的组件会将更改传播到 IntlProvider 并且将发生新的语言环境。使用 <FormattedMessage>
或 intl.formatMessage(id: 'app.header.title')
在页面上输出它,在他们的 github wiki 上阅读更多信息。
他们那里有一些DefineMessages功能,但老实说我找不到任何好的信息如何使用它,基本上你可以忘记它并没问题。
【讨论】:
它与 redux 完美配合。我用阿波罗尝试了这种方法,但它不起作用。我很绝望。【参考方案2】:有了新的 Context 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 ;
主App.jsx组件:
import Provider from "react-redux";
import IntlProviderWrapper from "./IntlContext";
class App extends Component
render()
return (
<Provider store=store>
<IntlProviderWrapper>
...
</IntlProviderWrapper>
</Provider>
);
LanguageSwitch.jsx
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;
我创建了一个 repository 来展示这个想法。 还有codesandbox example。
【讨论】:
效果很好。我只是好奇是否可以用 useContext 来代替。所以你可以使用上下文(IntlContext)并将switchToEnglish等附加到上下文? @Dac0d3r 当然,只需要导出整个上下文,检查编辑并链接到代码框。 非常感谢。看起来很棒,正是我需要的!!这值得 imo。成为公认的答案。 :-) Tomasz 我确实在这里创建了一个相关问题:***.com/questions/55541089/… 所以我可以删除它,或者您可以简单地链接到您的答案,我会接受它 - 由您决定 :-) @Dac0d3r 很高兴它有帮助!以上是关于React-intl 多语言应用程序:更改语言和翻译存储的主要内容,如果未能解决你的问题,请参考以下文章