前言
最近公司要把几个没有做过国际化的老项目接入国际化,其中有react也有vue的项目。看了好几篇写国际化的文章,效果我都觉得不太好,什么“终极方案”,并没有很方便。于是自己写了一个。注:本文用到的eslint插件开发相关功能,eslint相关的api不过多细讲
方案
首先,这个方法react和vue可以通用。原理是:
- 通过自定义eslint插件,检查代码的时候自动收集中文,然后形成一个大的json
- 丢给chapgpt翻译,这样中英文的json都得到了
- 通过eslint的自动修复功能,将代码中的中文替换为i18n语法
效果
直接看测试用例吧
{
code: `<span>测试</span>`,
output: `<span>{t('es.test')}</span>`,
},
{
code: `<span title="测试"></span>`,
output: `<span title={t('es.test')}></span>`,
},
{
code: `export const A = {b: '测试'}`,
output: `export const A = {b: t('es.test')}`,
},
实现(以react为例)
初始化eslint插件
中文收集
create(context) {
const sourceCode = context.getSourceCode()
return {
Literal (node) {
addCnData(node.value)
},
JSXText (node) {
addCnData(node.value)
},
// 模板语法,去掉前后引号
TemplateLiteral (node) {
addCnData(sourceCode.getText(node).slice(1, -1))
}
}
}
react的中文收集比较简单,AST只需要捕获Literal
、JSXText
、TemplateLiteral
这三种类型即可,然后用addCnData
方法将收集到的中文字符保存起来
async function addCnData (value) {
if (typeof value !== 'string') return
// 删除多余换行和空格
const val = value.replaceAll('\r', '').replaceAll('\n', '').trim()
if (!val) return
// 匹配中文
if(/.*[\u4e00-\u9fa5]+.*$/.test(val)) {
// 将中文追加写入文件
const writeHandle = await fs.open('D:\yourpath\chinese.js', 'a')
await writeHandle.appendFile(val + '---\n')
}
}
- 将
chinese.js
中的中文整理成如下格式
module.exports = {
"测试": "es.test"
}
中文替换成i18n语法
同样的方法创建新的规则:setChinese
create(context) {
return {
Literal (node) {
// cnJson为上述chinese.js里的对象
if (cnJson[node.value]) {
context.report({
node,
loc: node.loc,
messageId: `err1`,
fix: fixer => {
if (node.parent.type === 'JSXAttribute') {
return fixer.replaceTextRange(node.range, `{t('es.test')}`)
} else {
return fixer.replaceTextRange(node.range, `t('es.test')`)
}
}
})
}
},
JSXText (node) {
if (cnJson[node.value]) {
context.report({
node,
loc: node.loc,
messageId: `err2`,
fix: fixer => {
return fixer.replaceTextRange(node.range, `{t('es.test')}`)
}
})
}
}
}
},
代码很简单,TemplateLiteral节点涉及i18n的变量,需要手动处理下,就不用自动化修复了。
使用
- 因为没有发布npm,用
npm link
命令本地调试 - 假设我们的插件名叫
eslint-plugin-i18n
,在你的eslint配置文件中加入
plugins: ['i18n'],
rules: {
'i18n/getChinese': 2
}
- 执行
eslint src --fix --ext .js,.jsx
,收集中文并翻译 - 将rules替换为
'i18n/setChinese': 2
- 重复执行
eslint src --fix --ext .js,.jsx
,只需等待片刻,你的代码就自动修改完成了
总结
vue的处理也是同理,只不过是把AST节点换一换。eslint的功能十分强大,在日常开发中好好利用下可以提升很多效率。当然我也尝试过直接用babel来改代码,但是babel重新generate的时候,会无法保持原来的代码格式(有知道的大佬可以指点下),所以最后还是选择了eslint来处理。
原文链接:https://juejin.cn/post/7341533476663312447 作者:Ref_Aimer