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

4.9 KiB
Raw Permalink Blame History

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. 發版:改內容時同時修腳本檔開頭 @versionUserScript header 用這個判斷更新)。DEVELOPMENT.md 記錄了每個版本的改動脈絡,重大改動順手補一段。
  3. 不要建立 package.json / 加 build 工具 / 加 npm 相依。檔案必須保持能直接貼進 Tampermonkey 就跑。

核心架構(動一行詞庫前先讀完)

所有邏輯在 IIFE 內,四個關鍵結構:

  1. TRANSLATION_MAPMap)— 英→中詞庫,按語意分類排列。建構時會依字串長度排序成 WORD_BOUNDARY_REGEX長詞優先匹配。
  2. LOWER_MAP — 小寫鍵的查表。regex 用 gi 旗標(大小寫不敏感)匹配後,以小寫查譯文。
  3. SKIP_CONTEXT_SELECTOR — 使用者內容脈絡白名單檔名、commit 訊息、repo 描述、Topics、README、程式碼、Issue/PR 標題、使用者名稱、搜尋框語法…)。shouldSkipTextAncestorel.closest(...) 判斷祖先是否落在這些 selector。
  4. SKIP_TAGSSCRIPT/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
  • SPAMutationObserverchildList + attributes+ hook pushState/replaceState + popstate + turbo:load/turbo:render,所有 trigger 都走同一個 150ms debounce 後做全域 re-scan。

修改詞庫的不變條件

這些規則是踩過坑才定的(DEVELOPMENT.md 有血淚史),動之前先確認新需求不會撞到:

  • 整句優先於單字。要譯 Active branches 就加整句,不要靠 Active + branches 組合(長詞優先 regex 會整句吃掉否則會出現「Active 分支」這種半翻)。
  • 一個英文詞只能一個翻譯。因為 gi + LOWER_MAPOpentabopened(動詞)共用同一譯文。取捨原則:保頻率高的那個;另一個保留英文。
  • 搜尋語法不可翻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 帶 hashSearchInput-module__xxx_f5Xpk)會變。一律用穩定的 role / data-testid / data-hovercard-* / [href*="/blob/"] 這類語意屬性。
  • 詞庫條目不要帶結尾標點Search branches... 結尾 . 會讓 \b 尾界失敗。詞庫只放 Search branchesregex 在 \b 前停下自然保留原 ...
  • 避免太通用的短詞ofPageShowing 這類會打穿「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 找穩定的 selectordata-testid / role / href pattern
  • 誤翻搜尋語法/程式碼 → 加 skip selector動詞庫不能解。
  • 半翻「Active 分支清單」)→ 補整句進詞庫,利用長詞優先規則蓋過去。