orca-zh-tw-installer 2.3.0 → 2.4.0

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/index.js CHANGED
@@ -89,6 +89,7 @@ function createPatcher(label, filePath) {
89
89
  let code = fs.readFileSync(filePath, 'utf8');
90
90
  const ok = [];
91
91
  const failed = [];
92
+ const warned = [];
92
93
  return {
93
94
  label,
94
95
  /**
@@ -104,9 +105,25 @@ function createPatcher(label, filePath) {
104
105
  if (code === before || !done(code)) failed.push(name);
105
106
  else ok.push(name);
106
107
  },
108
+ /**
109
+ * 加值型修補:錨點找不到只警告,不讓整個安裝失敗。
110
+ *
111
+ * 語言切換與字典注入是核心,錨點壞了就必須中止——否則使用者會裝到一個
112
+ * 「看起來成功但沒效果」的語系包。但原生選單、快速鍵名稱、斜線命令說明
113
+ * 這些是額外的本地化,Orca 改了結構時頂多那部分維持英文,
114
+ * 不該連帶讓整包裝不起來。
115
+ */
116
+ patchOptional(name, done, find, repl) {
117
+ if (done(code)) { ok.push(`${name}(已存在)`); return; }
118
+ const before = code;
119
+ code = code.replace(find, repl);
120
+ if (code === before || !done(code)) warned.push(name);
121
+ else ok.push(name);
122
+ },
107
123
  save() { fs.writeFileSync(filePath, code); },
108
124
  get ok() { return ok; },
109
125
  get failed() { return failed; },
126
+ get warned() { return warned; },
110
127
  };
111
128
  }
112
129
 
@@ -182,7 +199,7 @@ const KEYBINDING_GROUP_SLUGS = {
182
199
  };
183
200
 
