@quecue/dev-notify 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.en.md +83 -0
- package/CHANGELOG.md +15 -0
- package/README.en.md +275 -0
- package/README.md +11 -4
- package/SECURITY.en.md +78 -0
- package/SECURITY.md +5 -3
- package/dist/channels.js +12 -11
- package/dist/claude-code.js +30 -30
- package/dist/claude-hook.js +23 -23
- package/dist/cli.js +106 -81
- package/dist/config.js +37 -20
- package/dist/credentials.js +14 -13
- package/dist/formatting.js +6 -4
- package/dist/i18n.js +960 -0
- package/dist/maintenance.js +17 -16
- package/dist/prompts.js +7 -6
- package/dist/reply-bridge.js +11 -10
- package/dist/reply-engine.js +20 -19
- package/dist/reply-hooks.js +21 -20
- package/dist/reply-interactions.js +36 -35
- package/dist/reply-outcomes.js +46 -23
- package/dist/reply-platform.js +14 -13
- package/dist/reply-state.js +31 -30
- package/dist/reply-telegram.js +4 -3
- package/dist/setup.js +69 -51
- package/dist/update.js +39 -31
- package/package.json +4 -1
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,960 @@
|
|
|
1
|
+
// 中文是默认语言;英文键必须与中文键完全一致,缺少翻译会在编译期报错。
|
|
2
|
+
const zh = {
|
|
3
|
+
'common.cancelled': '已取消。',
|
|
4
|
+
'common.failure': '操作失败。请检查文件、权限或输入;为避免泄露密钥,这里不显示底层异常。',
|
|
5
|
+
'config.homeAbsolute': 'DEV_NOTIFY_HOME 需要是绝对路径。',
|
|
6
|
+
'config.rootName': '配置',
|
|
7
|
+
'config.objectRequired': '{name} 需要是 JSON 对象。',
|
|
8
|
+
'config.objectUnknown': '{name} 包含不支持的字段;不能直接保存明文密钥。',
|
|
9
|
+
'config.enabledBoolean': 'enabled 需要是布尔值。',
|
|
10
|
+
'config.credentialEnvName': '凭据引用需要是合法的环境变量名称。',
|
|
11
|
+
'config.unsupportedVersion': '不支持这个配置版本。',
|
|
12
|
+
'config.invalidLanguage': 'language 需要是 zh 或 en。',
|
|
13
|
+
'config.invalidReference': '系统凭据引用无效。',
|
|
14
|
+
'config.chatIdsArray': 'telegram.chat_ids 需要是数组。',
|
|
15
|
+
'config.chatIdNumeric': '接收人需要使用数字 chat_id;大整数请写成字符串。',
|
|
16
|
+
'config.chatIdNonZero': '接收人需要是非零的数字 chat_id。',
|
|
17
|
+
'config.telegramToken': 'Telegram Token 格式不正确。',
|
|
18
|
+
'config.feishuWebhook': '飞书 webhook 需要是 open.feishu.cn 的 HTTPS 自定义机器人地址。',
|
|
19
|
+
'config.utf8': '输入需要是有效的 UTF-8 文本。',
|
|
20
|
+
'config.unreadable': '配置文件缺失、无法读取,或不是合法的 UTF-8 JSON。',
|
|
21
|
+
'config.exists': '配置已经存在,没有覆盖。Node 版不会修改旧版原型的配置。',
|
|
22
|
+
'config.createFailed': '无法创建配置,请检查路径和权限。',
|
|
23
|
+
'config.languageNoConfig': '配置文件不存在,无法保存语言设置:{file}。请先运行 setup --lang {language} 创建配置。',
|
|
24
|
+
'credentials.invalidReference': '系统凭据引用无效。',
|
|
25
|
+
'credentials.invalidBundle': '系统凭据数据无效,请重新运行 setup。',
|
|
26
|
+
'credentials.tooLong': '凭据总长度超过 2400 字节,请检查输入;没有保存。',
|
|
27
|
+
'credentials.readFailed': '无法读取系统凭据,或内容无效。请解锁系统凭据存储并允许访问,或重新运行 setup 配置。',
|
|
28
|
+
'credentials.exists': '这个随机凭据引用已经存在,没有覆盖,请重试。',
|
|
29
|
+
'credentials.accessFailed': '无法访问系统凭据存储,请检查系统权限。',
|
|
30
|
+
'credentials.writeUnknown': '凭据写入状态未知,清理也失败了。请检查引用 ID:{id}',
|
|
31
|
+
'credentials.writeFailed': '系统凭据写入失败,配置没有切换。',
|
|
32
|
+
'credentials.deleteFailed': '系统凭据删除失败,请检查存储权限。',
|
|
33
|
+
'credentials.platform': '系统凭据仅支持 Windows 和 macOS;其他平台请使用环境变量。',
|
|
34
|
+
'credentials.nativeLoad': '原生凭据组件无法加载。请确认 npm 安装保留了 optional 依赖,并且架构匹配;不会降级为明文存储。',
|
|
35
|
+
'credentials.oldReference': '这是旧版原型保存的凭据引用。请用 setup 重新输入并保存为 Node 凭据,或显式提供环境变量;不会自动读取或删除旧凭据。',
|
|
36
|
+
'credentials.missingEntry': '系统凭据条目缺失,请运行 setup 重新配置。',
|
|
37
|
+
'prompts.terminalRequired': '配置向导需要在交互终端中运行。自动化场景可以改用 setup --template --yes 搭配环境变量。',
|
|
38
|
+
'prompts.hiddenUnsupported': '当前终端不支持隐藏输入。为了不暴露密钥,这里不会改用明文输入;请在支持的终端中运行,或用环境变量配置。',
|
|
39
|
+
'prompts.hiddenIncomplete': '隐藏输入没有完成,凭据没有保存。',
|
|
40
|
+
'prompts.cancelled': '已取消。',
|
|
41
|
+
'prompts.inputTooLong': '凭据输入过长,没有保存。',
|
|
42
|
+
'channels.emptyTitle': '通知标题不能为空。',
|
|
43
|
+
'channels.telegramTooLong': 'Telegram 分段后仍然超过消息长度限制。',
|
|
44
|
+
'channels.feishuTooLong': '飞书分段后仍然超过请求大小限制。',
|
|
45
|
+
'channels.noResponse': '服务端没有返回内容。',
|
|
46
|
+
'channels.responseTooLarge': '服务端响应过大,已停止读取。',
|
|
47
|
+
'channels.notJsonObject': '服务端返回的不是 JSON 对象。',
|
|
48
|
+
'channels.network': '网络请求失败或响应无效。为避免重复通知,不会自动重发;这条消息可能没有送达。',
|
|
49
|
+
'channels.rejected': '渠道拒绝了这次发送。请检查凭据、接收人授权、签名和频率限制。',
|
|
50
|
+
'channels.sendFailed': '发送失败,这条消息可能没有送达。',
|
|
51
|
+
'channels.feishuReplyButton': '💬 在 Telegram 回复 Claude',
|
|
52
|
+
'format.noSpace': '可用空间不足,无法分段。',
|
|
53
|
+
'format.oneChar': '可用空间连一个字符都放不下。',
|
|
54
|
+
'format.telegramHeader': 'Telegram 标题或底部信息太长,没有剩余空间放正文。',
|
|
55
|
+
'format.feishuHeader': '飞书标题或底部信息太长,没有剩余空间放正文。',
|
|
56
|
+
'setup.readFailed': '无法读取现有配置,这次没有做任何修改。',
|
|
57
|
+
'setup.parseFailed': '现有配置无法解析,这次没有覆盖它。请先修复 JSON。',
|
|
58
|
+
'setup.lockUnavailable': '配置写入锁不可用。请检查权限;如果确认没有向导在运行,可以删除残留的 .setup.lock。',
|
|
59
|
+
'setup.changedDuringWizard': '配置在向导期间发生了变化,这次没有覆盖它。请重试。',
|
|
60
|
+
'setup.credentialVerifyFailed': '凭据写入后校验失败,配置没有切换。',
|
|
61
|
+
'setup.changedDuringSave': '配置在保存期间发生了变化,这次没有覆盖它。请重试。',
|
|
62
|
+
'setup.tempCleanupFailed': '临时配置没有清理掉:{name}',
|
|
63
|
+
'setup.credentialCleanupFailed': '配置没有切换,新凭据也未能清理。引用 ID:{id}',
|
|
64
|
+
'setup.lockCleanupFailed': '配置写入锁没有清理掉。请确认没有向导在运行,再删除 .setup.lock。',
|
|
65
|
+
'setup.oldCredentialCleanupFailed': '配置已保存,但旧凭据没有清理掉。引用 ID:{id}',
|
|
66
|
+
'setup.oldSystemRetained': '旧版原型的旧凭据仍然保留,由旧版工具继续管理,避免两个实现互相误删。',
|
|
67
|
+
'setup.path': '配置路径:{file}',
|
|
68
|
+
'setup.secretsNote': 'Token、webhook 和签名密钥都不会回显,将保存到 Windows Credential Manager / macOS Keychain;配置文件只保留引用。',
|
|
69
|
+
'setup.channelPrompt': '选择通知渠道:1 Telegram,2 飞书,3 两者{current}(输入其他内容取消):',
|
|
70
|
+
'setup.credentialUnreadable': '当前凭据暂时读不到,可能是条目缺失、凭据库锁定或权限不足。',
|
|
71
|
+
'setup.reenterPrompt': '要重新输入所选渠道的凭据吗?[y/N] ',
|
|
72
|
+
'setup.oldSystemDetected': '检测到旧版原型保存的凭据。本次会重新输入并保存为 Node 版凭据,旧凭据保持不变。',
|
|
73
|
+
'setup.secretRequiredKeep': '{label}(隐藏输入,不回显;留空保留当前值):',
|
|
74
|
+
'setup.secretRequiredNew': '{label}(隐藏输入,不回显;不会从环境变量自动填充):',
|
|
75
|
+
'setup.secretOptionalKeep': '{label}(隐藏输入,不回显;可选;留空保留当前值;输入 - 清除):',
|
|
76
|
+
'setup.secretOptionalNew': '{label}(隐藏输入,不回显;可选;不会从环境变量自动填充;输入 - 清除):',
|
|
77
|
+
'setup.requiredBlank': '这一项不能为空,请重新输入;按 Ctrl+C 可退出。',
|
|
78
|
+
'setup.invalidFormat': '格式不正确,请重新输入(输入内容不会显示)。',
|
|
79
|
+
'setup.telegramChatInstruction': '请先让接收人给 Bot 发一条消息,然后填写数字 chat_id;这里不会自动获取或配对接收人。',
|
|
80
|
+
'setup.telegramChatPrompt': '接收人 chat_id,多个用逗号分隔(留空保留现有名单):',
|
|
81
|
+
'setup.telegramChatInvalid': '请填写至少一个有效的数字 chat_id;按 Ctrl+C 可退出。',
|
|
82
|
+
'setup.channelsEnabled': '将启用:{channels}',
|
|
83
|
+
'setup.envPriority': '环境变量的优先级更高,空值也会覆盖这里的设置;测试通知使用最终生效的配置。',
|
|
84
|
+
'setup.envOverrides': '以下环境变量正在覆盖配置:{names}',
|
|
85
|
+
'setup.oldDeleteWarning': '保存成功后会删除旧凭据;如果其他配置也引用了同一个凭据,需要一并更新。',
|
|
86
|
+
'setup.disabledChannels': '没有选中的渠道会被停用;新凭据只用于本次选中的渠道。',
|
|
87
|
+
'setup.actionSave': '保存配置和系统凭据',
|
|
88
|
+
'setup.actionTest': '发送固定内容的测试通知',
|
|
89
|
+
'setup.actionHooks': '安装 Claude Code 通知 hooks',
|
|
90
|
+
'setup.continue': '将{actions}。继续?[Y/n] ',
|
|
91
|
+
'setup.saved': '配置和系统凭据已保存。',
|
|
92
|
+
'setup.testSuccess': '测试通知发送成功。',
|
|
93
|
+
'setup.testFailed': '配置已保存。测试通知没有发送成功,请运行 dev-notify doctor 检查。',
|
|
94
|
+
'setup.testFailedEnv': '配置已保存。测试通知没有发送成功,可能是环境变量覆盖或网络问题;请运行 dev-notify doctor 检查。',
|
|
95
|
+
'setup.testSkipped': '已跳过测试通知。',
|
|
96
|
+
'setup.hooksFailed': '配置已保存。Claude Code hooks 没有安装完成:{reason}',
|
|
97
|
+
'setup.hooksCheckHint': '请运行 integration claude-code status 检查',
|
|
98
|
+
'setup.replyHint': '如需在 Telegram 中回复 Claude,请运行:dev-notify reply setup',
|
|
99
|
+
'setup.clearNoReference': '当前配置没有系统凭据引用,无需清理。',
|
|
100
|
+
'setup.clearOldBackend': '这是旧版原型保存的凭据;Node 版不会跨实现删除,请用原工具处理。',
|
|
101
|
+
'setup.clearWarning': '将删除当前配置引用的系统凭据,并从配置中移除引用。环境变量不受影响;如果其他配置共享同一个凭据,它们也会失效。',
|
|
102
|
+
'setup.clearConfirm': '确认清除吗?[y/N] ',
|
|
103
|
+
'setup.cleared': '凭据引用已移除。如果系统条目删除失败,上方会显示提示。',
|
|
104
|
+
'setup.channelTelegram': 'Telegram({count} 个接收人)',
|
|
105
|
+
'setup.channelFeishu': '飞书',
|
|
106
|
+
'setup.labelFeishuWebhook': '飞书 webhook',
|
|
107
|
+
'setup.labelFeishuSecret': '飞书签名密钥',
|
|
108
|
+
'cli.help': `dev-notify {version} — 跨平台开发任务通知
|
|
109
|
+
|
|
110
|
+
命令:
|
|
111
|
+
send --title 标题 [--content 正文 | --content-file 文件 | --stdin]
|
|
112
|
+
[--channel all|telegram|feishu] [--level info|success|warn|error]
|
|
113
|
+
[--footer 辅助信息] [--dry-run]
|
|
114
|
+
setup [--no-test] [--no-hooks]
|
|
115
|
+
配置渠道及系统凭据;默认同时发送测试并安装
|
|
116
|
+
Claude Code 通知 hooks,一次确认完成
|
|
117
|
+
setup --template [--yes] 只创建无密钥模板;不会覆盖已有配置,也不会安装 hooks
|
|
118
|
+
credentials clear 移除当前 Node 凭据引用和条目(需要确认)
|
|
119
|
+
paths 显示配置路径(不会写入文件)
|
|
120
|
+
doctor / status 离线检查(不会发送消息)
|
|
121
|
+
update [--check] [--yes] [--no-post]
|
|
122
|
+
检查并更新到 npm 最新版本,并维护 hooks 和桥接
|
|
123
|
+
integration list 列出可用集成
|
|
124
|
+
integration claude-code install / status / remove
|
|
125
|
+
单独安装、查询或移除用户级 hooks(install/remove 可用 --yes)
|
|
126
|
+
reply setup 授权可信的 Telegram 私聊用户
|
|
127
|
+
reply start / status / stop
|
|
128
|
+
启动、查询或停止回复桥接
|
|
129
|
+
reply disable 撤销远程回复授权并停止桥接(需要确认)
|
|
130
|
+
reply run 前台运行桥接(排错用,不启用系统自启动)
|
|
131
|
+
language [zh|en] 查看或切换已保存的界面语言
|
|
132
|
+
|
|
133
|
+
全局选项:--config 路径、--lang zh|en、--help、--version
|
|
134
|
+
环境变量:TELEGRAM_BOT_TOKEN、TELEGRAM_CHAT_ID / TELEGRAM_CHAT_IDS、
|
|
135
|
+
FEISHU_WEBHOOK、FEISHU_SECRET;显式存在时优先。
|
|
136
|
+
DEV_NOTIFY_LANG=zh|en 切换界面语言。详见 README。
|
|
137
|
+
系统凭据保存在 Windows Credential Manager / macOS Keychain;不会写入明文密钥。`,
|
|
138
|
+
'cli.invalidArgs': '参数无效,请运行 --help 查看用法。',
|
|
139
|
+
'cli.invalidCommand': '命令或选项组合不正确,请运行 --help 查看用法。',
|
|
140
|
+
'cli.invalidLanguage': '语言必须是 zh 或 en:{value}',
|
|
141
|
+
'cli.integrationList': 'claude-code:支持通知、Telegram 回复和结构化问题交互。通知 hooks 与回复权限分开,默认只发送通知,不接收远程输入。',
|
|
142
|
+
'cli.integrationUsage': '请使用 integration list,或 integration claude-code install / status / remove。',
|
|
143
|
+
'cli.integrationStatusFile': 'Claude Code 用户级设置:{file}',
|
|
144
|
+
'cli.integrationStatusCounts': '本工具 hooks:Stop {stop} 个,Notification {notification} 个,会话生命周期 {lifecycle}/3 个,交互及结果确认 {interaction}/5 个;其他处理器 {others} 个。',
|
|
145
|
+
'cli.integrationDisabled': '当前文件启用了 disableAllHooks,安装后 hooks 不会生效;请自行解除禁用。',
|
|
146
|
+
'cli.integrationStatusNote': '这里只检查用户级文件。是否实际加载还受项目和托管策略影响,请在 Claude Code 的 /hooks 中确认。',
|
|
147
|
+
'cli.setupChannelFirst': '请先运行 setup 配置至少一个通知渠道,再安装 Claude Code hooks。',
|
|
148
|
+
'cli.replyUsage': '请使用 reply setup / start / status / stop / disable / run。',
|
|
149
|
+
'cli.credentialsUsage': 'credentials 目前只支持 clear,并且需要在交互终端中确认。',
|
|
150
|
+
'cli.yesTemplateOnly': '--yes 只能和 --template 一起使用;保存密钥前仍然需要确认。',
|
|
151
|
+
'cli.sendTitle': 'send 需要提供非空的 --title。',
|
|
152
|
+
'cli.sendSources': '--content、--content-file 和 --stdin 只能选择一个。',
|
|
153
|
+
'cli.channelLevel': '渠道或通知级别不正确。',
|
|
154
|
+
'cli.segmentationFailed': '{channel}:无法安全分段。请缩短标题或底部信息,或检查正文格式。',
|
|
155
|
+
'cli.dryRun': '{channel}:接收目标 {recipients},预计请求 {items} 条(dry-run,没有实际发送)',
|
|
156
|
+
'cli.sent': '{channel}:已发送 {sent}/{planned} 条',
|
|
157
|
+
'cli.testSent': '{channel}:测试已发送 {sent}/{planned} 条',
|
|
158
|
+
'cli.noChannels': '没有可用渠道,请先配置环境凭据和接收人。',
|
|
159
|
+
'cli.channelNotReady': '这个渠道未启用,或配置不完整。',
|
|
160
|
+
'cli.testTitle': 'dev-notify 配置测试',
|
|
161
|
+
'cli.testContent': '这是一条由你确认发送的测试通知。',
|
|
162
|
+
'cli.setupNoteTest': '保存后会向最终生效的接收目标发送一条固定内容的测试通知。',
|
|
163
|
+
'cli.setupNoteHooksPath': 'Claude Code 用户级设置:{path}',
|
|
164
|
+
'cli.setupNoteHooksScope': '会为该设置文件对应的所有项目安装通知 hooks。最终回复正文可能包含敏感内容,将发送到配置实际生效的渠道。',
|
|
165
|
+
'cli.setupNoteHooksLifecycle': '同时安装会话生命周期和结构化问题 hooks。远程输入只有在运行 reply setup 授权后才会开启。',
|
|
166
|
+
'cli.skipHooks': '跳过 Claude Code hooks:{reason}',
|
|
167
|
+
'cli.skipHooksNoPath': '跳过 Claude Code hooks:没有找到用户级设置路径。',
|
|
168
|
+
'cli.templateWillCreate': '将创建无密钥模板:{file}。不会联网,也不会修改 hooks。',
|
|
169
|
+
'cli.templateCancelled': '已取消,没有写入。',
|
|
170
|
+
'cli.templateCreated': '模板已创建。请配置环境凭据和接收人。',
|
|
171
|
+
'cli.configPath': '配置路径: {file}',
|
|
172
|
+
'cli.channelReady': '配置完整(尚未验证网络)',
|
|
173
|
+
'cli.channelNotReadyStatus': '未启用或配置不完整',
|
|
174
|
+
'cli.channelStatus': '{channel}:{status}',
|
|
175
|
+
'cli.credentialsNote': '凭据:优先使用环境变量,其次系统凭据;本检查不联网,系统可能弹出授权提示。',
|
|
176
|
+
'cli.confirmTemplate': '确认创建模板?[y/N] ',
|
|
177
|
+
'cli.nonInteractive': '当前不是交互终端。自动化场景请使用 setup --template --yes。',
|
|
178
|
+
'cli.replySaved': '授权已保存。请确认 hooks 已安装,然后运行 reply start。旧消息的回复映射不会保留。',
|
|
179
|
+
'cli.bridgeStopped': '桥接已停止或未运行。',
|
|
180
|
+
'cli.replyDisabled': '已撤销授权并请求停止。正在进行中的调用无法撤回。',
|
|
181
|
+
'cli.stopStopped': '桥接已停止或未运行。授权仍然保留,下次事件可以再次启动;如需彻底关闭,请运行 reply disable。',
|
|
182
|
+
'cli.stopRequested': '已发出停止请求,桥接正在退出。可运行 reply status 查看状态。',
|
|
183
|
+
'cli.replyStatusAccess': '远程回复:已授权 {users} 个私聊用户;工具权限逐次确认{state}。',
|
|
184
|
+
'cli.replyPermissionOn': '已开启',
|
|
185
|
+
'cli.replyPermissionOff': '未开启',
|
|
186
|
+
'cli.replyStatusNoAccess': '远程回复:尚未启用。',
|
|
187
|
+
'cli.bridgeReady': '桥接:已就绪。',
|
|
188
|
+
'cli.bridgeStarting': '桥接:进程存在,但还没有就绪。',
|
|
189
|
+
'cli.bridgeNotRunning': '桥接:未运行。',
|
|
190
|
+
'cli.replyStartReady': '回复桥接已就绪。请从新的任务通知进入。',
|
|
191
|
+
'cli.replyStartNotReady': '桥接还没有就绪。请运行 reply status 或 reply run 查看原因;如果旧版桥接在运行,请先停用它。',
|
|
192
|
+
'cli.languageCurrent': '当前语言:{language}({code})。',
|
|
193
|
+
'cli.languageChanged': '语言已切换为{language}({code})。',
|
|
194
|
+
'cli.languageAlready': '当前已经是{language}({code})。',
|
|
195
|
+
'cli.languageHint': '使用 language zh 或 language en 切换并保存。',
|
|
196
|
+
'update.npmUnavailable': '无法运行 npm。请确认已安装 npm,并且它在 PATH 中。',
|
|
197
|
+
'update.checkNetwork': '无法检查最新版本。请检查网络后重试。',
|
|
198
|
+
'update.checkHttp': '无法检查最新版本(HTTP {status})。请检查网络后重试。',
|
|
199
|
+
'update.parseRegistry': 'npm registry 返回的版本信息无法解析。',
|
|
200
|
+
'update.registryVersion': 'npm registry 返回的版本号格式不受支持。',
|
|
201
|
+
'update.versionFormat': '版本号格式不受支持。',
|
|
202
|
+
'update.terminalRequired': '更新需要在交互终端中确认;非交互场景请使用 dev-notify update --yes。',
|
|
203
|
+
'update.confirm': '更新到 {latest}?[y/N] ',
|
|
204
|
+
'update.manualPost': '如有 Claude Code hooks,请运行 dev-notify integration claude-code install;如使用远程回复,请重启桥接。',
|
|
205
|
+
'update.partialUpdated': '更新已完成,但后续维护步骤没有全部成功;请按上面的提示检查。',
|
|
206
|
+
'update.partial': '维护步骤没有全部成功;请按上面的提示检查。',
|
|
207
|
+
'update.postDoneUpdated': '更新后的维护步骤已完成。',
|
|
208
|
+
'update.postDone': '维护步骤已完成。',
|
|
209
|
+
'update.currentFormat': '当前版本号格式不受支持,无法检查更新。',
|
|
210
|
+
'update.upToDate': '已是最新版本 {version}。',
|
|
211
|
+
'update.maintenanceNote': '将执行 Claude Code hooks 和回复桥接维护。',
|
|
212
|
+
'update.versions': '当前版本 {current},npm 最新版本 {latest}。',
|
|
213
|
+
'update.checkHint': '运行 dev-notify update 更新。',
|
|
214
|
+
'update.postNote': '更新完成后会自动重新安装绑定当前配置的 Claude Code hooks,并重启正在运行的回复桥接;可用 --no-post 跳过。',
|
|
215
|
+
'update.cancelled': '已取消,没有更新。',
|
|
216
|
+
'update.running': '运行 npm install -g {name}@{latest} ...',
|
|
217
|
+
'update.failed': '更新没有完成。请检查 npm 权限,或手动运行 npm install -g {name}@latest。',
|
|
218
|
+
'update.updated': '已更新到 {latest}。请重新打开终端后运行 dev-notify --version 确认。',
|
|
219
|
+
'maintenance.runFailed': '无法运行更新后的 dev-notify。请重新打开终端后运行 dev-notify --version 检查。',
|
|
220
|
+
'maintenance.reasonHint': '请运行 dev-notify integration claude-code status 或 dev-notify reply status 检查。',
|
|
221
|
+
'maintenance.hooksCheckFailed': '无法检查 Claude Code hooks:{reason}',
|
|
222
|
+
'maintenance.noHooks': '未检测到本工具的 Claude Code hooks,跳过。',
|
|
223
|
+
'maintenance.otherConfig': 'Claude Code hooks 绑定的是其他通知配置,跳过自动更新;如需更新,请用原来的 --config 运行 integration claude-code install。',
|
|
224
|
+
'maintenance.updatingHooks': '更新 Claude Code hooks ...',
|
|
225
|
+
'maintenance.hooksUpdated': 'Claude Code hooks 已更新。',
|
|
226
|
+
'maintenance.hooksFailed': 'Claude Code hooks 更新失败。',
|
|
227
|
+
'maintenance.hooksFailedReason': 'Claude Code hooks 更新失败:{reason}',
|
|
228
|
+
'maintenance.bridgeCheckFailed': '无法检查回复桥接:{reason}',
|
|
229
|
+
'maintenance.restartingBridge': '重启回复桥接 ...',
|
|
230
|
+
'maintenance.bridgeStillRunning': '回复桥接仍在退出,请稍后运行 dev-notify reply start。',
|
|
231
|
+
'maintenance.bridgeRestarted': '回复桥接已重启。',
|
|
232
|
+
'maintenance.bridgeStartFailed': '回复桥接启动失败。',
|
|
233
|
+
'maintenance.bridgeRestartFailed': '回复桥接重启失败:{reason}',
|
|
234
|
+
'maintenance.noBridge': '未检测到运行中的回复桥接,跳过。',
|
|
235
|
+
'claude.settingsAbsolute': 'CLAUDE_CONFIG_DIR 需要是绝对路径,Claude Code 设置没有改动',
|
|
236
|
+
'claude.settingsTooLarge': 'Claude Code 设置超过 1 MiB,操作已停止,文件没有改动。',
|
|
237
|
+
'claude.settingsReadFailed': '无法读取 Claude Code 设置,操作已停止。',
|
|
238
|
+
'claude.settingsInvalidJson': 'Claude Code 设置不是合法的 UTF-8 JSON,没有覆盖。',
|
|
239
|
+
'claude.settingsInvalidShape': 'Claude Code 设置或 hooks 结构无效,没有覆盖。',
|
|
240
|
+
'claude.hooksInvalidShape': 'Claude Code hook 数组结构无效,没有覆盖。',
|
|
241
|
+
'claude.lockUnavailable': '暂时无法获取 Claude Code 设置写入锁。请确认没有安装进程在运行,再处理残留的 .dev-notify.lock。',
|
|
242
|
+
'claude.changedDuringConfirm': 'Claude Code 设置在确认期间发生了变化,没有覆盖,请重试。',
|
|
243
|
+
'claude.changedDuringSave': 'Claude Code 设置在保存期间发生了变化,没有覆盖,请重试。',
|
|
244
|
+
'claude.tempCleanupFailed': '临时文件清理失败。安装结束后请删除 .dev-notify-*.tmp。',
|
|
245
|
+
'claude.lockCleanupFailed': '锁文件清理失败。安装结束后请删除 .dev-notify.lock。',
|
|
246
|
+
'claude.settingsPath': 'Claude Code 用户级设置:{file}',
|
|
247
|
+
'claude.noHooks': '没有找到本工具添加的 hooks,设置没有改动。',
|
|
248
|
+
'claude.alreadyInstalled': '本工具 hooks 已经安装,配置一致,无需重复添加。',
|
|
249
|
+
'claude.configPath': '通知配置:{config}',
|
|
250
|
+
'claude.installScope': '会为这个 Claude Code 配置目录下的所有项目启用通知:任务结束时发送最终回复,需要你确认或输入时也会提醒。',
|
|
251
|
+
'claude.installSensitive': '最终回复和提醒正文可能包含敏感内容,会发送到配置实际生效的 Telegram / 飞书。环境变量仍然优先。',
|
|
252
|
+
'claude.installLifecycle': '同时安装会话生命周期和结构化问题 hooks。远程输入需要另行运行 reply setup 授权。',
|
|
253
|
+
'claude.installReads': '不会读取整份会话记录。启用回复后,会读取会话的进程元数据;结构化问题或权限请求会发送对应的问题和工具信息。',
|
|
254
|
+
'claude.installTiming': 'PreToolUse 只登记调用身份;PermissionRequest 会和本机终端窗口同时等待,远程回答的有效期是 10 分钟。安装完成事件只用于反馈结果,不会代替你作答。已核对 Claude Code 2.1.316;其他版本或宿主环境需要另行验证。',
|
|
255
|
+
'claude.otherHandlers': '当前文件里还有 {count} 个其他相关处理器,可能会重复通知。',
|
|
256
|
+
'claude.projectHooks': '项目级或插件的 hooks 也可能同时生效;本工具不会自动迁移或删除旧版 hooks。',
|
|
257
|
+
'claude.disabledWarning': '注意:该文件启用了 disableAllHooks,安装后 hooks 也不会生效;请自行解除禁用。',
|
|
258
|
+
'claude.removeScope': '只会移除本工具添加的通知、生命周期和交互处理器;其他设置、hooks、通知配置和系统凭据都会保留。如需停止回复桥接,请运行 reply disable 或 reply stop。',
|
|
259
|
+
'claude.confirmInstall': '安装这些 Claude Code hooks?[y/N] ',
|
|
260
|
+
'claude.confirmRemove': '移除本工具的 Claude Code hooks?[y/N] ',
|
|
261
|
+
'claude.cancelled': '已取消,Claude Code 设置没有改动。',
|
|
262
|
+
'claude.installed': 'Claude Code hooks 已安装。请在 /hooks 中检查并按界面确认;如果没有生效,请重启会话。',
|
|
263
|
+
'claude.removed': '本工具的 Claude Code hooks 已移除。请在 /hooks 中检查,必要时重启会话。',
|
|
264
|
+
'hook.timeout': 'Claude Code hook 输入超时,通知没有发送。',
|
|
265
|
+
'hook.tooLarge': 'Claude Code hook 输入超过大小限制,通知没有发送;内容不会被截断。',
|
|
266
|
+
'hook.footerProject': '项目:{value}',
|
|
267
|
+
'hook.footerTopic': '主题:{value}',
|
|
268
|
+
'hook.footerSession': '会话:{value}',
|
|
269
|
+
'hook.invalidJson': 'Claude Code hook 输入不是合法的 UTF-8 JSON,通知没有发送。',
|
|
270
|
+
'hook.notObject': 'Claude Code hook 输入需要是 JSON 对象。',
|
|
271
|
+
'hook.invalidStopState': 'Claude Code Stop 状态字段无效。',
|
|
272
|
+
'hook.invalidReply': 'Claude Code 最终回复字段无效。',
|
|
273
|
+
'hook.replyTitle': 'Claude Code 回复完成',
|
|
274
|
+
'hook.replyFallback': '本轮回复已结束,Claude Code 没有提供最终正文。请回到终端查看;这里不会读取会话文件来补正文,以免显示过期内容。',
|
|
275
|
+
'hook.invalidNotification': 'Claude Code 通知正文字段无效。',
|
|
276
|
+
'hook.notificationTitle': 'Claude Code 需要你处理',
|
|
277
|
+
'hook.notificationFallback': 'Claude Code 正在等待你的确认或输入,请回到终端处理。',
|
|
278
|
+
'hook.interactionFailed': 'Claude Code 的回复状态或交互处理失败。没有自动选择答案或批准权限,请在本机处理。',
|
|
279
|
+
'hook.sessionNameFailed': '读取不到 Claude Code 会话名称,通知底部将省略主题。',
|
|
280
|
+
'hook.replyNotReady': '远程回复还没有就绪,仍会尝试发送普通通知。',
|
|
281
|
+
'hook.coverageFailed': '没有核验到选择题通知的覆盖情况,将保留普通权限提醒。',
|
|
282
|
+
'hook.sendIncomplete': '{channel}:Claude Code 通知没有完整发送。整条消息不会自动重发。',
|
|
283
|
+
'hook.sendFailed': '{channel}:Claude Code 通知发送失败。请检查配置、系统凭据和网络;整条消息不会自动重发。',
|
|
284
|
+
'hook.noChannels': 'Claude Code 通知没有可用渠道,请运行 dev-notify doctor 检查。',
|
|
285
|
+
'reply.readFailed': '无法读取回复配置或状态。为了不覆盖现有数据,远程输入没有启用。',
|
|
286
|
+
'reply.lockUnavailable': '无法获取回复状态写入锁。',
|
|
287
|
+
'reply.lockBusy': '回复状态锁正忙。请确认相关进程已经退出,再处理残留锁。',
|
|
288
|
+
'reply.invalidPolicy': '回复授权配置无效,远程输入已停用。',
|
|
289
|
+
'reply.hooksMissing': '回复所需的 hooks 缺失、时序不安全或已禁用。请重新运行 integration claude-code install,并在 /hooks 中确认加载。',
|
|
290
|
+
'reply.botChanged': 'Telegram Bot 已变更或不可用,请重新运行 reply setup 授权。',
|
|
291
|
+
'reply.usersRevoked': '授权用户不在当前 Telegram 接收名单中,远程输入已停用。',
|
|
292
|
+
'reply.authorizationChanged': '回复授权已撤销或发生变化,没有写入旧状态。',
|
|
293
|
+
'reply.invalidState': '回复状态结构无效,远程输入已停用。',
|
|
294
|
+
'reply.setupHooksFirst': '请先运行 integration claude-code install,安装绑定此通知配置的完整 hooks,再配置回复。',
|
|
295
|
+
'reply.setupTelegramFirst': '回复 Claude 需要先配置 Telegram Bot 和私聊接收人。',
|
|
296
|
+
'reply.setupPrivateOnly': '远程回复仅支持 Telegram 私聊用户,不支持群聊。',
|
|
297
|
+
'reply.setupNoticeInput': '远程回复等同于在本机 Claude Code 终端输入并提交内容。它可以提交 Claude 命令,但不会自动批准工具权限。请只授权给可信用户。',
|
|
298
|
+
'reply.setupNoticeBridge': '飞书按钮会跳转到 Telegram,不直接接收飞书消息。这个功能需要独占 Bot 的 getUpdates,请不要与旧版桥接或其他机器共用同一个 Bot。',
|
|
299
|
+
'reply.setupNoticePlatform': 'Windows 使用系统 PowerShell / 控制台 API;macOS 使用 Ghostty 或 tmux,需要相应的系统权限。',
|
|
300
|
+
'reply.setupNoticeUnsupported': '目前不支持 VS Code 集成终端、WSL 和 SSH。目标不确定或会话已经切换时,会拒绝输入。',
|
|
301
|
+
'reply.setupAvailable': '通知接收人不会自动获得输入权限。可选择的私聊 chat_id:{users}',
|
|
302
|
+
'reply.setupPrompt': '请输入要授权的私聊 chat_id(逗号分隔;留空取消):',
|
|
303
|
+
'reply.setupInvalidUser': '只能授权当前通知名单中的私聊用户。',
|
|
304
|
+
'reply.setupAuthorizing': '将授权以下用户远程输入:{users}',
|
|
305
|
+
'reply.setupSensitive': '结构化问题会展示真实选项,也支持自定义回答;普通回复会在本轮结束后输入。问题、选项和工具请求参数可能包含敏感信息,会发送到授权私聊和已配置的飞书。',
|
|
306
|
+
'reply.setupPermissionsPrompt': '是否允许这些用户逐次批准或拒绝工具权限?这不会修改永久规则。[y/N] ',
|
|
307
|
+
'reply.setupConfirm': '确认启用远程回复并接受上述权限范围?[y/N] ',
|
|
308
|
+
'reply.setupChanged': '回复授权已被其他进程修改,请重试。',
|
|
309
|
+
'reply.setupConfigChanged': '通知配置在授权期间发生了变化,请重试。',
|
|
310
|
+
'reply.setupSaved': '授权已保存。旧消息的回复映射不会保留;请从启用后的任务完成通知进入。',
|
|
311
|
+
'reply.disableNotEnabled': '远程回复尚未启用。',
|
|
312
|
+
'reply.disableConfirm': '确认禁用远程回复?通知和凭据都会保留。[y/N] ',
|
|
313
|
+
'reply.disableChanged': '回复授权发生了变化,请重试。',
|
|
314
|
+
'reply.disabled': '远程回复已禁用。正在进行的操作无法撤回,桥接会在下次检查时退出。',
|
|
315
|
+
'reply.endSessionReason': '会话已经结束,或无法核验身份',
|
|
316
|
+
'reply.endSwitchedReason': '会话已经切换',
|
|
317
|
+
'reply.endTurnReason': '本轮已结束',
|
|
318
|
+
'reply.endLocalReason': '本机已开始新任务或新会话',
|
|
319
|
+
'reply.receivedTitle': '✅ Claude 已收到回复',
|
|
320
|
+
'reply.receivedBody': 'Claude 已收到你提交的回复,任务完成后会再发通知。',
|
|
321
|
+
'reply.receivedTelegramFailed': 'Telegram:收到确认没有发送成功;已提交的输入不会重放。',
|
|
322
|
+
'reply.receivedFeishuBody': 'Claude 已收到你提交的回复,任务完成后会再发通知。为减少扩散,这里不转发回复原文。',
|
|
323
|
+
'reply.receivedFeishuFooter': '会话:{session}',
|
|
324
|
+
'reply.receivedFeishuIncomplete': '飞书:收到确认没有完整发送;已提交的输入不会重放。',
|
|
325
|
+
'reply.receivedFeishuFailed': '飞书:收到确认发送失败;已提交的输入不会重放。',
|
|
326
|
+
'reply.bridgeNotReadyButton': '回复桥接还没有就绪,这条通知不会显示回复按钮。可运行 reply status 查看原因。',
|
|
327
|
+
'reply.botUsernameInvalid': 'Telegram Bot 用户名无效,回复按钮没有启用。',
|
|
328
|
+
'reply.noMessageId': '通知没有返回可关联的 Telegram 消息 ID。',
|
|
329
|
+
'reply.noSession': '没有核验到会话,结构化交互将在本机处理。',
|
|
330
|
+
'reply.noMatchingCall': '没有唯一匹配到这次工具调用,远程交互没有启用;本机窗口不受影响。',
|
|
331
|
+
'reply.bridgeNotReadyQuestion': '回复桥接还没有就绪,问题将在本机处理。',
|
|
332
|
+
'reply.permissionRequest': '工具权限请求:{tool}',
|
|
333
|
+
'reply.interactionEnded': '远程交互已经结束,或答案没有提交。不会自动作答,本机操作不受影响。',
|
|
334
|
+
'reply.interactionFailed': '远程交互处理失败,请在本机检查。',
|
|
335
|
+
'reply.interactionCancelled': '交互等待已取消,远程答案是否生效还没有确认。',
|
|
336
|
+
'reply.sessionGoneTitle': '⚠️ 无法回复',
|
|
337
|
+
'reply.sessionGoneBody': '这个会话已经关闭、切换,或这条通知已过期。请从最新通知进入。',
|
|
338
|
+
'reply.replyPromptTitle': '💬 回复 Claude',
|
|
339
|
+
'reply.replyPromptBody': '请回复此消息输入内容。该输入将提交到对应本机会话。\n会话:{session}',
|
|
340
|
+
'reply.replyPromptLongPress': '请长按这条消息并选择「回复」,然后输入内容。该输入将提交到对应本机会话。\n会话:{session}',
|
|
341
|
+
'reply.processingFailedCallback': '处理没有完成,请检查终端;不会自动重复提交。',
|
|
342
|
+
'reply.processingFailedTitle': '⚠️ 本次提交没有完成',
|
|
343
|
+
'reply.processingFailedBody': '处理时出现了异常,这次提交可能已经登记,也可能没有生效。请检查终端和后续结果;不会自动重复提交。',
|
|
344
|
+
'reply.interactionExpiredCallback': '会话已关闭,或这次交互已经失效。',
|
|
345
|
+
'reply.interactionExpiredTitle': '⚠️ 这次提交没有生效',
|
|
346
|
+
'reply.interactionExpiredBody': '会话已经关闭、切换,或交互已经失效,答案没有回传。',
|
|
347
|
+
'reply.replyBoxHint': '请在回复框输入内容',
|
|
348
|
+
'reply.staleTitle': '⚠️ 本次提交没有生效',
|
|
349
|
+
'reply.staleBody': '这条消息已经超过有效时间,答案没有回传。请查看最新问题或终端状态。',
|
|
350
|
+
'reply.howToTitle': '💬 回复方式',
|
|
351
|
+
'reply.howToBody': '请直接回复任务完成通知,或点击通知里的「回复 Claude」按钮。',
|
|
352
|
+
'reply.expiredReplyBody': '通知已过期,或对应会话已经关闭、切换。请从最新通知回复。',
|
|
353
|
+
'reply.replyFailedTitle': '❌ 回复没有提交',
|
|
354
|
+
'reply.invalidInput': '输入无效。',
|
|
355
|
+
'reply.sessionChanged': '会话已经变化,这次回复没有提交。',
|
|
356
|
+
'reply.pendingTitle': '⏳ 新回复没有提交',
|
|
357
|
+
'reply.pendingBody': '这个会话已有一条待确认的回复。请先等待确认,或检查本机终端后再试。',
|
|
358
|
+
'reply.queuedTitle': '⏳ 回复已排队',
|
|
359
|
+
'reply.queuedBody': 'Claude 正在处理当前任务;本地队列将在本轮结束后尝试提交,不会把文本输入到正在等待权限的弹窗。',
|
|
360
|
+
'reply.queueExpired': '排队的回复已超过 5 分钟,没有提交。请检查本机后重新回复。',
|
|
361
|
+
'reply.sessionClosed': '会话已经关闭或切换,这次回复没有提交。',
|
|
362
|
+
'reply.forwardedTitle': '✅ 已转发给 Claude',
|
|
363
|
+
'reply.forwardedBody': '终端输入已提交,正在等待 UserPromptSubmit 确认。',
|
|
364
|
+
'reply.forwardUnknownTitle': '⚠️ 转发状态待确认',
|
|
365
|
+
'reply.forwardFailed': '提交没有完成,请检查本机终端;不会自动重复提交。',
|
|
366
|
+
'reply.invalidQuestions': '问题结构无效,请在本机回答。',
|
|
367
|
+
'reply.permissionsNotAuthorized': '未授权远程处理工具权限。',
|
|
368
|
+
'reply.targetChanged': '会话目标发生了变化。',
|
|
369
|
+
'reply.callUnavailable': '调用已经结束或已绑定,没有创建远程问题。',
|
|
370
|
+
'reply.questionSwitched': '问题已切换,旧请求不再接受答案。',
|
|
371
|
+
'reply.allowButton': '✅ 本次允许',
|
|
372
|
+
'reply.denyButton': '⛔ 拒绝',
|
|
373
|
+
'reply.customDenyButton': '✍️ 自定义拒绝说明',
|
|
374
|
+
'reply.submitSelected': '提交所选项',
|
|
375
|
+
'reply.customInput': '✍️ 自定义输入',
|
|
376
|
+
'reply.closeRemote': '关闭远程答题(本机仍可操作)',
|
|
377
|
+
'reply.toolLabel': '工具:{tool}',
|
|
378
|
+
'reply.unknownTool': '未知',
|
|
379
|
+
'reply.permissionNote': '这里处理本次的允许、拒绝或自定义拒绝说明。Claude 没有提供完整的本地按钮列表,因此这里也不会创建永久权限规则。',
|
|
380
|
+
'reply.questionHeading': '问题 {index}/{total}:{question}',
|
|
381
|
+
'reply.multiSelectHint': '\n\n可多选,选好后点击「提交所选项」;也可自定义输入。',
|
|
382
|
+
'reply.singleSelectHint': '\n\n点击选项直接回答,或选择自定义输入。',
|
|
383
|
+
'reply.localWindowNote': '\n本机原生窗口也可以同时作答;Claude 先收到的完整答案生效。远程窗口有效期为 10 分钟,不会自动选择。',
|
|
384
|
+
'reply.feishuMultiSelectHint': '\n\n可多选:进入 Telegram 后逐项选择,再点击「提交所选项」;也可自定义输入。',
|
|
385
|
+
'reply.feishuSingleSelectHint': '\n\n进入 Telegram 后点击选项直接回答,或选择自定义输入。',
|
|
386
|
+
'reply.inactiveTitle': '⚠️ 交互已失效',
|
|
387
|
+
'reply.inactiveBody': '请从最新通知进入,或回到本机处理。',
|
|
388
|
+
'reply.noInteractionMessageId': '交互通知没有返回消息 ID。',
|
|
389
|
+
'reply.interactionNotSent': '交互通知没有完整发送,请回到本机处理。',
|
|
390
|
+
'reply.closedLocal': '已关闭远程答题,本机仍可正常处理。',
|
|
391
|
+
'reply.callbackExpired': '没有提交:按钮已失效,或已有答案等待确认。',
|
|
392
|
+
'reply.callbackClosed': '已关闭远程答题,本机不受影响。',
|
|
393
|
+
'reply.callbackRegistered': '答案已登记,尚未确认生效。',
|
|
394
|
+
'reply.callbackUpdated': '已更新。',
|
|
395
|
+
'reply.pendingConfirmationTitle': '⏳ 答案已登记,等待确认',
|
|
396
|
+
'reply.pendingRemaining': '仍需完成其余问题,之后才回传整份答案。',
|
|
397
|
+
'reply.pendingSubmitted': '已进入回传流程,Claude 是否采用会在稍后反馈。',
|
|
398
|
+
'reply.pendingFooter': '\n稍后会反馈结果;如果一直没有收到,请检查终端。\n请求:{id}',
|
|
399
|
+
'reply.notAppliedTitle': '⚠️ 本次提交未生效',
|
|
400
|
+
'reply.notAppliedBody': '这次操作没有提交:问题已处理、过期、题目已切换,或已有答案等待确认。\n请求:{id}',
|
|
401
|
+
'reply.denyInstruction': '请回复这条消息,填写拒绝说明。这段说明不会批准权限。',
|
|
402
|
+
'reply.answerInstruction': '请回复这条消息,输入这个问题的完整答案。',
|
|
403
|
+
'reply.answerInvalidTitle': '❌ 答案没有提交',
|
|
404
|
+
'reply.answerInvalidBody': '请输入不超过 4000 字符的答案;内容不会被截断。',
|
|
405
|
+
'reply.finalWaiting': '等待 Claude 确认,稍后会反馈最终结果;如果一直没有收到,请检查终端。',
|
|
406
|
+
'reply.nextWaiting': '仍需完成其余问题,之后才会回传整份答案;目前还没有生效。',
|
|
407
|
+
'reply.notSubmitted': '这次操作没有提交:对应问题已经结束、过期、切换,或已有答案等待确认。',
|
|
408
|
+
'reply.requestLine': '\n请求:{id}',
|
|
409
|
+
'reply.expiredUnsentAnswer': '远程答题已超时,没有提交任何答案;你仍可在本机继续处理。',
|
|
410
|
+
'reply.buttonUnknown': '已关闭 · 结果待核实',
|
|
411
|
+
'reply.buttonApplied': '已处理 · 不再接受答案',
|
|
412
|
+
'reply.buttonExpired': '已超时 · 未作答',
|
|
413
|
+
'reply.buttonInvalid': '已失效 · 未作答',
|
|
414
|
+
'reply.buttonClosed': '已关闭 · 不再接受答案',
|
|
415
|
+
'reply.buttonProcessed': '已处理 · 不再接受答案',
|
|
416
|
+
'reply.buttonEnded': '已结束 · 不再接受答案',
|
|
417
|
+
'reply.sessionUnknownSuffix': ';还没有收到本次答案的生效确认,请检查终端。',
|
|
418
|
+
'reply.sessionUnsentSuffix': ';这次远程答案没有回传。',
|
|
419
|
+
'reply.earlierHandled': '本机或其他端已经先处理了,这次 Telegram 答案没有提交。',
|
|
420
|
+
'reply.noVerifiableResult': 'Claude 已经结束了这个问题,但没有返回可核实的结果。请检查终端。',
|
|
421
|
+
'reply.answerApplied': 'Claude 已确认采用了与你提交内容一致的答案。如果本机也提交了相同内容,这次结果无法说明是哪一方生效。',
|
|
422
|
+
'reply.answerNotApplied': 'Claude 已经结束问题,但没有采用你提交的答案;本机或其他端可能已经先处理。',
|
|
423
|
+
'reply.questionProcessed': '问题已处理,旧按钮已失效。',
|
|
424
|
+
'reply.permissionApplied': '工具已获准并执行完成。如果本机同时也批准了,完成事件本身无法说明是哪一方放行。',
|
|
425
|
+
'reply.permissionNotApplied': '工具已经获准执行,这次远程决定没有阻止执行。',
|
|
426
|
+
'reply.toolFailedUnknown': '工具执行失败、被拒绝或取消。这个事件无法说明远程决定是否生效,请检查终端。',
|
|
427
|
+
'reply.toolFailed': '请求失败、被拒绝或取消,这次远程决定没有回传。',
|
|
428
|
+
'reply.waitTimeoutUnknown': '等待生效确认超时,或会话已经切换。结果暂时未知,请检查终端。',
|
|
429
|
+
'reply.sessionEndedUnsent': '会话已结束或已经切换;远程答案没有回传,你仍可在本机界面继续处理。',
|
|
430
|
+
'reply.expiredUnanswered': '远程答题已超时;没有提交任何答案,你仍可在本机界面继续处理。',
|
|
431
|
+
'reply.appliedTitle': '✅ 答案内容已生效',
|
|
432
|
+
'reply.resultUnknownTitle': '⚠️ 提交结果暂时无法确认',
|
|
433
|
+
'reply.requestLabel': '请求:{id}',
|
|
434
|
+
'reply.feedbackFailedLog': 'Telegram 结果反馈没有发送成功。不会自动重发,已经采用的答案不受影响。',
|
|
435
|
+
'reply.clearButtonsFailedLog': 'Telegram 旧按钮没有移除成功。服务端仍会拒绝这个请求。',
|
|
436
|
+
'reply.platformTimeout': '系统会话操作超时。输入可能已经部分送达,为避免重复提交,不会自动重试。',
|
|
437
|
+
'reply.platformFailed': '系统会话操作失败。为了避免泄露命令或输入,这里不显示底层信息。',
|
|
438
|
+
'reply.emptyReply': '回复内容不能为空。',
|
|
439
|
+
'reply.replyTooLong': '回复超过 4000 字符,没有提交。内容不会被截断,也不会拆成多次发送。',
|
|
440
|
+
'reply.emptyAfterCleanup': '回复清理后没有可提交的内容。',
|
|
441
|
+
'reply.targetInvalid': '会话已经关闭、切换,或无法核验身份。请从最新通知回复。',
|
|
442
|
+
'reply.windowsPartial': 'Windows 控制台注入失败,可能只写入了一部分。不会自动重试,请检查终端。',
|
|
443
|
+
'reply.unsupportedPlatform': '远程回复仅支持 Windows 和 macOS。',
|
|
444
|
+
'reply.tmuxBufferFailed': 'tmux 输入缓冲区创建失败,这次回复没有提交。',
|
|
445
|
+
'reply.tmuxChanged': '会话已经变化,这次回复没有提交。',
|
|
446
|
+
'reply.tmuxPasteFailed': 'tmux 粘贴失败,可能只送达了一部分。不会自动重试。',
|
|
447
|
+
'reply.tmuxSubmitFailed': 'tmux 提交失败,文本可能已经输入。不会自动重试。',
|
|
448
|
+
'reply.ghosttyFailed': 'Ghostty 没有找到目标窗口,或注入失败。不会改投其他窗口,也不会重复输入。',
|
|
449
|
+
'reply.telegramMethod': '不支持的 Telegram 桥接方法',
|
|
450
|
+
'reply.telegramConflict': 'Telegram 轮询冲突;检查旧版桥接、其他机器或 webhook,桥接不会抢占或删除 webhook',
|
|
451
|
+
'reply.telegramRequestFailed': 'Telegram 桥接请求失败;不输出服务端正文或秘密',
|
|
452
|
+
'reply.bridgeAuthFirst': '远程回复尚未授权,请先运行 reply setup。',
|
|
453
|
+
'reply.bridgeNotAuthorized': '远程回复尚未授权。',
|
|
454
|
+
'reply.bridgeLocked': '当前用户已经有同一个 Bot 的桥接在运行,或残留了锁文件。请确认进程退出后,再处理 reply-bots 中对应的锁。',
|
|
455
|
+
'reply.webhookConflict': '这个 Bot 已经设置了 webhook,不能同时使用 getUpdates。请先移除 webhook;本工具不会自动删除。',
|
|
456
|
+
'reply.pollFailedLog': 'Telegram 轮询失败;日志中没有记录密钥或服务端正文。',
|
|
457
|
+
'reply.pollFailedFatal': 'Telegram 连续轮询失败 5 次,桥接已经退出。请检查网络、Token 或 API 冲突后重新启动。',
|
|
458
|
+
'reply.updatesInvalid': 'Telegram 更新格式无效。',
|
|
459
|
+
'reply.handleFailedLog': '回复处理失败。这条更新不会重放;请检查终端,或从最新通知重试。',
|
|
460
|
+
'reply.bridgeFailed': '桥接启动或运行失败;为避免泄露密钥,没有显示底层错误。',
|
|
461
|
+
'channels.telegramReplyButton': '💬 回复 Claude',
|
|
462
|
+
};
|
|
463
|
+
const en = {
|
|
464
|
+
'common.cancelled': 'Cancelled.',
|
|
465
|
+
'common.failure': 'The operation failed. Check files, permissions, or input; to avoid leaking secrets, the underlying exception is not shown.',
|
|
466
|
+
'config.homeAbsolute': 'DEV_NOTIFY_HOME must be an absolute path.',
|
|
467
|
+
'config.rootName': 'configuration',
|
|
468
|
+
'config.objectRequired': '{name} must be a JSON object.',
|
|
469
|
+
'config.objectUnknown': '{name} contains unsupported fields; plaintext secrets cannot be stored directly.',
|
|
470
|
+
'config.enabledBoolean': 'enabled must be a boolean.',
|
|
471
|
+
'config.credentialEnvName': 'The credential reference must be a valid environment variable name.',
|
|
472
|
+
'config.unsupportedVersion': 'This configuration version is not supported.',
|
|
473
|
+
'config.invalidLanguage': 'language must be zh or en.',
|
|
474
|
+
'config.invalidReference': 'The system credential reference is invalid.',
|
|
475
|
+
'config.chatIdsArray': 'telegram.chat_ids must be an array.',
|
|
476
|
+
'config.chatIdNumeric': 'Recipients must use numeric chat_id values; write large integers as strings.',
|
|
477
|
+
'config.chatIdNonZero': 'Recipients must use non-zero numeric chat_id values.',
|
|
478
|
+
'config.telegramToken': 'The Telegram token format is invalid.',
|
|
479
|
+
'config.feishuWebhook': 'The Feishu webhook must be an HTTPS custom bot URL on open.feishu.cn.',
|
|
480
|
+
'config.utf8': 'Input must be valid UTF-8 text.',
|
|
481
|
+
'config.unreadable': 'The configuration file is missing, unreadable, or not valid UTF-8 JSON.',
|
|
482
|
+
'config.exists': 'Configuration already exists and was not overwritten. The Node version will not modify old-prototype configuration.',
|
|
483
|
+
'config.createFailed': 'Could not create the configuration. Check the path and permissions.',
|
|
484
|
+
'config.languageNoConfig': 'The configuration file does not exist, so the language setting cannot be saved: {file}. Run setup --lang {language} first to create a configuration.',
|
|
485
|
+
'credentials.invalidReference': 'The system credential reference is invalid.',
|
|
486
|
+
'credentials.invalidBundle': 'The system credential data is invalid. Re-run setup.',
|
|
487
|
+
'credentials.tooLong': 'The credential bundle exceeds 2400 bytes. Check the input; nothing was saved.',
|
|
488
|
+
'credentials.readFailed': 'Could not read the system credential, or its contents are invalid. Unlock the system credential store and allow access, or re-run setup.',
|
|
489
|
+
'credentials.exists': 'This random credential reference already exists and was not overwritten. Try again.',
|
|
490
|
+
'credentials.accessFailed': 'Could not access the system credential store. Check system permissions.',
|
|
491
|
+
'credentials.writeUnknown': 'The credential write state is unknown, and cleanup also failed. Check reference ID: {id}',
|
|
492
|
+
'credentials.writeFailed': 'Writing the system credential failed; the configuration was not switched.',
|
|
493
|
+
'credentials.deleteFailed': 'Deleting the system credential failed. Check storage permissions.',
|
|
494
|
+
'credentials.platform': 'System credentials are supported only on Windows and macOS; use environment variables on other platforms.',
|
|
495
|
+
'credentials.nativeLoad': 'The native credential component could not be loaded. Confirm that the npm install kept optional dependencies and that the architecture matches; it will not fall back to plaintext storage.',
|
|
496
|
+
'credentials.oldReference': 'This credential reference was saved by the old prototype. Re-enter it with setup and save it as a Node credential, or provide environment variables explicitly; old credentials are never read or deleted automatically.',
|
|
497
|
+
'credentials.missingEntry': 'The system credential entry is missing. Run setup to configure it again.',
|
|
498
|
+
'prompts.terminalRequired': 'The configuration wizard must run in an interactive terminal. For automation, use setup --template --yes with environment variables.',
|
|
499
|
+
'prompts.hiddenUnsupported': 'This terminal does not support hidden input. To avoid exposing secrets, it will not fall back to plaintext input; run in a supported terminal or configure with environment variables.',
|
|
500
|
+
'prompts.hiddenIncomplete': 'Hidden input did not complete; credentials were not saved.',
|
|
501
|
+
'prompts.cancelled': 'Cancelled.',
|
|
502
|
+
'prompts.inputTooLong': 'The credential input is too long; nothing was saved.',
|
|
503
|
+
'channels.emptyTitle': 'The notification title cannot be empty.',
|
|
504
|
+
'channels.telegramTooLong': 'A Telegram segment still exceeds the message length limit.',
|
|
505
|
+
'channels.feishuTooLong': 'A Feishu segment still exceeds the request size limit.',
|
|
506
|
+
'channels.noResponse': 'The server returned no content.',
|
|
507
|
+
'channels.responseTooLarge': 'The server response is too large; reading stopped.',
|
|
508
|
+
'channels.notJsonObject': 'The server did not return a JSON object.',
|
|
509
|
+
'channels.network': 'The network request failed or the response was invalid. To avoid duplicate notifications, it will not resend automatically; this message may not have been delivered.',
|
|
510
|
+
'channels.rejected': 'The channel rejected this send. Check credentials, recipient authorization, signing, and rate limits.',
|
|
511
|
+
'channels.sendFailed': 'Sending failed; this message may not have been delivered.',
|
|
512
|
+
'channels.feishuReplyButton': '💬 Reply to Claude on Telegram',
|
|
513
|
+
'format.noSpace': 'There is not enough space to split the content.',
|
|
514
|
+
'format.oneChar': 'There is not enough space for even one character.',
|
|
515
|
+
'format.telegramHeader': 'The Telegram title or footer is too long, leaving no room for the body.',
|
|
516
|
+
'format.feishuHeader': 'The Feishu title or footer is too long, leaving no room for the body.',
|
|
517
|
+
'setup.readFailed': 'Could not read the existing configuration; nothing was changed this time.',
|
|
518
|
+
'setup.parseFailed': 'The existing configuration could not be parsed and was not overwritten. Fix the JSON first.',
|
|
519
|
+
'setup.lockUnavailable': 'The configuration write lock is unavailable. Check permissions; if you confirm no wizard is running, you may delete a leftover .setup.lock.',
|
|
520
|
+
'setup.changedDuringWizard': 'The configuration changed during the wizard and was not overwritten. Try again.',
|
|
521
|
+
'setup.credentialVerifyFailed': 'Credential verification failed after writing; the configuration was not switched.',
|
|
522
|
+
'setup.changedDuringSave': 'The configuration changed while saving and was not overwritten. Try again.',
|
|
523
|
+
'setup.tempCleanupFailed': 'Temporary configuration was not cleaned up: {name}',
|
|
524
|
+
'setup.credentialCleanupFailed': 'The configuration was not switched, and the new credential could not be cleaned up. Reference ID: {id}',
|
|
525
|
+
'setup.lockCleanupFailed': 'The configuration write lock was not cleaned up. Confirm no wizard is running, then delete .setup.lock.',
|
|
526
|
+
'setup.oldCredentialCleanupFailed': 'The configuration was saved, but the old credential was not cleaned up. Reference ID: {id}',
|
|
527
|
+
'setup.oldSystemRetained': 'The old prototype credential is retained and continues to be managed by the old tool, so the two implementations do not delete each other\'s data.',
|
|
528
|
+
'setup.path': 'Config path: {file}',
|
|
529
|
+
'setup.secretsNote': 'Token, webhook, and signing secret are never echoed. They are stored in Windows Credential Manager / macOS Keychain; the configuration file keeps only references.',
|
|
530
|
+
'setup.channelPrompt': 'Choose notification channels: 1 Telegram, 2 Feishu, 3 both{current} (enter anything else to cancel): ',
|
|
531
|
+
'setup.credentialUnreadable': 'The current credential cannot be read right now. The entry may be missing, the credential store may be locked, or permissions may be insufficient.',
|
|
532
|
+
'setup.reenterPrompt': 'Re-enter credentials for the selected channels? [y/N] ',
|
|
533
|
+
'setup.oldSystemDetected': 'Credentials saved by the old prototype were detected. This run re-enters and saves them as Node credentials; the old credentials remain unchanged.',
|
|
534
|
+
'setup.secretRequiredKeep': '{label} (hidden input, not echoed; leave blank to keep the current value): ',
|
|
535
|
+
'setup.secretRequiredNew': '{label} (hidden input, not echoed; not filled from environment variables): ',
|
|
536
|
+
'setup.secretOptionalKeep': '{label} (hidden input, not echoed; optional; leave blank to keep the current value; enter - to clear): ',
|
|
537
|
+
'setup.secretOptionalNew': '{label} (hidden input, not echoed; optional; not filled from environment variables; enter - to clear): ',
|
|
538
|
+
'setup.requiredBlank': 'This field cannot be empty. Enter it again; press Ctrl+C to exit.',
|
|
539
|
+
'setup.invalidFormat': 'The format is invalid. Enter it again (input is not displayed).',
|
|
540
|
+
'setup.telegramChatInstruction': 'Have the recipient send the bot a message first, then enter the numeric chat_id; recipients are not fetched or paired automatically here.',
|
|
541
|
+
'setup.telegramChatPrompt': 'Recipient chat_id, separated by commas (leave blank to keep the current list): ',
|
|
542
|
+
'setup.telegramChatInvalid': 'Enter at least one valid numeric chat_id; press Ctrl+C to exit.',
|
|
543
|
+
'setup.channelsEnabled': 'Will enable: {channels}',
|
|
544
|
+
'setup.envPriority': 'Environment variables take precedence, and empty values also override these settings; the test notification uses the effective configuration.',
|
|
545
|
+
'setup.envOverrides': 'These environment variables are overriding configuration: {names}',
|
|
546
|
+
'setup.oldDeleteWarning': 'After a successful save, the old credential will be deleted; if other configurations reference the same credential, update them too.',
|
|
547
|
+
'setup.disabledChannels': 'Channels that are not selected will be disabled; new credentials are used only for the channels selected this time.',
|
|
548
|
+
'setup.actionSave': 'save configuration and system credentials',
|
|
549
|
+
'setup.actionTest': 'send a fixed-content test notification',
|
|
550
|
+
'setup.actionHooks': 'install Claude Code notification hooks',
|
|
551
|
+
'setup.continue': 'This will {actions}. Continue? [Y/n] ',
|
|
552
|
+
'setup.saved': 'Configuration and system credentials saved.',
|
|
553
|
+
'setup.testSuccess': 'Test notification sent successfully.',
|
|
554
|
+
'setup.testFailed': 'Configuration saved. The test notification was not sent successfully; run dev-notify doctor to check.',
|
|
555
|
+
'setup.testFailedEnv': 'Configuration saved. The test notification was not sent successfully, possibly due to environment overrides or a network problem; run dev-notify doctor to check.',
|
|
556
|
+
'setup.testSkipped': 'Test notification skipped.',
|
|
557
|
+
'setup.hooksFailed': 'Configuration saved. Claude Code hooks were not fully installed: {reason}',
|
|
558
|
+
'setup.hooksCheckHint': 'run integration claude-code status to check',
|
|
559
|
+
'setup.replyHint': 'To reply to Claude in Telegram, run: dev-notify reply setup',
|
|
560
|
+
'setup.clearNoReference': 'The current configuration has no system credential reference; nothing to clear.',
|
|
561
|
+
'setup.clearOldBackend': 'This credential was saved by the old prototype; the Node version will not delete across implementations. Use the old tool to handle it.',
|
|
562
|
+
'setup.clearWarning': 'This will delete the system credential referenced by the current configuration and remove the reference. Environment variables are unaffected; other configurations sharing the same credential will also stop working.',
|
|
563
|
+
'setup.clearConfirm': 'Clear it? [y/N] ',
|
|
564
|
+
'setup.cleared': 'Credential reference removed. If deleting the system entry failed, a notice is shown above.',
|
|
565
|
+
'setup.channelTelegram': 'Telegram ({count} recipients)',
|
|
566
|
+
'setup.channelFeishu': 'Feishu',
|
|
567
|
+
'setup.labelFeishuWebhook': 'Feishu webhook',
|
|
568
|
+
'setup.labelFeishuSecret': 'Feishu signing secret',
|
|
569
|
+
'cli.help': `dev-notify {version} — cross-platform developer task notifications
|
|
570
|
+
|
|
571
|
+
Commands:
|
|
572
|
+
send --title TITLE [--content TEXT | --content-file FILE | --stdin]
|
|
573
|
+
[--channel all|telegram|feishu] [--level info|success|warn|error]
|
|
574
|
+
[--footer NOTE] [--dry-run]
|
|
575
|
+
setup [--no-test] [--no-hooks]
|
|
576
|
+
Configure channels and system credentials; by default
|
|
577
|
+
also sends a test and installs Claude Code notification
|
|
578
|
+
hooks after one confirmation
|
|
579
|
+
setup --template [--yes] Create a secret-free template only; does not overwrite
|
|
580
|
+
existing configuration or install hooks
|
|
581
|
+
credentials clear Remove the current Node credential reference and entry
|
|
582
|
+
(requires confirmation)
|
|
583
|
+
paths Show configuration paths (does not write files)
|
|
584
|
+
doctor / status Offline check (does not send messages)
|
|
585
|
+
update [--check] [--yes] [--no-post]
|
|
586
|
+
Check for and install the latest npm version, then
|
|
587
|
+
maintain hooks and the bridge
|
|
588
|
+
integration list List available integrations
|
|
589
|
+
integration claude-code install / status / remove
|
|
590
|
+
Install, query, or remove user-level hooks separately
|
|
591
|
+
(install/remove accept --yes)
|
|
592
|
+
reply setup Authorize trusted Telegram private-chat users
|
|
593
|
+
reply start / status / stop
|
|
594
|
+
Start, query, or stop the reply bridge
|
|
595
|
+
reply disable Revoke remote reply authorization and stop the bridge
|
|
596
|
+
(requires confirmation)
|
|
597
|
+
reply run Run the bridge in the foreground (for diagnostics,
|
|
598
|
+
no system auto-start)
|
|
599
|
+
language [zh|en] Show or change the saved interface language
|
|
600
|
+
|
|
601
|
+
Global options: --config PATH, --lang zh|en, --help, --version
|
|
602
|
+
Environment: TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID / TELEGRAM_CHAT_IDS,
|
|
603
|
+
FEISHU_WEBHOOK, FEISHU_SECRET; explicitly present values take
|
|
604
|
+
precedence. DEV_NOTIFY_LANG=zh|en switches the interface language.
|
|
605
|
+
See README for details.
|
|
606
|
+
System credentials are stored in Windows Credential Manager / macOS Keychain;
|
|
607
|
+
secrets are never written in plaintext.`,
|
|
608
|
+
'cli.invalidArgs': 'Invalid arguments. Run --help for usage.',
|
|
609
|
+
'cli.invalidCommand': 'The command or option combination is invalid. Run --help for usage.',
|
|
610
|
+
'cli.invalidLanguage': 'The language must be zh or en: {value}',
|
|
611
|
+
'cli.integrationList': 'claude-code: supports notifications, Telegram replies, and structured question interaction. Notification hooks and reply permission are separate; by default only notifications are sent and no remote input is accepted.',
|
|
612
|
+
'cli.integrationUsage': 'Use integration list, or integration claude-code install / status / remove.',
|
|
613
|
+
'cli.integrationStatusFile': 'Claude Code user-level settings: {file}',
|
|
614
|
+
'cli.integrationStatusCounts': 'dev-notify hooks: Stop {stop}, Notification {notification}, session lifecycle {lifecycle}/3, interaction and result confirmation {interaction}/5; other handlers {others}.',
|
|
615
|
+
'cli.integrationDisabled': 'This file enables disableAllHooks, so hooks will not take effect after installation; lift the disablement yourself.',
|
|
616
|
+
'cli.integrationStatusNote': 'Only the user-level file is checked here. Actual loading also depends on project and managed policy; confirm in Claude Code /hooks.',
|
|
617
|
+
'cli.setupChannelFirst': 'Run setup to configure at least one notification channel before installing Claude Code hooks.',
|
|
618
|
+
'cli.replyUsage': 'Use reply setup / start / status / stop / disable / run.',
|
|
619
|
+
'cli.credentialsUsage': 'credentials currently supports only clear, and requires confirmation in an interactive terminal.',
|
|
620
|
+
'cli.yesTemplateOnly': '--yes can only be used with --template; confirmation is still required before saving secrets.',
|
|
621
|
+
'cli.sendTitle': 'send requires a non-empty --title.',
|
|
622
|
+
'cli.sendSources': 'Choose only one of --content, --content-file, and --stdin.',
|
|
623
|
+
'cli.channelLevel': 'The channel or notification level is invalid.',
|
|
624
|
+
'cli.segmentationFailed': '{channel}: could not split safely. Shorten the title or footer, or check the body format.',
|
|
625
|
+
'cli.dryRun': '{channel}: recipients {recipients}, planned requests {items} (dry-run, nothing sent)',
|
|
626
|
+
'cli.sent': '{channel}: sent {sent}/{planned} messages',
|
|
627
|
+
'cli.testSent': '{channel}: test sent {sent}/{planned} messages',
|
|
628
|
+
'cli.noChannels': 'No usable channel. Configure environment credentials and recipients first.',
|
|
629
|
+
'cli.channelNotReady': 'This channel is not enabled or its configuration is incomplete.',
|
|
630
|
+
'cli.testTitle': 'dev-notify configuration test',
|
|
631
|
+
'cli.testContent': 'This is a test notification you confirmed sending.',
|
|
632
|
+
'cli.setupNoteTest': 'After saving, a fixed-content test notification will be sent to the effective recipients.',
|
|
633
|
+
'cli.setupNoteHooksPath': 'Claude Code user-level settings: {path}',
|
|
634
|
+
'cli.setupNoteHooksScope': 'Notification hooks will be installed for all projects using this settings file. Final reply text may contain sensitive content and will be sent to the channels in effect.',
|
|
635
|
+
'cli.setupNoteHooksLifecycle': 'Session lifecycle and structured question hooks are installed at the same time. Remote input is enabled only after running reply setup to authorize it.',
|
|
636
|
+
'cli.skipHooks': 'Skipping Claude Code hooks: {reason}',
|
|
637
|
+
'cli.skipHooksNoPath': 'Skipping Claude Code hooks: no user-level settings path was found.',
|
|
638
|
+
'cli.templateWillCreate': 'Will create a secret-free template: {file}. It will not use the network or modify hooks.',
|
|
639
|
+
'cli.templateCancelled': 'Cancelled; nothing was written.',
|
|
640
|
+
'cli.templateCreated': 'Template created. Configure environment credentials and recipients.',
|
|
641
|
+
'cli.configPath': 'Config path: {file}',
|
|
642
|
+
'cli.channelReady': 'configuration complete (network not verified)',
|
|
643
|
+
'cli.channelNotReadyStatus': 'not enabled or configuration incomplete',
|
|
644
|
+
'cli.channelStatus': '{channel}: {status}',
|
|
645
|
+
'cli.credentialsNote': 'Credentials: environment variables take precedence, then system credentials; this check does not use the network, and the system may prompt for authorization.',
|
|
646
|
+
'cli.confirmTemplate': 'Create the template? [y/N] ',
|
|
647
|
+
'cli.nonInteractive': 'This is not an interactive terminal. For automation, use setup --template --yes.',
|
|
648
|
+
'cli.replySaved': 'Authorization saved. Confirm hooks are installed, then run reply start. Reply mappings for old messages are not retained.',
|
|
649
|
+
'cli.bridgeStopped': 'The bridge is stopped or was not running.',
|
|
650
|
+
'cli.replyDisabled': 'Authorization revoked and stop requested. Calls already in progress cannot be withdrawn.',
|
|
651
|
+
'cli.stopStopped': 'The bridge is stopped or was not running. Authorization remains, and a later event may start it again; to shut it down completely, run reply disable.',
|
|
652
|
+
'cli.stopRequested': 'Stop requested; the bridge is exiting. Run reply status to check.',
|
|
653
|
+
'cli.replyStatusAccess': 'Remote replies: {users} authorized private-chat users; per-request tool permission {state}.',
|
|
654
|
+
'cli.replyPermissionOn': 'enabled',
|
|
655
|
+
'cli.replyPermissionOff': 'not enabled',
|
|
656
|
+
'cli.replyStatusNoAccess': 'Remote replies: not enabled.',
|
|
657
|
+
'cli.bridgeReady': 'Bridge: ready.',
|
|
658
|
+
'cli.bridgeStarting': 'Bridge: process exists but is not ready yet.',
|
|
659
|
+
'cli.bridgeNotRunning': 'Bridge: not running.',
|
|
660
|
+
'cli.replyStartReady': 'Reply bridge ready. Enter from a new task notification.',
|
|
661
|
+
'cli.replyStartNotReady': 'The bridge is not ready yet. Run reply status or reply run to see why; if an old bridge is running, stop it first.',
|
|
662
|
+
'cli.languageCurrent': 'Current language: {language} ({code}).',
|
|
663
|
+
'cli.languageChanged': 'Language changed to {language} ({code}).',
|
|
664
|
+
'cli.languageAlready': 'Already using {language} ({code}).',
|
|
665
|
+
'cli.languageHint': 'Use language zh or language en to switch and save.',
|
|
666
|
+
'update.npmUnavailable': 'Could not run npm. Confirm npm is installed and on PATH.',
|
|
667
|
+
'update.checkNetwork': 'Could not check the latest version. Check the network and try again.',
|
|
668
|
+
'update.checkHttp': 'Could not check the latest version (HTTP {status}). Check the network and try again.',
|
|
669
|
+
'update.parseRegistry': 'The version information returned by the npm registry could not be parsed.',
|
|
670
|
+
'update.registryVersion': 'The npm registry returned an unsupported version format.',
|
|
671
|
+
'update.versionFormat': 'The version format is not supported.',
|
|
672
|
+
'update.terminalRequired': 'Updates must be confirmed in an interactive terminal; for non-interactive use, run dev-notify update --yes.',
|
|
673
|
+
'update.confirm': 'Update to {latest}? [y/N] ',
|
|
674
|
+
'update.manualPost': 'If Claude Code hooks are installed, run dev-notify integration claude-code install; if remote replies are in use, restart the bridge.',
|
|
675
|
+
'update.partialUpdated': 'The update completed, but not all post-update maintenance steps succeeded; check the notices above.',
|
|
676
|
+
'update.partial': 'Not all maintenance steps succeeded; check the notices above.',
|
|
677
|
+
'update.postDoneUpdated': 'Post-update maintenance completed.',
|
|
678
|
+
'update.postDone': 'Maintenance completed.',
|
|
679
|
+
'update.currentFormat': 'The current version format is not supported, so updates cannot be checked.',
|
|
680
|
+
'update.upToDate': 'Already up to date: {version}.',
|
|
681
|
+
'update.maintenanceNote': 'Claude Code hooks and reply bridge maintenance will run.',
|
|
682
|
+
'update.versions': 'Current version {current}; latest npm version {latest}.',
|
|
683
|
+
'update.checkHint': 'Run dev-notify update to update.',
|
|
684
|
+
'update.postNote': 'After updating, Claude Code hooks bound to the current configuration will be reinstalled and a running reply bridge restarted; use --no-post to skip.',
|
|
685
|
+
'update.cancelled': 'Cancelled; no update was performed.',
|
|
686
|
+
'update.running': 'Running npm install -g {name}@{latest} ...',
|
|
687
|
+
'update.failed': 'The update did not complete. Check npm permissions, or run npm install -g {name}@latest manually.',
|
|
688
|
+
'update.updated': 'Updated to {latest}. Reopen the terminal and run dev-notify --version to confirm.',
|
|
689
|
+
'maintenance.runFailed': 'Could not run the updated dev-notify. Reopen the terminal and run dev-notify --version to check.',
|
|
690
|
+
'maintenance.reasonHint': 'Run dev-notify integration claude-code status or dev-notify reply status to check.',
|
|
691
|
+
'maintenance.hooksCheckFailed': 'Could not check Claude Code hooks: {reason}',
|
|
692
|
+
'maintenance.noHooks': 'No dev-notify Claude Code hooks detected; skipping.',
|
|
693
|
+
'maintenance.otherConfig': 'Claude Code hooks are bound to another notification configuration; skipping automatic update. To update them, run integration claude-code install with the original --config.',
|
|
694
|
+
'maintenance.updatingHooks': 'Updating Claude Code hooks ...',
|
|
695
|
+
'maintenance.hooksUpdated': 'Claude Code hooks updated.',
|
|
696
|
+
'maintenance.hooksFailed': 'Claude Code hooks update failed.',
|
|
697
|
+
'maintenance.hooksFailedReason': 'Claude Code hooks update failed: {reason}',
|
|
698
|
+
'maintenance.bridgeCheckFailed': 'Could not check the reply bridge: {reason}',
|
|
699
|
+
'maintenance.restartingBridge': 'Restarting the reply bridge ...',
|
|
700
|
+
'maintenance.bridgeStillRunning': 'The reply bridge is still exiting; run dev-notify reply start later.',
|
|
701
|
+
'maintenance.bridgeRestarted': 'Reply bridge restarted.',
|
|
702
|
+
'maintenance.bridgeStartFailed': 'The reply bridge failed to start.',
|
|
703
|
+
'maintenance.bridgeRestartFailed': 'The reply bridge failed to restart: {reason}',
|
|
704
|
+
'maintenance.noBridge': 'No running reply bridge detected; skipping.',
|
|
705
|
+
'claude.settingsAbsolute': 'CLAUDE_CONFIG_DIR must be an absolute path; Claude Code settings were not changed',
|
|
706
|
+
'claude.settingsTooLarge': 'Claude Code settings exceed 1 MiB; the operation stopped and the file was not changed.',
|
|
707
|
+
'claude.settingsReadFailed': 'Could not read Claude Code settings; the operation stopped.',
|
|
708
|
+
'claude.settingsInvalidJson': 'Claude Code settings are not valid UTF-8 JSON and were not overwritten.',
|
|
709
|
+
'claude.settingsInvalidShape': 'Claude Code settings or hooks structure is invalid and was not overwritten.',
|
|
710
|
+
'claude.hooksInvalidShape': 'The Claude Code hook array structure is invalid and was not overwritten.',
|
|
711
|
+
'claude.lockUnavailable': 'Could not acquire the Claude Code settings write lock. Confirm no installation process is running, then handle a leftover .dev-notify.lock.',
|
|
712
|
+
'claude.changedDuringConfirm': 'Claude Code settings changed during confirmation and were not overwritten. Try again.',
|
|
713
|
+
'claude.changedDuringSave': 'Claude Code settings changed while saving and were not overwritten. Try again.',
|
|
714
|
+
'claude.tempCleanupFailed': 'Temporary file cleanup failed. Delete .dev-notify-*.tmp after installation.',
|
|
715
|
+
'claude.lockCleanupFailed': 'Lock file cleanup failed. Delete .dev-notify.lock after installation.',
|
|
716
|
+
'claude.settingsPath': 'Claude Code user-level settings: {file}',
|
|
717
|
+
'claude.noHooks': 'No hooks added by this tool were found; settings were not changed.',
|
|
718
|
+
'claude.alreadyInstalled': 'This tool\'s hooks are already installed and match the configuration; nothing was added.',
|
|
719
|
+
'claude.configPath': 'Notification configuration: {config}',
|
|
720
|
+
'claude.installScope': 'Notifications will be enabled for all projects under this Claude Code configuration directory: the final reply is sent when a task ends, and reminders appear when your confirmation or input is needed.',
|
|
721
|
+
'claude.installSensitive': 'Final replies and reminder text may contain sensitive content and will be sent to the effective Telegram / Feishu channels. Environment variables still take precedence.',
|
|
722
|
+
'claude.installLifecycle': 'Session lifecycle and structured question hooks are installed at the same time. Remote input requires separate authorization with reply setup.',
|
|
723
|
+
'claude.installReads': 'The full transcript is not read. After replies are enabled, session process metadata is read; structured questions or permission requests send the corresponding question and tool information.',
|
|
724
|
+
'claude.installTiming': 'PreToolUse only registers call identity; PermissionRequest waits in parallel with the local terminal window, and remote answers are valid for 10 minutes. Completion events are used only for result feedback and never answer on your behalf. Checked against Claude Code 2.1.316; other versions or host environments require separate verification.',
|
|
725
|
+
'claude.otherHandlers': 'This file contains {count} other related handlers, which may cause duplicate notifications.',
|
|
726
|
+
'claude.projectHooks': 'Project-level or plugin hooks may also be active; this tool will not automatically migrate or delete old hooks.',
|
|
727
|
+
'claude.disabledWarning': 'Note: this file enables disableAllHooks, so hooks will not take effect after installation; lift the disablement yourself.',
|
|
728
|
+
'claude.removeScope': 'Only notification, lifecycle, and interaction handlers added by this tool are removed; other settings, hooks, notification configuration, and system credentials are preserved. To stop the reply bridge, run reply disable or reply stop.',
|
|
729
|
+
'claude.confirmInstall': 'Install these Claude Code hooks? [y/N] ',
|
|
730
|
+
'claude.confirmRemove': 'Remove this tool\'s Claude Code hooks? [y/N] ',
|
|
731
|
+
'claude.cancelled': 'Cancelled; Claude Code settings were not changed.',
|
|
732
|
+
'claude.installed': 'Claude Code hooks installed. Check and confirm them in /hooks; if they do not take effect, restart the session.',
|
|
733
|
+
'claude.removed': 'This tool\'s Claude Code hooks were removed. Check /hooks and restart the session if necessary.',
|
|
734
|
+
'hook.timeout': 'Claude Code hook input timed out; the notification was not sent.',
|
|
735
|
+
'hook.tooLarge': 'Claude Code hook input exceeds the size limit; the notification was not sent and the content was not truncated.',
|
|
736
|
+
'hook.footerProject': 'Project: {value}',
|
|
737
|
+
'hook.footerTopic': 'Topic: {value}',
|
|
738
|
+
'hook.footerSession': 'Session: {value}',
|
|
739
|
+
'hook.invalidJson': 'Claude Code hook input is not valid UTF-8 JSON; the notification was not sent.',
|
|
740
|
+
'hook.notObject': 'Claude Code hook input must be a JSON object.',
|
|
741
|
+
'hook.invalidStopState': 'The Claude Code Stop state field is invalid.',
|
|
742
|
+
'hook.invalidReply': 'The Claude Code final reply field is invalid.',
|
|
743
|
+
'hook.replyTitle': 'Claude Code reply complete',
|
|
744
|
+
'hook.replyFallback': 'This turn has ended, but Claude Code did not provide final text. Return to the terminal; the session file is not read to fill in the body, to avoid showing stale content.',
|
|
745
|
+
'hook.invalidNotification': 'The Claude Code notification body field is invalid.',
|
|
746
|
+
'hook.notificationTitle': 'Claude Code needs your input',
|
|
747
|
+
'hook.notificationFallback': 'Claude Code is waiting for your confirmation or input. Return to the terminal to handle it.',
|
|
748
|
+
'hook.interactionFailed': 'Claude Code reply state or interaction handling failed. No answer or permission was selected automatically; handle it locally.',
|
|
749
|
+
'hook.sessionNameFailed': 'Could not read the Claude Code session name; the topic will be omitted from the notification footer.',
|
|
750
|
+
'hook.replyNotReady': 'Remote replies are not ready yet; a normal notification will still be attempted.',
|
|
751
|
+
'hook.coverageFailed': 'Could not verify question-notification coverage; the general permission reminder will be kept.',
|
|
752
|
+
'hook.sendIncomplete': '{channel}: the Claude Code notification was not fully sent. The message will not be resent automatically.',
|
|
753
|
+
'hook.sendFailed': '{channel}: the Claude Code notification failed to send. Check configuration, system credentials, and network; the message will not be resent automatically.',
|
|
754
|
+
'hook.noChannels': 'No usable channel for Claude Code notifications. Run dev-notify doctor to check.',
|
|
755
|
+
'reply.readFailed': 'Could not read reply configuration or state. To avoid overwriting existing data, remote input was not enabled.',
|
|
756
|
+
'reply.lockUnavailable': 'Could not acquire the reply state write lock.',
|
|
757
|
+
'reply.lockBusy': 'The reply state lock is busy. Confirm the relevant processes have exited, then handle the leftover lock.',
|
|
758
|
+
'reply.invalidPolicy': 'The reply authorization configuration is invalid; remote input is disabled.',
|
|
759
|
+
'reply.hooksMissing': 'Required reply hooks are missing, timed unsafely, or disabled. Re-run integration claude-code install and confirm loading in /hooks.',
|
|
760
|
+
'reply.botChanged': 'The Telegram bot changed or is unavailable. Re-run reply setup to authorize again.',
|
|
761
|
+
'reply.usersRevoked': 'Authorized users are no longer in the current Telegram recipient list; remote input is disabled.',
|
|
762
|
+
'reply.authorizationChanged': 'Reply authorization was revoked or changed; old state was not written.',
|
|
763
|
+
'reply.invalidState': 'The reply state structure is invalid; remote input is disabled.',
|
|
764
|
+
'reply.setupHooksFirst': 'Run integration claude-code install first to install the complete hooks bound to this notification configuration, then configure replies.',
|
|
765
|
+
'reply.setupTelegramFirst': 'Replying to Claude requires a configured Telegram bot and private-chat recipients.',
|
|
766
|
+
'reply.setupPrivateOnly': 'Remote replies support only Telegram private-chat users, not group chats.',
|
|
767
|
+
'reply.setupNoticeInput': 'Remote replies are equivalent to typing and submitting content in the local Claude Code terminal. They can submit Claude commands but never approve tool permissions automatically. Authorize only trusted users.',
|
|
768
|
+
'reply.setupNoticeBridge': 'Feishu buttons jump to Telegram and do not receive Feishu messages directly. This feature needs exclusive getUpdates access to the bot; do not share the same bot with an old bridge or other machines.',
|
|
769
|
+
'reply.setupNoticePlatform': 'Windows uses the system PowerShell / console API; macOS uses Ghostty or tmux and requires the corresponding system permissions.',
|
|
770
|
+
'reply.setupNoticeUnsupported': 'VS Code integrated terminal, WSL, and SSH are not supported. Input is refused when the target is uncertain or the session has switched.',
|
|
771
|
+
'reply.setupAvailable': 'Notification recipients do not automatically gain input rights. Available private-chat chat_id values: {users}',
|
|
772
|
+
'reply.setupPrompt': 'Enter the private-chat chat_id to authorize (comma-separated; leave blank to cancel): ',
|
|
773
|
+
'reply.setupInvalidUser': 'You can authorize only private-chat users in the current notification list.',
|
|
774
|
+
'reply.setupAuthorizing': 'Remote input will be authorized for: {users}',
|
|
775
|
+
'reply.setupSensitive': 'Structured questions show the real options and support custom answers; normal replies are entered after the current turn ends. Questions, options, and tool request parameters may contain sensitive information and will be sent to authorized private chats and configured Feishu.',
|
|
776
|
+
'reply.setupPermissionsPrompt': 'Allow these users to approve or deny tool permissions one request at a time? This does not modify permanent rules. [y/N] ',
|
|
777
|
+
'reply.setupConfirm': 'Enable remote replies and accept the permission scope above? [y/N] ',
|
|
778
|
+
'reply.setupChanged': 'Reply authorization was modified by another process. Try again.',
|
|
779
|
+
'reply.setupConfigChanged': 'The notification configuration changed during authorization. Try again.',
|
|
780
|
+
'reply.setupSaved': 'Authorization saved. Reply mappings for old messages are not retained; enter from task-completion notifications created after enabling.',
|
|
781
|
+
'reply.disableNotEnabled': 'Remote replies are not enabled.',
|
|
782
|
+
'reply.disableConfirm': 'Disable remote replies? Notifications and credentials will be preserved. [y/N] ',
|
|
783
|
+
'reply.disableChanged': 'Reply authorization changed. Try again.',
|
|
784
|
+
'reply.disabled': 'Remote replies disabled. Operations already in progress cannot be withdrawn; the bridge will exit on its next check.',
|
|
785
|
+
'reply.endSessionReason': 'The session ended, or its identity could not be verified',
|
|
786
|
+
'reply.endSwitchedReason': 'The session switched',
|
|
787
|
+
'reply.endTurnReason': 'This turn ended',
|
|
788
|
+
'reply.endLocalReason': 'A new task or session started locally',
|
|
789
|
+
'reply.receivedTitle': '✅ Claude received your reply',
|
|
790
|
+
'reply.receivedBody': 'Claude received your reply and will send another notification when the task completes.',
|
|
791
|
+
'reply.receivedTelegramFailed': 'Telegram: the receipt confirmation was not sent; the submitted input will not be replayed.',
|
|
792
|
+
'reply.receivedFeishuBody': 'Claude received your reply and will send another notification when the task completes. The reply text is not forwarded here to reduce exposure.',
|
|
793
|
+
'reply.receivedFeishuFooter': 'Session: {session}',
|
|
794
|
+
'reply.receivedFeishuIncomplete': 'Feishu: the receipt confirmation was not fully sent; the submitted input will not be replayed.',
|
|
795
|
+
'reply.receivedFeishuFailed': 'Feishu: the receipt confirmation failed to send; the submitted input will not be replayed.',
|
|
796
|
+
'reply.bridgeNotReadyButton': 'The reply bridge is not ready yet, so this notification will not show a reply button. Run reply status to see why.',
|
|
797
|
+
'reply.botUsernameInvalid': 'The Telegram bot username is invalid; the reply button was not enabled.',
|
|
798
|
+
'reply.noMessageId': 'The notification did not return a Telegram message ID to associate with.',
|
|
799
|
+
'reply.noSession': 'Could not verify the session; the structured interaction will be handled locally.',
|
|
800
|
+
'reply.noMatchingCall': 'Could not uniquely match this tool call; remote interaction was not enabled and the local window is unaffected.',
|
|
801
|
+
'reply.bridgeNotReadyQuestion': 'The reply bridge is not ready yet; the question will be handled locally.',
|
|
802
|
+
'reply.permissionRequest': 'Tool permission request: {tool}',
|
|
803
|
+
'reply.interactionEnded': 'The remote interaction ended, or no answer was submitted. Nothing is answered automatically; local operation is unaffected.',
|
|
804
|
+
'reply.interactionFailed': 'Remote interaction handling failed. Check locally.',
|
|
805
|
+
'reply.interactionCancelled': 'The interaction wait was cancelled; whether the remote answer took effect is not yet confirmed.',
|
|
806
|
+
'reply.sessionGoneTitle': '⚠️ Cannot reply',
|
|
807
|
+
'reply.sessionGoneBody': 'This session has closed or switched, or this notification has expired. Enter from the latest notification.',
|
|
808
|
+
'reply.replyPromptTitle': '💬 Reply to Claude',
|
|
809
|
+
'reply.replyPromptBody': 'Reply to this message with your input. It will be submitted to the corresponding local session.\nSession: {session}',
|
|
810
|
+
'reply.replyPromptLongPress': 'Long-press this message and choose "Reply", then enter your input. It will be submitted to the corresponding local session.\nSession: {session}',
|
|
811
|
+
'reply.processingFailedCallback': 'Processing did not complete. Check the terminal; nothing will be resubmitted automatically.',
|
|
812
|
+
'reply.processingFailedTitle': '⚠️ This submission did not complete',
|
|
813
|
+
'reply.processingFailedBody': 'An error occurred while processing. This submission may or may not have been registered or applied. Check the terminal and later results; nothing will be resubmitted automatically.',
|
|
814
|
+
'reply.interactionExpiredCallback': 'The session is closed, or this interaction has expired.',
|
|
815
|
+
'reply.interactionExpiredTitle': '⚠️ This submission did not take effect',
|
|
816
|
+
'reply.interactionExpiredBody': 'The session closed or switched, or the interaction expired; the answer was not returned.',
|
|
817
|
+
'reply.replyBoxHint': 'Please type in the reply box',
|
|
818
|
+
'reply.staleTitle': '⚠️ This submission did not take effect',
|
|
819
|
+
'reply.staleBody': 'This message is past its validity window; the answer was not returned. Check the latest question or the terminal state.',
|
|
820
|
+
'reply.howToTitle': '💬 How to reply',
|
|
821
|
+
'reply.howToBody': 'Reply directly to the task-completion notification, or tap the "Reply to Claude" button in the notification.',
|
|
822
|
+
'reply.expiredReplyBody': 'The notification expired, or the corresponding session closed or switched. Reply from the latest notification.',
|
|
823
|
+
'reply.replyFailedTitle': '❌ Reply not submitted',
|
|
824
|
+
'reply.invalidInput': 'Invalid input.',
|
|
825
|
+
'reply.sessionChanged': 'The session changed; this reply was not submitted.',
|
|
826
|
+
'reply.pendingTitle': '⏳ New reply not submitted',
|
|
827
|
+
'reply.pendingBody': 'This session already has a reply awaiting confirmation. Wait for confirmation, or check the local terminal and try again.',
|
|
828
|
+
'reply.queuedTitle': '⏳ Reply queued',
|
|
829
|
+
'reply.queuedBody': 'Claude is working on the current task; the local queue will try to submit after this turn ends and will not type text into a permission prompt that is waiting.',
|
|
830
|
+
'reply.queueExpired': 'The queued reply is more than 5 minutes old and was not submitted. Check the local machine and reply again.',
|
|
831
|
+
'reply.sessionClosed': 'The session is closed or switched; this reply was not submitted.',
|
|
832
|
+
'reply.forwardedTitle': '✅ Forwarded to Claude',
|
|
833
|
+
'reply.forwardedBody': 'Terminal input was submitted; waiting for UserPromptSubmit confirmation.',
|
|
834
|
+
'reply.forwardUnknownTitle': '⚠️ Forward status unconfirmed',
|
|
835
|
+
'reply.forwardFailed': 'The submission did not complete. Check the local terminal; nothing will be resubmitted automatically.',
|
|
836
|
+
'reply.invalidQuestions': 'The question structure is invalid; answer locally.',
|
|
837
|
+
'reply.permissionsNotAuthorized': 'Remote handling of tool permissions is not authorized.',
|
|
838
|
+
'reply.targetChanged': 'The session target changed.',
|
|
839
|
+
'reply.callUnavailable': 'The call has ended or is already bound; no remote question was created.',
|
|
840
|
+
'reply.questionSwitched': 'The question switched; the old request no longer accepts answers.',
|
|
841
|
+
'reply.allowButton': '✅ Allow this time',
|
|
842
|
+
'reply.denyButton': '⛔ Deny',
|
|
843
|
+
'reply.customDenyButton': '✍️ Custom deny reason',
|
|
844
|
+
'reply.submitSelected': 'Submit selected',
|
|
845
|
+
'reply.customInput': '✍️ Custom input',
|
|
846
|
+
'reply.closeRemote': 'Close remote answering (local still works)',
|
|
847
|
+
'reply.toolLabel': 'Tool: {tool}',
|
|
848
|
+
'reply.unknownTool': 'unknown',
|
|
849
|
+
'reply.permissionNote': 'This handles allow, deny, or a custom deny reason for this request. Claude did not provide the complete local button list, so no permanent permission rule is created here.',
|
|
850
|
+
'reply.questionHeading': 'Question {index}/{total}: {question}',
|
|
851
|
+
'reply.multiSelectHint': '\n\nYou can select multiple options, then tap "Submit selected"; custom input is also available.',
|
|
852
|
+
'reply.singleSelectHint': '\n\nTap an option to answer directly, or choose custom input.',
|
|
853
|
+
'reply.localWindowNote': '\nThe local native window can also answer at the same time; the first complete answer Claude receives takes effect. Remote windows are valid for 10 minutes and never auto-select.',
|
|
854
|
+
'reply.feishuMultiSelectHint': '\n\nMulti-select: open Telegram, select options one by one, then tap "Submit selected"; custom input is also available.',
|
|
855
|
+
'reply.feishuSingleSelectHint': '\n\nOpen Telegram, then tap an option to answer directly, or choose custom input.',
|
|
856
|
+
'reply.inactiveTitle': '⚠️ Interaction expired',
|
|
857
|
+
'reply.inactiveBody': 'Enter from the latest notification, or handle it locally.',
|
|
858
|
+
'reply.noInteractionMessageId': 'The interaction notification did not return a message ID.',
|
|
859
|
+
'reply.interactionNotSent': 'The interaction notification was not fully sent; handle it locally.',
|
|
860
|
+
'reply.closedLocal': 'Remote answering was closed; local handling is unaffected.',
|
|
861
|
+
'reply.callbackExpired': 'Not submitted: the button expired, or an answer is already awaiting confirmation.',
|
|
862
|
+
'reply.callbackClosed': 'Remote answering was closed; local handling is unaffected.',
|
|
863
|
+
'reply.callbackRegistered': 'Answer registered; effectiveness not yet confirmed.',
|
|
864
|
+
'reply.callbackUpdated': 'Updated.',
|
|
865
|
+
'reply.pendingConfirmationTitle': '⏳ Answer registered, awaiting confirmation',
|
|
866
|
+
'reply.pendingRemaining': 'The remaining questions still need answers before the full answer is returned.',
|
|
867
|
+
'reply.pendingSubmitted': 'The answer is being returned; whether Claude uses it will be reported later.',
|
|
868
|
+
'reply.pendingFooter': '\nThe result will be reported later; if you never receive it, check the terminal.\nRequest: {id}',
|
|
869
|
+
'reply.notAppliedTitle': '⚠️ This submission did not take effect',
|
|
870
|
+
'reply.notAppliedBody': 'This operation was not submitted: the question was already handled, expired, switched, or an answer is already awaiting confirmation.\nRequest: {id}',
|
|
871
|
+
'reply.denyInstruction': 'Reply to this message with the deny reason. This reason does not approve the permission.',
|
|
872
|
+
'reply.answerInstruction': 'Reply to this message with the complete answer to this question.',
|
|
873
|
+
'reply.answerInvalidTitle': '❌ Answer not submitted',
|
|
874
|
+
'reply.answerInvalidBody': 'Enter an answer of at most 4000 characters; the content will not be truncated.',
|
|
875
|
+
'reply.finalWaiting': 'Waiting for Claude to confirm; the final result will be reported later. If you never receive it, check the terminal.',
|
|
876
|
+
'reply.nextWaiting': 'The remaining questions still need answers before the full answer is returned; it has not taken effect yet.',
|
|
877
|
+
'reply.notSubmitted': 'This operation was not submitted: the question has ended, expired, switched, or an answer is already awaiting confirmation.',
|
|
878
|
+
'reply.requestLine': '\nRequest: {id}',
|
|
879
|
+
'reply.expiredUnsentAnswer': 'Remote answering timed out; no answer was submitted. You can still continue locally.',
|
|
880
|
+
'reply.buttonUnknown': 'Closed · result pending verification',
|
|
881
|
+
'reply.buttonApplied': 'Handled · no more answers',
|
|
882
|
+
'reply.buttonExpired': 'Expired · unanswered',
|
|
883
|
+
'reply.buttonInvalid': 'Invalid · unanswered',
|
|
884
|
+
'reply.buttonClosed': 'Closed · no more answers',
|
|
885
|
+
'reply.buttonProcessed': 'Handled · no more answers',
|
|
886
|
+
'reply.buttonEnded': 'Ended · no more answers',
|
|
887
|
+
'reply.sessionUnknownSuffix': '; no effectiveness confirmation was received for this answer. Check the terminal.',
|
|
888
|
+
'reply.sessionUnsentSuffix': '; this remote answer was not returned.',
|
|
889
|
+
'reply.earlierHandled': 'The local machine or another client handled it first; this Telegram answer was not submitted.',
|
|
890
|
+
'reply.noVerifiableResult': 'Claude ended this question but did not return a verifiable result. Check the terminal.',
|
|
891
|
+
'reply.answerApplied': 'Claude confirmed an answer matching what you submitted was used. If the local machine submitted identical content, this result cannot show which side took effect.',
|
|
892
|
+
'reply.answerNotApplied': 'Claude ended the question without using the answer you submitted; the local machine or another client may have handled it first.',
|
|
893
|
+
'reply.questionProcessed': 'The question was handled; old buttons have expired.',
|
|
894
|
+
'reply.permissionApplied': 'The tool was allowed and completed. If the local machine also approved it, this completion event cannot show which side allowed it.',
|
|
895
|
+
'reply.permissionNotApplied': 'The tool was allowed and executed; this remote decision did not prevent it.',
|
|
896
|
+
'reply.toolFailedUnknown': 'Tool execution failed, was denied, or was cancelled. This event cannot show whether the remote decision took effect. Check the terminal.',
|
|
897
|
+
'reply.toolFailed': 'The request failed, was denied, or was cancelled; this remote decision was not returned.',
|
|
898
|
+
'reply.waitTimeoutUnknown': 'Timed out waiting for effectiveness confirmation, or the session switched. The result is currently unknown. Check the terminal.',
|
|
899
|
+
'reply.sessionEndedUnsent': 'The session ended or switched; the remote answer was not returned. You can still continue in the local interface.',
|
|
900
|
+
'reply.expiredUnanswered': 'Remote answering timed out; no answer was submitted. You can still continue in the local interface.',
|
|
901
|
+
'reply.appliedTitle': '✅ Answer content took effect',
|
|
902
|
+
'reply.resultUnknownTitle': '⚠️ Submission result cannot be confirmed yet',
|
|
903
|
+
'reply.requestLabel': 'Request: {id}',
|
|
904
|
+
'reply.feedbackFailedLog': 'The Telegram result feedback was not sent. It will not be resent automatically; answers already used are unaffected.',
|
|
905
|
+
'reply.clearButtonsFailedLog': 'Telegram old buttons were not removed. The server will still reject this request.',
|
|
906
|
+
'reply.platformTimeout': 'The system session operation timed out. Input may have been partially delivered; to avoid duplicate submission, it will not be retried automatically.',
|
|
907
|
+
'reply.platformFailed': 'The system session operation failed. To avoid leaking commands or input, underlying details are not shown.',
|
|
908
|
+
'reply.emptyReply': 'Reply content cannot be empty.',
|
|
909
|
+
'reply.replyTooLong': 'The reply exceeds 4000 characters and was not submitted. The content will not be truncated or split into multiple messages.',
|
|
910
|
+
'reply.emptyAfterCleanup': 'The reply has no content left to submit after cleanup.',
|
|
911
|
+
'reply.targetInvalid': 'The session is closed or switched, or its identity cannot be verified. Reply from the latest notification.',
|
|
912
|
+
'reply.windowsPartial': 'Windows console injection failed and may have written only part of the text. It will not retry automatically; check the terminal.',
|
|
913
|
+
'reply.unsupportedPlatform': 'Remote replies support only Windows and macOS.',
|
|
914
|
+
'reply.tmuxBufferFailed': 'Failed to create the tmux input buffer; this reply was not submitted.',
|
|
915
|
+
'reply.tmuxChanged': 'The session changed; this reply was not submitted.',
|
|
916
|
+
'reply.tmuxPasteFailed': 'tmux paste failed and may have delivered only part of the text. It will not retry automatically.',
|
|
917
|
+
'reply.tmuxSubmitFailed': 'tmux submission failed; the text may already be entered. It will not retry automatically.',
|
|
918
|
+
'reply.ghosttyFailed': 'Ghostty did not find the target window, or injection failed. It will not fall back to another window or retype the input.',
|
|
919
|
+
'reply.telegramMethod': 'Unsupported Telegram bridge method',
|
|
920
|
+
'reply.telegramConflict': 'Telegram polling conflict; check for an old bridge, another machine, or a webhook. The bridge will not take over or delete a webhook',
|
|
921
|
+
'reply.telegramRequestFailed': 'The Telegram bridge request failed; the server body and secrets are not printed',
|
|
922
|
+
'reply.bridgeAuthFirst': 'Remote replies are not authorized yet. Run reply setup first.',
|
|
923
|
+
'reply.bridgeNotAuthorized': 'Remote replies are not authorized yet.',
|
|
924
|
+
'reply.bridgeLocked': 'A bridge for the same bot is already running for this user, or a lock file was left behind. Confirm the process has exited, then handle the corresponding lock in reply-bots.',
|
|
925
|
+
'reply.webhookConflict': 'This bot already has a webhook and cannot use getUpdates at the same time. Remove the webhook first; this tool will not delete it automatically.',
|
|
926
|
+
'reply.pollFailedLog': 'Telegram polling failed; no secrets or server body are written to the log.',
|
|
927
|
+
'reply.pollFailedFatal': 'Telegram polling failed 5 times in a row; the bridge has exited. Check the network, token, or API conflicts, then start it again.',
|
|
928
|
+
'reply.updatesInvalid': 'The Telegram update format is invalid.',
|
|
929
|
+
'reply.handleFailedLog': 'Reply handling failed. This update will not be replayed; check the terminal, or retry from the latest notification.',
|
|
930
|
+
'reply.bridgeFailed': 'The bridge failed to start or run; to avoid leaking secrets, the underlying error is not shown.',
|
|
931
|
+
'channels.telegramReplyButton': '💬 Reply to Claude',
|
|
932
|
+
};
|
|
933
|
+
let current = 'zh';
|
|
934
|
+
export function setLocale(locale) { current = locale; }
|
|
935
|
+
export function getLocale() { return current; }
|
|
936
|
+
export function parseLocale(value) {
|
|
937
|
+
if (typeof value !== 'string')
|
|
938
|
+
return undefined;
|
|
939
|
+
const normalized = value.trim().toLowerCase();
|
|
940
|
+
if (['zh', 'zh-cn', 'zh_cn'].includes(normalized))
|
|
941
|
+
return 'zh';
|
|
942
|
+
if (['en', 'en-us', 'en_us'].includes(normalized))
|
|
943
|
+
return 'en';
|
|
944
|
+
return undefined;
|
|
945
|
+
}
|
|
946
|
+
export function resolveLocale(explicit, env, configured) {
|
|
947
|
+
return parseLocale(explicit) ?? parseLocale(env.DEV_NOTIFY_LANG) ?? parseLocale(configured) ?? 'zh';
|
|
948
|
+
}
|
|
949
|
+
export function localeName(locale = current) {
|
|
950
|
+
return locale === 'zh' ? '简体中文' : 'English';
|
|
951
|
+
}
|
|
952
|
+
export function joinList(items) {
|
|
953
|
+
return items.join(current === 'zh' ? '、' : ', ');
|
|
954
|
+
}
|
|
955
|
+
export function t(key, params = {}) {
|
|
956
|
+
const message = current === 'en' ? en[key] : zh[key];
|
|
957
|
+
if (typeof message === 'function')
|
|
958
|
+
return message(params);
|
|
959
|
+
return message.replace(/\{(\w+)\}/g, (match, name) => Object.hasOwn(params, name) ? String(params[name]) : match);
|
|
960
|
+
}
|