必须给每个语义化容器显式设lang属性,因为浏览器、屏幕阅读器、字体引擎、标点处理等均依赖元素自身lang值而非继承;不显式声明会导致title、alt、标点间距、字体回退全错乱。

直接改 document.documentElement.lang 不够,浏览器和屏幕阅读器按每个元素自身的 lang 属性判定语言行为,不是继承来的;只动根节点会导致 title、alt、标点间距、字体回退全错乱。
为什么必须给每个语义化容器显式设 lang 属性
浏览器渲染、字体选择、标点处理(比如中文顿号 vs 英文逗号)、屏幕阅读器语音合成,全都依赖元素自身 lang 值。哪怕父级写了 lang="zh",子元素没写,它就按默认语言或 UA 设置走——结果就是:一个页面里标题读中文、按钮提示读英文、代码块用中文字体显示 bash 命令。
-
<h1 lang="zh">首页</h1>、<p lang="zh">欢迎使用</p>这类文本容器必须带lang - 已有
lang的特殊元素(如<pre lang="bash">)要保留原值,别覆盖——这是明确的多语言混排,不是 bug -
<script>和<style>里加lang没意义,不参与渲染 - 切换语言时,得遍历所有已带
lang的元素,同步更新(除明确要保留的)
data-i18n 怎么标记才不会漏掉 placeholder/title/alt
只给 <button data-i18n="btn_submit">提交</button> 加属性,会漏掉辅助技术关键字段。浏览器不会把 data-i18n 自动映射到 placeholder 或 title,得手动约定后缀。
- 基础文本用
data-i18n="key",更新textContent - 需要填
placeholder就加data-i18n-placeholder="search_hint" - 同理:
data-i18n-title、data-i18n-alt、data-i18n-aria-label -
value属性跳过不处理——表单输入值是用户数据,不属于翻译范畴 -
label标签内的文字必须标记,且for属性要与对应input[id]严格匹配
含 HTML 结构的文案怎么安全替换
像“请阅读使用条款”这种带标签的文案,不能只靠 textContent,但直接 innerHTML 有 XSS 风险。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
立即学习“前端免费学习笔记(深入)”;
- 语言包里对应字段必须是可信的纯 HTML 片段(白名单过滤过,不含
<script>、onerror等) - JS 渲染时检测该键是否含 HTML 标签,再决定用
textContent还是innerHTML - 动态插入的 DOM(弹窗、AJAX 表格行)插入后必须立即调用翻译函数,不会自动监听
- 避免在
<pre>、<code>内部写data-i18n——这些节点不参与文本渲染,替换无效
切换语言时怎么避免闪动、状态丢失和读音错乱
只批量替换文本 + 改根节点 lang,页面会闪、滚动位置重置、表单值清空、屏幕阅读器继续读旧语言。
- 更新前用
getComputedStyle或window.scrollY记录滚动位置,更新完window.scrollTo()恢复 - 保持当前路由、表单输入值、焦点状态——不要
window.location.reload() - 同步更新
document.documentElement.lang和所有带lang的语义化容器 - 若用了
Intl.DateTimeFormat或Intl.NumberFormat,必须重建实例,旧对象不会响应语言变更 - localStorage 存语言偏好可以,但不能用来覆盖服务端通过
Accept-Language注入的初始值——它可能过期或未设置
最易被忽略的是:每个带文本的语义化元素都得有自己独立的 lang,不是“设一次就完事”;还有动态插入内容后不主动触发翻译,等于白切。


















