orca-zh-tw-installer 2.0.0 → 2.1.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
@@ -131,6 +131,69 @@ function patchLocaleGate(p) {
131
131
  '$1\n if (language === "zh-TW") {\n return "zh-TW";\n }');
132
132
  }
133
133
 
134
+ // ── 原生選單本地化 ─────────────────────────────────────────────────────
135
+ // Orca 的 Electron 原生選單有兩類字串完全沒有經過 i18n,語系檔再完整也翻不到:
136
+ //
137
+ // 1. { role: "undo" } 這種沒給 label 的項目。label 由 Electron 自己提供,
138
+ // 而 Electron 只在 macOS 從系統取得本地化字串,Windows/Linux 是寫死英文。
139
+ // 所以「編輯」選單會出現 Undo / Redo / Cut / Copy / Select All 全英文,
140
+ // 只有 Paste 是中文——因為 Orca 給 Paste 寫了 label(它有自訂行為)。
141
+ //
142
+ // 2. Markdown 右鍵選單的標籤是直接寫在原始碼裡的字面值
143
+ // (markdownCommandItem("Bold", …)、label: "Format"),根本沒有對應的鍵。
144
+ //
145
+ // 兩類都靠改寫 main process 原始碼解決:注入 translateMain(...) 呼叫。
146
+ // translateMain 是 Orca 自己的翻譯函式,定義在該檔案的模組作用域,
147
+ // 所有選單建構點都在其後,可安全呼叫。
148
+ const MENU_ROLE_LABELS = {
149
+ about: 'About', services: 'Services', hide: 'Hide', hideOthers: 'Hide Others',
150
+ unhide: 'Show All', quit: 'Quit', undo: 'Undo', redo: 'Redo', cut: 'Cut',
151
+ copy: 'Copy', selectAll: 'Select All', toggleDevTools: 'Toggle Developer Tools',
152
+ togglefullscreen: 'Toggle Full Screen', minimize: 'Minimize', zoom: 'Zoom',
153
+ };
154
+ // 字面值 → 鍵名。必須連呼叫包裝一起比對:「Quote」在全檔出現 5 次,
155
+ // 但只有 markdownCommandItem("Quote" 這一處是選單標籤。
156
+ const MENU_MD_ITEMS = {
157
+ 'Add link': 'addLink', 'Bold': 'bold', 'Italic': 'italic', 'Strike': 'strike',
158
+ 'Inline code': 'inlineCode', 'Code block': 'codeBlock', 'Quote': 'quote',
159
+ 'Body text': 'bodyText', 'Heading 1': 'heading1', 'Heading 2': 'heading2',
160
+ 'Heading 3': 'heading3', 'Heading 4': 'heading4', 'Heading 5': 'heading5',
161
+ 'Bullet list': 'bulletList', 'Numbered list': 'numberedList', 'Checklist': 'checklist',
162
+ 'Link': 'link', 'Image': 'image', 'Divider': 'divider',
163
+ };
164
+ const MENU_SUBMENU_LABELS = { 'Format': 'format', 'Paragraph': 'paragraph', 'Insert': 'insert' };
165
+ const MENU_PASTE_ITEMS = { 'Paste': 'paste', 'Paste as plain text': 'pasteAsPlainText' };
166
+
167
+ const t = (key, en) => `translateMain("nativeMenu.${key}", ${JSON.stringify(en)})`;
168
+
169
+ function patchNativeMenus(p) {
170
+ p.patch('原生選單:為無 label 的 role 注入譯文',
171
+ c => c.includes('nativeMenu.selectAll'),
172
+ /\{\s*role:\s*"([A-Za-z]+)"\s*\}/g,
173
+ (m, role) => MENU_ROLE_LABELS[role]
174
+ ? `{ role: "${role}", label: ${t(role, MENU_ROLE_LABELS[role])} }`
175
+ : m);
176
+
177
+ p.patch('原生選單:Markdown 命令項改走 i18n',
178
+ c => c.includes('nativeMenu.addLink'),
179
+ /markdownCommandItem\("([^"]+)"/g,
180
+ (m, label) => MENU_MD_ITEMS[label]
181
+ ? `markdownCommandItem(${t(MENU_MD_ITEMS[label], label)}`
182
+ : m);
183
+
184
+ p.patch('原生選單:子選單標題改走 i18n',
185
+ c => c.includes('nativeMenu.format'),
186
+ /label:\s*"(Format|Paragraph|Insert)"/g,
187
+ (m, label) => `label: ${t(MENU_SUBMENU_LABELS[label], label)}`);
188
+
189
+ p.patch('原生選單:貼上項改走 i18n',
190
+ c => c.includes('nativeMenu.pasteAsPlainText'),
191
+ /editableContextPasteItem\("([^"]+)"/g,
192
+ (m, label) => MENU_PASTE_ITEMS[label]
193
+ ? `editableContextPasteItem(${t(MENU_PASTE_ITEMS[label], label)}`
194
+ : m);
195
+ }
196
+
134
197
  async function patch() {
135
198
  try {
136
199
  // dry-run 不寫檔,Orca 執行中也能安全跑,故不檢查
@@ -191,6 +254,7 @@ async function patch() {
191
254
  c => c.includes('"zh-TW": () => Promise.resolve()'),
192
255
  /(zh: \(\) => Promise\.resolve\(\)\.then\(\(\) => require\("\.\/chunks\/zh-[A-Za-z0-9_-]+\.js"\)\))/,
193
256
  '$1,\n "zh-TW": () => Promise.resolve().then(() => require("./chunks/zh-TW-nested.js"))');
257
+ patchNativeMenus(mp);
194
258
  mp.save();
195
259
 
196
260
  console.log('🛠️ 3/6 正在修補渲染器 (renderer process) 語言限制...');
@@ -251,6 +315,36 @@ async function patch() {
251
315
  );
252
316
  }
253
317
 
318
+ // 注入點都成功不代表改出來的檔案還能執行。原生選單那幾個補丁是用正則
319
+ // 改寫 8MB 的 bundle,一旦括號配對出錯,Orca 會在啟動時整個掛掉而不是
320
+ // 只有選單壞掉。所以重新封裝前先讓 Node 真的解析一遍。
321
+ const { execFileSync } = require('child_process');
322
+ // renderer 是 ES module(用了 import.meta.url),但副檔名是 .js,
323
+ // node --check 會以 CommonJS 解析而誤判失敗。複製成 .mjs 再檢查。
324
+ const probeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'orca-zh-tw-check-'));
325
+ try {
326
+ for (const [label, file, ext] of [
327
+ ['main process', mainFile, '.js'],
328
+ ['renderer', rendererFile, '.mjs'],
329
+ ]) {
330
+ const probe = path.join(probeDir, 'probe' + ext);
331
+ fs.copyFileSync(file, probe);
332
+ try {
333
+ execFileSync(process.execPath, ['--check', probe], { stdio: ['ignore', 'ignore', 'pipe'] });
334
+ console.log(` ✅ [${label}] 修補後的檔案通過 node --check`);
335
+ } catch (e) {
336
+ const msg = String(e.stderr || e.message)
337
+ .split('\n').filter(l => !/^\(node:/.test(l) && !/trace-warnings/.test(l))
338
+ .slice(0, 4).join('\n ');
339
+ throw new Error(
340
+ `[${label}] 修補後的檔案語法無效,已中止且未改動你的 Orca:\n ${msg}`
341
+ );
342
+ }
343
+ }
344
+ } finally {
345
+ fs.rmSync(probeDir, { recursive: true, force: true });
346
+ }
347
+
254
348
  if (DRY_RUN) {
255
349
  console.log('\n✅ [dry-run] 全部注入點驗證通過,未改動你的 Orca。');
256
350
  console.log(' 關閉 Orca 後執行 npm start 即可正式套用。\n');
@@ -11155,5 +11155,44 @@
11155
11155
  "auto.components.settings.RuntimeEnvironmentsPane.updatingServers": "正在更新伺服器…",
11156
11156
  "dashboardPopout.close": "關閉儀表板",
11157
11157
  "dashboardPopout.settings": "Agent 儀表板設定",
11158
- "dashboardPopout.settingsTooltip": "看板設定"
11158
+ "dashboardPopout.settingsTooltip": "看板設定",
11159
+ "nativeMenu.undo": "復原",
11160
+ "nativeMenu.redo": "重做",
11161
+ "nativeMenu.cut": "剪下",
11162
+ "nativeMenu.copy": "複製",
11163
+ "nativeMenu.selectAll": "全選",
11164
+ "nativeMenu.minimize": "最小化",
11165
+ "nativeMenu.zoom": "縮放",
11166
+ "nativeMenu.togglefullscreen": "切換全螢幕",
11167
+ "nativeMenu.toggleDevTools": "切換開發者工具",
11168
+ "nativeMenu.about": "關於",
11169
+ "nativeMenu.services": "服務",
11170
+ "nativeMenu.hide": "隱藏",
11171
+ "nativeMenu.hideOthers": "隱藏其他",
11172
+ "nativeMenu.unhide": "全部顯示",
11173
+ "nativeMenu.quit": "結束",
11174
+ "nativeMenu.addLink": "新增連結",
11175
+ "nativeMenu.format": "格式",
11176
+ "nativeMenu.bold": "粗體",
11177
+ "nativeMenu.italic": "斜體",
11178
+ "nativeMenu.strike": "刪除線",
11179
+ "nativeMenu.inlineCode": "行內程式碼",
11180
+ "nativeMenu.codeBlock": "程式碼區塊",
11181
+ "nativeMenu.quote": "引用",
11182
+ "nativeMenu.paragraph": "段落",
11183
+ "nativeMenu.bodyText": "本文",
11184
+ "nativeMenu.heading1": "標題 1",
11185
+ "nativeMenu.heading2": "標題 2",
11186
+ "nativeMenu.heading3": "標題 3",
11187
+ "nativeMenu.heading4": "標題 4",
11188
+ "nativeMenu.heading5": "標題 5",
11189
+ "nativeMenu.bulletList": "項目符號清單",
11190
+ "nativeMenu.numberedList": "編號清單",
11191
+ "nativeMenu.checklist": "核取清單",
11192
+ "nativeMenu.insert": "插入",
11193
+ "nativeMenu.link": "連結",
11194
+ "nativeMenu.image": "圖片",
11195
+ "nativeMenu.divider": "分隔線",
11196
+ "nativeMenu.paste": "貼上",
11197
+ "nativeMenu.pasteAsPlainText": "貼上為純文字"
11159
11198
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orca-zh-tw-installer",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Orca AI IDE 台灣繁體中文 (zh-TW) 一鍵安裝包",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -13835,6 +13835,47 @@ const zhTW = {
13835
13835
  "sidebar": {
13836
13836
  "label": "Agent 儀表板"
13837
13837
  }
13838
+ },
13839
+ "nativeMenu": {
13840
+ "undo": "復原",
13841
+ "redo": "重做",
13842
+ "cut": "剪下",
13843
+ "copy": "複製",
13844
+ "selectAll": "全選",
13845
+ "minimize": "最小化",
13846
+ "zoom": "縮放",
13847
+ "togglefullscreen": "切換全螢幕",
13848
+ "toggleDevTools": "切換開發者工具",
13849
+ "about": "關於",
13850
+ "services": "服務",
13851
+ "hide": "隱藏",
13852
+ "hideOthers": "隱藏其他",
13853
+ "unhide": "全部顯示",
13854
+ "quit": "結束",
13855
+ "addLink": "新增連結",
13856
+ "format": "格式",
13857
+ "bold": "粗體",
13858
+ "italic": "斜體",
13859
+ "strike": "刪除線",
13860
+ "inlineCode": "行內程式碼",
13861
+ "codeBlock": "程式碼區塊",
13862
+ "quote": "引用",
13863
+ "paragraph": "段落",
13864
+ "bodyText": "本文",
13865
+ "heading1": "標題 1",
13866
+ "heading2": "標題 2",
13867
+ "heading3": "標題 3",
13868
+ "heading4": "標題 4",
13869
+ "heading5": "標題 5",
13870
+ "bulletList": "項目符號清單",
13871
+ "numberedList": "編號清單",
13872
+ "checklist": "核取清單",
13873
+ "insert": "插入",
13874
+ "link": "連結",
13875
+ "image": "圖片",
13876
+ "divider": "分隔線",
13877
+ "paste": "貼上",
13878
+ "pasteAsPlainText": "貼上為純文字"
13838
13879
  }
13839
13880
  };
13840
13881
  exports.default = zhTW;
@@ -13848,3 +13889,4 @@ exports.auto = zhTW.auto;
13848
13889
  exports.components = zhTW.components;
13849
13890
  exports.dashboardPopout = zhTW.dashboardPopout;
13850
13891
  exports.dashboard = zhTW.dashboard;
13892
+ exports.nativeMenu = zhTW.nativeMenu;
package/zh-TW-nested.js CHANGED
@@ -13833,5 +13833,46 @@ export default {
13833
13833
  "sidebar": {
13834
13834
  "label": "Agent 儀表板"
13835
13835
  }
13836
+ },
13837
+ "nativeMenu": {
13838
+ "undo": "復原",
13839
+ "redo": "重做",
13840
+ "cut": "剪下",
13841
+ "copy": "複製",
13842
+ "selectAll": "全選",
13843
+ "minimize": "最小化",
13844
+ "zoom": "縮放",
13845
+ "togglefullscreen": "切換全螢幕",
13846
+ "toggleDevTools": "切換開發者工具",
13847
+ "about": "關於",
13848
+ "services": "服務",
13849
+ "hide": "隱藏",
13850
+ "hideOthers": "隱藏其他",
13851
+ "unhide": "全部顯示",
13852
+ "quit": "結束",
13853
+ "addLink": "新增連結",
13854
+ "format": "格式",
13855
+ "bold": "粗體",
13856
+ "italic": "斜體",
13857
+ "strike": "刪除線",
13858
+ "inlineCode": "行內程式碼",
13859
+ "codeBlock": "程式碼區塊",
13860
+ "quote": "引用",
13861
+ "paragraph": "段落",
13862
+ "bodyText": "本文",
13863
+ "heading1": "標題 1",
13864
+ "heading2": "標題 2",
13865
+ "heading3": "標題 3",
13866
+ "heading4": "標題 4",
13867
+ "heading5": "標題 5",
13868
+ "bulletList": "項目符號清單",
13869
+ "numberedList": "編號清單",
13870
+ "checklist": "核取清單",
13871
+ "insert": "插入",
13872
+ "link": "連結",
13873
+ "image": "圖片",
13874
+ "divider": "分隔線",
13875
+ "paste": "貼上",
13876
+ "pasteAsPlainText": "貼上為純文字"
13836
13877
  }
13837
13878
  };