AGE-110: 64% of 30d-active users sit on v0.4.10 and 0.2% on the newest build, so a client-side fix (the AGE-105 Sentry noise gate) reaches almost nobody. Play hygiene fixes one channel; the direct APK, the self-hosted F-Droid repo and third-party mirrors have no update mechanism at all — a device installed from a downloaded APK has literally no way to learn a newer version exists. - src/lib/update-check-policy.ts: pure, node --test'able decision logic — numeric version compare (a string compare puts 0.4.10 BEFORE 0.4.9, i.e. it would have told the largest stale cohort it was current), a 24h check throttle that survives a backwards clock, per-version dismissal, and a cached last-known-latest so the affordance survives between checks - src/lib/update-check.ts: Android-only runtime wiring. One unauthenticated GET per 24h to the GitHub releases API (every non-Play channel is downstream of a GitHub release; expo-updates cannot replace a native binary, which is what this cohort needs). Never throws. - UpdateBanner on the sessions list: one dismissible strip, no modal. "Not now" sticks for that version only. - Settings "Version" row showed a hard-coded "1.0.0" for every build ever shipped. It now shows the real version, plus "0.4.10 -> 0.4.14" when an update exists (ignoreDismissed: dismissal silences the banner, not the place a user goes to check). - en/zh-Hans strings, catalog parity kept. Tests: 19 new cases in update-check-policy.test.ts; full suite 300 pass, tsc --noEmit clean. Co-authored-by: engineer <engineer@macbookpro.lan> Co-authored-by: Paperclip <noreply@paperclip.ing>
456 lines
17 KiB
JSON
456 lines
17 KiB
JSON
{
|
||
"common": {
|
||
"cancel": "取消",
|
||
"ok": "确定",
|
||
"error": "错误",
|
||
"delete": "删除",
|
||
"retry": "重试",
|
||
"save": "保存",
|
||
"shareReport": "分享报告"
|
||
},
|
||
"settings": {
|
||
"sections": {
|
||
"security": "安全",
|
||
"notifications": "通知",
|
||
"privacy": "隐私",
|
||
"about": "关于"
|
||
},
|
||
"security": {
|
||
"biometricOpen": {
|
||
"label": "解锁时需要生物识别",
|
||
"descriptionEnabled": "使用 Face ID 或 Touch ID 解锁应用",
|
||
"descriptionUnavailable": "生物识别功能不可用"
|
||
},
|
||
"biometricSend": {
|
||
"label": "发送消息时需要生物识别",
|
||
"description": "发送消息前需要验证身份"
|
||
},
|
||
"lockNow": {
|
||
"label": "立即锁定应用",
|
||
"description": "重新打开时需要验证身份"
|
||
}
|
||
},
|
||
"notifications": {
|
||
"disabledNotice": "通知已在系统层面关闭。请在系统设置中启用通知以接收提醒。"
|
||
},
|
||
"privacy": {
|
||
"crashReporting": {
|
||
"label": "崩溃报告与使用分析",
|
||
"description": "分享匿名崩溃报告(Sentry)和使用分析(PostHog),帮助改进 OpenCode。您分享的诊断报告也会发送至我们的支持收件箱。不包含代码或提示词内容。"
|
||
},
|
||
"privacyPolicy": {
|
||
"label": "隐私政策",
|
||
"description": "我们收集哪些数据及收集方式"
|
||
}
|
||
},
|
||
"about": {
|
||
"version": "版本",
|
||
"github": {
|
||
"label": "GitHub",
|
||
"description": "查看源代码"
|
||
},
|
||
"docs": {
|
||
"label": "文档",
|
||
"description": "了解如何使用 OpenCode"
|
||
}
|
||
},
|
||
"language": {
|
||
"label": "语言",
|
||
"title": "选择语言",
|
||
"system": "跟随系统",
|
||
"en": "English",
|
||
"zhHans": "简体中文"
|
||
},
|
||
"footer": {
|
||
"appName": "OpenCode Mobile",
|
||
"tagline": "随时随地连接您的 AI 编程助手"
|
||
},
|
||
"alerts": {
|
||
"privacyNotSavedTitle": "隐私设置未保存",
|
||
"privacyNotSavedMessage": "本次会话已关闭崩溃报告,但您的选择未能保存。请重试。",
|
||
"notificationsDisabledTitle": "通知已关闭",
|
||
"notificationsDisabledMessage": "请在设备设置中为 OpenCode 启用通知以接收提醒。"
|
||
}
|
||
},
|
||
"session": {
|
||
"titleFallback": "会话",
|
||
"toolbar": {
|
||
"auto": "自动"
|
||
},
|
||
"banners": {
|
||
"reconnecting": "正在重新连接…(第 {{attempt}} 次尝试)",
|
||
"connected": "已连接 ✓",
|
||
"reverted": "消息已撤回 — 重新发送以确认",
|
||
"undo": "撤销"
|
||
},
|
||
"empty": {
|
||
"title": "开始一段对话",
|
||
"hint": "输入 / 使用命令"
|
||
},
|
||
"loadingOlder": "正在加载更早的消息...",
|
||
"input": {
|
||
"placeholderListening": "正在聆听...",
|
||
"placeholderFollowUp": "发送后续消息...",
|
||
"placeholderDefault": "输入消息..."
|
||
},
|
||
"actions": {
|
||
"editMessage": "编辑消息",
|
||
"replace": "替换"
|
||
},
|
||
"alerts": {
|
||
"messageActionsTitle": "消息操作",
|
||
"notSupportedTitle": "不支持此操作",
|
||
"notSupportedMessage": "编辑已发送的消息需要更新的 opencode 服务器版本。请更新服务器后重试。",
|
||
"revertAuthFailedTitle": "身份验证失败",
|
||
"revertAuthFailedMessage": "您的服务器凭据被拒绝。请检查连接后重试。",
|
||
"editFailedTitle": "编辑失败",
|
||
"editFailedMessage": "无法撤回到该消息。请重试。",
|
||
"replaceDraftTitle": "替换草稿?",
|
||
"replaceDraftMessage": "输入框中有未发送的消息。编辑此消息将替换它。",
|
||
"cameraPermissionTitle": "需要权限",
|
||
"cameraPermissionMessage": "拍照需要相机访问权限。",
|
||
"emptyClipboardTitle": "剪贴板为空",
|
||
"emptyClipboardMessage": "剪贴板中没有文本或图片。",
|
||
"authRequiredTitle": "需要身份验证",
|
||
"authRequiredMessage": "发送消息需要生物识别验证。请重试。",
|
||
"sendFailedTitle": "消息未发送",
|
||
"sendFailedMessage": "无法发送您的消息。请检查连接后重试。",
|
||
"replyFailedTitle": "回复失败",
|
||
"replyFailedMessage": "无法发送您的回复。请重试。",
|
||
"rejectFailedTitle": "拒绝失败",
|
||
"rejectFailedMessage": "无法发送您的回复。请重试。",
|
||
"imageFailedTitle": "图片未添加",
|
||
"imageFailedMessage": "一张或多张图片无法处理。请尝试其他照片。",
|
||
"speechErrorTitle": "语音输入失败",
|
||
"speechErrorMessage": "无法使用语音输入。请检查麦克风权限后重试。"
|
||
}
|
||
},
|
||
"connection": {
|
||
"shared": {
|
||
"connectionType": "连接类型",
|
||
"types": {
|
||
"local": "本地",
|
||
"tunnel": "隧道",
|
||
"cloud": "云端"
|
||
},
|
||
"name": "名称",
|
||
"namePlaceholder": "我的服务器",
|
||
"serverUrl": "服务器地址",
|
||
"directoryOptional": "项目目录(可选)",
|
||
"authentication": "身份验证",
|
||
"username": "用户名",
|
||
"password": "密码",
|
||
"alerts": {
|
||
"enterName": "请输入连接名称",
|
||
"enterUrl": "请输入服务器地址",
|
||
"invalidUrlTitle": "地址无效",
|
||
"invalidUrlMessage": "请输入包含 http:// 或 https:// 的完整地址,例如 http://192.168.1.100:4096",
|
||
"connectionFailedTitle": "连接失败",
|
||
"unknownError": "未知错误",
|
||
"saveFailedTitle": "无法保存连接",
|
||
"saveFailedMessage": "连接测试成功,但保存失败,请重试。"
|
||
}
|
||
},
|
||
"add": {
|
||
"quick": {
|
||
"title": "连接到 OpenCode",
|
||
"subtitle": "输入您电脑的 IP 地址进行连接",
|
||
"ipAddressLabel": "IP 地址",
|
||
"nameOptionalLabel": "名称(可选)",
|
||
"namePlaceholder": "我的 Mac",
|
||
"passwordIfSetLabel": "密码(如服务器已设置)",
|
||
"passwordPlaceholder": "留空表示无密码",
|
||
"usernameHintPrefix": "用户名默认为 ",
|
||
"usernameHintMiddle": "。需要自定义用户名?请使用",
|
||
"usernameHintSuffix": "。",
|
||
"advancedOptionsLink": "高级选项",
|
||
"connectButton": "连接",
|
||
"helpTitle": "如何查找您的 IP 地址:",
|
||
"helpMacPrefix": "在您的 Mac 上运行:",
|
||
"helpTailscalePrefix": "Tailscale 示例:",
|
||
"helpProtocolPrefix": "本地和 Tailscale 地址请使用 ",
|
||
"helpProtocolMiddle": ",除非已配置 TLS,此时请使用 ",
|
||
"helpProtocolSuffix": "。",
|
||
"helpRunningPrefix": "请确保 OpenCode 正在运行:",
|
||
"connectCardTitle": "OpenCode Connect",
|
||
"connectCardBadge": "即将上线",
|
||
"connectCardDesc": "将手机桥接到您的 opencode 服务器 — 无需配置隧道或防火墙。一键连接,随时随地。",
|
||
"advancedLink": "高级选项(隧道、云端、身份验证)"
|
||
},
|
||
"waitlist": {
|
||
"successText": "您已加入候补名单 — OpenCode Connect 准备就绪时我们会通过邮件通知您。",
|
||
"joinButton": "加入候补名单",
|
||
"alertTitle": "加入候补名单",
|
||
"queuedText": "已保存在此设备上 — 联网后我们会自动完成注册,你无需再做任何操作。",
|
||
"emailUsLink": "仍然无法注册?改为给我们发邮件",
|
||
"emailUsButton": "发送邮件",
|
||
"queueFailedMessage": "无法连接注册服务,也无法在此设备上保存你的请求。你可以改为给我们发邮件,我们会手动将你加入名单。",
|
||
"noMailAppMessage": "没有可用的邮件应用。请发送邮件至 support@agentlabs.cc,主题为 \"OpenCode Connect Waitlist\"。"
|
||
},
|
||
"advanced": {
|
||
"backToQuick": "简易模式",
|
||
"urlHintPrefix": "本地/Tailscale 示例:",
|
||
"urlHintOr": " 或 ",
|
||
"urlHintUse": "。仅在已配置 TLS 时使用 ",
|
||
"urlHintSuffix": "。",
|
||
"directoryHint": "留空则使用服务器的当前目录,或指定一个路径以在其他文件夹中工作。",
|
||
"saveButton": "保存连接"
|
||
},
|
||
"alerts": {
|
||
"enterIp": "请输入您电脑的 IP 地址",
|
||
"connectionFailedMessage": "{{summary}}\n\n目标:{{target}}\n错误:{{error}}"
|
||
}
|
||
},
|
||
"edit": {
|
||
"notFound": "未找到该连接",
|
||
"directoryHint": "留空则使用服务器的当前目录。新会话将在此文件夹中创建。",
|
||
"passwordLabel": "密码(留空则保留原密码)",
|
||
"testButton": "测试连接",
|
||
"saveButton": "保存更改",
|
||
"deleteButton": "删除连接",
|
||
"alerts": {
|
||
"successTitle": "成功",
|
||
"successMessage": "连接成功!",
|
||
"connectionFailedMessage": "{{summary}}\n\n({{detail}})",
|
||
"noDetail": "无详细信息",
|
||
"deleteTitle": "删除连接",
|
||
"deleteMessage": "确定要删除 \"{{name}}\" 吗?"
|
||
}
|
||
}
|
||
},
|
||
"nav": {
|
||
"sessionsTab": "会话",
|
||
"connectionsTab": "连接",
|
||
"settingsTab": "设置",
|
||
"addConnectionTitle": "添加连接",
|
||
"editConnectionTitle": "编辑连接"
|
||
},
|
||
"connectionsList": {
|
||
"activeBadge": "当前使用",
|
||
"lastConnected": "上次连接:{{date}}",
|
||
"actionsAlert": {
|
||
"message": "您想执行什么操作?",
|
||
"edit": "编辑"
|
||
},
|
||
"empty": {
|
||
"title": "暂无连接",
|
||
"subtitle": "添加一个 OpenCode 服务器连接"
|
||
},
|
||
"header": "点击切换,长按查看更多选项",
|
||
"preferences": {
|
||
"title": "偏好设置",
|
||
"pageSizeLabel": "每页消息数",
|
||
"pageSizeHint": "打开会话时加载的消息数量。数值越小加载越快。"
|
||
}
|
||
},
|
||
"sessionsList": {
|
||
"untitledSession": "未命名会话",
|
||
"time": {
|
||
"justNow": "刚刚",
|
||
"minutesAgo": "{{count}} 分钟前",
|
||
"hoursAgo": "{{count}} 小时前",
|
||
"daysAgo": "{{count}} 天前"
|
||
},
|
||
"filesCount": "{{count}} 个文件",
|
||
"actions": {
|
||
"rename": "重命名"
|
||
},
|
||
"alerts": {
|
||
"renameFailedTitle": "重命名失败",
|
||
"renameFailedMessage": "无法重命名该会话。请重试。",
|
||
"deleteTitle": "删除会话",
|
||
"deleteMessage": "删除 \"{{title}}\"?",
|
||
"deleteFailedTitle": "删除失败",
|
||
"deleteFailedMessage": "无法删除该会话。请重试。",
|
||
"createFailedMessage": "创建会话失败。请检查网络连接后重试。"
|
||
},
|
||
"empty": {
|
||
"noConnectionTitle": "无连接",
|
||
"noConnectionSubtitle": "连接到运行 opencode serve 的电脑(同一网络或通过 Tailscale)以开始使用。",
|
||
"setupGuideLink": "如何设置服务器",
|
||
"addConnectionButton": "添加连接",
|
||
"tryDemoButton": "试用演示(无需服务器)",
|
||
"authFailedTitle": "身份验证失败",
|
||
"authFailedSubtitle": "{{name}} 拒绝了您的凭据。请检查用户名和密码后重新连接。",
|
||
"checkCredentialsButton": "检查凭据",
|
||
"noSessions": "暂无会话"
|
||
},
|
||
"newSessionModal": {
|
||
"title": "新建会话",
|
||
"currentProjectLabel": "当前项目",
|
||
"serverDefault": "服务器默认目录",
|
||
"recentProjectsLabel": "最近项目",
|
||
"serverProjectsLabel": "服务器项目",
|
||
"browseFoldersLabel": "浏览文件夹…",
|
||
"browseFoldersHint": "浏览服务器的文件系统",
|
||
"enterPathLabel": "手动输入路径",
|
||
"createInButton": "在 {{dir}} 中创建",
|
||
"createSessionButton": "创建会话"
|
||
},
|
||
"renameModal": {
|
||
"title": "重命名会话"
|
||
}
|
||
},
|
||
"notifications": {
|
||
"categories": {
|
||
"permissions": {
|
||
"label": "权限请求",
|
||
"description": "当工具需要批准才能继续时"
|
||
},
|
||
"questions": {
|
||
"label": "问题",
|
||
"description": "当助手需要您的输入时"
|
||
},
|
||
"completed": {
|
||
"label": "任务完成",
|
||
"description": "当会话处理完成时"
|
||
},
|
||
"errors": {
|
||
"label": "错误",
|
||
"description": "当会话遇到问题时"
|
||
},
|
||
"connection": {
|
||
"label": "连接",
|
||
"description": "当应用长时间失去连接时"
|
||
}
|
||
}
|
||
},
|
||
"errorBoundary": {
|
||
"title": "出现了一些问题",
|
||
"subtitle": "应用遇到了一个意外错误,已自动上报。您可以分享详细报告以帮助我们更快修复。",
|
||
"errorLabel": "错误",
|
||
"unknownError": "未知错误",
|
||
"stackLabel": "堆栈",
|
||
"componentLabel": "组件",
|
||
"shareButton": "分享报告",
|
||
"tryAgainButton": "重试"
|
||
},
|
||
"telemetryConsent": {
|
||
"title": "帮助改进 OpenCode?",
|
||
"body": "分享匿名崩溃报告和使用分析,帮助我们更快地发现并修复问题。您分享的诊断报告也会发送至我们的支持收件箱。绝不包含代码、提示词或服务器地址。",
|
||
"bullets": {
|
||
"deviceInfo": "设备型号、系统版本、应用版本",
|
||
"stackTraces": "崩溃堆栈跟踪(不含变量值)",
|
||
"usageEvents": "匿名使用事件(打开应用、连接尝试、发送消息)— 发送至 PostHog EU",
|
||
"noCode": "您的代码、提示词或聊天消息",
|
||
"noServerUrls": "服务器地址或身份验证令牌"
|
||
},
|
||
"privacyLink": "阅读完整隐私政策",
|
||
"declineA11yLabel": "不用了,拒绝崩溃报告和使用分析",
|
||
"declineButton": "不用了",
|
||
"allowA11yLabel": "允许匿名崩溃报告和使用分析",
|
||
"allowButton": "允许",
|
||
"footnote": "您可以随时在设置 → 隐私中更改此设置。"
|
||
},
|
||
"authGate": {
|
||
"title": "OpenCode 已锁定",
|
||
"subtitle": "请验证身份以访问您的会话",
|
||
"unlockButton": "解锁"
|
||
},
|
||
"chat": {
|
||
"permissionPrompt": {
|
||
"title": "需要权限",
|
||
"deny": "拒绝",
|
||
"always": "始终允许",
|
||
"allow": "允许"
|
||
},
|
||
"questionPrompt": {
|
||
"headerFallback": "问题",
|
||
"answerPlaceholder": "输入您的答案...",
|
||
"customAnswerLabel": "输入自定义答案",
|
||
"dismiss": "忽略",
|
||
"next": "下一个",
|
||
"submit": "提交"
|
||
},
|
||
"statusIndicator": {
|
||
"retrying": "正在重试(第 {{attempt}} 次)...",
|
||
"working": "处理中..."
|
||
},
|
||
"slashPopover": {
|
||
"customBadge": "命令"
|
||
},
|
||
"modelPicker": {
|
||
"title": "选择模型",
|
||
"searchPlaceholder": "搜索模型..."
|
||
},
|
||
"variantPicker": {
|
||
"title": "推理强度",
|
||
"autoLabel": "自动",
|
||
"autoDescription": "使用模型默认推理强度",
|
||
"effort": {
|
||
"low": "速度更快,推理较简略",
|
||
"medium": "推理与速度均衡",
|
||
"high": "深入、详尽的推理"
|
||
}
|
||
},
|
||
"directorySwitcher": {
|
||
"title": "切换项目",
|
||
"serverDefaultLabel": "服务器默认",
|
||
"browseLabel": "浏览…",
|
||
"recentProjectsLabel": "最近项目",
|
||
"usesServerDir": "使用服务器的工作目录"
|
||
},
|
||
"directoryBrowserSheet": {
|
||
"noActiveConnection": "没有活动连接",
|
||
"listFailed": "无法列出目录",
|
||
"title": "浏览文件夹",
|
||
"jumpPlaceholder": "跳转到路径...",
|
||
"noSubfolders": "此处没有子文件夹",
|
||
"enterPathHint": "在上方输入路径以开始浏览",
|
||
"useFolderButton": "使用 {{folder}}",
|
||
"thisFolderFallback": "此文件夹"
|
||
},
|
||
"reasoningBlock": {
|
||
"label": "思考中"
|
||
},
|
||
"toolCallCard": {
|
||
"fallbackTitle": "工具",
|
||
"patternOnly": "模式:{{pattern}}",
|
||
"patternWithPath": "模式:{{pattern}},路径:{{path}}"
|
||
},
|
||
"sessionInfo": {
|
||
"noUsageData": "暂无使用数据",
|
||
"loading": "加载中...",
|
||
"loadAllMessages": "加载全部消息",
|
||
"jumpToBeginning": "跳转到开头",
|
||
"pills": {
|
||
"in": "输入",
|
||
"out": "输出",
|
||
"think": "思考",
|
||
"cacheRead": "缓存读",
|
||
"cacheWrite": "缓存写"
|
||
},
|
||
"meta": {
|
||
"created": "创建于",
|
||
"updated": "更新于",
|
||
"messages": "消息数",
|
||
"changes": "变更",
|
||
"shared": "已分享",
|
||
"yes": "是"
|
||
},
|
||
"time": {
|
||
"justNow": "刚刚",
|
||
"minutesAgo": "{{count}} 分钟前",
|
||
"hoursAgo": "{{count}} 小时前",
|
||
"daysAgo": "{{count}} 天前"
|
||
}
|
||
}
|
||
},
|
||
"demo": {
|
||
"title": "演示",
|
||
"banner": "演示 — 示例对话,未连接服务器",
|
||
"ctaTitle": "喜欢这个体验吗?",
|
||
"ctaSubtitle": "这是一个脚本化的演示。连接您自己的 opencode 服务器即可真正体验。",
|
||
"connectButton": "连接您自己的服务器",
|
||
"setupGuideLink": "如何设置服务器",
|
||
"hostedCtaLink": "没有服务器?加入 OpenCode Connect 候补名单 — 托管,无需搭建"
|
||
},
|
||
"update": {
|
||
"available": "有可用更新",
|
||
"body": "版本 {{version}} 已发布,你当前使用的是 {{current}}。",
|
||
"action": "去获取",
|
||
"dismiss": "暂不",
|
||
"upToDate": "已是最新"
|
||
}
|
||
}
|