diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index 73676d9e..cf7116de 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -36,7 +36,15 @@ jobs: - uses: actions/checkout@v4 - name: Show toolchain versions run: xcodebuild -version + - name: Check manual localization catalog + env: + PYTHONDONTWRITEBYTECODE: '1' + run: | + python3 ios/scripts/localizations.py --check + python3 -m unittest discover -s ios/scripts/tests -p 'test_localizations.py' - name: Build Hapi app for iOS Simulator run: xcodebuild build -project ios/Hapi.xcodeproj -scheme Hapi -destination 'generic/platform=iOS Simulator' CODE_SIGNING_ALLOWED=NO - name: Transcript layout regression tests run: ios/scripts/test-transcript.sh + - name: Verify localization catalog was not rewritten + run: git diff --exit-code -- ios/Hapi/Resources/Localizable.xcstrings diff --git a/ios/Hapi/Resources/Localizable.xcstrings b/ios/Hapi/Resources/Localizable.xcstrings index 62ffa946..78a29b4c 100644 --- a/ios/Hapi/Resources/Localizable.xcstrings +++ b/ios/Hapi/Resources/Localizable.xcstrings @@ -1,4806 +1,5286 @@ { - "sourceLanguage": "en", - "strings": { - "%@\n\nOpen a session chat to browse its files.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%@\n\n打开会话聊天即可浏览其文件。" + "sourceLanguage" : "en", + "strings" : { + "%@\n\nOpen a session chat to browse its files." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@\n\n打开会话聊天即可浏览其文件。" } } } }, - "%@ (%lld edits)": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%@(%lld 处编辑)" + "%@ (%lld edits)" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@(%lld 处编辑)" } } } }, - "%@ (+%lld more)": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%@(另有 %lld 个)" + "%@ (+%lld more)" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@(另有 %lld 个)" } } } }, - "%@ (optional)": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%@(可选)" + "%@ (optional)" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@(可选)" } } } }, - "%@ is over the 50 MB upload limit": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%@ 超过 50 MB 上传上限" + "%@ is over the 50 MB upload limit" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ 超过 50 MB 上传上限" } } } }, - "%@ log": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%@ 日志" + "%@ log" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ 日志" } } } }, - "%@ rejected its stored credentials and was signed out. Pair it again from the hub menu.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%@ 拒绝了已保存的凭据,已退出登录。请从 Hub 菜单重新配对。" + "%@ rejected its stored credentials and was signed out. Pair it again from the hub menu." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ 拒绝了已保存的凭据,已退出登录。请从 Hub 菜单重新配对。" } } } }, - "%@ tokens · %lld req · in %@ / out %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%@ Token · %lld 次请求 · 输入 %@ / 输出 %@" + "%@ tokens · %lld req · in %@ / out %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Token · %lld 次请求 · 输入 %@ / 输出 %@" } } } }, - "%lld Questions": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 个问题" + "%lld Questions" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 个问题" } } } }, - "%lld agent steps": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 个代理步骤" + "%lld agent steps" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 个代理步骤" } } } }, - "%lld chars": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 个字符" + "%lld chars" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 个字符" } } } }, - "%lld findings": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 条发现" + "%lld commands" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 条命令" } } } }, - "%lld lines": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 行" + "%lld edits" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 次修改" } } } }, - "%lld new messages ↓": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 条新消息 ↓" + "%lld failed tools" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 个工具失败" } } } }, - "%lld notes": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 条笔记" + "%lld findings" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 条发现" } } } }, - "%lld queued messages": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 条排队消息" + "%lld lines" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 行" } } } }, - "%lld requests · in %@ · out %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 次请求 · 输入 %@ · 输出 %@" + "%lld new messages ↓" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 条新消息 ↓" } } } }, - "%lld staged · %lld unstaged": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 个已暂存 · %lld 个未暂存" + "%lld notes" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 条笔记" } } } }, - "%lld tools": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 个工具" + "%lld other tools" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 个其他工具" } } } }, - "(empty)": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "(空)" + "%lld queued messages" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 条排队消息" } } } }, - "0 tokens": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "0 Token" + "%lld reads" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 次读取" } } } }, - "1 agent step": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 个代理步骤" + "%lld requests · in %@ · out %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 次请求 · 输入 %@ · 输出 %@" } } } }, - "1 finding": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 条发现" + "%lld searches" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 次搜索" } } } }, - "1 new message ↓": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 条新消息 ↓" + "%lld staged · %lld unstaged" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 个已暂存 · %lld 个未暂存" } } } }, - "1 note": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 条笔记" + "%lld tool calls" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 次工具调用" } } } }, - "1 queued message": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 条排队消息" + "%lld tools" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 个工具" } } } }, - "1 tool": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 个工具" + "%lld web requests" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 次网络请求" } } } }, - "30 days": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "近 30 天" + "(empty)" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "(空)" } } } }, - "7 days": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "近 7 天" + "0 tokens" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "0 Token" } } } }, - "A note can hold at most %lld attachments": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "每条笔记最多 %lld 个附件" + "1 agent step" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 个代理步骤" } } } }, - "Abort": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "中止" + "1 command" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 条命令" } } } }, - "About": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "关于" + "1 edit" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 次修改" } } } }, - "Access token": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "访问令牌" + "1 finding" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 条发现" } } } }, - "Action failed": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "操作失败" + "1 new message ↓" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 条新消息 ↓" } } } }, - "Active": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "活跃" + "1 note" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 条笔记" } } } }, - "Add Hub": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "添加 Hub" + "1 other tool" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 个其他工具" } } } }, - "Add Hub…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "添加 Hub…" + "1 queued message" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 条排队消息" } } } }, - "Add a note…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "添加备注…" + "1 read" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 次读取" } } } }, - "Add another hub": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "添加另一个 Hub" + "1 search" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 次搜索" } } } }, - "Add attachment": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "添加附件" + "1 tool" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 个工具" } } } }, - "Add photo": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "添加照片" + "1 tool call" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 次工具调用" } } } }, - "After": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "修改后" + "1 web request" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 次网络请求" } } } }, - "Agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "代理" + "30 days" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "近 30 天" } } } }, - "Agent Mode": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "代理模式" + "7 days" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "近 7 天" } } } }, - "Agent: %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "代理:%@" + "A note can hold at most %lld attachments" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "每条笔记最多 %lld 个附件" } } } }, - "All": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "全部" + "Abort" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "中止" } } } }, - "All time": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "全部时间" + "About" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关于" } } } }, - "Allow": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "允许" + "Access token" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "访问令牌" } } } }, - "Allow all edits": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "允许所有编辑" + "Action failed" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "操作失败" } } } }, - "Allow camera access in Settings to scan the pairing QR, or go back and use manual entry.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "请在「设置」中允许访问相机以扫描配对二维码,或返回使用手动输入。" + "Active" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "活跃" } } } }, - "Allow for this session": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "本会话允许" + "Add Hub" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加 Hub" } } } }, - "Already delivered to the agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已送达智能体" + "Add Hub…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加 Hub…" } } } }, - "Already handled elsewhere": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已在其他位置处理" + "Add a note…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加备注…" } } } }, - "Already handled elsewhere.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已在其他设备上处理。" + "Add another hub" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加另一个 Hub" } } } }, - "Already paired with %@ — switched to it.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已与 %@ 配对 — 已切换过去。" + "Add attachment" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加附件" } } } }, - "Answer every question first": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "请先回答所有问题" + "Add photo" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加照片" } } } }, - "Answer every required question first": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "请先回答所有必答问题" + "After" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "修改后" } } } }, - "App language": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "应用语言" + "Agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "代理" } } } }, - "App version": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "应用版本" + "Agent Mode" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "代理模式" } } } }, - "Appearance": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "外观" + "Agent process" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "子代理执行过程" } } } }, - "Applies after the app is relaunched.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "重新启动应用后生效。" + "Agent: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "代理:%@" } } } }, - "Apply changes": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "应用变更" + "All" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "全部" } } } }, - "Archive": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "归档" + "All time" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "全部时间" } } } }, - "Archive failed: %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "归档失败:%@" + "Allow" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "允许" } } } }, - "Attach": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "添加附件" + "Allow all edits" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "允许所有编辑" } } } }, - "Attachment only": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "仅附件" + "Allow camera access in Settings to scan the pairing QR, or go back and use manual entry." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请在「设置」中允许访问相机以扫描配对二维码,或返回使用手动输入。" } } } }, - "Attachments are still uploading — wait, or retry/remove the failed ones": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "附件仍在上传 — 请稍候,或重试/移除失败的附件" + "Allow for this session" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "本会话允许" } } } }, - "Audio recording failed": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "录音失败" + "Already delivered to the agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已送达智能体" } } } }, - "Awaiting approval": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "等待审批" + "Already handled elsewhere" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已在其他位置处理" } } } }, - "Back to latest": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "回到最新" + "Already handled elsewhere." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已在其他设备上处理。" } } } }, - "Background task": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "后台任务" + "Already paired with %@ — switched to it." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已与 %@ 配对 — 已切换过去。" } } } }, - "Before": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "修改前" + "Answer every question first" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请先回答所有问题" } } } }, - "Beginning of conversation": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已到会话起点" + "Answer every required question first" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请先回答所有必答问题" } } } }, - "Binary file not shown": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "二进制文件未显示" + "App language" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "应用语言" } } } }, - "Binary file — no preview available": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "二进制文件 — 无法预览" + "App version" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "应用版本" } } } }, - "Broadcast": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "广播" + "Appearance" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "外观" } } } }, - "Browse": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "浏览" + "Applies after the app is relaunched." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重新启动应用后生效。" } } } }, - "By agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "按 Agent" + "Apply changes" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "应用变更" } } } }, - "By model": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "按模型" + "Archive" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "归档" } } } }, - "Bypass approvals and sandbox": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "跳过审批和沙箱" + "Archive failed: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "归档失败:%@" } } } }, - "Cache creation": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "缓存创建" + "Attach" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加附件" } } } }, - "Cache hit rate": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "缓存命中率" + "Attachment only" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "仅附件" } } } }, - "Cache read": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "缓存命中" + "Attachments are still uploading — wait, or retry/remove the failed ones" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "附件仍在上传 — 请稍候,或重试/移除失败的附件" } } } }, - "Camera": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "相机" + "Audio recording failed" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "录音失败" } } } }, - "Camera access denied": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "相机权限被拒绝" + "Awaiting approval" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "等待审批" } } } }, - "Cancel": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "取消" + "Back to latest" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "回到最新" } } } }, - "Changes": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "变更" + "Background task" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "后台任务" } } } }, - "Check the connection to your hub and try again.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "请检查与 Hub 的连接后重试。" + "Before" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "修改前" } } } }, - "Checking hub…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "正在检查 Hub…" + "Beginning of conversation" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已到会话起点" } } } }, - "Close": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "关闭" + "Binary file not shown" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "二进制文件未显示" } } } }, - "Close agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "关闭代理" + "Binary file — no preview available" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "二进制文件 — 无法预览" } } } }, - "Code review": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Code review" + "Broadcast" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "广播" } } } }, - "Collaboration Mode": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "协作模式" + "Browse" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "浏览" } } } }, - "Connecting…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "连接中…" + "By agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "按 Agent" } } } }, - "Connection: %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "连接状态:%@" + "By model" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "按模型" } } } }, - "Continue loading history": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "继续加载历史" + "Bypass approvals and sandbox" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "跳过审批和沙箱" } } } }, - "Copy Contents": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "复制文件内容" + "Cache creation" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "缓存创建" } } } }, - "Copy Path": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "复制路径" + "Cache hit rate" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "缓存命中率" } } } }, - "Could not load this dashboard.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法加载此看板。" + "Cache read" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "缓存命中" } } } }, - "Could not reach the hub": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法连接 Hub" + "Camera" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "相机" } } } }, - "Could not reach your hub. Open HAPI to respond.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法连接 Hub。请打开 HAPI 进行回应。" + "Camera access denied" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "相机权限被拒绝" } } } }, - "Could not save": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法保存" + "Cancel" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "取消" } } } }, - "Could not start recording": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法开始录音" + "Changes" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "变更" } } } }, - "Could not store the push key.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法保存推送密钥。" + "Check the connection to your hub and try again." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请检查与 Hub 的连接后重试。" } } } }, - "Couldn't attach the file — check the hub connection": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法附加文件 — 请检查 Hub 连接" + "Checking hub…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "正在检查 Hub…" } } } }, - "Couldn't delete the note — check the hub connection": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法删除笔记 — 请检查 Hub 连接" + "Checking installed Agents…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "正在检查已安装的代理…" } } } }, - "Couldn't load history. Tap to retry.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "历史加载失败,点此重试" + "Choose Directory" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "选择目录" } } } }, - "Couldn't load the scratchlist": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法加载草稿夹" + "Close" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭" } } } }, - "Couldn't load this session": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法加载此会话" + "Close agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭代理" } } } }, - "Couldn't park the draft — check the hub connection": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法暂存草稿 — 请检查 Hub 连接" + "Close details to approve or answer in the conversation." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭详情后,可在对话中审批或回答。" } } } }, - "Couldn't read %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法读取 %@" + "Code review" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Code review" } } } }, - "Couldn't read the selected photo": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法读取所选照片" + "Collaboration Mode" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "协作模式" } } } }, - "Couldn't read the selected video": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法读取所选视频" + "Collapsed" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已折叠" } } } }, - "Couldn't remove the attachment — check the hub connection": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法移除附件 — 请检查 Hub 连接" + "Completed" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已完成" } } } }, - "Couldn't save the note — check the hub connection": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法保存笔记 — 请检查 Hub 连接" + "Connecting…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "连接中…" } } } }, - "Create": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "创建" + "Connection: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "连接状态:%@" } } } }, - "Create Team": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "创建团队" + "Continue command" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "继续命令" } } } }, - "Create a new git worktree next to the repo": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "在仓库旁创建新的 git 工作树" + "Continue loading history" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "继续加载历史" } } } }, - "Create and Make Directory": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "创建并新建目录" + "Copy" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "复制" } } } }, - "Creating…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "创建中…" + "Copy Contents" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "复制文件内容" } } } }, - "Daily tokens": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "每日 Token" + "Copy Path" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "复制路径" } } } }, - "Dark": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "深色" + "Copy full content" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "复制完整内容" } } } }, - "Database": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "数据库" + "Copy input" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "复制输入" } } } }, - "Delete": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "删除" + "Copy result" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "复制结果" } } } }, - "Delete Team": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "删除团队" + "Could not load this dashboard." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法加载此看板。" } } } }, - "Denied": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已拒绝" + "Could not reach the hub" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法连接 Hub" } } } }, - "Deny": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "拒绝" + "Could not reach your hub. Open HAPI to respond." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法连接 Hub。请打开 HAPI 进行回应。" } } } }, - "Detached HEAD": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "游离 HEAD" + "Could not save" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法保存" } } } }, - "Dictate": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "语音输入" + "Could not start recording" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法开始录音" } } } }, - "Diff": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Diff" + "Could not store the push key." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法保存推送密钥。" } } } }, - "Directory": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "目录" + "Couldn't attach the file — check the hub connection" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法附加文件 — 请检查 Hub 连接" } } } }, - "Directory does not exist. Creating the session will create it automatically.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "目录不存在,创建会话时将自动创建。" + "Couldn't delete the note — check the hub connection" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法删除笔记 — 请检查 Hub 连接" } } } }, - "Directory does not exist. Tap Create again to create it automatically.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "目录不存在。再次点按「创建」将自动新建该目录。" + "Couldn't load history. Tap to retry." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "历史加载失败,点此重试" } } } }, - "Disk footprint of the hub's SQLite database (database, write-ahead log, shared memory).": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub SQLite 数据库的磁盘占用(数据库、预写日志、共享内存)。" + "Couldn't load the scratchlist" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法加载草稿夹" } } } }, - "Done": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "完成" + "Couldn't load this session" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法加载此会话" } } } }, - "Draft parked to scratchlist": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "草稿已存入草稿夹" + "Couldn't park the draft — check the hub connection" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法暂存草稿 — 请检查 Hub 连接" } } } }, - "Edit": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "编辑" + "Couldn't read %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法读取 %@" } } } }, - "Edit %lld/%lld": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "编辑 %lld/%lld" + "Couldn't read the selected photo" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法读取所选照片" } } } }, - "Edit file": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "编辑文件" + "Couldn't read the selected video" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法读取所选视频" } } } }, - "Edit note": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "编辑笔记" + "Couldn't remove the attachment — check the hub connection" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法移除附件 — 请检查 Hub 连接" } } } }, - "Edit notebook": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "编辑笔记本" + "Couldn't save the note — check the hub connection" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法保存笔记 — 请检查 Hub 连接" } } } }, - "Effort": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "思考强度" + "Create" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "创建" } } } }, - "Enable in system settings…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "在系统设置中开启…" + "Create Team" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "创建团队" } } } }, - "Enabled": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已开启" + "Create a new git worktree next to the repo" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在仓库旁创建新的 git 工作树" } } } }, - "Enter Hub Details": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "输入 Hub 信息" + "Create and Make Directory" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "创建并新建目录" } } } }, - "Enter Manually": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "手动输入" + "Creating…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "创建中…" } } } }, - "Enter the hub's full address, e.g. http://192.168.1.20:3006.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "请输入 Hub 的完整地址,例如 http://192.168.1.20:3006。" + "Current Directory" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "当前目录" } } } }, - "Error": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "错误" + "Daily tokens" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "每日 Token" } } } }, - "Failed to abort": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "中止失败" + "Dark" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "深色" } } } }, - "Failed to cancel queued message": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "取消排队消息失败" + "Database" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "数据库" } } } }, - "Failed to create session": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "创建会话失败" + "Delete" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "删除" } } } }, - "Failed to list directory": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载目录失败" + "Delete Team" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "删除团队" } } } }, - "Failed to load Codex models": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载 Codex 模型失败" + "Denied" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已拒绝" } } } }, - "Failed to load diff": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载 Diff 失败" + "Deny" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "拒绝" } } } }, - "Failed to load models": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载模型失败" + "Detached HEAD" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "游离 HEAD" } } } }, - "Failed to load models: %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载模型失败:%@" + "Dictate" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "语音输入" } } } }, - "Failed to load older messages": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载更早消息失败" + "Diff" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Diff" } } } }, - "Failed to read file": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "读取文件失败" + "Directory" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "目录" } } } }, - "Failed to search files": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "搜索文件失败" + "Directory does not exist. Creating the session will create it automatically." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "目录不存在,创建会话时将自动创建。" } } } }, - "Failed to steer message": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "插入消息失败" + "Directory does not exist. Tap Create again to create it automatically." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "目录不存在。再次点按「创建」将自动新建该目录。" } } } }, - "Failed to synchronize messages": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "同步消息失败" + "Directory must be inside one of this machine's workspace roots." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "目录必须位于此机器配置的某个工作区根目录内。" } } } }, - "Failed to update session": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "更新会话失败" + "Disk footprint of the hub's SQLite database (database, write-ahead log, shared memory)." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub SQLite 数据库的磁盘占用(数据库、预写日志、共享内存)。" } } } }, - "Failed — tap to retry": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "失败 — 点按重试" + "Done" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "完成" } } } }, - "Fast": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "快速" + "Draft parked to scratchlist" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "草稿已存入草稿夹" } } } }, - "Fast Mode": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "快速模式" + "Edit" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "编辑" } } } }, - "Fetching the session list from the hub.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "正在从 Hub 获取会话列表。" + "Edit %lld/%lld" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "编辑 %lld/%lld" } } } }, - "File": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "文件" + "Edit file" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "编辑文件" } } } }, - "File actions": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "文件操作" + "Edit note" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "编辑笔记" } } } }, - "Files": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "文件" + "Edit notebook" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "编辑笔记本" } } } }, - "Follow system": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "跟随系统" + "Effort" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "思考强度" } } } }, - "Git status unavailable": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Git 状态不可用" + "Enable in system settings…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在系统设置中开启…" } } } }, - "Git status unavailable for this session": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此会话的 Git 状态不可用" + "Enabled" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已开启" } } } }, - "HAPI is self-hosted: your agent sessions run on your own machine, served by a hub you operate. Start the hub on your computer, then pair this app with the QR code it prints — or enter the hub URL and access token by hand.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "HAPI 是自托管的:你的智能体会话运行在你自己的机器上,由你自己运营的 Hub 提供服务。先在电脑上启动 Hub,然后用它打印的二维码配对本应用 — 也可以手动输入 Hub 地址和访问令牌。" + "Enter Hub Details" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入 Hub 信息" } } } }, - "Hub": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub" + "Enter Manually" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "手动输入" } } } }, - "Hub URL": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 地址" + "Enter the hub's full address, e.g. http://192.168.1.20:3006." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请输入 Hub 的完整地址,例如 http://192.168.1.20:3006。" } } } }, - "Hub already paired": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 已配对" + "Error" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "错误" } } } }, - "Hub database size on disk": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 数据库磁盘占用" + "Expanded" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已展开" } } } }, - "Hub error": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 错误" + "Failed to abort" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "中止失败" } } } }, - "Hub unreachable": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法连接 Hub" + "Failed to browse directories" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "浏览目录失败" } } } }, - "Hub unreachable — tap to retry.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法连接 Hub — 点按重试。" + "Failed to cancel queued message" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "取消排队消息失败" } } } }, - "Hubs": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub" + "Failed to check installed Agents" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "检查已安装代理失败" } } } }, - "Image is too large even after compression": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "图片压缩后仍然过大" + "Failed to create session" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "创建会话失败" } } } }, - "Inactive": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "未活跃" + "Failed to list directory" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载目录失败" } } } }, - "Input": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "输入" + "Failed to load Codex models" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载 Codex 模型失败" } } } }, - "Insights": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "统计" + "Failed to load diff" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载 Diff 失败" } } } }, - "Inspecting task log": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "查看任务日志" + "Failed to load models" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载模型失败" } } } }, - "Interrupt agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "中断代理" + "Failed to load models: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载模型失败:%@" } } } }, - "Invalid hub URL": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 地址无效" + "Failed to load older messages" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载更早消息失败" } } } }, - "Language": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "语言" + "Failed to read file" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "读取文件失败" } } } }, - "Launch Agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "启动代理" + "Failed to search files" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索文件失败" } } } }, - "Light": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "浅色" + "Failed to steer message" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "插入消息失败" } } } }, - "Line %lld": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "第 %lld 行" + "Failed to synchronize messages" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "同步消息失败" } } } }, - "List agents": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "列出代理" + "Failed to update session" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "更新会话失败" } } } }, - "List files": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "列出文件" + "Failed — tap to retry" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "失败 — 点按重试" } } } }, - "Live": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "实时" + "Fast" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "快速" } } } }, - "Live updates interrupted — reconnecting…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "实时更新已中断 — 正在重连…" + "Fast Mode" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "快速模式" } } } }, - "Load older messages": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载更早消息" + "Fetching the session list from the hub." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "正在从 Hub 获取会话列表。" } } } }, - "Loading machines…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载机器…" + "File" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "文件" } } } }, - "Loading messages…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载消息…" + "File actions" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "文件操作" } } } }, - "Loading models…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载模型中…" + "Files" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "文件" } } } }, - "Loading older messages…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载更早消息…" + "Follow system" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "跟随系统" } } } }, - "Loading sessions…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "正在加载会话…" + "Git status unavailable" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git 状态不可用" } } } }, - "Loading…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载中…" + "Git status unavailable for this session" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此会话的 Git 状态不可用" } } } }, - "Machine": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "机器" + "HAPI is self-hosted: your agent sessions run on your own machine, served by a hub you operate. Start the hub on your computer, then pair this app with the QR code it prints — or enter the hub URL and access token by hand." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "HAPI 是自托管的:你的智能体会话运行在你自己的机器上,由你自己运营的 Hub 提供服务。先在电脑上启动 Hub,然后用它打印的二维码配对本应用 — 也可以手动输入 Hub 地址和访问令牌。" } } } }, - "Managed by agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "由代理管理" + "Hub" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub" } } } }, - "Message": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "消息" + "Hub URL" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 地址" } } } }, - "Message agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "发消息给代理" + "Hub already paired" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 已配对" } } } }, - "Message cancelled — kept your current draft": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "消息已取消 — 已保留当前草稿" + "Hub database size on disk" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 数据库磁盘占用" } } } }, - "Message the agent…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "输入消息…" + "Hub error" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 错误" } } } }, - "Message: %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "消息:%@" + "Hub unreachable" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法连接 Hub" } } } }, - "Messages will appear here as the agent works.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "智能体工作时,消息会显示在这里。" + "Hub unreachable — tap to retry." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法连接 Hub — 点按重试。" } } } }, - "Microphone access is disabled — allow it in Settings to dictate": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "麦克风权限已被禁用 — 请在「设置」中允许后再使用语音输入" + "Hubs" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub" } } } }, - "Microphone permission is needed for dictation": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "语音输入需要麦克风权限" + "Image is too large even after compression" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "图片压缩后仍然过大" } } } }, - "Model": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "模型" + "Inactive" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未活跃" } } } }, - "Model list unavailable for this session.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此会话暂无可用模型列表。" + "Input" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入" } } } }, - "Name needs at least one letter or digit": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "名称需要至少一个字母或数字" + "Insights" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "统计" } } } }, - "New Session": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "新建会话" + "Inspecting task log" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查看任务日志" } } } }, - "New note": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "新建笔记" + "Interrupt agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "中断代理" } } } }, - "No HAPI hub answered at this address. Check that the hub is running and that this device can reach it (same network, or the relay tunnel is up).": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "该地址没有 HAPI Hub 应答。请确认 Hub 正在运行,且本设备能够访问它(处于同一网络,或中继隧道已开启)。" + "Invalid hub URL" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 地址无效" } } } }, - "No audio was recorded": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "未录到任何音频" + "Language" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "语言" } } } }, - "No changes in the working tree": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "工作区暂无变更" + "Launch Agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "启动代理" } } } }, - "No changes in this file": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此文件没有变更" + "Light" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "浅色" } } } }, - "No files matched": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "没有匹配的文件" + "Line %lld" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "第 %lld 行" } } } }, - "No machines online": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "没有在线机器" + "List agents" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "列出代理" } } } }, - "No messages yet": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "还没有消息" + "List files" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "列出文件" } } } }, - "No notes": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "暂无笔记" + "Live" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "实时" } } } }, - "No notes yet": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "还没有笔记" + "Live updates interrupted — reconnecting…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "实时更新已中断 — 正在重连…" } } } }, - "No sessions yet": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "还没有会话" + "Load more content" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载更多内容" } } } }, - "No storage data reported.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "暂无存储数据。" + "Load older messages" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载更早消息" } } } }, - "No transcription provider configured on hub": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 尚未配置转录提供商" + "Loading machines…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载机器…" } } } }, - "No usage recorded in this period.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此范围内没有记录到 Token 用量。" + "Loading messages…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载消息…" } } } }, - "Not delivered": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "未送达" + "Loading models…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载模型中…" } } } }, - "Not delivered — tap to retry": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "未送达 — 点按重试" + "Loading older messages…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载更早消息…" } } } }, - "Not requested": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "未请求" + "Loading sessions…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "正在加载会话…" } } } }, - "Note, draft, parking-lot idea…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "笔记、草稿或想法…" + "Loading…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载中…" } } } }, - "Notifications": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "通知" + "Machine" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "机器" } } } }, - "OK": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "好" + "Managed by agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "由代理管理" } } } }, - "OLED black": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "OLED 纯黑" + "Message" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "消息" } } } }, - "Offline": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "离线" + "Message agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "发消息给代理" } } } }, - "Offline — showing cached sessions": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "离线 — 显示缓存的会话" + "Message cancelled — kept your current draft" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "消息已取消 — 已保留当前草稿" } } } }, - "Open": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "打开" + "Message the agent…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入消息…" } } } }, - "Open Settings": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "打开设置" + "Message: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "消息:%@" } } } }, - "Open URL": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "打开链接" + "Messages will appear here as the agent works." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "智能体工作时,消息会显示在这里。" } } } }, - "Open link?": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "打开此链接?" + "Microphone access is disabled — allow it in Settings to dictate" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "麦克风权限已被禁用 — 请在「设置」中允许后再使用语音输入" } } } }, - "Options": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "选项" + "Microphone permission is needed for dictation" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "语音输入需要麦克风权限" } } } }, - "Other…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "其他…" + "Model" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "模型" } } } }, - "Output": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "输出" + "Model list unavailable for this session." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此会话暂无可用模型列表。" } } } }, - "Pair": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "配对" + "Name needs at least one letter or digit" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "名称需要至少一个字母或数字" } } } }, - "Pair with your hub": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "与你的 Hub 配对" + "New Session" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "新建会话" } } } }, - "Pairing succeeded but the credentials could not be stored on this device. Try again.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "配对成功,但凭据无法保存到此设备。请重试。" + "New note" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "新建笔记" } } } }, - "Pairing…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "配对中…" + "Next tool" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "下一个工具" } } } }, - "Park current draft": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "暂存当前草稿" + "No HAPI hub answered at this address. Check that the hub is running and that this device can reach it (same network, or the relay tunnel is up)." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "该地址没有 HAPI Hub 应答。请确认 Hub 正在运行,且本设备能够访问它(处于同一网络,或中继隧道已开启)。" } } } }, - "Park drafts from the header, or tap + to jot a note for this session.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "从顶部暂存草稿,或点按 + 为此会话记一条笔记。" + "No agent steps available yet." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "暂无可显示的子代理步骤。" } } } }, - "Path": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "路径" + "No audio was recorded" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未录到任何音频" } } } }, - "Paused": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已暂停" + "No changes in the working tree" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "工作区暂无变更" } } } }, - "Permission Mode": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "权限模式" + "No changes in this file" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此文件没有变更" } } } }, - "Permission mode": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "权限模式" + "No files matched" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "没有匹配的文件" } } } }, - "Permission request": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "权限请求" + "No machines online" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "没有在线机器" } } } }, - "Permission: %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "权限:%@" + "No messages yet" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "还没有消息" } } } }, - "Photo library": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "照片图库" + "No notes" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "暂无笔记" } } } }, - "Pin Globally": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "全局置顶" + "No notes yet" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "还没有笔记" } } } }, - "Pin failed: %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "置顶操作失败:%@" + "No output" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无输出" } } } }, - "Pin to Project": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "项目置顶" + "No sessions yet" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "还没有会话" } } } }, - "Pinned": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "置顶" + "No storage data reported." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "暂无存储数据。" } } } }, - "Plan": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "计划" + "No subdirectories" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "没有子目录" } } } }, - "Plan proposal": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "计划提案" + "No supported Agents are installed on this machine." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此机器上没有安装受支持的代理。" } } } }, - "Point the camera at the pairing QR from the hub terminal or the web app's Companion Pairing settings.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "将相机对准 Hub 终端或网页版「伴侣应用配对」设置中的配对二维码。" + "No transcription provider configured on hub" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 尚未配置转录提供商" } } } }, - "Preview": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "预览" + "No usage recorded in this period." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此范围内没有记录到 Token 用量。" } } } }, - "Preview not available for this image format": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此图片格式不支持预览" + "Not delivered" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未送达" } } } }, - "Printed by the hub at startup, and shown in the web app under Settings → Companion Pairing. Pasting a full pairing link into either field also works.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 启动时打印,也显示在网页版「设置 → 伴侣应用配对」中。将完整配对链接粘贴到任一输入框同样有效。" + "Not delivered — tap to retry" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未送达 — 点按重试" } } } }, - "Privacy Policy": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "隐私政策" + "Not requested" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未请求" } } } }, - "Project root": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "项目根目录" + "Note, draft, parking-lot idea…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "笔记、草稿或想法…" } } } }, - "Protocol version": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "协议版本" + "Notifications" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "通知" } } } }, - "Pull to retry once you are back online.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "恢复在线后下拉重试。" + "OK" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "好" } } } }, - "Push notifications": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "推送通知" + "OLED black" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "OLED 纯黑" } } } }, - "Pushes are end-to-end encrypted; only this device can read them.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "推送经过端到端加密,只有本机可以读取。" + "Offline" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "离线" } } } }, - "Query": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "查询" + "Offline — showing cached sessions" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "离线 — 显示缓存的会话" } } } }, - "Question": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "问题" + "Open" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "打开" } } } }, - "Range": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "范围" + "Open Settings" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "打开设置" } } } }, - "Re-register push": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "重新注册推送" + "Open URL" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "打开链接" } } } }, - "Read file": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "读取文件" + "Open link?" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "打开此链接?" } } } }, - "Read notebook": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "读取笔记本" + "Options" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "选项" } } } }, - "Reasoning": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "思考" + "Other…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "其他…" } } } }, - "Reasoning Effort": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "推理强度" + "Output" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输出" } } } }, - "Reasoning…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "思考中…" + "Pair" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "配对" } } } }, - "Reconnecting…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "重连中…" + "Pair with your hub" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "与你的 Hub 配对" } } } }, - "Refresh": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "刷新" + "Pairing succeeded but the credentials could not be stored on this device. Try again." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "配对成功,但凭据无法保存到此设备。请重试。" } } } }, - "Refreshing…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "正在刷新…" + "Pairing…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "配对中…" } } } }, - "Registered hubs": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已注册的 Hub" + "Park current draft" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "暂存当前草稿" } } } }, - "Remove %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "移除 %@" + "Park drafts from the header, or tap + to jot a note for this session." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "从顶部暂存草稿,或点按 + 为此会话记一条笔记。" } } } }, - "Removes the stored access token for this hub. Pair again to reconnect.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "将移除此 Hub 已保存的访问令牌。重新配对即可再次连接。" + "Path" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "路径" } } } }, - "Reply": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "回复" + "Paused" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已暂停" } } } }, - "Request failed": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "请求失败" + "Permission Mode" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "权限模式" } } } }, - "Request was already handled": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "请求已被处理" + "Permission mode" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "权限模式" } } } }, - "Requests": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "请求数" + "Permission request" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "权限请求" } } } }, - "Result": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "结果" + "Permission: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "权限:%@" } } } }, - "Result · error": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "结果 · 错误" + "Photo library" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "照片图库" } } } }, - "Resume agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "恢复代理" + "Pin Globally" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "全局置顶" } } } }, - "Retry": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "重试" + "Pin failed: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "置顶操作失败:%@" } } } }, - "Run shell": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "运行命令" + "Pin to Project" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "项目置顶" } } } }, - "Runner last spawn error: %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Runner 上次启动错误:%@" + "Pinned" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "置顶" } } } }, - "SQLite files": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "SQLite 文件" + "Plan" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "计划" } } } }, - "Save": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "保存" + "Plan proposal" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "计划提案" } } } }, - "Scan Again": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "重新扫描" + "Point the camera at the pairing QR from the hub terminal or the web app's Companion Pairing settings." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "将相机对准 Hub 终端或网页版「伴侣应用配对」设置中的配对二维码。" } } } }, - "Scan QR Code": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "扫描二维码" + "Preview" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "预览" } } } }, - "Scan to Pair": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "扫码配对" + "Preview not available for this image format" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此图片格式不支持预览" } } } }, - "Scanning unavailable": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无法扫码" + "Previous tool" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "上一个工具" } } } }, - "Scheduled · %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "定时发送 · %@" + "Printed by the hub at startup, and shown in the web app under Settings → Companion Pairing. Pasting a full pairing link into either field also works." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 启动时打印,也显示在网页版「设置 → 伴侣应用配对」中。将完整配对链接粘贴到任一输入框同样有效。" } } } }, - "Scratchlist": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "草稿夹" + "Privacy Policy" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "隐私政策" } } } }, - "Scratchlist (%lld)": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "草稿夹(%lld)" + "Project root" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "项目根目录" } } } }, - "Scratchlist is full (200 entries)": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "草稿夹已满(200 条)" + "Protocol version" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "协议版本" } } } }, - "Scratchlist is full (200 entries) — delete one first": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "草稿夹已满(200 条)— 请先删除一条" + "Pull to retry once you are back online." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "恢复在线后下拉重试。" } } } }, - "Search": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "搜索" + "Push notifications" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "推送通知" } } } }, - "Search content": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "搜索内容" + "Pushes are end-to-end encrypted; only this device can read them." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "推送经过端到端加密,只有本机可以读取。" } } } }, - "Search files": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "搜索文件" + "Query" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查询" } } } }, - "Search files…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "搜索文件…" + "Question" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "问题" } } } }, - "Section": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "分区" + "Range" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "范围" } } } }, - "Send": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "发送" + "Re-register push" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重新注册推送" } } } }, - "Send & steer into current turn": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "发送并插入当前回合" + "Read file" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "读取文件" } } } }, - "Send — long-press to steer": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "发送 — 长按可插入当前回合" + "Read notebook" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "读取笔记本" } } } }, - "Session Settings": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "会话设置" + "Reasoning" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "思考" } } } }, - "Session Type": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "会话类型" + "Reasoning Effort" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "推理强度" } } } }, - "Session files": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "会话文件" + "Reasoning…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "思考中…" } } } }, - "Session is controlled from the terminal — config changes will be rejected.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "会话正由终端控制 — 配置更改将被拒绝。" + "Reconnecting…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重连中…" } } } }, - "Session is inactive and could not be resumed": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "会话未激活且无法恢复" + "Refresh" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "刷新" } } } }, - "Session is offline — changes apply after it resumes or may be rejected.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "会话已离线 — 更改将在恢复后生效,也可能被拒绝。" + "Refreshing…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "正在刷新…" } } } }, - "Session not found on any paired hub.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "任何已配对的 Hub 上都找不到该会话。" + "Registered hubs" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已注册的 Hub" } } } }, - "Session settings": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "会话设置" + "Remove %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "移除 %@" } } } }, - "Session type": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "会话类型" + "Removes the stored access token for this hub. Pair again to reconnect." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "将移除此 Hub 已保存的访问令牌。重新配对即可再次连接。" } } } }, - "Sessions": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "会话" + "Reply" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "回复" } } } }, - "Sessions with usage: %lld": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "有用量记录的会话:%lld" + "Request failed" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请求失败" } } } }, - "Settings": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "设置" + "Request was already handled" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请求已被处理" } } } }, - "Setup guide": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "设置指南" + "Requests" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请求数" } } } }, - "Shared memory": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "共享内存" + "Result" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "结果" } } } }, - "Show all %lld lines": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "显示全部 %lld 行" + "Result · error" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "结果 · 错误" } } } }, - "Show hidden files": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "显示隐藏文件" + "Resume agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "恢复代理" } } } }, - "Shutdown Response": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "关闭响应" + "Retry" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重试" } } } }, - "Shutdown: %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "关闭:%@" + "Run script" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "运行脚本" } } } }, - "Sign Out": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "退出登录" + "Run shell" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "运行命令" } } } }, - "Sign Out…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "退出登录…" + "Runner last spawn error: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Runner 上次启动错误:%@" } } } }, - "Sign out of %@?": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "退出 %@ 的登录?" + "Running" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "运行中" } } } }, - "Signed out of %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已退出 %@ 的登录" + "SQLite files" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "SQLite 文件" } } } }, - "Simple": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "简单" + "Save" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "保存" } } } }, - "Source": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "源码" + "Scan Again" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重新扫描" } } } }, - "Spawn agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "创建代理" + "Scan QR Code" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "扫描二维码" } } } }, - "Staged": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已暂存" + "Scan to Pair" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "扫码配对" } } } }, - "Staged (%lld)": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已暂存(%lld)" + "Scanning unavailable" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法扫码" } } } }, - "Standard": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "标准" + "Scheduled · %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "定时发送 · %@" } } } }, - "Start an agent with the hapi CLI and it will appear here.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "用 hapi CLI 启动一个智能体,会话就会出现在这里。" + "Scratchlist" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "草稿夹" } } } }, - "Status: %@ · protocol v%lld": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "状态:%@ · 协议 v%lld" + "Scratchlist (%lld)" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "草稿夹(%lld)" } } } }, - "Steer": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "插入" + "Scratchlist is full (200 entries)" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "草稿夹已满(200 条)" } } } }, - "Stop dictation": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "停止语音输入" + "Scratchlist is full (200 entries) — delete one first" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "草稿夹已满(200 条)— 请先删除一条" } } } }, - "Stop the current turn": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "停止当前回合" + "Search" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索" } } } }, - "Storage": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "存储空间" + "Search content" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索内容" } } } }, - "Submit": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "提交" + "Search files" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索文件" } } } }, - "Team: %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "团队:%@" + "Search files…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索文件…" } } } }, - "Terminal": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "终端" + "Section" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "分区" } } } }, - "That code is not a HAPI pairing QR — scan one printed by the hub.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "这不是 HAPI 配对二维码 — 请扫描 Hub 打印的二维码。" + "Select" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "选择" } } } }, - "That file is over the %lld MB limit": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "该文件超过 %lld MB 上限" + "Send" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "发送" } } } }, - "That file is over the hub's per-file size limit": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "该文件超过 Hub 的单文件大小上限" + "Send & steer into current turn" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "发送并插入当前回合" } } } }, - "That file type isn't allowed for scratchlist attachments": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "草稿夹附件不支持该文件类型" + "Send — long-press to steer" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "发送 — 长按可插入当前回合" } } } }, - "The address the hub prints at startup — a LAN address like http://192.168.1.20:3006, or the public tunnel URL when running with --relay.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 启动时打印的地址 — 局域网地址如 http://192.168.1.20:3006,或使用 --relay 时的公网隧道地址。" + "Session Settings" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "会话设置" } } } }, - "The app checks the hub is reachable, then exchanges the token for a session.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "应用会先确认 Hub 可达,再用令牌换取会话。" + "Session Type" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "会话类型" } } } }, - "The hub answered unexpectedly (HTTP %lld). Try again in a moment.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 返回了意外响应(HTTP %lld)。请稍后重试。" + "Session files" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "会话文件" } } } }, - "The hub rejected the stored credentials — the access token was probably rotated. Pair again to reconnect.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 拒绝了已保存的凭据 — 访问令牌可能已被轮换。请重新配对以恢复连接。" + "Session is controlled from the terminal — config changes will be rejected." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "会话正由终端控制 — 配置更改将被拒绝。" } } } }, - "The hub rejected this access token — it may have been rotated. Get a fresh pairing code from the hub and try again.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 拒绝了此访问令牌 — 它可能已被轮换。请从 Hub 获取新的配对码后重试。" + "Session is inactive and could not be resumed" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "会话未激活且无法恢复" } } } }, - "The hub speaks protocol v%lld, this app supports v%lld. Update the older side, then try again.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "Hub 使用协议 v%lld,本应用支持 v%lld。请升级较旧的一方后重试。" + "Session is offline — changes apply after it resumes or may be rejected." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "会话已离线 — 更改将在恢复后生效,也可能被拒绝。" } } } }, - "The session is no longer active.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "该会话已不再活跃。" + "Session not found on any paired hub." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "任何已配对的 Hub 上都找不到该会话。" } } } }, - "Theme": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "主题" + "Session settings" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "会话设置" } } } }, - "Thinking": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "思考中" + "Session type" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "会话类型" } } } }, - "This agent manages its own permissions. YOLO mode is not available.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此代理自行管理权限,YOLO 模式不适用。" + "Sessions" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "会话" } } } }, - "This dashboard is only available to the hub owner (default namespace).": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此看板仅 Hub 所有者(default 命名空间)可用。" + "Sessions with usage: %lld" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "有用量记录的会话:%lld" } } } }, - "This device cannot scan QR codes (for example the Simulator). Go back and use manual entry instead.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此设备无法扫描二维码(例如模拟器)。请返回并使用手动输入。" + "Settings" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "设置" } } } }, - "This file is empty": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "文件为空" + "Setup guide" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "设置指南" } } } }, - "This hub will be added to your paired hubs and become active.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此 Hub 将加入已配对列表并成为当前 Hub。" + "Share file" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "分享文件" } } } }, - "This note's attachment budget is used up": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此笔记的附件配额已用完" + "Shared memory" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "共享内存" } } } }, - "To composer": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "复制到输入框" + "Show Hidden" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "显示隐藏目录" } } } }, - "Todo list": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "任务清单" + "Show all %lld lines" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "显示全部 %lld 行" } } } }, - "Token rejected": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "令牌被拒绝" + "Show hidden files" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "显示隐藏文件" } } } }, - "Token usage across agents and models": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "各 Agent 与模型的 Token 用量" + "Show image" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "展示图片" } } } }, - "Total": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "总计" + "Show video" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "展示视频" } } } }, - "Total tokens": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "总 Token" + "Showing %lld of %lld parts" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已显示 %lld 部分,共 %lld 部分" } } } }, - "Transcription failed": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "转录失败" + "Showing the last available record. Live updates are unavailable for this tool." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "正在显示最后保留的记录,此工具已无法实时更新。" } } } }, - "Try Again": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "重试" + "Shutdown Response" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭响应" } } } }, - "Type an answer first": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "请先输入答案" + "Shutdown: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭:%@" } } } }, - "Type to search files in the session directory": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "输入以在会话目录中搜索文件" + "Sign Out" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "退出登录" } } } }, - "Type your answer…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "输入您的答案…" + "Sign Out…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "退出登录…" } } } }, - "Uncached": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "非缓存" + "Sign out of %@?" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "退出 %@ 的登录?" } } } }, - "Unknown machine": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "未知机器" + "Signed out of %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已退出 %@ 的登录" } } } }, - "Unpin": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "取消置顶" + "Simple" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "简单" } } } }, - "Unread": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "未读" + "Source" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "源码" } } } }, - "Unstaged": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "未暂存" + "Spawn agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "创建代理" } } } }, - "Unstaged (%lld)": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "未暂存(%lld)" + "Staged" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已暂存" } } } }, - "Upload failed — check the hub connection": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "上传失败 — 请检查 Hub 连接" + "Staged (%lld)" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已暂存(%lld)" } } } }, - "Uploading…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "上传中…" + "Standard" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "标准" } } } }, - "Usage": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "用量" + "Start an agent with the hapi CLI and it will appear here." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "用 hapi CLI 启动一个智能体,会话就会出现在这里。" } } } }, - "Use selected directory as-is": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "直接使用选定的目录" + "Status: %@ · protocol v%lld" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "状态:%@ · 协议 v%lld" } } } }, - "Uses dangerous agent flags when spawning.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "启动时使用危险的代理标志。" + "Steer" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "插入" } } } }, - "Uses dangerous agent flags when spawning. Applies native %@ mode.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "启动时使用危险的代理标志。将应用原生 %@ 模式。" + "Stop dictation" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "停止语音输入" } } } }, - "Version mismatch": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "版本不匹配" + "Stop the current turn" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "停止当前回合" } } } }, - "Wait for agent": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "等待代理" + "Storage" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "存储空间" } } } }, - "Web fetch": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "获取网页" + "Subdirectories" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "子目录" } } } }, - "Web search": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "网络搜索" + "Submit" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "提交" } } } }, - "Workspace file": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "工作区文件" + "Team: %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "团队:%@" } } } }, - "Worktree": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "工作树" + "Terminal" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "终端" } } } }, - "Worktree sessions require an existing repository directory.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "工作树会话需要已存在的仓库目录。" + "That code is not a HAPI pairing QR — scan one printed by the hub." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "这不是 HAPI 配对二维码 — 请扫描 Hub 打印的二维码。" } } } }, - "Write file": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "写入文件" + "That file is over the %lld MB limit" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "该文件超过 %lld MB 上限" } } } }, - "Write-ahead log": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "预写日志" + "That file is over the hub's per-file size limit" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "该文件超过 Hub 的单文件大小上限" } } } }, - "approve %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "批准 %@" + "That file type isn't allowed for scratchlist attachments" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "草稿夹附件不支持该文件类型" } } } }, - "error": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "错误" + "The address the hub prints at startup — a LAN address like http://192.168.1.20:3006, or the public tunnel URL when running with --relay." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 启动时打印的地址 — 局域网地址如 http://192.168.1.20:3006,或使用 --relay 时的公网隧道地址。" } } } }, - "feature-x (optional)": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "feature-x(可选)" + "The app checks the hub is reachable, then exchanges the token for a session." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "应用会先确认 Hub 可达,再用令牌换取会话。" } } } }, - "needs input": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "需要输入" + "The hub answered unexpectedly (HTTP %lld). Try again in a moment." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 返回了意外响应(HTTP %lld)。请稍后重试。" } } } }, - "now": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "刚刚" + "The hub rejected the stored credentials — the access token was probably rotated. Pair again to reconnect." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 拒绝了已保存的凭据 — 访问令牌可能已被轮换。请重新配对以恢复连接。" } } } }, - "pending": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "等待中" + "The hub rejected this access token — it may have been rotated. Get a fresh pairing code from the hub and try again." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 拒绝了此访问令牌 — 它可能已被轮换。请从 Hub 获取新的配对码后重试。" } } } }, - "— Canceled": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "— 已取消" + "The hub speaks protocol v%lld, this app supports v%lld. Update the older side, then try again." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hub 使用协议 v%lld,本应用支持 v%lld。请升级较旧的一方后重试。" } } } }, - "● Recording… %@": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "● 录音中… %@" + "The selected Agent is not available on this machine." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "所选代理在此机器上不可用。" } } } }, - "Checking installed Agents…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "正在检查已安装的代理…" + "The session is no longer active." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "该会话已不再活跃。" } } } }, - "Choose Directory": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "选择目录" + "Theme" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "主题" } } } }, - "Current Directory": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "当前目录" + "Thinking" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "思考中" } } } }, - "Directory must be inside one of this machine's workspace roots.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "目录必须位于此机器配置的某个工作区根目录内。" + "This agent manages its own permissions. YOLO mode is not available." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此代理自行管理权限,YOLO 模式不适用。" } } } }, - "Failed to browse directories": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "浏览目录失败" + "This dashboard is only available to the hub owner (default namespace)." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此看板仅 Hub 所有者(default 命名空间)可用。" } } } }, - "Failed to check installed Agents": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "检查已安装代理失败" + "This device cannot scan QR codes (for example the Simulator). Go back and use manual entry instead." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此设备无法扫描二维码(例如模拟器)。请返回并使用手动输入。" } } } }, - "No subdirectories": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "没有子目录" + "This file is empty" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "文件为空" } } } }, - "No supported Agents are installed on this machine.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "此机器上没有安装受支持的代理。" + "This hub will be added to your paired hubs and become active." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此 Hub 将加入已配对列表并成为当前 Hub。" } } } }, - "Select": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "选择" + "This note's attachment budget is used up" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此笔记的附件配额已用完" } } } }, - "Show Hidden": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "显示隐藏目录" + "To composer" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "复制到输入框" } } } }, - "Subdirectories": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "子目录" + "Todo list" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "任务清单" } } } }, - "The selected Agent is not available on this machine.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "所选代理在此机器上不可用。" + "Token rejected" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "令牌被拒绝" } } } }, - "Up": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "上一级" + "Token usage across agents and models" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "各 Agent 与模型的 Token 用量" } } } }, - "Upgrade and restart this machine's HAPI runner before creating sessions.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "创建会话前,请升级并重启此机器上的 HAPI runner。" + "Tool %lld of %lld" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "第 %lld 个工具,共 %lld 个" } } } }, - "Workspace Roots": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "工作区根目录" + "Tool details" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "工具详情" } } } }, - "✓ Approved": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "✓ 已批准" + "Total" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "总计" } } } }, - "✕ Denied": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "✕ 已拒绝" + "Total tokens" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "总 Token" } } } }, - "1 tool call": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 次工具调用" + "Transcription failed" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "转录失败" } } } }, - "%lld tool calls": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 次工具调用" + "Try Again" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重试" } } } }, - "View image": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "查看图片" + "Type an answer first" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请先输入答案" } } } }, - "Show image": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "展示图片" + "Type to search files in the session directory" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入以在会话目录中搜索文件" } } } }, - "Show video": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "展示视频" + "Type your answer…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入您的答案…" } } } }, - "Share file": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "分享文件" + "Uncached" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "非缓存" } } } }, - "Run script": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "运行脚本" + "Unknown machine" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未知机器" } } } }, - "Continue command": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "继续命令" + "Unpin" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "取消置顶" } } } }, - "Wait for result": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "等待结果" + "Unread" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未读" } } } }, - "Expanded": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已展开" + "Unstaged" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未暂存" } } } }, - "Collapsed": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已折叠" + "Unstaged (%lld)" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未暂存(%lld)" } } } }, - "%lld commands": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 条命令" + "Up" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "上一级" } } } }, - "%lld edits": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 次修改" + "Upgrade and restart this machine's HAPI runner before creating sessions." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "创建会话前,请升级并重启此机器上的 HAPI runner。" } } } }, - "%lld failed tools": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 个工具失败" + "Upload failed — check the hub connection" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "上传失败 — 请检查 Hub 连接" } } } }, - "%lld other tools": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 个其他工具" + "Uploading…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "上传中…" } } } }, - "%lld reads": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 次读取" + "Usage" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "用量" } } } }, - "%lld searches": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 次搜索" + "Use selected directory as-is" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "直接使用选定的目录" } } } }, - "%lld web requests": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "%lld 次网络请求" + "Uses dangerous agent flags when spawning." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "启动时使用危险的代理标志。" } } } }, - "1 command": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 条命令" + "Uses dangerous agent flags when spawning. Applies native %@ mode." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "启动时使用危险的代理标志。将应用原生 %@ 模式。" } } } }, - "1 edit": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 次修改" + "Version mismatch" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "版本不匹配" } } } }, - "1 other tool": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 个其他工具" + "View agent process" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查看子代理执行过程" } } } }, - "1 read": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 次读取" + "View current file" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查看当前文件" } } } }, - "1 search": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 次搜索" + "View full input" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查看完整输入" } } } }, - "1 web request": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "1 次网络请求" + "View image" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查看图片" } } } }, - "Agent process": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "子代理执行过程" + "View process · %lld steps" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查看过程 · %lld 个步骤" } } } }, - "Close details to approve or answer in the conversation.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "关闭详情后,可在对话中审批或回答。" + "View tool details" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查看工具详情" } } } }, - "Completed": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已完成" + "Wait for agent" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "等待代理" } } } }, - "Copy": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "复制" + "Wait for result" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "等待结果" } } } }, - "Copy full content": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "复制完整内容" + "Waiting for output…" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "等待输出…" } } } }, - "Copy input": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "复制输入" + "Web fetch" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "获取网页" } } } }, - "Copy result": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "复制结果" + "Web search" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "网络搜索" } } } }, - "Load more content": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "加载更多内容" + "Workspace Roots" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "工作区根目录" } } } }, - "Next tool": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "下一个工具" + "Workspace file" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "工作区文件" } } } }, - "No agent steps available yet.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "暂无可显示的子代理步骤。" + "Worktree" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "工作树" } } } }, - "No output": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "无输出" + "Worktree sessions require an existing repository directory." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "工作树会话需要已存在的仓库目录。" } } } }, - "Previous tool": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "上一个工具" + "Write file" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "写入文件" } } } }, - "Running": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "运行中" + "Write-ahead log" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "预写日志" } } } }, - "Showing %lld of %lld parts": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已显示 %lld 部分,共 %lld 部分" + "approve %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "批准 %@" } } } }, - "Showing the last available record. Live updates are unavailable for this tool.": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "正在显示最后保留的记录,此工具已无法实时更新。" + "error" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "错误" } } } }, - "Tool %lld of %lld": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "第 %lld 个工具,共 %lld 个" + "feature-x (optional)" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "feature-x(可选)" } } } }, - "Tool details": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "工具详情" + "needs input" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "需要输入" } } } }, - "View agent process": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "查看子代理执行过程" + "now" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "刚刚" } } } }, - "View current file": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "查看当前文件" + "pending" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "等待中" } } } }, - "View full input": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "查看完整输入" + "— Canceled" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "— 已取消" } } } }, - "View process · %lld steps": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "查看过程 · %lld 个步骤" + "● Recording… %@" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "● 录音中… %@" } } } }, - "View tool details": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "查看工具详情" + "✓ Approved" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "✓ 已批准" } } } }, - "Waiting for output…": { - "localizations": { - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "等待输出…" + "✕ Denied" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "✕ 已拒绝" } } } } }, - "version": "1.0" -} + "version" : "1.0" +} \ No newline at end of file diff --git a/ios/README.md b/ios/README.md index 4db93a41..02b50c0c 100644 --- a/ios/README.md +++ b/ios/README.md @@ -36,9 +36,35 @@ changes under `ios/**` and `shared/fixtures/**`). ### Localization catalog -`Hapi/Resources/Localizable.xcstrings` is hand-maintained. Compiler string -extraction stays disabled so opening or building the project does not rewrite -the catalog with decorative or intentionally verbatim strings. +`Hapi/Resources/Localizable.xcstrings` is **manually managed**, including every +entry's `"extractionState" : "manual"`. Keep `SWIFT_EMIT_LOC_STRINGS = NO` for the +app/extension in Debug and Release. That setting disables compiler extraction; +it does **not** prevent the Xcode editor from synchronizing or saving a catalog. +Unspecified ownership can still turn entries into `stale` during synchronization. + +Use Xcode's native catalog formatting (key order, spacing, escaping), not a +generic JSON formatter. After adding or editing translations, run from repo root: + +```sh +python3 ios/scripts/localizations.py --check # read-only ownership check; no Xcode needed +python3 ios/scripts/localizations.py --fix # macOS/Xcode: mark manual, normalize native format +``` + +The normalizer uses `xcstringstool` on a temporary copy, verifies that all keys, +translations, plural variations and comments survive, and writes only if needed. +It never deletes real entries: review/remove unwanted auto-extracted additions +before `--fix`, rather than silently making them permanent. Keep dynamic values +and decorative text verbatim in SwiftUI where they are not localization keys. + +CI checks manual ownership, tests normalization idempotence, and verifies that +building/testing does not rewrite the catalog. Formatting is delegated to the +installed Xcode rather than reimplementing its ordering in Python; `--check` +does not enforce one Xcode version's byte-level formatting on another version. + +After migrating an existing checkout, use **Product → Clean Build Folder** if +Xcode still synchronizes old extraction results, then rebuild/reopen and inspect +the diff. Do not hide the file with `.gitignore`, `skip-worktree`, or restore it +unconditionally: real translation edits must remain visible and committed. ### Reading typography diff --git a/ios/scripts/localizations.py b/ios/scripts/localizations.py new file mode 100644 index 00000000..da661d19 --- /dev/null +++ b/ios/scripts/localizations.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +"""Check the manual catalog, or normalize it with Xcode's own serializer. + +--fix changes extraction ownership and formatting only. It never deletes real +keys or edits translations; review automatically extracted additions first. +""" + +import argparse +import copy +import json +import subprocess +import sys +import tempfile +import uuid +from pathlib import Path + +CATALOG = Path(__file__).resolve().parents[1] / "Hapi/Resources/Localizable.xcstrings" + + +def parse_catalog(content): + def unique_keys(pairs): + result = {} + for key, value in pairs: + if key in result: + raise ValueError(f"Duplicate JSON key: {key!r}") + result[key] = value + return result + + data = json.loads(content, object_pairs_hook=unique_keys) + if not isinstance(data.get("strings"), dict): + raise ValueError("Expected a string catalog with a 'strings' object") + if any(not isinstance(entry, dict) for entry in data["strings"].values()): + raise ValueError("Every string entry must be an object") + return data + + +def load_catalog(path): + return parse_catalog(path.read_bytes()) + + +def manual_keys_missing(data): + return [key for key, entry in data["strings"].items() if entry.get("extractionState") != "manual"] + + +def normalize(data): + expected = copy.deepcopy(data) + for entry in expected["strings"].values(): + entry["extractionState"] = "manual" + + with tempfile.TemporaryDirectory(prefix="hapi-localizations-") as directory: + directory = Path(directory) + catalog = directory / "Localizable.xcstrings" + empty_extraction = directory / "Empty.stringsdata" + empty_extraction.write_text(json.dumps({"source": "ManualCatalog", "tables": {}, "version": 1}), encoding="utf-8") + temporary = copy.deepcopy(expected) + # sync does not serialize an unchanged catalog. An untranslated automatic + # placeholder is removed by the empty extraction, forcing a native save. + # This only exists in the temporary copy, never in the source catalog. + placeholder = f"__hapi_format_{uuid.uuid4()}__" + temporary["strings"][placeholder] = {} + catalog.write_text(json.dumps(temporary, ensure_ascii=False), encoding="utf-8") + subprocess.run([ + "xcrun", "xcstringstool", "sync", str(catalog), "--stringsdata", str(empty_extraction), + ], check=True) + if load_catalog(catalog) != expected: + raise ValueError("Xcode changed catalog content unexpectedly; source file was not modified") + return catalog.read_bytes() + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + mode = parser.add_mutually_exclusive_group() + mode.add_argument("--check", action="store_true", help="Check manual ownership without rewriting (default; no Xcode needed)") + mode.add_argument("--fix", action="store_true", help="Mark all entries manual and save in native Xcode format (macOS/Xcode)") + parser.add_argument("catalog", nargs="?", type=Path, default=CATALOG) + args = parser.parse_args() + try: + before = args.catalog.read_bytes() + data = parse_catalog(before) + if args.fix: + normalized = normalize(data) + if args.catalog.read_bytes() != before: + raise ValueError("Catalog changed while normalizing; retry after Xcode finishes saving") + if normalized != before: + args.catalog.write_bytes(normalized) + print(f"Normalized {len(data['strings'])} manual entries: {args.catalog}") + else: + print("Catalog already normalized; no write needed") + else: + missing = manual_keys_missing(data) + if missing: + print("Entries without extractionState=manual:", file=sys.stderr) + for key in missing: + print(f" {key!r}", file=sys.stderr) + print("Review these keys, then run python3 ios/scripts/localizations.py --fix", file=sys.stderr) + return 1 + print(f"Catalog OK: {len(data['strings'])} manually managed entries") + except (OSError, ValueError, subprocess.CalledProcessError) as error: + print(f"Localization check failed: {error}", file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/ios/scripts/tests/test_localizations.py b/ios/scripts/tests/test_localizations.py new file mode 100644 index 00000000..8ca633a4 --- /dev/null +++ b/ios/scripts/tests/test_localizations.py @@ -0,0 +1,85 @@ +import copy +import io +import json +import subprocess +import sys +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import localizations + + +class LocalizationTests(unittest.TestCase): + def test_check_detects_automatic_entries_without_writing(self): + with tempfile.TemporaryDirectory() as directory: + path = Path(directory) / "Localizable.xcstrings" + data = {"sourceLanguage": "en", "strings": {"Test": {}}, "version": "1.0"} + path.write_text(json.dumps(data), encoding="utf-8") + before = path.read_bytes() + result = subprocess.run([sys.executable, localizations.__file__, "--check", str(path)], capture_output=True) + self.assertEqual(result.returncode, 1) + self.assertEqual(path.read_bytes(), before) + data["strings"]["Test"]["extractionState"] = "manual" + path.write_text(json.dumps(data), encoding="utf-8") + result = subprocess.run([sys.executable, localizations.__file__, "--check", str(path)], capture_output=True) + self.assertEqual(result.returncode, 0, result.stderr) + + def test_duplicate_keys_are_rejected(self): + with tempfile.TemporaryDirectory() as directory: + path = Path(directory) / "Localizable.xcstrings" + path.write_text('{"strings":{"Test":{},"Test":{}}}', encoding="utf-8") + with self.assertRaisesRegex(ValueError, "Duplicate JSON key"): + localizations.load_catalog(path) + + def test_fix_preserves_concurrent_edits(self): + with tempfile.TemporaryDirectory() as directory: + path = Path(directory) / "Localizable.xcstrings" + original = {"sourceLanguage": "en", "strings": {"Test": {}}, "version": "1.0"} + path.write_text(json.dumps(original), encoding="utf-8") + edited = json.dumps({**original, "strings": {"New edit": {}}}).encode("utf-8") + + def normalize_while_editing(data): + self.assertEqual(data, original) + path.write_bytes(edited) + return b"must not overwrite the edit" + + with patch.object(sys, "argv", [localizations.__file__, "--fix", str(path)]), \ + patch.object(localizations, "normalize", side_effect=normalize_while_editing), \ + patch.object(sys, "stderr", new_callable=io.StringIO) as stderr: + self.assertEqual(localizations.main(), 1) + self.assertIn("Catalog changed while normalizing", stderr.getvalue()) + self.assertEqual(path.read_bytes(), edited) + + @unittest.skipUnless(sys.platform == "darwin", "Native formatting requires Xcode") + def test_xcode_normalization_preserves_content_and_is_idempotent(self): + data = { + "sourceLanguage": "en", + "strings": { + "zebra": {"extractionState": "stale", "comment": "Keep this comment", "localizations": { + "zh-Hans": {"stringUnit": {"state": "translated", "value": "斑马 🦓\n"}}, + }}, + "%lld items": {"localizations": {"en": {"variations": {"plural": { + "one": {"stringUnit": {"state": "translated", "value": "%lld item"}}, + "other": {"stringUnit": {"state": "translated", "value": "%lld items"}}, + }}}}}, + "https://example.com/a": {"shouldTranslate": False}, + "Untranslated": {}, + }, + "version": "1.0", + } + original = copy.deepcopy(data) + first = localizations.normalize(data) + self.assertEqual(data, original) + parsed = json.loads(first) + for key, entry in original["strings"].items(): + self.assertEqual(parsed["strings"][key], {**entry, "extractionState": "manual"}) + self.assertEqual(set(parsed["strings"]), set(original["strings"])) + self.assertIn(b'"sourceLanguage" : "en"', first) + self.assertEqual(first, localizations.normalize(parsed)) + + +if __name__ == "__main__": + unittest.main()