From d23dda03a9434b1dc49741af06ed170e103b4671 Mon Sep 17 00:00:00 2001 From: Timmy Date: Wed, 22 Apr 2026 17:37:54 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9E=20CLAUDE.md=20?= =?UTF-8?q?=E2=80=94=20=E7=B5=A6=20Claude=20Code=20=E7=9A=84=E6=9E=B6?= =?UTF-8?q?=E6=A7=8B=E8=88=87=E4=B8=8D=E8=AE=8A=E6=A2=9D=E4=BB=B6=E5=82=99?= =?UTF-8?q?=E5=BF=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 聚焦三個區塊: - 開發流程(單檔 UserScript、無 build/test、手動驗證、@version 同步) - 核心架構(四個關鍵結構、三層替換順序、TreeWalker + MutationObserver + SPA hook) - 不變條件(整句優先、同詞單譯、搜尋語法 / 使用者內容不可翻、不依賴 React hash class) Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..3859d9b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,68 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## 專案性質 + +單一檔案 UserScript(ScriptCat / Tampermonkey),把 GitHub 介面翻成台灣繁體中文。全部邏輯在 `github-zh-tw.user.js`,**沒有** package.json、建置腳本、測試套件、lint 設定、相依套件。 + +## 開發流程 + +改 `github-zh-tw.user.js` 後: + +1. **驗證只能手動**:在瀏覽器裝 ScriptCat/Tampermonkey,把整份檔案貼進「新增腳本」,存檔後強制重載 `https://github.com/*` 驗結果。沒有自動化測試可跑。 +2. **發版**:改內容時同時修腳本檔開頭 `@version`(UserScript header 用這個判斷更新)。`DEVELOPMENT.md` 記錄了每個版本的改動脈絡,重大改動順手補一段。 +3. **不要**建立 `package.json` / 加 build 工具 / 加 npm 相依。檔案必須保持能直接貼進 Tampermonkey 就跑。 + +## 核心架構(動一行詞庫前先讀完) + +所有邏輯在 IIFE 內,四個關鍵結構: + +1. **`TRANSLATION_MAP`**(`Map`)— 英→中詞庫,按語意分類排列。建構時會依字串長度排序成 `WORD_BOUNDARY_REGEX`,**長詞優先**匹配。 +2. **`LOWER_MAP`** — 小寫鍵的查表。regex 用 `gi` 旗標(大小寫不敏感)匹配後,以小寫查譯文。 +3. **`SKIP_CONTEXT_SELECTOR`** — 使用者內容脈絡白名單(檔名、commit 訊息、repo 描述、Topics、README、程式碼、Issue/PR 標題、使用者名稱、搜尋框語法…)。`shouldSkipTextAncestor` 用 `el.closest(...)` 判斷祖先是否落在這些 selector。 +4. **`SKIP_TAGS`** — `SCRIPT/STYLE/CODE/PRE/INPUT/TEXTAREA/NOSCRIPT`。文字節點跳過,但**屬性仍會翻**(`` 會翻,輸入內容不動)。 + +### 替換流程(`replaceText` 三層,順序不可交換) + +``` +TIME_AGO_REGEX "3 days ago" → "3 天前" ← 先跑,避免 days 被當詞庫吃掉 +WORD_BOUNDARY_REGEX 詞庫整批替換 ← 長詞優先 +ABBREV_REGEX "62.8k" → "6.3 萬" ← 最後,避開 k/M 在詞庫中撞到 +``` + +### 掃描策略 + +- 文字節點:`TreeWalker(SHOW_TEXT)` 走全部,靠 `shouldSkipTextAncestor` 剔除。**不用** SCAN 白名單(v0.12 拿掉了,白名單會漏 ``/``/`` 等)。 +- 屬性:`querySelectorAll(ATTR_SELECTOR)` — 翻 `data-content` / `aria-label` / `title` / `placeholder`。 +- SPA:MutationObserver(`childList` + `attributes`)+ hook `pushState`/`replaceState` + `popstate` + `turbo:load`/`turbo:render`,所有 trigger 都走同一個 150ms debounce 後做全域 re-scan。 + +## 修改詞庫的不變條件 + +這些規則是踩過坑才定的(`DEVELOPMENT.md` 有血淚史),動之前先確認新需求不會撞到: + +- **整句優先於單字**。要譯 `Active branches` 就加整句,不要靠 `Active` + `branches` 組合(長詞優先 regex 會整句吃掉,否則會出現「Active 分支」這種半翻)。 +- **一個英文詞只能一個翻譯**。因為 `gi` + `LOWER_MAP`,`Open`(tab)和 `opened`(動詞)共用同一譯文。取捨原則:保頻率高的那個;另一個保留英文。 +- **搜尋語法不可翻**。`is:issue state:open` 這類 token 翻掉會破壞搜尋。靠 `[role="searchbox"]` / `[role="combobox"]` / `.pl-c1` 等 skip selector 擋下。加新詞時確認不會污染搜尋框。 +- **使用者內容不可翻**。檔名、commit 訊息、Issue 標題、Repo 描述、Topics、使用者名稱、README、程式碼。遇到誤翻時,**加 skip selector** 而不是從詞庫拔詞。 +- **React class 不可靠**。GitHub 新 UI 的 class 帶 hash(`SearchInput-module__xxx_f5Xpk`)會變。一律用穩定的 `role` / `data-testid` / `data-hovercard-*` / `[href*="/blob/"]` 這類語意屬性。 +- **詞庫條目不要帶結尾標點**。`Search branches...` 結尾 `.` 會讓 `\b` 尾界失敗。詞庫只放 `Search branches`,regex 在 `\b` 前停下自然保留原 `...`。 +- **避免太通用的短詞**。`of`、`Page`、`Showing` 這類會打穿「Member of X」「out of」等片語,不要進詞庫。 + +## 數字格式化(`formatAbbrev`) + +``` +val ≥ 1,000,000 → "X 萬"(≥100 萬整數;否則 1 位小數) +1,000,000 > val ≥ 10,000 → "X.X 萬"(`.0` 去掉) +val < 10,000 → "X,XXX" 千分號 +無 k/M 後綴的純整數 → 不動 +``` + +## 回報問題時要怎麼處理 + +使用者反映「某某沒翻」或「某某誤翻」時,先分類: + +- **沒翻** → 加詞庫。先確認在哪個語意分類、是否該加整句以免半翻。 +- **誤翻使用者內容**(檔名、commit 訊息、使用者名、repo 描述…)→ 加 `SKIP_CONTEXT_SELECTOR`,別動詞庫。用 DevTools 找穩定的 selector(`data-testid` / `role` / `href` pattern)。 +- **誤翻搜尋語法/程式碼** → 加 skip selector,動詞庫不能解。 +- **半翻**(「Active 分支清單」)→ 補整句進詞庫,利用長詞優先規則蓋過去。