From 47189318e59a2325f686ee8403ed14d0ea38eae8 Mon Sep 17 00:00:00 2001 From: xintaofei Date: Sat, 7 Mar 2026 14:00:29 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E5=A1=AB=E5=85=85=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/chat/agent-plan-overlay.tsx | 47 +++++++++----- src/components/chat/agent-selector.tsx | 6 +- src/components/chat/chat-input.tsx | 8 ++- src/components/chat/live-message-block.tsx | 4 +- src/components/chat/message-input.tsx | 21 +++--- src/components/chat/permission-dialog.tsx | 26 ++++---- src/components/chat/welcome-input-panel.tsx | 47 ++++++++++---- src/components/diff/unified-diff-preview.tsx | 28 ++++---- src/i18n/messages/en.json | 68 ++++++++++++++++++++ src/i18n/messages/zh-CN.json | 68 ++++++++++++++++++++ src/i18n/messages/zh-TW.json | 68 ++++++++++++++++++++ 11 files changed, 322 insertions(+), 69 deletions(-) diff --git a/src/components/chat/agent-plan-overlay.tsx b/src/components/chat/agent-plan-overlay.tsx index f5856c0..ff72849 100644 --- a/src/components/chat/agent-plan-overlay.tsx +++ b/src/components/chat/agent-plan-overlay.tsx @@ -1,6 +1,7 @@ "use client" import { memo, useMemo, useState } from "react" +import { useTranslations } from "next-intl" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import type { LiveMessage } from "@/contexts/acp-connections-context" @@ -36,29 +37,41 @@ function getLatestPlanEntries(message: LiveMessage | null): PlanEntryInfo[] { return [] } -function getStatusLabel(status: string): string { +function getStatusKey( + status: string +): + | "status.completed" + | "status.inProgress" + | "status.pending" + | "status.unknown" { switch (status) { case "completed": - return "Completed" + return "status.completed" case "in_progress": - return "In Progress" + return "status.inProgress" case "pending": - return "Pending" + return "status.pending" default: - return "Unknown" + return "status.unknown" } } -function getPriorityLabel(priority: string): string { +type PriorityKey = + | "priority.high" + | "priority.medium" + | "priority.low" + | "priority.unknown" + +function getPriorityKey(priority: string): PriorityKey { switch (priority) { case "high": - return "High" + return "priority.high" case "medium": - return "Medium" + return "priority.medium" case "low": - return "Low" + return "priority.low" default: - return "Unknown" + return "priority.unknown" } } @@ -94,6 +107,7 @@ export const AgentPlanOverlay = memo(function AgentPlanOverlay({ visible = true, defaultExpanded = true, }: AgentPlanOverlayProps) { + const t = useTranslations("Folder.chat.agentPlanOverlay") const liveEntries = useMemo( () => getLatestPlanEntries(message ?? null), [message] @@ -146,7 +160,10 @@ export const AgentPlanOverlay = memo(function AgentPlanOverlay({ } > - Plan {completedCount}/{resolvedEntries.length} + {t("collapsedSummary", { + completed: completedCount, + total: resolvedEntries.length, + })} @@ -162,7 +179,7 @@ export const AgentPlanOverlay = memo(function AgentPlanOverlay({
- Agent Plan + {t("title")} {completedCount}/{resolvedEntries.length} @@ -171,7 +188,7 @@ export const AgentPlanOverlay = memo(function AgentPlanOverlay({ type="button" variant="ghost" size="icon-xs" - aria-label="Collapse plan" + aria-label={t("collapsePlanAria")} onClick={() => setCollapsedByPlanKey((prev) => ({ ...prev, @@ -204,7 +221,7 @@ export const AgentPlanOverlay = memo(function AgentPlanOverlay({
- {getStatusLabel(entry.status)} + {t(getStatusKey(entry.status))} - {getPriorityLabel(entry.priority)} + {t(getPriorityKey(entry.priority))}
diff --git a/src/components/chat/agent-selector.tsx b/src/components/chat/agent-selector.tsx index 580b5ba..8e1c956 100644 --- a/src/components/chat/agent-selector.tsx +++ b/src/components/chat/agent-selector.tsx @@ -1,6 +1,7 @@ "use client" import { useEffect, useState } from "react" +import { useTranslations } from "next-intl" import { acpListAgents } from "@/lib/tauri" import type { AgentType, AcpAgentInfo } from "@/lib/types" import { AGENT_LABELS } from "@/lib/types" @@ -22,6 +23,7 @@ export function AgentSelector({ onOpenAgentsSettings, disabled = false, }: AgentSelectorProps) { + const t = useTranslations("Folder.chat.agentSelector") const [agents, setAgents] = useState([]) const [selected, setSelected] = useState( defaultAgentType ?? null @@ -80,14 +82,14 @@ export function AgentSelector({ if (agents.length === 0) { return (
-
暂无已启用的 Agent
+
{t("noEnabledAgents")}
{onOpenAgentsSettings ? ( ) : null}
diff --git a/src/components/chat/chat-input.tsx b/src/components/chat/chat-input.tsx index 055a862..8791533 100644 --- a/src/components/chat/chat-input.tsx +++ b/src/components/chat/chat-input.tsx @@ -1,5 +1,6 @@ "use client" +import { useTranslations } from "next-intl" import type { ConnectionStatus, PromptDraft, @@ -44,6 +45,7 @@ export function ChatInput({ attachmentTabId, draftStorageKey, }: ChatInputProps) { + const t = useTranslations("Folder.chat.chatInput") const isConnected = status === "connected" const isPrompting = status === "prompting" const isConnecting = status === "connecting" || status === "downloading" @@ -69,10 +71,10 @@ export function ChatInput({ draftStorageKey={draftStorageKey} placeholder={ isConnecting - ? "Connecting..." + ? t("connecting") : isPrompting - ? "Agent is responding..." - : "Send a message..." + ? t("agentResponding") + : t("sendMessage") } className="min-h-28 max-h-60" /> diff --git a/src/components/chat/live-message-block.tsx b/src/components/chat/live-message-block.tsx index 55239dc..fed2396 100644 --- a/src/components/chat/live-message-block.tsx +++ b/src/components/chat/live-message-block.tsx @@ -1,6 +1,7 @@ "use client" import { memo, useMemo } from "react" +import { useTranslations } from "next-intl" import type { LiveMessage } from "@/contexts/acp-connections-context" import { ContentPartsRenderer } from "@/components/message/content-parts-renderer" import { adaptLiveMessageFromAcp } from "@/lib/adapters/ai-elements-adapter" @@ -13,6 +14,7 @@ interface LiveMessageBlockProps { export const LiveMessageBlock = memo(function LiveMessageBlock({ message, }: LiveMessageBlockProps) { + const t = useTranslations("Folder.chat.liveMessageBlock") const hasContent = message.content.length > 0 const adapted = useMemo(() => adaptLiveMessageFromAcp(message), [message]) @@ -24,7 +26,7 @@ export const LiveMessageBlock = memo(function LiveMessageBlock({ ) : (
diff --git a/src/components/chat/message-input.tsx b/src/components/chat/message-input.tsx index 4d4ba7d..e776e47 100644 --- a/src/components/chat/message-input.tsx +++ b/src/components/chat/message-input.tsx @@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react" import { open } from "@tauri-apps/plugin-dialog" +import { useTranslations } from "next-intl" import { Button } from "@/components/ui/button" import { Textarea } from "@/components/ui/textarea" import { FileSearch, Plus, Send, Square, X } from "lucide-react" @@ -114,7 +115,7 @@ function SelectorLoadingChip({ label }: { label: string }) { export function MessageInput({ onSend, - placeholder = "Ask anything...", + placeholder, defaultPath, disabled = false, autoFocus = false, @@ -133,7 +134,9 @@ export function MessageInput({ attachmentTabId, draftStorageKey, }: MessageInputProps) { + const t = useTranslations("Folder.chat.messageInput") const effectiveDraftStorageKey = draftStorageKey ?? attachmentTabId ?? null + const resolvedPlaceholder = placeholder ?? t("askAnything") const [text, setText] = useState(() => { if (!effectiveDraftStorageKey) return "" return loadMessageInputDraft(effectiveDraftStorageKey) ?? "" @@ -388,7 +391,7 @@ export function MessageInput({ onCompositionStart={() => (composingRef.current = true)} onCompositionEnd={() => (composingRef.current = false)} onFocus={onFocus} - placeholder={placeholder} + placeholder={resolvedPlaceholder} className={cn( "text-sm pr-12 resize-none bg-transparent", topPaddingClass, @@ -411,7 +414,9 @@ export function MessageInput({ type="button" onClick={() => removeAttachment(attachment.path)} className="rounded-sm p-0.5 hover:bg-muted-foreground/15" - aria-label={`Remove ${attachment.name}`} + aria-label={t("removeAttachmentAria", { + name: attachment.name, + })} > @@ -428,12 +433,12 @@ export function MessageInput({ variant="ghost" size="icon" className="h-6 w-6 shrink-0" - title="Attach files" + title={t("attachFiles")} > {showConfigLoading && ( - + )} {hasConfigOptions && availableConfigOptions.map((option) => ( @@ -445,7 +450,7 @@ export function MessageInput({ } /> ))} - {showModeLoading && } + {showModeLoading && } {showModeSelector && effectiveModeId && ( @@ -471,7 +476,7 @@ export function MessageInput({ disabled={disabled || !hasSendableContent} size="icon" className="absolute right-2 bottom-2" - title="Send" + title={t("send")} > diff --git a/src/components/chat/permission-dialog.tsx b/src/components/chat/permission-dialog.tsx index d30b917..7edf7eb 100644 --- a/src/components/chat/permission-dialog.tsx +++ b/src/components/chat/permission-dialog.tsx @@ -1,6 +1,7 @@ "use client" import { useMemo } from "react" +import { useTranslations } from "next-intl" import { ShieldAlert, Terminal, @@ -19,15 +20,16 @@ interface PermissionDialogProps { onRespond: (requestId: string, optionId: string) => void } -function formatKindLabel(kind: string): string { +function formatKindLabel(kind: string, fallbackLabel: string): string { const normalized = kind.replace(/_/g, " ").trim() - return normalized.length > 0 ? normalized : "tool" + return normalized.length > 0 ? normalized : fallbackLabel } export function PermissionDialog({ permission, onRespond, }: PermissionDialogProps) { + const t = useTranslations("Folder.chat.permissionDialog") const parsed = useMemo( () => parsePermissionToolCall(permission?.tool_call), [permission?.tool_call] @@ -51,12 +53,10 @@ export function PermissionDialog({ {parsed.title}
-

- Agent requests permission to continue this turn. -

+

{t("subtitle")}

- {formatKindLabel(parsed.normalizedKind)} + {formatKindLabel(parsed.normalizedKind, t("kindFallbackTool"))} @@ -65,12 +65,12 @@ export function PermissionDialog({
- Command + {t("command")}
{parsed.cwd && (
- CWD: {parsed.cwd} + {t("cwd", { cwd: parsed.cwd })}
)}
@@ -80,7 +80,9 @@ export function PermissionDialog({
- Files: {parsed.fileChanges.length} + + {t("filesSummary", { count: parsed.fileChanges.length })} + {(parsed.additions > 0 || parsed.deletions > 0) && ( +{parsed.additions} / -{parsed.deletions} @@ -98,7 +100,7 @@ export function PermissionDialog({ ))} {parsed.fileChanges.length > 8 && (
- +{parsed.fileChanges.length - 8} more files + {t("moreFiles", { count: parsed.fileChanges.length - 8 })}
)}
@@ -112,7 +114,7 @@ export function PermissionDialog({
- Plan + {t("plan")}
{parsed.planExplanation && (

@@ -140,7 +142,7 @@ export function PermissionDialog({

- Target mode: {parsed.modeTarget} + {t("targetMode", { mode: parsed.modeTarget })}
)} diff --git a/src/components/chat/welcome-input-panel.tsx b/src/components/chat/welcome-input-panel.tsx index 62d402f..c96cff2 100644 --- a/src/components/chat/welcome-input-panel.tsx +++ b/src/components/chat/welcome-input-panel.tsx @@ -1,6 +1,7 @@ "use client" import { useCallback, useEffect, useMemo, useRef, useState } from "react" +import { useTranslations } from "next-intl" import { MessageInput } from "@/components/chat/message-input" import type { AgentType, PromptDraft, SessionStats } from "@/lib/types" import { useFolderContext } from "@/contexts/folder-context" @@ -65,18 +66,18 @@ function isExpectedAutoLinkError(error: unknown): boolean { return (error as { alerted?: unknown }).alerted === true } -function buildInlineAutoConnectErrorMessage(raw: string): string { - const normalized = raw.trim().replace(/[。.!?,,;;::]+$/u, "") - if (!normalized) return "点击前往设置 > Agents 管理安装。" - const hasSdkNotInstalled = /SDK\s*尚未安装$/u.test(normalized) - const message = - !hasSdkNotInstalled && normalized.endsWith("尚未安装") - ? normalized.replace(/尚未安装$/u, "SDK 尚未安装") - : normalized - if (message.includes("设置 > Agents 管理安装")) { - return `${message}。` +function buildInlineAutoConnectErrorMessage( + raw: string, + options: { + fallback: string + append: (message: string) => string + alreadyContainsPath: (message: string) => boolean } - return `${message},点击前往设置 > Agents 管理安装。` +): string { + const normalized = raw.trim().replace(/[。.!?,,;;::]+$/u, "") + if (!normalized) return options.fallback + if (options.alreadyContainsPath(normalized)) return normalized + return options.append(normalized) } export function WelcomeInputPanel({ @@ -85,6 +86,7 @@ export function WelcomeInputPanel({ tabId, isActive = true, }: WelcomeInputPanelProps) { + const t = useTranslations("Folder.chat.welcomeInputPanel") const fallbackContextId = useMemo(() => crypto.randomUUID(), []) const contextKey = tabId ?? `new-${fallbackContextId}` @@ -569,6 +571,23 @@ export function WelcomeInputPanel({ }) }, [selectedAgent]) + const buildAutoConnectErrorMessage = useCallback( + (raw: string) => + buildInlineAutoConnectErrorMessage(raw, { + fallback: t("autoConnectFallback"), + append: (message) => + t("autoConnectAppend", { + message, + path: t("agentsSettingsPath"), + }), + alreadyContainsPath: (message) => + [t("agentsSettingsPath"), "Settings > Agents"].some((path) => + message.includes(path) + ), + }), + [t] + ) + // Track live message visibility across turn completion. // Hooks must be called before any conditional returns. const prevConnStatusForLiveRef = useRef(connStatus) @@ -617,7 +636,7 @@ export function WelcomeInputPanel({ className="w-full cursor-pointer rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-center text-xs text-destructive transition-colors hover:bg-destructive/10" > {(() => { - const inlineMessage = buildInlineAutoConnectErrorMessage( + const inlineMessage = buildAutoConnectErrorMessage( autoConnectError ?? agentConnectError ?? "" ) return ( @@ -638,8 +657,8 @@ export function WelcomeInputPanel({ defaultPath={workingDir} placeholder={ agentsLoaded && usableAgentCount === 0 - ? "请先启用至少一个 Agent 后开始会话..." - : "Ask anything..." + ? t("enableAgentFirstPlaceholder") + : t("askAnythingPlaceholder") } autoFocus attachmentTabId={tabId ?? null} diff --git a/src/components/diff/unified-diff-preview.tsx b/src/components/diff/unified-diff-preview.tsx index 8b85b7b..d22ee55 100644 --- a/src/components/diff/unified-diff-preview.tsx +++ b/src/components/diff/unified-diff-preview.tsx @@ -3,6 +3,7 @@ import { useCallback, useEffect, useMemo, useRef } from "react" import dynamic from "next/dynamic" import type { editor as MonacoEditorNs } from "monaco-editor" +import { useTranslations } from "next-intl" import { useFolderContext } from "@/contexts/folder-context" import { defineMonacoThemes, useMonacoThemeSync } from "@/lib/monaco-themes" import { cn } from "@/lib/utils" @@ -414,11 +415,13 @@ function parseUnifiedDiff(diffText: string): ParsedDiffFile[] { .filter((file) => file.hunks.length > 0) } -function modeLabel(mode: DiffFileMode): string { - if (mode === "added") return "新增" - if (mode === "deleted") return "删除" - if (mode === "renamed") return "重命名" - return "修改" +function modeKey( + mode: DiffFileMode +): "mode.added" | "mode.deleted" | "mode.renamed" | "mode.modified" { + if (mode === "added") return "mode.added" + if (mode === "deleted") return "mode.deleted" + if (mode === "renamed") return "mode.renamed" + return "mode.modified" } function toDisplayPath(filePath: string, folderPath: string | null): string { @@ -436,11 +439,6 @@ function toDisplayPath(filePath: string, folderPath: string | null): string { return normalizedPath } -function hunkLabel(hunk: ParsedDiffHunk, index: number): string { - void hunk - return `Hunk ${index + 1}` -} - function countHunkChanges(hunk: ParsedDiffHunk): { additions: number deletions: number @@ -485,6 +483,7 @@ function HunkMonacoPreview({ modelId: string theme: string }) { + const t = useTranslations("Folder.diffPreview") const editorRef = useRef(null) const decorationsRef = useRef([]) @@ -567,7 +566,7 @@ function HunkMonacoPreview({ theme={theme} loading={
- Loading hunk... + {t("loadingHunk")}
} options={{ @@ -601,6 +600,7 @@ export function UnifiedDiffPreview({ modelId?: string className?: string }) { + const t = useTranslations("Folder.diffPreview") const { folder } = useFolderContext() const files = useMemo(() => parseUnifiedDiff(diffText), [diffText]) const theme = useMonacoThemeSync() @@ -613,7 +613,7 @@ export function UnifiedDiffPreview({ className )} > - No diff data + {t("noDiffData")}
) } @@ -638,7 +638,7 @@ export function UnifiedDiffPreview({ >
- {modeLabel(file.mode)} + {t(modeKey(file.mode))}
- {hunkLabel(hunk, index)} + {t("hunkLabel", { index: index + 1 })} +{hunkStats.additions} diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index c7c24b9..e0461ad 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -1022,6 +1022,74 @@ "add": "Add", "saving": "Saving..." } + }, + "chat": { + "chatInput": { + "connecting": "Connecting...", + "agentResponding": "Agent is responding...", + "sendMessage": "Send a message..." + }, + "messageInput": { + "askAnything": "Ask anything...", + "removeAttachmentAria": "Remove {name}", + "attachFiles": "Attach files", + "loadingSettings": "Loading settings...", + "loadingMode": "Loading mode...", + "cancel": "Cancel", + "send": "Send" + }, + "welcomeInputPanel": { + "agentsSettingsPath": "Settings > Agents", + "autoConnectFallback": "Click to open {path} and manage installation.", + "autoConnectAppend": "{message}. Click to open {path} and manage installation.", + "enableAgentFirstPlaceholder": "Enable at least one agent before starting a session...", + "askAnythingPlaceholder": "Ask anything..." + }, + "agentSelector": { + "noEnabledAgents": "No enabled agents", + "openAgentsSettings": "Open Agents settings" + }, + "liveMessageBlock": { + "assistantThinkingAria": "Assistant is thinking" + }, + "agentPlanOverlay": { + "title": "Agent Plan", + "collapsePlanAria": "Collapse plan", + "collapsedSummary": "Plan {completed}/{total}", + "status": { + "completed": "Completed", + "inProgress": "In Progress", + "pending": "Pending", + "unknown": "Unknown" + }, + "priority": { + "high": "High", + "medium": "Medium", + "low": "Low", + "unknown": "Unknown" + } + }, + "permissionDialog": { + "subtitle": "Agent requests permission to continue this turn.", + "kindFallbackTool": "tool", + "command": "Command", + "cwd": "CWD: {cwd}", + "filesSummary": "Files: {count}", + "moreFiles": "+{count} more files", + "plan": "Plan", + "targetMode": "Target mode: {mode}" + } + }, + "diffPreview": { + "mode": { + "added": "Added", + "deleted": "Deleted", + "renamed": "Renamed", + "modified": "Modified" + }, + "hunkLabel": "Hunk {index}", + "loadingHunk": "Loading hunk...", + "noDiffData": "No diff data" } } } diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index bde0c4b..f6ff650 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -1022,6 +1022,74 @@ "add": "添加", "saving": "保存中..." } + }, + "chat": { + "chatInput": { + "connecting": "连接中...", + "agentResponding": "Agent 正在响应...", + "sendMessage": "发送消息..." + }, + "messageInput": { + "askAnything": "请开始输入...", + "removeAttachmentAria": "移除 {name}", + "attachFiles": "附加文件", + "loadingSettings": "正在加载设置...", + "loadingMode": "正在加载模式...", + "cancel": "取消", + "send": "发送" + }, + "welcomeInputPanel": { + "agentsSettingsPath": "设置 > Agents", + "autoConnectFallback": "点击前往 {path} 管理安装。", + "autoConnectAppend": "{message},点击前往 {path} 管理安装。", + "enableAgentFirstPlaceholder": "请先启用至少一个 Agent 后开始会话...", + "askAnythingPlaceholder": "请开始输入..." + }, + "agentSelector": { + "noEnabledAgents": "暂无已启用的 Agent", + "openAgentsSettings": "打开 Agents 设置" + }, + "liveMessageBlock": { + "assistantThinkingAria": "助手正在思考" + }, + "agentPlanOverlay": { + "title": "Agent 计划", + "collapsePlanAria": "折叠计划", + "collapsedSummary": "计划 {completed}/{total}", + "status": { + "completed": "已完成", + "inProgress": "进行中", + "pending": "待处理", + "unknown": "未知" + }, + "priority": { + "high": "高", + "medium": "中", + "low": "低", + "unknown": "未知" + } + }, + "permissionDialog": { + "subtitle": "Agent 请求继续当前轮次的权限。", + "kindFallbackTool": "工具", + "command": "命令", + "cwd": "工作目录:{cwd}", + "filesSummary": "文件:{count}", + "moreFiles": "+{count} 个更多文件", + "plan": "计划", + "targetMode": "目标模式:{mode}" + } + }, + "diffPreview": { + "mode": { + "added": "新增", + "deleted": "删除", + "renamed": "重命名", + "modified": "修改" + }, + "hunkLabel": "代码块 {index}", + "loadingHunk": "正在加载代码块...", + "noDiffData": "无差异数据" } } } diff --git a/src/i18n/messages/zh-TW.json b/src/i18n/messages/zh-TW.json index f218879..e33251f 100644 --- a/src/i18n/messages/zh-TW.json +++ b/src/i18n/messages/zh-TW.json @@ -1022,6 +1022,74 @@ "add": "新增", "saving": "儲存中..." } + }, + "chat": { + "chatInput": { + "connecting": "連線中...", + "agentResponding": "Agent 正在回應...", + "sendMessage": "傳送訊息..." + }, + "messageInput": { + "askAnything": "請開始輸入...", + "removeAttachmentAria": "移除 {name}", + "attachFiles": "附加檔案", + "loadingSettings": "正在載入設定...", + "loadingMode": "正在載入模式...", + "cancel": "取消", + "send": "傳送" + }, + "welcomeInputPanel": { + "agentsSettingsPath": "設定 > Agents", + "autoConnectFallback": "點擊前往 {path} 管理安裝。", + "autoConnectAppend": "{message},點擊前往 {path} 管理安裝。", + "enableAgentFirstPlaceholder": "請先啟用至少一個 Agent 後開始會話...", + "askAnythingPlaceholder": "請開始輸入..." + }, + "agentSelector": { + "noEnabledAgents": "暫無已啟用的 Agent", + "openAgentsSettings": "開啟 Agents 設定" + }, + "liveMessageBlock": { + "assistantThinkingAria": "助手正在思考" + }, + "agentPlanOverlay": { + "title": "Agent 計畫", + "collapsePlanAria": "摺疊計畫", + "collapsedSummary": "計畫 {completed}/{total}", + "status": { + "completed": "已完成", + "inProgress": "進行中", + "pending": "待處理", + "unknown": "未知" + }, + "priority": { + "high": "高", + "medium": "中", + "low": "低", + "unknown": "未知" + } + }, + "permissionDialog": { + "subtitle": "Agent 請求繼續目前輪次的權限。", + "kindFallbackTool": "工具", + "command": "命令", + "cwd": "工作目錄:{cwd}", + "filesSummary": "檔案:{count}", + "moreFiles": "+{count} 個更多檔案", + "plan": "計畫", + "targetMode": "目標模式:{mode}" + } + }, + "diffPreview": { + "mode": { + "added": "新增", + "deleted": "刪除", + "renamed": "重新命名", + "modified": "修改" + }, + "hunkLabel": "區塊 {index}", + "loadingHunk": "正在載入區塊...", + "noDiffData": "無差異資料" } } }