语言包应按语言独立文件组织(如locales/zh-Hans.json),结构扁平、键名对齐、路径统一;文档用README.i18n.md明确支持语言、新增步骤和本地验证方法;切换时只更新带data-i18n属性的元素,保留表单状态;CI通过key比对、UTF-8校验及BCP 47格式正则强制规范。

语言包文件怎么组织才便于长期维护
把所有语言塞进一个 locales.json 里,或者按模块拆成 common.json、form.json 再嵌套三层对象,都是后期翻车高发区。键名不一致、缺失字段、加载顺序错乱,全由此起。
必须坚持三个硬约束:
- 每个语言一个独立文件:
locales/zh-Hans.json、locales/en.json、locales/ja.json - 所有文件结构扁平,键名完全对齐,哪怕某语言还没翻译也得留空字符串:
"btn_submit": "" - 路径固定、命名统一,不带环境前缀(如
locales/prod/zh.json),避免构建时路径错位
嵌套结构看着“模块化”,实则让 data-i18n="ui.header.title" 这种写法在 JS 查 key 时多一层遍历,还容易因深拷贝或引用丢失导致 fallback 失效。
怎么写文档才能让新成员三天内上手切换语言
别写“国际化流程说明.pdf”。直接在项目根目录放一个 README.i18n.md,只回答三件事:当前支持哪些语言码、新增语言要改哪 4 个地方、怎么本地验证是否生效。
立即学习“前端免费学习笔记(深入)”;
示例条目必须可执行:
- 新增语言
fr:复制locales/en.json→ 改名为locales/fr.json→ 填写键值 → 提交后 CI 会自动校验键名一致性 - 验证方式:
http-server -p 8080启服务 → 浏览器访问http://localhost:8080/?lang=fr→ 检查document.documentElement.lang是否为fr,且所有data-i18n元素文本已替换 - 关键检查点:打开 DevTools → Elements 面板 → 随机点一个
<input placeholder="Search">→ 看它是否有data-i18n-placeholder属性;没有?说明标记漏了
如何避免语言切换破坏已有功能状态
常见错误是调用 i18n.translate() 时无差别替换所有节点,结果 <select></select> 的选中项丢了、<textarea></textarea> 的光标跳到开头、第三方组件(如日历)重置为默认语言。
真正安全的更新逻辑只做三件事:
- 只遍历带
data-i18n或对应后缀属性(如data-i18n-title)的元素,跳过所有表单控件的value - 更新前用
getSelection().getRangeAt(0)记录光标位置,更新后用range.selectNodeContents()恢复(仅限contenteditable) - 对
<input type="date">、<input type="number">这类原生控件,不碰其value,只更新关联的<label></label>和title
千万别用 innerHTML = translatedHTML 替换整个 <form></form> —— 事件监听器、Vue/React 组件实例、甚至 input.addEventListener('input', ...) 都会消失。
CI/CD 里怎么卡住低级错误
靠人眼 review JSON 文件?永远会漏掉 "submit_btn" 在 en.json 里是 "Submit",但在 zh-Hans.json 里写成了 "提交按钮"(应为 "提交")这种语义偏差。
必须加两道机器检查:
- Git commit hook 跑脚本:比对所有
locales/*.json的顶层 key 数量和名称,不一致立刻exit 1 - CI pipeline 加 YAML 校验:用
jq检查每个文件是否含非法字符(如中文冒号、全角空格)、是否所有字符串值都为 UTF-8 编码、是否有键值为空但非空格字符串("key": " "是合法的,"key": ""是占位符)
最易被忽略的是 BCP 47 格式校验 —— zh_CN、zh-china、Chinese 全部会被浏览器静默忽略,必须用正则 ^[a-z]{2,3}(-[a-z]{2,})?$ 卡住。



















