只改document.documentelement.lang无效,lang必须在首屏html中正确声明;ssr需服务端注入、静态站应硬编码、spa须整页刷新或重写outerhtml;值须严格符合bcp 47(如zh-cn),局部多语言内容必须显式标注lang。

只改 document.documentElement.lang 不会让屏幕阅读器、浏览器翻译或 :lang() 样式重新生效——它只是个属性值,DOM 已渲染完成,没人重解析。
lang 属性必须在首屏 HTML 中写对,JS 动态设置无效
浏览器和辅助技术(如 NVDA、VoiceOver)只读取初始 HTML 的 。后续用 JS 改 document.documentElement.lang = "en-US",语音引擎不会重载,Chrome 翻译按钮也不会激活,SEO 也收不到信号。
- SSR 项目:根据
Accept-Language请求头或用户登录态,在模板里直接注入正确lang值 - 静态站点(Hugo/Jekyll):每个语言版本生成独立 HTML 文件,
lang硬编码进模板 - 纯前端 SPA:语言切换时强制整页刷新(
window.location.href),或重写document.documentElement.outerHTML(但 ARIA 缓存清不干净,兼容性差)
lang 值必须严格符合 BCP 47 规范
写错 lang 不报错,但等于没写:搜索引擎忽略、屏幕阅读器朗读错、:lang(zh) 样式完全不匹配。
- ✅ 正确写法:
zh-CN、en-US、pt-BR、zh-Hans(注意是短横线-,不是下划线_) - ❌ 典型错误:
zh_CN、Chinese、zh-ch、cn、zh-hans-cn(IANA 不收录三段式,Chrome 会静默降级为zh) - 选
zh-CN还是zh-Hans?多数 CMS、SEO 工具、翻译插件只认zh-CN;zh-Hans仅当你需强调“简体字”且明确排除港澳台繁体场景时才用
局部混排内容必须显式设 lang,不能靠继承
只定义主语言,不影响内部英文引文、<pre class="brush:php;toolbar:false;" lang="bash"></pre>、法语术语的识别。这些节点必须单独加 lang 属性。
-
<p lang="en">API</p>→ 不会被中文语音引擎硬读成“阿皮” -
<pre class="brush:php;toolbar:false;" lang="en">curl -X POST</pre>→ 语法高亮工具和翻译功能才能正确识别 -
<blockquote lang="ja">こんにちは</blockquote>→ 屏幕阅读器用日语发音引擎读 - 切换语言时,必须遍历所有已带
lang属性的元素(如<p lang="en"></p>),同步更新它们的lang值,除非你明确想保留原语言(比如一段日文引用始终该是日语)
字符编码集(charset)和 lang 属性无关,别混着配
<meta charset="UTF-8"> 是告诉浏览器用什么编码解码字节流,跟语言无关。UTF-8 能覆盖所有语言文字,不需要也不应该按语言切换 charset。
- 错误做法:
<meta charset="GBK">专用于中文 → 实际上会崩掉 emoji、日文假名、阿拉伯字母 - 正确做法:全站统一用
<meta charset="UTF-8">,一劳永逸 - 真正影响多语言显示的是字体栈和 CSS
:lang()规则,比如::lang(zh), :lang(ja), :lang(ko) { word-break: keep-all; }
最常被跳过的动作:切换语言时,漏掉那些显式写了 lang 的子元素——它们卡在旧语言上下文里,屏幕阅读器就永远读不准了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











