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

@@ -10,6 +10,7 @@ import { Plus, Key, Globe, Container } from 'lucide-react';
import { toast } from 'sonner';
import { credentialApi, deployApi } from '@/api';
import type { JsonData } from '@/types/common';
import { useTranslation } from 'react-i18next';
interface Repo {
id: number; name: string; url: string; credential_id: number | null;
@@ -32,6 +33,7 @@ interface Props {
}
export default function CredentialFormDialog({ open, onOpenChange, type, editId, repos, registries, onSave }: Props) {
const { t } = useTranslation();
const isRepo = type === 'repo';
const [name, setName] = useState('');
const [desc, setDesc] = useState('');
@@ -69,7 +71,7 @@ export default function CredentialFormDialog({ open, onOpenChange, type, editId,
}, [editId, open, isRepo]);
const handleSave = async () => {
if (!name.trim() || !url.trim()) { toast.error('请填写名称和地址'); return; }
if (!name.trim() || !url.trim()) { toast.error(t('deploy.form.nameAddrRequired')); return; }
setSaving(true);
try {
const cid = credentialId ? Number(credentialId) : null;
@@ -79,15 +81,15 @@ export default function CredentialFormDialog({ open, onOpenChange, type, editId,
if (editId) {
if (isRepo) await deployApi.updateRepo(editId, payload);
else await deployApi.updateRegistry(editId, payload);
toast.success('已更新');
toast.success(t('deploy.toast.updated'));
} else {
if (isRepo) await deployApi.createRepo(payload);
else await deployApi.createRegistry(payload);
toast.success('已创建');
toast.success(t('deploy.toast.created'));
}
onOpenChange(false);
onSave();
} catch { toast.error('保存失败'); }
} catch { toast.error(t('common.saveFailed')); }
finally { setSaving(false); }
};
@@ -99,26 +101,26 @@ export default function CredentialFormDialog({ open, onOpenChange, type, editId,
<DialogHeader>
<DialogTitle className="text-[var(--dg-text-primary)] flex items-center gap-2">
<CredIcon className="h-5 w-5 text-[var(--dg-blue)]" />
{editId ? '编辑' : '新增'}{isRepo ? ' Git 仓库' : ' 镜像仓库'}
{editId ? t('common.edit') : t('deploy.credentialformdialog.s66ab5e')}{isRepo ? t('deploy.credentialformdialog.s0b7cb4') : t('deploy.credentialformdialog.s7f34a8')}
</DialogTitle>
</DialogHeader>
<div className="space-y-4 py-2">
<div className="space-y-1"><Label>名称 *</Label>
<Input value={name} onChange={e => setName(e.target.value)} placeholder={isRepo ? '如:GitLab CE' : '如:Harbor'} className="bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]" /></div>
<div className="space-y-1"><Label>{isRepo ? '仓库 URL *' : 'Registry URL *'}</Label>
<div className="space-y-1"><Label>{t('deploy.form.nameStar')}</Label>
<Input value={name} onChange={e => setName(e.target.value)} placeholder={isRepo ? t('deploy.credentialformdialog.se9548a') : t('deploy.credentialformdialog.sa4d9ef')} className="bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]" /></div>
<div className="space-y-1"><Label>{isRepo ? t('deploy.form.repoUrlStar') : 'Registry URL *'}</Label>
<Input value={url} onChange={e => setUrl(e.target.value)} placeholder={isRepo ? 'http://10.10.10.72:9000/group/repo.git' : 'http://10.10.10.72'} className="font-mono text-sm bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]" /></div>
{!isRepo && <div className="space-y-1"><Label>默认命名空间</Label>
<Input value={namespace} onChange={e => setNamespace(e.target.value)} placeholder="如:aiops" className="bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]" /></div>}
{!isRepo && <div className="space-y-1"><Label>{t('deploy.form.defaultNamespace')}</Label>
<Input value={namespace} onChange={e => setNamespace(e.target.value)} placeholder=t('deploy.credentialformdialog.s2a8bb1') className="bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]" /></div>}
{/* 关联凭证 */}
<div className="space-y-1">
<Label>关联凭证 <span className="text-xs text-[var(--dg-text-secondary)] opacity-70">(认证由凭据管理统一配置)</span></Label>
<Label>{t('deploy.cred.linkedCred')} <span className="text-xs text-[var(--dg-text-secondary)] opacity-70">{t('deploy.credentialformdialog.s30220a')}</span></Label>
<Select value={String(credentialId)} onValueChange={v => setCredentialId(v === '__none' ? '' : v)}>
<SelectTrigger className="bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]">
<SelectValue placeholder={isRepo ? '选择凭据(API/密码等)' : '选择 Docker 密码凭据'} />
<SelectValue placeholder={isRepo ? t('deploy.cred.selectApiCred') : t('deploy.cred.selectDockerPwd')} />
</SelectTrigger>
<SelectContent>
<SelectItem value="__none">不关联凭证</SelectItem>
<SelectItem value="__none">{t('deploy.cred.notLinkedCred')}</SelectItem>
{filteredCredentials.map(c => (
<SelectItem key={c.id} value={String(c.id)}>
<span className="flex items-center gap-1.5">
@@ -132,14 +134,14 @@ export default function CredentialFormDialog({ open, onOpenChange, type, editId,
{filteredCredentials.length === 0 && (
<p className="text-xs dg-text-yellow flex items-center gap-1 mt-1">
<Plus className="h-3 w-3" />
暂无{isRepo ? '' : 'Docker 密码'}类型凭证,请在凭证配置页面新增
暂无{isRepo ? '' : t('pipeline.dockerPassword')}类型凭证,请在凭证配置页面新增
</p>
)}
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => onOpenChange(false)}>取消</Button>
<Button onClick={handleSave} disabled={saving}>{saving ? '保存中...' : '保存'}</Button>
<Button variant="outline" onClick={() => onOpenChange(false)}>{t('common.cancel')}</Button>
<Button onClick={handleSave} disabled={saving}>{saving ? i18n.t('k8s.topology.saving') : i18n.t('common.save')}</Button>
</DialogFooter>
</DialogContent>
</Dialog>