data-i18n需覆盖所有可翻译属性并带对应后缀(如-placeholder),lang属性须逐节点更新而非仅改documentElement,语言包加载须防错降级,动态DOM需手动触发翻译,SVG和HTML结构文案需特殊处理。

data-i18n 标记必须覆盖所有可翻译的 DOM 属性
只给 <h1 data-i18n="header_title"> 加属性,页面大部分文案依然不会变——placeholder、title、alt、value(按钮文字)这些属性完全不受 textContent 更新影响。JS 替换时若不显式处理,切换后搜索框占位符还是旧语言。
常见漏点包括:
-
<input data-i18n-placeholder="search_hint">—— 必须带-placeholder后缀,不能指望通用逻辑自动识别 -
<button data-i18n="btn_submit" data-i18n-value="btn_submit">—— 某些浏览器渲染时优先取value,textContent被忽略 -
<label data-i18n="form_email"><input></label>——label文字必须标记,否则屏幕阅读器读不到新文本 -
<select data-i18n="country_select"><option value="CN">中国</option></select>——option文字需单独遍历替换,不能只靠父级键名
lang 属性不能只改 document.documentElement.lang
执行 document.documentElement.lang = 'zh-Hans' 后,页面看起来像切了语言,但屏幕阅读器仍用旧语音引擎读英文术语,:lang(zh-Hans) CSS 选择器也不生效——因为浏览器和辅助技术在 DOM 解析初期就锁定每个节点自身的 lang 值,不响应运行时继承更新。
必须同步遍历并重设所有已存在的 lang 属性:
立即学习“前端免费学习笔记(深入)”;
-
<p lang="en">API</p>→ 切换时需判断是否要保留(如术语引用),否则改为lang="zh-Hans" -
<pre lang="bash">→ 这类技术语种通常不随主语言变,应加data-keep-lang显式跳过 -
<blockquote lang="ja">→ 若为引用内容,保留原lang;若是用户生成内容,则需同步更新
BCP 47 格式必须严格:用 zh-Hans,不是 zh_Hans 或 chinese,否则 :lang() 和浏览器翻译直接忽略。
JSON 语言包加载失败会导致整页留空
fetch 失败或 key 缺失时,langPack[key] 返回 undefined,赋给 textContent 就是空字符串——用户看到的不是“未翻译”,而是大片空白或原始键名(如 header_title)。
防崩关键动作:
- 路径拼接用
./locales/${lang}.json,别硬编码./zh.json;加try/catch包住整个fetch()+response.json()流程 - 所有语言文件结构必须扁平且键名对齐:
{"header_title": "首页", "btn_submit": "提交"}✅;嵌套结构或缺失字段 ❌ - fallback 分两级:先试
zh-HK→ 降级zh→ 最终退到内置默认对象(如{header_title: "Welcome"}) - HTTP 响应头必须是
Content-Type: application/json,否则 fetch 可能静默失败
动态插入的 DOM 必须手动触发翻译
JS 弹窗、AJAX 表格行、Toast 提示等动态内容,插入 DOM 后不会自动识别 data-i18n——浏览器不会二次扫描,querySelectorAll('[data-i18n]') 只返回初始加载时的节点。
实操要点:
- 封装一个
t('common_error')函数,内部查当前语言包,供 JS 动态调用 - 插入新节点后立即执行翻译逻辑:
translateElement(newNode),而非依赖全局批量刷新 -
<svg><text data-i18n="download">下载</text></svg>——SVGTextElement需特殊处理,textContent替换方式与 HTML 元素不同 - 含 HTML 结构的文案(如
"terms_link": "请阅读<a href="https://www.php.cn/link/07fd2295ead5c4d45892fe3ab22a846a">使用条款</a>")必须用innerHTML,但语言包值需经校验为可信纯 HTML,否则 XSS 风险极高
最易被忽略的是:表单 value 属性一般不翻译(用户输入数据),但按钮的 value 是界面文案,必须处理;<script> 和 <pre> 内部加 data-i18n 完全无效,JS 找不到可替换目标。



















