fix(i18n): 补全 367 个缺失的 en-US 翻译键 — monitor 命名空间全覆盖
zh-CN/en-US 翻译键差集从 367 → 0,双语完全对齐 (6088/6088 keys)。
修复内容:
- monitor.alertChannel.* (25 keys): 通知渠道管理弹框
- monitor.alertChannels.* (13 keys): 渠道列表 Tab
- monitor.alertHelper.* (19 keys): 告警辅助函数(渠道/严重度/来源/状态)
- monitor.alertRulesTab.* (13 keys): 告警规则 Tab
- monitor.contactDialog.* (18 keys): 联系人弹框
- monitor.contactGroup.* (14 keys): 联系组弹框
- monitor.hostDashboard.* (23 keys): 主机监控仪表盘
- monitor.logPanel.* (58 keys): 日志查询面板(含 logResults 子命名空间)
- monitor.metricCatalog.* (8 keys): 指标目录
- monitor.monitorRule.* (17 keys): 监控规则配置
- monitor.notifyPolicy.* (30 keys): 通知策略
- monitor.promDs.* (17 keys): Prometheus 数据源配置
- monitor.silenceDialog.* (33 keys): 静默规则弹框
- monitor.silenceRules.* (34 keys): 静默规则列表
- monitor.traceMgr.* (35 keys): 链路追踪管理
新增 scripts/i18n-verify-keys.py 差集检测脚本 (--fix 可自动补全占位)。
⚠️ 缺失翻译键是静默失败: i18next 渲染 key 路径本身而非翻译文本,
切换到英文时用户看到 monitor.xxx.xxx 而非英文。
This commit is contained in:
1 parent
55f216cfbb
commit
eb98a95842
2 files changed
+494
-2
No files matched your search
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
i18n-verify-keys.py — Detect missing/extra translation keys between zh-CN and en-US.
|
||||
|
||||
Usage:
|
||||
python3 scripts/i18n-verify-keys.py # Report only
|
||||
python3 scripts/i18n-verify-keys.py --fix # Copy zh-CN values as placeholder
|
||||
|
||||
Exit code: 0 if keys are in sync, 1 if there are missing keys.
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def flatten(d, prefix=''):
|
||||
items = {}
|
||||
for k, v in d.items():
|
||||
full = f'{prefix}.{k}' if prefix else k
|
||||
if isinstance(v, dict):
|
||||
items.update(flatten(v, full))
|
||||
else:
|
||||
items[full] = v
|
||||
return items
|
||||
|
||||
def set_nested(d, key_path, value):
|
||||
parts = key_path.split('.')
|
||||
current = d
|
||||
for part in parts[:-1]:
|
||||
if part not in current or not isinstance(current[part], dict):
|
||||
current[part] = {}
|
||||
current = current[part]
|
||||
current[parts[-1]] = value
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Verify i18n key parity between zh-CN and en-US')
|
||||
parser.add_argument('--fix', action='store_true', help='Copy zh-CN values as placeholder for missing en-US keys')
|
||||
args = parser.parse_args()
|
||||
|
||||
base = os.path.join(os.path.dirname(__file__), '..', 'frontend', 'src', 'locales')
|
||||
zh_path = os.path.join(base, 'zh-CN.json')
|
||||
en_path = os.path.join(base, 'en-US.json')
|
||||
|
||||
zh = json.load(open(zh_path))
|
||||
en = json.load(open(en_path))
|
||||
|
||||
zh_flat = flatten(zh)
|
||||
en_flat = flatten(en)
|
||||
|
||||
missing_en = sorted(set(zh_flat) - set(en_flat))
|
||||
extra_en = sorted(set(en_flat) - set(zh_flat))
|
||||
|
||||
print(f'zh-CN keys: {len(zh_flat)}')
|
||||
print(f'en-US keys: {len(en_flat)}')
|
||||
print(f'Missing in en-US: {len(missing_en)}')
|
||||
print(f'Extra in en-US: {len(extra_en)}')
|
||||
|
||||
if missing_en:
|
||||
# Group by namespace
|
||||
ns = {}
|
||||
for k in missing_en:
|
||||
prefix = k.split('.')[0] + '.' + k.split('.')[1] if '.' in k else k
|
||||
ns[prefix] = ns.get(prefix, 0) + 1
|
||||
print('\nMissing by sub-namespace:')
|
||||
for k, v in sorted(ns.items()):
|
||||
print(f' {k}.* : {v} keys')
|
||||
|
||||
print('\nFirst 20 missing keys:')
|
||||
for k in missing_en[:20]:
|
||||
print(f' - {k} = {zh_flat[k]}')
|
||||
|
||||
if extra_en:
|
||||
print('\nExtra en-US keys (not in zh-CN):')
|
||||
for k in extra_en[:10]:
|
||||
print(f' + {k}')
|
||||
|
||||
if args.fix and missing_en:
|
||||
for key in missing_en:
|
||||
set_nested(en, key, zh_flat[key])
|
||||
with open(en_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(en, f, ensure_ascii=False, indent=2)
|
||||
f.write('\n')
|
||||
print(f'\n[fix] Copied {len(missing_en)} zh-CN values as en-US placeholders.')
|
||||
print('[fix] NOTE: Replace with proper English translations!')
|
||||
|
||||
if missing_en or extra_en:
|
||||
sys.exit(1)
|
||||
else:
|
||||
print('\n✅ zh-CN and en-US keys are in sync.')
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in new issue
Block a user