fix(i18n): 回退到稳定的 32% 覆盖率状态 (tsc + Vite 构建通过)

批量转换脚本引入的语法错误已回退,保留稳定的 i18n 转换:
- 翻译词典: 22 namespaces, 3600+ keys
- 已接入: 145+ 文件 (Dashboard/Login/K8s 主页面/Monitor/System/Deploy)
- 语言切换器在 Header 中可用 (🇨🇳/🇺🇸)
- tsc 零错误, Vite 构建成功
This commit is contained in:
attacker committed 2026-07-03 02:02:29 +08:00
1 parent ecec73989b
commit 72bfb0e12d
191 files changed
+5057 -7592

No files matched your search

+15 -16
View File
@@ -15,7 +15,6 @@ 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;
@@ -112,9 +111,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" />{i18n.t('automation.remoteSelectHost')}</span>
<span className="flex items-center gap-2"><ServerIcon className="h-4 w-4 dg-text-blue" />选择目标主机</span>
<Input
placeholder=i18n.t('task.remoteexecpage.s253acd')
placeholder="搜索 主机名/IP"
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && load()}
@@ -125,8 +124,8 @@ export function RemoteExecPage() {
<CardContent className="max-h-[520px] overflow-y-auto space-y-1">
{servers.length === 0 ? (
<PageEmpty
title=i18n.t('dashboard.serversStatus.empty')
description=i18n.t('task.remoteexecpage.s0afbf1')
title="暂无服务器"
description="请先在「服务器管理」添加"
className="py-10"
/>
) : (
@@ -144,8 +143,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]">{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>}
? <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>}
</label>
))}
</>
@@ -176,17 +175,17 @@ export function RemoteExecPage() {
{tab === 'exec' ? (
<Card className="dg-card">
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">{i18n.t('task.remoteexecpage.seb6e67')}</CardTitle></CardHeader>
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">批量执行命令</CardTitle></CardHeader>
<CardContent className="space-y-3">
<textarea
value={command}
onChange={(e) => setCommand(e.target.value)}
rows={5}
placeholder=i18n.t('task.remoteexecpage.s766288')
placeholder="输入要在选中主机上执行的 shell 命令,例如:df -h | head -5"
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">{i18n.t('monitor.probeTimeout')}</span>
<span className="text-xs dg-text-secondary">超时(秒)</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">
@@ -198,17 +197,17 @@ export function RemoteExecPage() {
</Card>
) : (
<Card className="dg-card">
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">{i18n.t('task.remoteexecpage.s30048c')}</CardTitle></CardHeader>
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">批量上传文件</CardTitle></CardHeader>
<CardContent className="space-y-3">
<div className="space-y-1.5">
<span className="text-xs dg-text-secondary">{i18n.t('task.remoteexecpage.sb7e21a')}</span>
<span className="text-xs dg-text-secondary">选择本地文件</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">{i18n.t('task.remoteexecpage.sb47f03')}</span>
<Input value={remotePath} onChange={(e) => setRemotePath(e.target.value)} placeholder=i18n.t('task.remoteexecpage.sd4b44a')
<span className="text-xs dg-text-secondary">远程目标路径(目录则自动追加文件名)</span>
<Input value={remotePath} onChange={(e) => setRemotePath(e.target.value)} placeholder="/tmp/ 或 /opt/app/config.yaml"
className="h-8 text-xs font-mono dg-input" />
</div>
<Button onClick={doUpload} disabled={running} className="dg-btn-primary h-8 text-xs">
@@ -221,7 +220,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)]">{i18n.t('automation.execResult')}</CardTitle></CardHeader>
<CardHeader className="pb-3"><CardTitle className="text-sm text-[var(--dg-text-primary)]">执行结果</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)]">
@@ -233,7 +232,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 || i18n.t('task.remoteexecpage.s1a6383')}
{r.error || r.output || '(无输出)'}
</pre>
</div>
))}