refactor(i18n): U44 残余硬编码中文清零 — 终端审计状态+凭证类型+流水线阶段+时间格式+CSV导出

20 文件 ~70 处 UI 硬编码中文清零:
- credential-manager/constants.ts: 8 凭证类型 label/desc → labelKey/descKey + i18n.t()
- pipeline-run-detail/types.ts: 6 阶段 label → i18n.t('deploy.stage.*') + labelKey
- pipeline-manager/constants.ts + pipeline-editor/types.ts: 分秒 duration → i18n.t('common.duration.minSec')
- LiveMonitorDialog: 6 终端状态消息 → t()
- RdpAuditViewer: 6 RDP审计状态 → i18n.t('monitor.rdp.*')
- WorkspaceTermDialog: 2 终端连接状态 → t()
- TerminalSessionsTab: 4 时长格式+状态标签 → i18n.t()/t()
- k8s-event-utils + QueryHistoryPanel: 6 相对时间 → i18n.t('common.duration.*Ago')
- export-audit.ts: 9 CSV导出表头 → i18n.t('system.auditExport.*')
- useAuditSettings: 4 审计保留策略消息 → i18n.t('system.auditSettings.*')
- event-handler.ts: 4 AgentCLI事件消息 → i18n.t('aiops.cli.*')
- 其他 9 文件: NotifyPolicyTab/RoleFormDialog/CronJobViewDialog/TerminalOutput/shared-components/prometheus-ds/helpers/CloudServerImport/AdvancedSettingsPanel/releaseManagerHelpers

新增 75 翻译键, zh/en 7987→8059 对齐
tsc -b=0, npm build✓ (17.13s), ESLint=0/43/any=0, go build=0, 17/17 测试通过
This commit is contained in:
attacker committed 2026-07-14 23:13:32 +08:00
1 parent bd1ccefa7f
commit 05ee051879
26 files changed
+307 -93

No files matched your search

