lang属性必须逐元素显式设置,不能仅修改document.documentelement.lang;所有含文本的语义化标签需严格按bcp 47标准设lang值(如zh-hans),技术性元素(如)保留原lang,动态内容插入后须立即更新,且需区分哪些节点不应改动。

lang属性必须逐元素设置,不能只改document.documentElement.lang
只执行document.documentElement.lang = 'zh-Hans',页面文字不会变、屏幕阅读器仍读英文、中文顿号被当英文逗号渲染、<pre class="brush:php;toolbar:false;" lang="bash"></pre>里的代码字体被中文字体覆盖——浏览器和辅助技术压根不看继承值,只查每个元素自身的lang属性。
常见错误现象:<p>欢迎来到北京</p>在lang="en"根节点下,顿号宽度仍是英文间距;@@##@@的替代文本被 VoiceOver 读作 /ˈloʊɡoʊ/ 而非中文发音。
- 所有含文本的语义化标签(
<h1></h1>、<p></p>、<section></section>、<label></label>、<footer></footer>等)都必须显式写lang,值与当前语言包严格一致,如lang="zh-Hans" - 已有明确语言用途的元素(如
<pre class="brush:php;toolbar:false;" lang="bash"></pre>、<code lang="sql">)保留原lang值,这是合法混排,不是 bug -
<script></script>和<style></style>内部不要加lang,它们不参与文本渲染,设了也白设
lang值必须符合BCP 47标准,不能用简写或错拼
写成lang="zh_cn"(下划线)、lang="ZH-CN"(大写)、lang="zh-CN "(末尾空格)或lang="Chinese",浏览器和爬虫都会忽略——等于没写。CSS 的:lang(zh)伪类也会失效。
真实影响:iOS VoiceOver 某些版本对lang="ja"降级为英语朗读,而lang="ja-JP"能触发日语语音引擎;lang="zh"模糊声明会导致拼音标注逻辑错乱,lang="zh-Hans"和lang="zh-Hant"触发的字体 fallback 和断行规则完全不同。
- 地区码可选但推荐带上,如
zh-Hans-CN、en-GB、fr-FR - 服务端渲染时,需根据
Accept-Language头标准化转换,避免后端返回zh_ch就直接赋值 - 静态多语言站建议每个语言版本单独一份 HTML,在
上硬编码lang,避免 JS 注入延迟导致闪动
局部多语言内容必须显式声明lang,不能靠上下文推断
浏览器不会自动识别「这段英文是引用」「这行日文是代码注释」。不加lang,就全按根语言处理——拼写检查失效、语音朗读错、字体 fallback 异常(比如日文假名被中文字体渲染)。
典型使用场景:<blockquote lang="fr">Je suis français.</blockquote>;<code lang="en">useState(触发 IDE 英文高亮);<pre class="brush:php;toolbar:false;" lang="bash">curl -X POST</pre>(语法高亮工具依赖该值)。
- 中英混排段落里夹一句日文,必须单独加
lang="ja",否则标点间距和 text-align 行为可能错乱 - 客服对话中出现阿拉伯语用户名,需包裹在
<span lang="ar"></span>里,并配dir="rtl" - 避免用
lang="cn"或lang="ch"——这些不是 BCP 47 合法值
切换语言时lang属性必须同步更新,且要区分目标节点
SPA 切换语言后,如果只改document.documentElement.lang,但没遍历更新已存在的<p lang="en"></p>、<section lang="en"></section>等节点,屏幕阅读器仍会按旧语言播报,Chrome 自动翻译按钮也不出现。
关键判断点:是否需要保留原语言?<pre class="brush:php;toolbar:false;" lang="bash"></pre>这类元素切换语言时应保持lang="bash"不变;而<p lang="en">Hello</p>这种普通文本块则必须同步改为lang="zh-Hans"。
- 推荐封装一个更新函数,例如
updateLangAttribute(rootNode, newLang),跳过已带非BCP 47值(如bash、sql)的元素 - 动态插入的 DOM(如弹窗、表格新行)在
appendChild()后,必须立即调用该函数处理其子树 - 不要依赖
MutationObserver自动监听——它无法区分插入的是翻译目标还是脚本/样式节点,且首次插入时容易错过时机
lang,而是**哪些节点不该动**:你得一眼认出<pre class="brush:php;toolbar:false;" lang="bash"></pre>是技术上下文,<span lang="fr"></span>是引用内容,而<h2 lang="en"></h2>只是历史遗留未清理的冗余标记——三者处理方式完全不同。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











