refactor(i18n): U32 全量 hash key 清理 — 151 个 hash key → 语义化键 + React Hooks 警告 53→43
- 151 个 hash-style flat key (s+hex 后缀) 全部重命名为语义化 nested key
- monitor 58 个: alertChannelDialog/alertManager/alertRulesTab/chartRangeHint/
esIndexPicker/helpers/hostMonitor/logAlertSpanel/logClusterPanel/logDingAssistant/
logQueryToolbar/logRbac/lokiLabelBrowse/metricsExplorer/middlewareMonit/
mwOverviewChart/portPolicyDialog/prometheusDashb/queryHistoryPan/savedQueriesPan/
siteMonitor/snmpMonitor/snmpOverviewChart/zabbixDashboard/zabbixDatasource
- kubernetes 42 个: deploymentBundle/deploymentEditAdvanced/deploymentEditService/
deploymentView/deploymentWorkload/eventsPage/kubernetesCluster/namespaceManage/
namespaceResource/podExecTerminal/podFileBrowser/podLogsViewer/podMetricsPage/
resourceVisualEditor/workloadViewPage
- aiops 17 个: agentCliMessage/aiAnalysisResult/analyzerHelpers/assistant/predictUtils
- agent 12 个: agentAlerts/agentMonitor/hostDetailDialog
- cloud 13 个: billingRecordDialog/billingRuleDialog/platformManager
- pipeline 6 个: buildNodesManage/deployRbac/deployTargetField
- system 3 个: auditSetting
- 58 个源文件中的 147 处 t()/i18n.t() 调用更新为语义化键路径
- 3 个命名空间冲突修复 (monitor.hostMonitor/agent.agentMonitor/aiops.aiAnalysisResult
原 string 值提升为 .title 子键)
- React Hooks 警告修复 (53→43, -10):
- exhaustive-deps 4→0: useMemo/useCallback 添加 t 到 deps 数组
- preserve-manual-memoization 5→0: 变量遮蔽修复 (filter(t)→filter(tg))
- 1 个冗余 eslint-disable 指令移除 (CronJobManager)
- zh/en 7480=7480 完全对齐, 0 个 hash key 残留
- tsc -b=0, npm build✓ (17.59s), ESLint errors=0/warnings=43/any=0
- go build=0, 17/17 集成测试通过, Docker healthy
This commit is contained in:
1 parent
4f2d279865
commit
ff426d908b
63 files changed
+674
-477
No files matched your search
@@ -121,7 +121,7 @@ export function AlertChannelDialog({
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="dg-input max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-[var(--dg-text-primary)]"> {i18n.t('monitor.alertchanneldia.s976ad48f')} </DialogTitle>
|
||||
<DialogTitle className="text-[var(--dg-text-primary)]"> {i18n.t('monitor.alertChannelDialog.title')} </DialogTitle>
|
||||
<DialogDescription className="dg-text-muted">
|
||||
管理告警通知渠道(钉钉/企业微信/邮件/短信/Webhook),配置后可在告警规则中引用
|
||||
</DialogDescription>
|
||||
@@ -176,7 +176,7 @@ export function AlertChannelDialog({
|
||||
{ch.test_status === 'success' ? (
|
||||
<span className="text-[11px] dg-text-green"> {i18n.t('monitor.alertChannels.testPassed')} </span>
|
||||
) : (
|
||||
<span className="text-[11px] dg-text-muted"> {i18n.t('monitor.alertchanneldia.s8c852a4c')} </span>
|
||||
<span className="text-[11px] dg-text-muted"> {i18n.t('monitor.alertChannelDialog.notTested')} </span>
|
||||
)}
|
||||
<div className="flex items-center gap-1" onClick={(e) => e.stopPropagation()}>
|
||||
<Button
|
||||
@@ -247,7 +247,7 @@ export function AlertChannelDialog({
|
||||
onCheckedChange={(v) => setChannelForm({ ...channelForm, enabled: v })}
|
||||
className="data-[state=checked]:bg-emerald-600"
|
||||
/>
|
||||
<Label className="dg-text-secondary text-xs"> {i18n.t('monitor.alertchanneldia.sbdab1c59')} </Label>
|
||||
<Label className="dg-text-secondary text-xs"> {i18n.t('monitor.alertChannelDialog.enableChannel')} </Label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -118,8 +118,8 @@ export function AlertManager() {
|
||||
>
|
||||
<Card className="dg-card">
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-[var(--dg-text-primary)]"> {i18n.t('monitor.alertmanagertsx.s358b05d0')} </CardTitle>
|
||||
<CardDescription className="dg-text-muted"> {i18n.t('monitor.alertmanagertsx.s615fa6cb')} </CardDescription>
|
||||
<CardTitle className="text-[var(--dg-text-primary)]"> {i18n.t('monitor.alertManager.trendTitle')} </CardTitle>
|
||||
<CardDescription className="dg-text-muted"> {i18n.t('monitor.alertManager.last24hStats')} </CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="h-[200px]">
|
||||
|
||||
@@ -135,7 +135,7 @@ export function AlertRulesTab({
|
||||
</TableHead>
|
||||
<TableHead className="dg-text-secondary"> {i18n.t('monitor.ruleName')} </TableHead>
|
||||
<TableHead className="dg-text-secondary"> {i18n.t('monitor.dashboard.custom.datasource')} </TableHead>
|
||||
<TableHead className="dg-text-secondary"> {i18n.t('monitor.alertrulestabts.s65939ccd')} </TableHead>
|
||||
<TableHead className="dg-text-secondary"> {i18n.t('monitor.alertRulesTab.condition')} </TableHead>
|
||||
<TableHead className="dg-text-secondary"> {i18n.t('kubernetes.event.eventLevel')} </TableHead>
|
||||
<TableHead className="dg-text-secondary"> {i18n.t('monitor.alertDuration')} </TableHead>
|
||||
<TableHead className="dg-text-secondary"> {i18n.t('monitor.notificationChannel')} </TableHead>
|
||||
|
||||
@@ -42,7 +42,7 @@ export function EsIndexPicker({ datasourceId, value, onChange }: Props) {
|
||||
onClick={() => setOpen(!open)}
|
||||
className="h-10 px-2 text-xs rounded flex items-center gap-1 font-mono min-w-[150px] max-w-[220px]"
|
||||
style={{ background: 'var(--dg-bg-tertiary)', border: '1px solid var(--dg-border)', color: 'var(--dg-text-primary)' }}
|
||||
title={i18n.t('monitor.esindexpickerts.sa0eff8ea')}
|
||||
title={i18n.t('monitor.esIndexPicker.selectHint')}
|
||||
>
|
||||
<span className="truncate flex-1 text-left">{value || i18n.t('monitor.selectIndex')}</span>
|
||||
{loading ? <Loader2 className="h-3 w-3 animate-spin shrink-0" /> : <ChevronDown className="h-3 w-3 shrink-0" />}
|
||||
@@ -60,7 +60,7 @@ export function EsIndexPicker({ datasourceId, value, onChange }: Props) {
|
||||
<input
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
placeholder={i18n.t('monitor.esindexpickerts.s9ae0c004')}
|
||||
placeholder={i18n.t('monitor.esIndexPicker.searchPlaceholder')}
|
||||
className="flex-1 bg-transparent text-xs outline-none font-mono"
|
||||
style={{ color: 'var(--dg-text-primary)' }}
|
||||
/>
|
||||
@@ -90,7 +90,7 @@ export function EsIndexPicker({ datasourceId, value, onChange }: Props) {
|
||||
</button>
|
||||
))}
|
||||
{!loading && filtered.length === 0 && (
|
||||
<p className="text-xs px-2 py-3 text-center" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.esindexpickerts.saf5cc132')} </p>
|
||||
<p className="text-xs px-2 py-3 text-center" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.esIndexPicker.noMatch')} </p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -58,7 +58,7 @@ export function LogAlertsPanel() {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-sm text-[var(--dg-text-muted)]"> {i18n.t('monitor.logalertspanelt.s5bc514d8')} </p>
|
||||
<p className="text-sm text-[var(--dg-text-muted)]"> {i18n.t('monitor.logAlertSpanel.desc')} </p>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" size="sm" onClick={load} disabled={loading}>
|
||||
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />刷新
|
||||
|
||||
@@ -42,7 +42,7 @@ export function LogClusterPanel({ clusters }: Props) {
|
||||
{/* 头部 */}
|
||||
<div className="flex items-center justify-between px-4 py-2" style={{ background: 'var(--dg-bg-tertiary)', borderBottom: '1px solid var(--dg-border)' }}>
|
||||
<span className="text-xs" style={{ color: 'var(--dg-text-muted)' }}>共 {clusters.length} 个聚类模式,总计 {total.toLocaleString()} 条日志</span>
|
||||
<span className="text-[10px]" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.logclusterpanel.s38112792')} </span>
|
||||
<span className="text-[10px]" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.logClusterPanel.desc')} </span>
|
||||
</div>
|
||||
|
||||
{/* 聚类列表 */}
|
||||
@@ -91,7 +91,7 @@ export function LogClusterPanel({ clusters }: Props) {
|
||||
{/* 展开详情 */}
|
||||
{expanded[i] && (
|
||||
<div className="px-4 py-3 animate-fade-in" style={{ background: 'var(--dg-bg-primary)', paddingLeft: '48px' }}>
|
||||
<p className="text-[10px] mb-1" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.logclusterpanel.se909e426')} </p>
|
||||
<p className="text-[10px] mb-1" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.logClusterPanel.sampleLog')} </p>
|
||||
<div className="p-2 rounded text-[11px] font-mono break-all" style={{ background: 'var(--dg-bg-tertiary)', color: 'var(--dg-text-secondary)' }}>
|
||||
{cluster.sample}
|
||||
</div>
|
||||
|
||||
@@ -20,10 +20,10 @@ export function LogDingAssistant({ onRuleCreated }: { onRuleCreated?: () => void
|
||||
size="lg"
|
||||
className="h-12 rounded-full shadow-lg bg-gradient-to-r from-amber-500 to-orange-500 hover:from-amber-400 hover:to-orange-400 text-white gap-2 px-5"
|
||||
onClick={() => setOpen(true)}
|
||||
title={i18n.t('monitor.logdingassistan.s26b79b6b')}
|
||||
title={i18n.t('monitor.logDingAssistant.addAlert')}
|
||||
>
|
||||
<Sparkles className="h-5 w-5" />
|
||||
<span className="font-medium"> {i18n.t('monitor.logdingassistan.s1a663141')} </span>
|
||||
<span className="font-medium"> {i18n.t('monitor.logDingAssistant.ding')} </span>
|
||||
</Button>
|
||||
</div>
|
||||
<LogAlertFromQueryDialog
|
||||
|
||||
@@ -122,7 +122,7 @@ export function LogQueryToolbar({
|
||||
</button>
|
||||
|
||||
<div className="flex items-center gap-1 ml-1">
|
||||
<span className="text-[10px]" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.logquerytoolbar.s8b76adb2')} </span>
|
||||
<span className="text-[10px]" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.logQueryToolbar.goTo')} </span>
|
||||
<input
|
||||
type="number"
|
||||
value={jumpPage}
|
||||
|
||||
@@ -217,7 +217,7 @@ export default function LogRBAC() {
|
||||
icon={<Shield className="h-10 w-10" />}
|
||||
title={i18n.t('monitor.logRbac.noPolicies')}
|
||||
description={i18n.t('monitor.logRbac.noPoliciesDesc')}
|
||||
action={<Button onClick={() => setCreateOpen(true)}><Plus className="h-4 w-4 mr-1" /> {i18n.t('monitor.logrbactsx.s6058845c')} </Button>}
|
||||
action={<Button onClick={() => setCreateOpen(true)}><Plus className="h-4 w-4 mr-1" /> {i18n.t('monitor.logRbac.newPermission')} </Button>}
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
@@ -319,7 +319,7 @@ export default function LogRBAC() {
|
||||
</div>
|
||||
{selectedUser ? (
|
||||
assignments.length === 0 ? (
|
||||
<p className="text-xs text-[var(--dg-text-muted)]"> {i18n.t('monitor.logrbactsx.sa120fc78')} </p>
|
||||
<p className="text-xs text-[var(--dg-text-muted)]"> {i18n.t('monitor.logRbac.noPermissionAssigned')} </p>
|
||||
) : (
|
||||
<div className="space-y-1.5">
|
||||
{assignments.map((a) => {
|
||||
@@ -340,7 +340,7 @@ export default function LogRBAC() {
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
<p className="text-xs text-[var(--dg-text-muted)] flex items-center gap-1"><Users className="w-3.5 h-3.5" /> {i18n.t('monitor.logrbactsx.s9be00c95')} </p>
|
||||
<p className="text-xs text-[var(--dg-text-muted)] flex items-center gap-1"><Users className="w-3.5 h-3.5" /> {i18n.t('monitor.logRbac.selectUserHint')} </p>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -373,7 +373,7 @@ export default function LogRBAC() {
|
||||
</Badge>
|
||||
))}
|
||||
{previewRoleId !== null && previewMatches.length === 0 && (
|
||||
<span className="text-xs text-[var(--dg-text-muted)]"> {i18n.t('monitor.logrbactsx.s64096f4d')} </span>
|
||||
<span className="text-xs text-[var(--dg-text-muted)]"> {i18n.t('monitor.logRbac.noMatchHint')} </span>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
@@ -98,7 +98,7 @@ export function LokiLabelBrowser({ datasourceId, query, timeRange, onQueryChange
|
||||
))}
|
||||
</div>
|
||||
<div className="flex-1 overflow-y-auto max-h-48 p-1">
|
||||
{!activeLabel && <p className="text-[11px] px-2 py-4 text-center" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.lokilabelbrowse.s088b9477')} </p>}
|
||||
{!activeLabel && <p className="text-[11px] px-2 py-4 text-center" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.lokiLabelBrowse.selectLabelHint')} </p>}
|
||||
{loadingValues && <div className="flex justify-center py-6"><Loader2 className="h-4 w-4 animate-spin" /></div>}
|
||||
{!loadingValues && activeLabel && values.map((v) => (
|
||||
<button
|
||||
|
||||
@@ -90,8 +90,8 @@ export function QueryHistoryPanel({ visible, onClose, onSelect, onCreateAlert }:
|
||||
{history.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center h-48 gap-2">
|
||||
<Clock className="h-8 w-8" style={{ color: 'var(--dg-border)' }} />
|
||||
<span className="text-xs" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.queryhistorypan.s1e60bc17')} </span>
|
||||
<span className="text-[10px]" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.queryhistorypan.s3895021f')} </span>
|
||||
<span className="text-xs" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.queryHistoryPan.emptyHistory')} </span>
|
||||
<span className="text-[10px]" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.queryHistoryPan.autoRecordHint')} </span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="divide-y" style={{ borderColor: 'var(--dg-border)' }}>
|
||||
@@ -139,7 +139,7 @@ export function QueryHistoryPanel({ visible, onClose, onSelect, onCreateAlert }:
|
||||
onClick={() => onSelect(item)}
|
||||
className="h-6 w-6 flex items-center justify-center rounded transition-colors"
|
||||
style={{ background: 'var(--dg-bg-tertiary)', color: 'var(--dg-green)' }}
|
||||
title={i18n.t('monitor.queryhistorypan.s4fb36a61')}
|
||||
title={i18n.t('monitor.queryHistoryPan.runQuery')}
|
||||
>
|
||||
<Play className="h-3 w-3" />
|
||||
</button>
|
||||
|
||||
@@ -43,7 +43,7 @@ export function SavedQueriesPanel({ visible, onClose, onSelect }: Props) {
|
||||
</div>
|
||||
<div className="flex-1 overflow-y-auto p-3 space-y-2">
|
||||
{items.length === 0 ? (
|
||||
<p className="text-xs text-center py-8" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.savedqueriespan.s9c8dc62b')} </p>
|
||||
<p className="text-xs text-center py-8" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('monitor.savedQueriesPan.emptySaved')} </p>
|
||||
) : items.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
|
||||
Reference in new issue
Block a user