@@ -325,7 +325,7 @@ export function CredentialManager() {
{/* 内容 */}
<div>
<label className="block text-sm font-medium text-[var(--dg-text-secondary)] mb-1">
{formData.type === 'ssh_key' ? 'SSH 私钥' : formData.type === 'api_token' ? 'Token' : formData.type === 'access_key' ? 'AK/SK (每行一对,用空格或逗号分隔)' : '密码'}
{formData.type === 'ssh_key' ? t('system.credTypeLabel.sshKey') : formData.type === 'api_token' ? t('system.credTypeLabel.apiToken') : formData.type === 'access_key' ? 'AK/SK (每行一对,用空格或逗号分隔)' : t('system.credTypeLabel.password')}
{!editingId && <span className="dg-text-red"> *</span>}
{editingId && <span className="text-xs text-[var(--dg-text-muted)] ml-1">{t('system.leaveBlankNoUpdate')}</span>}
</label>
@@ -102,7 +102,7 @@ export function LiveMonitorDialog({ open, onOpenChange, sessionId, sessionInfo }
setConnected(true);
setConnectError('');
mountXterm(term, fitAddon, () => containerRef.current);
term.writeln('\x1b[36m[审计监控] 已连接到会话...\x1b[0m');
term.writeln(`\x1b[36m${t('monitor.terminal.auditConnected')}\x1b[0m`);
};
ws.onmessage = (event) => {
@@ -112,7 +112,7 @@ export function LiveMonitorDialog({ open, onOpenChange, sessionId, sessionInfo }
case 'session_info':
setMeta(msg.payload);
term.writeln(
`\x1b[36m用户: ${msg.payload.username} 服务器: ${msg.payload.server_name} (${msg.payload.server_ip})\x1b[0m`,
`\x1b[36m${t('monitor.terminal.userServer', { username: msg.payload.username, serverName: msg.payload.server_name, serverIp: msg.payload.server_ip })}\x1b[0m`,
);
break;
case 'history':
@@ -127,14 +127,14 @@ export function LiveMonitorDialog({ open, onOpenChange, sessionId, sessionInfo }
}
};
ws.onerror = () => setConnectError('WebSocket 连接失败');
ws.onerror = () => setConnectError(t('monitor.terminal.wsConnFailed'));
ws.onclose = (e) => {
if (!didOpen) {
setConnectError(`连接失败 (code=${e.code}): ${e.reason || '认证失败或网络问题'}`);
setConnectError(t('monitor.terminal.connFailedCode', { code: e.code, reason: e.reason || t('monitor.terminal.authOrNetwork') }));
}
setConnected(false);
term.writeln('\r\n\x1b[33m[审计监控] 连接已断开\x1b[0m');
term.writeln(`\r\n\x1b[33m${t('monitor.terminal.auditDisconnected')}\x1b[0m`);
};
const timeout = setTimeout(() => {
@@ -153,6 +153,7 @@ export function LiveMonitorDialog({ open, onOpenChange, sessionId, sessionInfo }
wsRef.current = null;
setConnected(false);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open, sessionId]);
// 容器尺寸变化时持续 fit // Logan.Li
@@ -126,7 +126,7 @@ export function RdpAuditViewer({ open, onOpenChange, sessionId, mode }: RdpAudit
useEffect(() => {
if (!open || !sessionId) return;
setStatus(mode === 'live' ? '正在连接 RDP 实时审计...' : '正在加载 RDP 录屏...');
setStatus(mode === 'live' ? i18n.t('monitor.rdp.connectingLive') : i18n.t('monitor.rdp.loadingRecording'));
setLoading(true);
setFrames([]);
setIndex(0);
@@ -161,8 +161,8 @@ export function RdpAuditViewer({ open, onOpenChange, sessionId, mode }: RdpAudit
/* ignore */
}
};
ws.onerror = () => { setLoading(false); setStatus('RDP 实时审计连接失败'); };
ws.onclose = () => setStatus((prev) => prev || 'RDP 实时审计已断开');
ws.onerror = () => { setLoading(false); setStatus(i18n.t('monitor.rdp.liveConnFailed')); };
ws.onclose = () => setStatus((prev) => prev || i18n.t('monitor.rdp.liveDisconnected'));
return () => {
ws.close();
wsRef.current = null;
@@ -182,13 +182,13 @@ export function RdpAuditViewer({ open, onOpenChange, sessionId, mode }: RdpAudit
setCanvasSize({ width: sizeFrame.width, height: sizeFrame.height });
}
setFrames(list);
setStatus(list.length ? '' : '该 RDP 会话没有可播放画面帧');
setStatus(list.length ? '' : i18n.t('monitor.rdp.noFrames'));
setPlaying(list.length > 0);
setLoading(false);
})
.catch(() => {
if (!cancelled) {
setStatus('RDP 录屏加载失败');
setStatus(i18n.t('monitor.rdp.loadFailed'));
setLoading(false);
}
});
@@ -45,7 +45,7 @@ const MODULE_GROUPS: { key: string; label: string; prefixes: string[] }[] = [
{ key: 'deploy', label: i18n.t('common.menuApp'), prefixes: ['deploy:'] },
{ key: 'monitor', label: i18n.t('common.menuMonitoring'), prefixes: ['monitor:', 'agent:'] },
{ key: 'auto', label: i18n.t('common.menuAutomation'), prefixes: ['auto:'] },
{ key: 'aiops', label: '🤖 AIOps智能', prefixes: ['aiops:'] },
{ key: 'aiops', label: i18n.t('system.role.aiopsGroup'), prefixes: ['aiops:'] },
{ key: 'approval', label: i18n.t('common.menuApproval'), prefixes: ['approval:'] },
{ key: 'audit', label: i18n.t('common.menuAudit'), prefixes: ['audit:'] },
{ key: 'system', label: i18n.t('common.menuSystem'), prefixes: ['system:'] },
@@ -17,16 +17,17 @@ import { useTerminalSessions, useTerminalSessionMutations } from '@/hooks/api/us
import { useConfirm } from '@/components/ui/confirm-dialog';
import { ReplayDialog } from './ReplayDialog';
import { useTranslation } from 'react-i18next';
import i18n from '@/i18n';
function formatDuration(sec: number): string {
if (!sec || sec < 0) return '--';
if (sec < 60) return `${sec}秒`;
if (sec < 60) return i18n.t('common.duration.seconds', { count: sec });
const m = Math.floor(sec / 60);
const s = sec % 60;
if (m < 60) return `${m}分${s > 0 ? `${s}秒` : ''}`;
if (m < 60) return s > 0 ? i18n.t('common.duration.minSec', { m, s }) : i18n.t('common.duration.min', { m });
const h = Math.floor(m / 60);
const rm = m % 60;
return `${h}时${rm > 0 ? `${rm}分` : ''}`;
return rm > 0 ? i18n.t('common.duration.hoursMin', { h, m: rm }) : i18n.t('common.duration.hour', { count: h });
}
function formatSize(bytes: number): string {
@@ -170,7 +171,7 @@ export function TerminalSessionsTab() {
}
onClick={() => setStatusFilter(st)}
>
{st === '' ? '全部' : st === 'active' ? '活动中' : st === 'closed' ? '已关闭' : '失败'}
{st === '' ? t('system.terminalSession.all') : st === 'active' ? t('system.terminalSession.active') : st === 'closed' ? t('system.terminalSession.closed') : t('system.terminalSession.failed')}
</Button>
))}
</div>
@@ -24,14 +24,14 @@ function escapeCsv(s: string): string {
export function exportAuditReportCsv(meta: ReplaySessionMeta, commands: CommandBookmark[]) {
const lines: string[] = [
i18n.t('audit.reportTitle'),
`会话ID,${meta.id}`,
`用户,${escapeCsv(meta.username || '')}`,
`目标主机,${escapeCsv(meta.server_name || '')}`,
`${i18n.t('system.auditExport.sessionId')},${meta.id}`,
`${i18n.t('system.auditExport.user')},${escapeCsv(meta.username || '')}`,
`${i18n.t('system.auditExport.targetHost')},${escapeCsv(meta.server_name || '')}`,
`IP,${meta.server_ip}:${meta.server_port}`,
`客户端IP,${meta.client_ip || ''}`,
`开始时间,${meta.start_time || ''}`,
`时长(秒),${meta.duration || 0}`,
`录制大小,${meta.record_size || 0}`,
`${i18n.t('system.auditExport.clientIp')},${meta.client_ip || ''}`,
`${i18n.t('system.auditExport.startTime')},${meta.start_time || ''}`,
`${i18n.t('system.auditExport.duration')},${meta.duration || 0}`,
`${i18n.t('system.auditExport.status')},${meta.record_size || 0}`,
'',
i18n.t('audit.reportTitle'),
];
@@ -107,8 +107,8 @@ export function useAuditSettings() {
const total = res.cleanup?.total ?? 0;
toast.success(
total > 0
? `已应用 ${days} 天保留策略,立即清理 ${total} 条超期记录`
: `已应用 ${days} 天保留策略,暂无超期记录需清理`,
? i18n.t('system.auditSettings.appliedWithCleanup', { days, total })
: i18n.t('system.auditSettings.appliedNoCleanup', { days }),
);
} catch (e: unknown) {
toast.error(
@@ -131,16 +131,13 @@ export function useAuditSettings() {
total?: number;
};
if (typeof s.total === "number") {
detail =
s.total > 0
? `,清理 ${s.total} 条`
: i18n.t("system.auditSetting.noExpiredRecords");
detail = s.total > 0 ? i18n.t('system.auditSettings.cleanupCount', { count: s.total }) : i18n.t("system.auditSetting.noExpiredRecords");
}
} catch {
// ignore
}
}
return `上次清理:${t}${detail}`;
return i18n.t('system.auditSettings.lastCleanup', { time: t, detail });
})();
return {