lang属性仅声明语言而非触发翻译,必须严格使用bcp 47格式(如zh-hans);translate="no"是唯一有效禁译手段,需显式写在目标元素上;spa中须同步更新document.documentelement.lang并为动态内容手动设置lang和translate。

lang属性根本不会触发浏览器自动翻译
写了 lang="zh-CN",页面不会因此“自动变成中文”或“自动弹出翻译栏”。浏览器是否显示翻译提示、用什么模型处理文本、甚至是否启用翻译功能,全部由用户设置和 UA 行为控制——lang 只是声明,不是指令。
常见错误现象:中文页误写 lang="en-US",Chrome 检测到内容是中文但声明为英文,就认定“这页是外语”,弹出“翻译成中文”,结果把“登录”翻成“log in”再翻回“登陆”,语义崩坏。
实操建议:
- 根元素
必须与当前渲染内容的主语言严格一致,不能靠 JS 后续修改来“补救” - 动态切换语言时,必须同步更新
document.documentElement.lang,并配合location.reload()才能重触翻译逻辑 - 不要用
<meta http-equiv="Content-Language">或<meta name="google" content="notranslate">,现代浏览器完全忽略前者,后者只影响搜索摘要
translate="no" 是唯一有效的禁译手段
translate 属性才是控制翻译行为的开关,但它只有两个合法值:"yes"(默认,可省略)和大小写敏感的 "no"。写成 translate="false"、translate="off" 或空字符串,Chrome 全部无视。
常见错误现象:给 ,结果按钮文字、API 密钥仍被翻译;或在 JS 中执行 el.translate = "no",DOM 上没属性,翻译引擎根本看不到。
实操建议:
- 禁译区域必须显式写在目标元素上,例如
<code translate="no">curl -X POST - 父级设了
translate="no",子级默认继承;若子级需要可翻译,得显式写translate="yes" - JS 动态插入的内容(如聊天消息、API 返回文案),必须手动给新节点加
translate="no",不能只靠初始 HTML
BCP 47 格式写错等于没写
lang 值不是随便填的字符串。写成 zh_CN、Chinese、en-us,浏览器会静默降级为 und(未知语言),导致屏幕阅读器乱读、CSS :lang() 选择器失效、SEO 语言信号丢失。
常见错误现象:<p lang="zh">你好</p> 在某些 iOS VoiceOver 下触发粤语发音;<pre class="brush:php;toolbar:false;" lang="bash"></pre> 被当成一种“语言”,代码注释全被翻译成中文,变量名崩坏。
实操建议:
- 严格使用 BCP 47 格式:小写字母 + 连字符,如
zh-Hans、en-US、pt-BR - 局部多语言内容必须显式标注,例如
<blockquote lang="ja">こんにちは</blockquote> - 代码块、术语、命令行输出,应按内容实际语言设
lang(bash不是语言,用lang="en"或留空)
SPA 中 lang 和 translate 的更新最容易被忽略
单页应用里,路由切换不刷新页面,document.documentElement.lang 不变,新加载的中文内容仍带着旧的 lang="en-US" 声明。此时 Chrome 已完成语言判定,后续 DOM 插入再加 lang 或 translate 都晚了——它不会重新扫描整页。
真正容易被忽略的是:你改了根 lang,也加了 translate="no",但聊天框里新追加的每一条消息,如果没单独设 lang 和 translate,它们依然可能被误判、误翻、误读。
实操建议:
- 每次路由跳转后,先更新
document.documentElement.lang,再渲染新内容 - 所有动态插入的文本节点,必须手动设置
lang和translate属性,不能依赖父容器继承 - 验证方式不是看页面显示,而是打开 Elements 面板,确认目标元素上真实存在对应属性
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











