document.documentelement.lang仅是语义标记,不触发文本更新;data-i18n必须显式标注在元素上,lang属性需逐个更新,json键名须完全一致,加载失败需fallback,intl对象需重建。

只改 document.documentElement.lang 不会触发任何文本更新,屏幕阅读器、字体回退、标点渲染也不会变——它只是个语义标记,不是开关。
data-i18n 标记必须打在具体元素上,不能靠 class 或 id 推断
浏览器和 JS 都不会自动猜哪个 <p></p> 该显示“关于我们”,哪个该显示“About Us”。必须显式写 data-i18n="nav.about",否则遍历 [data-i18n] 时根本找不到它。
-
<h2 class="header">首页</h2>→ 不加data-i18n,切换语言后文字永远不变 -
<input placeholder="搜索...">→ 要翻译 placeholder,得写data-i18n-placeholder="search_hint",textContent对它无效 -
<img alt="产品图">→ 同样需data-i18n-alt="product_image",否则 alt 不会更新 - 含 HTML 的文案(如
"请阅读@#@#@#@#@#@#@#@#@#@0")必须用innerHTML替换,且语言包里对应值得是已转义的可信 HTML,否则有 XSS 风险
lang 属性必须逐个更新,根节点设置对已渲染元素无效
只执行 document.documentElement.lang = 'zh-CN',所有已有 <p lang="en"></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8961" title="html-to-pptx-converter"><img
src="https://img.php.cn/upload/skill/000/000/081/179232667384043.jpg" alt="html-to-pptx-converter" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8961" title="html-to-pptx-converter" class="overflowclass">html-to-pptx-converter</a>
<p class="overflowclass">使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。</p>
</div>
<a rel="nofollow" href="/xiazai/skill8961" title="html-to-pptx-converter" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div> 的段落仍按英文规则断字、朗读、渲染引号——浏览器在解析 DOM 时就已锁定各节点的 lang 值,不会回溯重算。
- 切换语言时,要遍历所有带
lang属性的元素:document.querySelectorAll('[lang]'),再逐个设el.lang = nextLang - 例外:明确需保留原语言的内容(如引用日文原文的
<blockquote lang="ja"></blockquote>),就不更新它的lang -
lang值必须符合 BCP 47 标准:zh-CN可行,zh_CN、chinese或zh会被部分浏览器忽略,fallback 到und
JSON 语言包结构不一致,加载后必出空文案
如果 en.json 里有 "button.submit": "Submit",但 zh.json 里漏了这行或写成 "btn.submit": "提交",JS 查 i18n['zh']['button.submit'] 就是 undefined,最终显示空白。
- 所有语言 JSON 文件键名必须完全一致,哪怕某语言暂未翻译,也得留
"button.submit": ""或占位符 - 扁平结构优先:
{"home.title": "Home", "form.email": "Email"},别嵌套成{"home": {"title": "Home"}}——增加 JS 查找成本,且容易漏层级 - 加载失败必须 fallback:
fetch('/locales/zh.json').catch(() => loadFallback('en')),否则用户看到满屏空格 - 路径拼接别硬来:
window.location.href = '/zh' + location.pathname在/blog/post/下会变成/zh/blog/post/,但若当前已是/en/blog/post/,就得先用正则location.pathname.replace(/^\/(en|zh|ja)\//, '/zh/')替换前缀,避免多斜杠或 404
最易被忽略的点:切换语言后,Intl.DateTimeFormat 和 Intl.NumberFormat 实例不会自动更新——你得重建它们,否则日期仍按旧语言格式显示。还有,表单输入框的 value 别动,但 placeholder、title、alt 这些属性必须单独处理,漏一个,无障碍体验就断一环。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










