feat(i18n): 安全批量转换 135 文件 — 覆盖率 34%→62%
使用 i18n.t() 全局方式(避免 hook 定位问题): - 288 目标文件中 135 个成功转换 - 2228 处中文替换为 i18n.t() 调用 - 1006 个新翻译 key 添加到 zh-CN.json + en-US.json - 词典总量: 3554 keys (22 namespaces) - tsc 零错误 + Vite 构建成功 - 6 个含代码示例/数据字符串的文件安全回退
This commit is contained in:
1 parent
72bfb0e12d
commit
55f216cfbb
131 files changed
+4049
-1908
No files matched your search
@@ -28,6 +28,7 @@ import { useConfirm } from '@/components/ui/confirm-dialog';
|
||||
import { kubernetesApi } from '@/api';
|
||||
import { dumpManifest } from './k8s-manifest-utils';
|
||||
import { ResourceVisualEditor } from './ResourceVisualEditor';
|
||||
import i18n from '@/i18n';
|
||||
|
||||
interface Props {
|
||||
clusterCode: string;
|
||||
@@ -225,11 +226,11 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
try {
|
||||
const yaml = await dumpManifest(svcManifest);
|
||||
await kubernetesApi.applyYAML(clusterCode, yaml);
|
||||
toast({ title: 'Service 已创建', description: name });
|
||||
toast({ title: i18n.t('kubernetes.deploymentedits.sabd7e004'), description: name });
|
||||
setShowCreate(null);
|
||||
load();
|
||||
} catch (e) {
|
||||
toast({ title: '创建失败', description: e?.message || String(e), variant: 'destructive' });
|
||||
toast({ title: i18n.t('monitor.dashboard.custom.toastCreateFailed'), description: e?.message || String(e), variant: 'destructive' });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -260,30 +261,30 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
try {
|
||||
const yaml = await dumpManifest(manifest);
|
||||
await kubernetesApi.applyYAML(clusterCode, yaml);
|
||||
toast({ title: 'Ingress 已创建', description: name });
|
||||
toast({ title: i18n.t('kubernetes.deploymentedits.se356fbe5'), description: name });
|
||||
setShowCreate(null);
|
||||
load();
|
||||
} catch (e) {
|
||||
toast({ title: '创建失败', description: e?.message || String(e), variant: 'destructive' });
|
||||
toast({ title: i18n.t('monitor.dashboard.custom.toastCreateFailed'), description: e?.message || String(e), variant: 'destructive' });
|
||||
}
|
||||
};
|
||||
|
||||
// 删除资源
|
||||
const deleteResource = async (kind: 'service' | 'ingress', name: string) => {
|
||||
const ok = await confirm({
|
||||
title: '删除资源',
|
||||
title: i18n.t('kubernetes.deploymentedits.s8a2a35a5'),
|
||||
description: `确认删除 ${kind === 'service' ? 'Service' : 'Ingress'} 「${name}」?此操作不可撤销。`,
|
||||
confirmText: '删除',
|
||||
confirmText: i18n.t('kubernetes.storage.delete2'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
if (!ok) return;
|
||||
try {
|
||||
const resource = kind === 'service' ? 'services' : 'ingresses';
|
||||
await kubernetesApi.deleteResourceYaml(clusterCode, namespace, resource, name);
|
||||
toast({ title: '已删除', description: `${kind === 'service' ? 'Service' : 'Ingress'} ${name} 已删除` });
|
||||
toast({ title: i18n.t('monitor.silenceRules.deleted'), description: `${kind === 'service' ? 'Service' : 'Ingress'} ${name} 已删除` });
|
||||
load();
|
||||
} catch (e) {
|
||||
toast({ title: '删除失败', description: e?.message || String(e), variant: 'destructive' });
|
||||
toast({ title: i18n.t('kubernetes.msg.deleteFailed2'), description: e?.message || String(e), variant: 'destructive' });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -292,7 +293,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
<Card className="dg-card">
|
||||
<CardContent className="p-12 text-center">
|
||||
<Loader2 className="h-6 w-6 animate-spin mx-auto dg-text-muted" />
|
||||
<p className="dg-text-muted mt-3 text-sm">加载中...</p>
|
||||
<p className="dg-text-muted mt-3 text-sm"> {i18n.t('monitor.logPanel.logResults.loading')} </p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
@@ -305,7 +306,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
<CardContent className="p-3">
|
||||
<div className="flex items-center gap-2 text-xs dg-text-secondary">
|
||||
<Network className="h-3.5 w-3.5 dg-text-blue" />
|
||||
<span>选择器:</span>
|
||||
<span> {i18n.t('kubernetes.deploymentedits.sb8eef7f0')} </span>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{Object.entries(selectorLabels).map(([k, v]) => (
|
||||
<code key={k} className="bg-[var(--dg-bg-tertiary)] px-1.5 py-0.5 rounded text-[var(--dg-text-secondary)] text-[11px]">{k}={v}</code>
|
||||
@@ -338,7 +339,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
<Plus className="h-3 w-3 mr-1" />创建 Service
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs dg-text-muted mt-1">仅显示 selector 匹配此 Deployment 的关联 Service</p>
|
||||
<p className="text-xs dg-text-muted mt-1"> {i18n.t('kubernetes.deploymentedits.sd0ad85b8')} </p>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0">
|
||||
{matchedSvcs.length === 0 && showCreate !== 'service' ? (
|
||||
@@ -356,14 +357,14 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
{matched ? <CheckCircle className="h-4 w-4 dg-text-blue" /> : <Network className="h-4 w-4 dg-text-muted" />}
|
||||
<span className="text-sm font-semibold text-[var(--dg-text-primary)]">{svc.name}</span>
|
||||
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary text-[10px]">{svc.type}</Badge>
|
||||
{matched && <Badge className="bg-blue-500/20 text-blue-300 border-blue-500/30 text-[10px]">关联</Badge>}
|
||||
{matched && <Badge className="bg-blue-500/20 text-blue-300 border-blue-500/30 text-[10px]"> {i18n.t('kubernetes.deploymentedits.s1c3cf7f5')} </Badge>}
|
||||
<code className="text-[11px] dg-text-muted ml-auto">{svc.clusterIP}</code>
|
||||
<Button size="sm" variant="ghost" className="h-6 text-xs dg-text-green"
|
||||
onClick={() => setVisualEditor({ resource: 'services', name: svc.name })}>
|
||||
<Pencil className="h-3 w-3 mr-1" />编辑
|
||||
</Button>
|
||||
<Button size="sm" variant="ghost" className="h-6 w-6 p-0 dg-text-red hover:dg-text-red"
|
||||
title="删除 Service" onClick={() => deleteResource('service', svc.name)}>
|
||||
title={i18n.t('kubernetes.service.deleteService')} onClick={() => deleteResource('service', svc.name)}>
|
||||
<Trash2 className="h-3 w-3" />
|
||||
</Button>
|
||||
</div>
|
||||
@@ -399,13 +400,13 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
{/* 基本信息 */}
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<Label className="dg-text-muted text-[11px]">名称</Label>
|
||||
<Label className="dg-text-muted text-[11px]"> {i18n.t('kubernetes.secret.secretName')} </Label>
|
||||
<Input value={svcForm.name} onChange={e => setSvcForm(s => ({ ...s, name: e.target.value }))}
|
||||
placeholder={`${deploymentName}-svc`}
|
||||
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="dg-text-muted text-[11px]">类型</Label>
|
||||
<Label className="dg-text-muted text-[11px]"> {i18n.t('system.credentialType')} </Label>
|
||||
<select value={svcForm.type} onChange={e => setSvcForm(s => ({ ...s, type: e.target.value }))}
|
||||
className="h-7 mt-0.5 w-full bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded text-xs text-[var(--dg-text-secondary)] px-2">
|
||||
<option value="ClusterIP">ClusterIP</option>
|
||||
@@ -416,7 +417,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
|
||||
{/* 快速预设 */}
|
||||
<div>
|
||||
<Label className="dg-text-muted text-[11px] mb-1 block">快速添加常用端口</Label>
|
||||
<Label className="dg-text-muted text-[11px] mb-1 block"> {i18n.t('kubernetes.deploymentedits.s83907cde')} </Label>
|
||||
<div className="flex gap-1.5">
|
||||
{PORT_PRESETS.map(p => (
|
||||
<button key={p.name} onClick={() => addPort(p)}
|
||||
@@ -483,13 +484,13 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
<code key={k} className="bg-[var(--dg-bg-tertiary)] px-1 py-0.5 rounded dg-text-secondary ml-1">{k}={v}</code>
|
||||
))
|
||||
) : (
|
||||
<span className="dg-text-muted italic">未检测到</span>
|
||||
<span className="dg-text-muted italic"> {i18n.t('kubernetes.deploymentedits.s5847b0f9')} </span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-2 pt-1">
|
||||
<Button size="sm" variant="ghost" className="h-7 text-xs dg-text-secondary" onClick={() => setShowCreate(null)}>取消</Button>
|
||||
<Button size="sm" className="h-7 bg-blue-600 hover:bg-blue-700 text-xs" onClick={createService}>创建</Button>
|
||||
<Button size="sm" variant="ghost" className="h-7 text-xs dg-text-secondary" onClick={() => setShowCreate(null)}> {i18n.t('rbac.jobRole.cancel')} </Button>
|
||||
<Button size="sm" className="h-7 bg-blue-600 hover:bg-blue-700 text-xs" onClick={createService}> {i18n.t('rbac.jobRole.create')} </Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -531,13 +532,13 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
{matched ? <CheckCircle className="h-4 w-4 dg-text-purple" /> : <GitBranch className="h-4 w-4 dg-text-muted" />}
|
||||
<span className="text-sm font-semibold text-[var(--dg-text-primary)]">{ing.name}</span>
|
||||
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary text-[10px]">{ing.className}</Badge>
|
||||
{matched && <Badge className="bg-purple-500/20 text-purple-300 border-purple-500/30 text-[10px]">关联</Badge>}
|
||||
{matched && <Badge className="bg-purple-500/20 text-purple-300 border-purple-500/30 text-[10px]"> {i18n.t('kubernetes.deploymentedits.s1c3cf7f5')} </Badge>}
|
||||
<Button size="sm" variant="ghost" className="h-6 text-xs dg-text-green ml-auto"
|
||||
onClick={() => setVisualEditor({ resource: 'ingresses', name: ing.name })}>
|
||||
<Pencil className="h-3 w-3 mr-1" />编辑
|
||||
</Button>
|
||||
<Button size="sm" variant="ghost" className="h-6 w-6 p-0 dg-text-red hover:dg-text-red"
|
||||
title="删除 Ingress" onClick={() => deleteResource('ingress', ing.name)}>
|
||||
title={i18n.t('kubernetes.ingress.deleteIngress')} onClick={() => deleteResource('ingress', ing.name)}>
|
||||
<Trash2 className="h-3 w-3" />
|
||||
</Button>
|
||||
</div>
|
||||
@@ -569,7 +570,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<Label className="dg-text-muted text-[11px]">名称</Label>
|
||||
<Label className="dg-text-muted text-[11px]"> {i18n.t('kubernetes.secret.secretName')} </Label>
|
||||
<Input value={ingForm.name} onChange={e => setIngForm(s => ({ ...s, name: e.target.value }))}
|
||||
placeholder={`${deploymentName}-ingress`}
|
||||
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
|
||||
@@ -599,8 +600,8 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-end gap-2 pt-1">
|
||||
<Button size="sm" variant="ghost" className="h-7 text-xs dg-text-secondary" onClick={() => setShowCreate(null)}>取消</Button>
|
||||
<Button size="sm" className="h-7 bg-purple-600 hover:bg-purple-700 text-xs" onClick={createIngress}>创建</Button>
|
||||
<Button size="sm" variant="ghost" className="h-7 text-xs dg-text-secondary" onClick={() => setShowCreate(null)}> {i18n.t('rbac.jobRole.cancel')} </Button>
|
||||
<Button size="sm" className="h-7 bg-purple-600 hover:bg-purple-700 text-xs" onClick={createIngress}> {i18n.t('rbac.jobRole.create')} </Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -619,7 +620,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
)}
|
||||
|
||||
<div className="flex justify-end gap-2 pt-2">
|
||||
<Button size="sm" variant="outline" className="h-7 text-xs border-[var(--dg-border)] dg-text-secondary" onClick={onCancel}>返回查看</Button>
|
||||
<Button size="sm" variant="outline" className="h-7 text-xs border-[var(--dg-border)] dg-text-secondary" onClick={onCancel}> {i18n.t('kubernetes.deploymentedits.s3a77522f')} </Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user