feat(i18n): 增量国际化迁移 — deploy/kubernetes/monitor/task 全模块 + 补全 28 缺失翻译键

迁移范围:
- deploy 模块 (PipelineEditor/PipelineDetailDialog/PipelineFormDialog/PipelineRunDialog/ReleaseCreateDialog/ReleaseDetailDialog/ReleaseManager/ToolConfigTab/JobRoleCreateDialog 等 14 文件)
- kubernetes 模块 (YamlEditorToolbar/DeploymentHpaTab/DeploymentLogsTab/DeploymentPodsTab/DnsHostSection/SchedulingSection/EventsTab/HPACronHPATab/HistoryTab/PodsTab/ServicesTab/ActionModals 等 12 文件)
- monitor 模块 (AlertEventsTab/AlertCenterDetail/DatasourcePage/LogAlertBell/LogCenter/LogCenterArchBanner/StatChartPanel/LogRoleCreateDialog 等 8 文件)
- task 模块 (CronJobStatsPanel/CronJobTable/CronJobViewDialog/ExecutionHistoryDialog 4 文件)
- layout (PageEmpty/PageLoading 2 文件)
- site-monitor/snmp-monitor 模块 (6 文件)

翻译键: 3975 → 4003 (+28 缺失键补全), 22 命名空间, zh-CN/en-US 完全对齐
新增命名空间: agent/aiops/cloud/kubernetes/monitor/pipeline/rbac/system/task/ui

验证: go build✅ tsc -b=0 npm build✅ (20.78s) 17/17 集成测试通过
This commit is contained in:
attacker committed 2026-07-02 12:39:36 +08:00
1 parent eddf01dd79
commit 63e4c220d4
59 files changed
+6713 -641

No files matched your search

@@ -1,4 +1,5 @@
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
@@ -50,40 +51,41 @@ export function JobRoleCreateDialog({
onDescriptionChange,
onSubmit,
}: JobRoleCreateDialogProps) {
const { t } = useTranslation();
const preview = useMemo(() => matchPipelines(pattern, pipelines), [pattern, pipelines]);
const patternHint = useMemo(() => {
if (!pattern.trim()) return '输入正则,匹配流水线 code 或 Job 名称';
if (!pattern.trim()) return t('rbac.jobRole.patternHint.empty');
try {
// eslint-disable-next-line no-new
new RegExp(pattern);
return preview.length > 0 ? `命中 ${preview.length} 个发布任务` : '无匹配任务';
return preview.length > 0 ? t('rbac.jobRole.patternHint.matched', { count: preview.length }) : t('rbac.jobRole.patternHint.noMatch');
} catch {
return '正则语法错误';
return t('rbac.jobRole.patternHint.syntaxError');
}
}, [pattern, preview.length]);
}, [pattern, preview.length, t]);
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-md bg-[var(--dg-bg-primary)] border-[var(--dg-border)]">
<DialogHeader>
<DialogTitle>新建 Job 权限</DialogTitle>
<DialogTitle>{t('rbac.jobRole.newTitle')}</DialogTitle>
<DialogDescription className="text-[var(--dg-text-muted)]">
按正则匹配流水线 code 或 Job 名称,分配 owner / editor / viewer 权限
{t('rbac.jobRole.desc')}
</DialogDescription>
</DialogHeader>
<div className="space-y-3">
<div className="grid grid-cols-2 gap-2">
<div className="space-y-1">
<Label className="text-xs">名称</Label>
<Input value={name} onChange={(e) => onNameChange(e.target.value)} placeholder="后端发布" className="h-8 text-sm dg-input" />
<Label className="text-xs">{t('rbac.jobRole.label.name')}</Label>
<Input value={name} onChange={(e) => onNameChange(e.target.value)} placeholder={t('rbac.jobRole.placeholder.name')} className="h-8 text-sm dg-input" />
</div>
<div className="space-y-1">
<Label className="text-xs">标识</Label>
<Input value={code} onChange={(e) => onCodeChange(e.target.value)} placeholder="backend-jobs" className="h-8 text-sm font-mono dg-input" />
<Label className="text-xs">{t('rbac.jobRole.label.code')}</Label>
<Input value={code} onChange={(e) => onCodeChange(e.target.value)} placeholder={t('rbac.jobRole.placeholder.code')} className="h-8 text-sm font-mono dg-input" />
</div>
</div>
<div className="space-y-1">
<Label className="text-xs">匹配正则</Label>
<Label className="text-xs">{t('rbac.jobRole.label.pattern')}</Label>
<Input
value={pattern}
onChange={(e) => onPatternChange(e.target.value)}
@@ -93,26 +95,26 @@ export function JobRoleCreateDialog({
<p className="text-[10px] text-[var(--dg-text-muted)]">{patternHint}</p>
</div>
<div className="space-y-1">
<Label className="text-xs">权限级别</Label>
<Label className="text-xs">{t('rbac.jobRole.label.roleLevel')}</Label>
<Select value={role} onValueChange={onRoleChange}>
<SelectTrigger className="h-8 text-sm dg-input"><SelectValue /></SelectTrigger>
<SelectContent>
<SelectItem value="owner">拥有者 — 配置 + 执行 + 授权</SelectItem>
<SelectItem value="editor">编辑者 — 配置 + 执行</SelectItem>
<SelectItem value="viewer">查看者 — 只读</SelectItem>
<SelectItem value="owner">{t('rbac.jobRole.role.owner')}</SelectItem>
<SelectItem value="editor">{t('rbac.jobRole.role.editor')}</SelectItem>
<SelectItem value="viewer">{t('rbac.jobRole.role.viewer')}</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-1">
<Label className="text-xs">说明</Label>
<Input value={description} onChange={(e) => onDescriptionChange(e.target.value)} placeholder="可选" className="h-8 text-sm dg-input" />
<Label className="text-xs">{t('rbac.jobRole.label.description')}</Label>
<Input value={description} onChange={(e) => onDescriptionChange(e.target.value)} placeholder={t('rbac.jobRole.placeholder.description')} className="h-8 text-sm dg-input" />
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => onOpenChange(false)}>取消</Button>
<Button variant="outline" onClick={() => onOpenChange(false)}>{t('rbac.jobRole.cancel')}</Button>
<Button onClick={onSubmit} disabled={saving}>
{saving ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : <Save className="h-4 w-4 mr-1" />}
创建
{t('rbac.jobRole.create')}
</Button>
</DialogFooter>
</DialogContent>