# i18n 审计流程 > 把所有"$lang 是否能正常翻译"的检查收口到一个入口: > **新增组件 / 新增翻译 / 拉取新 bundle.json 之后,跑这一个命令就能出报告。** ## 快速开始 ```bash # 标准体检(最常用) python scripts/i18n_audit.py # 严格模式 — 出现真问题就 exit 1,适合 CI / pre-commit hook python scripts/i18n_audit.py --strict # 拉了新 bundle.json(覆盖了 lang-bundle.json),指定新的: python scripts/i18n_audit.py --bundle ./lang-bundle.2026-07-04.json ``` 报告结束时会输出: ``` 健康度评分: ✓ 99.95% 翻译覆盖,0 个真问题 或 ! 存在 N 类问题需要修: - <类目 1> - <类目 2> ``` 完整结构化报告写到 `scripts/lang_audit_report_v2.json`,适合 diff 或后续处理。 ## 它在做什么(7 个检查) | # | 检查维度 | 暴露什么问题 | 真实程度 | | --- | --- | --- | --- | | 1 | **静态 `$lang(key)` 字面 → bundle leaf** | key 字符串不存在于 bundle | 直接失效 | | 2 | **占位符参数匹配** | `key` 含 `{name}` 但调用没传 `{ name: ... }`,运行时会**字面显示 `{name}`** | 直接失效 | | 3 | **`data()` 中误用** | `data() { return { x: this.$lang(...) } }` 在 mp/鸿蒙 remote-only 模式下会**永久缓存空串** | 远程首屏失效 | | 4 | **bundle ↔ 本地 lang drift** | `lang/zh-cn/...` 有的 key,bundle 没有(可能影响兜底) | 加载策略变更时显现 | | 5 | **pages.json 硬编码导航标题** | `navigationBarTitleText: "商品分类"`,运行时**必须 `lang.refresh()` 兜底** | 取决于 refresh() 调用时机 | | 6 | **i18n-lazy mixin 使用情况** | 哪些组件没遵循延迟初始化约定 | 标记数据风险点 | | 7 | **P2 动态 key** (`verify-p2-keys.js`) | 拼接类 `$lang('prefix.' + var)` 在所有值下都能解析 | 模拟 runtime | ## 误报防御(已针对历史坑修过) - **JS 注释剥离** 改用等长空白,正则偏移不偏(以前的 ghost key 大都是这个原因) - **`[^'\"]+` 跨换行陷阱** 已用手动 paren-depth 解析替代,不会把整个文件吃进 key - **JS 对象简写** `{ appName }` 等同于 `{ appName: appName }`,正则同时识别 - **`/api/lang/bundle` 真会有的** `tabBar.*` 走 root level,审计对 `common.tabBar.home` 故意不报警 - **`lang.js` JSDoc 内** 的 `$lang('title')`、`$lang('welcomeText')` 示例被注释剥离规则前置过滤 ## 文件清单 ``` scripts/ ├── i18n_audit.py ← 唯一入口(run this) ├── audit_lang_bundle_v2.py ← 静态扫描(被 i18n_audit.py 调) ├── audit_lang_bundle.js ← Node 端 lang 加载工具 ├── verify-p2-keys.js ← 动态 key 验证(被 i18n_audit.py 调) ├── I18N_AUDIT.md ← 本文档 └── lang_audit_report_v2.json ← 最近一次报告(自动生成) ``` ## 何时该跑 1. **拉了新 bundle.json**:`/api/lang/bundle` 返回结果存到 `lang-bundle.json` 后,跑一次。 2. **新增 / 修改翻译 key**:`lang/zh-cn/...` 或 `lang/en-us/...` 文件改动后,跑一次。 3. **新增组件**:任何 .vue/.js 引入 `$lang(...)` 后,跑一次。 4. **修复 i18n bug 后**:跑一次,确认`健康度评分`达 `99.95%`。 5. **PR 合并前(CI)**:`python scripts/i18n_audit.py --strict`,exit code 控制是否合入。 ## 想加新的检查怎么办 在 `audit_lang_bundle_v2.py` 加一个 section,产生新字段 → 在 `i18n_audit.py::summarize` 里加一行 `print`。`audit_lang_bundle_v2.py` 写好了自动落入结构化报告。 ## 已知"非 bug 但需注意"(已知风险不需修) - **`pages.json` 中 20 个 `navigationBarTitleText` 硬编码**:由 `lang.refresh()` 自动覆盖,只要 refresh 在页面 mount 后被调到即可。 - **`components-diy/diy-tab.vue` 的 title 是运行时 DIY 数据**:DIY 数据规范/白名单层面解决,不在审计范围。 ## 最近一次结果速查 ```bash cat scripts/lang_audit_report_v2.json ``` 主要字段: ```json { "code_calls_total": 2675, "code_unique_keys": 2083, "found_in_bundle": 2082, "missing_summary": {"SYNTAX_BUG": 1}, "missing_classified": {...}, "placeholder_issues": [], "data_lang_issues": {...}, "hardcoded_navbar_titles": [...], "tabbar_missing": [...], "local_only_keys": [] } ``` `placeholder_issues` 为 `[]` 是绿;`data_lang_issues` 为 `{}` 是绿;`missing_summary.SYNTAX_BUG` ≥ 1 通常是 grep 误报,详见 `missing_classified` 字段的 `reason`。