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

+16 -15
View File
@@ -15,6 +15,7 @@ import { serverApi, remoteExecApi, type RemoteExecResult, type RemoteUploadResul
import { PageShell } from '@/components/layout/PageShell';
import { PageEmpty } from '@/components/layout/PageEmpty';
import type { JsonData } from '@/types/common';
import i18n from '@/i18n';
interface RemoteServer {
id: number; hostname: string; ip: string; username: string; port: number;
@@ -111,9 +112,9 @@ export function RemoteExecPage() {
<Card className="col-span-5 dg-card">
<CardHeader className="pb-3">
<CardTitle className="text-sm flex items-center justify-between text-[var(--dg-text-primary)]">
<span className="flex items-center gap-2"><ServerIcon className="h-4 w-4 dg-text-blue" />选择目标主机</span>
<span className="flex items-center gap-2"><ServerIcon className="h-4 w-4 dg-text-blue" />{i18n.t('automation.remoteSelectHost')}</span>
<Input
placeholder="搜索 主机名/IP"
placeholder=i18n.t('task.remoteexecpage.s253acd')
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && load()}
@@ -124,8 +125,8 @@ export function RemoteExecPage() {
<CardContent className="max-h-[520px] overflow-y-auto space-y-1">
{servers.length === 0 ? (
<PageEmpty
title="暂无服务器"
description="请先在「服务器管理」添加"
title=i18n.t('dashboard.serversStatus.empty')
description=i18n.t('task.remoteexecpage.s0afbf1')
className="py-10"
/>
) : (
@@ -143,8 +144,8 @@ export function RemoteExecPage() {
<div className="text-[10px] text-[var(--dg-text-muted)] font-mono">{s.ip} · {s.username || 'root'}</div>
</div>
{s.has_auth === false
? <Badge className="bg-amber-500/20 dg-text-yellow text-[10px]">无凭据</Badge>
: <Badge className="bg-emerald-500/20 dg-text-green text-[10px]">{s.auth_type === 'key' ? '密钥' : '密码'}</Badge>}
? <Badge className="bg-amber-500/20 dg-text-yellow text-[10px]">{i18n.t('task.remoteexecpage.s152f53')}</Badge>
: <Badge className="bg-emerald-500/20 dg-text-green text-[10px]">{s.auth_type === 'key' ? i18n.t('k8s.resource.secrets') : i18n.t('login.password')}</Badge>}
</label>
))}
</>
@@ -175,17 +176,17 @@ export function RemoteExecPage() {
{tab === 'exec' ? (
<Card className="dg-card">
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">批量执行命令</CardTitle></CardHeader>
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">{i18n.t('task.remoteexecpage.seb6e67')}</CardTitle></CardHeader>
<CardContent className="space-y-3">
<textarea
value={command}
onChange={(e) => setCommand(e.target.value)}
rows={5}
placeholder="输入要在选中主机上执行的 shell 命令,例如:df -h | head -5"
placeholder=i18n.t('task.remoteexecpage.s766288')
className="w-full bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded-md px-3 py-2 text-xs font-mono text-[var(--dg-text-primary)] resize-none"
/>
<div className="flex items-center gap-3">
<span className="text-xs dg-text-secondary">超时(秒)</span>
<span className="text-xs dg-text-secondary">{i18n.t('monitor.probeTimeout')}</span>
<Input type="number" min={1} value={timeoutSec} onChange={(e) => setTimeoutSec(Number(e.target.value) || 60)}
className="h-8 w-24 text-xs dg-input" />
<Button onClick={doExec} disabled={running} className="ml-auto dg-btn-primary h-8 text-xs">
@@ -197,17 +198,17 @@ export function RemoteExecPage() {
</Card>
) : (
<Card className="dg-card">
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">批量上传文件</CardTitle></CardHeader>
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">{i18n.t('task.remoteexecpage.s30048c')}</CardTitle></CardHeader>
<CardContent className="space-y-3">
<div className="space-y-1.5">
<span className="text-xs dg-text-secondary">选择本地文件</span>
<span className="text-xs dg-text-secondary">{i18n.t('task.remoteexecpage.sb7e21a')}</span>
<Input type="file" onChange={(e) => setFile(e.target.files?.[0] || null)}
className="h-8 text-xs dg-input" />
{file && <span className="text-[10px] text-[var(--dg-text-muted)]">{file.name} ({(file.size / 1024).toFixed(1)} KB)</span>}
</div>
<div className="space-y-1.5">
<span className="text-xs dg-text-secondary">远程目标路径(目录则自动追加文件名)</span>
<Input value={remotePath} onChange={(e) => setRemotePath(e.target.value)} placeholder="/tmp/ 或 /opt/app/config.yaml"
<span className="text-xs dg-text-secondary">{i18n.t('task.remoteexecpage.sb47f03')}</span>
<Input value={remotePath} onChange={(e) => setRemotePath(e.target.value)} placeholder=i18n.t('task.remoteexecpage.sd4b44a')
className="h-8 text-xs font-mono dg-input" />
</div>
<Button onClick={doUpload} disabled={running} className="dg-btn-primary h-8 text-xs">
@@ -220,7 +221,7 @@ export function RemoteExecPage() {
{(execResults.length > 0 || uploadResults.length > 0) && (
<Card className="dg-card">
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">执行结果</CardTitle></CardHeader>
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">{i18n.t('automation.execResult')}</CardTitle></CardHeader>
<CardContent className="space-y-2 max-h-[300px] overflow-y-auto">
{execResults.map((r, i) => (
<div key={i} className="p-2 rounded border border-[var(--dg-border)] bg-[var(--dg-bg-tertiary)]">
@@ -232,7 +233,7 @@ export function RemoteExecPage() {
</Badge>
</div>
<pre className="text-[10px] font-mono dg-text-secondary whitespace-pre-wrap break-all max-h-32 overflow-y-auto">
{r.error || r.output || '(无输出)'}
{r.error || r.output || i18n.t('task.remoteexecpage.s1a6383')}
</pre>
</div>
))}