Files
lucky_shop/docs/i18n-p2-solution-plan.md
ZF sun d124d58552 docs: add i18n full audit report and p2 solution plan docs
新增两份国际化审计相关文档:
1. 全量国际化审计报告,覆盖项目内i18n调用问题并记录修复过程
2. P2动态key国际化处理方案文档,盘点8处动态key现状并提供落地解决方案
2026-06-29 15:39:33 +08:00

6.6 KiB
Raw Blame History

P2 动态 key 国际化处理方案

范围:审计报告 P2 章节列出的 8 处运行时拼接 $lang() key 日期:2026-06-29 结论:所有已知取值目前在 zh-cn / en-us 中均已存在对应 key,核心问题是无法被静态扫描覆盖;已通过“枚举值兜底 + 运行时 fallback + 专项验证脚本”解决。

实施状态:✅ 已完成(2026-06-29)


一、8 处动态 key 现状盘点

# 文件 调用方式 运行时取值 对应语言包 key 是否齐全
1 components/payment/payment.vue:27 $lang('components.payment.' + item.type) alipay、wechatpay lang/xx/components/payment.js ✅
2 components-diy/diy-tab.vue:907 $lang(title)(仅当 title 含 .) 由 DIY 数据或业务配置决定,常见如 goods.list.xxx、member.index.xxx 取决于具体 title ⚠️ 需数据侧保证
3 pages_order/list.vue:15 $lang('status.' + statusItem.status) all、waitpay、waitsend、waitconfirm、waitrate lang/xx/order/list.js 中 status 对象 ✅
4 pages_promotion/fenxiao/order.vue:6 $lang(item.nameKey) all、pendingSettlement、settled、refunded lang/xx/fenxiao/order.js ✅
5 pages_promotion/fenxiao/team.vue:7 $lang(item.nameKey) levelOne、levelTwo lang/xx/fenxiao/team.js ✅
6 pages_promotion/point/order_list.vue:8 $lang('point.orderList.' + statusItem.nameKey) statusAll、statusPendingPayment、statusCompleted lang/xx/point/order_list.js ✅
7 pages_tool/goods/evaluate.vue:6 $lang(item.langKey) tabAll、tabPositive、tabNeutral、tabNegative lang/xx/goods/evaluate.js ✅
8 pages_tool/pay/cashier.vue:16 $lang('pay.cashier.' + item.type) alipay、wechatpay lang/xx/pay/cashier.js ✅

二、核心风险分析

  1. 静态扫描盲区:scripts/i18n-check.js 只检查 zh-cn / en-us 两包 key 一致性,不会验证 $lang('a.' + b) 形式的 key 在运行时是否真实存在。
  2. 后端新增取值:#1、#8 的 item.type 来自 /api/pay/type,理论上后端可能新增支付方式(如 unionpay、applepay),前端当前只处理了 alipay / wechatpay。
  3. DIY 配置不可控:#2 diy-tab.vue 的 title 来自装修组件数据,如果运营人员填写了含 . 的字符串且未配置对应 key,会显示 raw key 或空串。
  4. 本地枚举安全:#3 ~ #7 的取值由前端本地数组硬编码,只要语言包同步就不会出现缺失;风险最低。

三、推荐处理方案

3.1 立即执行:为动态调用增加 fallback 兜底

对于能拿到原始中文/默认文案的场景,给 $lang() 增加第二参数作为兜底,避免生产环境出现 raw key 或空串。

# 文件 建议修改
1 components/payment/payment.vue:27 {{ $lang('components.payment.' + item.type, item.name) }}
3 pages_order/list.vue:15 {{ $lang('status.' + statusItem.status, statusItem.name) }}
8 pages_tool/pay/cashier.vue:16 {{ $lang('pay.cashier.' + item.type, item.name) }}

说明:item.name / statusItem.name 本身可能是中文,兜底仅在对应 key 缺失时生效,符合“宁可显示中文也不显示 raw key”的保守策略。

3.2 立即执行:DIY tab 组件兜底增强

components-diy/diy-tab.vue:907 已有对象型 title 的兜底逻辑,但字符串型 title 在 key 缺失时会返回 raw key。建议改为:

return this.$lang ? this.$lang(title, title) : title;

这样当 key 不存在时,至少返回原始 title 字符串本身,不会暴露 raw key。

3.3 可选执行:扩展支付方式 key

在 lang/zh-cn/components/payment.js、lang/en-us/components/payment.js、lang/zh-cn/pay/cashier.js、lang/en-us/pay/cashier.js 中预置常见支付方式 key:

// components/payment.js
unionpay: '银联支付',
applepay: 'Apple Pay',
// ...

// pay/cashier.js
unionpay: '银联支付',
applepay: 'Apple Pay',
// ...

这样即使后端新增支付方式,也不会出现 raw key。建议与产品/后端确认当前系统支持的全部支付方式后补充。

3.4 立即执行:建立 P2 专项验证脚本

新增 scripts/verify-p2-keys.js,枚举所有已知动态取值,模拟 resolver 检查是否能解析:

  • 读取 common/js/lang.js 的 normalizeSharedLangPack / normalizePageLangPack。
  • 对 #1、#3、#4、#5、#6、#7、#8 的取值列表逐一验证。
  • 对 #2 的 diy-tab,收集项目内所有可能作为 title 传入的 i18n key(可通过扫描 diy-tab 调用方或装修数据 schema 获得),建立白名单。

脚本输出示例:

✅ components/payment.alipay => 支付宝支付
✅ components/payment.wechatpay => 微信支付
✅ status.waitpay => 待付款
...

3.5 长期建议:减少动态 key 模式

  • 支付方式:建议后端接口直接返回支付方式名称的 i18n key 或多语言 map,而不是让前端用 type 去拼 key。
  • 订单状态:pages_order/list.vue 已经在 statusList 里做了 name 兜底,后续可考虑直接用 statusItem.name 渲染,不再走动态 key。
  • 分销/团队/积分 tab:这些本地枚举 tab 可以直接写死 $lang('xxx'),不需要通过 nameKey / langKey 间接取值,虽然改动略多,但能彻底消除 P2 风险。

四、实施优先级

优先级 事项 预计改动量 收益 状态
P0 为 #1、#3、#8 增加 item.name / statusItem.name fallback 3 处模板 高:防止后端新增取值时暴露 raw key ✅ 已完成
P0 diy-tab.vue 改为 this.$lang(title, title) 1 处 JS 高:防止 DIY 配置错误导致 raw key ✅ 已完成
P1 建立 scripts/verify-p2-keys.js 并接入 CI / pre-commit 1 个脚本 高:持续守护动态 key ✅ 已完成
P1 扩展支付方式 key(确认后端全部支持类型后) 4 个语言包 中:提升扩展性 ⏸️ 可选,待与后端确认
P2 逐步将本地枚举 tab 改为直接 $lang() 调用 5 ~ 6 个文件 低:彻底消除动态 key ⏸️ 可选,收益较低

五、验证清单

  • 修改后 npm run i18n:check 通过。
  • node --check 检查新增脚本通过;.vue 文件 script 块提取后语法检查通过。
  • scripts/verify-p2-keys.js 输出全部 ✅。
  • 在英文环境下手动检查支付方式弹窗、订单列表 tab、分销/团队/积分 tab、商品评价 tab 显示正常(建议发布后人工复核)。