mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-07 06:52:28 +00:00
* feat(web): group consecutive tool-use cards Add a web-only visible projection that groups consecutive root-level execution tools into expandable cards. Keep approval and question tools standalone, reuse older-history loading on expand, and add regression coverage for grouping and UI behavior. * fix(web): hydrate oldest visible tool group Mark needsOlderHistory on the first visible grouped tool run even when earlier visible blocks are non-tool content, and add regression coverage for the boundary. * fix(web): continue grouped history hydration Decouple ToolGroupCard older-history chaining from the shared loading flag, invalidate stale hydration runs safely, and add regression coverage for multi-page hydration. * fix(web): harden grouped tool hydration - retry incomplete group hydration after transient pagination contention\n- keep approved and denied permissioned tool cards eligible for grouping\n- cover both regressions with targeted web tests * fix(web): keep Codex permission cards standalone - treat CodexPermission as a semantic grouping boundary even after approval\n- keep permissioned execution tools groupable while preserving permission milestones\n- add regression coverage for Codex permission eligibility and boundary behavior * fix(web): narrow incomplete tool-group hydration - only mark groups at the oldest visible boundary as needing older history\n- avoid auto-paginating complete groups behind text, standalone tools, or permission milestones\n- add regression coverage for the adjacent boundary cases
416 lines
17 KiB
TypeScript
416 lines
17 KiB
TypeScript
export default {
|
||
// Loading states
|
||
'loading': '加载中…',
|
||
'authorizing': '认证中…',
|
||
'loading.session': '加载会话…',
|
||
'loading.git': '加载 Git 状态…',
|
||
'loading.file': '加载文件…',
|
||
'loading.files': '加载文件…',
|
||
'loading.messages': '加载消息…',
|
||
'loading.machines': '加载机器…',
|
||
|
||
// Login / Auth
|
||
'login.title': 'HAPI',
|
||
'login.subtitle': '随时随地,Vibe Coding',
|
||
'login.bind.title': '绑定 Telegram',
|
||
'login.submit': '登录',
|
||
'login.bind.submit': '绑定',
|
||
'login.submitting': '登录中…',
|
||
'login.bind.submitting': '绑定中…',
|
||
'login.placeholder': '访问令牌',
|
||
'login.error.enterToken': '请输入访问令牌',
|
||
'login.error.bindingUnavailable': '绑定服务不可用。',
|
||
'login.error.loginUnavailable': '登录服务不可用。',
|
||
'login.error.bindFailed': '绑定失败',
|
||
'login.error.authFailed': '认证失败',
|
||
'login.help': '需要帮助?',
|
||
'login.server.default': '(默认)',
|
||
'login.server.custom': '(自定义)',
|
||
'login.server.title': '服务器地址',
|
||
'login.server.description': '设置 HAPI 服务器地址以使用 API 和实时更新。',
|
||
'login.server.current': '当前:',
|
||
'login.server.origin': '服务器地址',
|
||
'login.server.placeholder': 'https://hapi.example.com',
|
||
'login.server.hint': '仅使用 http(s) 协议。任何路径将被忽略。',
|
||
'login.server.required': '必须先填写服务器地址才能登录。',
|
||
'login.server.useSameOrigin': '使用同源',
|
||
'login.server.save': '保存',
|
||
'login.footer': '用',
|
||
'login.footer.for': '设计,Vibe Coding',
|
||
'login.footer.copyright': '©',
|
||
|
||
// Sessions page
|
||
'sessions.count': '{n} 个会话,{m} 个项目',
|
||
'sessions.new': '新建会话',
|
||
'sessions.empty.title': '还没有会话',
|
||
'sessions.empty.hint': '在 workspace 下任意目录启动一个会话,或先浏览目录树看看。',
|
||
'sessions.empty.startSession': '启动会话',
|
||
'sessions.empty.browse': '浏览 workspace',
|
||
'sessions.search.placeholder': '搜索会话…',
|
||
'sessions.search.clear': '清除搜索',
|
||
'sessions.search.count': '{n} / {total} 个会话',
|
||
'sessions.search.noResults': '没有匹配的会话。',
|
||
'sessions.group.showMore': '再显示 {n} 个',
|
||
'sessions.group.showLess': '收起',
|
||
|
||
// Session list
|
||
'session.item.path': '路径',
|
||
'session.item.agent': '代理',
|
||
'session.item.model': '模型',
|
||
'session.item.worktree': '工作树',
|
||
'session.item.pending': '待处理',
|
||
'session.item.thinking': '思考中',
|
||
'session.time.justNow': '刚刚',
|
||
'session.time.minutesAgo': '{n} 分钟前',
|
||
'session.time.hoursAgo': '{n} 小时前',
|
||
'session.time.daysAgo': '{n} 天前',
|
||
|
||
// Session header
|
||
'session.title': '文件',
|
||
'session.more': '更多操作',
|
||
'session.outline.open': '会话大纲',
|
||
'session.outline.close': '关闭大纲',
|
||
'session.outline.title': '大纲',
|
||
'session.outline.loadOlder': '加载更早',
|
||
'session.outline.empty': '已加载消息中暂无大纲项',
|
||
'session.outline.kind.user': '用户',
|
||
|
||
// Session actions
|
||
'session.action.rename': '重命名',
|
||
'session.action.archive': '归档',
|
||
'session.action.delete': '删除',
|
||
'session.action.copy': '复制',
|
||
|
||
// Dialogs
|
||
'dialog.rename.title': '重命名会话',
|
||
'dialog.rename.placeholder': '会话名称',
|
||
'dialog.rename.save': '保存',
|
||
'dialog.rename.saving': '保存中…',
|
||
'dialog.rename.error': '重命名失败,请重试。',
|
||
|
||
'dialog.archive.title': '归档会话',
|
||
'dialog.archive.description': '确定要归档 "{name}" 吗?这将断开活动会话。',
|
||
'dialog.archive.confirm': '归档',
|
||
'dialog.archive.confirming': '归档中…',
|
||
|
||
'dialog.delete.title': '删除会话',
|
||
'dialog.delete.description': '确定要删除 "{name}" 吗?此操作无法撤销。',
|
||
'dialog.delete.confirm': '删除',
|
||
'dialog.delete.confirming': '删除中…',
|
||
'dialog.error.default': '操作失败,请重试。',
|
||
|
||
// Common buttons
|
||
'button.cancel': '取消',
|
||
'button.save': '保存',
|
||
'button.confirm': '确认',
|
||
'button.close': '关闭',
|
||
'button.dismiss': '忽略',
|
||
'button.copy': '复制',
|
||
'button.paste': '粘贴',
|
||
|
||
// New session form
|
||
'newSession.title': '创建会话',
|
||
'newSession.machine': '机器',
|
||
'newSession.directory': '目录',
|
||
'newSession.placeholder': '/path/to/project',
|
||
'newSession.browse': '浏览',
|
||
'newSession.recent': '最近路径',
|
||
'newSession.type': '会话类型',
|
||
'newSession.type.simple': '简单',
|
||
'newSession.type.simple.desc': '直接使用选定的目录',
|
||
'newSession.type.worktree': '工作树',
|
||
'newSession.type.worktree.desc': '在仓库旁创建新工作树',
|
||
'newSession.type.worktree.placeholder': 'feature-x (默认 1228-xxxx)',
|
||
'newSession.agent': '代理',
|
||
'newSession.model': '模型',
|
||
'newSession.effort': '思考强度',
|
||
'newSession.model.optional': '可选',
|
||
'newSession.model.loadFailed': '加载 Codex 模型失败',
|
||
'newSession.opencodeModel.loading': '正在发现 OpenCode 模型…',
|
||
'newSession.opencodeModel.loadFailed': '加载 OpenCode 模型失败',
|
||
'newSession.opencodeModel.retry': '重试',
|
||
'newSession.opencodeModel.empty': '未在此目录发现 OpenCode 模型',
|
||
'newSession.opencodeModel.default': '默认',
|
||
'newSession.reasoningEffort': '推理强度',
|
||
'newSession.yolo': 'YOLO 模式',
|
||
'newSession.yolo.title': '跳过审批和沙箱',
|
||
'newSession.yolo.desc': '启动时使用危险的代理标志。',
|
||
'newSession.create': '创建',
|
||
'newSession.creating': '创建中…',
|
||
|
||
// Spawn session (old component)
|
||
'spawn.title': '创建会话',
|
||
'spawn.sessionType': '会话类型',
|
||
'spawn.useAsIs': '直接使用选定的目录',
|
||
'spawn.createWorktree': '在仓库旁创建新工作树',
|
||
'spawn.worktreePlaceholder': 'feature-x (默认 1228-xxxx)',
|
||
'spawn.cancel': '取消',
|
||
'spawn.create': '创建会话',
|
||
'spawn.creating': '创建中…',
|
||
'session.directoryMissingSimple': '目录不存在,创建会话时将自动创建。',
|
||
'session.directoryMissingSimpleConfirm': '目录不存在。再次点击按钮将自动新建该目录。',
|
||
'session.directoryMissingWorktree': 'worktree 需要已存在的仓库目录。',
|
||
'session.codexModelsLoadFailed': '加载 Codex 模型失败',
|
||
'session.createAndCreateDirectory': '创建并新建目录',
|
||
|
||
// Machine
|
||
'machine.unknown': '未知平台',
|
||
|
||
// Chat
|
||
'chat.placeholder': '输入消息…',
|
||
'chat.send': '发送',
|
||
'chat.abort': '中止',
|
||
'chat.settings': '设置',
|
||
'chat.terminal': '终端',
|
||
'chat.switchRemote': '切换到远程模式',
|
||
|
||
// Terminal
|
||
'terminal.commandName': '命令',
|
||
'terminal.commandMessage': '命令消息',
|
||
'terminal.commandArgs': '命令参数',
|
||
'terminal.stdout': '标准输出',
|
||
'terminal.stderr': '标准错误',
|
||
'terminal.unsupportedWindows': 'Windows 主机暂不支持远程终端。',
|
||
'terminal.paste.fallbackTitle': '粘贴输入',
|
||
'terminal.paste.fallbackDescription': '无法读取剪贴板,请在下方粘贴文本。',
|
||
'terminal.paste.placeholder': '在此粘贴终端输入…',
|
||
|
||
// Code block
|
||
'code.copy': '复制',
|
||
'code.truncated': '预览已截断 — 打开详情查看完整输出',
|
||
|
||
// Diff view
|
||
'diff.title': '差异',
|
||
'diff.view': '查看',
|
||
|
||
// Files page
|
||
'files.page.title': '文件',
|
||
'files.page.refresh': '刷新',
|
||
'files.page.searchPlaceholder': '搜索文件',
|
||
'files.projectRoot': '项目根目录',
|
||
'files.branch.detached': '游离 HEAD',
|
||
'files.branch.summary': '{staged} 个已暂存,{unstaged} 个未暂存',
|
||
'files.tab.changes': '变更',
|
||
'files.tab.directories': '目录',
|
||
'files.search.empty': '没有匹配搜索的文件。',
|
||
'files.search.error.failed': '搜索文件失败。',
|
||
'files.search.error.failedWithDetail': '搜索文件失败:{error}',
|
||
'files.changes.section.staged': '已暂存变更({n})',
|
||
'files.changes.section.unstaged': '未暂存变更({n})',
|
||
'files.changes.empty.unavailable': 'Git 状态不可用。请使用“目录”浏览全部文件,或直接搜索。',
|
||
'files.changes.empty.none': '未检测到变更。请使用“目录”浏览全部文件,或直接搜索。',
|
||
'files.changes.error.gitStatusUnavailable': 'Git 状态不可用。',
|
||
'files.changes.error.gitStatusUnavailableWithDetail': 'Git 状态不可用:{error}',
|
||
'files.changes.error.unstagedDiffUnavailableWithDetail': '未暂存 Diff 不可用:{error}',
|
||
'files.changes.error.stagedDiffUnavailableWithDetail': '已暂存 Diff 不可用:{error}',
|
||
'files.directories.empty': '空目录。',
|
||
'files.directories.error.listFailed': '加载目录失败。',
|
||
'files.directories.error.listFailedWithDetail': '加载目录失败:{error}',
|
||
|
||
// File page
|
||
'file.page.fallbackName': '文件',
|
||
'file.page.unknownPath': '未知路径',
|
||
'file.page.copyPath': '复制路径',
|
||
'file.page.copyContent': '复制文件内容',
|
||
'file.page.tab.diff': 'Diff',
|
||
'file.page.tab.file': '文件',
|
||
'file.page.missingPath': '未提供文件路径。',
|
||
'file.page.binary': '该文件看起来是二进制文件,无法显示。',
|
||
'file.page.empty': '文件为空。',
|
||
'file.page.noChanges': '没有可显示的变更。',
|
||
'file.error.readFailed': '读取文件失败。',
|
||
'file.error.readFailedWithDetail': '读取文件失败:{error}',
|
||
'file.error.diffUnavailable': 'Diff 不可用。',
|
||
'file.error.diffUnavailableWithDetail': 'Diff 不可用:{error}',
|
||
|
||
// Tool card
|
||
'tool.askQuestion': '其他',
|
||
'tool.edit': '编辑',
|
||
'tool.multiedit': '多文件编辑',
|
||
'tool.write': '写入',
|
||
'tool.todo': '任务',
|
||
'tool.confirm': '确认',
|
||
'tool.deny': '拒绝',
|
||
'tool.abort': '中止',
|
||
'tool.allow': '允许',
|
||
'tool.allowAll': '允许所有编辑',
|
||
'tool.denyAll': '拒绝所有编辑',
|
||
'tool.approved': '已批准',
|
||
'tool.rejected': '已拒绝',
|
||
'tool.cancel': '取消',
|
||
'tool.exitPlan': '退出计划模式',
|
||
'tool.patch': '补丁',
|
||
'tool.input': '输入',
|
||
'tool.trace': '追踪',
|
||
'tool.trace.callsSuffix': '次调用',
|
||
'tool.result': '结果',
|
||
'tool.semanticTitle.readFile': '读取文件',
|
||
'tool.semanticTitle.runShell': '运行命令',
|
||
'tool.semanticTitle.search': '搜索',
|
||
'tool.semanticTitle.openUrl': '打开链接',
|
||
'tool.semanticTitle.query': '查询',
|
||
'tool.questionsAnswers': '问答',
|
||
'tool.submit': '提交',
|
||
'tool.submitting': '提交中…',
|
||
'tool.prev': '← 上一个',
|
||
'tool.next': '下一个 →',
|
||
'tool.yes': '是',
|
||
'tool.yesForSession': '本会话允许',
|
||
'tool.allowForSession': '本会话允许',
|
||
'tool.abortLabel': '中止',
|
||
'tool.other': '其他',
|
||
'tool.otherDescription': '输入您自己的答案',
|
||
'tool.question': '问题',
|
||
'tool.selectOption': '请至少选择一个选项或输入答案。',
|
||
'tool.waitingForApproval': '等待审批…',
|
||
'tool.canceled': '已取消',
|
||
'tool.approvedForSession': '本会话已批准',
|
||
'tool.aborted': '已中止',
|
||
'tool.approvedAllowAllEdits': '已批准:允许所有编辑',
|
||
'tool.requestFailed': '请求失败',
|
||
'tool.askUserQuestion.fallback': 'AskUserQuestion 格式不正确。请输入您的答案:',
|
||
'tool.askUserQuestion.placeholder': '输入您的答案…',
|
||
'tool.askUserQuestion.otherPlaceholder': '或输入您自己的答案…',
|
||
'tool.requestUserInput.textPlaceholder': '输入您的答案…',
|
||
'tool.requestUserInput.noteLabel': '补充说明(可选)',
|
||
'tool.requestUserInput.notePlaceholder': '添加备注…',
|
||
'toolGroup.title': '工具活动',
|
||
'toolGroup.primary.fileTargets': '{target} 等 +{n}',
|
||
'toolGroup.primary.commandTargets': '{target} 等 +{n}',
|
||
'toolGroup.primary.searchTargets': '{target} 等 +{n}',
|
||
'toolGroup.primary.urlTargets': '{target} 等 +{n}',
|
||
'toolGroup.primary.otherTargets': '{target} 等 +{n}',
|
||
'toolGroup.summary.read': '读取 {n}',
|
||
'toolGroup.summary.mutation': '编辑 {n}',
|
||
'toolGroup.summary.command': '执行 {n}',
|
||
'toolGroup.summary.search': '搜索 {n}',
|
||
'toolGroup.summary.web': '访问 {n}',
|
||
'toolGroup.summary.other': '工具 {n}',
|
||
'toolGroup.badge.running': '运行中 {n}',
|
||
'toolGroup.badge.pending': '等待中 {n}',
|
||
'toolGroup.badge.error': '错误 {n}',
|
||
'toolGroup.badge.fileTargets': '{n} 文件',
|
||
'toolGroup.toolCount': '{n} 次 tool use',
|
||
'toolGroup.loadingOlderHistory': '正在补加载更早的工具活动…',
|
||
'toolGroup.historyUnavailable': '更早的工具活动已不可用。',
|
||
'toolGroup.rowStatus.running': '运行中',
|
||
'toolGroup.rowStatus.pending': '等待中',
|
||
'toolGroup.rowStatus.error': '错误',
|
||
|
||
// Composer buttons
|
||
'composer.settings': '设置',
|
||
'composer.terminal': '终端',
|
||
'composer.abort': '中止',
|
||
'composer.switchRemote': '切换到远程模式',
|
||
'composer.attach': '添加文件',
|
||
'composer.send': '发送',
|
||
'composer.stop': '停止',
|
||
'composer.voice': '语音助手',
|
||
'composer.codexSlashUnsupported.title': '无法执行 Codex 命令',
|
||
'composer.codexSlashUnsupported.body': 'HAPI 远程模式暂不支持 {command} 这类 Codex 内建 slash command,请改用自然语言,或在本地 Codex TUI 中执行。',
|
||
|
||
// Voice assistant
|
||
'voice.connecting': '连接中...',
|
||
'voice.active': '活跃',
|
||
'voice.muted': '已静音',
|
||
'voice.error': '错误',
|
||
'voice.mute': '静音',
|
||
'voice.unmute': '取消静音',
|
||
'voice.end': '结束',
|
||
'voice.error.micPermission': '麦克风权限被拒绝',
|
||
'voice.error.network': '网络错误',
|
||
'voice.error.notInitialized': '语音会话未初始化',
|
||
'voice.error.startFailed': '启动语音会话失败',
|
||
'voice.error.notAllowed': '语音功能不可用',
|
||
'voice.error.connection': '连接错误',
|
||
'voice.dismiss': '关闭',
|
||
|
||
// Banners
|
||
'offline.title': '离线',
|
||
'offline.message': '您当前处于离线状态。某些功能可能受限。',
|
||
'syncing.title': '同步中…',
|
||
'syncing.message': '正在同步您的数据。',
|
||
'reconnecting.message': '正在重新连接...',
|
||
'reconnecting.reason.error': '流连接错误',
|
||
'reconnecting.reason.closed': '流连接已关闭',
|
||
'reconnecting.reason.heartbeatTimeout': '心跳超时',
|
||
'reconnecting.reason.visibilityRecovery': '后台恢复中',
|
||
|
||
// Send blocked
|
||
'send.blocked.title': '无法发送消息',
|
||
'send.blocked.noConnection': '未连接到服务器',
|
||
'resume.failed.title': '恢复会话失败',
|
||
'toast.ready.title': '等待输入',
|
||
'toast.ready.body': '{agent} 正在 {session} 等待你的输入',
|
||
'toast.permission.title': '权限请求',
|
||
'toast.task.completed': '任务完成',
|
||
'toast.task.failed': '任务失败',
|
||
|
||
// Install prompt
|
||
'install.title': '安装 HAPI',
|
||
'install.description': '将 HAPI 添加到主屏幕以便快速访问。',
|
||
'install.button': '安装',
|
||
|
||
// Language switcher
|
||
'language.title': '语言',
|
||
'language.english': 'English',
|
||
'language.chinese': '简体中文',
|
||
|
||
// Settings page
|
||
'settings.title': '设置',
|
||
'settings.language.title': '语言',
|
||
'settings.language.label': '语言',
|
||
'settings.display.title': '显示',
|
||
'settings.display.appearance': '外观',
|
||
'settings.display.appearance.system': '跟随系统',
|
||
'settings.display.appearance.dark': '深色',
|
||
'settings.display.appearance.light': '浅色',
|
||
'settings.display.fontSize': '字体大小',
|
||
'settings.display.terminalFontSize': '终端字体大小',
|
||
'settings.chat.title': '聊天',
|
||
'settings.chat.enterBehavior': '回车键行为',
|
||
'settings.chat.enterBehavior.send': '发送消息',
|
||
'settings.chat.enterBehavior.newline': '插入换行',
|
||
'settings.chat.terminalToolDisplay': '终端工具卡片',
|
||
'settings.chat.terminalToolDisplay.compact': '简洁(仅命令)',
|
||
'settings.chat.terminalToolDisplay.detailed': '详细(显示输出预览)',
|
||
'settings.voice.title': '语音助手',
|
||
'settings.voice.language': '语音语言',
|
||
'settings.voice.autoDetect': '自动检测',
|
||
'settings.about.title': '关于',
|
||
'settings.about.website': '官方网站',
|
||
'settings.about.appVersion': '应用版本',
|
||
'settings.about.protocolVersion': '协议版本',
|
||
|
||
// Browse / Workspace
|
||
'browse.title': '浏览',
|
||
'browse.goUp': '返回上层',
|
||
'browse.empty': '未找到子目录',
|
||
'browse.refresh': '刷新',
|
||
'browse.startSession': '启动会话',
|
||
'browse.nav': '浏览',
|
||
'browse.noRootTitle': '未启用 workspace 浏览',
|
||
'browse.noRootHint': '浏览功能是可选的。带一个或多个 --workspace-root 参数重启 runner,即可启用文件树浏览和受限的会话启动。',
|
||
'browse.noRootFooter': '你仍然可以在「新建会话」页面直接创建会话。',
|
||
'browse.noMachinesConnected': '没有已连接的 CLI。在某台机器上运行 `hapi runner start --workspace-root /path/a --workspace-root /path/b` 来开始。',
|
||
|
||
// Misc
|
||
'misc.noMachines': '无可用机器',
|
||
'misc.machine': '机器',
|
||
'misc.collaborationMode': '协作模式',
|
||
'misc.permissionMode': '权限模式',
|
||
'misc.model': '模型',
|
||
'misc.reasoningEffort': '推理强度',
|
||
'misc.effort': '思考强度',
|
||
'misc.loading': '加载中…',
|
||
'misc.loadOlder': '加载更早的',
|
||
'misc.newMessage': '{n} 条新消息',
|
||
'misc.loadingMessages': '加载消息中…',
|
||
'misc.typeMessage': "输入 'continue' 继续...",
|
||
'misc.typeAMessage': '输入消息...',
|
||
'misc.offline': '离线',
|
||
'misc.permissionRequired': '需要权限',
|
||
'misc.percentLeft': '剩余 {percent}%',
|
||
'misc.online': '在线',
|
||
} as const
|