簡單說就是翻譯一下,切換中英文,但毫不是把整個語言包放進去,那可不必,只是按需處理便可,那麼如何制定一個優雅的國際化方案,纔是須要重點研究的。前端
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會讓你很頭疼,很痛苦的事情,像是一種習慣,仍是早養成爲好,等最後再去弄,你會感嘆怎麼這麼多東西要翻譯,因此一套整合好的國際化解決方案就頗有用。
實行該國際化方案的🌰