必须逐类检查dom元素并精准添加data-i18n属性:input需data-i18n-placeholder、img需data-i18n-alt、含html文案用data-i18n-html;语言包加载失败须fallback至默认语言并刷新;dom更新应避免innerhtml全量替换,优先textcontent;切换语言时同步更新所有lang属性、滚动位置及intl实例。

如何给已有 HTML 补上 data-i18n 标记不漏不重
直接在现有 DOM 上加 data-i18n 容易跳过表单属性、动态节点或嵌套文本。必须逐类检查:
-
<input placeholder="搜索">要补data-i18n-placeholder="search_placeholder",不能只写data-i18n="search_placeholder" -
<img alt="logo">必须加data-i18n-alt="logo_alt",否则 alt 不会更新 -
<button>提交</button>和<button><span>提交</span></button>都要标记——后者需作用于<span></span>,不是父<button></button> - 所有
<script></script>、<style></style>、<pre class="brush:php;toolbar:false;"></pre>内部的文本不用加,它们不参与渲染,加了无效 - 含 HTML 的文案(如“请阅读服务条款”)要单独用
data-i18n-html标记,并确保语言包里对应值是白名单过滤后的纯 HTML 片段
JSON 语言包加载失败时页面为啥全白?
常见原因是 fetch 静默失败或 key 缺失后留空。关键不是“怎么加载”,而是“加载失败后怎么办”:
- 路径拼接必须用
./locales/${lang}.json,别硬编码zh.json;服务器返回非application/jsonMIME 类型时,fetch()不报错但response.json()会抛异常 - fallback 顺序必须是:先试完整码(
zh-HK),再截主语言(zh),最后退到默认(en);缺一环就可能卡住 - 所有语言包键名必须严格一致,某语言暂未翻译也要保留键并设为空字符串:
"btn_submit": "",否则查不到 key 就跳过,对应元素变空白 - 不要在
catch里只打印 console.error——得 fallback 到默认语言包,并触发一次完整刷新
切换语言后滚动位置丢失、事件监听器消失?
问题不在翻译逻辑本身,而在 DOM 更新方式:
- 用
innerHTML = translatedText替换整个节点会销毁事件监听器和已初始化组件状态;优先用textContent更新纯文本,仅对含标签的文案才用innerHTML - 切换前必须用
window.scrollY记录位置,更新完 DOM 后调用window.scrollTo(0, scrollY)恢复,否则页面跳回顶部 - 动态插入的 DOM(弹窗、AJAX 表格行)插入后必须立即调用翻译函数,不能等下次全局扫描——否则用户看到的是未翻译内容
- 若用了
Intl.DateTimeFormat或Intl.NumberFormat,切换后必须重建实例,旧对象不会自动更新格式规则
为什么只改 document.documentElement.lang 屏幕阅读器还是读中文?
因为浏览器和辅助技术按每个元素自身的 lang 属性决定语音、字体回退和标点间距,不是继承来的:
-
document.documentElement.lang = 'en'只影响根节点,已存在的<p lang="zh"></p>仍按中文朗读 - 切换语言时必须遍历所有带
lang属性的元素(包括<pre class="brush:php;toolbar:false;" lang="bash"></pre>、<q lang="ja"></q>),把它们的lang值也同步更新,除非明确要保留原语言 -
lang值必须符合 BCP 47 标准(如zh-Hans、en-US),zh_CN或chinese会被忽略 - 局部多语言内容(如代码块、英文术语、引文)必须显式写
lang="bash"或lang="en",不能指望全局覆盖
lang 就自动同步。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











