局部语言变化必须显式为承载可见文本且语义明确的元素(如、、、、、等)添加符合bcp 47规范的lang属性,仅靠继承无效。

局部语言变化不能靠继承,必须显式为对应元素加 lang 属性;否则屏幕阅读器、浏览器翻译、CSS :lang() 和字体回退全会失效。
哪些元素必须加 lang 才算“真正起作用”
只有承载用户可见文本内容、且语义明确的元素才适合加 lang。不是所有标签都合理,也不是加了就自动生效。
-
<blockquote></blockquote>、<q></q>、<figcaption></figcaption>这类语义化引述/说明标签,天然适合标注外文内容,读屏软件识别率高 <code>和<pre class="brush:php;toolbar:false;"></pre>可加lang="en"标注注释语言(别用lang="bash",它不是合法 BCP 47 语言码)-
<p></p>、<div>、<code><span></span>可以加,但需确保内部是纯文本或可控 HTML;含复杂子结构时优先拆到语义更细的标签上 - 避免给
<script></script>、<style></style>、<meta>加lang——它们不渲染文本,加了无意义 - 表单控件如
<input>的 placeholder/title/alt 等属性,需用data-i18n-placeholder等专用标记,不能靠父级lang传递 - ✅ 正确示例:
zh-CN、en-US、ja-JP、fr-FR(全部小写,短横线-,地域码大写) - ❌ 典型错误:
zh_CN(下划线非法)、ZH-cn(大小写混用)、chinese(非标准)、zh-Hans-CN(三段式 IANA 不收录,Chrome 降级为zh) - 选
zh-CN还是zh-Hans?多数场景用zh-CN:SEO 工具、翻译插件、NVDA/VoiceOver 全链路支持最稳;仅当需排除港澳台繁体且强调字形时才用zh-Hans -
<pre class="brush:php;toolbar:false;" lang="en"># Initialize counter</pre>比<pre class="brush:php;toolbar:false;" lang="bash"></pre>更合理——语法高亮靠 class 或data-language,lang是给语义和辅助技术看的 -
<p lang="en">API</p>→ 屏幕阅读器读作 /ˈeɪ.piː.ˈaɪ/;没加lang就硬读成“阿皮” -
<blockquote lang="ja">ありがとう</blockquote>→ VoiceOver 调用日语 TTS 引擎;没加就用中文规则逐字拼读 -
<code lang="en">useState→ IDE 可据此触发英文关键词高亮;lang缺失时可能当成标识符处理 - 不要用
<div lang="en"> 包裹多个段落来“批量切换”——语义模糊,干扰父级 <code>:lang(zh)样式匹配,还可能让字体 fallback 链错乱CSS
:lang()和[lang]选择器的实际差异二者行为不同,误用会导致样式不生效,尤其在多语言混排时。
-
[lang="zh-CN"]只匹配显式写了lang="zh-CN"的元素,不继承,不模糊匹配 -
:lang(zh-CN)能匹配继承自父级的值,但 Safari 对lang="zh-Hans"可能不触发,Chrome 对lang="zh"也不一定响应 - 稳妥做法是并列写:
html[lang="zh-CN"], html:lang(zh-CN), html:lang(zh),或直接用p[lang="en-US"]这类精确属性选择器 -
:lang()无法匹配lang="bash"这类非标准值,哪怕你写了,CSS 也完全不计算
最容易被忽略的是:局部
lang必须和根lang同时存在、互不替代。一个页面可以有+ 多个<p lang="en"></p>+ 一个<blockquote lang="fr"></blockquote>,这才是真实混排的常态。漏掉任意一层,可访问性、SEO 和字体渲染都会出问题。 -
lang 值怎么写才不被浏览器静默忽略
写错不报错,但等于没写。浏览器和辅助技术只认严格符合 BCP 47 的格式,大小写、分隔符、子标签顺序全要对。
为什么不能只靠 继承
的 lang 只定义主语言,不影响子元素的语言识别逻辑。浏览器、读屏软件、翻译引擎都按具体元素上的 lang 值做决策,不会向上查祖宗。











