之前專案採用了react-intl做多語言切換,記錄一下。
大體的實現原理和react-redux的實現原理類似,最外層包一個Provider,利用getChildContext,將intlConfigPropTypes存起來,在FormattedMessage、FormattedNumber等元件或者呼叫injectIntl生成的高階元件中使用,來完成國際化的。
使用過程也非常簡單,和react-redux的使用方法非常類似。
國際化資原始檔內容
目前我們管理資原始檔的方式是在 src/locales 資料夾下:
.
├── en-US.js
├── en-US.messages.js
├── zh-CN.js
└── zh-CN.messages.js複製程式碼
注意: 檔案命名、變數命名,是有規律的
*.messages.js 是我們的資原始檔(這裡我們採用了 js 格式,你也可以使用 json 等等),返回的是一個物件,key 為我們翻譯用的 id,value 為具體語言的翻譯,內容是:
const login={
'username':'Username',
'new_user':'new user?'
}
const reset={
'reset.title':'Reset Your Password',
}
const en_US = {
...login,
...reset
};
export default en_US;複製程式碼
en-US.js 檔案封裝了 messages、locale 等國際化上下文元件需要的內容:
import datePickerLocale from 'antd/lib/date-picker/locale/en_US';
import appLocaleData from 'react-intl/locale-data/en';
import messages from './en-US.messages.js';
import antdEn from 'antd/lib/locale-provider/en_US';
window.appLocale = {
// 合併所有 messages,加入 antd 元件的 messages
messages: Object.assign({}, messages, {
datePickerLocale,
}),
// locale語言標記
locale: 'en-US',
// react-intl locale-data
data: appLocaleData,
antd:antdEn,
// 自定義 formates
formats: {
date: {
normal: {
hour12: false,
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
},
},
},
};
export default window.appLocale;
複製程式碼
有了這些資原始檔以及相關的封裝之後,我們就可以在 InltProvider
中使用了。
使用
可以用Component來定義字串:
<FormattedMessage
id="CopyButton.text"
defaultMessage="複製"
/>複製程式碼
第二種,如果有些地方用不了Component,例如 Input 的
placeholder,這時候可以使用HOC把翻譯的Function以props傳遞進去:
injectIntl(Component);
this.props.intl.formatMessage(...);複製程式碼
挖坑記錄
IntlProvider中的屬性變更並不會觸發FormattedMessage重新渲染,剛開始想要forceUpdate強制更新元件,後來上網查了一個解決方案,在元件中加入key,就能解決這個問題,但大型複雜專案不建議使用這種解決方案,因為會引起此<IntlProvider>
包裹下的所有元件全部被更新。