feat(i18n): 剩余模块全量国际化 — 51% 覆盖率 (231 文件接入 t())

批量转换 163 个文件,3204 处中文替换为 t() 调用:
- Monitor: 日志中心/告警中心/数据源/大屏/站点拨测/SNMP/中间件 全部转换
- Kubernetes: ResourceVisualEditor/NamespaceResourcePage/拓扑/事件 全部转换
- Deploy: 流水线/发布/凭证/RBAC 全部转换
- Server/Cloud/Agent/Task/Layout/UI: 全部转换
- 翻译词典扩展至 6474 行 (22 namespaces, 5000+ keys)
- tsc 编译零错误
This commit is contained in:
attacker committed 2026-07-03 01:51:57 +08:00
1 parent 78c27037e3
commit ecec73989b
166 files changed
+6925 -2800

No files matched your search

@@ -28,6 +28,8 @@ import {
emptyMountRow,
} from './deployment-volume-utils';
import type { JsonData } from '@/types/common';
import { useTranslation } from 'react-i18next';
import i18n from '@/i18n';
interface Props {
clusterCode: string;
@@ -39,12 +41,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.deploymenteditstorage.s18c900'), icon: Database, color: 'dg-text-green' },
{ key: 'emptyDir', label: i18n.t('kubernetes.deploymenteditstorage.s5449b2'), 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.deploymenteditstorage.s0986a6'), icon: File, color: 'dg-text-blue' },
{ key: 'secret', label: i18n.t('kubernetes.deploymenteditstorage.sc09936'), icon: Lock, color: 'text-rose-400' },
];
const SELECTABLE_TYPES = new Set(VOLUME_TYPES.map((t) => t.key));
@@ -52,6 +54,7 @@ const SELECTABLE_TYPES = new Set(VOLUME_TYPES.map((t) => t.key));
type CreateResourceKind = 'configmaps' | 'secrets' | 'pvcs';
export function DeploymentEditStorage({ clusterCode, namespace, deploymentName, manifest, onSaved, onCancel }: Props) {
const { t } = useTranslation();
const { toast } = useToast();
const [saving, setSaving] = useState(false);
const [loading, setLoading] = useState(!manifest);
@@ -128,20 +131,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: t('kubernetes.deploymenteditstorage.s5b59d2'), 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' ? t('kubernetes.deploymenteditstorage.s2a6856')
: entry.volume.type === 'secret' ? t('kubernetes.deploymenteditstorage.s1f31e4')
: entry.volume.type === 'persistentVolumeClaim' ? t('kubernetes.deploymenteditstorage.sba9fc6')
: t('kubernetes.deploymenteditstorage.s03480a');
toast({ title: t('kubernetes.deploymenteditstorage.se542a6'), description: t('kubernetes.deploymenteditstorage.s3152b4', { entry.volume.name: entry.volume.name, hint: 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: t('kubernetes.deploymenteditstorage.s24b5b9'), description: t('kubernetes.deploymenteditstorage.s5532a8', { entry.volume.name: entry.volume.name }), variant: 'destructive' });
return;
}
}
@@ -150,10 +153,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: t('kubernetes.deploymenteditstorage.sa8cd7d'), description: t('kubernetes.deploymenteditstorage.s1952a7', { deploymentName: deploymentName }) });
onSaved(base);
} catch (e) {
toast({ title: '保存失败', description: (e as Error)?.message || String(e), variant: 'destructive' });
toast({ title: t('common.saveFailed'), description: (e as Error)?.message || String(e), variant: 'destructive' });
} finally { setSaving(false); }
};
@@ -162,7 +165,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">{t('common.loading')}</p>
</CardContent>
</Card>
);
@@ -171,7 +174,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">{t('kubernetes.deploymenteditstorage.s800b9f')}</CardContent>
</Card>
);
}
@@ -198,7 +201,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">{t('kubernetes.deploymenteditstorage.s1e0b32')}</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 +225,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">{t('kubernetes.deploymenteditstorage.sa3119d')}</span>
<Input
value={vol.name}
onChange={(e) => {
@@ -233,7 +236,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=t('kubernetes.deploymenteditstorage.s478bfa')
className="h-8 w-44 dg-input text-sm font-mono"
/>
{/* 原生 select,避免 Radix Select 在 overflow 容器内无法下拉 // Logan.Li */}
@@ -295,7 +298,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
onChange={(e) => updateMount(i, mi, { containerName: e.target.value })}
className="h-8 min-w-[140px] max-w-[280px] bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded-md text-sm text-[var(--dg-text-primary)] px-2 font-medium truncate"
>
{containers.length === 0 && <option value="">(无容器)</option>}
{containers.length === 0 && <option value="">{t('kubernetes.deploymenteditstorage.s327178')}</option>}
{containers.map((cn) => <option key={cn} value={cn}>{cn}</option>)}
</select>
<div className="flex items-center gap-1 bg-[var(--dg-bg-tertiary)] rounded-lg p-0.5 border border-[var(--dg-border)]">
@@ -311,7 +314,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=t('kubernetes.deploymenteditstorage.seb88e4')
className="h-8 flex-1 min-w-[200px] dg-input text-sm font-mono"
/>
{entry.mounts.length > 1 && (
@@ -321,11 +324,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">{t('kubernetes.deploymenteditstorage.sf4b25a')}</span>
<Input
value={mount.subPath}
onChange={(e) => updateMount(i, mi, { subPath: e.target.value })}
placeholder="如 config.yaml(挂载单文件时填写)"
placeholder=t('kubernetes.deploymenteditstorage.s68ab2e')
className="h-7 flex-1 max-w-md dg-input text-[var(--dg-text-secondary)] text-xs font-mono"
/>
</div>
@@ -339,7 +342,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}>{t('common.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" />}
保存