设置 document.documentElement.lang 不会触发文本更新或修复标点、字体及屏幕阅读器行为;lang 必须在 <meta charset="UTF-8"> 之后且无 BOM,服务端 Content-Type 也需声明 charset=UTF-8;data-i18n 默认只处理 textContent,其他属性需显式标记如 data-i18n-placeholder;动态插入 DOM 需手动调用翻译函数;所有含文本语义化标签须显式声明 lang 属性,且严格遵循 BCP 47 格式。
只改 document.documentElement.lang 不会触发任何文本更新,也不会修复标点、字体或屏幕阅读器行为——这是最常被当作“已国际化”却实际失效的操作。
浏览器在解析 HTML 时,前 1024 字节内必须先看到 <meta charset="UTF-8">,否则可能 fallback 到系统默认编码(如 Windows 上的 GBK),导致 lang 值本身被错误解码成乱码,后续所有基于该值的逻辑(包括 i18n 框架语言判定)都会错。
<html lang="zh-Hans"> 必须出现在 <meta charset="UTF-8"> 之后,且 <meta charset> 应紧贴 <head> 开始,前面不能有空格、BOM 或注释<meta charset> 会失效;务必选 “UTF-8”(无 BOM)curl -I 或 Chrome DevTools 的 Network → Headers 查看响应头中的 Content-Type,确保它包含 charset=UTF-8,否则服务端配置(如 Nginx 的 charset utf-8;)优先级高于 HTML 中的 meta
常见错误是给 <input placeholder="Search"> 加 data-i18n="search",但 placeholder 不会变——data-i18n 默认只更新元素的文本内容,对 placeholder、alt、title、aria-label 等完全无效。
data-i18n-placeholder="search_hint"、data-i18n-alt="avatar_desc"、data-i18n-title="tooltip_info"
value 属性一般不翻译(属于用户输入数据),但 <button> 和 <input type="submit"> 的显示文案建议统一用 textContent 更新,避免 value 被意外提交"请阅读<a href="https://www.php.cn/link/07fd2295ead5c4d45892fe3ab22a846a">服务条款</a>")必须用 innerHTML 替换,且语言包里对应值要是可信纯 HTML 片段(不能拼接用户输入,否则有 XSS 风险)AJAX 加载的弹窗、分页表格新行、懒加载模块插入后,里面的 data-i18n 标记只是字符串,不会变成对应语言文本——没有监听机制,也不会触发重渲染。
立即学习“前端免费学习笔记(深入)”;
translateElement(modalEl) 或 translateElements(newRow.querySelectorAll('[data-i18n]'))
flatpickr.localize()),不能只刷新页面文本很多团队设了 document.documentElement.lang = 'zh-Hans' 就以为万事大吉,结果 <p> 里的顿号按英文间距渲染、<pre lang="bash"> 的代码字体被中文字体覆盖、<img alt="logo"> 的 alt 文本仍被读作英文——因为浏览器和屏幕阅读器只看**每个元素自身的 lang 属性**。
<h1>、<p>、<section>、<footer> 等)都必须显式写 lang,值与当前语言包一致(如 lang="zh-Hans")lang 的特殊元素(如 <pre lang="bash">、<code lang="sql">)切换语言时保留原值,这是多语言混排的合法场景<script> 和 <style> 内部不要写 lang,它们不参与文本渲染,设了也白设最容易被忽略的是:lang 属性错误(比如写成 zh-CN 而非 zh-Hans)比不写更糟——它会强制浏览器按错误规则渲染标点、连字、语音,且无法 fallback。BCP 47 格式必须严格校验,不能靠肉眼判断。