fix(i18n): U18 幻影 i18n hash 键治理 — 从 git 历史恢复 1540/1696 处原始中文文本 (91%)

问题: i18n 批量转换 (commit 55f216c) 生成了 813 个 hash 键引用但翻译从未写入 JSON,
导致用户在受影响模块看到 hash 键路径(如 monitor.quickquerybarts.s64559524)而非实际文本.
影响范围: 126 个文件、1696 处引用、monitor/kubernetes/aiops/pipeline/task/agent/cloud 11 个命名空间.

修复策略: 用 git 历史中 pre-i18n 版本(commit 7e1c8f5)的原始中文文本,
通过结构相似度匹配(difflib SequenceMatcher)将 hash 键引用替换为实际字符串.
对于组件拆分后产生的新文件,映射到其原始源文件查找中文文本.

修复明细:
- monitor 命名空间: 335 键修复(站点拨测/日志中心/中间件监控/告警规则/SNMP/主机监控)
- kubernetes 命名空间: 195 键修复(资源编辑器/Deployment编辑器/事件/命名空间/Pod日志)
- aiops 命名空间: 70 键修复(容量预测/成本预测/告警分析)
- pipeline/task/agent/cloud/common 命名空间: 其余键修复

验证: tsc -b=0, npm build✓ (16.87s), ESLint=0/0/0, go build=0, 17/17 测试通过, Docker healthy
This commit is contained in:
attacker committed 2026-07-11 05:49:23 +08:00
1 parent be1011eb58
commit 4c4aaf60f6
100 files changed
+688 -688

No files matched your search

