改 document.documentElement.lang 无效,因为浏览器、屏幕阅读器等依赖各元素自身的 lang 属性而非继承值;必须遍历所有带 lang 属性的元素并逐一更新。

只改 document.documentElement.lang 为什么没用
因为浏览器、屏幕阅读器、字体回退链、标点渲染规则,全部依赖每个元素自身的 lang 属性,而不是继承值。改根节点只是“贴了个标签”,已渲染的 <p>、<label>、<blockquote> 仍按旧 lang 解析。
常见错误现象:
• 中文页面切换英文后,<p lang="zh-Hans">欢迎</p> 还读作“huānyíng”
• <pre lang="bash">npm install</pre> 的等宽字体被中文字体覆盖
• 日文引文 <cite lang="ja">こんにちは</cite> 顿号间距异常
- 必须遍历所有带
lang属性的元素:document.querySelectorAll('[lang]') - 对每个匹配元素执行
el.lang = newLang,包括<input placeholder>外的语义标签 - 已有特殊语言内容(如
<code lang="sql">)保留原值,不参与主语言切换
data-i18n 标记漏翻译的真正原因
不是脚本没运行,而是 DOM 深度超 6 层时,多数 i18n 工具(含 node-static-i18n 和手写遍历逻辑)会主动截断或跳过内层节点——这是为防栈溢出或性能卡顿做的硬限制。
常见错误现象:
• document.querySelectorAll('[data-i18n]').length 返回数量明显少于预期
• SSR 首屏 HTML 中,data-i18n 出现在 <body><div><div><div><div><div><p data-i18n="tip"></p></div></div></div></div></div>,第 7 层失效
• 动态插入的弹窗、表格行、懒加载模块,内部 data-i18n 完全不生效
立即学习“前端免费学习笔记(深入)”;
- 用浏览器 Elements 面板右键 → “Reveal in Elements panel”,手动数从
<body>到目标节点的层级,确保 ≤6 - 把纯样式
<div>替换为语义标签:<main>、<section>、<article>,天然降低嵌套深度 - 动态插入 DOM 后,立即调用翻译函数(如
translate(el)),不能依赖全局扫描
lang 属性和 <meta charset> 的顺序陷阱
如果 <meta charset="UTF-8"> 出现在 <html lang="zh-Hans"> 之后,浏览器可能用默认编码(如 ISO-8859-1)解析 lang 值本身,导致其被解码为乱码——后续所有基于该值的逻辑(语音引擎切换、字体回退)全部失效。
常见错误现象:
• Chrome 控制台里 document.documentElement.lang 显示为 "zh-Hans" 或空字符串
• 页面中文正常,但屏幕阅读器读英文单词时发音怪异
• <link rel="canonical" hreflang="zh-Hans"> 被搜索引擎忽略
-
<meta charset>必须放在<head>最前面,且在文档前 1024 字节内 - 绝对不要写成:
<html lang="zh-Hans"><head><meta charset="UTF-8"></head> - 正确写法:
<!DOCTYPE html><html lang="zh-Hans"><head><meta charset="UTF-8"></head>
动态属性(placeholder、alt、title)为什么没更新
data-i18n 默认只替换元素的 textContent,对属性值完全无感知。把 data-i18n 当万能翻译开关,是绝大多数初学者踩的第一个坑。
常见错误现象:
• <input placeholder="Search"> 切换语言后仍是英文
• <img alt="User avatar"> 的替代文本未变,影响无障碍访问
• <label for="email">Email</label> 文字翻了,但 for 属性没同步,点击失效
- 必须显式使用带后缀的标记:
data-i18n-placeholder、data-i18n-alt、data-i18n-title -
value属性一般不翻译(属用户输入数据),但<button>和<input type="submit">建议统一用textContent更新 - 含 HTML 结构的文案(如“请阅读服务条款”)要用
innerHTML替换,且语言包中对应值必须是可信纯 HTML 片段,禁止拼接用户输入
lang 属性同步这两件事——它们不会报错,但会让部分文字“静默失效”,直到用户投诉才暴露。



















