diff --git a/ui/src/i18n/locales/en-US.ts b/ui/src/i18n/locales/en-US.ts index 2ab24b4e4..33c076fe4 100644 --- a/ui/src/i18n/locales/en-US.ts +++ b/ui/src/i18n/locales/en-US.ts @@ -304,8 +304,8 @@ export const enUS = { cron: { title: "Cron Jobs", desc: "Scheduled agent wakeups and recurring tasks.", - noJobs: "No cron jobs configured.", - addJob: "Add Job", + noJobs: "No jobs yet.", + addJob: "Add job", runNow: "Run", remove: "Remove", enable: "Enable", @@ -314,6 +314,57 @@ export const enUS = { lastRun: "Last run", nextRun: "Next run", + // Scheduler card + scheduler: "Scheduler", + schedulerDesc: "Gateway-owned cron scheduler status.", + jobs: "Jobs", + + // New job form + newJob: "New Job", + newJobDesc: "Create a scheduled wakeup or agent run.", + name: "Name", + description: "Description", + agentId: "Agent ID", + agentIdPlaceholder: "default", + scheduleKind: "Schedule", + everyLabel: "Every", + atLabel: "At", + cronLabel: "Cron", + runAt: "Run at", + every: "Every", + unit: "Unit", + minutes: "Minutes", + hours: "Hours", + days: "Days", + expression: "Expression", + timezone: "Timezone (optional)", + session: "Session", + main: "Main", + isolated: "Isolated", + wakeMode: "Wake mode", + nextHeartbeat: "Next heartbeat", + now: "Now", + payload: "Payload", + systemEvent: "System event", + agentTurn: "Agent turn", + systemText: "System text", + agentMessage: "Agent message", + deliver: "Deliver", + to: "To", + toPlaceholder: "+1555… or chat id", + timeoutSeconds: "Timeout (seconds)", + postToMainPrefix: "Post to main prefix", + + // Jobs list + jobsList: "Jobs", + jobsListDesc: "All scheduled jobs stored in the gateway.", + + // Run history + runHistory: "Run history", + runHistoryDesc: "Latest runs for", + selectJob: "Select a job to inspect run history.", + noRuns: "No runs yet.", + form: { schedule: "Schedule (cron)", message: "Message", @@ -336,8 +387,9 @@ export const enUS = { desc: "Manage bundled and installed skills.", noSkills: "No skills found.", filter: "Filter skills", - apiKey: "API Key", - saveKey: "Save Key", + shown: "shown", + apiKey: "API key", + saveKey: "Save key", install: "Install", installing: "Installing…", enabled: "Enabled", @@ -345,6 +397,11 @@ export const enUS = { toggle: "Toggle", keySaved: "API key saved", keyError: "Failed to save API key", + eligible: "eligible", + blocked: "blocked", + missing: "Missing", + reason: "Reason", + blockedByAllowlist: "blocked by allowlist", }, // Nodes page @@ -427,14 +484,29 @@ export const enUS = { status: "Status", health: "Health", models: "Models", + modelsDesc: "Catalog from models.list.", heartbeat: "Heartbeat", + lastHeartbeat: "Last heartbeat", events: "Events", + eventLog: "Event Log", + eventLogDesc: "Latest gateway events.", + noEvents: "No events yet.", rpcCall: "RPC Call", + manualRpc: "Manual RPC", + manualRpcDesc: "Send a raw gateway method with JSON params.", method: "Method", params: "Params", + paramsJson: "Params (JSON)", call: "Call", result: "Result", noResult: "No result yet.", + snapshots: "Snapshots", + snapshotsDesc: "Status, health, and heartbeat data.", + securityAudit: "Security audit", + critical: "critical", + warnings: "warnings", + noCritical: "No critical issues", + runAuditCmd: "Run for details.", }, // Logs page diff --git a/ui/src/i18n/locales/zh-TW.ts b/ui/src/i18n/locales/zh-TW.ts index f7800f1fb..5516263db 100644 --- a/ui/src/i18n/locales/zh-TW.ts +++ b/ui/src/i18n/locales/zh-TW.ts @@ -311,7 +311,7 @@ export const zhTW = { cron: { title: "排程任務", desc: "排程代理喚醒與週期性任務。", - noJobs: "尚未設定排程任務。", + noJobs: "尚無任務。", addJob: "新增任務", runNow: "立即執行", remove: "移除", @@ -321,6 +321,57 @@ export const zhTW = { lastRun: "上次執行", nextRun: "下次執行", + // 排程器卡片 + scheduler: "排程器", + schedulerDesc: "閘道器所管理的排程器狀態。", + jobs: "任務數", + + // 新任務表單 + newJob: "新增任務", + newJobDesc: "建立排程喚醒或代理執行。", + name: "名稱", + description: "描述", + agentId: "代理 ID", + agentIdPlaceholder: "default", + scheduleKind: "排程類型", + everyLabel: "間隔", + atLabel: "指定時間", + cronLabel: "Cron", + runAt: "執行時間", + every: "每隔", + unit: "單位", + minutes: "分鐘", + hours: "小時", + days: "天", + expression: "運算式", + timezone: "時區(選填)", + session: "工作階段", + main: "主要", + isolated: "獨立", + wakeMode: "喚醒模式", + nextHeartbeat: "下次心跳", + now: "立即", + payload: "內容類型", + systemEvent: "系統事件", + agentTurn: "代理回合", + systemText: "系統文字", + agentMessage: "代理訊息", + deliver: "傳送", + to: "收件者", + toPlaceholder: "+1555… 或聊天 ID", + timeoutSeconds: "逾時(秒)", + postToMainPrefix: "發送至主工作階段前綴", + + // 任務列表 + jobsList: "任務", + jobsListDesc: "所有儲存在閘道器的排程任務。", + + // 執行歷史 + runHistory: "執行歷史", + runHistoryDesc: "最近的執行記錄:", + selectJob: "選擇任務以檢視執行歷史。", + noRuns: "尚無執行記錄。", + form: { schedule: "排程(cron 格式)", message: "訊息", @@ -343,6 +394,7 @@ export const zhTW = { desc: "管理內建與已安裝的技能。", noSkills: "找不到技能。", filter: "篩選技能", + shown: "個顯示中", apiKey: "API 金鑰", saveKey: "儲存金鑰", install: "安裝", @@ -352,6 +404,11 @@ export const zhTW = { toggle: "切換", keySaved: "API 金鑰已儲存", keyError: "儲存 API 金鑰失敗", + eligible: "可用", + blocked: "已封鎖", + missing: "缺少", + reason: "原因", + blockedByAllowlist: "被許可清單封鎖", }, // 節點頁面 @@ -434,14 +491,29 @@ export const zhTW = { status: "狀態", health: "健康狀態", models: "模型", + modelsDesc: "來自 models.list 的目錄。", heartbeat: "心跳", + lastHeartbeat: "上次心跳", events: "事件", + eventLog: "事件日誌", + eventLogDesc: "最新的閘道器事件。", + noEvents: "尚無事件。", rpcCall: "RPC 呼叫", + manualRpc: "手動 RPC", + manualRpcDesc: "使用 JSON 參數發送原始閘道器方法。", method: "方法", params: "參數", + paramsJson: "參數(JSON)", call: "呼叫", result: "結果", noResult: "尚無結果。", + snapshots: "快照", + snapshotsDesc: "狀態、健康狀態與心跳資料。", + securityAudit: "安全稽核", + critical: "嚴重", + warnings: "警告", + noCritical: "無嚴重問題", + runAuditCmd: "執行以檢視詳情。", }, // 日誌頁面 diff --git a/ui/src/ui/views/config.ts b/ui/src/ui/views/config.ts index ff6f57f32..8b5c02409 100644 --- a/ui/src/ui/views/config.ts +++ b/ui/src/ui/views/config.ts @@ -1,4 +1,5 @@ import { html, nothing } from "lit"; +import { t } from "../../i18n"; import type { ConfigUiHints } from "../types"; import { analyzeConfigSchema, renderConfigForm, SECTION_META } from "./config-form"; import { @@ -73,21 +74,15 @@ const sidebarIcons = { default: html``, }; -// Section definitions -const SECTIONS: Array<{ key: string; label: string }> = [ - { key: "env", label: "Environment" }, - { key: "update", label: "Updates" }, - { key: "agents", label: "Agents" }, - { key: "auth", label: "Authentication" }, - { key: "channels", label: "Channels" }, - { key: "messages", label: "Messages" }, - { key: "commands", label: "Commands" }, - { key: "hooks", label: "Hooks" }, - { key: "skills", label: "Skills" }, - { key: "tools", label: "Tools" }, - { key: "gateway", label: "Gateway" }, - { key: "wizard", label: "Setup Wizard" }, -]; +// Section definitions - labels are resolved via t() at render time +const SECTION_KEYS = [ + "env", "update", "agents", "auth", "channels", "messages", + "commands", "hooks", "skills", "tools", "gateway", "wizard", +] as const; + +function getSectionLabel(key: string): string { + return t(`config.sections.${key}`) || humanize(key); +} type SubsectionEntry = { key: string; @@ -191,13 +186,15 @@ export function renderConfig(props: ConfigProps) { // Get available sections from schema const schemaProps = analysis.schema?.properties ?? {}; - const availableSections = SECTIONS.filter(s => s.key in schemaProps); + const knownKeys = new Set(SECTION_KEYS); + const availableSections = SECTION_KEYS + .filter(k => k in schemaProps) + .map(k => ({ key: k, label: getSectionLabel(k) })); // Add any sections in schema but not in our list - const knownKeys = new Set(SECTIONS.map(s => s.key)); const extraSections = Object.keys(schemaProps) .filter(k => !knownKeys.has(k)) - .map(k => ({ key: k, label: k.charAt(0).toUpperCase() + k.slice(1) })); + .map(k => ({ key: k, label: getSectionLabel(k) })); const allSections = [...availableSections, ...extraSections]; @@ -255,8 +252,8 @@ export function renderConfig(props: ConfigProps) {