国际化方案
在 ICE 模板 PRO 中,基于 react-intl 实现了国际化,支持中英文双语言切换,你也可以按照以下文档应用到其他模板项目。
国际化的核心步骤
- 创建资源文件,以
key: value
方式存储 - 加载资源文件,将页面上
key
的内容替换为相关value
创建资源文件
在多语言环境下,一般涉及的转换较多,因此在 PRO 模板中我们按照页面维度对 key:value
进行组织,有利于拆分维护。
.
├── dist
├── src
│ └── locales // 多语言文件存放目录,推荐按照页面进行组织
│ ├── en-US
│ │ ├── page1.js
│ │ ├── page2.js
│ │ └── index.js
│ │
│ └── zh-CN
│ ├── page1.js
│ ├── page2.js
│ └── index.js
└── package.json
多语言约定
在开发中我们约定在 src/locales
目录下约定国际化资源文件
- 多语言文件的命名规范:
<lang>-<COUNTRY>.js
- 多语言文件的内容规范:
key:value
组成的字面量,该文件的写法如下:
zh-CN.js
export default {
'app.pageName.componentName.title': '你好,ICE',
};
en-US.js
export default {
'app.pageName.componentName.title': 'Hello,ICE',
};
加载资源文件
根据当前环境的语言,获取对应的国际化资源创建 react-intl 国际化上下文组件。react-intl 提供了一个类似 redux 一样的 Provider Component,用与提供国际化的上下文:
// 引入 react-intl 多语言包
import en from 'react-intl/locale-data/en';
import zh from 'react-intl/locale-data/zh';
// 引入 locale 配置文件
import en_US from './locales/en-US';
import zh_CN from './locales/zh-CN';
// 设置语言包
addLocaleData([...en, ...zh]);
const localeInfo = {
'zh-CN': {
appLocale: 'zh',
appMessages: zh_CN,
},
'en-US': {
appLocale: 'en',
appMessages: en_US,
},
};
ReactDOM.render(
<IntlProvider // react-intl Provider
locale={localeInfo[locale].appLocale} // 当前语言环境: zh、cn、etc...
messages={localeInfo[locale].messages} // 当前语言包,翻译所需的 key-value 对象
>
{React.Children.only(children)}
</IntlProvider>,
document.getElementById('root')
);
通常一个单页项目只有一个 IntlProvider,当然 IntlProvider 是支持嵌套的。 IntlProvider 有三个入参:
- locale: 例如 ‘zh’ ‘en’
- messages: 翻译所需的 key-value 对象
- formats: 自定义 format,比如日期格式等自定义
在定义好 IntlProvider 之后,我们就可以在页面使用它提供的 api 或者组件来进行国际化。完成示例参考:PRO
基础组件国际化配置
以上国际化配置方案主要是基于自定义的业务组件,在实际项目中,我们还需要对依赖的基础组件也进行国际化处理,保持一致性。
指定多语言文案
通过 <ConfigProvider locale={localeObj}>
传入语言包,以支持多语言。目前基础组件包内置的 locale
库支持中英繁日四种语言,覆盖各组件的简单词汇,例如:确定、取消、展开、收起、下一页等, 简单词汇映射表可参考 基础组件多语言文案
ConfigProvider
提供简单组件简单词汇国际化能力,由于日期时间的国际化较为特殊,例如中国的日历是从周一到周日,美国的日历是从周日到周六等,时间相关的组件如 DatePicker 等需要国际化,请查看相应组件文档。
如何使用
- 引入基础组件的语言包
- 根据当前语言环境配置 ConfigProvider
// 引入 react-intl 多语言包
import en from 'react-intl/locale-data/en';
import zh from 'react-intl/locale-data/zh';
+ // 引入 locale 配置文件
+ import en_US from './locales/en-US';
+ import zh_CN from './locales/zh-CN';
// 设置语言包
addLocaleData([...en, ...zh]);
const localeInfo = {
'zh-CN': {
+ nextLocale: zhCN,
appLocale: 'zh',
appMessages: zh_CN,
},
'en-US': {
+ nextLocale: enUS,
appLocale: 'en',
appMessages: en_US,
},
};
ReactDOM.render(
<IntlProvider // react-intl Provider
locale={localeInfo[locale].appLocale} // 当前语言环境: zh、cn、etc...
messages={localeInfo[locale].messages} // 当前语言包,翻译所需的 key-value 对象
>
<ConfigProvider
locale={localeInfo[locale].nextLocale} // 基础组件语言包配置
>
{React.Children.only(children)}
</ConfigProvider>
</IntlProvider>,
document.getElementById('root')
);
常见用法
一般国际化场景的用法主要有两种:
- 文案(需要自己配置好不同语言)
- 日期(直接交给 intl 处理即可)
格式化字符串
在 src/locales
新建 en-US.js
和 zh-CN.js
文件:
// en-US.js
export default {
'app.page.componentName.title': 'Hello,ICE',
}
// zh-CN.js
export default {
'app.page.componentName.title': '你好,飞冰',
}
在组件中我们可以通过 react-intl 提供组件的方式调用,也可以通过其 API 方式进行调用:
通过组件的形式
import { FormattedMessage } from 'react-intl';
export default () => {
return <FormattedMessage id="app.page.componentName.title" />;
};
通过 API 的形式
import { injectIntl } from 'react-intl';
const App = ({ intl }) => (
<div>{intl.formatMessage({ id: 'app.page.componentName.title' })}</div>
);
export default injectIntl(App);
日期时间
<FormattedDate />
用于格式化日期,能够将一个时间戳格式化成不同语言中的日期格式,传入时间戳作为参数:
import { FormattedDate } from 'react-intl';
<FormattedDate value={new Date(1550229406000)} />;
由于 react-intl 是基于开源项目 formatjs,除了提供组件调用的方式,还支持语言、时间、货币等等的国际化。更多 API 请参考 react-intl