data-i18n 必须加在文本承载元素上,仅对渲染文本的标签生效;表单属性需用专用后缀;键名须为小写+下划线;含html文案用innerhtml替换并防xss;ie11需兜底getattribute;json加载失败静默fallback;路径动态拼接、命名符合bcp 47;语言包结构扁平对齐;fallback机制保障降级;lang属性必须同步更新三处且初始化早于dom渲染。

data-i18n 标记必须显式加在文本承载元素上
不是所有标签都能被翻译,data-i18n 只对实际渲染文本的元素生效。比如 <h1 data-i18n="header"></h1> 可以,但 <script></script>、<style></style>、<pre class="brush:php;toolbar:false;"></pre> 里加了也没用——它们不输出用户可见文本。
表单控件的属性要单独处理:placeholder、title、alt 不能靠 textContent 覆盖,得用对应后缀:data-i18n-placeholder、data-i18n-title、data-i18n-alt。否则切换后输入框还是中文占位符,按钮 tooltip 仍是旧语言。
-
data-i18n值必须是纯英文小写+下划线(如form_submit),禁用空格、中文、驼峰或连字符,避免和 BCP 47 语言码(如zh-Hans)混淆 - 含 HTML 结构的文案(如 “请登录继续”)要用
innerHTML替换,但语言包里对应值必须是可信的纯 HTML 字符串,否则有 XSS 风险 - IE11 不支持
element.dataset.i18n,得兜底用element.getAttribute('data-i18n')
JSON 语言包加载失败时页面会静默变空白
fetch 失败、路径拼错、MIME 类型不对、键名不一致——任何一个环节出错,data-i18n 元素就会显示原始 key(如 header_title),而不是报错中断。这不是 bug,是设计使然:JS 不会主动抛异常,只默默 fallback 到 undefined。
正确做法是把加载逻辑包进 try/catch,且检查 response.ok 和 response.headers.get('content-type')?.includes('application/json')。路径别写死,用模板字符串动态拼:./locales/${lang}.json,而不是 ./zh.json。
- 文件命名必须符合 BCP 47:
zh-Hans.json✅,zh_CN.json❌(会被忽略或降级失败) - 所有语言 JSON 必须结构扁平、键名严格对齐;某语言缺翻译项,也要留空字符串,不能直接删 key
- fallback 必须有:用户选了
zh-HK但只有zh-Hans.json,就自动加载后者,否则整页文案消失
只改 document.documentElement.lang 是无效切换
浏览器和屏幕阅读器(NVDA/VoiceOver)只读取首屏 HTML 的 。JS 动态设 document.documentElement.lang = "en-US" 后,Chrome 翻译按钮不会激活,语音引擎不会重载,SEO 也收不到信号——DOM 已渲染完成,没人重解析。
真正有效的做法是:语言切换时,必须同步更新三处:
-
document.documentElement.lang(设为完整 BCP 47 值,如zh-Hans,不是zh) - 所有已带
lang属性的子元素(如<p lang="en">API</p>),需手动保留或重设其lang值,否则会被继承覆盖 -
localStorage.setItem('lang', 'zh-Hans')—— 必须在语言包成功加载后执行,否则刷新可能拿到未就绪的状态
切换后字体回退、标点间距、拼写检查全靠 lang 属性驱动
很多人以为“文字变了就是切换成功”,其实不然。设为 lang="ja" 后,浏览器才可能启用 Meiryo 或 Noto Sans CJK JP 字体;设为 lang="fr",法语标点(如 « »)才会正确排版;拼写检查器也按该语言启动。这些行为完全不依赖 JS 文本替换,只认 lang 属性。
局部混排内容(如英文代码块、日文引用)必须显式标注 lang,不能靠根节点继承。例如:<pre class="brush:php;toolbar:false;" lang="bash">curl -X POST</pre> 和 <blockquote lang="ja">こんにちは</blockquote>,切换主语言时这些节点的 lang 必须保留原值,否则代码高亮失效、日文朗读错误。
最易被忽略的是初始化时机:语言包必须在 DOM 渲染前加载并完成替换,否则会出现闪屏(先中文,再跳英文)。把初始化逻辑放在 <script></script> 标签中,且置于所有待翻译元素之前,比 DOMContentLoaded 更可靠。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











