theme: cyanosis
highlight: atom-one-dark
作者在接手vue老项目时,有多次遇到需要把项目进行国际化的需求。而项目里通常有大量散落的中文硬编码,要一个个把中文找出来,提取到json语言包里,再用i18n国际化标记对源码里的中文进行替换,这个过程非常费时费力。我就考虑在github
上找一找有什么工具能够自动处理下,且能够满足以下几点要求:
- 自动提取项目里的中文到json语言包
- 自动将源码里的中文替换成i18n标记
- 自动翻译成多种语言
遇到的问题
-
提取和翻译二者难以两全,有的工具要么仅支持提取转换中文,要么仅支持翻译。如果要满足的我开发需求得安装两套工具
-
代码转换的准确率低。开源项目里大多数对中文进行提取转换的工具是基于正则表达式实现的,这种做法的最大缺点是缺少上下文语义的分析。比如对下面模板字符串的转换
`测试${a}`
使用正则替换的工具通常错误的转换成
`this.$t('测试')${a}`
而正确的应该是
`${this.$t('测试')}${a}`
导致这个错误的原因就在于工具没分析出这个中文出现在模板字符串里(虽然对于正则大佬还是能处理这种bug,但是要考虑的场景非常之多)
-
转化工具可定制程度较低。由于市面上像
vue-i18n
、react-intl
等i18n库特别多,它们的国际化标记往往是不统一的,有的是this.$t('xxx')
形式,有的是t('xx')
形式。如果转化工具不支持用户定制i18的函数名和调用对象,就很难适配不同的i18n库 -
框架支持度单一。大部分提取工具仅支持vue或react
鉴于我找到的工具大部分都存在问题1和问题2,于是我决定自己动手实现了一个自动提取中文并翻译的命令行工具,让整个国际化流程可以实现自动化。
解决方案
整体流程
首先我们通过glob
工具遍历项目目录下的文件,利用Nodejs读取文件源码,借助babel
工具我们可以很方便的在遍历的过程中对每个节点进行处理:
traverse(ast, {
enter() {
// 判断是否跳过i18n转换
...
},
StringLiteral() {
// 处理字符串里的中文
...
},
TemplateLiteral() {
// 处理模板字符串里的中文
...
},
JSXText() {
// 处理jsx文本节点里的中文
...
},
JSXAttribute() {
// 处理jsx属性里的中文
...
},
CallExpression() {
// 处理表达式里的中文
...
},
ImportDeclaration() {
// 根据配置加入导入声明
...
}
})
在遍历的过程中,同时将中文以key-value
的形式保存到json文件中:
// 目录结构:
src
├── locales
│ ├── en-US.json
│ └── zh-CN.json
└── index.js
// zh-CN.json
{
"我是中文": "我是中文",
"嗯": "嗯"
}
遍历完成后,最后以zh-CN.json
为蓝本,调用谷歌或有道翻译,翻译成其他语言包。
翻译规则
翻译时要考虑一种特殊情况,假如项目里之前已经存在翻译好的语言包。如果主语言和目标语言存在相同的key。那么目标语言包里key对应的value,不会被重新翻译,而是复用原来的值。这是考虑到英文翻译后,有时会遇到文字超出容器宽度,影响到布局样式,为了解决这个问题,国际化实践中,开发者往往会用更短的同义词替换长的单词,如果我们二次翻译时把用户替换好的单词又覆盖掉,用户就不得不自己重新替换一遍。
vue文件的处理
对于vue文件处理有点特殊,直接使用babel是无法直接对其进行解析的。这时我们可以使用vue官方提供的@vue/compiler-sfc
工具,将文件拆成html,js,css三个部分,分别去解析。
其中css可以跳过直接用源码,js部分依然用babel处理,html部分我们可以使用htmlparser2
工具解析:
new htmlparser2.Parser({
onopentag(){
// 处理html属性里的中文
...
},
ontext(){
// 处理文本节点里的中文
...
},
oncomment() {
// 判断是否跳过转换
...
}
})
解析完后,再将html,js和css三部分重新组装起来即可。
最后
以上就是我的一个实现思路,目前做出来的自动化工具已开源,项目地址为https://github.com/IFreeOvO/i18n-cli。
包含功能
- 支持.mjs.cjs.js.ts.jsx.tsx.vue 后缀文件提取中文
- 支持 vue2.0,vue3.0,react 提取中文
- 支持通过/i18n-ignore/注释,忽略中文提取
- 支持将提取的中文以 key-value 形式存入*.json 语言包里
- 支持 prettier 格式化代码
- 支持将中文语言包自动翻译成其他语言
- 自定义语言包的 key
- 自定义 i18n 工具的调用对象
- 自定义 i18n 工具的方法名
- 自定义 i18n 第三方包的导入
使用中如遇bug或者有好的想法建议,可以在issues里提出。当然,有能力的朋友也可以直接提PR。
暂无评论内容