@@ -52,8 +52,8 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
renderRow: (item: any, opts: ResourceRowOpts) => React.ReactNode;
}> = {
deployments: {
title: 'Deployments', subtitle: i18n.t('kubernetes.namespaceresour.s35c744fb'), icon: Boxes,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('kubernetes.capacitypagetsx.s0428b36a'), i18n.t('kubernetes.container.image')],
title: 'Deployments', subtitle: i18n.t('Deployment 工作负载运行状态'), icon: Boxes,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('名称'), i18n.t('kubernetes.container.image')],
renderRow: (d, opts) => (
<TableRow key={d.name} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-tertiary)]/30 cursor-pointer" onClick={() => opts.onDetail?.(d)}>
<TableCell className="font-medium text-[var(--dg-text-primary)]">{d.name}</TableCell>
@@ -77,7 +77,7 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
),
},
pods: {
title: 'Pods', subtitle: i18n.t('kubernetes.namespaceresour.s780b7dd3'), icon: Container,
title: 'Pods', subtitle: i18n.t('Pod 实例运行状态'), icon: Container,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('system.terminalStatus'), i18n.t('kubernetes.node.title'), 'CPU', i18n.t('kubernetes.pod.memory'), i18n.t('agent.agentServiceRestart'), i18n.t('kubernetes.container.image'), i18n.t('system.auditAction')],
renderRow: (p, opts) => {
const statusMap: Record<string, string> = { Running: 'bg-[var(--dg-green)]/20 text-[var(--dg-green)] border-[var(--dg-green)]/30', Pending: 'bg-[var(--dg-orange)]/20 text-[var(--dg-orange)] border-[var(--dg-orange)]/30', Failed: 'bg-[var(--dg-red)]/20 text-[var(--dg-red)] border-[var(--dg-red)]/30' };
@@ -113,7 +113,7 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
},
},
services: {
title: 'Services', subtitle: i18n.t('kubernetes.namespaceresour.s5e76b605'), icon: Network,
title: 'Services', subtitle: i18n.t('Service 网络服务'), icon: Network,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('system.credentialType'), 'Cluster IP', i18n.t('system.ldapPort'), i18n.t('system.auditAction')],
renderRow: (s, opts) => (
<TableRow key={s.name} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-tertiary)]/30">
@@ -127,7 +127,7 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
),
},
ingresses: {
title: 'Ingresses', subtitle: i18n.t('kubernetes.namespaceresour.s8d501473'), icon: Network,
title: 'Ingresses', subtitle: i18n.t('Ingress 路由规则'), icon: Network,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), 'Hosts', 'TLS', i18n.t('system.auditAction')],
renderRow: (i, opts) => {
const hosts = i.hosts || [];
@@ -143,8 +143,8 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
},
},
configmaps: {
title: 'ConfigMaps', subtitle: i18n.t('kubernetes.namespaceovervi.s0986a6e7'), icon: FileText,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('kubernetes.namespaceresour.sbd1fa02a'), i18n.t('system.auditAction')],
title: 'ConfigMaps', subtitle: i18n.t('配置字典'), icon: FileText,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('名称'), i18n.t('system.auditAction')],
renderRow: (c, opts) => (
<TableRow key={c.name} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-tertiary)]/30">
<TableCell className="font-medium text-[var(--dg-text-primary)]">{c.name}</TableCell>
@@ -155,7 +155,7 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
),
},
secrets: {
title: 'Secrets', subtitle: i18n.t('kubernetes.namespaceresour.sd1424af7'), icon: Shield,
title: 'Secrets', subtitle: i18n.t('密钥管理(仅名称与类型)'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('system.credentialType'), i18n.t('system.auditAction')],
renderRow: (s, opts) => (
<TableRow key={s.name} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-tertiary)]/30">
@@ -167,7 +167,7 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
),
},
hpas: {
title: 'HPAs', subtitle: i18n.t('kubernetes.namespaceresour.s9abc8d19'), icon: Activity,
title: 'HPAs', subtitle: i18n.t('水平自动伸缩'), icon: Activity,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('monitor.alertEvents.col.target'), i18n.t('k8s.hpaCronHpa.col.minMax'), 'CPU%', 'Mem%'],
renderRow: (h, _opts) => (
<TableRow key={h.name} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-tertiary)]/30">
@@ -194,7 +194,7 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
),
},
pvcs: {
title: i18n.t('kubernetes.namespaceresour.s18c90062'), subtitle: 'PersistentVolumeClaim', icon: Boxes,
title: i18n.t('存储卷声明'), subtitle: 'PersistentVolumeClaim', icon: Boxes,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('system.terminalStatus'), i18n.t('kubernetes.storage.pvcSize'), 'StorageClass', i18n.t('system.auditAction')],
renderRow: (p, opts) => (
<TableRow key={p.name} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-tertiary)]/30">
@@ -208,8 +208,8 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
),
},
statefulsets: {
title: 'StatefulSets', subtitle: i18n.t('kubernetes.namespaceresour.sbfeb44d8'), icon: Boxes,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('kubernetes.capacitypagetsx.s0428b36a'), i18n.t('kubernetes.pod.ready'), i18n.t('kubernetes.container.image')],
title: 'StatefulSets', subtitle: i18n.t('有状态应用'), icon: Boxes,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('名称'), i18n.t('kubernetes.pod.ready'), i18n.t('kubernetes.container.image')],
renderRow: (s, opts) => (
<TableRow key={s.name} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-tertiary)]/30 cursor-pointer" onClick={() => opts.onDetail?.(s)}>
<TableCell className="font-medium text-[var(--dg-text-primary)]">{s.name}</TableCell>
@@ -221,7 +221,7 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
),
},
daemonsets: {
title: 'DaemonSets', subtitle: i18n.t('kubernetes.namespaceresour.se1c074e2'), icon: Boxes,
title: 'DaemonSets', subtitle: i18n.t('守护进程集'), icon: Boxes,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('monitor.siteProtocol.http.expectedPrefix'), i18n.t('cloud.current'), i18n.t('kubernetes.pod.ready'), i18n.t('kubernetes.container.image')],
renderRow: (d, opts) => (
<TableRow key={d.name} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-tertiary)]/30 cursor-pointer" onClick={() => opts.onDetail?.(d)}>
@@ -235,8 +235,8 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
),
},
serviceaccounts: {
title: 'ServiceAccounts', subtitle: i18n.t('kubernetes.namespaceresour.s645c9a3d'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('kubernetes.namespaceresour.sbaf7ed70'), i18n.t('kubernetes.namespaceresour.s260c11ec'), i18n.t('system.userCreatedAt'), i18n.t('system.auditAction')],
title: 'ServiceAccounts', subtitle: i18n.t('服务账号(RBAC 身份标识)'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('名称'), i18n.t('命名空间'), i18n.t('system.userCreatedAt'), i18n.t('system.auditAction')],
renderRow: (sa, opts) => (
<TableRow key={sa.name} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-tertiary)]/30">
<TableCell className="font-medium text-[var(--dg-text-primary)]">{sa.name}</TableCell>
@@ -247,15 +247,15 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
</TableCell>
<TableCell className="text-xs text-[var(--dg-text-muted)]">{sa.age || '-'}</TableCell>
<TableCell onClick={(e) => e.stopPropagation()}>
<Button variant="ghost" size="icon" className="h-7 w-7 text-[var(--dg-text-secondary)] hover:text-[var(--dg-blue)]" title={i18n.t('kubernetes.namespaceresour.s4bde086b')}
<Button variant="ghost" size="icon" className="h-7 w-7 text-[var(--dg-text-secondary)] hover:text-[var(--dg-blue)]" title={i18n.t('查看YAML')}
onClick={() => opts.onYaml?.(sa.name)}><FileCode className="h-3.5 w-3.5" /></Button>
</TableCell>
</TableRow>
),
},
roles: {
title: 'Roles', subtitle: i18n.t('kubernetes.namespaceresour.s8905a680'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('kubernetes.namespaceresour.secde032d'), i18n.t('system.apiKeyScope'), i18n.t('system.userCreatedAt'), i18n.t('system.auditAction')],
title: 'Roles', subtitle: i18n.t('命名空间级角色权限(RBAC)'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('名称'), i18n.t('system.apiKeyScope'), i18n.t('system.userCreatedAt'), i18n.t('system.auditAction')],
renderRow: (r, opts) => {
const verbs = r.verbs || [];
const resources = r.resources || [];
@@ -275,7 +275,7 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
<TableCell className="text-xs text-[var(--dg-text-muted)]">{r.age || '-'}</TableCell>
<TableCell onClick={(e) => e.stopPropagation()}>
<div className="flex items-center gap-0.5">
<Button variant="ghost" size="icon" className="h-7 w-7 text-[var(--dg-text-secondary)] hover:text-[var(--dg-blue)]" title={i18n.t('kubernetes.namespaceresour.s4bde086b')}
<Button variant="ghost" size="icon" className="h-7 w-7 text-[var(--dg-text-secondary)] hover:text-[var(--dg-blue)]" title={i18n.t('查看YAML')}
onClick={() => opts.onYaml?.(r.name)}><FileCode className="h-3.5 w-3.5" /></Button>
<Button variant="ghost" size="icon" className="h-7 w-7 text-[var(--dg-green)] hover:text-[var(--dg-green)]" title={i18n.t('common.edit')}
onClick={() => opts.onEdit?.(r.name)}><Pencil className="h-3.5 w-3.5" /></Button>
@@ -286,8 +286,8 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
},
},
rolebindings: {
title: 'RoleBindings', subtitle: i18n.t('kubernetes.namespaceresour.sca10fe5c'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('kubernetes.namespaceresour.s227e5e28'), i18n.t('kubernetes.namespaceresour.s2667c7d8'), i18n.t('system.userCreatedAt'), i18n.t('system.auditAction')],
title: 'RoleBindings', subtitle: i18n.t('角色绑定关系(RBAC 授权)'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('名称'), i18n.t('命名空间'), i18n.t('system.userCreatedAt'), i18n.t('system.auditAction')],
renderRow: (rb, opts) => {
const subjects = rb.subjects || [];
const subjStr = subjects.length > 3 ? subjects.slice(0, 3).join(', ') + ` +${subjects.length - 3}` : subjects.join(', ');
@@ -306,7 +306,7 @@ export const RESOURCE_CONFIG: Record<ResourceType, {
<TableCell className="text-xs text-[var(--dg-text-muted)]">{rb.age || '-'}</TableCell>
<TableCell onClick={(e) => e.stopPropagation()}>
<div className="flex items-center gap-0.5">
<Button variant="ghost" size="icon" className="h-7 w-7 text-[var(--dg-text-secondary)] hover:text-[var(--dg-blue)]" title={i18n.t('kubernetes.namespaceresour.s4bde086b')}
<Button variant="ghost" size="icon" className="h-7 w-7 text-[var(--dg-text-secondary)] hover:text-[var(--dg-blue)]" title={i18n.t('查看YAML')}
onClick={() => opts.onYaml?.(rb.name)}><FileCode className="h-3.5 w-3.5" /></Button>
<Button variant="ghost" size="icon" className="h-7 w-7 text-[var(--dg-green)] hover:text-[var(--dg-green)]" title={i18n.t('common.edit')}
onClick={() => opts.onEdit?.(rb.name)}><Pencil className="h-3.5 w-3.5" /></Button>