html多语言国际化必须显式为每个含文本的语义化标签设置lang属性,逐层覆盖而非依赖继承;data-i18n需扩展至placeholder/title/alt等所有可翻译属性,动态dom插入后须立即调用translatenode()翻译,且结构嵌套深度不得超过6层。

HTML结构化数据本身不参与国际化翻译,但它是语言切换时语义正确、渲染合规、无障碍可用的底层支撑——漏掉它,lang属性就只是个摆设,data-i18n标记再全也救不了标点错位、字体覆盖、屏幕阅读器乱读。
lang 属性必须逐层写在语义化标签上,不能靠继承
只改 document.documentElement.lang = 'zh-HK',<p></p> 里的顿号还是英文间距,<pre class="brush:php;toolbar:false;" lang="bash"></pre> 的代码字体被中文字体撑开,<img alt="logo"> 的替代文本仍被读作英文。因为浏览器和屏幕阅读器根本不查父级 lang,只认元素自己有没有、值对不对。
- 所有含文本的语义化标签(
<h1></h1>、<p></p>、<section></section>、<footer></footer>)都得显式加lang,值与当前语言包一致 -
<pre class="brush:php;toolbar:false;" lang="bash"></pre>、<code lang="sql">这类已有明确语言用途的元素,切换语言时保留原lang值,不覆盖 -
<script></script>和<style></style>内部写lang没用,它们不参与文本渲染
data-i18n 必须覆盖所有可翻译属性,不只是 textContent
只给 <button>提交</button> 加 data-i18n="btn_submit",但漏掉 placeholder 或 aria-label,结果输入框提示永远是英文,辅助技术播报内容错位,表单点击失效。
- 每个要翻译的元素至少有一个基础
data-i18n键;含placeholder就额外加data-i18n-placeholder;同理data-i18n-title、data-i18n-alt -
value属性一般不翻译(属于用户输入数据),跳过处理;但<label for="email"></label>的文字必须标记,且for属性要与目标id严格同步 - 含 HTML 结构的文案(如“请阅读使用条款”)必须用
innerHTML替换,语言包里对应值要是可信纯 HTML 片段,否则有 XSS 风险
动态插入的 DOM 必须手动触发翻译,不会自动监听
AJAX 加载的弹窗、分页表格新行、<template></template> 克隆后插入,里面的 data-i18n 标记只是字符串,不调用翻译函数就不会变成对应语言文本——而且控制台完全不报错,只能靠肉眼排查漏翻。
- 每次
appendChild()或insertAdjacentElement()后,立刻调用封装好的translateNode(node)函数遍历子树 -
<template></template>内容克隆前是静态字符串,JS 扫描不到;克隆后是未翻译原始节点,需显式传入translateNode() - 语言包加载完成前,模板应隐藏(
style="display:none")或占位,避免闪出英文原文
DOM 深度超 6 层会导致 data-i18n 节点被跳过
当 data-i18n 嵌套在 <div><div><div><div><div><p data-i18n="msg"></p></div></div></div></div></div> 这类纯 CSS 堆叠结构里时,遍历逻辑常因深度截断或性能阈值跳过最内层节点——中文页正常,切英文后那段文字仍显示中文,且无任何报错。
- 用浏览器 Elements 面板右键 → “Reveal in Elements panel”,手动数路径层级:从
到目标data-i18n元素,必须 ≤6 - 把冗余
<div> 替换为语义标签:<code><main></main>、<section></section>,天然中断嵌套深度,同时支持 i18n 工具识别作用域 - SSR 渲染首屏 HTML 时,若
data-i18n元素在下第 7 层才出现,服务端初始化脚本很可能只扫描前 6 层
真正容易被忽略的不是怎么写 data-i18n,而是怎么让每个带文本的节点都有正确的 lang、怎么让每个动态插入的片段都走一遍翻译、以及怎么确保结构深度不把关键节点“埋没”——这些都不是一次配置就能完事的事,得在每次 DOM 变更时检查、补位、验证。











