前端页面支持多语言 I8N 改造当前项目好费劲

9 天前
 ljlljl0
当前是先开发的中文版本 web 项目,页面数量挺多的,50 来个 VUE 页面。现在想支持英语,发现从头改造一遍好费劲。每个页面都得调整。

想了解下大家开发阶段是怎么做的?新开的项目的时候就支持还是说像我这样先国内版本后国外版本去支持呢?
2027 次点击
所在节点    程序员
17 条回复
apkapb
9 天前
半途添加肯定麻烦,慢慢纵使 ai 弄呗。


最开始老虎到 i18n ,做起来就稍微简单点
iMusic
9 天前
我们是后期才考虑加国际化的,改造花了半个月。先用脚本提取文字,记录页面上的位置,然后 AI 翻译,手动替换。

社区有个方案,编译的时候自动 AI 翻译+替换
kinfuy
9 天前
dssxzuxc
9 天前
如果是 vue-i18n ,我试过三种做法

一:单文件自定义块
```
<i18n>
{
"zh-CN": {
"a": "xxx"
},
"en-US": {
"a": "yyy"
}
}
</i18n>
```
优点是可以快速搞定,AI 工具一直 Tab 就行了,大部分时间花在看 vue-i18n 文档,缺点是零散在几十几百个 vue 文件里,适合那种特别老的项目,不想额外管理 i18n 文件,且页面和文字几乎不会再改动。

二:json 文件
重构 i18n 确实烦人,但是如果还想正常迭代项目只能重构。将所有中文文本抽离出来,大致分类一下,再让 AI 一次性翻译完英文,然后手动一个个去替换原始文本 t('xxx.yyy')。我建议二层嵌套就行,顶多三层嵌套。

三:ts 文件
事先声明我这属于瞎折腾,用 json 方案就行了。
i18n-ally 和 vue-i18n 在 ts 文件上都有一些坑,搞了好久总算能用了,但是跟 json 方案比差不了多少。
这是我的 i18n-ally 的 vscode 配置文件
"i18n-ally.enabledFrameworks": ["vue"],
"i18n-ally.enabledParsers": ["ts"],
"i18n-ally.parsers.typescript.compilerOptions": {
"moduleResolution": "node"
}
这样就能正常识别 ts 文件

这是我的 i18n/index.ts 文件
import zhCN from './locales/zh-CN'
import enUS from './locales/en-US'

const messages: Record<I18n.Language, I18n.LocaleMessage> = {
'zh-CN': zhCN,
'en-US': enUS,
}

const i18n = createI18n({
locale: getStorage(StorageKeyEnum.language, 'zh-CN'),
fallbackLocale: 'en',
messages,
legacy: false,
})

export function setupI18n(app: App) {
app.use(i18n)
}

export function setLocale(locale: I18n.Language) {
i18n.global.locale.value = locale
}

export const t = i18n.global.t

LocaleMessage 是我的翻译文本类型
大概这样
type LocaleMessage = {
icon: {
...
}
route: {
...
}
tab: {
...
}
table: {
...
}
}

然后可以递归得到所有 key 的联合类型
type GetI18nKey<T, K extends keyof T = keyof T> =
K extends string ?
T[K] extends Record<string, unknown> ?
`${K}.${GetI18nKey<T[K]>}`
: K
: never

type I18nKey = GetI18nKey<LocaleMessage>

type RouteKey = GetI18nKey<LocaleMessage, 'route'>
type TableKey = GetI18nKey<LocaleMessage, 'table'>

在你需要硬编码比如路由元信息等地方用 I18nKey 类型进行限定就能完全消除硬编码
zhuangzhuang1988
9 天前
i18n-ally + 人肉提取 没那么复杂的。
规划翻译字段类型,通用的,枚举的。
一般枚举的 我会先提取这样的。

/**
*$t('enum.E_MessageType .Warning')
*$t('enum.E_MessageType .Error')
*/
enum E_MessageType {
/**
* 警告
*/
Warning,
/**
* 错误
*/
Error,
}

上面注释会被 i18n-ally 识别的,然后提取到翻译。

代码层, 页面(模板)层。 注入一个 $enumTrans 的翻译对象。
$enumTrans 包含各种枚举, 可以通过一些 js 动态功能 + ts 类型处理。
类似这样,
<script setup lang="ts">
const { $enumTrans } = useI18nExt()

let msgType = E_MessageType.Warning
function showMsg() {
console.log($enumTrans.MessageType(msgType))
}
</script>
<template>
<div>
{{$enumTrans.MessageType(msgType)}}
</div>
</template>
zhuangzhuang1988
9 天前
提取翻译不是难的,难得是页面排版,特别是中文几个字,到英文变成了十几个字,页面各种乱
raolight
8 天前
改现有项目的话,工作量有点大,我最近也有在改,OP 可以看一下这个翻译的方案,离线+在线翻译,每个页面都自动翻译完之后自己手动设置离线翻译还行,不过可能还需要 ai 润色一下🤔

https://translate.zvo.cn/
ljlljl0
8 天前
@zhuangzhuang1988 之前翻译过一次,也遇到这个问题了,后面放弃了。最近项目完善了,还是要回头重新搞,太头疼了。
zhuangzhuang1988
8 天前
@ljlljl0 我也是,就一个新加坡客户,要加英文,翻译得累死
lisongeee
8 天前
只是想快速提取的话,可以试试 https://github.com/lisonge/i18n-ast-convert
Thecosy
7 天前
我直接用 claude 一键 i18 了。半天搞定。https://www.icecmspro.com
ljlljl0
7 天前
@Thecosy 我项目内容太多了。另外我看你这个好像内容没有转,只是菜单支持的吧,内容多了这块 AI 也不太好用。
itodouble657
7 天前
我也有个疑惑 后台表怎么设计比较好 例如公告、消息提醒还有各种文档的中英文
xiaogenban
6 天前
哈哈哈,这个我上半年也在干,1500 个 thymeleaf 模板页面,做成双语,几个后端和我一起改的,那叫一个难受,没想到啥捷径
laobaiguolai
6 天前
免费使用,几行代码就搞定。https://translate.zvo.cn/4019.html
eyelly
5 天前
ljlljl0
5 天前
手动翻译了,目前还比较顺利,估计在有一周能翻译完。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1152739

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX