# dsh-zh-tw-ui **繁體中文** | [English](README.md) 把 **DeepSeek Harness(DSH)Web 介面整頁**變成繁體中文(台灣)的插件 —— 包含 DSH 本體、**第三方插件**、以及 DSH 之後才新增的文案。 它不是語言包。它不動 DSH 的語言系統,而是在畫面上把簡體字改寫成繁體字, 所以沒有「字典沒收錄就掉回簡體」的問題。 ``` 設定 → 一般 → 語言:中文(簡體) ← 底層維持簡體 畫面上你看到的:繁體中文(台灣) ← 這個插件在顯示層轉換 ``` --- ## 這個插件解決什麼問題 DSH 內建只有 `zh`(簡體)與 `en`。想在台灣用 DSH,會遇到三種破口: 1. **DSH 本體有簡體字**(沒有繁體語言包時); 2. **第三方插件**(市集、側邊欄、IM、Agent Teams…)各自帶自己的簡體字典,語言包管不到; 3. **DSH 每次更新**都會新增文案,語言包的字典永遠落後一個版本。 本插件處理的是這三件事的**共同根源**:不管文字是誰產生的,都在顯示層轉成繁體。 ## 目標 / 非目標 **目標** | | | |---|---| | G1 | 整頁繁體:DSH 本體 + 第三方插件 + 之後才出現的動態內容 | | G2 | **與 DSH 版本解耦**:DSH 升級不該讓它失效 | | G3 | **不碰 DSH 內部 API**:不註冊字典、不 patch `LocaleRuntime`、不依賴任何 `@deepseek-ai/*` peer 版本,因此永遠不會被 DSH 的相容性檢查擋下,也能與其他語言插件共存 | | G4 | 安全邊界明確:程式碼、編輯器、你輸入的內容**絕對不動** | | G5 | 可逆、可審、可自行調校(開關、覆蓋表、跳過標記) | **非目標** - **不是語言包**:DSH 的「語言」清單不會多出一個選項,也不會改變 DSH 的語言設定。 - **不做簡→繁以外的翻譯**:不翻譯英文,不呼叫任何模型。 - **不改變底層資料**:只改畫面(詳見[已知限制](#已知限制))。 - **不支援 TUI / headless profile**:這是純瀏覽器端(client)插件。 - **不處理 canvas 內繪製的文字、跨來源 iframe**。 --- ## 為什麼不直接用其他繁體化插件 這是本專案存在的理由,所以講清楚。以下是 **2026-10-13** 的實測(資料來源:各套件 npm manifest / repo README,不是轉述)。 | 方案 | 機制 | 蓋到第三方插件 | 與 DSH 0.2.0-rc.2 的關係 | |---|---|---|---| | `@huanlin/dsh-plugin-better-locale` 0.4.3 | 註冊字典 | ✗ | peer 宣告 `^0.1.5-rc.2`(不含 0.2.x)→ 需手動放行例外才載入 | | `@mimateinn/dsh-i18n` 0.2.6 | 字典 + 簡→繁字元轉換回退 | ✓ | peer 宣告 `<0.2.0-0` → 被相容性閘門擋,需例外 | | `dsh-locale-zh-tw`(npm 0.1.1) | patch `LocaleRuntime` 內部 | ✓ | 自述對應 `dsh-client-locale@0.1.1-rc.2` 結構;**失敗會靜默降級** | | `dsh-multi-lang-ui` 0.1.1 | 字典 + 字元表 + DOM 兜底 | ✓ | peer 無上限,過得了閘門(機制上最接近本專案) | | `iceice666/dsh-locale-zh-tw` | 純字典(50 ns / 1691 條) | ✗(作者明說) | — | | **dsh-zh-tw-ui**(本專案) | **純 DOM 轉換** | ✓ | **無 peer 宣告,不碰 DSH API** | 三種既有做法各有結構性問題: 1. **字典型**(better-locale、iceice666)——覆蓋率是「它發布那一刻的上游」。 我實測 better-locale 0.4.3 帶 39 個 namespace,而 DSH 0.2.0-rc.2 註冊了約 49 個核心 namespace,其中 **17 個完全沒有繁體字典**(`pluginManager`、`permission`、 `settings.shell`、`settings.webSearch`、`agent-team`、`voice-input`、`schedule.manager`…)。 更關鍵的是它的回退鏈是 `zh-TW → zh → en`,所以**缺口顯示的是簡體,不是英文** —— 使用者看到的結果就是「裝了但好像沒成功」。 2. **patch 核心型**(`dsh-locale-zh-tw` npm 版)——與 DSH 內部結構強耦合,而且它自己 設計成「任何失敗都靜默降級」:DSH 一改版就可能變成完全沒作用,還不會報錯。 3. **宣告了 peer 範圍的**——只要你的 DSH 版本落在範圍外,DSH 會**直接跳過整個 bundle**, 而且是在啟動時靜默跳過(本機的 `compatibility.json` 就是這種「手動放行例外」的痕跡)。 語言插件本來就與 DSH 版本高度耦合,這個問題只會反覆發生。 **本專案的取捨**:不碰 DSH 任何 API,只在 DOM 上做事。代價是它變成「顯示層轉換」, 換來的是與版本完全解耦、第三方插件也覆蓋、而且壞掉時看得出來(而不是靜默)。 這個取捨的完整後果列在[已知限制](#已知限制)。 > 附註:`dsh-multi-lang-ui` 的做法(字典 + 字元表 + DOM 兜底)在功能上與本專案重疊, > 它也是本專案之外的可行選擇。本專案選擇更小、更單一:**只做 DOM 轉換**、只有一個 > 職責、沒有字典需要跟版、沒有任何 `@deepseek-ai/*` 依賴。 --- ## 運作方式 ``` ┌─ DSH 本體文案(簡體) 畫面文字 ────────┼─ 第三方插件文案(各自簡體) └─ 之後才出現的內容(串流、動態面板) │ ▼ DOM 文字節點 → OpenCC cn→twp(台灣用語)→ 台灣用語覆蓋表 → 寫回 ▲ └─ MutationObserver:新增節點 / 文字變更時再跑一次 ``` - 轉換引擎:**OpenCC `cn → twp`**(簡體 → 繁體台灣用語), 例如 设置→設定、网络→網路、软件→軟體、文件夹→資料夾、服务器→伺服器、 内存→記憶體、屏幕→螢幕、鼠标→滑鼠、保存→儲存、搜索→搜尋、插件→外掛。 - 台灣用語覆蓋表(`src/convert.mjs` 的 `DEFAULT_OVERRIDES`)修正 OpenCC 的漏網之魚: 只讀→唯讀、超時→逾時、反饋→回饋、獲取→取得、許可權→權限。 - 同時把 `` 設為 `zh-Hant-TW`(讓瀏覽器選用台灣字形)。 - 每個文字節點都有記憶快取;不含漢字的字串直接跳過;**只在自己寫入的值不同時才寫**, 並且記住自己寫過的值,避免與 React 互相觸發造成迴圈。 ## 安全邊界:絕對不轉的東西 | 對象 | 行為 | |---|---| | `` `
` `` `` ``、CodeMirror / Monaco / xterm / ace / 語法高亮 | **整棵子樹與屬性都不動** |
| `` `