简单说就是翻译一下,切换中英文,但毫不是把整个语言包放进去,那可不必,只是按需处理便可,那么如何制定一个优雅的国际化方案,才是须要重点研究的。前端
react-intl
库react-intl
是一个 Yahoo 公司出品的,有兴趣能够自行了解一下。react
安装:
yarn add react-intl
使用:
... import { IntlProvider } from "react-intl"; ... class Root extends Component { render() { const { global: { locale },//可枚举的值为"zh"和"en" } = this.props; return ( <IntlProvider locale={locale} messages={language.getData()[locale]}> <App /> </IntlProvider> ); } }
分析:git
IntlProvider
包裹一下。而后传入两个参数:github
locale
: 当前语言环境 。messages
:按需配置的语言包(下面重点分析)。至此基本装配够用了,其余“高玩”的配置有兴趣的能够继续探究。shell
配置语言包:
我们以 login 为例:app
en-US
:ide
const login = { "login.title": "User Center", "login.username": "please enter username", "login.usernameEmpty": "username cannot be empty!", "login.maxLength": "username is no more than 100 characters", }; export default login;
zh-CN
:函数
const login = { "login.title": "用户中心", "login.username": "请输入用户名", "login.usernameEmpty": "用户名不能为空!", "login.maxLength": "用户名不得多于100个字符", }; export default login;
... /* 引入 */ import { injectIntl } from "react-intl"; ... /* 注入专属国际化数据 */ @injectIntl class Login extends React.Component { constructor(props) { super(props); const { intl: { formatMessage }, } = this.props; /* 使用 */ message.warning(formatMessage({ id: "login.maxLength" })) } ... }
分析:优化
en-US
和zh-CN
目录下配置两个结构相同,值不一样的文件。react-intl
提供的injectIntl
高阶组件对所在组件进行包装,从而能够直接经过 props 得到国际化数据intl
。intl
中得到formatMessage
,传入片断id
,就能得到翻译的值。但有弊端:this
formatMessage
翻译,文件很少片断很少还行,要是都多呢?那岂不是要写不少行,每次 render 都去执行翻译函数,栗 🌰:... render() { const { intl: { formatMessage }, } = this.props; const { codeImage } = this.state; const usernamePlaceholder = formatMessage({ id: "login.username" }); const usernameEmpty = formatMessage({ id: "login.usernameEmpty" }); const passwordPlaceholder = formatMessage({ id: "login.password" }); const passwordEmpty = formatMessage({ id: "login.passwordEmpty" }); const codePlaceholder = formatMessage({ id: "login.code" }); const maxLength = formatMessage({ id: "login.maxLength" }); const pwdMaxLength = formatMessage({ id: "header_pwdMaxLength" }); const codeEmpty = formatMessage({ id: "login.codeEmpty" }); return ( <div className="loginpagewrap"> ... </div>) } ...
这明显不合理啊,得想个辙啊。
首先针对传统模式各个环节进行优化。
import BaseIntl from "./baseIntl"; let config = { light_searchSelect: { en: "searchSelect", zh: "联想select", }, light_baseSelect: { en: "baseSelect", zh: "基本select", }, light_computeNum: { en: "computeNum", zh: "计算值", }, }; export default new BaseIntl({ config });
一个文件解决,这多好,而且经过baseIntl
进行扩展,主要为其补充了共用的翻译片断,这样大大的解决了重复翻译片断的问题。
react-intl
定制一个属于咱们的高阶组件intlHoc
作这个高阶组件前,得先明确咱们不是破坏react-intl
,而是扩展 ta。
直接上代码:
import React from "react"; import { inject, observer } from "mobx-react"; import { injectIntl } from "react-intl"; import language from "SRC/language"; function hoc(id) { return function (WrappedComponent) { @injectIntl @inject("global") class IntlHoc extends React.Component { constructor(props) { super(props); const { global: { locale }, } = this.props; this.state = { formatedMessage: this.formatMessage(), localeFlag: locale, }; } formatMessage() { const { intl } = this.props; const { formatMessage } = intl; let targetArr = language.getIntlById(id); let trmpArr = {}; for (let key in targetArr) { trmpArr[key] = formatMessage({ id: key }); } return trmpArr; } shouldComponentUpdate() { const { global: { locale }, } = this.props; if (this.state.localeFlag !== locale) { this.setState({ localeFlag: locale, formatedMessage: this.formatMessage(), }); } return true; } render() { const { formatedMessage } = this.state; const props = Object.assign({}, this.props, { intlData: formatedMessage, }); return <WrappedComponent {...props} />; } } return IntlHoc; }; } export default hoc;
而后代替injectIntl
进行包装,栗 🌰:
... import injectInternational from "COMMON/hocs/intlHoc"; ... @injectInternational("light") class TempEdit extends Component { const { intlData } = this.props; render(){ return <div>{intlData.light_editting}</div> } }
分析:
formatMessage
翻译的方式,并将其在高阶组件内部统一作好以后,再将数据注入到组件props中,经过intlData获取,直接经过“.”的方式就能得到翻译,既简化了流程又避免了函数的多余执行。国际化是一件若是你不在乎ta,ta会让你很头疼,很痛苦的事情,像是一种习惯,仍是早养成为好,等最后再去弄,你会感叹怎么这么多东西要翻译,因此一套整合好的国际化解决方案就颇有用。
实行该国际化方案的🌰