前端「国际化」解决方案

5,223 阅读6分钟

背景

最近在做的一个新项目在接入CDP数据平台项目时,CDP平台已经支持了国际化语言切换功能(如下图),因此作为集成到CDP的子应用项目需要尽快完善国际化功能;

国际化简介

什么是国际化?

这里说的前端国际化,是指需要将页面中一些静态文本转化成对应的语言,也就是一套代码能支持多语言切换;

为什么要国际化?

当我们的业务扩展到海外,使用者来自不同国家,为了方便海外用户群体的使用,就有了这样的需求和必要;

准备工作

在正式开始代码开发之前,需要了解一些平台和安装一些工具,我们统一将这些零散的事务放到这个章节来讲述。

项目技术栈

最开始先要知道当前项目的技术栈:**React + Antd + Redux ,**这样大家就知道我们所处的项目环境;

Crowdin平台

什么是Crowdin?

官方网站:Crowdin | Localization Management Platform for agile teams

Crowdin是一个tms ( Translation Management System ) 系统,一个在线项目翻译协作平台

功能 & 角色

我们将项目代码中需要翻译的内容提取出来,上传到Crowdin平台上,由项目中PM来在平台上进行翻译,翻译完成后,前端开发人员再下载到前端项目中使用;

注册 & 使用流程

大家可以跟着这里的步骤进行操作

  1. 注册一个账号

  2. 创建一个项目

  1. 建立一个集成方式,这里我们选vscode

  1. 点击下载,在vscode上安装crowdin插件

  2. 配置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平台下载翻译好的文件,所要存放的位置和名字
  1. vsCode中的效果

提取 & 编译需要的包

react-intl

安装

npm i -S react-intl

功能:信息标识,标识需要翻译的字符串内容

使用示例

babel-plugin-formatjs

官网:formatjs.io/docs/toolin…

功能:简单来讲,就是处理那些字符串信息用于翻译,特别是针对使用了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

官网:formatjs.io/docs/toolin…

功能

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"
}

开发工作流

  1. 代码开发

使用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 }}
/>
  1. 执行命令提取

    npm run extract // 注意这里实际上是执行的 formatjs extract 'src/**/*.{js,jsx,tsx}' --out-file locales/extract/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]' --format crowdin

得到的结果如下,对应的信息内容还是中文

  1. 上传提取文件

在vsCode 中上传上一步提取的文件,上传的方法就是:点击vsCode 中Crowdin页面的上传按钮,如图

  1. 在crowdin平台翻译

在平台上,进入到当前项目,到content 下,可以看到我们刚刚提取并上传的文件;

接着进入到home页,开始翻译

接着点击翻译全部

进入到沉浸式翻译模式,可以看到,Crowdin提供了翻译建议,辅助你进行更高效的翻译工作;

  1. 下载翻译文件

在vsCode 中下载翻译好的文件,下载方式即:在vsCode的Crowdin页面点击下载,下载后可以看到对应文件夹已得到翻译好的JSON文件;

  1. 执行命令编译

    npm run compile // 注意这里实际上是执行的 formatjs compile locales/translations/en/en.json --ast --out-file src/locales/en.json --format crowdin

编译完得到的结果如下图,这也就是我们刚刚反复提到的可以被react-intl 直接消费的JSON文件

  1. 引入编译文件

在代码中引入编译后的内容, 注意这里呼应了第一步代码开发中的内容,IntlProvider 的messages 参数就是编译好的文件~

至此,你可以看到你的项目已经实现国际化啦~

Q & A

1.项目版本迭代时,如何解决版本问题,是否需要重新翻译?

项目迭代时,待翻译内容有新增时,新的部分会在上传平台后显示出来,就可以继续翻译;

你可能担心,如果待翻译内容有变更时,怎么办? 如果只是变更(不改标识的ID),在上传crowdin平台时,会有变更提示,如下:

如果确认继续上传,则会显示如下,即:有一项删除一项增加;

那么此时,pm可以有感知的去重新翻译变更的内容。

2.如何支持多种语言?

一种语言对应一个json翻译文件,crowdin负责管理所有翻译文件,要在项目代码中管理语言切换时,选用哪一个翻译文件;

3.服务端内容是否受到国际化影响?

如果目前服务端返回内容不存在大量翻译内容,可以不做服务端的国际化,当然如果要做,这套方案也同样支持;

在我们项目中有一个下载接口,需要下载不同语言文件,这个接口已经单独做了处理;