必须在<html>标签设符合BCP 47标准的lang值(如zh-CN),否则语音合成失效;局部多语言内容需嵌套lang属性,且动态切换时须同步更新document.documentElement.lang与SpeechSynthesisUtterance.lang。

不设或设错 lang,语音合成基本不可用——中文会被切成英文音节,“行”读成 háng 而非 xíng,屏幕阅读器和 Web Speech API 都会 fallback 到系统默认语言,结果就是用户根本听不懂。
为什么只写 <html lang="zh-CN"> 远远不够
全局 lang 只决定页面基调,但浏览器不会自动推断局部语言内容。一段英文引用、一个日文术语、甚至 <code> 里的 useState,若没显式声明 lang,就会被中文引擎强行切分音节,比如把 API 读成“阿-皮-一”。
-
<p lang="en-US">The Art of Computer Programming</p>—— 必须加,否则中文 TTS 会逐字母硬读 -
<td lang="ja-JP">こんにちは</td>—— 表格单元格必须单独设,<table lang="ja">完全无效 -
<code lang="en">fetch()</code>—— 技术词嵌在中文段落里时,用<code>包裹并设lang是最稳定的做法
lang 值必须严格符合 BCP 47,写错等于没写
浏览器和语音引擎只认小写字母 + 连字符 + 地区码(可选)的组合,其他格式全被忽略。后端返回 zh_ch 或 ZH-CN 这类脏数据,前端必须清洗后再赋给 document.documentElement.lang。
- ✅ 正确:
zh-CN、zh-Hans、en-GB、ja-JP - ❌ 无效:
zh_cn(下划线)、ZH-CN(大写)、zh(缺地区码)、Chinese(非标准字符串) - iOS VoiceOver 某些版本对
ja支持不稳定,ja-JP才能锁定日语引擎
动态更新语言时,DOM、SpeechSynthesis、屏幕阅读器三者必须同步
SPA 切换语言不能只改 document.body.lang 或只更新文本。已创建的 SpeechSynthesisUtterance 实例不会自动继承新 lang,必须重新 new 并显式设 utterance.lang;同时 document.documentElement.lang 必须第一时间更新,否则屏幕阅读器仍按旧语种解析可访问树。
立即学习“前端免费学习笔记(深入)”;
- 改语言前:先
speechSynthesis.cancel()清空队列 - 改语言时:同步设置
document.documentElement.lang = "en-US" - 改语言后:新建
utterance,并显式赋值utterance.lang = "en-US" - 别漏掉
<mark lang="en-US">React</mark>这类语义标注节点的语言声明
最容易被忽略的是:语音是否自然,80% 取决于 lang 是否准确、是否嵌套得当,而不是用了多高级的 TTS 库。它不是“锦上添花”,而是整个语音链路的启动开关。



















