lang属性必须写在<html>标签上才有效,浏览器、屏幕阅读器和翻译服务仅解析document.documentElement.lang;局部多语言内容需显式标注子元素lang;hreflang与html lang须双向一致;:lang()匹配需精确对应BCP 47值。

lang属性必须写在标签上才有效
浏览器、屏幕阅读器和翻译服务(比如 Chrome 的 translate.js)只在初始 HTML 解析阶段读取 document.documentElement.lang,也就是 <html lang="..."> 这个值。其他位置全无效:<body lang="zh-CN"> 不触发整页语言识别,<div lang="en"> 无法让翻译按钮出现,meta http-equiv="Content-Language" 在 HTML5 中已被弃用,现代浏览器直接忽略。
常见错误现象:
– 页面点了翻译按钮没反应
– 日文段落被 VoiceOver 当成中文朗读,音调错乱
– Google Search Console 报“未指定语言”
实操建议:
– 所有模板的 <html> 开标签必须带 lang,且值严格按 BCP 47 标准写,如 zh-CN、en-US、ja
– 动态页面(如 SSR 或 CSR)必须在首屏 HTML 中就写对,JS 后期执行 document.documentElement.lang = "en" 已经太晚,语音引擎不重载,:lang() 不重计算
– 禁用任何全局覆盖 lang 的插件,它会破坏子语言嵌套逻辑
局部多语言内容必须显式标注子元素lang
主语言靠 <html lang="zh-CN"> 奠定基调,但嵌入的英文术语、日文引用、代码注释等,如果不单独声明 lang,屏幕阅读器仍用中文规则硬读——比如把 API 读成“阿皮”,把 # Initialize counter 当中文断词处理。
立即学习“前端免费学习笔记(深入)”;
常见错误现象:
– 表格里一列是英文产品名,一列是中文说明,但全没标 lang,NVDA 全部按中文发音
– <pre lang="bash"> 导致注释被翻译工具当成 bash 语言处理(其实 bash 不是合法语言标签)
实操建议:
– 外文单词级:用 <span lang="en">API</span>
– 段落级:用 <p lang="en">This is a code example.</p>
– 语义更明确的容器优先:<blockquote lang="fr">、<q lang="ja">、<figcaption lang="de">
– 代码块注释统一用 lang="en"(不是 lang="bash"),数值、日期、单位(如 USD、2026-09-22)无需加 lang
hreflang 和 html lang 必须双向一致
hreflang 是给搜索引擎看的,<html lang> 是给浏览器和辅助技术看的,两者语义必须对齐。如果 hreflang="ja" 指向一个页面,但该页的 <html lang="en"> 没同步改成 ja,Google 可能索引错版本,用户搜日文关键词却返回英文页;Chrome 翻译菜单也可能误判模型,把日文原文用英文 NMT 模型再“翻译”一遍,语义全毁。
常见错误现象:
– hreflang="en" 和 hreflang="en" 同时指向英文页和日文页(违反互斥原则)
– hreflang="en-US" 写法错误(BCP 47 要求仅用 ISO 639-1 双字母码,en-US 应简化为 en)
– href 用了相对路径或带重定向的 URL,导致 hreflang 声明被忽略
实操建议:
– 每个语言版本页面的 <head> 都要包含**完全相同**的 hreflang 块,且 hreflang 值严格对应目标页真实语言
– x-default 推荐设为默认语言页(如 https://example.com/global/en),用于未匹配到明确语言偏好的用户
– 所有 href 必须是绝对 URL,协议、域名、路径精确一致(含尾部斜杠)
– 页面上线前,用 Google Search Console 的「国际化报告」验证 hreflang 是否被正确识别
:lang() CSS 匹配要防精确失配
:lang(zh-Hans) 只匹配 lang="zh-Hans",不匹配 lang="zh-CN";反过来也一样。很多团队写了 td:lang(zh) 却发现样式不生效,就是因为实际用的是 zh-CN —— 它不等于 zh,也不继承自父级。
常见错误现象:
– <td lang="zh-CN">超视网膜XDR显示屏</td> 上的 td:lang(zh) 规则完全不触发
– <td lang="zh-Hans"><strong>用户ID</strong></td> 中,strong:lang(zh-Hans) 失效(<strong> 自身没 lang,也不继承)
实操建议:
– 用属性选择器前缀匹配更稳妥:td[lang^="zh"] 覆盖 zh-CN、zh-Hans、zh-Hant
– 避免依赖 :lang() 做关键布局控制,它只适合字体、字号、强调样式等非结构性优化
– 如果表格中混排多种中文变体,建议统一用 zh-CN(兼容性最稳),而非混用 zh-Hans 和 zh-Hant 增加维护成本
真正难的不是写对一个 lang,而是所有层级都保持语言意图一致:根标签、子容器、表格单元格、代码块、甚至 hreflang 声明——漏掉任意一环,翻译就可能翻错,读屏就可能读崩,SEO 就可能掉坑。别指望浏览器“猜”,它只认你明写的那个字符串。



















