新增两份国际化审计相关文档: 1. 全量国际化审计报告,覆盖项目内i18n调用问题并记录修复过程 2. P2动态key国际化处理方案文档,盘点8处动态key现状并提供落地解决方案
6.6 KiB
6.6 KiB
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 |
✅ |
二、核心风险分析
- 静态扫描盲区:
scripts/i18n-check.js只检查 zh-cn / en-us 两包 key 一致性,不会验证$lang('a.' + b)形式的 key 在运行时是否真实存在。 - 后端新增取值:#1、#8 的
item.type来自/api/pay/type,理论上后端可能新增支付方式(如unionpay、applepay),前端当前只处理了alipay/wechatpay。 - DIY 配置不可控:#2
diy-tab.vue的 title 来自装修组件数据,如果运营人员填写了含.的字符串且未配置对应 key,会显示 raw key 或空串。 - 本地枚举安全:#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 显示正常(建议发布后人工复核)。