fix(k8s): 修复 shared-components.tsx JSX 结构错误致前端构建失败 + 补全残余 i18n 硬编码中文

- fix: shared-components.tsx ContainerInfo 端口区块多余 <div> 标签致 JSX 闭合错误 (TS17008)
- i18n: EventsPage/DeploymentDetail/DeploymentEditAdvanced/Containers/Storage 等 K8s 组件残余硬编码中文→t() 调用
- i18n: zh/en 7987 键完全对齐, 新增 k8s.eventsPage/k8s.workload 等语义化键
- tsc -b=0, npm build✓ (17.48s), ESLint errors=0/warnings=43/any=0, go build=0
- 17/17 集成测试通过, Docker 部署 healthy
This commit is contained in:
attacker committed 2026-07-14 20:07:46 +08:00
1 parent 39a4432f79
commit bd1ccefa7f
13 files changed
+172 -42

No files matched your search

@@ -176,7 +176,7 @@ export function DeploymentDetail({ clusterCode, namespace, deploymentName, onBac
<Tabs defaultValue="pods">
<TabsList className="bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)]">
<TabsTrigger value="pods" className="data-[state=active]:bg-[var(--dg-bg-active)]">
Pod 列表 ({pods.length})
{i18n.t('k8s.deploymentDetail.podList')} ({pods.length})
</TabsTrigger>
<TabsTrigger value="logs" className="data-[state=active]:bg-[var(--dg-bg-active)]">
<FileText className="h-4 w-4 mr-1" />{i18n.t("common.podLogs")}
@@ -281,7 +281,7 @@ export function DeploymentEditAdvanced({ clusterCode, namespace, deploymentName,
<Button variant="outline" className="border-[var(--dg-border)] dg-text-secondary" onClick={onCancel}> {i18n.t('rbac.jobRole.cancel')} </Button>
<Button className="bg-blue-600 hover:bg-blue-700" disabled={saving} onClick={save}>
{saving ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : <Save className="h-4 w-4 mr-1" />}
保存
{i18n.t('common.save')}
</Button>
</div>
</div>
@@ -202,7 +202,7 @@ export function DeploymentEditContainers({ clusterCode, namespace, deploymentNam
<Button variant="outline" className="border-[var(--dg-border)] dg-text-secondary" onClick={onCancel}> {i18n.t('rbac.jobRole.cancel')} </Button>
<Button className="bg-blue-600 hover:bg-blue-700" disabled={saving} onClick={save}>
{saving ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : <Save className="h-4 w-4 mr-1" />}
保存
{i18n.t('common.save')}
</Button>
</div>
</div>
@@ -343,7 +343,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
<Button variant="outline" className="border-[var(--dg-border)] dg-text-secondary" onClick={onCancel}> {i18n.t('rbac.jobRole.cancel')} </Button>
<Button className="bg-blue-600 hover:bg-blue-700" disabled={saving} onClick={save}>
{saving ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : <Save className="h-4 w-4 mr-1" />}
保存
{i18n.t('common.save')}
</Button>
</div>
</div>
@@ -165,12 +165,12 @@ export default function EventsPage() {
<span className="text-[var(--dg-text-muted)]"> {i18n.t('kubernetes.eventsPage.filterLabel')} </span>
{selectedReason && (
<button type="button" className="inline-flex items-center gap-1 rounded border border-[var(--dg-border)] px-2 py-0.5 text-[var(--dg-text-secondary)] hover:bg-[var(--dg-bg-tertiary)]" onClick={() => setSelectedReason('')}>
原因 {selectedReason} <X className="h-3 w-3" />
{i18n.t('k8s.eventsPage.reasonLabel')} {selectedReason} <X className="h-3 w-3" />
</button>
)}
{selectedKind && (
<button type="button" className="inline-flex items-center gap-1 rounded border border-[var(--dg-border)] px-2 py-0.5 text-[var(--dg-text-secondary)] hover:bg-[var(--dg-bg-tertiary)]" onClick={() => setSelectedKind('')}>
类型 {selectedKind} <X className="h-3 w-3" />
{i18n.t('k8s.eventsPage.kindLabel')} {selectedKind} <X className="h-3 w-3" />
</button>
)}
</div>
@@ -240,7 +240,7 @@ export default function EventsPage() {
<CardContent className="p-4">
<h3 className="text-sm font-medium text-[var(--dg-text-primary)] mb-3 flex items-center gap-1.5">
<AlertTriangle className="h-4 w-4 text-[var(--dg-orange)]" />
最新告警 ({summary.recent_warnings.length})
{i18n.t('k8s.eventsPage.recentWarnings')} ({summary.recent_warnings.length})
</h3>
<div className="space-y-1">
{summary.recent_warnings.map((w: JsonData, i: number) => (
@@ -164,7 +164,7 @@ export function KubernetesClusterDialog({
/>
{nameError && <p className="text-xs dg-text-red">{nameError}</p>}
<p className="text-xs text-[var(--dg-text-muted)]">
只允许英文、数字和连字符(-),首尾不能是连字符。名称将作为集群唯一标识。
{i18n.t('k8s.clusterDialog.codeRule')}
</p>
</div>
<div className="space-y-2">
@@ -243,7 +243,7 @@ export function KubernetesClusterDialog({
/>
{!hasKubeConfig && (
<p className="text-xs text-[var(--dg-text-muted)]">
粘贴 kubeconfig 内容后将自动解析 API Server 地址
{i18n.t('k8s.clusterDialog.kubeconfigHint')}
</p>
)}
</div>
@@ -255,7 +255,7 @@ export function KubernetesClusterDialog({
onClick={() => { onOpenChange(false); }}
className="border-[var(--dg-border)] text-[var(--dg-text-secondary)] hover:text-[var(--dg-text-primary)] hover:bg-[var(--dg-bg-hover)]"
>
取消
{i18n.t('common.cancel')}
</Button>
<Button
onClick={handleSubmit}
@@ -132,7 +132,7 @@ export function KubernetesNodes() {
<TableCell>{getRoleBadge(n.role)}</TableCell>
<TableCell>{getStatusBadge(n.status)}</TableCell>
<TableCell className="text-sm text-[var(--dg-text-secondary)]">
{n.cpu ? `${n.cpu}核` : '-'} / {n.memory ? `${Math.round(n.memory / 1024)}GB` : '-'}
{n.cpu ? `${n.cpu}${i18n.t('k8s.nodes.cores')}` : '-'} / {n.memory ? `${Math.round(n.memory / 1024)}GB` : '-'}
</TableCell>
<TableCell>
{(() => {
@@ -158,7 +158,7 @@ export default function NamespaceManagementPage() {
onKeyDown={(e) => e.key === 'Enter' && handleCreate()}
/>
<p className="text-xs text-[var(--dg-text-muted)]">
名称需符合 DNS-1123 标准(小写字母/数字/连字符)
{i18n.t('k8s.nsMgmt.dnsHint')}
</p>
</div>
</div>
@@ -166,7 +166,7 @@ export default function NamespaceManagementPage() {
<Button variant="outline" onClick={() => setCreateOpen(false)}> {i18n.t('rbac.jobRole.cancel')} </Button>
<Button onClick={handleCreate} disabled={creating || !newName.trim()}>
{creating ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : null}
创建
{i18n.t('common.create')}
</Button>
</DialogFooter>
</DialogContent>
@@ -280,7 +280,7 @@ export default function NamespaceManagementPage() {
{i18n.t('common.deleteNamespaceWarn')} <span className="font-bold">{deleteTarget}</span> {i18n.t('common.allResources')}
</p>
<p className="text-xs text-[var(--dg-red)]/70 mt-1">
此操作不可逆,所有 Deployment/Pod/Service/ConfigMap 等资源将被永久删除。
{i18n.t('k8s.nsMgmt.confirmDeleteDesc')}
</p>
</div>
</div>
@@ -288,7 +288,7 @@ export default function NamespaceManagementPage() {
<Button variant="outline" onClick={() => setDeleteTarget(null)}> {i18n.t('rbac.jobRole.cancel')} </Button>
<Button variant="destructive" onClick={handleDelete} disabled={deleting}>
{deleting ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : null}
确认删除
{i18n.t('k8s.nsMgmt.confirmDelete')}
</Button>
</DialogFooter>
</DialogContent>
@@ -119,7 +119,7 @@ export function PodFileBrowser({
const text = await kubernetesApi.readPodFileText(clusterCode, namespace, podName, filePath, container || undefined);
setPreview({ file: fileName, content: text });
} catch (e) {
setPreview({ file: fileName, content: `读取失败: ${(e as JsonData).message}` });
setPreview({ file: fileName, content: `${i18n.t('k8s.podFiles.readError')}: ${(e as JsonData).message}` });
}
};
@@ -137,7 +137,7 @@ export function PodFileBrowser({
await kubernetesApi.uploadPodFile(clusterCode, namespace, podName, currentPath, file, container || undefined);
loadFiles(currentPath);
} catch (err) {
setError(`上传失败: ${(err as JsonData).message}`);
setError(`${i18n.t('k8s.podFiles.uploadError')}: ${(err as JsonData).message}`);
} finally {
setUploading(false);
if (fileInputRef.current) fileInputRef.current.value = '';
@@ -211,7 +211,7 @@ export function PodFileBrowser({
<div className="flex items-center gap-2">
<input type="file" ref={fileInputRef} className="hidden" onChange={handleUpload} />
<Button size="sm" variant="outline" className="h-7 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs" onClick={() => fileInputRef.current?.click()} disabled={uploading}>
{uploading ? <Loader2 className="h-3 w-3 animate-spin mr-1" /> : <Upload className="h-3 w-3 mr-1" />}上传
{uploading ? <Loader2 className="h-3 w-3 animate-spin mr-1" /> : <Upload className="h-3 w-3 mr-1" />}{i18n.t('common.upload')}
</Button>
<Button size="sm" variant="outline" className="h-7 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs" onClick={() => loadFiles(currentPath)} disabled={loading}>
{loading ? <Loader2 className="h-3 w-3 animate-spin" /> : <RefreshCw className="h-3 w-3" />}
@@ -97,6 +97,6 @@ export async function saveDeploymentBundleYaml(
await kubernetesApi.applyYAML(clusterCode, docYaml);
continue;
}
throw new Error(`不支持的资源类型: ${manifest.kind}(仅支持 Deployment / Service)`);
throw new Error(i18n.t('k8s.bundleYaml.unsupportedType', { kind: manifest.kind }));
}
}
@@ -57,7 +57,7 @@ export function ContainerInfo({ c }: { c: JsonData }) {
内存: <span className="text-[var(--dg-text-primary)] font-mono">{c.resources?.requests?.memory || '-'}/{c.resources?.limits?.memory || '-'}</span>
</div>
<div className="text-[var(--dg-text-secondary)]">
端口: <span className="text-[var(--dg-text-primary)] font-mono">
{i18n.t('k8s.workload.portsLabel')}: <span className="text-[var(--dg-text-primary)] font-mono">
{(c.ports || []).map((p: JsonData) => p.containerPort || p.port).join(', ') || '-'}
</span>
</div>
+76 -11
View File
@@ -662,7 +662,8 @@
"readWrite": "Read Write",
"manageAll": "Manage All",
"createNew": "Create New",
"saveSuccess": "Saved successfully"
"saveSuccess": "Saved successfully",
"daysSuffix": "days"
},
"menu": {
"aiAgentCli": "Agent CLI",
@@ -2655,7 +2656,8 @@
"tokenPlaceholder": "Paste Service Account Token...",
"tokenConfigured": "Configured, enter new value to override...",
"addTitle": "Add Cluster",
"editTitle": "Edit Cluster"
"editTitle": "Edit Cluster",
"codeRule": "Only English letters, numbers, and hyphens(-) allowed. Cannot start or end with a hyphen. Serves as cluster unique identifier."
},
"clusterOverview": {
"nodeCount": "Nodes",
@@ -3205,7 +3207,8 @@
"notReady": "Not Ready",
"selectCluster": "Select Cluster",
"subtitle": "Kubernetes cluster node status and resources",
"noData": "No node data"
"noData": "No node data",
"cores": "cores"
},
"nsMgmt": {
"status": "Status",
@@ -3216,7 +3219,10 @@
"title": "Namespace Management",
"quotaLimit": "Quota Limits",
"nameExample": "e.g. my-app",
"quotaSubtitle": "{{code}} · Resource Quotas & Lifecycle"
"quotaSubtitle": "{{code}} · Resource Quotas & Lifecycle",
"dnsHint": "Name must comply with DNS-1123 (lowercase letters/numbers/hyphens)",
"confirmDeleteDesc": "This action is irreversible. All Deployments/Pods/Services/ConfigMaps will be permanently deleted.",
"confirmDelete": "Confirm Delete"
},
"nsOverview": {
"workloadReplicas": "Workload replica management",
@@ -3688,7 +3694,9 @@
"confirmDeletePod": "Confirm Delete Pod",
"deletePodDesc": "This operation cannot be undone",
"image": "Image",
"deployment": "Deployment"
"deployment": "Deployment",
"memoryLabel": "Memory",
"portsLabel": "Ports"
},
"workloadView": {
"restartSent": "Restart command sent",
@@ -3740,7 +3748,19 @@
"podLevel": "Pod Level",
"podNameLabel": "Pod Name",
"podManagePolicy": "Pod Management Policy",
"uploadFile": "Upload"
"uploadFile": "Upload",
"eventsPage": {
"reasonLabel": "Reason",
"kindLabel": "Kind",
"recentWarnings": "Recent Warnings"
},
"podFiles": {
"readError": "Read failed",
"uploadError": "Upload failed"
},
"bundleYaml": {
"unsupportedType": "Unsupported resource type: {{kind}} (only Deployment / Service supported)"
}
},
"monitor": {
"acknowledge": "Acknowledge",
@@ -3808,7 +3828,10 @@
"alertChannelDialog": {
"notTested": "Not Tested",
"title": "Notification Channel Configuration",
"enableChannel": "Enable this channel"
"enableChannel": "Enable this channel",
"desc": "Manage alert notification channels (DingTalk/WeChat/Email/SMS/Webhook). Reference in alert rules after configuration.",
"createNew": "New",
"emptyChannels": "No notification channels. Add on the right."
},
"alertChannelDialog2": {
"editChannel": "Edit Channel",
@@ -3901,7 +3924,9 @@
"alertList": "Alerts",
"alertManager": {
"trendTitle": "Alert Trends",
"last24hStats": "Past 24 hours alert statistics"
"last24hStats": "Past 24 hours alert statistics",
"notifyConfig": "Notification Config",
"createRule": "Create Rule"
},
"alertMessage": "Message",
"alertMgr2": {
@@ -3948,7 +3973,12 @@
"deleteRule": "Delete Alert Rule",
"deleteConfirm": "Delete this alert rule?",
"deleted": "Alert rule deleted",
"condition": "Trigger Condition"
"condition": "Trigger Condition",
"batchDelete": "Batch Delete",
"emptyRules": "No alert rules",
"severityCritical": "Critical",
"severityWarning": "Warning",
"severityInfo": "Info"
},
"alertSeverity": "Severity",
"alertSource": "Source",
@@ -4502,7 +4532,22 @@
"usedHint": "Used {{value}}",
"clusterNodesHint": "Cluster {{value}} nodes",
"slowQueriesHint": "Slow queries {{value}}",
"pointCount": "{{min}} — {{max}} · {{count}} pts"
"pointCount": "{{min}} — {{max}} · {{count}} pts",
"queryCount": "Log Count",
"totalCount": "Total",
"loadMore": "Load More",
"displayFields": "Display Fields",
"indexFields": "Indexed Fields",
"logQueryHint": "Log queries depend on datasource connections. Platform does not store log data.",
"labelBrowser": "Label Browser",
"selectedCount": "Selected",
"addAlertFromQuery": "Add current query as alert",
"emptyLogAlerts": "No log alerts. Click the bell icon in Loki/ES query page to create from current query.",
"useDefaultIndex": "Use datasource default",
"maxHistory": "Max 50 entries · Local storage",
"countSuffix": "entries",
"prometheusDs": "Prometheus Datasource",
"addDatasource": "Add Datasource"
},
"logAlertBell": {
"linked": "Alert Policy Linked",
@@ -7832,7 +7877,27 @@
"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?"
"deleteTermSessionsConfirmDesc": "Delete {{count}} selected terminal session records?",
"newUser": "New User",
"password": "Password",
"local": "Local",
"batchImportCsv": "Batch Import Users (CSV)",
"csvImportDesc": "Upload a CSV file to batch create users. Download the template first, fill in and upload.",
"selectCsvFile": "Select CSV File",
"previewData": "Preview",
"moreEntries": "{{count}} more entries...",
"confirmImport": "Confirm Import ({{count}})",
"ldapImportTitle": "Import Users from LDAP",
"ldapImportDesc": "Retrieve user list from LDAP server, select users to import",
"foundUsers": "Found {{count}} users",
"noUserData": "No user data",
"selectedItems": "Selected {{selected}} / Total {{total}}",
"credentialEmpty": "No credentials. Click \"Add Credential\" to create",
"credentialSshKey": "SSH Private Key",
"credentialAkSk": "AK/SK (one pair per line, space or comma separated)",
"credentialEncryptedHint": "Credentials are encrypted with AES-256-GCM, decrypted only on server side",
"permissionAssign": "Permission Assignment",
"adminPassword": "Admin Password"
},
"aiops": {
"activeCount": "{{count}} active",
+76 -11
View File
@@ -662,7 +662,8 @@
"readWrite": "读写",
"manageAll": "管理全部",
"createNew": "新建",
"saveSuccess": "保存成功"
"saveSuccess": "保存成功",
"daysSuffix": "天"
},
"menu": {
"aiAgentCli": "Agent CLI",
@@ -2655,7 +2656,8 @@
"tokenPlaceholder": "粘贴 Service Account Token...",
"tokenConfigured": "已配置,输入新值覆盖...",
"addTitle": "添加集群",
"editTitle": "编辑集群"
"editTitle": "编辑集群",
"codeRule": "只允许英文、数字和连字符(-),首尾不能是连字符。名称将作为集群唯一标识。"
},
"clusterOverview": {
"nodeCount": "节点数",
@@ -3205,7 +3207,8 @@
"notReady": "未就绪",
"selectCluster": "选择集群",
"subtitle": "Kubernetes 集群工作节点状态与资源",
"noData": "暂无节点数据"
"noData": "暂无节点数据",
"cores": "核"
},
"nsMgmt": {
"status": "状态",
@@ -3216,7 +3219,10 @@
"title": "命名空间管理",
"quotaLimit": "配额限制",
"nameExample": "例如: my-app",
"quotaSubtitle": "{{code}} · 资源配额与生命周期管理"
"quotaSubtitle": "{{code}} · 资源配额与生命周期管理",
"dnsHint": "名称需符合 DNS-1123 标准(小写字母/数字/连字符)",
"confirmDeleteDesc": "此操作不可逆,所有 Deployment/Pod/Service/ConfigMap 等资源将被永久删除。",
"confirmDelete": "确认删除"
},
"nsOverview": {
"workloadReplicas": "工作负载副本管理",
@@ -3688,7 +3694,9 @@
"confirmDeletePod": "确认删除 Pod",
"deletePodDesc": "操作不可恢复",
"image": "镜像",
"deployment": "Deployment"
"deployment": "Deployment",
"memoryLabel": "内存",
"portsLabel": "端口"
},
"workloadView": {
"restartSent": "重启指令已下发",
@@ -3740,7 +3748,19 @@
"podLevel": "Pod 级别",
"podNameLabel": "Pod 名称",
"podManagePolicy": "Pod 管理策略",
"uploadFile": "上传"
"uploadFile": "上传",
"eventsPage": {
"reasonLabel": "原因",
"kindLabel": "类型",
"recentWarnings": "最新告警"
},
"podFiles": {
"readError": "读取失败",
"uploadError": "上传失败"
},
"bundleYaml": {
"unsupportedType": "不支持的资源类型: {{kind}}(仅支持 Deployment / Service)"
}
},
"monitor": {
"acknowledge": "确认告警",
@@ -3808,7 +3828,10 @@
"alertChannelDialog": {
"notTested": "未测试",
"title": "通知渠道配置",
"enableChannel": "启用此渠道"
"enableChannel": "启用此渠道",
"desc": "管理告警通知渠道(钉钉/企业微信/邮件/短信/Webhook),配置后可在告警规则中引用",
"createNew": "新建",
"emptyChannels": "暂无通知渠道,请在右侧添加"
},
"alertChannelDialog2": {
"editChannel": "编辑渠道",
@@ -3901,7 +3924,9 @@
"alertList": "告警列表",
"alertManager": {
"trendTitle": "告警趋势",
"last24hStats": "过去24小时告警统计"
"last24hStats": "过去24小时告警统计",
"notifyConfig": "通知配置",
"createRule": "新建规则"
},
"alertMessage": "告警信息",
"alertMgr2": {
@@ -3948,7 +3973,12 @@
"deleteRule": "删除告警规则",
"deleteConfirm": "确定删除此告警规则?",
"deleted": "告警规则已删除",
"condition": "触发条件"
"condition": "触发条件",
"batchDelete": "批量删除",
"emptyRules": "暂无告警规则",
"severityCritical": "严重",
"severityWarning": "警告",
"severityInfo": "提示"
},
"alertSeverity": "级别",
"alertSource": "来源",
@@ -4502,7 +4532,22 @@
"usedHint": "已用 {{value}}",
"clusterNodesHint": "集群 {{value}} 节点",
"slowQueriesHint": "慢查询 {{value}}",
"pointCount": "{{min}} — {{max}} · {{count}} 点"
"pointCount": "{{min}} — {{max}} · {{count}} 点",
"queryCount": "日志条数",
"totalCount": "总数",
"loadMore": "加载更多",
"displayFields": "显示字段",
"indexFields": "索引字段",
"logQueryHint": "日志查询依赖数据源连接,平台不存储海量日志本体",
"labelBrowser": "Label 浏览器",
"selectedCount": "已选",
"addAlertFromQuery": "将当前查询添加为告警",
"emptyLogAlerts": "暂无日志告警。在 Loki/ES 查询页点击右下角「叮当」可从当前查询快速创建。",
"useDefaultIndex": "使用数据源默认",
"maxHistory": "最多保存 50 条 · 本地存储",
"countSuffix": "条",
"prometheusDs": "Prometheus 数据源",
"addDatasource": "添加数据源"
},
"logAlertBell": {
"linked": "已关联告警策略",
@@ -7832,7 +7877,27 @@
"deleteUserConfirmDesc": "确认删除用户「{{name}}」吗?",
"batchDeleteUsersConfirmDesc": "确定删除选中的 {{count}} 个用户吗?此操作不可恢复。",
"deleteCredConfirmDesc": "确定删除「{{name}}」吗?删除后无法恢复,关联的服务器将无法使用此凭据连接。",
"deleteTermSessionsConfirmDesc": "确认删除选中的 {{count}} 条终端会话记录?"
"deleteTermSessionsConfirmDesc": "确认删除选中的 {{count}} 条终端会话记录?",
"newUser": "新建用户",
"password": "密码",
"local": "本地",
"batchImportCsv": "批量导入用户(CSV)",
"csvImportDesc": "上传 CSV 文件批量创建用户。请先下载模板,按格式填写后上传。",
"selectCsvFile": "选择 CSV 文件",
"previewData": "预览",
"moreEntries": "还有 {{count}} 条...",
"confirmImport": "确认导入 ({{count}})",
"ldapImportTitle": "从 LDAP 导入用户",
"ldapImportDesc": "从 LDAP 服务器检索用户列表,选择需要导入的用户",
"foundUsers": "找到 {{count}} 个用户",
"noUserData": "暂无用户数据",
"selectedItems": "已选择 {{selected}} 项 / 共 {{total}} 项",
"credentialEmpty": "暂无凭据,点击「添加凭据」创建",
"credentialSshKey": "SSH 私钥",
"credentialAkSk": "AK/SK (每行一对,用空格或逗号分隔)",
"credentialEncryptedHint": "凭据内容使用 AES-256-GCM 加密存储,仅在服务器端解密使用",
"permissionAssign": "权限分配",
"adminPassword": "管理员密码"
},
"aiops": {
"activeCount": "{{count}} 个活跃",