data-i18n 必须精确标注每个文本节点,lang 属性需逐层显式设置,JSON 语言包须扁平且键名一致,动态内容插入后须立即调用翻译函数,DOM 深度不得超过 6 层。

data-i18n 必须打到每个文本节点,不是“加个 class 就行”
JS 翻译逻辑只认 data-i18n 属性,不看 class、id 或内容本身。漏标一个,那一段文字就永远卡在原始语言里,控制台还不会报错。
常见漏标场景:
-
<option>文字必须单独加data-i18n,父级<select data-i18n="country_select">不会自动递归翻译子项 -
<label>里的文本要标,但for属性值(如for="email")是 DOM ID 引用,不翻译;若 ID 本身含语义(如id="submit_btn"),建议保持英文不变 -
<svg>内的<text>节点也要加data-i18n,SVG 不是“纯图形”,文字节点参与渲染和朗读 -
<script>和<style>里写data-i18n完全无效——它们不输出可见文本
lang 属性不能只改 documentElement,得逐层同步
只执行 document.documentElement.lang = 'zh-Hans',对已存在的 <p>、<h2>、<footer> 等元素毫无作用。浏览器和屏幕阅读器严格按每个元素自己的 lang 属性决定字体回退、标点宽度、语音语调——不继承。
正确做法:
立即学习“前端免费学习笔记(深入)”;
- 初始化时,除根节点外,所有含文本的语义化标签(
<h1>、<section>、<article>、<blockquote>等)必须显式设lang="zh-Hans" - 切换语言时,需遍历所有已有
lang属性的元素:保留明确需要多语言混排的(如<pre lang="bash">、<q lang="ja">),其余统一更新为当前语言码 - BCP 47 格式必须严格:用
zh-Hans,不用zh_CN或chinese,否则部分浏览器直接忽略
DOM 深度超 6 层会导致 data-i18n 被跳过
当 data-i18n 出现在 <div><div><div><div><div><p data-i18n="tip"></p></div></div></div></div></div> 这类纯布局嵌套中,JS 遍历逻辑或 SSR 初始化脚本常因性能阈值截断,导致最内层节点根本没被扫描到——文字不更新,也没错误提示。
解决方式:
- 用开发者工具右键目标元素 → “Reveal in Elements panel”,手动数从
<body>到该节点的层级,确保 ≤6 - 把冗余
<div>替换为语义标签:<main>、<section>、<aside>等天然构成作用域边界,既利于 SEO,也帮 i18n 工具识别范围 - 动态插入的内容(如 AJAX 加载的表格行、弹窗内容)必须在
appendChild()后立即调用翻译函数,不能等全局扫描
JSON 语言包结构必须扁平,加载失败必须 fallback
语言包一旦嵌套(如 {"form": {"login": {"btn": "登录"}}),JS 查找 form.login.btn 就得做路径解析,容易出错;而扁平结构 {"form_login_btn": "登录"} 直接查 key,稳定、快、无歧义。
关键约束:
- 每个语言一个文件:
locales/zh-Hans.json、locales/en-US.json,内容全是顶层键值对 - 所有文件键名必须完全一致;某语言暂未翻译,填空字符串
"nav_help": ""或占位符"nav_help": "[未翻译]",避免返回undefined导致留白 -
fetch()必须包try/catch,捕获TypeError: Failed to fetch和 404;fallback 顺序:完整码(zh-HK)→ 主语言码(zh)→ 内置默认对象(硬编码英文) - 服务端返回 JSON 时,响应头必须含
Content-Type: application/json,否则response.json()可能静默失败
data-i18n 都落到该落的地方、每处 lang 都及时同步、每次动态插入都触发翻译——这些细节不靠工具自动兜底,得靠结构约束和人眼确认。



















