必须为每种语言配置独立 HtmlWebpackPlugin 实例并使用带语言标识的模板(如index.zh-CN.html),在模板中为文本标签显式设置lang属性,JSON语言包需扁平结构且路径键名严格一致,动态内容须由运行时JS翻译。

html-webpack-plugin 多实例配置必须按语言拆模板
直接复用同一份 index.html 模板无法生成多语言 HTML 文件——html-webpack-plugin 不会自动替换 data-i18n 属性,它只负责注入资源、生成 HTML 结构。要输出 zh-CN/index.html、en-US/index.html 等独立文件,必须为每种语言准备专属模板:
- 模板文件名建议带语言标识,如
src/index.zh-CN.html、src/index.en-US.html - 每个模板中保留原始中文文案(或英文),但必须打上
data-i18n属性,例如<h1 data-i18n="header_title">欢迎</h1> - 在
webpack.config.js中创建多个HtmlWebpackPlugin实例,每个实例指定不同template和filename,并传入对应语言的templateParameters(可选)
不这么做,就只剩“单 HTML + JS 运行时翻译”一条路,构建阶段无法产出静态多语言页面。
lang 属性必须手动同步到所有语义化元素
只设置 document.documentElement.lang = 'zh-Hans' 是无效操作——浏览器和屏幕阅读器完全不认这个全局声明。每个含文本的标签(<p>、<h2>、<footer>)都得显式写 lang="zh-Hans",否则标点间距、字体 fallback、语音朗读全错。
- 构建时可在模板中硬编码根节点
<html lang="zh-Hans">,但子元素不能靠继承 - 若使用
html-webpack-plugin的templateParameters注入语言码,可用 EJS 或类似语法批量写入:<p lang="<%= lang %>">... - 已有
lang的特殊节点(如<pre lang="bash">、<blockquote lang="ja">)必须跳过更新,这是合法的多语言混排场景
漏掉任意一个 lang,就可能让日文顿号被当成中文渲染,或英文代码块套上思源黑体。
立即学习“前端免费学习笔记(深入)”;
JSON 语言包路径和结构必须严格一致
构建阶段加载语言包不是运行时行为,所以路径错误或键缺失会导致整个 HTML 渲染失败——Webpack 打包时找不到 locales/zh-CN.json 就会报错,而不是静默 fallback。
- 语言包文件必须放在
src/locales/下,命名统一为zh-CN.json、en-US.json,不可用zh.json或chinese.json - 所有 JSON 必须扁平结构:
{"login_btn": "登录", "form_email_required": "邮箱不能为空"},禁止嵌套对象 - 键名必须完全一致:某语言缺译,也得保留该键并设为空字符串
"nav_help": "",否则构建时JSON.parse()可能因格式问题中断
构建工具不会帮你校验键对齐,一旦 en-US.json 少了个 submit_btn,生成的英文页就会出现原始键名,而不是 fallback 到中文。
动态插入内容必须在构建后由 JS 补充翻译
Webpack 构建只处理初始 HTML 模板,AJAX 加载的弹窗、分页表格新行、懒加载模块里的 data-i18n 标记,在构建时根本不存在,自然不会被处理。
- 构建产物里只保证首屏静态内容完成标记,其余部分需靠运行时 JS 主动调用翻译函数
- 推荐封装一个
translateNode(node)函数,遍历子节点查找data-i18n及其变体(data-i18n-placeholder等),再查语言包替换 - 插入新 DOM 后必须立即执行:
modalEl.appendChild(newContent); translateNode(newContent);
别指望构建阶段覆盖所有动态场景——那是运行时职责,混淆这两层,项目后期必然出现“首页正常,弹窗全是 key”的问题。



















