Files
github-zh-tw/CLAUDE.md
Timmy d23dda03a9 docs: 新增 CLAUDE.md — 給 Claude Code 的架構與不變條件備忘
聚焦三個區塊:
- 開發流程(單檔 UserScript、無 build/test、手動驗證、@version 同步)
- 核心架構(四個關鍵結構、三層替換順序、TreeWalker + MutationObserver + SPA hook)
- 不變條件(整句優先、同詞單譯、搜尋語法 / 使用者內容不可翻、不依賴 React hash class)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 17:37:54 +08:00

69 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## 專案性質
單一檔案 UserScriptScriptCat / 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`。文字節點跳過,但**屬性仍會翻**`<input placeholder>` 會翻,輸入內容不動)。
### 替換流程(`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 拿掉了,白名單會漏 `<th>`/`<td>`/`<relative-time>` 等)。
- 屬性:`querySelectorAll(ATTR_SELECTOR)` — 翻 `data-content` / `aria-label` / `title` / `placeholder`
- SPAMutationObserver`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 分支清單」)→ 補整句進詞庫,利用長詞優先規則蓋過去。