只改document.documentElement.lang无效,必须同步更新所有带lang属性的元素并严格遵循BCP 47格式;局部多语言内容需显式声明lang,不可依赖继承,且lang值错误比不写更糟。

只改 document.documentElement.lang,页面文字不会变、屏幕阅读器仍读错、标点间距乱、字体回退失效——这不是国际化,只是改了个标签。
data-i18n 标记必须覆盖所有可翻译属性,不只是 textContent
常见错误现象:<input placeholder="Search"> 切换语言后还是英文;<img alt="user avatar"> 的替代文本没更新;<label for="email">Email</label> 文字翻了但 for 属性没同步,点击 label 失效。
-
data-i18n只作用于元素的textContent,对placeholder、title、alt、aria-label等属性完全无效 - 必须显式加对应后缀:如
data-i18n-placeholder="search_hint"、data-i18n-alt="avatar_desc"、data-i18n-title="tooltip_info" -
value属性一般不翻译(属于用户输入数据),跳过处理;但button和input[type="submit"]的显示文案建议统一用textContent更新,避免value被意外提交 - 含 HTML 结构的文案(如“请阅读服务条款”)必须用
innerHTML替换,且语言包里对应值要是可信纯 HTML 片段(不能带用户输入、不执行 JS),否则有 XSS 风险
lang 属性必须显式设在每个含文本的语义化标签上
很多团队以为 document.documentElement.lang = 'zh-Hans' 就万事大吉,结果 <p> 里的顿号按英文间距渲染,<pre lang="bash"> 里的代码字体被中文字体覆盖,<img alt="logo"> 的 alt 文本仍被读作英文。
- 浏览器和屏幕阅读器按**每个元素自身的
lang属性**决定标点宽度、连字规则、字体回退链、语音朗读方式——不继承父级 - 所有含文本的语义化标签(
<h1>、<p>、<section>、<footer>等)都必须显式写lang,值与当前语言包一致(如lang="zh-Hans") - 已有
lang的特殊元素(如<pre lang="bash">、<code lang="sql">)切换语言时保留原值,这是多语言混排的合法场景 -
<script>和<style>内部不要写lang,它们不参与文本渲染,设了也白设
动态插入的 DOM 必须手动触发翻译,不会自动监听
使用 AJAX 加载的弹窗、表格行、懒加载模块插入后,如果没调用翻译函数,里面的 data-i18n 标记就只是字符串,不会变成对应语言文本。
立即学习“前端免费学习笔记(深入)”;
- 点击按钮打开的
<modal>,内部<h2 data-i18n="modal_title">不会自动更新 - 分页表格每页 AJAX 获取新
<tr>,新行里的data-i18n保持原始键名,需插入后立即遍历并替换 - 不要依赖 MutationObserver 自动监听——它无法判断是否已加载完语言包,容易查不到 key 导致留空;应在 DOM 插入完成后的回调里主动调用翻译函数
- 第三方组件(如日期选择器)若支持 i18n,需单独调用其 locale 方法(如
flatpickr.set("locale", "zh")),不能指望全局data-i18n
JSON 语言包加载必须带 fallback,且结构要扁平对齐
fetch 失败、响应不是 JSON、或 key 缺失时,JS 查不到值就留空,用户看到的是一整页空白或原始键名。
- 路径必须可预测:
./locales/${lang}.json,例如./locales/zh-Hans.json、./locales/en-US.json - fallback 顺序必须是:先试完整 BCP 47 码(如
zh-HK),再截主语言(zh),最后退到默认语言(如en) - 所有语言包结构必须严格扁平、键名完全一致;某语言暂未翻译,也要保留键并设为空字符串:
"btn_submit": "" - 服务器返回 JSON 时,HTTP
Content-Type必须是application/json,否则fetch可能静默失败,控制台也不报错
最易被忽略的是:语言切换时,既要更新文本,又要同步更新所有已有 lang 属性的元素——尤其是那些明确写了 lang="ja" 或 lang="fr" 的引用块、代码片段、术语说明。它们不该跟着主语言一起切,但必须被识别、被排除在批量更新之外,否则多语言混排就崩了。



















