国际化方案

在 ICE 模板 PRO 中,基于 react-intl 实现了国际化,支持中英文双语言切换,你也可以按照以下文档应用到其他模板项目。

预览国际化示例模板

国际化的核心步骤

  • 创建资源文件,以 key: value 方式存储
  • 加载资源文件,将页面上 key 的内容替换为相关 value

创建资源文件

在多语言环境下,一般涉及的转换较多,因此在 PRO 模板中我们按照页面维度对 key:value 进行组织,有利于拆分维护。

  1. .
  2. ├── dist
  3. ├── src
  4. └── locales // 多语言文件存放目录,推荐按照页面进行组织
  5. ├── en-US
  6. ├── page1.js
  7. ├── page2.js
  8. └── index.js
  9. └── zh-CN
  10. ├── page1.js
  11. ├── page2.js
  12. └── index.js
  13. └── package.json

多语言约定

在开发中我们约定在 src/locales 目录下约定国际化资源文件

  • 多语言文件的命名规范:<lang>-<COUNTRY>.js
  • 多语言文件的内容规范:key:value 组成的字面量,该文件的写法如下:

zh-CN.js

  1. export default {
  2. 'app.pageName.componentName.title': '你好,ICE',
  3. };

en-US.js

  1. export default {
  2. 'app.pageName.componentName.title': 'Hello,ICE',
  3. };

加载资源文件

根据当前环境的语言,获取对应的国际化资源创建 react-intl 国际化上下文组件。react-intl 提供了一个类似 redux 一样的 Provider Component,用与提供国际化的上下文:

  1. // 引入 react-intl 多语言包
  2. import en from 'react-intl/locale-data/en';
  3. import zh from 'react-intl/locale-data/zh';
  4. // 引入 locale 配置文件
  5. import en_US from './locales/en-US';
  6. import zh_CN from './locales/zh-CN';
  7. // 设置语言包
  8. addLocaleData([...en, ...zh]);
  9. const localeInfo = {
  10. 'zh-CN': {
  11. appLocale: 'zh',
  12. appMessages: zh_CN,
  13. },
  14. 'en-US': {
  15. appLocale: 'en',
  16. appMessages: en_US,
  17. },
  18. };
  19. ReactDOM.render(
  20. <IntlProvider // react-intl Provider
  21. locale={localeInfo[locale].appLocale} // 当前语言环境: zh、cn、etc...
  22. messages={localeInfo[locale].messages} // 当前语言包,翻译所需的 key-value 对象
  23. >
  24. {React.Children.only(children)}
  25. </IntlProvider>,
  26. document.getElementById('root')
  27. );

通常一个单页项目只有一个 IntlProvider,当然 IntlProvider 是支持嵌套的。 IntlProvider 有三个入参:

  • locale: 例如 ‘zh’ ‘en’
  • messages: 翻译所需的 key-value 对象
  • formats: 自定义 format,比如日期格式等自定义

在定义好 IntlProvider 之后,我们就可以在页面使用它提供的 api 或者组件来进行国际化。完成示例参考:PRO

基础组件国际化配置

以上国际化配置方案主要是基于自定义的业务组件,在实际项目中,我们还需要对依赖的基础组件也进行国际化处理,保持一致性。

指定多语言文案

通过 <ConfigProvider locale={localeObj}> 传入语言包,以支持多语言。目前基础组件包内置的 locale 库支持中英繁日四种语言,覆盖各组件的简单词汇,例如:确定、取消、展开、收起、下一页等, 简单词汇映射表可参考 基础组件多语言文案

ConfigProvider 提供简单组件简单词汇国际化能力,由于日期时间的国际化较为特殊,例如中国的日历是从周一到周日,美国的日历是从周日到周六等,时间相关的组件如 DatePicker 等需要国际化,请查看相应组件文档。

如何使用

  • 引入基础组件的语言包
  • 根据当前语言环境配置 ConfigProvider
  1. // 引入 react-intl 多语言包
  2. import en from 'react-intl/locale-data/en';
  3. import zh from 'react-intl/locale-data/zh';
  4. + // 引入 locale 配置文件
  5. + import en_US from './locales/en-US';
  6. + import zh_CN from './locales/zh-CN';
  7. // 设置语言包
  8. addLocaleData([...en, ...zh]);
  9. const localeInfo = {
  10. 'zh-CN': {
  11. + nextLocale: zhCN,
  12. appLocale: 'zh',
  13. appMessages: zh_CN,
  14. },
  15. 'en-US': {
  16. + nextLocale: enUS,
  17. appLocale: 'en',
  18. appMessages: en_US,
  19. },
  20. };
  21. ReactDOM.render(
  22. <IntlProvider // react-intl Provider
  23. locale={localeInfo[locale].appLocale} // 当前语言环境: zh、cn、etc...
  24. messages={localeInfo[locale].messages} // 当前语言包,翻译所需的 key-value 对象
  25. >
  26. <ConfigProvider
  27. locale={localeInfo[locale].nextLocale} // 基础组件语言包配置
  28. >
  29. {React.Children.only(children)}
  30. </ConfigProvider>
  31. </IntlProvider>,
  32. document.getElementById('root')
  33. );

常见用法

一般国际化场景的用法主要有两种:

  • 文案(需要自己配置好不同语言)
  • 日期(直接交给 intl 处理即可)

格式化字符串

src/locales 新建 en-US.jszh-CN.js 文件:

  1. // en-US.js
  2. export default {
  3. 'app.page.componentName.title': 'Hello,ICE',
  4. }
  5. // zh-CN.js
  6. export default {
  7. 'app.page.componentName.title': '你好,飞冰',
  8. }

在组件中我们可以通过 react-intl 提供组件的方式调用,也可以通过其 API 方式进行调用:

通过组件的形式

  1. import { FormattedMessage } from 'react-intl';
  2. export default () => {
  3. return <FormattedMessage id="app.page.componentName.title" />;
  4. };

通过 API 的形式

  1. import { injectIntl } from 'react-intl';
  2. const App = ({ intl }) => (
  3. <div>{intl.formatMessage({ id: 'app.page.componentName.title' })}</div>
  4. );
  5. export default injectIntl(App);

日期时间

<FormattedDate /> 用于格式化日期,能够将一个时间戳格式化成不同语言中的日期格式,传入时间戳作为参数:

  1. import { FormattedDate } from 'react-intl';
  2. <FormattedDate value={new Date(1550229406000)} />;

由于 react-intl 是基于开源项目 formatjs,除了提供组件调用的方式,还支持语言、时间、货币等等的国际化。更多 API 请参考 react-intl