refactor(i18n): U43 深度残余硬编码中文 UI 文本清零 — 17 文件 ~40 处→0

趋势标签(上升/下降/平稳) + K8s 卡片标题(Pod级别/安全上下文/实例/详情) + data-table 默认值(搜索/暂无数据) + Deployment 编辑器标签(数据卷/挂载/只读写/manifest提示/镜像拉取凭证) + HostSettings 4 个命名空间描述 + 7 个 K8s 页面刷新按钮 + 资源编辑器新建/编辑 + Agent 执行命令描述 + 账单保存成功 toast + 容量预警标题

新增 common 30 语义化翻译键, zh/en 7898→7928 对齐
tsc -b=0, npm build✓ (16.55s), ESLint=0/43/any=0, go build=0, 17/17 测试通过
This commit is contained in:
attacker committed 2026-07-14 05:27:49 +08:00
1 parent c6e0d6ca57
commit 39a4432f79
26 files changed
+117 -62

No files matched your search

@@ -303,7 +303,7 @@ export function AgentMonitor() {
{t("agent.agentmonitortsx.s8h9i0j1k")}
</DialogTitle>
<DialogDescription className="dg-text-secondary">
在 {cmdHost} 上执行命令
{t('common.executeOn', { host: cmdHost })}
</DialogDescription>
</DialogHeader>
@@ -102,7 +102,7 @@ export function HostDetailDialog({
<div className="flex items-center justify-between mb-2">
<span className="text-sm font-medium text-[var(--dg-text-primary)] flex items-center gap-1.5">
<Activity className="h-4 w-4 dg-text-blue" />
指标趋势
{i18n.t('common.metricTrend')}
</span>
<Select value={String(hours)} onValueChange={(v) => setHours(Number(v))}>
<SelectTrigger size="sm" className="h-7 w-28 dg-input text-[var(--dg-text-secondary)] text-xs">
@@ -158,7 +158,7 @@ export function HostDetailDialog({
<div>
<span className="text-sm font-medium text-[var(--dg-text-primary)] flex items-center gap-1.5 mb-2">
<Network className="h-4 w-4 dg-text-blue" />
端口发现 ({ports.length})
{i18n.t('common.portDiscovery', { count: ports.length })}
</span>
{ports.length === 0 ? (
<p className="text-xs dg-text-muted"> {i18n.t('agent.hostDetailDialog.noPortData')} </p>
@@ -181,10 +181,10 @@ export function HostDetailDialog({
className="bg-blue-600 hover:bg-blue-700 text-white"
>
<Terminal className="h-4 w-4 mr-1.5" />
远程命令
{i18n.t('common.remoteCommand')}
</Button>
<Button variant="outline" onClick={onClose} className="border-[var(--dg-border)] text-[var(--dg-text-secondary)]">
关闭
{i18n.t('common.close')}
</Button>
</DialogFooter>
</DialogContent>
@@ -207,7 +207,7 @@ export function AIPredictiveAnalytics() {
<div className="flex items-center gap-1">
{getTrendIcon(prediction.trend)}
<span className={`text-sm ${trendColorClass(prediction.trend)}`}>
{prediction.trend === 'up' ? '上升' : prediction.trend === 'down' ? '下降' : '平稳'}
{prediction.trend === 'up' ? t('common.trendUp') : prediction.trend === 'down' ? t('common.trendDown') : t('common.trendStable')}
</span>
</div>
</div>
@@ -42,7 +42,7 @@ export function PredictiveCapacityTab({
<div className="flex items-center justify-between">
<CardTitle className="text-[var(--dg-text-primary)] flex items-center gap-2">
<HardDrive className="h-5 w-5 dg-text-yellow" />
容量规划预警
{t('aiops.capacity.warningTitle')}
</CardTitle>
{!loading && forecasts.length > 0 && (
<Button
@@ -57,7 +57,7 @@ export function PredictiveCapacityTab({
) : (
<Sparkles className="h-3.5 w-3.5 mr-1" />
)}
AI 深度解读
{t('aiops.capacity.aiInsight')}
</Button>
)}
</div>
@@ -156,7 +156,7 @@ export function PredictiveCostTab({
<div className="flex items-center gap-1 mt-1 text-xs">
{getTrendIcon(summary.trend)}
<span className={trendColorClass(summary.trend)}>
{summary.trend === 'up' ? '上升' : summary.trend === 'down' ? '下降' : '平稳'}
{summary.trend === 'up' ? t('common.trendUp') : summary.trend === 'down' ? t('common.trendDown') : t('common.trendStable')}
</span>
<span className="dg-text-muted ml-1">{t('aiops.predictivecost.s5o6p7q8r', { pct: summary.confidence })}</span>
</div>
@@ -198,7 +198,7 @@ export function PredictiveCostTab({
<div className="flex items-center gap-1 text-sm">
{getTrendIcon(dim.trend)}
<span className={trendColorClass(dim.trend)}>
{dim.trend === 'up' ? '上升' : dim.trend === 'down' ? '下降' : '平稳'}
{dim.trend === 'up' ? t('common.trendUp') : dim.trend === 'down' ? t('common.trendDown') : t('common.trendStable')}
</span>
</div>
</div>
@@ -278,8 +278,8 @@ export function PredictiveCostTab({
</Badge>
</div>
<p className="text-sm dg-text-secondary mt-2">
当前 {formatCurrency(risk.current)} / 阈值 {formatCurrency(risk.threshold)}
,预测 {formatCurrency(risk.predicted)}
{t('aiops.capacity.currentThreshold', { current: formatCurrency(risk.current), threshold: formatCurrency(risk.threshold) })}
{t('aiops.capacity.predictedLabel', { predicted: formatCurrency(risk.predicted) })}
</p>
<div className="flex items-center gap-4 mt-2 text-xs dg-text-muted">
<span>{risk.timeframe}</span>
@@ -80,7 +80,7 @@ export function BillingRecordDialog({ open, onOpenChange, editingRecord, onSucce
}
onOpenChange(false);
onSuccess();
toast('保存成功');
toast(i18n.t("common.saveSuccess"));
} catch (e) {
toast.error(i18n.t('kubernetes.msg.saveFailed'), { description: (e as JsonData).message });
} finally {
@@ -71,7 +71,7 @@ export function BillingRuleDialog({ open, onOpenChange, editingRule, onSuccess }
}
onOpenChange(false);
onSuccess();
toast('保存成功');
toast(i18n.t("common.saveSuccess"));
} catch (e) {
toast.error(i18n.t('kubernetes.msg.saveFailed'), { description: (e as JsonData).message });
} finally {
@@ -97,9 +97,7 @@ export default function CapacityPage() {
</SelectContent>
</Select>
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={loadCapacity} disabled={loading}>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />
刷新
</Button>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />{i18n.t('common.refresh')}</Button>
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={exportCSV}>
<Download className="h-4 w-4 mr-1" />
CSV
@@ -99,9 +99,7 @@ export default function ClusterOverviewPage() {
) : undefined}
actions={(
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={loadData} disabled={loading}>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />
刷新
</Button>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />{i18n.t('common.refresh')}</Button>
)}
>
{/* 节点列表 // Logan.Li */}
@@ -188,7 +186,7 @@ export default function ClusterOverviewPage() {
<Boxes className="h-4 w-4 text-[var(--dg-green)]" />{i18n.t("common.namespaceLabel")}
</h2>
<Link to={`/kubernetes/${clusterCode}/namespaces`} className="text-sm text-[var(--dg-blue)] hover:text-[var(--dg-blue)] transition-colors flex items-center gap-1">
管理全部 <ChevronRight className="h-3 w-3" />
{i18n.t('common.manageAll')} <ChevronRight className="h-3 w-3" />
</Link>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
@@ -123,7 +123,7 @@ export function DeploymentEditContainers({ clusterCode, namespace, deploymentNam
return (
<Card className="dg-card">
<CardContent className="p-8 text-center dg-text-muted">
未获取到 manifest 数据,请使用 YAML 编辑模式直接修改。
{i18n.t('common.noManifestHint')}
</CardContent>
</Card>
);
@@ -136,7 +136,7 @@ export function DeploymentEditContainers({ clusterCode, namespace, deploymentNam
<CardHeader className="pb-3">
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
<KeyRound className="h-4 w-4 dg-text-yellow" />
镜像拉取凭证 (imagePullSecrets)
{i18n.t('common.imagePullSecrets')}
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-muted text-[10px]">{i18n.t('k8s.podLevel')}</Badge>
</CardTitle>
</CardHeader>
@@ -196,7 +196,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
<div>
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
<Database className="h-4 w-4 dg-text-green" />
数据卷
{i18n.t('common.volumeDefinition')}
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary">{entries.length}</Badge>
</CardTitle>
<p className="text-[11px] dg-text-muted mt-1"> {i18n.t('kubernetes.storage.volumeDesc')} </p>
@@ -210,7 +210,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
{entries.length === 0 ? (
<div className="text-center py-10 dg-text-muted text-sm border border-dashed border-[var(--dg-border)] rounded-lg">
<Database className="h-8 w-8 mx-auto mb-2 dg-text-muted" />
未配置数据卷,点击「添加数据卷」开始
{i18n.t('common.noVolumeHint')}
</div>
) : entries.map((entry, i) => {
const vol = entry.volume;
@@ -282,7 +282,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
<div className="flex items-center justify-between gap-2">
<p className="text-[11px] dg-text-muted flex items-center gap-1.5">
<Container className="h-3.5 w-3.5 dg-text-blue" />
将上述数据卷挂载到容器
{i18n.t('common.mountToContainers')}
</p>
<Button size="sm" variant="ghost" className="h-6 px-2 text-[11px] dg-text-secondary hover:text-[var(--dg-text-primary)]" onClick={() => addMount(i)}>
<Plus className="h-3 w-3 mr-0.5" />{i18n.t("common.addMount")}
@@ -302,11 +302,11 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
<div className="flex items-center gap-1 bg-[var(--dg-bg-tertiary)] rounded-lg p-0.5 border border-[var(--dg-border)]">
<button type="button" onClick={() => updateMount(i, mi, { readOnly: true })}
className={`px-2.5 py-1 rounded text-xs font-medium transition-all ${mount.readOnly ? 'bg-amber-500/20 text-amber-300' : 'dg-text-muted hover:text-[var(--dg-text-secondary)]'}`}>
只读
{i18n.t('common.readOnly')}
</button>
<button type="button" onClick={() => updateMount(i, mi, { readOnly: false })}
className={`px-2.5 py-1 rounded text-xs font-medium transition-all ${!mount.readOnly ? 'bg-blue-500/20 text-blue-300' : 'dg-text-muted hover:text-[var(--dg-text-secondary)]'}`}>
读写
{i18n.t('common.readWrite')}
</button>
</div>
<Input
@@ -221,9 +221,7 @@ export default function EventsPage() {
</SelectContent>
</Select>
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={() => { loadEvents(); loadSummary(); }} disabled={loading}>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />
刷新
</Button>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />{i18n.t('common.refresh')}</Button>
</>
)}
>
@@ -101,9 +101,7 @@ export function KubernetesNodes() {
</SelectContent>
</Select>
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={loadNodes} disabled={loading}>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />
刷新
</Button>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />{i18n.t('common.refresh')}</Button>
</>
)}
>
@@ -137,9 +137,7 @@ export default function NamespaceManagementPage() {
actions={(
<>
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={loadData} disabled={loading}>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />
刷新
</Button>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />{i18n.t('common.refresh')}</Button>
<Dialog open={createOpen} onOpenChange={setCreateOpen}>
<DialogTrigger asChild>
<Button size="sm" className="dg-btn-primary">
@@ -199,9 +199,7 @@ export default function NamespaceResourcePage() {
<SelectContent className="max-h-[300px]">{namespaces.map((ns) => <SelectItem key={ns} value={ns}>{ns}</SelectItem>)}</SelectContent>
</Select>
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={loadData} disabled={loading}>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />
刷新
</Button>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />{i18n.t('common.refresh')}</Button>
{BULK_EXPORT_TYPES.includes(type) && (
<>
<Button variant="outline" size="sm" className="dg-btn-secondary text-xs" onClick={handleExportCSV} title={i18n.t('k8s.nsResourcePage.exportCsv')}>
@@ -37,7 +37,7 @@ export function PodDetailDialog({ pod, onClose }: PodDetailDialogProps) {
<div className="flex items-center justify-between px-5 py-4 border-b border-[var(--dg-border)]">
<h3 className="text-base font-semibold text-[var(--dg-text-primary)] flex items-center gap-2">
<Container className="h-4 w-4 text-[var(--dg-blue)]" />
Pod 详情
{i18n.t('common.podDetail')}
</h3>
<button className="text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)]" onClick={onClose}>✕</button>
</div>
@@ -115,9 +115,7 @@ export default function PodMetricsPage() {
</SelectContent>
</Select>
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={loadMetrics} disabled={loading}>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />
刷新
</Button>
<RefreshCw className={`h-4 w-4 mr-1 ${loading ? 'animate-spin' : ''}`} />{i18n.t('common.refresh')}</Button>
</>
)}
>
@@ -182,7 +182,7 @@ export function ResourceVisualEditor({ clusterCode, namespace, resource, name, o
<MetaIcon className={`h-5 w-5 shrink-0 ${meta.color}`} />
<div className="min-w-0">
<h2 className="text-lg font-bold text-[var(--dg-text-primary)] truncate">
{isCreate ? `新建 ${meta.title}` : `${meta.title} 编辑`}
{isCreate ? i18n.t('common.createNew') + ' ' + meta.title : meta.title + ' ' + i18n.t('common.edit')}
</h2>
<p
className="text-xs text-[var(--dg-text-muted)] truncate"
@@ -32,22 +32,22 @@ export function HostSettingsCard({
<label className="flex items-center gap-2 text-xs text-[var(--dg-text-secondary)] cursor-pointer">
<input type="checkbox" checked={hostNetwork} onChange={e => onHostNetworkChange(e.target.checked)}
className="accent-blue-500" />
hostNetwork(共享主机网络命名空间)
{i18n.t('common.hostNetworkDesc')}
</label>
<label className="flex items-center gap-2 text-xs text-[var(--dg-text-secondary)] cursor-pointer">
<input type="checkbox" checked={hostIPC} onChange={e => onHostIPCChange(e.target.checked)}
className="accent-blue-500" />
hostIPC(共享主机 IPC 命名空间)
{i18n.t('common.hostIPCDesk')}
</label>
<label className="flex items-center gap-2 text-xs text-[var(--dg-text-secondary)] cursor-pointer">
<input type="checkbox" checked={hostPID} onChange={e => onHostPIDChange(e.target.checked)}
className="accent-blue-500" />
hostPID(共享主机 PID 命名空间)
{i18n.t('common.hostPIDDesk')}
</label>
<label className="flex items-center gap-2 text-xs text-[var(--dg-text-secondary)] cursor-pointer">
<input type="checkbox" checked={shareProcessNamespace} onChange={e => onShareProcessNamespaceChange(e.target.checked)}
className="accent-blue-500" />
shareProcessNamespace(共享进程命名空间)
{i18n.t('common.shareProcessNamespaceDesc')}
</label>
</CardContent>
</Card>
@@ -1,6 +1,7 @@
// PodMiscCard.tsx — Pod 级别杂项设置卡片 (Q21 提取)
// dnsPolicy / restartPolicy / schedulerName / terminationGracePeriodSeconds / serviceAccountName
import { Settings } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
@@ -25,11 +26,12 @@ export function PodMiscCard({
terminationGracePeriodSeconds, onTerminationGracePeriodSecondsChange,
serviceAccountName, onServiceAccountNameChange,
}: PodMiscCardProps) {
const { t } = useTranslation();
return (
<Card className="dg-card">
<CardHeader className="pb-3">
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
<Settings className="h-4 w-4 dg-text-secondary" />Pod 级别
<Settings className="h-4 w-4 dg-text-secondary" />{t('common.podLevel')}
</CardTitle>
</CardHeader>
<CardContent className="pt-0 grid grid-cols-2 gap-3">
@@ -1,5 +1,6 @@
// PodSecurityCard.tsx — Pod 安全上下文 (securityContext) 卡片 (Q21 提取)
import { Shield } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
@@ -21,11 +22,12 @@ export function PodSecurityCard({
podRunAsGroup, onPodRunAsGroupChange,
podRunAsNonRoot, onPodRunAsNonRootChange,
}: PodSecurityCardProps) {
const { t } = useTranslation();
return (
<Card className="dg-card">
<CardHeader className="pb-3">
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
<Shield className="h-4 w-4 text-rose-400" />Pod 安全上下文 (securityContext)
<Shield className="h-4 w-4 text-rose-400" />{t('common.podSecurityContext')}
</CardTitle>
</CardHeader>
<CardContent className="pt-0 grid grid-cols-2 gap-3">
@@ -23,7 +23,7 @@ export function PodInstancesTable({
<Card className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
<CardHeader className="pb-3">
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
<Activity className="h-4 w-4 text-[var(--dg-green)]" />Pod 实例 ({pods.length})
<Activity className="h-4 w-4 text-[var(--dg-green)]" />{i18n.t('common.podInstances', { count: pods.length })}
</CardTitle>
</CardHeader>
<CardContent className="p-0">
+8 -4
View File
@@ -22,6 +22,7 @@
* ```
*/
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import {
Table,
TableBody,
@@ -224,7 +225,7 @@ export function DataTable<T = Record<string, unknown>>(
data,
rowKey,
searchable = false,
searchPlaceholder = '搜索...',
searchPlaceholder = undefined,
searchKeys,
sortable: globalSortable = false,
pagination: enablePagination = false,
@@ -237,7 +238,7 @@ export function DataTable<T = Record<string, unknown>>(
exportFilename = 'export.csv',
columnToggle = false,
loading = false,
emptyText = '暂无数据',
emptyText = undefined,
emptyRender,
onRowClick,
rowClassName,
@@ -247,6 +248,9 @@ export function DataTable<T = Record<string, unknown>>(
toolbarExtra,
} = props;
const { t } = useTranslation();
const effectiveSearchPlaceholder = searchPlaceholder ?? t('common.searchPlaceholder');
const effectiveEmptyText = emptyText ?? t('common.noData');
// ── Search state ──
const [searchTerm, setSearchTerm] = React.useState('');
@@ -405,7 +409,7 @@ export function DataTable<T = Record<string, unknown>>(
type="text"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder={searchPlaceholder}
placeholder={effectiveSearchPlaceholder}
className="pl-9 h-9 w-56 bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)] placeholder:text-[var(--dg-text-muted)]"
/>
</div>
@@ -532,7 +536,7 @@ export function DataTable<T = Record<string, unknown>>(
colSpan={visibleColumns.length + (selectable ? 1 : 0)}
className="text-center text-[var(--dg-text-muted)] py-16"
>
{emptyRender ? emptyRender() : emptyText}
{emptyRender ? emptyRender() : effectiveEmptyText}
</TableCell>
</TableRow>
) : (
+33 -3
View File
@@ -636,7 +636,33 @@
"last1Hour": "Last 1 hour",
"currentHost": "Current host: {{host}}",
"minutes30": "30 min",
"hours2": "2 hours"
"hours2": "2 hours",
"trendUp": "Up",
"trendDown": "Down",
"trendStable": "Stable",
"executeOn": "Execute command on {{host}}",
"podLevel": "Pod Level",
"podSecurityContext": "Pod Security Context",
"hostNetworkDesc": "hostNetwork (share host network namespace)",
"hostIPCDesk": "hostIPC (share host IPC namespace)",
"hostPIDDesk": "hostPID (share host PID namespace)",
"shareProcessNamespaceDesc": "shareProcessNamespace (share process namespace)",
"podInstances": "Pod Instances ({{count}})",
"podDetail": "Pod Details",
"metricTrend": "Metric Trends",
"portDiscovery": "Port Discovery ({{count}})",
"remoteCommand": "Remote Command",
"searchPlaceholder": "Search...",
"imagePullSecrets": "Image Pull Secrets",
"noManifestHint": "No manifest data available. Please use YAML edit mode to modify directly.",
"volumeDefinition": "Volumes",
"noVolumeHint": "No volumes configured. Click \"Add Volume\" to start.",
"mountToContainers": "Mount volumes to containers",
"readOnly": "Read Only",
"readWrite": "Read Write",
"manageAll": "Manage All",
"createNew": "Create New",
"saveSuccess": "Saved successfully"
},
"menu": {
"aiAgentCli": "Agent CLI",
@@ -3713,7 +3739,8 @@
"kubectlTerminalDesc": "Kubernetes cluster command-line terminal",
"podLevel": "Pod Level",
"podNameLabel": "Pod Name",
"podManagePolicy": "Pod Management Policy"
"podManagePolicy": "Pod Management Policy",
"uploadFile": "Upload"
},
"monitor": {
"acknowledge": "Acknowledge",
@@ -8021,7 +8048,10 @@
"expectedToReach": "Expected to",
"days": "days",
"afterReachThreshold": "until threshold reached",
"aiSuggestion": "AI Suggestion"
"aiSuggestion": "AI Suggestion",
"warningTitle": "Capacity Planning Alerts",
"currentThreshold": "Current {{current}} / Threshold {{threshold}}",
"predictedLabel": ", Predicted {{predicted}}"
},
"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",
+33 -3
View File
@@ -636,7 +636,33 @@
"last1Hour": "最近 1 小时",
"currentHost": "当前主机: {{host}}",
"minutes30": "30分钟",
"hours2": "2小时"
"hours2": "2小时",
"trendUp": "上升",
"trendDown": "下降",
"trendStable": "平稳",
"executeOn": "在 {{host}} 上执行命令",
"podLevel": "Pod 级别",
"podSecurityContext": "Pod 安全上下文 (securityContext)",
"hostNetworkDesc": "hostNetwork(共享主机网络命名空间)",
"hostIPCDesk": "hostIPC(共享主机 IPC 命名空间)",
"hostPIDDesk": "hostPID(共享主机 PID 命名空间)",
"shareProcessNamespaceDesc": "shareProcessNamespace(共享进程命名空间)",
"podInstances": "Pod 实例 ({{count}})",
"podDetail": "Pod 详情",
"metricTrend": "指标趋势",
"portDiscovery": "端口发现 ({{count}})",
"remoteCommand": "远程命令",
"searchPlaceholder": "搜索...",
"imagePullSecrets": "镜像拉取凭证 (imagePullSecrets)",
"noManifestHint": "未获取到 manifest 数据,请使用 YAML 编辑模式直接修改。",
"volumeDefinition": "数据卷",
"noVolumeHint": "未配置数据卷,点击「添加数据卷」开始",
"mountToContainers": "将上述数据卷挂载到容器",
"readOnly": "只读",
"readWrite": "读写",
"manageAll": "管理全部",
"createNew": "新建",
"saveSuccess": "保存成功"
},
"menu": {
"aiAgentCli": "Agent CLI",
@@ -3713,7 +3739,8 @@
"kubectlTerminalDesc": "Kubernetes 集群命令行终端",
"podLevel": "Pod 级别",
"podNameLabel": "Pod 名称",
"podManagePolicy": "Pod 管理策略"
"podManagePolicy": "Pod 管理策略",
"uploadFile": "上传"
},
"monitor": {
"acknowledge": "确认告警",
@@ -8021,7 +8048,10 @@
"expectedToReach": "预计",
"days": "天",
"afterReachThreshold": "后达到阈值",
"aiSuggestion": "AI建议"
"aiSuggestion": "AI建议",
"warningTitle": "容量规划预警",
"currentThreshold": "当前 {{current}} / 阈值 {{threshold}}",
"predictedLabel": ",预测 {{predicted}}"
},
"capacityPlanPrompt": "根据以下主机资源使用数据,提供成本优化和容量规划建议(识别闲置/过载主机,给出缩容/扩容建议)",
"capacityPlanning": "容量规划",