resConfigs 仅控制 Android 打包语言资源,不生成组件级国际化映射表;需通过 AST/正则提取 key、CSV/YAML 管理翻译、动态 import 懒加载 JSON 实现自动化多语言支持。

resConfigs 配置不能替代组件级国际化资源映射表生成 —— 它只控制 Android 构建时打包哪些语言的 resources.arsc,不生成、也不管理组件自身的多语言字符串映射逻辑。
真正需要自动化生成“组件国际化资源映射表”的场景,通常出现在:
- 自研 UI 组件库需支持多语言(如按钮文案、提示语、校验错误信息)
- 组件以独立包形式发布,需向使用者暴露结构化语言资源(非硬编码)
- 构建流程中需从源码提取 key → 合并翻译 → 输出 JSON/JS 模块供运行时加载
下面分三步说清怎么做、为什么、容易踩什么坑:
如何让构建脚本自动扫描组件并提取 i18n key
核心是用 AST 或正则在构建阶段遍历组件源码(如 .ts / .vue),识别调用 $t('xxx')、t('yyy')、useI18n().t('zzz') 等模式,收集所有字符串 key。
推荐用 glob + acorn 或轻量方案 find + grep(适合简单项目):
grep -r -o -E "\$t\('[^']+'\)|t\('[^']+'\)|\.t\('[^']+'\)" src/components/ | sed "s/[^']*'\([^']*\)'.*/\1/" | sort -u > i18n/keys.txt
- 必须排除 node_modules 和构建产物目录,否则会混入依赖里的 key
- 正则要覆盖常见 i18n 调用写法,比如 Vue I18n v9 的
useI18n().t()和 Composition API 风格 - 若组件使用动态 key(如
$t(`${type}.label`)),静态扫描会漏掉,需人工补全或加白名单注释
如何在构建时合并翻译并输出标准化映射表
提取出 key 列表后,需与翻译源对齐。不建议手写 JSON,而应把翻译维护在 CSV 或 YAML 中(方便运营/翻译人员协作),再由构建脚本转成运行时可用格式。
示例 locales/en.yaml:
button: { submit: "Submit", cancel: "Cancel" }
form: { required: "This field is required" }
构建脚本(./scripts/gen-i18n.js)执行:
- 读取
keys.txt所有 key,按点号分割路径(如form.required→["form", "required"]) - 递归构建嵌套对象,缺失字段填空字符串或占位符(如
"MISSING: form.required") - 输出为
dist/locales/en.json和dist/locales/zh-CN.json,确保字段完全对齐 - 可选:生成 TypeScript 类型定义
locales.d.ts,避免运行时 key 错误
如何让组件在构建后自动注入映射表并支持运行时切换
关键不是“打包进 APK”,而是让组件能被消费方按需加载语言包。典型做法是导出一个 createI18nMap 工厂函数:
export function createI18nMap(lang: string) {
switch (lang) {
case 'en': return import('./locales/en.json');
case 'zh-CN': return import('./locales/zh-CN.json');
default: return import('./locales/en.json');
}
}
- 不要直接
import * as en from './locales/en.json',否则 Webpack 会全部打包进去 - 组件内部用
createI18nMap(lang).then(m => m.default[key])实现懒加载 - Cocos Creator 场景下注意:
import()在构建后可能被转为require(),需确认builder.js中已启用dynamicImport支持 - Android/iOS 原生层若需访问这些映射,得额外桥接到 JSContext 或通过 AssetManager 加载 JSON 文件
为什么不用 Android 的 resConfigs 解决组件 i18n
resConfigs 'en' 只影响 res/values/strings.xml 类原生资源,对 JS/TS 组件完全无效。组件内字符串走的是 JS 运行时逻辑,和 resources.arsc 是两套体系。
混淆点常出现在:开发者看到 appcompat 带来几十种语言的 strings,就以为自己组件的文案也受其控制 —— 实际上,那些只是 androidx.appcompat 自己的界面字符串,你的 Button.text = $t('login') 不会因此被删掉或替换。
真正的体积优化来自:减少冗余语言 JSON 包体积 + 按需加载 + 构建时剔除未使用的 locale 模块(需配合 webpack.IgnorePlugin 或 Vite 的 treeShaking 配置)。
最容易被忽略的是 key 的一致性维护 —— 提取脚本跑一次、翻译文件改一次、组件里又硬写了一个新 key,三者不同步,映射表就失效了。建议把 gen-i18n.js 接入 pre-commit hook 或 CI 构建第一步,强制校验。










