必须为所有含文本的语义化标签显式设置 lang 属性,且与语言包一致;data-i18n 默认只替换 textcontent,placeholder 等需加后缀;dom 深度超 6 层会漏扫描;动态插入内容需立即翻译;微服务需用 closed shadow dom 隔离样式。

只改 document.documentElement.lang 是无效的
浏览器、屏幕阅读器、字体回退链、标点渲染规则,全部依赖每个元素自身的 lang 属性,而不是继承值。你执行 document.documentElement.lang = 'en' 后,<p lang="zh-Hans">你好</p> 依然按中文规则渲染顿号宽度、语音朗读方式和字体 fallback,结果就是:文字没变、标点挤在一起、屏幕阅读器读错音、中文字体覆盖代码块。
必须显式同步所有含文本的语义化标签:
-
<h1></h1>、<p></p>、<section></section>、<footer></footer>等都得带lang,且值与当前语言包一致(如lang="zh-Hans") - 已有明确语义的
lang不可覆盖:<pre class="brush:php;toolbar:false;" lang="bash"></pre>、<code lang="sql">保留原值,这是合法混排 -
<script></script>和<style></style>内部不参与文本渲染,加lang没用
data-i18n 只管 textContent,其他属性要显式声明
常见错误是只写 <input placeholder="Search" data-i18n="search_hint">,但切换语言后 placeholder 还是英文——因为 data-i18n 默认只替换元素文本内容,对 placeholder、alt、title、aria-label 完全无效。
必须加后缀显式绑定:
data-i18n-placeholder="search_hint"data-i18n-alt="avatar_desc"data-i18n-title="tooltip_info"data-i18n-aria-label="close_button"
value 属性一般跳过翻译(属于用户输入),但 <button></button> 和 <input type="submit"> 的显示文案建议统一用 textContent 更新,避免提交时意外发出去
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”,手动数从 body 到该节点的层级,必须 ≤6。
修复手段:
- 把冗余
<div> 替换为语义标签:<code><main></main>、<section></section>、<article></article>,天然中断嵌套深度 - 动态插入的 DOM(弹窗、表格行、懒加载模块)必须在
appendChild()后立即调用翻译函数,不能等全局扫描 - SSR 首屏 HTML 中,若
data-i18n在第 7 层才出现,需调整服务端初始化脚本的遍历深度阈值 - 必须在
constructor()中调用,connectedCallback()已太晚 -
mode: 'open'等于放弃隔离,外部可通过el.shadowRoot直接注入恶意样式 - 子应用 HTML 片段不能直接
innerHTML = htmlString,否则内联<style></style>和<script></script>逃逸至全局作用域
微服务架构下 html 和 body 样式必须隔离
子应用一旦声明 body { font-size: 14px; },主应用的 body { font-size: 16px; } 就被覆盖;两个子应用都引入 normalize.css,html 的 scrollbar 或 font-smoothing 设置会互相干扰。
唯一可靠隔离手段是 Custom Elements + attachShadow({ mode: 'closed' }):
正确做法:用 DOMParser 解析字符串,提取 <style></style> 内容转为 CSSStyleSheet 实例,再通过 shadowRoot.adoptedStyleSheets = [sheet] 注入











