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 {
|
||||
emptyMountRow,
|
||||
} from './deployment-volume-utils';
|
||||
import type { JsonData } from '@/types/common';
|
||||
import i18n from '@/i18n';
|
||||
|
||||
interface Props {
|
||||
clusterCode: string;
|
||||
@@ -39,12 +40,12 @@ interface Props {
|
||||
}
|
||||
|
||||
const VOLUME_TYPES: { key: VolumeForm['type']; label: string; icon: typeof HardDrive; color: string }[] = [
|
||||
{ key: 'persistentVolumeClaim', label: '存储卷声明', icon: Database, color: 'dg-text-green' },
|
||||
{ key: 'emptyDir', label: '临时目录(EmptyDir)', icon: Disc, color: 'dg-text-secondary' },
|
||||
{ key: 'persistentVolumeClaim', label: i18n.t('kubernetes.namespaceresour.s18c90062'), icon: Database, color: 'dg-text-green' },
|
||||
{ key: 'emptyDir', label: i18n.t('kubernetes.deploymentedits.s5449b239'), icon: Disc, color: 'dg-text-secondary' },
|
||||
{ key: 'hostPath', label: 'HostPath', icon: HardDrive, color: 'dg-text-yellow' },
|
||||
{ key: 'nfs', label: 'NFS', icon: Server, color: 'dg-text-purple' },
|
||||
{ key: 'configMap', label: '配置字典', icon: File, color: 'dg-text-blue' },
|
||||
{ key: 'secret', label: '密文', icon: Lock, color: 'text-rose-400' },
|
||||
{ key: 'configMap', label: i18n.t('kubernetes.namespaceovervi.s0986a6e7'), icon: File, color: 'dg-text-blue' },
|
||||
{ key: 'secret', label: i18n.t('kubernetes.deploymentedits.sc099362a'), icon: Lock, color: 'text-rose-400' },
|
||||
];
|
||||
|
||||
const SELECTABLE_TYPES = new Set(VOLUME_TYPES.map((t) => t.key));
|
||||
@@ -128,20 +129,20 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
const save = async () => {
|
||||
for (const entry of entries) {
|
||||
if (!entry.volume.name.trim()) {
|
||||
toast({ title: '请填写数据卷名称', variant: 'destructive' });
|
||||
toast({ title: i18n.t('kubernetes.deploymentedits.s5b59d298'), variant: 'destructive' });
|
||||
return;
|
||||
}
|
||||
if (!formToVolume(entry.volume)) {
|
||||
const hint = entry.volume.type === 'configMap' ? '请选择 ConfigMap'
|
||||
: entry.volume.type === 'secret' ? '请选择 Secret'
|
||||
: entry.volume.type === 'persistentVolumeClaim' ? '请选择 PVC'
|
||||
: '的类型必填项';
|
||||
toast({ title: '数据卷配置不完整', description: `请为「${entry.volume.name}」${hint}`, variant: 'destructive' });
|
||||
const hint = entry.volume.type === 'configMap' ? i18n.t('kubernetes.deploymentedits.s2a6856ee')
|
||||
: entry.volume.type === 'secret' ? i18n.t('kubernetes.deploymentedits.s1f31e442')
|
||||
: entry.volume.type === 'persistentVolumeClaim' ? i18n.t('kubernetes.deploymentedits.sba9fc667')
|
||||
: i18n.t('kubernetes.deploymentedits.s03480abb');
|
||||
toast({ title: i18n.t('kubernetes.deploymentedits.se542a63b'), description: `请为「${entry.volume.name}」${hint}`, variant: 'destructive' });
|
||||
return;
|
||||
}
|
||||
const validMounts = entry.mounts.filter((m) => m.mountPath.trim());
|
||||
if (validMounts.length === 0) {
|
||||
toast({ title: '请填写挂载路径', description: `数据卷「${entry.volume.name}」需至少挂载到一个容器`, variant: 'destructive' });
|
||||
toast({ title: i18n.t('kubernetes.deploymentedits.s24b5b9e3'), description: `数据卷「${entry.volume.name}」需至少挂载到一个容器`, variant: 'destructive' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -150,10 +151,10 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
const { volumes, mounts } = volumeEntriesToStorage(entries);
|
||||
const base = applyStorageToManifest(rawManifest, volumes, mounts, passthroughVolumes);
|
||||
await saveDeploymentManifest(clusterCode, namespace, deploymentName, base);
|
||||
toast({ title: '存储配置已保存', description: `${deploymentName} 更新已提交` });
|
||||
toast({ title: i18n.t('kubernetes.deploymentedits.sa8cd7d90'), description: `${deploymentName} 更新已提交` });
|
||||
onSaved(base);
|
||||
} catch (e) {
|
||||
toast({ title: '保存失败', description: (e as Error)?.message || String(e), variant: 'destructive' });
|
||||
toast({ title: i18n.t('kubernetes.msg.saveFailed'), description: (e as Error)?.message || String(e), variant: 'destructive' });
|
||||
} finally { setSaving(false); }
|
||||
};
|
||||
|
||||
@@ -162,7 +163,7 @@ export function DeploymentEditStorage({ 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>
|
||||
);
|
||||
@@ -171,7 +172,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
if (!manifest) {
|
||||
return (
|
||||
<Card className="dg-card">
|
||||
<CardContent className="p-8 text-center dg-text-muted">未获取到 manifest 数据,请使用 YAML 编辑模式。</CardContent>
|
||||
<CardContent className="p-8 text-center dg-text-muted"> {i18n.t('kubernetes.deploymentedits.s800b9f0b')} </CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -198,7 +199,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
数据卷
|
||||
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary">{entries.length}</Badge>
|
||||
</CardTitle>
|
||||
<p className="text-[11px] dg-text-muted mt-1">定义数据卷,并将其挂载到工作负载的容器中</p>
|
||||
<p className="text-[11px] dg-text-muted mt-1"> {i18n.t('kubernetes.deploymentedits.s1e0b322c')} </p>
|
||||
</div>
|
||||
<Button size="sm" variant="outline" className="h-7 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs shrink-0" onClick={addEntry}>
|
||||
<Plus className="h-3 w-3 mr-1" />添加数据卷
|
||||
@@ -222,7 +223,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
<div className="p-3 space-y-2.5 border-b border-[var(--dg-border)]/80">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<VIcon className={`h-4 w-4 ${vtype?.color || 'dg-text-secondary'}`} />
|
||||
<span className="text-xs dg-text-secondary shrink-0">数据卷名称</span>
|
||||
<span className="text-xs dg-text-secondary shrink-0"> {i18n.t('kubernetes.deploymentedits.sa3119d33')} </span>
|
||||
<Input
|
||||
value={vol.name}
|
||||
onChange={(e) => {
|
||||
@@ -233,7 +234,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
if (vol.type === 'persistentVolumeClaim' && !vol.pvcName) patch.pvcName = name;
|
||||
updateVolume(i, patch);
|
||||
}}
|
||||
placeholder="如 app-logs / fluent-bit-config"
|
||||
placeholder={i18n.t('kubernetes.deploymentedits.s478bfaef')}
|
||||
className="h-8 w-44 dg-input text-sm font-mono"
|
||||
/>
|
||||
{/* 原生 select,避免 Radix Select 在 overflow 容器内无法下拉 // Logan.Li */}
|
||||
@@ -311,7 +312,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
<Input
|
||||
value={mount.mountPath}
|
||||
onChange={(e) => updateMount(i, mi, { mountPath: e.target.value })}
|
||||
placeholder="挂载路径 /bitcloud/app/.../logs"
|
||||
placeholder={i18n.t('kubernetes.deploymentedits.seb88e484')}
|
||||
className="h-8 flex-1 min-w-[200px] dg-input text-sm font-mono"
|
||||
/>
|
||||
{entry.mounts.length > 1 && (
|
||||
@@ -321,11 +322,11 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[11px] dg-text-muted shrink-0">子路径 subPath</span>
|
||||
<span className="text-[11px] dg-text-muted shrink-0"> {i18n.t('kubernetes.deploymentedits.sf4b25a22')} </span>
|
||||
<Input
|
||||
value={mount.subPath}
|
||||
onChange={(e) => updateMount(i, mi, { subPath: e.target.value })}
|
||||
placeholder="如 config.yaml(挂载单文件时填写)"
|
||||
placeholder={i18n.t('kubernetes.deploymentedits.s68ab2e24')}
|
||||
className="h-7 flex-1 max-w-md dg-input text-[var(--dg-text-secondary)] text-xs font-mono"
|
||||
/>
|
||||
</div>
|
||||
@@ -339,7 +340,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
</Card>
|
||||
|
||||
<div className="flex justify-end gap-2 pt-2">
|
||||
<Button variant="outline" className="border-[var(--dg-border)] dg-text-secondary" onClick={onCancel}>取消</Button>
|
||||
<Button variant="outline" className="border-[var(--dg-border)] dg-text-secondary" onClick={onCancel}> {i18n.t('rbac.jobRole.cancel')} </Button>
|
||||
<Button className="bg-blue-600 hover:bg-blue-700" disabled={saving} onClick={save}>
|
||||
{saving ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : <Save className="h-4 w-4 mr-1" />}
|
||||
保存
|
||||
|
||||
Reference in new issue
Block a user