lang属性必须显式写在每个含文本的语义化标签上,因浏览器和屏幕阅读器依据各元素自身lang值决定标点宽度、连字规则与字体回退链,不继承父级。

lang 属性必须显式写在每个含文本的语义化标签上
只改 document.documentElement.lang 不会修复溢出排版,浏览器和屏幕阅读器按每个元素自身的 lang 值决定标点宽度、连字规则、字体回退链——不继承父级。比如 <p lang="zh-Hans">顿号、逗号、句号</p> 和 <p lang="ja">、。!?</p> 渲染间距完全不同,混排时漏写 lang 就会错乱。
常见错误现象:<pre class="brush:php;toolbar:false;" lang="bash">curl -X POST</pre> 保留了正确值,但旁边 <p>请运行以上命令</p> 没加 lang,导致中文顿号被当成英文标点渲染,视觉上挤在一起;<blockquote lang="fr">…</blockquote> 插入后没同步设 lang,法语引号间距异常。
- 所有含文本的语义化标签(
<h1></h1>、<p></p>、<section></section>、<footer></footer>、<label></label>、<figcaption></figcaption>)都必须显式写lang - 已有
lang的特殊元素(如<pre class="brush:php;toolbar:false;" lang="bash"></pre>、<code lang="sql">)切换语言时保留原值,这是合法混排场景 -
<script></script>和<style></style>内部不要写lang,它们不参与文本渲染
BCP 47 语言标签写错比不写更糟
写错 lang 值会导致字体回退异常、拼写检查关闭、CSS :lang() 失效,甚至某些 SSR 框架拒绝渲染。例如 zh_CN(下划线非法)、chinese(非标准子标签)、zh(太宽泛,无法区分简繁)都会触发降级行为。
必须用 IANA 注册的 BCP 47 标签:zh-Hans(简体中文)、zh-Hant(繁体中文)、pt-BR(巴西葡萄牙语)、en-US;lang="bash" 虽非自然语言,但被语法高亮工具识别,可安全使用。
- 验证方式:Chrome DevTools → Elements → 看每个节点是否带合法
lang值 - VS Code 显示 “UTF-8 with BOM” 时,
<meta charset="UTF-8">可能失效,需另存为 UTF-8(无 BOM) - HTTP 响应头
Content-Type: text/html; charset=GBK会覆盖<meta charset>,必须统一为 UTF-8
动态插入内容必须手动触发 lang 同步与翻译
AJAX 加载的弹窗、分页表格行、懒加载模块插入后,lang 属性不会自动继承,data-i18n 也不会自动解析——DOM 是静态字符串,不是活的翻译节点。
常见错误现象:<modal><h2 data-i18n="modal_title"></h2></modal> 打开后文字仍是键名;<tr data-i18n="row_label"><td>...</td></tr> 插入表格后未遍历更新,标点和字体仍按旧语言渲染。
- 插入新 DOM 后,立即执行两件事:设置每个文本节点的
lang属性 + 调用翻译函数替换textContent或innerHTML - 避免依赖
MutationObserver自动监听——它无法感知语言上下文变更,且对data-i18n无意义 - 富文本区域(如
<div contenteditable>)里的用户输入不强制设 <code>lang,但包裹它的容器必须声明:lang() 伪类比 [lang] 更适合嵌套多语言排版
想用 CSS 控制日文标点间距或阿拉伯文右对齐,却样式没生效?大概率选错了选择器。
[lang="ja"]只匹配显式写了lang="ja"的元素,不继承;而:lang(ja)能匹配该元素或其任意祖先有lang="ja",适合处理嵌套文本块。例如:
<section lang="ja"><p>こんにちは</p> <blockquote><p>引用部分</p></blockquote></section>中,p:lang(ja) { font-family: "Hiragino Kaku Gothic"; }会让整个段落生效,而p[lang="ja"]只命中第一层<p></p>。-
:lang()支持层级穿透,[lang]是精确匹配,二者语义不同 - RTL 场景下,
[dir="rtl"]应与lang配合使用,不能仅靠dir推断语言 - 字体链依赖
lang:Chrome 对lang="ja"元素优先加载日文字体,lang="zh-Hans"触发中文字体回退逻辑,混用时可能意外换字体
data-i18n都翻对了,只要lang漏写或写错,标点、字体、语音、拼写检查就全乱。这不是“锦上添花”,而是多语言页面的呼吸系统。 -











