react-intl 國際化多語言方案

ReneeTsang發表於2019-03-11

之前專案採用了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>包裹下的所有元件全部被更新。


相關文章