只改document.documentElement.lang无效,必须同步更新所有显式声明lang属性的元素并严格遵循BCP 47格式;data-i18n需覆盖placeholder、title、alt等带后缀的可翻译属性,动态DOM须手动触发翻译。

只设 document.documentElement.lang 不足以让页面真正多语言——屏幕阅读器照旧读错、CSS 的 :lang() 选择器不生效、字体回退和标点间距全乱套。必须同步更新每个元素自身的 lang 属性,否则所谓“切换”只是文字变了个样。
为什么不能只改 document.documentElement.lang
浏览器和辅助技术(如 VoiceOver、NVDA)在 DOM 解析初期就锁定每个节点的 lang 值,之后不再重新评估。根节点的 lang 只影响未显式声明 lang 的子节点,且仅限继承场景。
- 写
<p lang="en">API</p>后,它就彻底脱离根语言控制,切换根lang对它毫无影响 -
:lang(zh-CN) { quotes: "「" "」"; }样式不会命中任何元素,因为实际节点可能是lang="zh"或lang="zh-Hans" - 英文术语被中文语音引擎硬读成“阿皮”,不是文案问题,是
lang语义缺失
如何批量更新所有 lang 属性
切换语言时,不能只改根节点,必须遍历并重置所有显式带 lang 的元素——但得分类处理,不是暴力覆盖。
- 用
document.querySelectorAll('[lang]')获取全部已设lang的节点 - 对业务上“应随主语言变化”的节点(如
<p>、<h2>、<div class="content">),统一设为新语言码,例如el.lang = 'zh-Hans' - 对语义必需保留原语言的节点(如
<pre lang="bash">、<blockquote lang="ja">),跳过不处理,或按白名单保留 - 第三方组件插入的 DOM(如地图控件、图表库)可能自带
lang,需在其load回调后手动补扫
data-i18n 标记后,哪些属性必须额外加后缀
data-i18n 默认只更新 textContent,但表单和交互元素的关键文本藏在其他属性里,漏掉就会残留原文。
立即学习“前端免费学习笔记(深入)”;
-
placeholder→ 必须用data-i18n-placeholder="search_hint" -
title和alt→ 分别用data-i18n-title、data-i18n-alt -
value(仅限按钮等展示型控件)→ 用data-i18n-value;表单输入框的value绝对不要动,否则清空用户已填内容 - SVG 内嵌文本(
<text>下载</text>)需单独识别SVGTextElement类型并处理,querySelectorAll('[data-i18n]')默认不包含它
JSON 语言包加载失败时最致命的三个漏点
fetch 报 TypeError: Failed to fetch 或返回 404 很常见,但没兜底会导致整页文案留空,用户看到的是一堆 data-i18n="xxx" 键名。
- 没用
try/catch包住fetch()和response.json(),网络抖动或路径写错直接抛错中断流程 - 没检查
response.ok,HTTP 状态码非 2xx(比如 403、502)时仍强行解析,结果是空对象或undefined - fallback 逻辑写得太弱:只 fallback 到
'en',但用户选的是'zh-HK',而你只有zh-Hans.json,该降级到zh-Hans而不是跳到en
真正麻烦的不是替换文字,而是那些没显式标记、却依赖语言上下文的细节:滚动位置突跳、动态插入的弹窗没翻译、Intl.DateTimeFormat 实例没重建、甚至 <img data-i18n-src="flag-en"> 这种资源路径也得跟着切——这些地方一漏,用户立刻感知到“假国际化”。



















