背景
开源项目 js-analyzer(一个可视化的前端依赖分析工具) 有了英语 issues, 不过目前项目内各种操作信息都还都是中文,准备将项目支持国际化,方便更多人使用。如果你还没使用过这个工具,也可以去 guthub 了解一下~
准备
因为是 vue3 项目,网上一搜,全是使用 i18n,说实话,个人觉得这个维护起来真的特别别扭。既要要定义变量名,还要维护多个语言文件..... 我的项目不大,场景也简单,搞这个太重了,主要是维护起来太痛苦了。
// i18n.ts
import { createI18n } from 'vue-i18n'
const messages = { en: {
message: {
hello: 'hello world'
}
},
ja: {
message: {
hello: 'こんにちは、世界'
}
}
}
const i18n = createI18n({
locale: 'en',
messages
})
export default i18n
初步设想
感觉可以把所有的语言定义在一个对象里,然后通过系统的需要自动切换取值。
// 定义
const languageMap = {
"关系图": { "en": "Relationship Map", "ja": "関係図" },
}
// 使用
const type = 'en'
const text = languageMap['关系图'][type]
收集中文
接下来,就是要全局查找项目中的中文字符串,我们可以使用正则表达式找出所有中文 [\u4e00-\u9fa5]+
复制出所有中文放到一个文本编辑器里
关系图
包管理
热 词
隐式引用
默认标题
导出信息
我的项目
项目管理
....
AI 生成翻译和 JSON
传统的做法,就是一个一个手动写,还得用词典一个一个翻译成各种语言,这个过程真的很痛苦,还记得我早些年做的一个项目使用 in18 做国际化,这个过程我花了整整 3 天!一个一个去翻译、复制、粘贴。这还仅仅是中文翻译成英文,更别说其他语言了。
所以想让 AI 生成帮助我们想要的 JSON 格式,例如:
{
"关系图": { "en": "Relationship Map", "ja": "関係図" },
...
}
将刚刚复制出所有中文+提示一起发送给 AI,内容如下:
引用列表
引用次数
引用名
引用源
引用文件
...
将上面的列表转换成如下格式的json列表:
{
'{上面的某一项}': { 'en': '{对应的英文翻译}', 'ja': '{对应的日语翻译}' },
...
}
回答结果:
{
"关系图": { "en": "Relationship Map", "ja": "関係図" },
"包管理": { "en": "Package Management", "ja": "パッケージ管理" },
"热词": { "en": "Hot Words", "ja": "ホットワード" },
"隐式引用": { "en": "Implicit Reference", "ja": "暗黙の参照" },
"默认标题": { "en": "Default Title", "ja": "デフォルトのタイトル" },
"导出信息": { "en": "Export Information", "ja": "情報をエクスポートする" },
"我的项目": { "en": "My Project", "ja": "私のプロジェクト" },
"项目管理": { "en": "Project Management", "ja": "プロジェクト管理" },
// 更多省略.....
}
结果出乎意料的好,几秒钟就生成好了我项目所有的语言配置信息。
这里我使用的是 coze, 模型选择:GPT4 Turbo 128k,其他参数默认
代码示例
自定义国际化的全部代码
// language.ts
import { computed } from "vue"
type Lang = 'en' | 'ja'
const defaultLanguage = 'zh_CN'
// 支持的语言列表
export const languageOptions = [
{ value: 'en', label: 'English' },
{ value: 'zh_CN', label: '中文(简体)' },
]
// 翻译映射
export const languageMap = {
"关系图": { "en": "Relationship Map", "ja": "関係図" },
"包管理": { "en": "Package Management", "ja": "パッケージ管理" },
"热词": { "en": "Hot Words", "ja": "ホットワード" },
"隐式引用": { "en": "Implicit Reference", "ja": "暗黙の参照" },
"默认标题": { "en": "Default Title", "ja": "デフォルトのタイトル" },
// 更多省略.....
} as const
// 获取翻译文本
export function $tf(text: keyof typeof languageMap) {
const language = localStorage.getItem('language') || defaultLanguage
if (language === defaultLanguage) return text
return languageMap[text][language as Lang]
}
// 切换语言
export function switchLanguage (type: Lang) {
localStorage.setItem('language', type)
window.location.reload()
}
使用:
// test.ts
import { $tf, switchLanguage } from '@/language';
// 已存在的文本
const test = $tf('关系图')
// 映射表里不存在的文本, ts 会报错
const test = $tf('关系图1') // error: 类型“"导出信息1"”的参数不能...
// 切换语言
switchLanguage('en')
切换语言后,我使用 window.location.reload()刷新当前系统,是因为项目不存在什么表单信息,可以直接刷新,不影响体验。
批量替换
上面已经准备好了翻译库,接下来就是将项目中的所有中文调用 $tf()获取文本,这里我们使用正则一键替换:
- 中文字符串替换
-
正则:
(['"][\u4e00-\u9fa5]+[^'"]+['"]) -
替换:
$tf($1)
- vue template 中文字符串替换
-
正则:
>([\u4e00-\u9fa5]+) -
替换:
>{{$tf('$1')}}
- 处理漏网之鱼
肯定还有一些没被正确替换的,我们还是继续用 [\u4e00-\u9fa5]+ 正则去搜索检查,看看是不是所有的中文都被处理。
- 收尾工作
这样,我们就可以把大部分字符串一键替换,不过还有一些收尾工作:
-
修正自动替换错误的内容。
-
补全 import 信息。
-
不同语言长度不一致,我们还需要切换不同的语言,修正页面样式到合适的宽度。
完成效果
英语
日语
总结
到此为止,整个国际化的工作就完成了。以上只是提供一种思路,当然,如果你的使用的 i18n, 同样也可以使用 AI 生成自定义的 json。核心 promt 如下:
{list}
将上面的列表转换成如下格式的json列表:
{
'{上面的某一项}': { 'en': '{对应的英文翻译}', 'ja': '{对应的日语翻译}' },
...
}
希望能帮助到你~