默认语言包内联为全局变量避免首屏等待,非默认语言包按需动态加载;深层节点需控制dom嵌套≤6层并手动更新动态插入内容;data-i18n属性需带后缀如placeholder/title/alt;lang属性须逐元素设置且遵循bcp 47格式。

怎么让语言包加载不卡住首屏
fetch 语言包如果放在 DOMContentLoaded 后才触发,用户会看到空白文案或原始 data-i18n 键名;但全量预加载所有语言又会让首屏体积暴涨。关键不是“要不要加载”,而是“什么时候、加载多少”。
- 把默认语言包(如
en.json)内联为全局 JS 变量,比如window.I18N_LOCALES = { en: { "home.title": "Home" } },避免首次渲染等待网络 - 非默认语言包(如
zh.json)用loadScript或import()动态加载,只在用户切换时触发,不参与首屏关键路径 - 服务端可配合 HTTP/2 Server Push,在返回 HTML 时主动推送用户
Accept-Language匹配的语言包,但需控制并发数,避免压垮连接 - 注意 fetch 的
credentials: 'same-origin'和 CORS 配置,否则本地开发时可能静默失败,控制台只报TypeError: Failed to fetch
为什么 data-i18n 元素遍历会漏掉深层节点
DOM 深度超过 6 层时,querySelectorAll('[data-i18n]') 仍能查到,但实际遍历更新逻辑常因性能截断或 SSR 渲染层级限制跳过最内层——结果是语言切换后部分文字没变,且无任何错误提示。
- 检查目标元素路径:右键 Elements 面板中该节点 → “Reveal in Elements panel”,从
开始数嵌套层级,确认 ≤6 - 把纯布局
<div> 替换为语义化标签,如 <code><main></main>、<section></section>、@#@#@#@#@#@#@#@#@#@0")只能走innerHTML,但语言包里对应值必须是白名单过滤后的纯 HTML 片段,禁止拼接用户输入lang 属性同步为什么总出错
只改
document.documentElement.lang是最常见也最危险的错误——它对已渲染的子元素完全无效。浏览器字体回退、标点间距、屏幕阅读器语音引擎,全部依赖每个元素自身的lang属性,而不是继承值。- 初始化时,除设置
document.documentElement.lang = 'zh-Hans'外,还需遍历所有含文本的语义化标签(<h1></h1>、<p></p>、<section></section>),统一设el.lang = 'zh-Hans' - 已有特殊
lang的元素(如<pre class="brush:php;toolbar:false;" lang="sql"></pre>、<code lang="js">)必须跳过,这是合法的多语言混排,强行覆盖会导致代码字体异常 -
<script></script>和<style></style>标签内不要写lang,它们不参与文本渲染,设了也白设 - BCP 47 格式必须严格:用
zh-Hans,不用zh_CN或chinese,后者会被浏览器忽略甚至触发 fallback 失败
lang属性没同步、深层节点漏遍历、或 placeholder 被忽略这些细节里,一漏就是整块功能不可用,还很难复现。 - 初始化时,除设置











