From a7838aaf6524c60a0f9036380fe04f741bd860d0 Mon Sep 17 00:00:00 2001 From: attacker Date: Mon, 13 Jul 2026 22:21:47 +0800 Subject: [PATCH] =?UTF-8?q?refactor(i18n):=20U41=20=E6=AE=8B=E4=BD=99?= =?UTF-8?q?=E7=A1=AC=E7=BC=96=E7=A0=81=E4=B8=AD=E6=96=87=E6=B8=85=E9=9B=B6?= =?UTF-8?q?=20=E2=80=94=20=E5=B7=A5=E5=85=B7=E5=87=BD=E6=95=B0+=E5=AE=A1?= =?UTF-8?q?=E8=AE=A1RDP=E6=A0=87=E7=AD=BE+AIOps=E5=88=86=E6=9E=90+Monitor?= =?UTF-8?q?=E6=AE=8B=E4=BD=99+=E5=AE=A1=E6=89=B9=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 18 文件 ~35 处 UI 硬编码中文→t()/i18n.t() 调用: - agent-utils.ts timeAgo() 秒前/分钟前/小时前 - utils.ts formatDistanceToNow() 分钟前/小时前/天前 - request.ts 响应解析失败错误消息 - ActiveSessionsPanel/HistorySessionsPanel RDP 在线/历史会话标签 - MetricsExplorer 清除/已选/最近1小时 - HostMonitor 当前主机 subtitle - AIAnalysisResult 证据链 (新增 useTranslation hook) - capacity-predict.ts 容量预测摘要模板 - ApprovalResourcePage 阿里云/腾讯云/华为云 - ApprovalPermissionPage 堡垒机 - site-monitor/helpers.ts 频率/时间/证书天数格式化 - site-monitor/analytics.ts 证书剩余/检查失败/延迟波动事件 - middleware-monitor MwTargetChartsPanel/MwTrendChart/helpers.ts - snmp-monitor SnmpMetricTrendChart/SnmpDeviceChartsPanel - host-monitor/utils.ts 图表点数标签 + PortPolicyDialog 系统进程说明 新增 34 翻译键 (common.duration.secAgo/hourAgo/dayAgo + common.selected/ responseParseError/rdpActiveSessions/rdpHistorySessions/rdpSessionCount/ evidenceChain/last1Hour/currentHost + monitor.lbl 10键 + monitor.siteMonitor 8键 + approval.provider 3键 + approval.permType 1键 + monitor.portPolicyDialog.systemProcessDesc + aiops.capacity.summary) zh/en 7813→7847 对齐; tsc -b=0, npm build✓ (17.31s), ESLint=0/43/any=0, go build=0, 17/17 测试通过 --- ROADMAP.md | 1 + .../src/components/aiops/AIAnalysisResult.tsx | 4 +- .../src/components/aiops/capacity-predict.ts | 2 +- frontend/src/lib/agent-utils.ts | 7 +-- frontend/src/lib/utils.ts | 6 +-- frontend/src/locales/en-US.json | 52 ++++++++++++++++--- frontend/src/locales/zh-CN.json | 52 ++++++++++++++++--- .../pages/approval/ApprovalPermissionPage.tsx | 2 +- .../pages/approval/ApprovalResourcePage.tsx | 2 +- .../terminal-audit/ActiveSessionsPanel.tsx | 2 +- .../terminal-audit/HistorySessionsPanel.tsx | 4 +- frontend/src/pages/monitor/HostMonitor.tsx | 2 +- .../src/pages/monitor/MetricsExplorer.tsx | 6 +-- .../monitor/host-monitor/PortPolicyDialog.tsx | 2 +- .../src/pages/monitor/host-monitor/utils.ts | 3 +- .../MwTargetChartsPanel.tsx | 8 +-- .../middleware-monitor/MwTrendChart.tsx | 3 +- .../monitor/middleware-monitor/helpers.ts | 6 +-- .../src/pages/monitor/site-monitor/helpers.ts | 14 ++--- .../site-monitor/observability/analytics.ts | 6 +-- .../snmp-monitor/SnmpDeviceChartsPanel.tsx | 8 +-- .../snmp-monitor/SnmpMetricTrendChart.tsx | 3 +- frontend/src/utils/request.ts | 2 +- 23 files changed, 140 insertions(+), 57 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 639d41c..92327ac 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -528,6 +528,7 @@ services/api.ts (1324L) | U38 | i18n phantom CTK 清理 — 模板字面量 + JSX 属性残余中文清零(13 文件 16 处→0: LogsHeader "行"suffix + analyzerHelpers "当前值" + DeploymentEditStorage 2 toast description + WorkloadViewPage 2 toast description + ServerFileBrowser confirm + LogDatasourcePage toast + LogAlertsPanel confirm + DeployTargetFields JSX hint + UserGroupsManager 3 处 confirm/desc + BuildNodesManager JSX "(可选)" + useLdapManagement confirm — 新增 14 语义化翻译键 (common.lineSuffix/currentValue/memberCount/fillIfMultiContainer/confirmDeleteType + k8s.editStorage.*Desc + k8s.workloadView.restartSentDesc + k8s.workloads.scaleSuccessDesc + aiops.reachable + monitor.deleteRuleConfirmDesc + deploy.rbac.deleteGroupDesc + pipeline.removeMemberDesc + system.ldapMgmt.deleteEntryDesc),zh/en 7737→7751 +14 对齐;tsc -b=0, npm build✓ (16.86s), ESLint=0/43/any=0, go build=0, 17/17 测试通过) | P3 | **done** | | U39 | 残余 JSX 属性/模板字面量中文清零(10 文件 14 处→0: DualLineChart subtitle 接收/发送 + NetworkTab 5处 unit="个" + FDUsageCard subtitle 当前 + NamespaceOverviewPage/NamespaceManagementPage subtitle + CreateHPADialog title+text 命名空间 + LogFieldSidebar title 个值 + LiveMonitorDialog title 全屏/退出全屏 + ExecutionHistoryDialog title 成功/失败 + LdapSettingsTab className 成功检查→ldapTestSuccess boolean 状态替代字符串匹配 — 新增 11 翻译键, zh/en 7751→7762 对齐;tsc -b=0, npm build✓ (16.94s), ESLint=0/0/any=0, go build=0, 17/17 测试通过) | P3 | **done** | | U40 | Monitor + Agent 子组件残余硬编码中文 i18n 补全(14 文件 ~50 处→0: ContextSwitchCard CTX/IRQ/次 + ProcessTable agentWaitData/cpuUsagePercent + FDUsageCard fdHandles + PortMonitorTab 黑名单/白名单/策略配置/暂无端口数据 + PortPolicyDialog 白名单全量上报/黑名单仅上报选中/端口列表/逗号分隔/白名单无需配置/已输入端口 + HostTimeRangePicker 时间范围/自定义/取消/应用 + DualLineChart 接收/发送 (i18n.t→useTranslation hook) + ZoomableAreaChart 暂无数据 + SiteResultsPanel 选择任务/次/可用率/立即拨测/SSL证书预警/到期/剩余/阈值/天 + MiddlewareMonitor Redis单机集群/上次更新/添加平台默认/暂无实例 + SiteMonitor subtitle + SNMPMonitor 标题/采集间隔/IP地址/OID模板/SNMP版本/确认/暂无设备/采集指标/暂无指标 + HealthProbeSection TCP目标地址/TCP端口 + AgentAlerts Agent告警/刷新/未恢复/已恢复/恢复/新建规则/创建第一条规则 — 新增 monitor.lbl 46 语义化翻译键 + agent.alerts 6 键, zh/en 7762→7814 对齐;tsc -b=0, npm build✓ (16.88s), ESLint=0/43/any=0, go build=0, 17/17 测试通过) | P3 | **done** | +| U41 | i18n 残余硬编码中文清零 — 工具函数 + 审计RDP标签 + AIOps分析 + Monitor残余 + 审批选项(18 文件 ~35 处→0: agent-utils.ts timeAgo 秒前/分钟前/小时前 + utils.ts formatDistanceToNow 分钟前/小时前/天前 + request.ts 响应解析失败 + ActiveSessionsPanel RDP在线会话 + HistorySessionsPanel RDP历史会话/RDP会话共N条 + MetricsExplorer 清除/已选/最近1小时 + HostMonitor 当前主机 + AIAnalysisResult 证据链(useTranslation hook) + capacity-predict.ts 容量预测摘要模板 + ApprovalResourcePage 阿里云/腾讯云/华为云 + ApprovalPermissionPage 堡垒机 + site-monitor/helpers.ts 推荐频率/秒/分钟/小时/天 + site-monitor/analytics.ts 证书剩余/失败/延迟波动 + middleware-monitor/MwTargetChartsPanel 选择实例/已用/集群节点/慢查询 + MwTrendChart 暂无趋势数据 + middleware-monitor/helpers.ts 相对时间 + snmp-monitor/SnmpMetricTrendChart 暂无趋势数据等待采集 + SnmpDeviceChartsPanel 点击设备/可观测/刷新/暂无指标 + host-monitor/utils.ts 图表点数 + PortPolicyDialog 系统进程端口说明 — 新增 common.duration.secAgo/hourAgo/dayAgo + common.selected/responseParseError/rdpActiveSessions/rdpHistorySessions/rdpSessionCount/evidenceChain/last1Hour/currentHost + monitor.lbl 10键 + monitor.siteMonitor 8键 + approval.provider 3键 + approval.permType 1键 + monitor.portPolicyDialog.systemProcessDesc + aiops.capacity.summary 共 34 翻译键, zh/en 7813→7847 对齐;tsc -b=0, npm build✓ (17.31s), ESLint=0/43/any=0, go build=0, 17/17 测试通过) | P3 | **done** | | U37 | 全量 JSX 文本节点硬编码中文清零(65 文件 151 处→0: MiddlewareMonitor/SiteMonitor/SNMPMonitor/HealthProbeSection/ContextSwitchCard/ProcessTable/PortMonitorTab/MwTargetChartsPanel/MiddlewareDialog/ChartRangeHint/SnmpDeviceChartsPanel/AlertRulesTab/LogClusterPanel/LogDatasourcePage/LogQueryToolbar/LogAlertsPanel/PrometheusDatasourceManager/PodMetricsPage/CapacityPage/NamespaceManagementPage/NamespaceResourcePage/DeploymentEditService/EventsPage/DeploymentDetail/ClusterOverviewPage/DeploymentEditContainers/DeploymentEditStorage/WorkloadViewPage/BottomStatusBar/UpdateStrategySelectorCards/PodInstancesTable/shared-components/UpdateStrategyCard/TolerationsCard/HostSettingsCard/IngressListItem/ServiceListItem/ServiceCreateForm/IngressCreateForm/CreateHPADialog/DeployCredentials/DeployRBAC/UserGroupsManager/BuildNodesManager/DeployTargetFields/PipelineCreateDialog/CredFormDialog/WorkspaceTermDialog/AgentAlerts/AgentRuleDialog/LiveMonitorDialog/RoleFormDialog/CronJobViewDialog/TerminalOutput/AIAnalysisResult/AIPredictiveAnalytics/PredictiveCostTab/PredictiveCapacityTab/ActiveSessionsPanel/HistorySessionsPanel/TerminalDialog/ServerFileBrowser/PodFileBrowser/SiteResultsPanel/SiteProtocolPieChart — 151 JSX 文本节点中文全部替换为 t()/i18n.t() 调用;新增 common.* 98 翻译键 (selectedCount/itemsCount/newValue/namespaceLabel/containerLabel/replicasLabel/minReplicas/maxReplicas/createNamespace/noNamespace/unknownResource/exportYaml/loadTrend/loadCapacity/predicted/threshold/hostSettings/addVolume/addMount/createService/createIngress/editAction/updateStrategy/selectAndLabel/historyVersion/fileBrowser/scale/back/createHpa/allNamespaces/certLabel/observable/deviceList/addDevice/addMonitor/collectNow/addTask/addProbe/restoreFull/contextSwitch/processTop/listenPorts/terminalRealtime/auditWebssh/buildTerminal/fileBrowse/newDir/loadDeployment/notLinked/selectedPerms/none/hasLabel/deleteNamespace/deleteNamespaceWarn/allResources/notFoundDeploy/nodeList/fileLabel/addCustom/newInstanceService/newInstanceIngress/totalContainers/workContainers/loadingEllipsis/volumeClaimTemplates/containerTemplate/passwordOptional/updated/page/perPage/clusterMode/totalLogs/countLabel/percentage/queryTime/addDatasource/newPermission/newEnv/envLabel/displayName/newUserGroup/auditTrace/predictValue/confidence/predictMonthEnd/noCapacityData/securityMode/standardRdp/domainLabel/noRdpActive/noRdpHistory/buffer/matched/podLogs/createHpaTitle/password/events/total);37 文件已有 import i18n→i18n.t() 模式, 2 文件新增 import i18n;zh/en 7640→3526 namespace-flat +98 键对齐;tsc -b=0, npm build✓ (17.96s), ESLint=0/43/any=0, go build=0, 17/17 测试通过) | P3 | **done** | --- diff --git a/frontend/src/components/aiops/AIAnalysisResult.tsx b/frontend/src/components/aiops/AIAnalysisResult.tsx index 97f573c..89db0f1 100644 --- a/frontend/src/components/aiops/AIAnalysisResult.tsx +++ b/frontend/src/components/aiops/AIAnalysisResult.tsx @@ -4,6 +4,7 @@ import { Button } from '@/components/ui/button'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Sparkles, Brain, Loader2 } from 'lucide-react'; import { AlertCircle, TrendingUp, CheckCircle, FileText, Terminal, Play } from 'lucide-react'; +import { useTranslation } from 'react-i18next'; import type { AlertItem, AIAnalysis } from './analyzerHelpers'; import i18n from '@/i18n'; @@ -15,6 +16,7 @@ interface AIAnalysisResultProps { } export function AIAnalysisResult({ selectedAlert, isAnalyzing, analysis, onAutoFix }: AIAnalysisResultProps) { + const { t } = useTranslation(); return ( @@ -91,7 +93,7 @@ export function AIAnalysisResult({ selectedAlert, isAnalyzing, analysis, onAutoF

- 证据链 + {t('common.evidenceChain')}

{analysis.evidence.slice(0, 5).map((item, idx) => ( diff --git a/frontend/src/components/aiops/capacity-predict.ts b/frontend/src/components/aiops/capacity-predict.ts index 0557c83..72fd52c 100644 --- a/frontend/src/components/aiops/capacity-predict.ts +++ b/frontend/src/components/aiops/capacity-predict.ts @@ -178,7 +178,7 @@ export function buildCapacityInsightPrompt(forecasts: CapacityForecast[]): strin if (forecasts.length === 0) return ''; const lines = forecasts.map((f) => { const risk = f.daysUntilThreshold >= 999 ? i18n.t('aiops.capacity.noRisk') : i18n.t('aiops.predictutilsts.daysUntilThreshold', { days: f.daysUntilThreshold }); - return `- ${f.resource}:当前 ${f.currentUsage}% → 7天后预测 ${f.predictedUsage}%(阈值 ${f.threshold}%),${risk}`; + return i18n.t('aiops.capacity.summary', { resource: f.resource, current: f.currentUsage, predicted: f.predictedUsage, threshold: f.threshold, risk }); }); return [ i18n.t('aiops.capacity.expertPrompt'), diff --git a/frontend/src/lib/agent-utils.ts b/frontend/src/lib/agent-utils.ts index c600dde..5639935 100644 --- a/frontend/src/lib/agent-utils.ts +++ b/frontend/src/lib/agent-utils.ts @@ -1,4 +1,5 @@ import type { JsonData } from "@/types/common"; +import i18n from "@/i18n"; // Agent 监控相关工具函数(供组件与 API 层共享) // Logan.Li /** 在线判定:3 分钟内有上报视为在线 */ @@ -15,9 +16,9 @@ export function timeAgo(ts: unknown): string { const t = new Date(ts as string | number | Date).getTime(); if (Number.isNaN(t)) return '--'; const diff = Math.floor((Date.now() - t) / 1000); - if (diff < 60) return `${diff}秒前`; - if (diff < 3600) return `${Math.floor(diff / 60)}分钟前`; - if (diff < 86400) return `${Math.floor(diff / 3600)}小时前`; + if (diff < 60) return i18n.t('common.duration.secAgo', { count: diff }); + if (diff < 3600) return i18n.t('common.duration.minAgo', { count: Math.floor(diff / 60) }); + if (diff < 86400) return i18n.t('common.duration.hourAgo', { count: Math.floor(diff / 3600) }); return new Date(ts as string | number | Date).toLocaleString(); } diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts index 4c6225f..854ece4 100644 --- a/frontend/src/lib/utils.ts +++ b/frontend/src/lib/utils.ts @@ -18,11 +18,11 @@ export function formatDistanceToNow(timestamp: number): string { if (seconds < 60) { return i18n.t('task.cronJob.time.justNow'); } else if (minutes < 60) { - return `${minutes}分钟前`; + return i18n.t('common.duration.minAgo', { count: minutes }); } else if (hours < 24) { - return `${hours}小时前`; + return i18n.t('common.duration.hourAgo', { count: hours }); } else if (days < 30) { - return `${days}天前`; + return i18n.t('common.duration.dayAgo', { count: days }); } else { return new Date(timestamp).toLocaleDateString(); } diff --git a/frontend/src/locales/en-US.json b/frontend/src/locales/en-US.json index dde5c93..cf8f774 100644 --- a/frontend/src/locales/en-US.json +++ b/frontend/src/locales/en-US.json @@ -181,7 +181,10 @@ "minSec": "{{m}}m {{s}}s", "hour": "{{count}}h", "hourMin": "{{h}}h {{m}}m", - "minAgo": "{{count}} min ago" + "minAgo": "{{count}} min ago", + "secAgo": "{{count}}s ago", + "hourAgo": "{{count}}h ago", + "dayAgo": "{{count}}d ago" }, "ebCaughtError": "[ErrorBoundary] Caught error:", "ebCopyError": "Copy Error", @@ -623,7 +626,15 @@ "fillIfMultiContainer": "(required for multi-container)", "confirmDeleteType": "Delete {{type}} \"{{name}}\"?", "unitCount": "", - "fieldValues": "{{count}} values" + "fieldValues": "{{count}} values", + "selected": "{{count}} selected", + "responseParseError": "Response parse failed", + "rdpActiveSessions": "RDP Active Sessions", + "rdpHistorySessions": "RDP History Sessions", + "rdpSessionCount": "RDP sessions: {{count}}", + "evidenceChain": "Evidence Chain", + "last1Hour": "Last 1 hour", + "currentHost": "Current host: {{host}}" }, "menu": { "aiAgentCli": "Agent CLI", @@ -1478,7 +1489,15 @@ "general": "General Approval" }, "workflowSubtitle": "Configure multi-level approval workflows for resource, application, and permission requests", - "workflowTitle": "Approval Workflow Config" + "workflowTitle": "Approval Workflow Config", + "provider": { + "aliyun": "Alibaba Cloud", + "tencent": "Tencent Cloud", + "huawei": "Huawei Cloud" + }, + "permType": { + "bastion": "Bastion" + } }, "audit": { "csvHeader": "Time,User,Command,Output Size,Session ID,Critical", @@ -4423,7 +4442,16 @@ "snmpVersion": "SNMP Version", "snmpNoDevice": "No SNMP devices. Click \"Add Device\" to start monitoring.", "snmpCollectMetrics": "Collected Metrics", - "snmpNoMetrics": "No metrics yet. Please collect first." + "snmpNoMetrics": "No metrics yet. Please collect first.", + "noTrendData": "No trend data", + "noTrendDataWaiting": "No trend data, waiting for collection", + "selectInstanceHint": "Select an instance to view trends and health", + "clickDeviceHint": "Click a device row to view CPU / Memory / Temperature / Fan trends", + "noMetricsHint": "No visualizable metrics, please complete at least one collection", + "usedHint": "Used {{value}}", + "clusterNodesHint": "Cluster {{value}} nodes", + "slowQueriesHint": "Slow queries {{value}}", + "pointCount": "{{min}} — {{max}} · {{count}} pts" }, "logAlertBell": { "linked": "Alert Policy Linked", @@ -4813,7 +4841,8 @@ "neverReport": "Never report", "filterMode": "Filter Mode", "title": "Port Monitoring Policy", - "desc": "Configure Agent port reporting filter rules" + "desc": "Configure Agent port reporting filter rules", + "systemProcessDesc": "⚠️ Regardless of mode, the following system process ports {{neverReport}}: sshd, rpcbind, master, systemd, dbus-daemon, rsyslogd, etc. Automatically skipped during collection." }, "postgresql": "PostgreSQL", "prevPage": "Previous", @@ -5004,7 +5033,15 @@ "probeDesc": "Configure probe tasks by protocol type, the system will automatically probe at intervals", "taskNotFound": "Probe task does not exist or has been deleted", "clickToObserve": "Click to view details", - "alerting": "Alerting" + "alerting": "Alerting", + "recommendFreq": "Recommended {{freq}}, min {{minFreq}}", + "seconds": "{{count}}s", + "minutes": "{{count}}min", + "hours": "{{count}}h", + "certDays": "{{count}}d", + "certRemaining": "Certificate remaining {{days}} days", + "checkFailed": "{{label}} failed", + "latencyFluctuation": "{{label}} latency fluctuation" }, "siteProbe": "Site Probe", "siteProbeTitle": "Site Probe Tasks", @@ -7933,7 +7970,8 @@ "expertPrompt": "You are an AIOps capacity planning expert. Based on the following server resource capacity forecast data, provide a comprehensive risk assessment and actionable operations recommendations:", "resCpu": "Server CPU Compute", "resMemory": "Server Memory", - "resDisk": "Storage Disk Space" + "resDisk": "Storage Disk Space", + "summary": "- {{resource}}: Current {{current}}% → 7-day forecast {{predicted}}% (threshold {{threshold}}%), {{risk}}" }, "capacityPlanPrompt": "Based on the following host resource usage, provide cost optimization and capacity planning advice (identify idle/overloaded hosts; suggest scale-down/scale-up)", "capacityPlanning": "Capacity Planning", diff --git a/frontend/src/locales/zh-CN.json b/frontend/src/locales/zh-CN.json index 7048109..ef679ca 100644 --- a/frontend/src/locales/zh-CN.json +++ b/frontend/src/locales/zh-CN.json @@ -181,7 +181,10 @@ "minSec": "{{m}}分{{s}}秒", "hour": "{{count}}时", "hourMin": "{{h}}时{{m}}分", - "minAgo": "{{count}}分钟前" + "minAgo": "{{count}}分钟前", + "secAgo": "{{count}}秒前", + "hourAgo": "{{count}}小时前", + "dayAgo": "{{count}}天前" }, "ebCaughtError": "[ErrorBoundary] 捕获到错误:", "ebCopyError": "复制错误", @@ -623,7 +626,15 @@ "fillIfMultiContainer": "(多容器时填写)", "confirmDeleteType": "确认删除 {{type}} \"{{name}}\"?", "unitCount": "个", - "fieldValues": "{{count}} 个值" + "fieldValues": "{{count}} 个值", + "selected": "{{count}} 已选", + "responseParseError": "响应解析失败", + "rdpActiveSessions": "RDP 在线会话", + "rdpHistorySessions": "RDP 历史会话", + "rdpSessionCount": "RDP 会话共 {{count}} 条", + "evidenceChain": "证据链", + "last1Hour": "最近 1 小时", + "currentHost": "当前主机: {{host}}" }, "menu": { "aiAgentCli": "Agent CLI", @@ -1478,7 +1489,15 @@ "general": "通用审批" }, "workflowSubtitle": "为资源申请、应用申请、权限审批配置多级审批流程", - "workflowTitle": "审批流程配置" + "workflowTitle": "审批流程配置", + "provider": { + "aliyun": "阿里云", + "tencent": "腾讯云", + "huawei": "华为云" + }, + "permType": { + "bastion": "堡垒机" + } }, "audit": { "csvHeader": "时间,用户,命令,输出大小,会话ID,高危", @@ -4423,7 +4442,16 @@ "snmpVersion": "SNMP 版本", "snmpNoDevice": "暂无 SNMP 设备,点击「添加设备」开始监控", "snmpCollectMetrics": "采集指标", - "snmpNoMetrics": "暂无指标,请先采集" + "snmpNoMetrics": "暂无指标,请先采集", + "noTrendData": "暂无趋势数据", + "noTrendDataWaiting": "暂无趋势数据,等待后台采集", + "selectInstanceHint": "选择左侧实例查看趋势与健康度", + "clickDeviceHint": "点击设备行查看 CPU / 内存 / 温度 / 风扇趋势图", + "noMetricsHint": "暂无可视化指标,请先完成至少一次采集", + "usedHint": "已用 {{value}}", + "clusterNodesHint": "集群 {{value}} 节点", + "slowQueriesHint": "慢查询 {{value}}", + "pointCount": "{{min}} — {{max}} · {{count}} 点" }, "logAlertBell": { "linked": "已关联告警策略", @@ -4813,7 +4841,8 @@ "neverReport": "永远不上报", "filterMode": "过滤模式", "title": "端口监控策略", - "desc": "配置 Agent 端口上报过滤规则" + "desc": "配置 Agent 端口上报过滤规则", + "systemProcessDesc": "⚠️ 无论选择哪种模式,以下系统进程端口 {{neverReport}}:sshd、rpcbind、master、systemd、dbus-daemon、rsyslogd 等。Agent 采集时自动跳过。" }, "postgresql": "PostgreSQL", "prevPage": "上一页", @@ -5004,7 +5033,15 @@ "probeDesc": "按协议类型配置探活任务,系统将按间隔自动拨测", "taskNotFound": "拨测任务不存在或已删除", "clickToObserve": "点击可观测进入详情页", - "alerting": "告警中" + "alerting": "告警中", + "recommendFreq": "推荐 {{freq}},最小 {{minFreq}}", + "seconds": "{{count}}秒", + "minutes": "{{count}}分钟", + "hours": "{{count}}小时", + "certDays": "{{count}}天", + "certRemaining": "证书剩余 {{days}} 天", + "checkFailed": "{{label}}失败", + "latencyFluctuation": "{{label}}延迟波动" }, "siteProbe": "站点拨测", "siteProbeTitle": "站点拨测任务", @@ -7933,7 +7970,8 @@ "expertPrompt": "你是 AIOps 容量规划专家。基于以下服务器资源容量预测数据,给出综合风险评估与可执行的运维建议:", "resCpu": "服务器CPU算力", "resMemory": "服务器内存", - "resDisk": "存储磁盘空间" + "resDisk": "存储磁盘空间", + "summary": "- {{resource}}:当前 {{current}}% → 7天后预测 {{predicted}}%(阈值 {{threshold}}%),{{risk}}" }, "capacityPlanPrompt": "根据以下主机资源使用数据,提供成本优化和容量规划建议(识别闲置/过载主机,给出缩容/扩容建议)", "capacityPlanning": "容量规划", diff --git a/frontend/src/pages/approval/ApprovalPermissionPage.tsx b/frontend/src/pages/approval/ApprovalPermissionPage.tsx index 747ea17..44f82bc 100644 --- a/frontend/src/pages/approval/ApprovalPermissionPage.tsx +++ b/frontend/src/pages/approval/ApprovalPermissionPage.tsx @@ -6,7 +6,7 @@ function ApprovalPermissionPage() { const { t } = useTranslation(); const PERMISSION_FIELDS: FormField[] = [ { key: 'perm_type', label: t('approval.type.permission'), type: 'select', options: [ - '堡垒机', 'VPN', 'Log', 'DB', 'SSH', 'K8s', + t('approval.permType.bastion'), 'VPN', 'Log', 'DB', 'SSH', 'K8s', ], required: true }, { key: 'account', label: 'Account', type: 'text', placeholder: 'logan.li', required: true }, { key: 'reason', label: 'Reason', type: 'textarea', placeholder: '', required: true }, diff --git a/frontend/src/pages/approval/ApprovalResourcePage.tsx b/frontend/src/pages/approval/ApprovalResourcePage.tsx index 96306d3..33f5ec0 100644 --- a/frontend/src/pages/approval/ApprovalResourcePage.tsx +++ b/frontend/src/pages/approval/ApprovalResourcePage.tsx @@ -5,7 +5,7 @@ import { ApprovalCategoryPage, type FormField } from './ApprovalCategoryPage'; function ApprovalResourcePage() { const { t } = useTranslation(); const RESOURCE_FIELDS: FormField[] = [ - { key: 'provider', label: t('approval.resourceTitle'), type: 'select', options: ['阿里云', '腾讯云', '华为云', 'AWS'], required: true }, + { key: 'provider', label: t('approval.resourceTitle'), type: 'select', options: [t('approval.provider.aliyun'), t('approval.provider.tencent'), t('approval.provider.huawei'), 'AWS'], required: true }, { key: 'region', label: 'Region', type: 'text', placeholder: 'cn-hangzhou', required: true }, { key: 'spec', label: 'Spec', type: 'select', options: ['2C4G', '4C8G', '8C16G', '16C32G', '32C64G'], required: true }, { key: 'disk', label: 'Disk(GB)', type: 'number', defaultValue: 40, required: true }, diff --git a/frontend/src/pages/audit/terminal-audit/ActiveSessionsPanel.tsx b/frontend/src/pages/audit/terminal-audit/ActiveSessionsPanel.tsx index f3d485e..9579d90 100644 --- a/frontend/src/pages/audit/terminal-audit/ActiveSessionsPanel.tsx +++ b/frontend/src/pages/audit/terminal-audit/ActiveSessionsPanel.tsx @@ -319,7 +319,7 @@ export function ActiveSessionsPanel({ userToggledOff, onUserToggledOff }: Active -
RDP 在线会话
+
{t('common.rdpActiveSessions')}
{rdpQuery.isLoading ? (
) : rdpSessions.length === 0 ? ( diff --git a/frontend/src/pages/audit/terminal-audit/HistorySessionsPanel.tsx b/frontend/src/pages/audit/terminal-audit/HistorySessionsPanel.tsx index 36c8825..6ae781b 100644 --- a/frontend/src/pages/audit/terminal-audit/HistorySessionsPanel.tsx +++ b/frontend/src/pages/audit/terminal-audit/HistorySessionsPanel.tsx @@ -248,7 +248,7 @@ export function HistorySessionsPanel() { -
RDP 历史会话
+
{t('common.rdpHistorySessions')}
{rdpQuery.isLoading ? (
@@ -303,7 +303,7 @@ export function HistorySessionsPanel() {
- RDP 会话共 {rdpTotal} 条 + {t('common.rdpSessionCount', { count: rdpTotal })}
); @@ -163,7 +163,7 @@ export function MetricsExplorer() {

{t('monitor.metricsExplorer.metricList')}

- {selectedMetrics.length} 已选 + {t('common.selected', { count: selectedMetrics.length })}
{Object.entries(grouped).map(([cat, names]) => ( @@ -203,7 +203,7 @@ export function MetricsExplorer() {

- {target?.name || ''} — 最近 1 小时 + {target?.name || ''} — {t('common.last1Hour')}

{selectedMetrics.length === 0 ? ( diff --git a/frontend/src/pages/monitor/host-monitor/PortPolicyDialog.tsx b/frontend/src/pages/monitor/host-monitor/PortPolicyDialog.tsx index a982de4..39dffc9 100644 --- a/frontend/src/pages/monitor/host-monitor/PortPolicyDialog.tsx +++ b/frontend/src/pages/monitor/host-monitor/PortPolicyDialog.tsx @@ -84,7 +84,7 @@ export function PortPolicyDialog({

- ⚠️ 无论选择哪种模式,以下系统进程端口 {t('monitor.portPolicyDialog.neverReport')} :sshd、rpcbind、master、systemd、dbus-daemon、rsyslogd 等。Agent 采集时自动跳过。 + {t('monitor.portPolicyDialog.systemProcessDesc', { neverReport: t('monitor.portPolicyDialog.neverReport') })}

diff --git a/frontend/src/pages/monitor/host-monitor/utils.ts b/frontend/src/pages/monitor/host-monitor/utils.ts index 838fd88..d6c6477 100644 --- a/frontend/src/pages/monitor/host-monitor/utils.ts +++ b/frontend/src/pages/monitor/host-monitor/utils.ts @@ -1,4 +1,5 @@ // 主机监控工具函数 // Logan.Li +import i18n from '@/i18n'; import type { BucketPoint, HostMonitorTimeRange } from './types'; import type { JsonData } from '@/types/common'; /** 按时间跨度格式化 X 轴标签(避免 7 天范围只显示时分) // Logan.Li */ @@ -175,7 +176,7 @@ export function getActualDataSpan(history: JsonData[], _range: HostMonitorTimeRa const min = Math.min(...ts); const max = Math.max(...ts); const spanMin = Math.max(1, Math.round((max - min) / 60)); - return `${formatAxisTime(min, spanMin)} — ${formatAxisTime(max, spanMin)} · ${history.length} 点`; + return i18n.t('monitor.lbl.pointCount', { min: formatAxisTime(min, spanMin), max: formatAxisTime(max, spanMin), count: history.length }); } export function getCurrentVal(latest: JsonData, netInfo: JsonData, diskIOInfo: JsonData, swapInfo: JsonData, fdInfo: JsonData, diff --git a/frontend/src/pages/monitor/middleware-monitor/MwTargetChartsPanel.tsx b/frontend/src/pages/monitor/middleware-monitor/MwTargetChartsPanel.tsx index b3ad91f..3b9c1b7 100644 --- a/frontend/src/pages/monitor/middleware-monitor/MwTargetChartsPanel.tsx +++ b/frontend/src/pages/monitor/middleware-monitor/MwTargetChartsPanel.tsx @@ -67,7 +67,7 @@ export function MwTargetChartsPanel({ target, chartDefs, accent }: Props) { return ( - 选择左侧实例查看趋势与健康度 + {t('monitor.lbl.selectInstanceHint')} ); @@ -127,14 +127,14 @@ export function MwTargetChartsPanel({ target, chartDefs, accent }: Props) { value={memPct ?? (m.redis_used_memory > 0 ? 50 : 0)} display={fmtMemory(m.redis_used_memory)} level={memPct != null ? gaugeTone(memPct, 80, 90) : 'ok'} - hint={memPct != null ? `已用 ${memPct.toFixed(0)}%` : t('monitor.lbl.noMaxMemory')} + hint={memPct != null ? t('monitor.lbl.usedHint', { value: `${memPct.toFixed(0)}%` }) : t('monitor.lbl.noMaxMemory')} /> 0 ? 'warn' : 'ok'} - hint={m.redis_cluster_known_nodes ? `集群 ${fmtVal(m.redis_cluster_known_nodes)} 节点` : undefined} + hint={m.redis_cluster_known_nodes ? t('monitor.lbl.clusterNodesHint', { value: fmtVal(m.redis_cluster_known_nodes) }) : undefined} /> )} @@ -157,7 +157,7 @@ export function MwTargetChartsPanel({ target, chartDefs, accent }: Props) { value={Math.min(100, (m.mysql_threads_running || 0) * 5)} display={fmtVal(m.mysql_threads_running)} level={(m.mysql_threads_running || 0) > 20 ? 'warn' : 'ok'} - hint={`慢查询 ${fmtVal(m.mysql_slow_queries)}`} + hint={t('monitor.lbl.slowQueriesHint', { value: fmtVal(m.mysql_slow_queries) })} /> )} diff --git a/frontend/src/pages/monitor/middleware-monitor/MwTrendChart.tsx b/frontend/src/pages/monitor/middleware-monitor/MwTrendChart.tsx index 10a1bef..1d3f5bc 100644 --- a/frontend/src/pages/monitor/middleware-monitor/MwTrendChart.tsx +++ b/frontend/src/pages/monitor/middleware-monitor/MwTrendChart.tsx @@ -1,5 +1,6 @@ // 中间件指标趋势图 — 光标拖拽选区 // Logan.Li import { useMemo } from 'react'; +import i18n from '@/i18n'; import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ReferenceArea, @@ -41,7 +42,7 @@ export function MwTrendChart({ if (chartData.length === 0) { return (
- 暂无趋势数据 + {i18n.t('monitor.lbl.noTrendData')}
); } diff --git a/frontend/src/pages/monitor/middleware-monitor/helpers.ts b/frontend/src/pages/monitor/middleware-monitor/helpers.ts index da21c13..6b02b71 100644 --- a/frontend/src/pages/monitor/middleware-monitor/helpers.ts +++ b/frontend/src/pages/monitor/middleware-monitor/helpers.ts @@ -245,8 +245,8 @@ export function fmtLastSeen(iso?: string): string { const d = new Date(iso); if (Number.isNaN(d.getTime())) return '--'; const diff = Math.floor((Date.now() - d.getTime()) / 1000); - if (diff < 60) return `${diff}s 前`; - if (diff < 3600) return `${Math.floor(diff / 60)}m 前`; - if (diff < 86400) return `${Math.floor(diff / 3600)}h 前`; + if (diff < 60) return i18n.t('common.duration.secAgo', { count: diff }); + if (diff < 3600) return i18n.t('common.duration.minAgo', { count: Math.floor(diff / 60) }); + if (diff < 86400) return i18n.t('common.duration.hourAgo', { count: Math.floor(diff / 3600) }); return `${d.getMonth() + 1}/${d.getDate()} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`; } \ No newline at end of file diff --git a/frontend/src/pages/monitor/site-monitor/helpers.ts b/frontend/src/pages/monitor/site-monitor/helpers.ts index a6d8c5f..c630f8c 100644 --- a/frontend/src/pages/monitor/site-monitor/helpers.ts +++ b/frontend/src/pages/monitor/site-monitor/helpers.ts @@ -95,15 +95,15 @@ export const probeTypeMeta: Record spikeThreshold; - if (failed) pushEvent(events, r, `${label}失败`, 'error', r.error_message || r.remote_ip); + if (failed) pushEvent(events, r, i18n.t('monitor.siteMonitor.checkFailed', { label }), 'error', r.error_message || r.remote_ip); else if (spike) { spikeCount++; - pushEvent(events, r, `${label}延迟波动`, 'warn', fmtMs(latency)); + pushEvent(events, r, i18n.t('monitor.siteMonitor.latencyFluctuation', { label }), 'warn', fmtMs(latency)); } return { time: fmtTime(r.checked_at).slice(-5), latency, failed, spike }; }); diff --git a/frontend/src/pages/monitor/snmp-monitor/SnmpDeviceChartsPanel.tsx b/frontend/src/pages/monitor/snmp-monitor/SnmpDeviceChartsPanel.tsx index 2e0476f..8dd90e3 100644 --- a/frontend/src/pages/monitor/snmp-monitor/SnmpDeviceChartsPanel.tsx +++ b/frontend/src/pages/monitor/snmp-monitor/SnmpDeviceChartsPanel.tsx @@ -88,7 +88,7 @@ export function SnmpDeviceChartsPanel({ device, templateName }: Props) { return ( - 点击设备行查看 CPU / 内存 / 温度 / 风扇趋势图 + {t('monitor.lbl.clickDeviceHint')} ); @@ -104,7 +104,7 @@ export function SnmpDeviceChartsPanel({ device, templateName }: Props) {

- 可观测 · {device.name} + {t('monitor.lbl.observability')} · {device.name}

{templateName} @@ -123,7 +123,7 @@ export function SnmpDeviceChartsPanel({ device, templateName }: Props) {
@@ -147,7 +147,7 @@ export function SnmpDeviceChartsPanel({ device, templateName }: Props) {
) : charts.length === 0 ? (
- 暂无可视化指标,请先完成至少一次采集 + {t('monitor.lbl.noMetricsHint')}
) : (
diff --git a/frontend/src/pages/monitor/snmp-monitor/SnmpMetricTrendChart.tsx b/frontend/src/pages/monitor/snmp-monitor/SnmpMetricTrendChart.tsx index 6b286e6..78b0d99 100644 --- a/frontend/src/pages/monitor/snmp-monitor/SnmpMetricTrendChart.tsx +++ b/frontend/src/pages/monitor/snmp-monitor/SnmpMetricTrendChart.tsx @@ -1,5 +1,6 @@ // SNMP 指标趋势折线图 — 光标拖拽选区 // Logan.Li import { useMemo } from 'react'; +import i18n from '@/i18n'; import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ReferenceArea, @@ -30,7 +31,7 @@ export function SnmpMetricTrendChart({ data, color, unit, height = 160 }: Props) if (chartData.length === 0) { return (
- 暂无趋势数据,等待后台采集 + {i18n.t('monitor.lbl.noTrendDataWaiting')}
); } diff --git a/frontend/src/utils/request.ts b/frontend/src/utils/request.ts index 89eaa60..81d98b5 100644 --- a/frontend/src/utils/request.ts +++ b/frontend/src/utils/request.ts @@ -108,7 +108,7 @@ async function request( try { json = await response.json(); } catch { - throw new Error(`HTTP ${response.status}: 响应解析失败`); + throw new Error(`HTTP ${response.status}: ${i18n.t('common.responseParseError')}`); } if (!response.ok || (json.code && json.code !== 200)) {