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

@@ -1,4 +1,5 @@
import { useState, useRef, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import {
Dialog,
DialogContent,
@@ -40,6 +41,7 @@ export function TerminalDialog({
serverIp,
hasAuth = true,
}: TerminalDialogProps) {
const { t } = useTranslation();
const containerRef = useRef<HTMLDivElement>(null);
const termRef = useRef<XTerm | null>(null);
const wsRef = useRef<WebSocket | null>(null);
@@ -66,10 +68,10 @@ export function TerminalDialog({
try {
setAssigning(true);
await serverCredentialApi.assign(serverId, Number(selectedCredId));
toast.success('凭据已关联');
toast.success(t('common.operationSuccess'));
setAuthReady(true);
} catch (e) {
toast.error(e?.message || '关联失败');
toast.error(e?.message || t('common.operationFailed'));
} finally {
setAssigning(false);
}
@@ -141,12 +143,12 @@ export function TerminalDialog({
ws.onclose = () => {
setConnected(false);
setHasOutput(true);
term.write('\r\n\x1b[31m[连接已关闭]\x1b[0m\r\n');
term.write(`\r\n\x1b[31m[${t('server.connectionClosed')}]\r\n`);
};
ws.onerror = () => {
setHasOutput(true);
term.write('\r\n\x1b[31m[连接发生错误]\x1b[0m\r\n');
term.write(`\r\n\x1b[31m[${t('server.connectionError')}]\r\n`);
};
return () => {
@@ -233,18 +235,18 @@ export function TerminalDialog({
<div className="p-6 flex flex-col items-center justify-center gap-4" style={{ height: '480px' }}>
<Shield className="h-12 w-12 dg-text-yellow" />
<div className="text-center">
<p className="text-[var(--dg-text-primary)] font-medium mb-1">服务器未配置认证凭据</p>
<p className="text-sm text-[var(--dg-text-muted)]">请选择一个凭据用于 SSH 连接</p>
<p className="text-[var(--dg-text-primary)] font-medium mb-1">{t('server.noAuthCred')}</p>
<p className="text-sm text-[var(--dg-text-muted)]">{t('server.selectCredHint')}</p>
</div>
{credentials.length === 0 ? (
<p className="text-xs text-[var(--dg-text-muted)]">暂无可用凭据,请先去「凭证配置」添加</p>
<p className="text-xs text-[var(--dg-text-muted)]">{t('server.noCredAvailable')}</p>
) : (
<select
value={selectedCredId}
onChange={(e) => setSelectedCredId(e.target.value)}
className="w-64 px-3 py-2 bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded-md text-[var(--dg-text-primary)] text-sm"
>
<option value="">-- 选择凭据 --</option>
<option value="">{t('server.selectCred')}</option>
{credentials.map((c: JsonData) => (
<option key={c.id} value={String(c.id)}>
{c.type === 'ssh_key' ? '🔑' : '🔒'} {c.name}
@@ -257,7 +259,7 @@ export function TerminalDialog({
disabled={!selectedCredId || assigning}
className="bg-[var(--dg-blue)] hover:opacity-90 text-white"
>
{assigning ? '关联中...' : '确认连接'}
{assigning ? t('server.linking') : t('server.confirmConnect')}
</Button>
</div>
)}
@@ -265,7 +267,7 @@ export function TerminalDialog({
{authReady && (
<div className="relative bg-[#0a0e14]" style={{ height: fullscreen ? 'calc(100vh - 49px)' : '520px' }}>
<div ref={containerRef} className="xterm-terminal-host h-full" />
<TerminalLoadingOverlay show={!hasOutput} label="正在登录..." />
<TerminalLoadingOverlay show={!hasOutput} label={t('server.terminalLoggingIn')} />
</div>
)}
</DialogContent>