184
201
  function patchKeybindingTitles(p, translateFn) {
185
- p.patch('快速鍵名稱與群組改走 i18n',
202
+ p.patchOptional('快速鍵名稱與群組改走 i18n',
186
203
  c => c.includes('keybindingGroup.'),
187
204
  // id 緊接 title、group、scope 是 keybinding 定義獨有的形狀。
188
205
  // 不能只比對 group:"…"——built-in/imported 等其他結構也有 group 欄位。
@@ -225,7 +242,7 @@ const OPTION_LABELS = {
225
242
  };
226
243
 
227
244
  function patchOptionLabels(p, translateFn) {
228
- p.patch('選項清單標籤改走 i18n',
245
+ p.patchOptional('選項清單標籤改走 i18n',
229
246
  c => c.includes('optionLabel.in-progress'),
230
247
  /\{(\s*)id: "([a-z0-9-]+)",(\s*)label: "([^"]{1,40})"/g,
231
248
  (m, s0, id, s1, label) => {
@@ -236,27 +253,52 @@ function patchOptionLabels(p, translateFn) {
236
253
  });
237
254
  }
238
255
 
256
+ // ── Agent 斜線命令說明本地化 ───────────────────────────────────────────
257
+ // 在 Agent composer 輸入 / 時列出的命令清單,description 是 Orca 自己寫的
258
+ // 說明文字,寫死在 COMMON_COMMANDS/CLAUDE_COMMANDS/CODEX_COMMANDS 裡。
259
+ // name 是真的要送給 CLI 的命令,絕對不能動。
260
+ //
261
+ // 鍵用英文原文的 slug 而不是命令名:/clear、/compact、/init 在不同 agent
262
+ // 有不同說明(Claude 的 /clear 是「Clear conversation history」,
263
+ // Codex 的是「Clear the terminal and start a new chat」),
264
+ // 用命令名當鍵會撞在一起。
265
+ const slashKey = en => 'slashCommand.' + en
266
+ .replace(/[^A-Za-z0-9 ]/g, '')
267
+ .split(/\s+/)
268
+ .filter(Boolean)
269
+ .map((w, i) => i === 0 ? w.toLowerCase() : w[0].toUpperCase() + w.slice(1).toLowerCase())
270
+ .join('');
271
+
272
+ function patchSlashCommands(p, translateFn) {
273
+ p.patchOptional('Agent 斜線命令說明改走 i18n',
274
+ c => c.includes('slashCommand.'),
275
+ /\{(\s*)name: "([a-z][a-z0-9:-]*)",(\s*)description: "((?:[^"\\]|\\.){2,80})"(\s*)\}/g,
276
+ (m, s0, name, s1, en, s2) =>
277
+ `{${s0}name: ${JSON.stringify(name)},${s1}get description() { `
278
+ + `return ${translateFn}(${JSON.stringify(slashKey(en))}, ${JSON.stringify(en)}); }${s2}}`);
279
+ }
280
+
239
281
  function patchNativeMenus(p) {
240
- p.patch('原生選單:為無 label 的 role 注入譯文',
282
+ p.patchOptional('原生選單:為無 label 的 role 注入譯文',
241
283
  c => c.includes('nativeMenu.selectAll'),
242
284
  /\{\s*role:\s*"([A-Za-z]+)"\s*\}/g,
243
285
  (m, role) => MENU_ROLE_LABELS[role]
244
286
  ? `{ role: "${role}", label: ${t(role, MENU_ROLE_LABELS[role])} }`
245
287
  : m);
246
288
 
247
- p.patch('原生選單:Markdown 命令項改走 i18n',
289
+ p.patchOptional('原生選單:Markdown 命令項改走 i18n',
248
290
  c => c.includes('nativeMenu.addLink'),
249
291
  /markdownCommandItem\("([^"]+)"/g,
250
292
  (m, label) => MENU_MD_ITEMS[label]
251
293
  ? `markdownCommandItem(${t(MENU_MD_ITEMS[label], label)}`
252
294
  : m);
253
295
 
254
- p.patch('原生選單:子選單標題改走 i18n',
296
+ p.patchOptional('原生選單:子選單標題改走 i18n',
255
297
  c => c.includes('nativeMenu.format'),
256
298
  /label:\s*"(Format|Paragraph|Insert)"/g,
257
299
  (m, label) => `label: ${t(MENU_SUBMENU_LABELS[label], label)}`);
258
300
 
259
- p.patch('原生選單:貼上項改走 i18n',
301
+ p.patchOptional('原生選單:貼上項改走 i18n',
260
302
  c => c.includes('nativeMenu.pasteAsPlainText'),
261
303
  /editableContextPasteItem\("([^"]+)"/g,
262
304
  (m, label) => MENU_PASTE_ITEMS[label]
@@ -363,6 +405,24 @@ async function patch() {
363
405
  patchOptionLabels(rp, 'translate');
364
406
  rp.save();
365
407
 
408
+ // Agent 斜線命令的說明在另一個 chunk。檔名帶 hash(index-DlEnJ7xL.js),
409
+ // 每次 Orca 建置都會變,所以靠內容找而不是靠檔名。
410
+ // 那個 chunk 有 import { t as translate },模組層可直接呼叫。
411
+ const slashFile = fs.readdirSync(assetsDir)
412
+ .filter(f => f.endsWith('.js'))
413
+ .map(f => path.join(assetsDir, f))
414
+ .find(f => {
415
+ try { return fs.readFileSync(f, 'utf8').includes('CODEX_COMMANDS'); } catch { return false; }
416
+ });
417
+ let sp = null;
418
+ if (slashFile) {
419
+ sp = createPatcher('slash commands', slashFile);
420
+ patchSlashCommands(sp, 'translate');
421
+ sp.save();
422
+ } else {
423
+ console.log(' ⚠️ 找不到含 CODEX_COMMANDS 的 chunk,斜線命令說明將維持英文。');
424
+ }
425
+
366
426
  console.log('📂 4/6 正在植入繁體中文字典 (ESM + CJS 兩種格式)...');
367
427
  const esmDict = path.join(__dirname, 'zh-TW-nested.js');
368
428
  const cjsDict = path.join(__dirname, 'zh-TW-nested.cjs.js');
@@ -374,13 +434,16 @@ async function patch() {
374
434
  fs.copyFileSync(cjsDict, path.join(chunksDir, 'zh-TW-nested.js'));
375
435
 
376
436
  console.log('🔎 5/6 正在驗證所有注入點...');
377
- const allFailed = [
378
- ...mp.failed.map(n => `[main] ${n}`),
379
- ...rp.failed.map(n => `[renderer] ${n}`),
380
- ];
381
- for (const p of [mp, rp]) {
437
+ const patchers = sp ? [mp, rp, sp] : [mp, rp];
438
+ const allFailed = patchers.flatMap(p => p.failed.map(n => `[${p.label}] ${n}`));
439
+ const allWarned = patchers.flatMap(p => p.warned.map(n => `[${p.label}] ${n}`));
440
+ for (const p of patchers) {
382
441
  for (const n of p.ok) console.log(` ✅ [${p.label}] ${n}`);
383
442
  }
443
+ // 加值型修補失敗只警告——那部分維持英文,但語言切換與字典照樣生效。
444
+ for (const n of allWarned) {
445
+ console.log(` ⚠️ ${n}(錨點已變,該部分維持英文,其餘不受影響)`);
446
+ }
384
447
  if (allFailed.length) {
385
448
  for (const n of allFailed) console.error(` ❌ ${n}`);
386
449
  throw new Error(
@@ -397,10 +460,12 @@ async function patch() {
397
460
  // node --check 會以 CommonJS 解析而誤判失敗。複製成 .mjs 再檢查。
398
461
  const probeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'orca-zh-tw-check-'));
399
462
  try {
400
- for (const [label, file, ext] of [
463
+ const toCheck = [
401
464
  ['main process', mainFile, '.js'],
402
465
  ['renderer', rendererFile, '.mjs'],
403
- ]) {
466
+ ];
467
+ if (slashFile) toCheck.push(['slash commands', slashFile, '.mjs']);
468
+ for (const [label, file, ext] of toCheck) {
404
469
  const probe = path.join(probeDir, 'probe' + ext);
405
470
  fs.copyFileSync(file, probe);
406
471
  try {
@@ -11302,5 +11302,54 @@
11302
11302
  "optionLabel.off": "關",
11303
11303
  "optionLabel.on": "開",
11304
11304
  "optionLabel.auto": "自動",
11305
- "optionLabel.default": "設定檔預設"
11305
+ "optionLabel.default": "設定檔預設",
11306
+ "slashCommand.clearTheConversation": "清除對話",
11307
+ "slashCommand.showAvailableCommands": "顯示可用命令",
11308
+ "slashCommand.clearConversationHistory": "清除對話記錄",
11309
+ "slashCommand.summarizeAndCompactTheConversation": "摘要並壓縮對話",
11310
+ "slashCommand.initializeAClaudemd": "初始化 CLAUDE.md",
11311
+ "slashCommand.reviewTheCurrentChanges": "審查目前的變更",
11312
+ "slashCommand.chooseTheModelAndReasoningEffort": "選擇模型與推理強度",
11313
+ "slashCommand.includeIdeContext": "納入 IDE 上下文",
11314
+ "slashCommand.chooseWhatCodexIsAllowedToDo": "選擇 Codex 的權限範圍",
11315
+ "slashCommand.remapTuiShortcuts": "重新對應 TUI 快速鍵",
11316
+ "slashCommand.toggleVimMode": "切換 Vim 模式",
11317
+ "slashCommand.toggleExperimentalFeatures": "切換實驗性功能",
11318
+ "slashCommand.approveOneAutoreviewRetry": "核准一次自動審查重試",
11319
+ "slashCommand.configureMemoryUse": "設定記憶體使用",
11320
+ "slashCommand.manageAndUseSkills": "管理與使用技能",
11321
+ "slashCommand.importSetupFromClaudeCode": "從 Claude Code 匯入設定",
11322
+ "slashCommand.viewLifecycleHooks": "檢視生命週期掛鉤",
11323
+ "slashCommand.renameTheCurrentThread": "重新命名目前的討論串",
11324
+ "slashCommand.startANewChat": "開始新的聊天",
11325
+ "slashCommand.archiveThisSessionAndExit": "封存此工作階段並結束",
11326
+ "slashCommand.deleteThisSessionAndExit": "刪除此工作階段並結束",
11327
+ "slashCommand.resumeASavedChat": "繼續已儲存的聊天",
11328
+ "slashCommand.forkTheCurrentChat": "分支目前的聊天",
11329
+ "slashCommand.continueInCodexDesktop": "在 Codex Desktop 中繼續",
11330
+ "slashCommand.createAnAgentsmdFile": "建立 AGENTS.md 檔案",
11331
+ "slashCommand.compactTheConversation": "壓縮對話",
11332
+ "slashCommand.switchToPlanMode": "切換到計畫模式",
11333
+ "slashCommand.setOrViewTheGoal": "設定或檢視目標",
11334
+ "slashCommand.switchTheActiveAgentThread": "切換使用中的 Agent 討論串",
11335
+ "slashCommand.startASideConversation": "開始側邊對話",
11336
+ "slashCommand.copyTheLastResponseAsMarkdown": "以 Markdown 複製最後一則回應",
11337
+ "slashCommand.toggleRawScrollbackMode": "切換原始回捲模式",
11338
+ "slashCommand.showTheWorkingDiff": "顯示工作區差異",
11339
+ "slashCommand.mentionAFile": "提及一個檔案",
11340
+ "slashCommand.showSessionConfigurationAndUsage": "顯示工作階段設定與使用量",
11341
+ "slashCommand.viewAccountUsage": "檢視帳號使用量",
11342
+ "slashCommand.configureTheTerminalTitle": "設定終端機標題",
11343
+ "slashCommand.configureTheStatusLine": "設定狀態列",
11344
+ "slashCommand.chooseASyntaxHighlightingTheme": "選擇語法突顯主題",
11345
+ "slashCommand.chooseOrHideTheTerminalPet": "選擇或隱藏終端機寵物",
11346
+ "slashCommand.listConfiguredMcpTools": "列出已設定的 MCP 工具",
11347
+ "slashCommand.browsePlugins": "瀏覽外掛",
11348
+ "slashCommand.logOutOfCodex": "登出 Codex",
11349
+ "slashCommand.exitCodex": "結束 Codex",
11350
+ "slashCommand.sendLogsToMaintainers": "將記錄檔傳送給維護者",
11351
+ "slashCommand.listBackgroundTerminals": "列出背景終端機",
11352
+ "slashCommand.stopAllBackgroundTerminals": "停止所有背景終端機",
11353
+ "slashCommand.clearTheTerminalAndStartANewChat": "清除終端機並開始新的聊天",
11354
+ "slashCommand.chooseACommunicationStyle": "選擇溝通風格"
11306
11355
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orca-zh-tw-installer",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Orca AI IDE 台灣繁體中文 (zh-TW) 一鍵安裝包",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -14040,6 +14040,57 @@ const zhTW = {
14040
14040
  "on": "開",
14041
14041
  "auto": "自動",
14042
14042
  "default": "設定檔預設"
14043
+ },
14044
+ "slashCommand": {
14045
+ "clearTheConversation": "清除對話",
14046
+ "showAvailableCommands": "顯示可用命令",
14047
+ "clearConversationHistory": "清除對話記錄",
14048
+ "summarizeAndCompactTheConversation": "摘要並壓縮對話",
14049
+ "initializeAClaudemd": "初始化 CLAUDE.md",
14050
+ "reviewTheCurrentChanges": "審查目前的變更",
14051
+ "chooseTheModelAndReasoningEffort": "選擇模型與推理強度",
14052
+ "includeIdeContext": "納入 IDE 上下文",
14053
+ "chooseWhatCodexIsAllowedToDo": "選擇 Codex 的權限範圍",
14054
+ "remapTuiShortcuts": "重新對應 TUI 快速鍵",
14055
+ "toggleVimMode": "切換 Vim 模式",
14056
+ "toggleExperimentalFeatures": "切換實驗性功能",
14057
+ "approveOneAutoreviewRetry": "核准一次自動審查重試",
14058
+ "configureMemoryUse": "設定記憶體使用",
14059
+ "manageAndUseSkills": "管理與使用技能",
14060
+ "importSetupFromClaudeCode": "從 Claude Code 匯入設定",
14061
+ "viewLifecycleHooks": "檢視生命週期掛鉤",
14062
+ "renameTheCurrentThread": "重新命名目前的討論串",
14063
+ "startANewChat": "開始新的聊天",
14064
+ "archiveThisSessionAndExit": "封存此工作階段並結束",
14065
+ "deleteThisSessionAndExit": "刪除此工作階段並結束",
14066
+ "resumeASavedChat": "繼續已儲存的聊天",
14067
+ "forkTheCurrentChat": "分支目前的聊天",
14068
+ "continueInCodexDesktop": "在 Codex Desktop 中繼續",
14069
+ "createAnAgentsmdFile": "建立 AGENTS.md 檔案",
14070
+ "compactTheConversation": "壓縮對話",
14071
+ "switchToPlanMode": "切換到計畫模式",
14072
+ "setOrViewTheGoal": "設定或檢視目標",
14073
+ "switchTheActiveAgentThread": "切換使用中的 Agent 討論串",
14074
+ "startASideConversation": "開始側邊對話",
14075
+ "copyTheLastResponseAsMarkdown": "以 Markdown 複製最後一則回應",
14076
+ "toggleRawScrollbackMode": "切換原始回捲模式",
14077
+ "showTheWorkingDiff": "顯示工作區差異",
14078
+ "mentionAFile": "提及一個檔案",
14079
+ "showSessionConfigurationAndUsage": "顯示工作階段設定與使用量",
14080
+ "viewAccountUsage": "檢視帳號使用量",
14081
+ "configureTheTerminalTitle": "設定終端機標題",
14082
+ "configureTheStatusLine": "設定狀態列",
14083
+ "chooseASyntaxHighlightingTheme": "選擇語法突顯主題",
14084
+ "chooseOrHideTheTerminalPet": "選擇或隱藏終端機寵物",
14085
+ "listConfiguredMcpTools": "列出已設定的 MCP 工具",
14086
+ "browsePlugins": "瀏覽外掛",
14087
+ "logOutOfCodex": "登出 Codex",
14088
+ "exitCodex": "結束 Codex",
14089
+ "sendLogsToMaintainers": "將記錄檔傳送給維護者",
14090
+ "listBackgroundTerminals": "列出背景終端機",
14091
+ "stopAllBackgroundTerminals": "停止所有背景終端機",
14092
+ "clearTheTerminalAndStartANewChat": "清除終端機並開始新的聊天",
14093
+ "chooseACommunicationStyle": "選擇溝通風格"
14043
14094
  }
14044
14095
  };
14045
14096
  exports.default = zhTW;
@@ -14057,3 +14108,4 @@ exports.nativeMenu = zhTW.nativeMenu;
14057
14108
  exports.keybindingGroup = zhTW.keybindingGroup;
14058
14109
  exports.keybinding = zhTW.keybinding;
14059
14110
  exports.optionLabel = zhTW.optionLabel;
14111
+ exports.slashCommand = zhTW.slashCommand;
package/zh-TW-nested.js CHANGED
@@ -14038,5 +14038,56 @@ export default {
14038
14038
  "on": "開",
14039
14039
  "auto": "自動",
14040
14040
  "default": "設定檔預設"
14041
+ },
14042
+ "slashCommand": {
14043
+ "clearTheConversation": "清除對話",
14044
+ "showAvailableCommands": "顯示可用命令",
14045
+ "clearConversationHistory": "清除對話記錄",
14046
+ "summarizeAndCompactTheConversation": "摘要並壓縮對話",
14047
+ "initializeAClaudemd": "初始化 CLAUDE.md",
14048
+ "reviewTheCurrentChanges": "審查目前的變更",
14049
+ "chooseTheModelAndReasoningEffort": "選擇模型與推理強度",
14050
+ "includeIdeContext": "納入 IDE 上下文",
14051
+ "chooseWhatCodexIsAllowedToDo": "選擇 Codex 的權限範圍",
14052
+ "remapTuiShortcuts": "重新對應 TUI 快速鍵",
14053
+ "toggleVimMode": "切換 Vim 模式",
14054
+ "toggleExperimentalFeatures": "切換實驗性功能",
14055
+ "approveOneAutoreviewRetry": "核准一次自動審查重試",
14056
+ "configureMemoryUse": "設定記憶體使用",
14057
+ "manageAndUseSkills": "管理與使用技能",
14058
+ "importSetupFromClaudeCode": "從 Claude Code 匯入設定",
14059
+ "viewLifecycleHooks": "檢視生命週期掛鉤",
14060
+ "renameTheCurrentThread": "重新命名目前的討論串",
14061
+ "startANewChat": "開始新的聊天",
14062
+ "archiveThisSessionAndExit": "封存此工作階段並結束",
14063
+ "deleteThisSessionAndExit": "刪除此工作階段並結束",
14064
+ "resumeASavedChat": "繼續已儲存的聊天",
14065
+ "forkTheCurrentChat": "分支目前的聊天",
14066
+ "continueInCodexDesktop": "在 Codex Desktop 中繼續",
14067
+ "createAnAgentsmdFile": "建立 AGENTS.md 檔案",
14068
+ "compactTheConversation": "壓縮對話",
14069
+ "switchToPlanMode": "切換到計畫模式",
14070
+ "setOrViewTheGoal": "設定或檢視目標",
14071
+ "switchTheActiveAgentThread": "切換使用中的 Agent 討論串",
14072
+ "startASideConversation": "開始側邊對話",
14073
+ "copyTheLastResponseAsMarkdown": "以 Markdown 複製最後一則回應",
14074
+ "toggleRawScrollbackMode": "切換原始回捲模式",
14075
+ "showTheWorkingDiff": "顯示工作區差異",
14076
+ "mentionAFile": "提及一個檔案",
14077
+ "showSessionConfigurationAndUsage": "顯示工作階段設定與使用量",
14078
+ "viewAccountUsage": "檢視帳號使用量",
14079
+ "configureTheTerminalTitle": "設定終端機標題",
14080
+ "configureTheStatusLine": "設定狀態列",
14081
+ "chooseASyntaxHighlightingTheme": "選擇語法突顯主題",
14082
+ "chooseOrHideTheTerminalPet": "選擇或隱藏終端機寵物",
14083
+ "listConfiguredMcpTools": "列出已設定的 MCP 工具",
14084
+ "browsePlugins": "瀏覽外掛",
14085
+ "logOutOfCodex": "登出 Codex",
14086
+ "exitCodex": "結束 Codex",
14087
+ "sendLogsToMaintainers": "將記錄檔傳送給維護者",
14088
+ "listBackgroundTerminals": "列出背景終端機",
14089
+ "stopAllBackgroundTerminals": "停止所有背景終端機",
14090
+ "clearTheTerminalAndStartANewChat": "清除終端機並開始新的聊天",
14091
+ "chooseACommunicationStyle": "選擇溝通風格"
14041
14092
  }
14042
14093
  };