lang属性必须正确设置在<html>标签上,如lang="zh-CN",否则屏幕阅读器会按默认语种错误发音;服务端需在首屏输出正确值,运行时修改无效。

lang 属性不写或写错,屏幕阅读器真会念错
不设 lang,或设成错误语言代码(比如中文页面写 lang="en"),屏幕阅读器大概率按默认语种发音,导致中文被英语音素强行“翻译”——“微信”读成 /weɪ tʃiːn/,“支付宝”变成 /zhī fù bǎo/ 的英文口型。这不是小众问题,是视障用户日常遇到的语音断裂、词义扭曲根源。
-
lang必须写在<html>标签上,如<html lang="zh-CN">;局部切换才用内联,比如一段法文引文加<span lang="fr"></span> - 别用模糊值:
lang="zh"不够,必须精确到区域,如zh-CN(简体中文)、zh-TW(繁体中文),否则某些阅读器仍 fallback 到英语发音引擎 - 动态渲染页面(React/Vue)要注意:服务端没输出
lang,JS 再补也晚了——阅读器已按初始值加载语音模型,后续改lang属性无效
React 里动态切 lang 怎么做才生效
React 组件内改 document.documentElement.lang 看似可行,但多数屏幕阅读器(尤其是 NVDA、VoiceOver)只在页面加载时读取一次 lang,运行时修改不触发语音引擎重载。真正起作用的方式得从源头干预。
- 服务端渲染(SSR)或静态生成(SSG)时,根据用户语言偏好直接输出正确
lang值,比如 Next.js 用getServerSideProps读Accept-Language头 - 纯客户端应用,必须在
<html>渲染前完成设置:把语言逻辑提到index.html的内联脚本里,或用document.write在<html>开始前注入(慎用),而非等 React mount 后再改 - 避免用
useState控制lang——状态更新不会让阅读器重新解析根节点
lang="zh-Hans" 和 lang="zh-CN" 有啥区别
对屏幕阅读器来说,zh-Hans(简体汉字)和 zh-CN(中国大陆)实际效果几乎一致,主流阅读器都支持,但细节有差别:
-
zh-CN是 IETF 推荐标准,兼容性最稳,Windows Narrator、iOS VoiceOver 都优先认它 -
zh-Hans更强调书写形式(Hans = Han Simplified),适合多地区共用简体字的场景(如大陆、新加坡),但旧版 JAWS 可能识别不稳定 - 别混用:
zh-Hans-CN是非法标签,浏览器会忽略,阅读器 fallback 到默认语言 - 繁体推荐用
zh-TW或zh-Hant,但zh-TW在台湾本地更可靠
测试 lang 是否生效的最快方式
别依赖肉眼检查 HTML 源码——得听。真实验证必须用屏幕阅读器本身,且注意操作路径:
- Chrome + NVDA:打开页面后按
Ctrl+Shift+D强制重载语音配置(NVDA 2023.3+ 支持),再用方向键逐字朗读,重点听中英文混排处(如 “点击Submit按钮”)是否自然切语种 - Safari + VoiceOver:重启 VoiceOver(
CMD+F5关再开),否则缓存旧lang设置 - 命令行快速验证:用
curl -s [url] | grep "<html"确认服务端输出正确,但这个只保前端输出,不保阅读器行为
最常被忽略的是:语言切换后没强制刷新阅读器语音上下文。改完 lang 不重启或不重载,等于没改。

















