hias-cli 翻译功能设计
很多前端项目一开始并不会完整规划国际化。业务推进一段时间后,页面、弹窗、按钮、状态、提示语已经散落在 Vue、React、JSX、工具函数和配置对象里。此时再手工迁移,工作量大,而且容易漏。
hias-cli 的翻译能力就是为这个阶段设计的:它不是简单地搜索中文再替换,而是尽量理解不同文件里的语法边界,把源语言文案迁移成国际化调用,并生成可维护的语言包。源码可以是中文,也可以是英文;英文源码会使用更严格的 UI 文案识别,避免把协议值、类名、路径、类型值误当作文案。
核心流程
一次 hias tf 大致会经历四步:
- 读取源文件,判断文件类型。
- 按源码语言提取文案,保留每段文案在源码中的位置。
- 生成 key,查询缓存或翻译服务,写入语言包。
- 把源文件中的中文替换为
$t或t调用。
这个流程看起来直接,但难点都藏在“文案边界”里。
为什么不能只靠正则
中文可能出现在很多地方:
<button>登录</button><input placeholder="请输入用户名" /><h1>留言({remarkList ? remarkList.length : 0})</h1>const message = '保存成功'它们替换后的语法并不一样。Vue 模板文本需要 {{ $t(...) }},属性需要变成动态绑定,JSX 文本需要 {t(...)},JS 字符串需要表达式调用。
如果只用正则,很容易把文件路径、正则表达式、注释、样式类名、TypeScript 类型、插值标点一起误处理。
缓存优先
真实项目里,机器翻译只能解决一部分问题。菜单名、状态名、按钮名、行业术语通常需要统一表达。
因此 hias-cli 支持先导入公司翻译表:
hias tci .\.hias\company.xlsx推荐表格:
| zh-CN | en-US | ja-JP |
|---|---|---|
| 登录 | Login | ログイン |
| 正常状态 | Normal Status | 正常状態 |
导入后,缓存会按语言方向组织:
{
"zh-CN|en-US": {
"登录": "Login"
},
"zh-CN|ja-JP": {
"登录": "ログイン"
}
}这样翻译过程可以优先使用人工词库,缺失时再调用翻译服务或回退原文。
面向边界的取词
翻译迁移真正影响体验的往往是边界细节。
例如:
<h1>留言({{ remarkList ? remarkList.length : 0 }})</h1>理想结果不是把左括号吞进文案:
<h1>{{ $t('demo.leave_a_message') }}{{ remarkList ? remarkList.length : 0 }})</h1>而是:
<h1>{{ $t('demo.leave_a_message') }}({{ remarkList ? remarkList.length : 0 }})</h1>另一个例子是资源路径:
<img src="@/assets/images/ssHome/供应商总数量.png" alt="供应商总数量" />src 是文件引用,不能翻译;alt 是可见语义,可以翻译。
现在的取词会进一步处理:
- JS/TS/JSX/TSX 和 Vue SFC
- Vue
<script setup lang="jsx">与<script setup lang="tsx"> - 模板字符串、可选链、
||和??兜底文案 - JSX/TSX 文本节点和自定义展示属性
- Vue 模板展示文本和展示属性
- 已处理的
$t(...)、this.$t(...)、t(...)跳过 - 注释、正则、样式、class/className、style、资源路径、TS 类型语法跳过
当某段代码确实不希望自动处理时,可以使用:
// @hias-i18n-ignore-next
/* @hias-i18n-ignore-start */
/* @hias-i18n-ignore-end */
// @hias-i18n-ignore-file报告和一致性检查
批量迁移时,取词是否全面、失败文件有哪些、语言包是否缺 key 都需要机器可读的结果。
tf / tfo 支持输出 JSON 报告:
hias tfo src\views views --dry-run --report .hias\reports\views.json翻译后可以执行:
hias tcheck src --report .hias\reports\tcheck.json它会检查源码引用了但语言包缺失的 key、语言包中未被源码引用的 key、不同 locale JSON 之间不一致的 key,以及无法解析的 JSON 文件。