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

@@ -14,6 +14,7 @@ import { Loader2, Plug, RefreshCw } from 'lucide-react';
import { useToast } from '@/hooks/use-toast';
import { logCenterApi, type LogDataSource, type TestConnectionResult } from '@/api';
import type { LogEngine } from './log-center-types';
import { useTranslation } from 'react-i18next';
export function LogDatasourceDialog({
open, onOpenChange, engine, editing, onSaved,
@@ -24,6 +25,7 @@ export function LogDatasourceDialog({
editing?: LogDataSource | null;
onSaved: () => void;
}) {
const { t } = useTranslation();
const { toast } = useToast();
const [name, setName] = useState('');
const [url, setUrl] = useState('');
@@ -127,12 +129,12 @@ export function LogDatasourceDialog({
: payload();
const result: TestConnectionResult = await logCenterApi.testDatasource(data);
if (result.status === 'ok') {
toast({ title: '连接成功' });
toast({ title: t('aiops.llmTestSuccess') });
} else {
toast({ title: '连接失败', description: result.error || '未知错误', variant: 'destructive' });
toast({ title: t('aiops.llmTestFailed'), description: result.error || t('monitor.dashboard.agent.toast.unknownError'), variant: 'destructive' });
}
} catch (e: any) {
toast({ title: '连接失败', description: e?.message || String(e), variant: 'destructive' });
toast({ title: t('aiops.llmTestFailed'), description: e?.message || String(e), variant: 'destructive' });
} finally {
setTesting(false);
}
@@ -147,11 +149,11 @@ export function LogDatasourceDialog({
} else {
await logCenterApi.createDatasource(payload());
}
toast({ title: '已保存' });
toast({ title: t('deploy.toast.saved') });
onOpenChange(false);
onSaved();
} catch (e: any) {
toast({ title: '保存失败', description: e?.message || String(e), variant: 'destructive' });
toast({ title: t('common.saveFailed'), description: e?.message || String(e), variant: 'destructive' });
} finally {
setSaving(false);
}
@@ -162,7 +164,7 @@ export function LogDatasourceDialog({
<DialogContent className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)] max-w-md max-h-[85vh] overflow-y-auto">
<DialogHeader>
<DialogTitle className="text-[var(--dg-text-primary)]">
{editing ? '编辑' : '添加'}{engine === 'loki' ? ' Loki' : ' Elasticsearch'} 数据源
{editing ? t('common.edit') : t('common.add')}{engine === 'loki' ? ' Loki' : ' Elasticsearch'} 数据源
</DialogTitle>
<DialogDescription className="text-[var(--dg-text-muted)]">
仅保存连接信息,日志本体存储在您的 Loki / ES 集群
@@ -170,17 +172,17 @@ export function LogDatasourceDialog({
</DialogHeader>
<div className="space-y-3 py-1">
<div>
<Label className="text-xs text-[var(--dg-text-muted)]">名称</Label>
<Label className="text-xs text-[var(--dg-text-muted)]">{t('common.name')}</Label>
<Input value={name} onChange={e => setName(e.target.value)} className="mt-1 h-9 bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
</div>
<div>
<Label className="text-xs text-[var(--dg-text-muted)]">地址</Label>
<Label className="text-xs text-[var(--dg-text-muted)]">{t('common.address')}</Label>
<Input value={url} onChange={e => setUrl(e.target.value)} placeholder="http://host:port" className="mt-1 h-9 font-mono text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
</div>
{engine === 'elasticsearch' && (
<div>
<div className="flex items-center justify-between">
<Label className="text-xs text-[var(--dg-text-muted)]">默认索引</Label>
<Label className="text-xs text-[var(--dg-text-muted)]">{t('monitor.logdatasourcedialog.s6621b5')}</Label>
<Button
variant="ghost"
size="sm"
@@ -210,7 +212,7 @@ export function LogDatasourceDialog({
获取索引
</Button>
</div>
<Input value={defaultIndex} onChange={e => setDefaultIndex(e.target.value)} placeholder="索引名或通配符,如 .monitoring-es-7-*" className="mt-1 h-9 font-mono text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
<Input value={defaultIndex} onChange={e => setDefaultIndex(e.target.value)} placeholder=t('monitor.logdatasourcedialog.s606402') className="mt-1 h-9 font-mono text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
{/* 已获取索引快捷选择(支持通配) // Logan.Li */}
{indices.length > 0 && (
<div className="mt-2 flex flex-wrap gap-1 max-h-24 overflow-auto">
@@ -245,23 +247,23 @@ export function LogDatasourceDialog({
</div>
)}
<div>
<Label className="text-xs text-[var(--dg-text-muted)]">认证方式</Label>
<Label className="text-xs text-[var(--dg-text-muted)]">{t('deploy.cred.authMethod')}</Label>
<Select value={authType} onValueChange={(v) => setAuthType(v as LogDataSource['auth_type'])}>
<SelectTrigger className="mt-1 h-9 w-full bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
<SelectItem value="none" className="text-xs">无认证</SelectItem>
<SelectItem value="none" className="text-xs">{t('monitor.logdatasourcedialog.s7870c3')}</SelectItem>
<SelectItem value="basic" className="text-xs">Basic Auth</SelectItem>
<SelectItem value="bearer" className="text-xs">Bearer Token</SelectItem>
<SelectItem value="custom" className="text-xs">自定义 Headers</SelectItem>
<SelectItem value="custom" className="text-xs">{t('monitor.logdatasourcedialog.s2e7220')}</SelectItem>
</SelectContent>
</Select>
</div>
{authType === 'basic' && (
<div className="grid grid-cols-2 gap-2">
<Input value={user} onChange={e => setUser(e.target.value)} placeholder="用户名" className="h-9 text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
<Input type="password" value={pass} onChange={e => setPass(e.target.value)} placeholder="密码" className="h-9 text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
<Input value={user} onChange={e => setUser(e.target.value)} placeholder=t('login.username') className="h-9 text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
<Input type="password" value={pass} onChange={e => setPass(e.target.value)} placeholder=t('login.password') className="h-9 text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
</div>
)}
{authType === 'bearer' && (
@@ -277,23 +279,23 @@ export function LogDatasourceDialog({
const next = [...headers];
next[i].name = e.target.value;
setHeaders(next);
}} placeholder="Header 名,如 X-Scope-OrgID" className="h-9 text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
}} placeholder=t('monitor.logdatasourcedialog.sc7f8eb') className="h-9 text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
<Input value={h.value} onChange={e => {
const next = [...headers];
next[i].value = e.target.value;
setHeaders(next);
}} placeholder="Header 值" className="h-9 text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
}} placeholder=t('monitor.logdatasourcedialog.scf7126') className="h-9 text-xs bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]" />
</div>
))}
<Button variant="outline" size="sm" className="h-7 text-xs border-[var(--dg-border)]" onClick={() => setHeaders([...headers, { name: '', value: '' }])}>添加 Header</Button>
<Button variant="outline" size="sm" className="h-7 text-xs border-[var(--dg-border)]" onClick={() => setHeaders([...headers, { name: '', value: '' }])}>{t('monitor.logdatasourcedialog.s86a7a6')}</Button>
</div>
)}
<div className="flex items-center justify-between">
<Label className="text-xs text-[var(--dg-text-muted)]">跳过 TLS 校验</Label>
<Label className="text-xs text-[var(--dg-text-muted)]">{t('monitor.logdatasourcedialog.sa441a8')}</Label>
<Switch checked={skipTLS} onCheckedChange={setSkipTLS} />
</div>
<div className="flex items-center justify-between">
<Label className="text-xs text-[var(--dg-text-muted)]">设为默认</Label>
<Label className="text-xs text-[var(--dg-text-muted)]">{t('aiops.llmSetDefault')}</Label>
<Switch checked={isDefault} onCheckedChange={setIsDefault} />
</div>
</div>