lang属性不是可选装饰,而是浏览器、屏幕阅读器、搜索引擎和翻译引擎解析文本语言的强制依据;必须严格设在标签且符合BCP 47标准(如zh-CN),局部多语言内容需显式标注,动态插入时须同步更新lang值。

lang属性不是“可选装饰”,而是语言上下文的强制声明
它不控制页面显示或功能,但决定了浏览器、屏幕阅读器、搜索引擎和翻译引擎如何“理解”一段文本——比如 <p>Bonjour</p> 没加 lang="fr",VoiceOver 可能用中文音读“邦茹瓦”,Chrome 也可能跳过右键翻译菜单。
关键点在于:它不靠猜测,只认显式声明。根节点 设的是默认语言,但所有外文内容(人名、术语、引文、代码注释)都必须单独包裹或标注,否则一律按根语言处理。
常见错误写法直接导致功能失效
Google、Safari、NVDA 等工具对语言代码极其敏感,错一个字符就弃用整条规则:
-
zh_cn(下划线)→ 不符合 BCP 47,hreflang静默失效 -
Chinese或en-us(大小写/非标准码)→ 屏幕阅读器降级为英语发音 -
zh-CN(末尾空格)→ DOM 中实际值含空格,:lang(zh-CN)CSS 选择器不匹配 -
lang="zh"单独使用 → iOS VoiceOver 某些版本无法调用简体中文 TTS 引擎
SPA 动态切换语言时,document.documentElement.lang 只是起点
React/Vue 项目里改了 document.documentElement.lang,但已渲染的 <p></p>、<div> 节点仍带着旧 <code>lang 值,辅助技术和爬虫看到的还是旧语言上下文。
立即学习“前端免费学习笔记(深入)”;
必须同步做三件事:
- 遍历当前挂载的所有文本容器节点,手动更新其
lang属性 - 新插入的富文本、评论、第三方组件,需在
innerHTML或appendChild前显式设置lang - Shadow DOM 内部不继承根
lang,每个 shadow root 都要单独设lang
用 :lang() 写样式时,匹配逻辑和 [lang=""] 完全不同
CSS 的 :lang(zh-CN) 会匹配 lang="zh-CN"、lang="zh-CN-u-va-posix" 等扩展形式;而 [lang="zh-CN"] 只认完全相等的字符串。混用容易白写样式。
更隐蔽的问题是:如果后端返回 zh_ch,前端没标准化就直接赋给元素,:lang(zh-CN) 根本不会生效——因为浏览器根本不认识这个值。
真正难的从来不是记住 zh-CN 这个写法,而是确保从 SSR 输出、JS 动态渲染、到用户粘贴进编辑器的每一处文本,都落在同一套语言声明路径上。



















