克隆 template 后 data-i18n 不生效,因 template 内容不参与渲染且翻译脚本不自动扫描;必须在 document.importNode 后立即调用 translateNode(clonedNode),递归处理子树并同步设置 lang 属性。

template 元素克隆后 data-i18n 不生效
直接把 <template> 当作模块复用,里面写了 data-i18n="header_title",但克隆插入后文字还是英文——这不是 bug,是设计使然。<template> 内容不参与 DOM 渲染、不触发事件、也不被全局翻译脚本扫描。克隆出来的是“冷节点”,属性还在,但没人处理它。
常见错误是只在 DOMContentLoaded 里跑一次 translateNode(document.body),漏掉后续动态挂载的模板实例。
- 每次调用
document.importNode(template.content, true)后,必须立刻传给翻译函数,比如translateNode(clonedNode) -
translateNode()要递归遍历子树,识别data-i18n和带后缀的属性(如data-i18n-placeholder) - 别依赖“自动扫描 document”,克隆体是独立子树,得显式喂进去
如何让 template 模块支持语言切换
语言切换不是重刷整个页面,而是“克隆 → 插入 → 立即翻译”闭环。关键点不在模板本身,而在插入后的即时处理。
- 模板加载完成前,用
style="display:none"隐藏,避免闪出原始文案 - 翻译函数里,对每个已处理的文本节点(
<p>、<h2>),同步设node.lang = currentLang;已有lang属性的节点(如<pre lang="bash">)跳过,保留原值 - 克隆后检查父容器是否带
lang,若无则补上,防止嵌套结构中部分区域语言错乱 - 表单控件(
<input>、<select>)只更新placeholder、title、label文本,跳过value——那是用户输入,不该被翻译
fetch 加载外部 template 时的国际化断链风险
当 <template> 内容来自 fetch('nav.html') 而非内联时,链条变长:网络请求 → 解析 HTML → 提取 template.content → 克隆 → 插入 → 翻译。任一环节失败,就会空白或残留英文。
立即学习“前端免费学习笔记(深入)”;
-
fetch()成功后,先检查响应类型是否为text/html,再用DOMParser解析,避免 MIME 类型不匹配导致解析失败 - 解析出的
<template>可能含多个data-i18n,但没加载完语言包就克隆,会查不到 key —— 必须等Promise.all([fetchTemplate(), fetchLocale(lang)])都 resolve 后再执行 - HTTP 返回的 HTML 模板文件,必须确保 UTF-8 编码且不含 BOM,否则 IE/Edge Legacy 会回退到 GBK,中文全乱码
- 不要在
<script>或<style>标签里写data-i18n,这些节点不渲染文本,加了也白加
JSON 语言包结构与 template 的键名对齐陷阱
模板里写 data-i18n="nav.home",但 JSON 里是 {"nav": {"home": "首页"}},翻译函数找不到键——因为扁平化是硬性要求。
- 所有语言包(
zh.json、en.json)必须是顶层键值对:{"nav_home": "首页", "btn_submit": "提交"} - 键名统一用小写字母 + 下划线,不嵌套、不驼峰,否则不同语言文件容易漏字段或拼错
- 某语言暂未翻译,也要留空字符串:
"nav_home": "",而不是删掉这个 key,否则translateNode()查不到就留白 - 加载失败时 fallback 到默认语言包,但不能 fallback 到硬编码字符串——那会破坏可维护性
lang 属性没同步、data-i18n 还躺在那里没人理——它不会自己动。



















