feat(i18n): 安全审计模块全量国际化 — 7 文件硬编码中文改翻译键 + audit 命名空间(89 键)

迁移文件:
- AuditOperationsTab.tsx — 操作审计(搜索/筛选/虚拟滚动表格/详情弹窗/统计弹窗)
- TerminalAuditTab.tsx — 终端审计子标签(在线/历史/命令)
- LoginLogsTab.tsx — 登录日志(DataTable + 状态筛选 + 登录方式)
- ActiveSessionsPanel.tsx — 在线会话(自动刷新 + 阻断确认 + 实时监控)
- HistorySessionsPanel.tsx — 历史会话(回放/下载录制)
- SessionCommandsPanel.tsx — 会话命令(虚拟滚动)
- helpers.tsx — formatDuration/getStatusBadge (i18n.t 非组件模式)

翻译键: audit 命名空间 89 键 (operations/login/terminal 三子域)
  + common.duration 时长单位(秒/分/时)
总键数: 481→610, 命名空间: 8→9 (common/menu/header/login/dashboard/server/alert/approval/audit)
zh-CN/en-US 完全对齐, tsc -b=0, npm build✓, 17/17 测试通过
This commit is contained in:
attacker committed 2026-06-29 20:44:08 +08:00
1 parent fef4997391
commit 186ece6495
10 files changed
+375 -141

No files matched your search

@@ -2,6 +2,7 @@
// v2: 虚拟滚动,支持万级命令记录流畅查看
import { useMemo, useState, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useVirtualizer } from '@tanstack/react-virtual';
import { Card, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
@@ -13,6 +14,7 @@ import { formatSize } from './helpers';
const GRID_COLS = 'minmax(150px,1fr) minmax(80px,0.8fr) minmax(200px,2fr) minmax(100px,0.8fr) minmax(80px,0.5fr)';
export function SessionCommandsPanel() {
const { t } = useTranslation();
const [keyword, setKeyword] = useState('');
const [sessionIdInput, setSessionIdInput] = useState('');
@@ -53,14 +55,14 @@ export function SessionCommandsPanel() {
<div className="relative w-64">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-slate-500" />
<Input
placeholder="搜索用户/命令..."
placeholder={t('audit.terminal.searchUserCommand')}
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
className="pl-9 h-9 bg-slate-800/50 border-slate-700 text-slate-200 placeholder:text-slate-500"
/>
</div>
<Input
placeholder="会话 ID(可选)"
placeholder={t('audit.terminal.sessionIdPlaceholder')}
value={sessionIdInput}
onChange={(e) => setSessionIdInput(e.target.value)}
className="w-32 h-9 bg-slate-800/50 border-slate-700 text-slate-200 placeholder:text-slate-500"
@@ -71,7 +73,7 @@ export function SessionCommandsPanel() {
onClick={() => refetch()}
>
<RefreshCw className="h-4 w-4 mr-2" />
刷新
{t('common.refresh')}
</Button>
</div>
@@ -85,7 +87,7 @@ export function SessionCommandsPanel() {
) : filtered.length === 0 ? (
<div className="flex flex-col items-center justify-center py-16 text-slate-500">
<Search className="h-8 w-8 mb-3 opacity-40" />
<p className="text-sm">暂无会话命令记录</p>
<p className="text-sm">{t('audit.terminal.noCommands')}</p>
</div>
) : (
<>
@@ -94,11 +96,11 @@ export function SessionCommandsPanel() {
className="grid gap-2 px-4 py-2 border-b border-slate-800 bg-slate-900 text-xs font-medium text-slate-400"
style={{ gridTemplateColumns: GRID_COLS }}
>
<span>时间</span>
<span>用户</span>
<span>命令</span>
<span>输出大小</span>
<span>关联会话</span>
<span>{t('audit.terminal.col.startTime')}</span>
<span>{t('audit.terminal.col.user')}</span>
<span>{t('audit.terminal.col.command')}</span>
<span>{t('audit.terminal.col.outputSize')}</span>
<span>{t('audit.terminal.col.sessionRef')}</span>
</div>
{/* 虚拟滚动列表 */}
@@ -141,7 +143,7 @@ export function SessionCommandsPanel() {
{/* 行数统计 */}
<div className="text-center py-2 text-xs text-slate-500 border-t border-slate-800">
共 {filtered.length} 条命令 {filtered.length > 200 && '· 虚拟滚动渲染'}
{t('audit.terminal.totalCommands', { count: filtered.length })} {filtered.length > 200 && `· ${t('audit.terminal.virtualScroll')}`}
</div>
</>
)}