自定义元素中需显式添加data-i18n属性绑定翻译键,如;属性翻译用data-i18n-placeholder等后缀;shadow dom内文本须在connectedcallback中主动处理,且需监听lang-change事件单独更新,不能依赖全局遍历。

自定义元素里怎么绑定翻译键
直接在自定义元素上加 data-i18n 属性,值是语言包里的键名,比如 <my-button data-i18n="submit.btn"></my-button>。自定义元素内部不能靠猜——它不会自动从父级或 class 名提取键,必须显式声明。
如果要翻译的是属性(如 placeholder、title),得用带后缀的写法:data-i18n-placeholder="form.search" 或 data-i18n-title="tooltip.save"。默认只更新 textContent,其他属性不联动。
- 别在
<script></script>、<style></style>、<pre class="brush:php;toolbar:false;"></pre>里加data-i18n—— 这些节点不渲染为用户可见文本,加了无效 - Shadow DOM 内部的文本需单独处理:不能靠外部遍历,得在
connectedCallback或attributeChangedCallback里主动查自己 shadowRoot 下的节点 - IE11 不支持
this.dataset.i18n驼峰访问,得用this.getAttribute('data-i18n')兜底
语言切换时如何避免 Shadow DOM 文本丢失
自定义元素一旦挂载,其 Shadow DOM 就脱离主文档树。全局遍历 document.querySelectorAll('[data-i18n]') 找不到它内部的节点——这是最常被忽略的坑。
正确做法是在语言变更事件中,让每个自定义元素自己响应:监听一个自定义事件(如 lang-change),在 connectedCallback 里注册监听,在 disconnectedCallback 里移除。切换时触发事件,由各实例自行更新内部文本。
- 不要在
attributeChangedCallback里直接操作shadowRoot更新文本——lang属性只是标记,不是实时数据源;应配合全局语言状态读取对应 JSON 键值 - 若用插值(如
"hello {name}"),插值参数不能存在语言包里,得由组件外传入,否则无法复用同一套翻译资源 - Shadow DOM 中含 HTML 结构(如带
<strong></strong>的提示语)时,必须用innerHTML替换,但语言包值需确保是白名单过滤后的纯片段,否则有 XSS 风险
为什么不能只改 document.documentElement.lang
只设置根节点 lang,对自定义元素内部的文本、屏幕阅读器播报、字体回退完全没影响。浏览器和辅助技术按每个节点自己的 lang 属性决定行为,不是继承来的。
自定义元素内部若含多语言混排内容(比如一段英文代码块、日文引用),必须显式给对应子节点设 lang="en" 或 lang="ja"。切换主语言时,这些局部 lang 值不能跟着变——它们是内容固有属性,不是 UI 主题的一部分。
-
document.documentElement.lang必须符合 BCP 47 标准(如zh-Hans),zh_CN或chinese会被忽略,导致 fallback 失效 - 自定义元素若封装了
<time></time>或<input type="date">,仅更新文本不够,还得重建Intl.DateTimeFormat实例并重设lang属性,否则日期格式仍用旧语言 - 第三方 Web Component(如
vaadin-date-picker)通常不响应全局lang变更,得手动调其 API 设置语言,不能指望统一刷新
JSON 语言包怎么组织才不崩在自定义元素里
每个语言一个扁平 JSON 文件(locales/en.json、locales/zh.json),所有键名严格一致,不嵌套层级。自定义元素加载时按需 fetch,失败则 fallback 到 en,而不是留空或报错中断。
键名建议按组件命名空间隔离,比如 my-button.submit、my-input.placeholder,避免全站共用 submit 导致语义冲突。不同组件间键名重复没关系,只要各自语言包里值对得上。
- 某语言暂未翻译时,对应键必须存在且值为空字符串
""或占位符(如"[missing: my-button.submit]"),否则 JS 查不到 key 就留白,调试困难 - 不要把动态内容(如用户昵称、当前时间)塞进 JSON;用插值语法 + 组件传参实现,保持语言包纯静态
- 加载多个语言包时用
Promise.all并行,但每个自定义元素只加载自己需要的键集(可预编译成最小 bundle),避免全量加载拖慢首屏
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











