背景
最近在做的一个新项目在接入CDP数据平台项目时,CDP平台已经支持了国际化语言切换功能(如下图),因此作为集成到CDP的子应用项目需要尽快完善国际化功能;
国际化简介
什么是国际化?
这里说的前端国际化,是指需要将页面中一些静态文本转化成对应的语言,也就是一套代码能支持多语言切换;
为什么要国际化?
当我们的业务扩展到海外,使用者来自不同国家,为了方便海外用户群体的使用,就有了这样的需求和必要;
准备工作
在正式开始代码开发之前,需要了解一些平台和安装一些工具,我们统一将这些零散的事务放到这个章节来讲述。
项目技术栈
最开始先要知道当前项目的技术栈:**React + Antd + Redux ,**这样大家就知道我们所处的项目环境;
Crowdin平台
什么是Crowdin?
官方网站:Crowdin | Localization Management Platform for agile teams
Crowdin是一个tms ( Translation Management System ) 系统,一个在线项目翻译协作平台
功能 & 角色
我们将项目代码中需要翻译的内容提取出来,上传到Crowdin平台上,由项目中PM来在平台上进行翻译,翻译完成后,前端开发人员再下载到前端项目中使用;
注册 & 使用流程
大家可以跟着这里的步骤进行操作
-
注册一个账号
-
创建一个项目
-
建立一个集成方式,这里我们选vscode
-
点击下载,在vscode上安装crowdin插件
-
配置crowdin.yml文件
我的crowdin.yml文件是这样配置的
"project_id": ****
"api_token": "****"
"base_path": ""
"preserve_hierarchy": true
"files": [
{
"source": "/locales/extract/en.json",
"translation": "/locales/translations/%two_letters_code%/%original_file_name%",
}
]
接着来看下配置文件中的几个参数:
- project_id:就是上面说的创建的项目的ID
- api_token:需要在个人中心设置中生成,用来鉴权
- base_path: 基础路径,这里没写就是当前目录根路径
- preserve_hierarchy: true 上传到tms后,是否保留文件目录,如果不设置,上传后在tms上没有目录层级;
- files > source: 需要上传的文件位置
- files > translation: 从Crowdin平台下载翻译好的文件,所要存放的位置和名字
-
vsCode中的效果
提取 & 编译需要的包
react-intl
安装
npm i -S react-intl
功能:信息标识,标识需要翻译的字符串内容
使用示例
babel-plugin-formatjs
功能:简单来讲,就是处理那些字符串信息用于翻译,特别是针对使用了react-intl的模块
安装
npm i babel-plugin-formatjs
配置
// babel.config.json
{
"plugins": [
[
"formatjs",
{
"idInterpolationPattern": "[sha512:contenthash:base64:6]",
"ast": true
}
]
]
}
参数说明:
idInterpolationPattern : id生成模式,如果检查到的信息标识符没有定义ID,则使用这个pattern去自动生成ID
ast: 将defaultMessage预解析进入AST,以提高运行时性能。
更多参数可见官网;
@formatjs/cli
功能
js格式化cli工具,这个工具有两个作用:
一是提取,对使用了react-intl的指定文件进行提取;
二是编译,对翻译完成的文件编译为react-intl可消费的JSON文件。
安装
npm i -D @formatjs/cli
命令
这里直接给出命令的示例,接着说明两个命令各个参数的意义;
formatjs extract
formatjs extract "src/**/*.{js,tsx}" --out-file locales/extract/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]' --format crowdin
- --format crowdin :将提取的内容按照某个格式转成TMS所需要的格式,使用crowdin即可对接Crowdin平台
- --out-file [path] :输出文件地址,输出一个集合的json文件到目标文件目录,这个json是所提供文件的所有待翻译内容;
- --id-interpolation-pattern [pattern] :ID生成规则,如果某些消息描述符没有id,则此模式将用于自动为它们生成id
formatjs compile
formatjs compile locales/translations/en/en.json --ast --out-file src/locales/en.json --format crowdin
参数同上,把 locales/translations/en/en.json 编译输出到 src/locales/en.json
script命令配置
为了方便,我们配置一下package.json的script命令:
"scripts": {
...
"extract": "formatjs extract 'src/**/*.{js,jsx,tsx}' --out-file locales/extract/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]' --format crowdin",
"compile": "formatjs compile locales/translations/en/en.json --ast --out-file src/locales/en.json --format crowdin"
}
开发工作流
-
代码开发
使用IntlProvider组件包裹业务组件
// /src/index.js
import { IntlProvider } from 'react-intl';
...
<IntlProvider messages={Messages} locale="" defaultLocale="">
<Router>
<App path={path} />
</Router>
</IntlProvider>
...
使用react-intl标记待翻译内容, 这里有两种方式
第一种,使用**intl.formatMessage**
import { useIntl } from 'react-intl';
...
const { formatMessage } = useIntl();
...
// jsx中
{formatMessage({
id:"layout.koc",
defaultMessage:"KOC分析"
})}
第二种,使用**<FormattedMessage/>**
import { FormattedMessage } from 'react-intl';
// jsx 中
<FormattedMessage
id="koc.breadcrumb"
defaultMessage="用户 {refSdkU} 的一'度'粉丝列表"
values={{ refSdkU }}
/>
-
执行命令提取
npm run extract // 注意这里实际上是执行的 formatjs extract 'src/**/*.{js,jsx,tsx}' --out-file locales/extract/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]' --format crowdin
得到的结果如下,对应的信息内容还是中文
-
上传提取文件
在vsCode 中上传上一步提取的文件,上传的方法就是:点击vsCode 中Crowdin页面的上传按钮,如图
-
在crowdin平台翻译
在平台上,进入到当前项目,到content 下,可以看到我们刚刚提取并上传的文件;
接着进入到home页,开始翻译
接着点击翻译全部
进入到沉浸式翻译模式,可以看到,Crowdin提供了翻译建议,辅助你进行更高效的翻译工作;
-
下载翻译文件
在vsCode 中下载翻译好的文件,下载方式即:在vsCode的Crowdin页面点击下载,下载后可以看到对应文件夹已得到翻译好的JSON文件;
-
执行命令编译
npm run compile // 注意这里实际上是执行的 formatjs compile locales/translations/en/en.json --ast --out-file src/locales/en.json --format crowdin
编译完得到的结果如下图,这也就是我们刚刚反复提到的可以被react-intl 直接消费的JSON文件;
-
引入编译文件
在代码中引入编译后的内容, 注意这里呼应了第一步代码开发中的内容,IntlProvider 的messages 参数就是编译好的文件~
至此,你可以看到你的项目已经实现国际化啦~
Q & A
1.项目版本迭代时,如何解决版本问题,是否需要重新翻译?
项目迭代时,待翻译内容有新增时,新的部分会在上传平台后显示出来,就可以继续翻译;
你可能担心,如果待翻译内容有变更时,怎么办? 如果只是变更(不改标识的ID),在上传crowdin平台时,会有变更提示,如下:
如果确认继续上传,则会显示如下,即:有一项删除一项增加;
那么此时,pm可以有感知的去重新翻译变更的内容。
2.如何支持多种语言?
一种语言对应一个json翻译文件,crowdin负责管理所有翻译文件,要在项目代码中管理语言切换时,选用哪一个翻译文件;
3.服务端内容是否受到国际化影响?
如果目前服务端返回内容不存在大量翻译内容,可以不做服务端的国际化,当然如果要做,这套方案也同样支持;
在我们项目中有一个下载接口,需要下载不同语言文件,这个接口已经单独做了处理;