feat(i18n): 全量中英文国际化改造
- 翻译 en-US.json 中 1006 条未翻译的中文条目为英文 - 提取 30+ 组件文件的硬编码中文到 locale JSON - 新增 900+ 翻译键覆盖所有业务模块: - Layout (Sidebar, Header, Breadcrumb) - Server (ServerForm, CloudServerImport, WebShell, RdpTools) - Deploy (ReleaseManager, PipelineCreate, AppRelease) - Kubernetes (DeploymentEdit, PodExec, PodLogs, ResourceEditor) - Monitor (UnifiedQueryPanel, AlertCenter, Prometheus/Grafana Dashboard) - AIOps (predictUtils, PredictiveCostTab, AIPredictive) - System (useLdapManagement, AgentMonitor, AgentWizard) - tsc --noEmit 类型检查通过
This commit is contained in:
1 parent
76ec9387f0
commit
a9513c2056
44 files changed
+4342
-1792
No files matched your search
@@ -41,15 +41,15 @@ interface PipelineCreateDialogProps {
|
||||
const PRESETS = [
|
||||
{
|
||||
key: 'ssh',
|
||||
label: '主机发布',
|
||||
desc: 'SCP 上传构建产物到关联主机',
|
||||
label: t('deploy.presetHost'),
|
||||
desc: t('deploy.presetHostDesc'),
|
||||
stages: ['checkout', 'build', 'deploy'],
|
||||
deployTarget: 'ssh' as const,
|
||||
},
|
||||
{
|
||||
key: 'k8s',
|
||||
label: 'Kubernetes 发布',
|
||||
desc: '镜像打包后 CI 更新 Deployment',
|
||||
label: t('deploy.presetK8s'),
|
||||
desc: t('deploy.presetK8sDesc'),
|
||||
stages: ['checkout', 'build', 'image', 'deploy'],
|
||||
deployTarget: 'k8s' as const,
|
||||
},
|
||||
@@ -153,7 +153,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
|
||||
const validateStep1 = () => {
|
||||
if (!newName.trim()) {
|
||||
toast.error('请输入流水线名称');
|
||||
toast.error(t('deploy.enterPipelineName'));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -170,11 +170,11 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
}
|
||||
if (selectedStages.includes('deploy')) {
|
||||
if (deployTarget.deployTarget === 'ssh' && deployTarget.serverIds.length === 0) {
|
||||
toast.error('主机发布需至少关联一台主机');
|
||||
toast.error(t('deploy.needHost'));
|
||||
return false;
|
||||
}
|
||||
if (deployTarget.deployTarget === 'k8s' && (!deployTarget.k8sClusterId || !deployTarget.k8sDeployment)) {
|
||||
toast.error('Kubernetes 发布需选择集群与 Deployment');
|
||||
toast.error(t('deploy.needK8s'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -241,9 +241,9 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
<Dialog open={open} onOpenChange={(v) => { if (!v) resetForm(); onOpenChange(v); }}>
|
||||
<DialogContent className="max-w-lg max-h-[88vh] overflow-y-auto bg-[var(--dg-bg-primary)] border-[var(--dg-border)]">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-[var(--dg-text-primary)]">新建流水线</DialogTitle>
|
||||
<DialogTitle className="text-[var(--dg-text-primary)]">{t('deploy.newPipelineTitle')}</DialogTitle>
|
||||
<DialogDescription className="text-[var(--dg-text-muted)]">
|
||||
选择发布方式,关联主机或 Kubernetes Deployment,创建后可继续编辑阶段脚本
|
||||
{t('deploy.newPipelineDesc')}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
@@ -257,7 +257,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
step === 1 ? 'bg-[var(--dg-bg-hover)] text-[var(--dg-text-primary)]' : 'text-[var(--dg-text-muted)]',
|
||||
)}
|
||||
>
|
||||
1. 基础
|
||||
{t('deploy.step1')}
|
||||
</button>
|
||||
<span className="text-[var(--dg-border)]">/</span>
|
||||
<button
|
||||
@@ -268,7 +268,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
step === 2 ? 'bg-[var(--dg-bg-hover)] text-[var(--dg-text-primary)]' : 'text-[var(--dg-text-muted)]',
|
||||
)}
|
||||
>
|
||||
2. 代码与发布
|
||||
{t('deploy.step2')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -294,35 +294,35 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">名称 <span className="text-[var(--dg-red)]">*</span></Label>
|
||||
<Label className="text-xs">{t('deploy.pipeName')} <span className="text-[var(--dg-red)]">*</span></Label>
|
||||
<Input
|
||||
value={newName}
|
||||
onChange={(e) => setNewName(e.target.value)}
|
||||
placeholder="例如 demo-api"
|
||||
placeholder={t('deploy.pipeNamePlaceholder')}
|
||||
className="h-9 dg-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">描述</Label>
|
||||
<Label className="text-xs">{t('deploy.pipeDesc')}</Label>
|
||||
<Textarea
|
||||
value={newDesc}
|
||||
onChange={(e) => setNewDesc(e.target.value)}
|
||||
placeholder="可选"
|
||||
placeholder={t('deploy.pipeDescPlaceholder')}
|
||||
rows={2}
|
||||
className="dg-input text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">环境分组</Label>
|
||||
<Label className="text-xs">{t('deploy.envGroup')}</Label>
|
||||
<Select
|
||||
value={String(newEnvironmentId)}
|
||||
onValueChange={(v) => setNewEnvironmentId(v === '__none' ? '' : v)}
|
||||
>
|
||||
<SelectTrigger className="h-9 dg-input"><SelectValue placeholder="选择环境" /></SelectTrigger>
|
||||
<SelectTrigger className="h-9 dg-input"><SelectValue placeholder={t('deploy.selectEnv')} /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="__none">不指定</SelectItem>
|
||||
<SelectItem value="__none">{t('deploy.notSpecified')}</SelectItem>
|
||||
{environments.map((env) => (
|
||||
<SelectItem key={env.id as number} value={String(env.id)}>
|
||||
{String(env.display_name)}
|
||||
@@ -348,7 +348,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">
|
||||
Git 仓库 {selectedStages.includes('checkout') && <span className="text-[var(--dg-red)]">*</span>}
|
||||
{t('deploy.gitRepo')} {selectedStages.includes('checkout') && <span className="text-[var(--dg-red)]">*</span>}
|
||||
</Label>
|
||||
<Input
|
||||
value={newSource}
|
||||
@@ -358,18 +358,18 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">分支</Label>
|
||||
<Label className="text-xs">{t('deploy.pipeBranch')}</Label>
|
||||
<Input value={newBranch} onChange={(e) => setNewBranch(e.target.value)} className="h-8 text-xs dg-input" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">Git 凭证</Label>
|
||||
<Label className="text-xs">{t('deploy.gitCredential')}</Label>
|
||||
<Select value={String(newGitCredentialId)} onValueChange={(v) => setNewGitCredentialId(v === '__none' ? '' : v)}>
|
||||
<SelectTrigger className="h-8 text-xs dg-input"><SelectValue placeholder="选择凭证" /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="__none">不关联</SelectItem>
|
||||
<SelectItem value="__none">{t('deploy.notLinked')}</SelectItem>
|
||||
{gitCredentials.map((c) => (
|
||||
<SelectItem key={c.id as number} value={String(c.id)}>
|
||||
<span className="flex items-center gap-1"><Globe className="h-3 w-3" />{String(c.name)}</span>
|
||||
@@ -380,7 +380,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
</div>
|
||||
{selectedStages.includes('image') && (
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">镜像凭证 <span className="text-[var(--dg-red)]">*</span></Label>
|
||||
<Label className="text-xs">{t('deploy.imageCredential')} <span className="text-[var(--dg-red)]">*</span></Label>
|
||||
<Select value={String(newRegistryCredentialId)} onValueChange={(v) => setNewRegistryCredentialId(v === '__none' ? '' : v)}>
|
||||
<SelectTrigger className="h-8 text-xs dg-input"><SelectValue placeholder="Docker 凭证" /></SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -398,7 +398,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
|
||||
{deployTarget.deployTarget === 'k8s' && (
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">Dockerfile 路径</Label>
|
||||
<Label className="text-xs">{t('deploy.dockerfilePath')}</Label>
|
||||
<Input
|
||||
value={newDockerfile}
|
||||
onChange={(e) => setNewDockerfile(e.target.value)}
|
||||
@@ -409,7 +409,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
)}
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">CI 阶段</Label>
|
||||
<Label className="text-xs">{t('deploy.ciStages')}</Label>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{STAGE_DEFS.map((def) => {
|
||||
const active = selectedStages.includes(def.key);
|
||||
@@ -441,17 +441,17 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
className="flex items-center gap-1.5 text-xs text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)]"
|
||||
>
|
||||
<Settings2 className="h-3.5 w-3.5" />
|
||||
高级设置
|
||||
{t('deploy.advancedSettings')}
|
||||
<ChevronDown className={cn('h-3.5 w-3.5 transition-transform', advancedOpen && 'rotate-180')} />
|
||||
</button>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent className="mt-3 space-y-3 pt-3 border-t border-[var(--dg-border)]">
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">构建节点</Label>
|
||||
<Label className="text-xs">{t('deploy.buildNode')}</Label>
|
||||
<Select value={buildNodeId || '__auto'} onValueChange={(v) => setBuildNodeId(v === '__auto' ? '' : v)}>
|
||||
<SelectTrigger className="h-8 text-xs dg-input"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="__auto">自动调度(Master 优先)</SelectItem>
|
||||
<SelectItem value="__auto">{t('deploy.autoSchedule')}</SelectItem>
|
||||
{buildNodes.map((n) => (
|
||||
<SelectItem key={n.id} value={String(n.id)}>
|
||||
{n.name} ({n.running_count || 0}/{n.max_executors})
|
||||
@@ -465,13 +465,13 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
<Input value={newJobName} onChange={(e) => setNewJobName(e.target.value)} className="h-8 text-xs font-mono dg-input" />
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">触发方式</Label>
|
||||
<Label className="text-xs">{t('deploy.triggerMethod')}</Label>
|
||||
<Select value={newTriggerMode} onValueChange={setNewTriggerMode}>
|
||||
<SelectTrigger className="h-8 text-xs dg-input"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="manual">手动</SelectItem>
|
||||
<SelectItem value="git_push">代码推送</SelectItem>
|
||||
<SelectItem value="cron">定时</SelectItem>
|
||||
<SelectItem value="manual">{t('deploy.triggerManual')}</SelectItem>
|
||||
<SelectItem value="git_push">{t('deploy.codePush')}</SelectItem>
|
||||
<SelectItem value="cron">{t('deploy.triggerCron')}</SelectItem>
|
||||
<SelectItem value="webhook">Webhook</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
@@ -494,7 +494,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
)}
|
||||
<div className="space-y-1.5">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-xs">环境变量</Label>
|
||||
<Label className="text-xs">{t('deploy.envVars')}</Label>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
@@ -502,7 +502,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
className="h-6 text-[10px]"
|
||||
onClick={() => setNewEnvVars([...newEnvVars, { key: '', value: '' }])}
|
||||
>
|
||||
<Plus className="h-3 w-3 mr-0.5" />添加
|
||||
<Plus className="h-3 w-3 mr-0.5" />{t('deploy.addVar')}
|
||||
</Button>
|
||||
</div>
|
||||
{newEnvVars.map((v, i) => (
|
||||
@@ -543,12 +543,12 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline
|
||||
</Collapsible>
|
||||
|
||||
<div className="flex justify-between gap-2 pt-2 border-t border-[var(--dg-border)]">
|
||||
<Button variant="ghost" onClick={() => setStep(1)}>上一步</Button>
|
||||
<Button variant="ghost" onClick={() => setStep(1)}>{t('deploy.prevStep')}</Button>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" onClick={() => onOpenChange(false)}>取消</Button>
|
||||
<Button onClick={handleCreate} disabled={saving}>
|
||||
{saving ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : <Rocket className="h-4 w-4 mr-1" />}
|
||||
{saving ? '创建中' : '创建'}
|
||||
{saving ? t('deploy.creating') : t('deploy.pipeCreate')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user