feat(i18n): 剩余模块全量国际化 — 51% 覆盖率 (231 文件接入 t())

批量转换 163 个文件,3204 处中文替换为 t() 调用:
- Monitor: 日志中心/告警中心/数据源/大屏/站点拨测/SNMP/中间件 全部转换
- Kubernetes: ResourceVisualEditor/NamespaceResourcePage/拓扑/事件 全部转换
- Deploy: 流水线/发布/凭证/RBAC 全部转换
- Server/Cloud/Agent/Task/Layout/UI: 全部转换
- 翻译词典扩展至 6474 行 (22 namespaces, 5000+ keys)
- tsc 编译零错误
This commit is contained in:
attacker committed 2026-07-03 01:51:57 +08:00
1 parent 78c27037e3
commit ecec73989b
166 files changed
+6925 -2800

No files matched your search

@@ -8,6 +8,7 @@ import { Search, Server, Network, Loader2, Check } from 'lucide-react';
import { cn } from '@/lib/utils';
import { serverApi, kubernetesApi } from '@/api';
import { getPublicApiBase } from '@/utils/request';
import { useTranslation } from 'react-i18next';
export interface DeployTargetValue {
deployTarget: 'ssh' | 'k8s';
@@ -49,6 +50,7 @@ interface DeploymentItem {
// 发布目标选择:SSH 关联主机 / K8s 关联 Deployment // Logan.Li
export function DeployTargetFields({ value, onChange, requireTarget = true }: DeployTargetFieldsProps) {
const { t } = useTranslation();
const [servers, setServers] = useState<ServerItem[]>([]);
const [clusters, setClusters] = useState<ClusterItem[]>([]);
const [deployments, setDeployments] = useState<DeploymentItem[]>([]);
@@ -148,8 +150,8 @@ export function DeployTargetFields({ value, onChange, requireTarget = true }: De
<div className="space-y-3">
<div className="flex gap-1 p-1 rounded-lg bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)]">
{([
{ key: 'ssh' as const, label: '主机发布', icon: Server },
{ key: 'k8s' as const, label: 'Kubernetes 发布', icon: Network },
{ key: 'ssh' as const, label: t('deploy.deploytargetfields.secf819'), icon: Server },
{ key: 'k8s' as const, label: t('deploy.deploytargetfields.s7ff062'), icon: Network },
]).map((item) => {
const active = value.deployTarget === item.key;
const Icon = item.icon;
@@ -199,7 +201,7 @@ export function DeployTargetFields({ value, onChange, requireTarget = true }: De
<Input
value={serverSearch}
onChange={(e) => setServerSearch(e.target.value)}
placeholder="搜索主机名或 IP"
placeholder=t('deploy.deploytargetfields.sc76249')
className="pl-8 h-8 text-xs dg-input"
/>
</div>
@@ -209,7 +211,7 @@ export function DeployTargetFields({ value, onChange, requireTarget = true }: De
<Loader2 className="h-4 w-4 animate-spin mr-1.5" />加载中
</div>
) : filteredServers.length === 0 ? (
<p className="text-xs text-[var(--dg-text-muted)] text-center py-8">暂无可用主机</p>
<p className="text-xs text-[var(--dg-text-muted)] text-center py-8">{t('deploy.deploytargetfields.sb42401')}</p>
) : (
<div className="p-1.5 space-y-1">
{filteredServers.map((srv) => {
@@ -241,10 +243,10 @@ export function DeployTargetFields({ value, onChange, requireTarget = true }: De
</div>
)}
</ScrollArea>
<p className="text-[10px] text-[var(--dg-text-muted)]">构建完成后 SCP 上传 jar/tar.gz 到远程目录并执行部署命令</p>
<p className="text-[10px] text-[var(--dg-text-muted)]">{t('deploy.deploytargetfields.sb2b6db')}</p>
<div className="grid grid-cols-2 gap-2">
<div className="space-y-1">
<Label className="text-xs">远程目录</Label>
<Label className="text-xs">{t('deploy.deploytargetfields.s5ca05a')}</Label>
<Input
value={value.deployRemotePath}
onChange={(e) => onChange({ deployRemotePath: e.target.value })}
@@ -253,7 +255,7 @@ export function DeployTargetFields({ value, onChange, requireTarget = true }: De
/>
</div>
<div className="space-y-1">
<Label className="text-xs">部署命令</Label>
<Label className="text-xs">{t('deploy.deploytargetfields.s65b20b')}</Label>
<Input
value={value.deployScript}
onChange={(e) => onChange({ deployScript: e.target.value })}
@@ -280,10 +282,10 @@ export function DeployTargetFields({ value, onChange, requireTarget = true }: De
})}
>
<SelectTrigger className="h-8 text-xs dg-input">
<SelectValue placeholder="选择集群" />
<SelectValue placeholder=t('k8s.topology.selectCluster') />
</SelectTrigger>
<SelectContent>
<SelectItem value="__none">请选择</SelectItem>
<SelectItem value="__none">{t('common.selectPlaceholder')}</SelectItem>
{clusters.map((c) => (
<SelectItem key={c.id} value={String(c.id)}>{c.name}</SelectItem>
))}
@@ -291,11 +293,11 @@ export function DeployTargetFields({ value, onChange, requireTarget = true }: De
</Select>
</div>
<div className="space-y-1">
<Label className="text-xs">已选 Deployment</Label>
<Label className="text-xs">{t('deploy.deploytargetfields.s806e4e')}</Label>
<Input
readOnly
value={value.k8sDeployment ? `${value.k8sNamespace}/${value.k8sDeployment}` : ''}
placeholder="从下方列表选择"
placeholder=t('deploy.deploytargetfields.sbb1671')
className="h-8 text-xs dg-input font-mono"
/>
</div>
@@ -307,7 +309,7 @@ export function DeployTargetFields({ value, onChange, requireTarget = true }: De
<Input
value={depSearch}
onChange={(e) => setDepSearch(e.target.value)}
placeholder="搜索 Deployment 或命名空间"
placeholder=t('deploy.deploytargetfields.saa98b2')
className="pl-8 h-8 text-xs dg-input"
/>
</div>
@@ -317,7 +319,7 @@ export function DeployTargetFields({ value, onChange, requireTarget = true }: De
<Loader2 className="h-4 w-4 animate-spin mr-1.5" />加载 Deployment
</div>
) : filteredDeployments.length === 0 ? (
<p className="text-xs text-[var(--dg-text-muted)] text-center py-8">暂无 Deployment</p>
<p className="text-xs text-[var(--dg-text-muted)] text-center py-8">{t('deploy.deploytargetfields.s5689d3')}</p>
) : (
<div className="p-1.5 space-y-1">
{filteredDeployments.map((dep) => {
@@ -348,11 +350,11 @@ export function DeployTargetFields({ value, onChange, requireTarget = true }: De
)}
</ScrollArea>
<div className="space-y-1">
<Label className="text-xs">容器名 <span className="text-[var(--dg-text-muted)]">(多容器时填写)</span></Label>
<Label className="text-xs">{t('kubernetes.pod.containerName')} <span className="text-[var(--dg-text-muted)]">{t('deploy.deploytargetfields.s7f5a1e')}</span></Label>
<Input
value={value.k8sContainerName}
onChange={(e) => onChange({ k8sContainerName: e.target.value })}
placeholder="默认首个容器"
placeholder=t('deploy.deploytargetfields.s389076')
className="h-8 text-xs font-mono dg-input"
/>
</div>