feat(i18n): 全量中英文国际化改造

- 翻译 en-US.json 中 1006 条未翻译的中文条目为英文
- 提取 30+ 组件文件的硬编码中文到 locale JSON
- 新增 900+ 翻译键覆盖所有业务模块:
  - Layout (Sidebar, Header, Breadcrumb)
  - Server (ServerForm, CloudServerImport, WebShell, RdpTools)
  - Deploy (ReleaseManager, PipelineCreate, AppRelease)
  - Kubernetes (DeploymentEdit, PodExec, PodLogs, ResourceEditor)
  - Monitor (UnifiedQueryPanel, AlertCenter, Prometheus/Grafana Dashboard)
  - AIOps (predictUtils, PredictiveCostTab, AIPredictive)
  - System (useLdapManagement, AgentMonitor, AgentWizard)
- tsc --noEmit 类型检查通过
This commit is contained in:
attacker committed 2026-07-04 03:42:27 +08:00
1 parent 76ec9387f0
commit a9513c2056
44 files changed
+4342 -1792

No files matched your search

+20 -18
View File
@@ -1,4 +1,5 @@
import { useState, useRef, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { cn } from '@/lib/utils';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
@@ -53,6 +54,7 @@ interface TermEntry {
}
export function WebShell() {
const { t } = useTranslation();
const [servers, setServers] = useState<JsonData[]>([]);
const [sessions, setSessions] = useState<TerminalSession[]>([]);
const [activeSession, setActiveSession] = useState<string | null>(null);
@@ -70,7 +72,7 @@ export function WebShell() {
const res: JsonData = await serverApi.getServers();
setServers(res?.list || []);
} catch (e) {
console.error('加载服务器列表失败:', e);
console.error('loadServers error:', e);
setServers([]);
}
};
@@ -150,11 +152,11 @@ export function WebShell() {
};
ws.onopen = () => {
term.write(`\x1b[32m正在连接 ${server.hostname} (${server.ip})...\x1b[0m\r\n`);
term.write(`\x1b[32m${t('server.connecting', { name: server.hostname, ip: server.ip })}\x1b[0m\r\n`);
};
ws.onclose = () => {
term.write('\r\n\x1b[31m[连接已关闭]\x1b[0m\r\n');
term.write(`\r\n\x1b[31m[${t('server.connectionClosed')}]\r\n`);
setSessions((prev) =>
prev.map((s) => (s.id === sessionId ? { ...s, connected: false, ready: true } : s))
);
@@ -162,7 +164,7 @@ export function WebShell() {
ws.onerror = () => {
setSessions((prev) => prev.map((s) => (s.id === sessionId ? { ...s, ready: true } : s)));
term.write('\r\n\x1b[31m[连接发生错误]\x1b[0m\r\n');
term.write(`\r\n\x1b[31m[${t('server.connectionError')}]\r\n`);
};
termsRef.current.set(sessionId, { term, ws, fit, opened: false });
@@ -256,7 +258,7 @@ export function WebShell() {
entry.opened = true;
entry.resizeCleanup = attachTerminalResize(el, entry.fit, entry.term, entry.ws);
} catch (e) {
console.error('打开终端失败:', e);
console.error('openTerminal error:', e);
}
}
} else {
@@ -276,33 +278,33 @@ export function WebShell() {
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold text-[var(--dg-text-primary)]">WebShell</h1>
<p className="text-sm text-[var(--dg-text-secondary)] mt-1">远程服务器终端管理</p>
<p className="text-sm text-[var(--dg-text-secondary)] mt-1">{t('server.remoteTerminal')}</p>
</div>
<div className="flex items-center gap-2">
<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
<DialogTrigger asChild>
<Button className="bg-[var(--dg-blue)] hover:opacity-90 text-white">
<Plus className="h-4 w-4 mr-2" />
新建连接
{t('server.newConnection')}
</Button>
</DialogTrigger>
<DialogContent className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
<DialogHeader>
<DialogTitle className="text-[var(--dg-text-primary)]">新建终端连接</DialogTitle>
<DialogTitle className="text-[var(--dg-text-primary)]">{t('server.newTerminal')}</DialogTitle>
<DialogDescription className="text-[var(--dg-text-secondary)]">
选择要连接的服务器
{t('server.selectServer')}
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="space-y-2">
<label className="text-sm font-medium text-[var(--dg-text-secondary)]">选择服务器</label>
<label className="text-sm font-medium text-[var(--dg-text-secondary)]">{t('server.selectServer')}</label>
<Select value={selectedServer} onValueChange={setSelectedServer}>
<SelectTrigger className="bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]">
<SelectValue placeholder="选择服务器" />
<SelectValue placeholder={t('server.selectServer')} />
</SelectTrigger>
<SelectContent className="bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]">
{runningServers.length === 0 ? (
<SelectItem value="__none" disabled>暂无运行中的服务器</SelectItem>
<SelectItem value="__none" disabled>{t('server.noRunningServers')}</SelectItem>
) : (
runningServers.map((server) => (
<SelectItem key={server.id} value={server.id}>
@@ -325,7 +327,7 @@ export function WebShell() {
className="bg-[var(--dg-blue)] hover:opacity-90 text-white"
>
<Terminal className="h-4 w-4 mr-2" />
连接
{t('server.webshellConnect')}
</Button>
</DialogFooter>
</DialogContent>
@@ -372,7 +374,7 @@ export function WebShell() {
))}
</div>
) : (
<span className="text-sm text-[var(--dg-text-secondary)]">暂无连接</span>
<span className="text-sm text-[var(--dg-text-secondary)]">{t('server.noConnections')}</span>
)}
</div>
<div className="flex items-center gap-1">
@@ -410,7 +412,7 @@ export function WebShell() {
<TerminalLoadingOverlay
key={`${session.id}-loading`}
show={activeSession === session.id && !session.ready}
label="正在登录..."
label={t('server.webshellLoggingIn')}
/>
))}
</div>
@@ -420,8 +422,8 @@ export function WebShell() {
style={{ height: terminalHeight }}
>
<Terminal className="h-16 w-16 mb-4 opacity-50" />
<p className="text-lg font-medium">暂无活动连接</p>
<p className="text-sm mt-1">点击“新建连接”开始远程会话</p>
<p className="text-lg font-medium">{t('server.noActiveConnections')}</p>
<p className="text-sm mt-1">{t('server.newConnectionHint')}</p>
</div>
)}
</CardContent>
@@ -431,7 +433,7 @@ export function WebShell() {
{activeSessionData && (
<Card className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
<CardHeader className="pb-2">
<CardTitle className="text-sm text-[var(--dg-text-secondary)]">快捷命令</CardTitle>
<CardTitle className="text-sm text-[var(--dg-text-secondary)]">{t('server.quickCommands')}</CardTitle>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-2">