refactor(i18n): U42 残余硬编码中文彻底清零 — 33文件54处→0, zh/en 7847→7898对齐
全量 JSX children + toast/confirm + sr-only 描述硬编码中文清零: - Kubernetes模块: UpdateStrategyCard maxSurge/maxUnavailable说明 + IngressCreateForm host域名/Service端口 + ServiceCreateForm 端口配置/selector + DeploymentEditService 无selector/个关联/暂无Service/Ingress + ClusterOverviewPage 核 + KubernetesClusterDialog 已配置 + KubectlTerminal/ResourceVisualEditor/CreateHPADialog/DeploymentEditContainers/Storage + PodInstancesTable/UpdateStrategySelectorCards - AI模块: PredictiveCapacityTab AI深度解读/紧急/警告/7天预测/预计N天 + PredictiveCostTab AI深度解读 + event-handler.ts 高危操作确认toast - Deploy模块: DeployCredentials 启用/禁用 + DeployRBAC 删除角色confirm + WorkspaceTermDialog + CredFormDialog Windows用户 - Monitor模块: AlertRulesTab 删除confirm/分钟 + PrometheusDatasourceManager/LogDatasourcePage 删除confirm + QueryHistoryPanel 条 - System模块: ServerFileBrowser/TerminalDialog/RdpAuditViewer sr-only + SystemManager/CredentialManager/TerminalSessionsTab 删除confirm + SecuritySettingsTab 30分钟/2小时 - Task模块: CronJobViewDialog 次 新增 61 翻译键 (k8s.editAdvanced 6 + k8s.editService 11 + k8s.cluster 2 + k8s.misc 9 + aiops.capacity 9 + aiops.cost 1 + aiops.cli 2 + deploy 4 + monitor 5 + system 10 + task 1 + common 2) tsc -b=0, npm build✓ (17.71s), ESLint=0/43/any=0, go build=0, 17/17 测试通过
This commit is contained in:
1 parent
a7838aaf65
commit
c6e0d6ca57
35 files changed
+217
-104
No files matched your search
@@ -76,7 +76,7 @@ export function PredictiveCapacityTab({
|
||||
<div className="p-4 rounded-lg border border-purple-500/30 bg-purple-500/5">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Sparkles className="h-4 w-4 dg-text-purple" />
|
||||
<span className="text-sm font-medium text-purple-300">AI 深度解读</span>
|
||||
<span className="text-sm font-medium text-purple-300">{t('aiops.capacity.aiInsight')}</span>
|
||||
</div>
|
||||
{looksLikeMarkdown(insight) ? (
|
||||
<AgentMarkdown content={insight} />
|
||||
@@ -103,24 +103,24 @@ export function PredictiveCapacityTab({
|
||||
}
|
||||
>
|
||||
{forecast.daysUntilThreshold <= 7
|
||||
? '紧急'
|
||||
? t('aiops.capacity.urgency')
|
||||
: forecast.daysUntilThreshold <= 14
|
||||
? '警告'
|
||||
: '正常'}
|
||||
? t('aiops.capacity.warning')
|
||||
: t('common.normal')}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<div className="flex items-center justify-between text-sm mb-1">
|
||||
<span className="dg-text-secondary">7天使用率预测</span>
|
||||
<span className="dg-text-secondary">{t('aiops.capacity.sevenDayForecast')}</span>
|
||||
<span className="dg-text-secondary">
|
||||
{forecast.daysUntilThreshold >= 999 ? (
|
||||
'增长平缓,暂无触顶风险'
|
||||
t('aiops.capacity.noRisk')
|
||||
) : (
|
||||
<>
|
||||
预计{' '}
|
||||
<span className="dg-text-yellow font-medium">{forecast.daysUntilThreshold}天</span>{' '}
|
||||
后达到阈值
|
||||
{t('aiops.capacity.expectedToReach')}{' '}
|
||||
<span className="dg-text-yellow font-medium">{forecast.daysUntilThreshold}{t('aiops.capacity.days')}</span>{' '}
|
||||
{t('aiops.capacity.afterReachThreshold')}
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
@@ -147,7 +147,7 @@ export function PredictiveCapacityTab({
|
||||
<div className="flex items-start gap-2">
|
||||
<Zap className="h-4 w-4 dg-text-green mt-0.5" />
|
||||
<div>
|
||||
<span className="text-sm dg-text-secondary">AI建议:</span>
|
||||
<span className="text-sm dg-text-secondary">{t('aiops.capacity.aiSuggestion')}:</span>
|
||||
<p className="text-sm text-[var(--dg-text-secondary)] mt-1">{forecast.recommendation}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -108,7 +108,7 @@ export function PredictiveCostTab({
|
||||
<div className="p-4 rounded-lg border border-purple-500/30 bg-purple-500/5">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Sparkles className="h-4 w-4 dg-text-purple" />
|
||||
<span className="text-sm font-medium text-purple-300">AI 深度解读</span>
|
||||
<span className="text-sm font-medium text-purple-300">{t('aiops.cost.aiInsight')}</span>
|
||||
</div>
|
||||
{looksLikeMarkdown(insight) ? (
|
||||
<AgentMarkdown content={insight} />
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { Dispatch, SetStateAction, RefObject } from 'react';
|
||||
import type { ChatItem } from '../AgentCLIMessages';
|
||||
import type { WsEvent } from '../agent-cli-constants';
|
||||
import type { ConfirmOptions } from '@/components/ui/confirm-dialog';
|
||||
import i18n from '@/i18n';
|
||||
|
||||
export interface WsEventHandlerDeps {
|
||||
push: (it: Omit<ChatItem, 'id'>) => void;
|
||||
@@ -31,10 +32,10 @@ export function createWsEventHandler(deps: WsEventHandlerDeps) {
|
||||
// 高危命令确认(后端驱动 → 弹框 → 回传)
|
||||
async function handleConfirm(ev: WsEvent) {
|
||||
const ok = await confirm({
|
||||
title: '⚠️ 确认执行高危操作',
|
||||
description: `工具:${ev.tool_name}\n风险:${ev.risk}\n命令:${ev.command || '(无)'}`,
|
||||
confirmText: '确认执行',
|
||||
cancelText: '拒绝',
|
||||
title: i18n.t('aiops.cli.confirmHighRiskTitle'),
|
||||
description: i18n.t('aiops.cli.confirmHighRiskDesc', { tool: ev.tool_name, risk: ev.risk, command: ev.command || '(无)' }),
|
||||
confirmText: i18n.t('common.confirm'),
|
||||
cancelText: i18n.t('common.cancel'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
wsRef.current?.send(JSON.stringify({ type: ok ? 'confirm' : 'deny', confirm_id: ev.confirm_id }));
|
||||
|
||||
@@ -312,7 +312,7 @@ export default function DeployCredentials() {
|
||||
<td className="px-3 py-2"><div className="w-6 h-6 rounded border" style={{ backgroundColor: env.color }} /></td>
|
||||
<td className="px-3 py-2 text-[var(--dg-text-secondary)]">{env.sort_order}</td>
|
||||
<td className="px-3 py-2">
|
||||
<Badge className={env.enabled ? 'bg-emerald-500/20 dg-text-green border-emerald-500/30' : 'bg-[var(--dg-bg-active)]/20 dg-text-secondary border-[var(--dg-border)]'}>{env.enabled ? '启用' : '禁用'}</Badge>
|
||||
<Badge className={env.enabled ? 'bg-emerald-500/20 dg-text-green border-emerald-500/30' : 'bg-[var(--dg-bg-active)]/20 dg-text-secondary border-[var(--dg-border)]'}>{env.enabled ? t('common.enable') : t('common.disable')}</Badge>
|
||||
</td>
|
||||
<td className="px-3 py-2 text-right">
|
||||
<div className="flex justify-end gap-1">
|
||||
|
||||
@@ -148,7 +148,7 @@ export default function DeployRBAC() {
|
||||
const handleDelete = async (role: ItemRole) => {
|
||||
const ok = await _confirm({
|
||||
title: i18n.t('deploy.rbac.policy.deletePolicy'),
|
||||
description: `确定删除「${role.name}」?将影响 ${matchCount[role.id]?.length || 0} 个发布任务`,
|
||||
description: i18n.t("deploy.rbac.deleteRoleDesc", { name: role.name, count: matchCount[role.id]?.length || 0 }),
|
||||
variant: 'destructive',
|
||||
});
|
||||
if (!ok) return;
|
||||
|
||||
@@ -156,7 +156,7 @@ export function WorkspaceTermDialog({
|
||||
)}
|
||||
style={fullscreen ? { maxWidth: '100vw', width: '100vw', height: '100vh' } : { maxWidth: '900px', width: '90vw' }}
|
||||
>
|
||||
<DialogTitle className="sr-only">Workspace 终端 #{buildNumber}</DialogTitle>
|
||||
<DialogTitle className="sr-only">{t("deploy.workspaceTerminalTitle", { num: buildNumber })}</DialogTitle>
|
||||
<DialogDescription className="sr-only">{t("common.buildTerminal")}</DialogDescription>
|
||||
<div className="flex items-center justify-between px-4 py-2 border-b border-[var(--dg-border)]">
|
||||
<div className="flex items-center gap-2 text-sm min-w-0">
|
||||
|
||||
@@ -292,7 +292,7 @@ export function CredFormDialog({ open, onClose, onSaved, editData }: CredFormDia
|
||||
{secretType === 'rdp' && (
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-[var(--dg-text-secondary)] text-xs">Windows 用户 <span className="dg-text-red">*</span></Label>
|
||||
<Label className="text-[var(--dg-text-secondary)] text-xs">{t("deploy.cred.windowsUser")} <span className="dg-text-red">*</span></Label>
|
||||
<Input value={rdpUsername} onChange={e => setRdpUsername(e.target.value)} placeholder="Administrator"
|
||||
className="bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]" />
|
||||
</div>
|
||||
|
||||
@@ -157,7 +157,7 @@ export default function ClusterOverviewPage() {
|
||||
<span className="text-[var(--dg-text-secondary)]">{cpuPct.toFixed(0)}%</span>
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-[var(--dg-text-muted)]">{cpuCores} 核</span>
|
||||
<span className="text-[var(--dg-text-muted)]">{cpuCores} {i18n.t("k8s.cluster.cpuCores", { count: cpuCores })}</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="text-xs">
|
||||
|
||||
@@ -137,7 +137,7 @@ export function DeploymentEditContainers({ clusterCode, namespace, deploymentNam
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<KeyRound className="h-4 w-4 dg-text-yellow" />
|
||||
镜像拉取凭证 (imagePullSecrets)
|
||||
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-muted text-[10px]">Pod 级别</Badge>
|
||||
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-muted text-[10px]">{i18n.t('k8s.podLevel')}</Badge>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0 space-y-2">
|
||||
|
||||
@@ -262,7 +262,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
<code key={k} className="bg-[var(--dg-bg-tertiary)] px-1.5 py-0.5 rounded text-[var(--dg-text-secondary)] text-[11px]">{k}={v}</code>
|
||||
))}
|
||||
{Object.keys(selectorLabels).length === 0 && (
|
||||
<span className="dg-text-muted italic">(无 selector)</span>
|
||||
<span className="dg-text-muted italic">{i18n.t('k8s.editService.noSelector')}</span>
|
||||
)}
|
||||
</div>
|
||||
<Button size="sm" variant="ghost" className="h-6 ml-auto text-xs dg-text-secondary" onClick={load}>
|
||||
@@ -279,7 +279,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Network className="h-4 w-4 dg-text-blue" />
|
||||
Services
|
||||
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary">{matchedSvcs.length} 个关联</Badge>
|
||||
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary">{i18n.t('k8s.editService.svcLinked', { count: matchedSvcs.length })}</Badge>
|
||||
</CardTitle>
|
||||
<Button size="sm" variant="outline" className="h-7 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs"
|
||||
onClick={() => {
|
||||
@@ -295,7 +295,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
{matchedSvcs.length === 0 && showCreate !== 'service' ? (
|
||||
<div className="text-center py-6 dg-text-muted text-sm border border-dashed border-[var(--dg-border)] rounded-lg">
|
||||
<Network className="h-8 w-8 mx-auto mb-2 dg-text-muted" />
|
||||
当前命名空间暂无关联 Service
|
||||
{i18n.t('k8s.editService.noSvcInNs')}
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
@@ -330,7 +330,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<GitBranch className="h-4 w-4 dg-text-purple" />
|
||||
Ingresses (应用路由)
|
||||
{i18n.t('k8s.editService.ingressesLabel')}
|
||||
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary">{matchedIngs.length}/{ingresses.length}</Badge>
|
||||
</CardTitle>
|
||||
<Button size="sm" variant="outline" className="h-7 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs"
|
||||
@@ -341,13 +341,13 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
<Plus className="h-3 w-3 mr-1" />{i18n.t("common.createIngress")}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs dg-text-muted mt-1">backend 指向关联 Service 的 Ingress 自动高亮</p>
|
||||
<p className="text-xs dg-text-muted mt-1">{i18n.t('k8s.editService.ingressAutoHighlight')}</p>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0">
|
||||
{ingresses.length === 0 ? (
|
||||
<div className="text-center py-6 dg-text-muted text-sm border border-dashed border-[var(--dg-border)] rounded-lg">
|
||||
<GitBranch className="h-8 w-8 mx-auto mb-2 dg-text-muted" />
|
||||
当前命名空间暂无 Ingress
|
||||
{i18n.t('k8s.editService.noIngInNs')}
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
|
||||
@@ -296,7 +296,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
onChange={(e) => updateMount(i, mi, { containerName: e.target.value })}
|
||||
className="h-8 min-w-[140px] max-w-[280px] bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded-md text-sm text-[var(--dg-text-primary)] px-2 font-medium truncate"
|
||||
>
|
||||
{containers.length === 0 && <option value="">(无容器)</option>}
|
||||
{containers.length === 0 && <option value="">{i18n.t('k8s.cluster.noContainer')}</option>}
|
||||
{containers.map((cn) => <option key={cn} value={cn}>{cn}</option>)}
|
||||
</select>
|
||||
<div className="flex items-center gap-1 bg-[var(--dg-bg-tertiary)] rounded-lg p-0.5 border border-[var(--dg-border)]">
|
||||
|
||||
@@ -161,7 +161,7 @@ export function KubectlTerminal({ open, onOpenChange, clusterId, clusterName }:
|
||||
style={fullscreen ? { maxWidth: '100vw', width: '100vw', height: '100vh' } : { maxWidth: '900px', width: '90vw' }}
|
||||
>
|
||||
<DialogTitle className="sr-only">kubectl — {clusterName}</DialogTitle>
|
||||
<DialogDescription className="sr-only">Kubernetes 集群命令行终端</DialogDescription>
|
||||
<DialogDescription className="sr-only">{i18n.t('k8s.kubectlTerminalDesc')}</DialogDescription>
|
||||
|
||||
{/* 头部 */}
|
||||
<div className="flex items-center justify-between px-4 py-2 border-b border-[var(--dg-border)]">
|
||||
|
||||
@@ -219,7 +219,7 @@ export function KubernetesClusterDialog({
|
||||
{formData.config_type === 0 ? (
|
||||
<div className="space-y-2">
|
||||
<Label className="text-[var(--dg-text-secondary)]">
|
||||
Token {hasToken && <span className="dg-text-green text-xs ml-1">✓ 已配置(留空不修改)</span>}
|
||||
Token {hasToken && <span className="dg-text-green text-xs ml-1">{i18n.t('k8s.clusterDialog.configured')}</span>}
|
||||
</Label>
|
||||
<Textarea
|
||||
value={formData.token}
|
||||
@@ -232,7 +232,7 @@ export function KubernetesClusterDialog({
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
<Label className="text-[var(--dg-text-secondary)]">
|
||||
Kubeconfig {hasKubeConfig && <span className="dg-text-green text-xs ml-1">✓ 已配置(留空不修改)</span>}
|
||||
Kubeconfig {hasKubeConfig && <span className="dg-text-green text-xs ml-1">{i18n.t('k8s.clusterDialog.configured')}</span>}
|
||||
</Label>
|
||||
<Textarea
|
||||
value={formData.kube_config}
|
||||
|
||||
@@ -203,7 +203,7 @@ export function ResourceVisualEditor({ clusterCode, namespace, resource, name, o
|
||||
<button
|
||||
className={`px-3 py-1.5 text-xs font-medium transition-colors ${mode === 'yaml' ? 'bg-blue-600 text-white' : 'bg-transparent text-[var(--dg-text-secondary)] hover:bg-[var(--dg-bg-tertiary)]'}`}
|
||||
onClick={() => { if (mode === 'visual') switchToYaml(); else setMode('yaml'); }}
|
||||
>YAML 编辑</button>
|
||||
>YAML {i18n.t('k8s.rve.yamlEditBtn')}</button>
|
||||
</div>
|
||||
<Button variant="ghost" size="icon" className="h-8 w-8 text-[var(--dg-text-secondary)]" onClick={onClose}><X className="h-4 w-4" /></Button>
|
||||
</div>
|
||||
|
||||
@@ -92,7 +92,7 @@ export function CreateHPADialog({ clusterCode, namespace, deploymentName, onCrea
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<Label className="dg-text-secondary text-sm">CPU 目标 (%)</Label>
|
||||
<Label className="dg-text-secondary text-sm">{i18n.t('k8s.hpa.cpuTarget')}</Label>
|
||||
<Input type="number" value={form.cpuPercent} min={0} max={100}
|
||||
onChange={(e) => setForm({ ...form, cpuPercent: Number(e.target.value) })}
|
||||
className="dg-input mt-1" />
|
||||
|
||||
@@ -40,23 +40,23 @@ export function UpdateStrategyCard({
|
||||
<label className="flex items-center gap-1.5 text-xs text-[var(--dg-text-secondary)] cursor-pointer">
|
||||
<input type="radio" checked={strategyType === 'RollingUpdate'} onChange={() => onStrategyTypeChange('RollingUpdate')}
|
||||
className="accent-blue-500" />
|
||||
RollingUpdate(滚动更新)
|
||||
{i18n.t('k8s.editAdvanced.rollingUpdateDesc')}
|
||||
</label>
|
||||
<label className="flex items-center gap-1.5 text-xs text-[var(--dg-text-secondary)] cursor-pointer">
|
||||
<input type="radio" checked={strategyType === 'Recreate'} onChange={() => onStrategyTypeChange('Recreate')}
|
||||
className="accent-blue-500" />
|
||||
Recreate(重建)
|
||||
{i18n.t('k8s.editAdvanced.recreateDesc')}
|
||||
</label>
|
||||
</div>
|
||||
{strategyType === 'RollingUpdate' && (
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<Label className="dg-text-muted text-xs">maxSurge(整数或百分比,超出期望副本数)</Label>
|
||||
<Label className="dg-text-muted text-xs">{i18n.t('k8s.editAdvanced.maxSurgeHint')}</Label>
|
||||
<Input value={maxSurge} onChange={e => onMaxSurgeChange(e.target.value)}
|
||||
placeholder="25%" className="h-8 mt-1 dg-input text-sm font-mono" />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="dg-text-muted text-xs">maxUnavailable(整数或百分比,不可用上限)</Label>
|
||||
<Label className="dg-text-muted text-xs">{i18n.t('k8s.editAdvanced.maxUnavailableHint')}</Label>
|
||||
<Input value={maxUnavailable} onChange={e => onMaxUnavailableChange(e.target.value)}
|
||||
placeholder="25%" className="h-8 mt-1 dg-input text-sm font-mono" />
|
||||
</div>
|
||||
@@ -74,12 +74,12 @@ export function UpdateStrategyCard({
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0 grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<Label className="dg-text-muted text-xs">revisionHistoryLimit(保留 RS 历史)</Label>
|
||||
<Label className="dg-text-muted text-xs">{i18n.t('k8s.editAdvanced.revisionHistoryLimitHint')}</Label>
|
||||
<Input type="number" value={revisionHistoryLimit} onChange={e => onRevisionHistoryLimitChange(e.target.value)}
|
||||
className="h-8 mt-1 dg-input text-sm font-mono" />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="dg-text-muted text-xs">progressDeadlineSeconds(升级超时秒数)</Label>
|
||||
<Label className="dg-text-muted text-xs">{i18n.t('k8s.editAdvanced.progressDeadlineSecondsHint')}</Label>
|
||||
<Input type="number" value={progressDeadlineSeconds} onChange={e => onProgressDeadlineSecondsChange(e.target.value)}
|
||||
className="h-8 mt-1 dg-input text-sm font-mono" />
|
||||
</div>
|
||||
|
||||
@@ -35,7 +35,7 @@ export function IngressCreateForm({ ingForm, setIngForm, deploymentName, onCance
|
||||
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="dg-text-muted text-[11px]">host (域名)</Label>
|
||||
<Label className="dg-text-muted text-[11px]">{i18n.t('k8s.editService.hostDomain')}</Label>
|
||||
<Input value={ingForm.host} onChange={e => setIngForm(s => ({ ...s, host: e.target.value }))}
|
||||
placeholder="app.example.com"
|
||||
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
|
||||
@@ -47,7 +47,7 @@ export function IngressCreateForm({ ingForm, setIngForm, deploymentName, onCance
|
||||
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="dg-text-muted text-[11px]">Service 端口</Label>
|
||||
<Label className="dg-text-muted text-[11px]">{i18n.t('k8s.editService.servicePortLabel')}</Label>
|
||||
<Input type="number" value={ingForm.svcPort} onChange={e => setIngForm(s => ({ ...s, svcPort: e.target.value }))}
|
||||
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
|
||||
</div>
|
||||
|
||||
@@ -84,7 +84,7 @@ export function ServiceCreateForm({ svcForm, setSvcForm, selectorLabels, deploym
|
||||
{/* 端口列表 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="dg-text-muted text-[11px]">
|
||||
端口配置 <span className="dg-text-muted">({svcForm.ports.length} 个端口)</span>
|
||||
{i18n.t('k8s.editService.portConfig')} <span className="dg-text-muted">({i18n.t('k8s.editService.portCount', { count: svcForm.ports.length })})</span>
|
||||
</Label>
|
||||
{svcForm.ports.map((p, i) => (
|
||||
<div key={i} className="flex items-center gap-1.5 p-2 rounded bg-[var(--dg-bg-tertiary)]/50 border border-[var(--dg-border)]/50">
|
||||
@@ -128,7 +128,7 @@ export function ServiceCreateForm({ svcForm, setSvcForm, selectorLabels, deploym
|
||||
|
||||
{/* Selector 预览 */}
|
||||
<div className="text-[10px] dg-text-muted border-t border-[var(--dg-border)]/50 pt-2">
|
||||
<span className="dg-text-muted">selector (自动检测): </span>
|
||||
<span className="dg-text-muted">{i18n.t('k8s.editService.selectorAutoDetect')} </span>
|
||||
{Object.keys(selectorLabels).length > 0 ? (
|
||||
Object.entries(selectorLabels).map(([k, v]) => (
|
||||
<code key={k} className="bg-[var(--dg-bg-tertiary)] px-1 py-0.5 rounded dg-text-secondary ml-1">{k}={v}</code>
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
} from '@/components/ui/table';
|
||||
import { Activity, Terminal, HardDrive } from 'lucide-react';
|
||||
import { statusColor } from '../k8s-yaml-utils';
|
||||
import type { JsonData } from '@/types/common';
|
||||
import i18n from '@/i18n';
|
||||
import type { JsonData } from '@/types/common';
|
||||
|
||||
export function PodInstancesTable({
|
||||
pods,
|
||||
@@ -30,7 +30,7 @@ export function PodInstancesTable({
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow className="border-[var(--dg-border)] hover:bg-transparent">
|
||||
<TableHead className="text-[var(--dg-text-secondary)]">Pod 名称</TableHead>
|
||||
<TableHead className="text-[var(--dg-text-secondary)]">{i18n.t('k8s.podNameLabel')}</TableHead>
|
||||
<TableHead className="text-[var(--dg-text-secondary)]"> {i18n.t('system.terminalStatus')} </TableHead>
|
||||
<TableHead className="text-[var(--dg-text-secondary)]"> {i18n.t('kubernetes.pod.nodeName')} </TableHead>
|
||||
<TableHead className="text-[var(--dg-text-secondary)]">Pod IP</TableHead>
|
||||
|
||||
@@ -55,7 +55,7 @@ export function UpdateStrategySelectorCards({ stats }: { stats: WorkloadStats })
|
||||
)}
|
||||
{isSts && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-[var(--dg-text-muted)]">Pod 管理策略</span>
|
||||
<span className="text-[var(--dg-text-muted)]">{i18n.t('k8s.podManagePolicy')}</span>
|
||||
<span className="text-[var(--dg-text-secondary)] font-mono">{spec.podManagementPolicy || 'OrderedReady'}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -75,7 +75,7 @@ export function AlertRulesTab({
|
||||
if (selectedIds.length === 0) return;
|
||||
const ok = await confirm({
|
||||
title: i18n.t('monitor.alertRulesTab.deleteRule'),
|
||||
description: `确定删除选中的 ${selectedIds.length} 条告警规则吗?此操作不可撤销。`,
|
||||
description: i18n.t("monitor.deleteRulesConfirmDesc", { count: selectedIds.length }),
|
||||
confirmText: i18n.t('system.terminalBatchDelete'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
@@ -194,7 +194,7 @@ export function AlertRulesTab({
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<span className="text-sm text-[var(--dg-text-secondary)]">{(rule.duration || 0) / 60}分钟</span>
|
||||
<span className="text-sm text-[var(--dg-text-secondary)]">{i18n.t("monitor.durationMinutes", { count: (rule.duration || 0) / 60 })}</span>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{renderRuleChannels(rule, notifyChannels)}
|
||||
|
||||
@@ -50,7 +50,7 @@ export default function PrometheusDatasourceManager() {
|
||||
const handleDelete = async (ds: PromDS) => {
|
||||
const ok = await _confirm({
|
||||
title: i18n.t('monitor.deleteDatasource'),
|
||||
description: `确定删除数据源「${ds.name}」吗?此操作不可撤销。`,
|
||||
description: i18n.t("monitor.deleteDatasourceConfirmDesc", { name: ds.name }),
|
||||
variant: 'destructive',
|
||||
});
|
||||
if (!ok) return;
|
||||
|
||||
@@ -48,7 +48,7 @@ export function LogDatasourcePage() {
|
||||
const handleDelete = async (ds: LogDataSource) => {
|
||||
const ok = await confirm({
|
||||
title: i18n.t('monitor.deleteDatasource'),
|
||||
description: `确认删除「${ds.name}」?`,
|
||||
description: i18n.t("monitor.deleteLogDsConfirmDesc", { name: ds.name }),
|
||||
variant: 'destructive',
|
||||
confirmText: i18n.t('kubernetes.storage.delete2'),
|
||||
});
|
||||
|
||||
@@ -131,7 +131,7 @@ export function QueryHistoryPanel({ visible, onClose, onSelect, onCreateAlert }:
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[10px]" style={{ color: 'var(--dg-text-muted)' }}>{item.timeRange}</span>
|
||||
{item.resultCount !== undefined && (
|
||||
<span className="text-[10px]" style={{ color: 'var(--dg-text-muted)' }}>{item.resultCount} 条</span>
|
||||
<span className="text-[10px]" style={{ color: 'var(--dg-text-muted)' }}>{i18n.t("monitor.queryHistory.count", { count: item.resultCount })}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
|
||||
@@ -164,7 +164,7 @@ export function ServerFileBrowser({ open, onOpenChange, serverId, serverName }:
|
||||
}
|
||||
>
|
||||
<DialogTitle className="sr-only">{i18n.t("common.fileBrowse")} — {serverName}</DialogTitle>
|
||||
<DialogDescription className="sr-only">SFTP 文件管理 · 上传 · 下载 · 删除</DialogDescription>
|
||||
<DialogDescription className="sr-only">{i18n.t("system.sftpFileDesc")}</DialogDescription>
|
||||
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between px-4 py-2.5 border-b border-[var(--dg-border)] shrink-0">
|
||||
@@ -173,7 +173,7 @@ export function ServerFileBrowser({ open, onOpenChange, serverId, serverName }:
|
||||
<span className="text-[var(--dg-text-primary)] font-medium text-sm truncate">
|
||||
{serverName}
|
||||
</span>
|
||||
<span className="text-[var(--dg-text-muted)] text-xs">· SFTP 文件管理</span>
|
||||
<span className="text-[var(--dg-text-muted)] text-xs">{i18n.t("system.sftpFileLabel")}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
|
||||
@@ -222,7 +222,7 @@ export function TerminalDialog({
|
||||
}
|
||||
>
|
||||
<DialogTitle className="sr-only">{t("common.podLogs")} - {serverName}</DialogTitle>
|
||||
<DialogDescription className="sr-only">SSH 终端连接</DialogDescription>
|
||||
<DialogDescription className="sr-only">{t("system.sshTerminalDesc")}</DialogDescription>
|
||||
{/* 终端头部 */}
|
||||
<div className="flex items-center justify-between px-4 py-2 border-b border-[var(--dg-border)]">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
|
||||
@@ -124,7 +124,7 @@ export function CredentialManager() {
|
||||
const item = credentials.find(c => c.id === id);
|
||||
const ok = await confirm({
|
||||
title: t('pipeline.deleteCred'),
|
||||
description: `确定删除「${item?.name || id}」吗?删除后无法恢复,关联的服务器将无法使用此凭据连接。`,
|
||||
description: i18n.t("system.deleteCredConfirmDesc", { name: item?.name || id }),
|
||||
confirmText: t('common.delete'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ import { cn } from '@/lib/utils';
|
||||
import { getAuthToken, getWsBase } from '@/utils/request';
|
||||
import { rdpSessionApi } from '@/api';
|
||||
import { Loader2, Maximize2, Minimize2, Pause, Play, RotateCcw, X } from 'lucide-react';
|
||||
import i18n from '@/i18n';
|
||||
|
||||
interface RdpAuditViewerProps {
|
||||
open: boolean;
|
||||
@@ -237,8 +238,8 @@ export function RdpAuditViewer({ open, onOpenChange, sessionId, mode }: RdpAudit
|
||||
)}
|
||||
style={fullscreen ? { maxWidth: '100vw', width: '100vw', height: '100vh' } : { maxWidth: '1120px', width: '94vw' }}
|
||||
>
|
||||
<DialogTitle className="sr-only">{mode === 'live' ? 'RDP 实时审计' : 'RDP 历史回放'}</DialogTitle>
|
||||
<DialogDescription className="sr-only">Windows RDP 图形会话审计查看</DialogDescription>
|
||||
<DialogTitle className="sr-only">{mode === 'live' ? i18n.t('system.rdpLiveAudit') : i18n.t('system.rdpHistoryReplay')}</DialogTitle>
|
||||
<DialogDescription className="sr-only">{i18n.t("system.rdpAuditDesc")}</DialogDescription>
|
||||
<div className="flex items-center justify-between px-4 py-2 border-b border-[var(--dg-border)]">
|
||||
<div className="text-sm font-medium text-[var(--dg-text-primary)]">
|
||||
{mode === 'live' ? 'RDP 实时审计' : `RDP 历史回放 #${sessionId || ''}`}
|
||||
|
||||
@@ -207,7 +207,7 @@ export function SystemManager() {
|
||||
const handleDelete = async (user: any) => {
|
||||
const ok = await confirm({
|
||||
title: t("system.deleteUser"),
|
||||
description: `确认删除用户「${user.nickname || user.username}」吗?`,
|
||||
description: t('system.deleteUserConfirmDesc', { name: user.nickname || user.username }),
|
||||
confirmText: t("common.delete"),
|
||||
variant: "destructive",
|
||||
});
|
||||
@@ -228,7 +228,7 @@ export function SystemManager() {
|
||||
if (selectedUserIds.length === 0) return;
|
||||
const ok = await confirm({
|
||||
title: t("system.batchDeleteUsers"),
|
||||
description: `确定删除选中的 ${selectedUserIds.length} 个用户吗?此操作不可恢复。`,
|
||||
description: t("system.batchDeleteUsersConfirmDesc", { count: selectedUserIds.length }),
|
||||
confirmText: t("system.terminalBatchDelete"),
|
||||
variant: "destructive",
|
||||
});
|
||||
|
||||
@@ -129,7 +129,7 @@ export function TerminalSessionsTab() {
|
||||
if (selected.size === 0) return;
|
||||
const ok = await confirm({
|
||||
title: t('system.terminalBatchDelete'),
|
||||
description: `确认删除选中的 ${selected.size} 条终端会话记录?`,
|
||||
description: t("system.deleteTermSessionsConfirmDesc", { count: selected.size }),
|
||||
confirmText: t('common.delete'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
|
||||
@@ -266,11 +266,11 @@ export function SecuritySettingsTab(props: SecuritySettingsTabProps) {
|
||||
<SelectItem value="15">
|
||||
{t("monitor.traceMgr.min15")}
|
||||
</SelectItem>
|
||||
<SelectItem value="30">30分钟</SelectItem>
|
||||
<SelectItem value="30">{t("common.minutes30")}</SelectItem>
|
||||
<SelectItem value="60">
|
||||
{t("monitor.traceMgr.hour1")}
|
||||
</SelectItem>
|
||||
<SelectItem value="120">2小时</SelectItem>
|
||||
<SelectItem value="120">{t("common.hours2")}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@@ -65,7 +65,7 @@ export function CronJobViewDialog({ open, onOpenChange, job }: Props) {
|
||||
</div>
|
||||
<div>
|
||||
<div className="dg-text-muted mb-0.5">{t("common.totalRun")}</div>
|
||||
<div className="text-[var(--dg-text-primary)] tabular-nums">{job.run_count ?? 0} 次</div>
|
||||
<div className="text-[var(--dg-text-primary)] tabular-nums">{t("task.cronJob.runCount", { count: job.run_count ?? 0 })}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="dg-text-muted mb-0.5">{t("common.successFail")}</div>
|
||||
|
||||
@@ -634,7 +634,9 @@
|
||||
"rdpSessionCount": "RDP sessions: {{count}}",
|
||||
"evidenceChain": "Evidence Chain",
|
||||
"last1Hour": "Last 1 hour",
|
||||
"currentHost": "Current host: {{host}}"
|
||||
"currentHost": "Current host: {{host}}",
|
||||
"minutes30": "30 min",
|
||||
"hours2": "2 hours"
|
||||
},
|
||||
"menu": {
|
||||
"aiAgentCli": "Agent CLI",
|
||||
@@ -1801,7 +1803,9 @@
|
||||
"operationFailed": "Operation failed",
|
||||
"tagsLabel": "Tags"
|
||||
},
|
||||
"sensitiveWarn": "Please keep sensitive information safe"
|
||||
"sensitiveWarn": "Please keep sensitive information safe",
|
||||
"windowsUser": "Windows User",
|
||||
"badgeDefault": "Default"
|
||||
},
|
||||
"credCol": {
|
||||
"name": "Credential Name",
|
||||
@@ -2162,7 +2166,8 @@
|
||||
"noPolicy": "No job permission policies",
|
||||
"createHint": "After creating a policy, users will automatically get access to matching pipelines via regex"
|
||||
},
|
||||
"deleteGroupDesc": "Delete \"{{name}}\"? All members and pipeline grants will be removed."
|
||||
"deleteGroupDesc": "Delete \"{{name}}\"? All members and pipeline grants will be removed.",
|
||||
"deleteRoleDesc": "Delete \"{{name}}\"? This will affect {{count}} release tasks"
|
||||
},
|
||||
"rdpPassword": "Windows Password",
|
||||
"rdpPasswordPlaceholder": "Windows login password",
|
||||
@@ -2550,7 +2555,8 @@
|
||||
"noVars": "No variables, click \"Add Variable\" to create",
|
||||
"envVar": "Environment Variables",
|
||||
"envVarOptional": "Environment Variables (optional)"
|
||||
}
|
||||
},
|
||||
"workspaceTerminalTitle": "Workspace Terminal #{{num}}"
|
||||
},
|
||||
"k8s": {
|
||||
"actionModal": {
|
||||
@@ -2606,11 +2612,13 @@
|
||||
"now": "Now",
|
||||
"allNamespaces": "All Namespaces",
|
||||
"provider": "Provider",
|
||||
"region": "Region"
|
||||
"region": "Region",
|
||||
"cpuCores": "{{count}} cores",
|
||||
"noContainer": "(no containers)"
|
||||
},
|
||||
"clusterDialog": {
|
||||
"nameHint": "Only English letters, numbers and hyphens (-) allowed. Cannot start or end with hyphen. Name will be the cluster unique identifier.",
|
||||
"configured": "Configured (leave empty to keep)",
|
||||
"configured": "✓ Configured (leave blank to keep)",
|
||||
"kubeconfigHint": "API Server address will be auto-parsed after pasting kubeconfig content",
|
||||
"cancel": "Cancel",
|
||||
"nameRule": "Only letters, digits, and hyphens (-) allowed; cannot start or end with a hyphen",
|
||||
@@ -2857,8 +2865,8 @@
|
||||
"updateStrategy": "Update Strategy",
|
||||
"rollingUpdate": "Rolling Update",
|
||||
"recreate": "Recreate",
|
||||
"maxSurgeHint": "Integer or percentage, exceeds desired replicas",
|
||||
"maxUnavailableHint": "Integer or percentage, max unavailable",
|
||||
"maxSurgeHint": "maxSurge (integer or percentage, surge above desired)",
|
||||
"maxUnavailableHint": "maxUnavailable (integer or percentage, max unavailable)",
|
||||
"historyVersions": "History Versions & Progress",
|
||||
"rsHistory": "Retain RS History",
|
||||
"upgradeTimeout": "Upgrade timeout (seconds)",
|
||||
@@ -2879,7 +2887,11 @@
|
||||
"secondsPlaceholder": "seconds",
|
||||
"maxSurge": "Max Surge",
|
||||
"maxUnavailable": "Max Unavailable",
|
||||
"strategyLabel": "Update Strategy"
|
||||
"strategyLabel": "Update Strategy",
|
||||
"rollingUpdateDesc": "RollingUpdate (Rolling)",
|
||||
"recreateDesc": "Recreate (Recreate)",
|
||||
"revisionHistoryLimitHint": "revisionHistoryLimit (RS history to retain)",
|
||||
"progressDeadlineSecondsHint": "progressDeadlineSeconds (upgrade timeout seconds)"
|
||||
},
|
||||
"editBasic": {
|
||||
"synced": "Synced",
|
||||
@@ -2960,7 +2972,7 @@
|
||||
"edit": "Edit",
|
||||
"createNew": "Create New Service",
|
||||
"portConfig": "Port Configuration",
|
||||
"portCount": "ports",
|
||||
"portCount": "{{count}} ports",
|
||||
"addCustomPort": "Add Custom Port",
|
||||
"autoDetect": "Auto Detect",
|
||||
"ingresses": "Ingresses (App Routes)",
|
||||
@@ -2968,15 +2980,22 @@
|
||||
"autoHighlight": "Ingress whose backend points to related Service is auto-highlighted",
|
||||
"noRelatedIngress": "No Ingress in current namespace",
|
||||
"createNewIngress": "Create New Ingress",
|
||||
"hostDomain": "Host (Domain)",
|
||||
"hostDomain": "host (domain)",
|
||||
"servicePort": "Service Port",
|
||||
"noSelector": "(No selector)",
|
||||
"noSelector": "(no selector)",
|
||||
"confirmDelete": "Confirm Delete",
|
||||
"deleteDesc": "This operation cannot be undone",
|
||||
"portName": "Port Name",
|
||||
"targetPort": "Target Port",
|
||||
"protocol": "Protocol",
|
||||
"serviceCreated": "Service created"
|
||||
"serviceCreated": "Service created",
|
||||
"servicePortLabel": "Service Port",
|
||||
"selectorAutoDetect": "selector (auto-detected):",
|
||||
"svcLinked": "{{count}} linked",
|
||||
"ingressAutoHighlight": "Ingresses pointing to linked Services are auto-highlighted",
|
||||
"noSvcInNs": "No linked Services in current namespace",
|
||||
"noIngInNs": "No Ingresses in current namespace",
|
||||
"ingressesLabel": "Ingresses (App Routes)"
|
||||
},
|
||||
"editStorage": {
|
||||
"volumes": "Volumes",
|
||||
@@ -3420,7 +3439,8 @@
|
||||
"commonExamples": "Common:",
|
||||
"accessModeRWO": "ReadWriteOnce (Single node read-write)",
|
||||
"accessModeROX": "ReadOnlyMany (Multi-node read-only)",
|
||||
"accessModeRWX": "ReadWriteMany (Multi-node read-write)"
|
||||
"accessModeRWX": "ReadWriteMany (Multi-node read-write)",
|
||||
"yamlEditBtn": "YAML Edit"
|
||||
},
|
||||
"scheduling": {
|
||||
"mode": {
|
||||
@@ -3689,7 +3709,11 @@
|
||||
"download": "Download",
|
||||
"copied": "Copied",
|
||||
"fetchFailed": "Failed to fetch YAML"
|
||||
}
|
||||
},
|
||||
"kubectlTerminalDesc": "Kubernetes cluster command-line terminal",
|
||||
"podLevel": "Pod Level",
|
||||
"podNameLabel": "Pod Name",
|
||||
"podManagePolicy": "Pod Management Policy"
|
||||
},
|
||||
"monitor": {
|
||||
"acknowledge": "Acknowledge",
|
||||
@@ -5294,7 +5318,14 @@
|
||||
"nextPage": "Next"
|
||||
},
|
||||
"zookeeper": "ZooKeeper",
|
||||
"deleteRuleConfirmDesc": "Delete \"{{name}}\"?"
|
||||
"deleteRuleConfirmDesc": "Delete \"{{name}}\"?",
|
||||
"deleteRulesConfirmDesc": "Delete {{count}} selected alert rules? This action cannot be undone.",
|
||||
"deleteDatasourceConfirmDesc": "Delete datasource \"{{name}}\"? This action cannot be undone.",
|
||||
"deleteLogDsConfirmDesc": "Delete \"{{name}}\"?",
|
||||
"durationMinutes": "{{count}} min",
|
||||
"queryHistory": {
|
||||
"count": "{{count}} entries"
|
||||
}
|
||||
},
|
||||
"task": {
|
||||
"cronJob": {
|
||||
@@ -5372,7 +5403,8 @@
|
||||
"batchDeleteConfirm": "Delete {{count}} selected jobs? This cannot be undone.",
|
||||
"confirmDelete": "Delete \"{{name}}\"? This cannot be undone.",
|
||||
"execDuration": "Duration: {{ms}}ms"
|
||||
}
|
||||
},
|
||||
"runCount": "{{count}} times"
|
||||
},
|
||||
"cronJobCol": {
|
||||
"task": "Task",
|
||||
@@ -7763,7 +7795,17 @@
|
||||
"liveMonitor": {
|
||||
"exitFullscreen": "Exit Fullscreen",
|
||||
"fullscreen": "Fullscreen"
|
||||
}
|
||||
},
|
||||
"rdpLiveAudit": "RDP Live Audit",
|
||||
"rdpHistoryReplay": "RDP History Replay",
|
||||
"rdpAuditDesc": "Windows RDP graphical session audit viewer",
|
||||
"sshTerminalDesc": "SSH terminal connection",
|
||||
"sftpFileDesc": "SFTP file management · upload · download · delete",
|
||||
"sftpFileLabel": "· SFTP file management",
|
||||
"deleteUserConfirmDesc": "Delete user \"{{name}}\"?",
|
||||
"batchDeleteUsersConfirmDesc": "Delete {{count}} selected users? This action cannot be undone.",
|
||||
"deleteCredConfirmDesc": "Delete \"{{name}}\"? This cannot be undone. Servers using this credential will lose connection.",
|
||||
"deleteTermSessionsConfirmDesc": "Delete {{count}} selected terminal session records?"
|
||||
},
|
||||
"aiops": {
|
||||
"activeCount": "{{count}} active",
|
||||
@@ -7966,12 +8008,20 @@
|
||||
"recDisk": "Disk space is running low. Consider expanding storage or cleaning up historical data and logs.",
|
||||
"recMonitor": "Recommend continued monitoring of resource usage trends.",
|
||||
"in24Hours": "In 24 hours",
|
||||
"noRisk": "Growth is gradual, no threshold breach risk",
|
||||
"noRisk": "Growth is gradual, no threshold risk",
|
||||
"expertPrompt": "You are an AIOps capacity planning expert. Based on the following server resource capacity forecast data, provide a comprehensive risk assessment and actionable operations recommendations:",
|
||||
"resCpu": "Server CPU Compute",
|
||||
"resMemory": "Server Memory",
|
||||
"resDisk": "Storage Disk Space",
|
||||
"summary": "- {{resource}}: Current {{current}}% → 7-day forecast {{predicted}}% (threshold {{threshold}}%), {{risk}}"
|
||||
"summary": "- {{resource}}: Current {{current}}% → 7-day forecast {{predicted}}% (threshold {{threshold}}%), {{risk}}",
|
||||
"aiInsight": "AI Deep Insight",
|
||||
"urgency": "Critical",
|
||||
"warning": "Warning",
|
||||
"sevenDayForecast": "7-Day Usage Forecast",
|
||||
"expectedToReach": "Expected to",
|
||||
"days": "days",
|
||||
"afterReachThreshold": "until threshold reached",
|
||||
"aiSuggestion": "AI Suggestion"
|
||||
},
|
||||
"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",
|
||||
@@ -8108,7 +8158,9 @@
|
||||
"hint": "Shift+Enter for new line / Enter to send",
|
||||
"stop": "Stop",
|
||||
"execute": "Run"
|
||||
}
|
||||
},
|
||||
"confirmHighRiskTitle": "⚠️ Confirm High-Risk Operation",
|
||||
"confirmHighRiskDesc": "Tool: {{tool}}\nRisk: {{risk}}\nCommand: {{command}}"
|
||||
},
|
||||
"cloudService": "Cloud Services",
|
||||
"codingPlan": "Coding Plan",
|
||||
@@ -8474,7 +8526,10 @@
|
||||
"zhipuGeneral": "Zhipu GLM (General)",
|
||||
"zhipuGetKey": "Register a Zhipu account and enable model services to get an API Key",
|
||||
"zhipuOpenPlatform": "Zhipu Open Platform",
|
||||
"reachable": "reachable"
|
||||
"reachable": "reachable",
|
||||
"cost": {
|
||||
"aiInsight": "AI Deep Insight"
|
||||
}
|
||||
},
|
||||
"breadcrumb": {
|
||||
"aiAlertAnalyzer": "Alert Analysis",
|
||||
|
||||
@@ -634,7 +634,9 @@
|
||||
"rdpSessionCount": "RDP 会话共 {{count}} 条",
|
||||
"evidenceChain": "证据链",
|
||||
"last1Hour": "最近 1 小时",
|
||||
"currentHost": "当前主机: {{host}}"
|
||||
"currentHost": "当前主机: {{host}}",
|
||||
"minutes30": "30分钟",
|
||||
"hours2": "2小时"
|
||||
},
|
||||
"menu": {
|
||||
"aiAgentCli": "Agent CLI",
|
||||
@@ -1801,7 +1803,9 @@
|
||||
"operationFailed": "操作失败",
|
||||
"tagsLabel": "标签"
|
||||
},
|
||||
"sensitiveWarn": "敏感信息请妥善保管"
|
||||
"sensitiveWarn": "敏感信息请妥善保管",
|
||||
"windowsUser": "Windows 用户",
|
||||
"badgeDefault": "默认"
|
||||
},
|
||||
"credCol": {
|
||||
"name": "凭据名称",
|
||||
@@ -2162,7 +2166,8 @@
|
||||
"noPolicy": "暂无 Job 权限策略",
|
||||
"createHint": "创建策略后,用户将按正则自动获得匹配流水线的访问权限"
|
||||
},
|
||||
"deleteGroupDesc": "确定删除「{{name}}」?所有成员和流水线授权将同时移除。"
|
||||
"deleteGroupDesc": "确定删除「{{name}}」?所有成员和流水线授权将同时移除。",
|
||||
"deleteRoleDesc": "确定删除「{{name}}」?将影响 {{count}} 个发布任务"
|
||||
},
|
||||
"rdpPassword": "Windows 密码",
|
||||
"rdpPasswordPlaceholder": "Windows 登录密码",
|
||||
@@ -2550,7 +2555,8 @@
|
||||
"noVars": "暂无变量,点击\"添加变量\"新增",
|
||||
"envVar": "环境变量",
|
||||
"envVarOptional": "环境变量 (可选)"
|
||||
}
|
||||
},
|
||||
"workspaceTerminalTitle": "Workspace 终端 #{{num}}"
|
||||
},
|
||||
"k8s": {
|
||||
"actionModal": {
|
||||
@@ -2606,11 +2612,13 @@
|
||||
"now": "现在",
|
||||
"allNamespaces": "全部命名空间",
|
||||
"provider": "提供商",
|
||||
"region": "区域"
|
||||
"region": "区域",
|
||||
"cpuCores": "{{count}} 核",
|
||||
"noContainer": "(无容器)"
|
||||
},
|
||||
"clusterDialog": {
|
||||
"nameHint": "只允许英文、数字和连字符(-),首尾不能是连字符。名称将作为集群唯一标识。",
|
||||
"configured": "已配置(留空不修改)",
|
||||
"configured": "✓ 已配置(留空不修改)",
|
||||
"kubeconfigHint": "粘贴 kubeconfig 内容后将自动解析 API Server 地址",
|
||||
"cancel": "取消",
|
||||
"nameRule": "只允许英文、数字和连字符(-),首尾不能是连字符",
|
||||
@@ -2857,8 +2865,8 @@
|
||||
"updateStrategy": "更新策略 (Strategy)",
|
||||
"rollingUpdate": "滚动更新",
|
||||
"recreate": "重建",
|
||||
"maxSurgeHint": "整数或百分比,超出期望副本数",
|
||||
"maxUnavailableHint": "整数或百分比,不可用上限",
|
||||
"maxSurgeHint": "maxSurge(整数或百分比,超出期望副本数)",
|
||||
"maxUnavailableHint": "maxUnavailable(整数或百分比,不可用上限)",
|
||||
"historyVersions": "历史版本 & 进度",
|
||||
"rsHistory": "保留 RS 历史",
|
||||
"upgradeTimeout": "升级超时秒数",
|
||||
@@ -2879,7 +2887,11 @@
|
||||
"secondsPlaceholder": "秒",
|
||||
"maxSurge": "最大超出",
|
||||
"maxUnavailable": "最大不可用",
|
||||
"strategyLabel": "更新策略"
|
||||
"strategyLabel": "更新策略",
|
||||
"rollingUpdateDesc": "RollingUpdate(滚动更新)",
|
||||
"recreateDesc": "Recreate(重建)",
|
||||
"revisionHistoryLimitHint": "revisionHistoryLimit(保留 RS 历史)",
|
||||
"progressDeadlineSecondsHint": "progressDeadlineSeconds(升级超时秒数)"
|
||||
},
|
||||
"editBasic": {
|
||||
"synced": "已同步",
|
||||
@@ -2960,7 +2972,7 @@
|
||||
"edit": "编辑",
|
||||
"createNew": "创建新 Service",
|
||||
"portConfig": "端口配置",
|
||||
"portCount": "个端口",
|
||||
"portCount": "{{count}} 个端口",
|
||||
"addCustomPort": "添加自定义端口",
|
||||
"autoDetect": "自动检测",
|
||||
"ingresses": "Ingresses (应用路由)",
|
||||
@@ -2976,7 +2988,14 @@
|
||||
"portName": "端口名称",
|
||||
"targetPort": "目标端口",
|
||||
"protocol": "协议",
|
||||
"serviceCreated": "Service 已创建"
|
||||
"serviceCreated": "Service 已创建",
|
||||
"servicePortLabel": "Service 端口",
|
||||
"selectorAutoDetect": "selector (自动检测):",
|
||||
"svcLinked": "{{count}} 个关联",
|
||||
"ingressAutoHighlight": "backend 指向关联 Service 的 Ingress 自动高亮",
|
||||
"noSvcInNs": "当前命名空间暂无关联 Service",
|
||||
"noIngInNs": "当前命名空间暂无 Ingress",
|
||||
"ingressesLabel": "Ingresses (应用路由)"
|
||||
},
|
||||
"editStorage": {
|
||||
"volumes": "数据卷",
|
||||
@@ -3420,7 +3439,8 @@
|
||||
"commonExamples": "常见:",
|
||||
"accessModeRWO": "ReadWriteOnce (单节点读写)",
|
||||
"accessModeROX": "ReadOnlyMany (多节点只读)",
|
||||
"accessModeRWX": "ReadWriteMany (多节点读写)"
|
||||
"accessModeRWX": "ReadWriteMany (多节点读写)",
|
||||
"yamlEditBtn": "YAML 编辑"
|
||||
},
|
||||
"scheduling": {
|
||||
"mode": {
|
||||
@@ -3689,7 +3709,11 @@
|
||||
"download": "下载",
|
||||
"copied": "已复制",
|
||||
"fetchFailed": "获取YAML失败"
|
||||
}
|
||||
},
|
||||
"kubectlTerminalDesc": "Kubernetes 集群命令行终端",
|
||||
"podLevel": "Pod 级别",
|
||||
"podNameLabel": "Pod 名称",
|
||||
"podManagePolicy": "Pod 管理策略"
|
||||
},
|
||||
"monitor": {
|
||||
"acknowledge": "确认告警",
|
||||
@@ -5294,7 +5318,14 @@
|
||||
"nextPage": "下一页"
|
||||
},
|
||||
"zookeeper": "ZooKeeper",
|
||||
"deleteRuleConfirmDesc": "删除「{{name}}」?"
|
||||
"deleteRuleConfirmDesc": "删除「{{name}}」?",
|
||||
"deleteRulesConfirmDesc": "确定删除选中的 {{count}} 条告警规则吗?此操作不可撤销。",
|
||||
"deleteDatasourceConfirmDesc": "确定删除数据源「{{name}}」吗?此操作不可撤销。",
|
||||
"deleteLogDsConfirmDesc": "确认删除「{{name}}」?",
|
||||
"durationMinutes": "{{count}}分钟",
|
||||
"queryHistory": {
|
||||
"count": "{{count}} 条"
|
||||
}
|
||||
},
|
||||
"task": {
|
||||
"cronJob": {
|
||||
@@ -5372,7 +5403,8 @@
|
||||
"batchDeleteConfirm": "确定删除选中的 {{count}} 个任务吗?此操作不可恢复。",
|
||||
"confirmDelete": "确定删除「{{name}}」吗?此操作不可恢复。",
|
||||
"execDuration": "耗时 {{ms}}ms"
|
||||
}
|
||||
},
|
||||
"runCount": "{{count}} 次"
|
||||
},
|
||||
"cronJobCol": {
|
||||
"task": "任务",
|
||||
@@ -7763,7 +7795,17 @@
|
||||
"liveMonitor": {
|
||||
"exitFullscreen": "退出全屏",
|
||||
"fullscreen": "全屏"
|
||||
}
|
||||
},
|
||||
"rdpLiveAudit": "RDP 实时审计",
|
||||
"rdpHistoryReplay": "RDP 历史回放",
|
||||
"rdpAuditDesc": "Windows RDP 图形会话审计查看",
|
||||
"sshTerminalDesc": "SSH 终端连接",
|
||||
"sftpFileDesc": "SFTP 文件管理 · 上传 · 下载 · 删除",
|
||||
"sftpFileLabel": "· SFTP 文件管理",
|
||||
"deleteUserConfirmDesc": "确认删除用户「{{name}}」吗?",
|
||||
"batchDeleteUsersConfirmDesc": "确定删除选中的 {{count}} 个用户吗?此操作不可恢复。",
|
||||
"deleteCredConfirmDesc": "确定删除「{{name}}」吗?删除后无法恢复,关联的服务器将无法使用此凭据连接。",
|
||||
"deleteTermSessionsConfirmDesc": "确认删除选中的 {{count}} 条终端会话记录?"
|
||||
},
|
||||
"aiops": {
|
||||
"activeCount": "{{count}} 个活跃",
|
||||
@@ -7971,7 +8013,15 @@
|
||||
"resCpu": "服务器CPU算力",
|
||||
"resMemory": "服务器内存",
|
||||
"resDisk": "存储磁盘空间",
|
||||
"summary": "- {{resource}}:当前 {{current}}% → 7天后预测 {{predicted}}%(阈值 {{threshold}}%),{{risk}}"
|
||||
"summary": "- {{resource}}:当前 {{current}}% → 7天后预测 {{predicted}}%(阈值 {{threshold}}%),{{risk}}",
|
||||
"aiInsight": "AI 深度解读",
|
||||
"urgency": "紧急",
|
||||
"warning": "警告",
|
||||
"sevenDayForecast": "7天使用率预测",
|
||||
"expectedToReach": "预计",
|
||||
"days": "天",
|
||||
"afterReachThreshold": "后达到阈值",
|
||||
"aiSuggestion": "AI建议"
|
||||
},
|
||||
"capacityPlanPrompt": "根据以下主机资源使用数据,提供成本优化和容量规划建议(识别闲置/过载主机,给出缩容/扩容建议)",
|
||||
"capacityPlanning": "容量规划",
|
||||
@@ -8108,7 +8158,9 @@
|
||||
"hint": "Shift+回车换行 · 回车发送",
|
||||
"stop": "停止",
|
||||
"execute": "执行"
|
||||
}
|
||||
},
|
||||
"confirmHighRiskTitle": "⚠️ 确认执行高危操作",
|
||||
"confirmHighRiskDesc": "工具:{{tool}}\n风险:{{risk}}\n命令:{{command}}"
|
||||
},
|
||||
"cloudService": "云服务",
|
||||
"codingPlan": "编码套餐 Coding Plan",
|
||||
@@ -8474,7 +8526,10 @@
|
||||
"zhipuGeneral": "智谱 GLM (通用)",
|
||||
"zhipuGetKey": "注册智谱账号并开通模型服务后获取 API Key",
|
||||
"zhipuOpenPlatform": "智谱开放平台",
|
||||
"reachable": "可达"
|
||||
"reachable": "可达",
|
||||
"cost": {
|
||||
"aiInsight": "AI 深度解读"
|
||||
}
|
||||
},
|
||||
"breadcrumb": {
|
||||
"aiAlertAnalyzer": "告警分析",
|
||||
|
||||
Reference in new issue
Block a user