AI Workflow · part 7
[Skill] 我的繁中不夠台 — zhtw-mcp 掃 72 篇文章修了 128 處陸用詞
❯ cat --toc
TL;DR
sysprog21/zhtw-mcp(jserv 老師寫的繁中檢查工具)套到 ai-muninn 全部 72 篇繁中文章。三輪掃完修了 128 處陸用詞 / 42 個檔案 / 兩岸用詞命中數從 207 降到 135。但真正的收穫不是這些數字 — 是發現我寫 並行 / 平行 / 文件 / 檔案 都對,寫數據 / 用戶卻預設滑過去。盲點不是「不知道」,是「不會主動懷疑」。
白話版:為什麼一個會中文的人寫不好「台灣中文」?
你打字時,手指其實有一個詞庫。詞庫不是空的 — 是被你看過的東西塞滿的。Bilibili 的科普影片、知乎的技術文、GitHub 上的中文 README,絕大多數是簡體 + 對岸用詞。看多了,即使你寫繁體,「數據」「用戶」「連接」這些詞還是會自動跑到指尖。
你要寫的是「資料」「使用者」「連線」。寫的瞬間你完全知道該寫哪個。但你沒有特別停下來想 — 因為你覺得「我又不是新手,還要自己檢查?」
結果就是,寫完 72 篇文章後,某個檢查工具跑過去,跟你說:你寫了 36 次「數據」、9 次「用戶」、7 次「連接」。整本詞庫滲透進去了,你完全沒發現。
這是「會但不檢」的問題,不是「不會」。解法不是學新詞,是把自我檢查變成寫作流程的一部分。
起因
幾天前(2026-05-02)寫 DGX Spark 量化深度文,我反覆寫了「並發」「高併發」當技術詞 — 直到 Gemini 2.5 Pro 跳出來提醒才意識到那是大陸用語。台灣寫 concurrency 該用「並行」,而大陸的「並行」反而是 parallel — 同一個詞鏡像衝突最容易踩。
那篇單獨修了。但我懷疑全部 72 篇都有類似問題,沒工具能批次掃。
直到看到 sysprog21/zhtw-mcp — jserv 老師寫的(嵌入式 / Linux kernel 圈的台灣老前輩),工具方向不會錯,直接裝來掃。
工具:zhtw-mcp 是什麼
zhtw-mcp 是一個 Rust 寫的繁中檢查工具,落實三個官方標準:
- 重訂標點符號手冊 — 全形標點規則
- 國字標準字體 — 字形變體(裏→裡、着→著)
- 兩岸詞彙正規化 — 來自 OpenCC 的 TWPhrases / TWVariants 資料集 + 自家規則
整套規則 1100+ 詞彙、15 條大小寫規則,全部編成執行檔。可以當命令列跑,也能接 MCP server 給 AI 助理當檢查工具用。
我從原始碼編一份(GitHub releases 還沒發執行檔):
git clone https://github.com/sysprog21/zhtw-mcp ~/Projects/zhtw-mcp
cd ~/Projects/zhtw-mcp
make # 先用 python 下載 OpenCC 資料 → 編執行檔,~50s
裝好的執行檔在 target/release/zhtw-mcp。命令列用法很直觀:
zhtw-mcp lint file.md # 列出問題
zhtw-mcp lint file.md --content-type markdown # 跳過程式碼區塊
zhtw-mcp lint file.md --relaxed # 鬆綁標點 / 文法
zhtw-mcp lint file.md --fix --dry-run # 預覽修法
⚠️ 第一個雷:不能直接用 --fix
我第一個直覺是「掃完直接 --fix 全套搞定」。試了一個檔差點災難:
zhtw-mcp 預設會把 YAML 標頭裡的 "..." 改成 「...」:
# 修前(正常)
description: "完整的本地 AI Agent 架構..."
# 修後(YAML 壞掉)
description: 「完整的本地 AI Agent 架構...」
YAML 解析器認不得「」當作字串包裹符,整個文章顯示失敗。72 篇全跑一輪 = 整個站炸掉。
而且 ai-muninn 風格刻意保留半形混排(中英混排 + 半形標點,讀起來更像程式碼註解,不是正規論文),--fix 會強制把所有半形標點改成全形,寫起來變得拘謹,不是我要的調性。
流程設計:用 Python 精準動刀,不要直接 --fix
最後設計成這樣:
- 掃描階段:用 zhtw-mcp
--format compact --relaxed抓命中列表 - 過濾階段:寫個 Python 只挑
cross_strait(兩岸用詞)規則,其他像標點全跳 - 應用階段:Python 自己做替換,跳過 YAML 標頭 +
```程式碼區塊 + 行內反引號
def split_sections(text):
# 切出標頭、程式碼區塊、內文三塊
...
def fix_text(text):
out_lines = []
for kind, chunk, start in split_sections(text):
for line in chunk:
if kind == 'body':
# 只在內文做兩岸用詞替換
# 還要避開行內反引號裡的內容
...
完整 Python 不貼了(每一輪掃完我都調整詞彙對照表),但邏輯就這三層保護。
三輪結果
第一輪:高頻硬陸用詞(84 處 / 42 檔)
這輪主打「動詞或名詞單詞預設寫成陸版」 — 台灣讀者一眼看到會皺眉的詞:
| 陸用 → 台用 | 命中數 | 為何踩坑 |
|---|---|---|
| 數據 → 資料 | 36 | 最高頻!幾乎每篇技術文都會寫到 data |
| 用戶 → 使用者 | 9 | user 直譯 |
| 連接 → 連線 | 7 | network connection 直譯 |
| 發送 → 傳送 | 5 | send 直譯 |
| 模板 → 範本 | 5 | template 直譯 |
| 導航 → 導覽 | 4 | navigation 直譯 |
| 只讀 → 唯讀 | 4 | readonly |
| 設備 → 裝置 | 3 | device |
| 性能 → 效能 | 2 | performance |
| 卸載 → 解除安裝 | 2 | uninstall |
| 溢出 → 溢位 | 2 | overflow |
| 在線 → 線上 | 2 | online |
| 擴展 → 擴充 | 2 | extension(軟體情境) |
| 緩存 → 快取 | 1 | cache |
這 14 個詞應該進我的繁中盲點記憶清單 — 之前只記了「並發 / 複現 / 矽片 / 內存」5 個,這次新發現 14 個高頻盲點。
第二輪:邊界詞(36 處)
這輪只動兩個我自己同意的邊界詞:
優化→最佳化(30 處)算法→演算法(6 處)
這兩個詞兩岸通用,「優化」「算法」在台灣軟體圈也廣用,沒改也不算錯。但教育部偏好「最佳化」「演算法」,檢查工具也會標起來。所以這輪是「作者判斷」而不是「自動修」 — 想要更貼教育部標準才動。
算法 → 演算法 有個正規表達式陷阱:不能用單純 replace,因為「演算法」本身包含「算法」這段子字串,會變成「演演算法」。要用 negative lookbehind:
pattern = re.compile(r'(?<!演)算法')
剩下沒動的邊界詞:
- 通過 / 透過 — 兩岸並存
- 前綴 / 字首 — 技術情境通用
- 分配 / 配置 — 程式記憶體情境通用
- 版本號 / 版本號碼 — 科技文「版本號」普及
- 消息 / 訊息 — 高風險!「好消息」「收到消息」是台灣慣用語(指新聞 / 資訊,不是 message),無腦替換會變「好訊息」、「收到訊息」 — 直接破壞語意。這條我刻意拒絕了。
第三輪:同字不同義(8 處)
這輪掃「兩岸字一樣但語意衝突」最危險的那層:
| 英文概念 | 大陸用 | 台灣用 | 注意 |
|---|---|---|---|
| concurrency | 並發 | 並行 | 大陸的「並行」其實是 parallel,完全不同概念 |
| parallel | 並行 | 平行 | 同上,語意鏡像衝突 |
| process(作業系統) | 進程 | 行程 / 程序 | 台灣「進程」是「進步」,不是作業系統的 process |
| file | 文件 | 檔案 | 兩岸都用「文件」,但台灣指 document |
| document | 文檔 | 文件 | 鏡像衝突 |
| render | 渲染 | 算繪 | 台灣「渲染」原意是「誇張」(繪畫術語) |
| traverse | 遍歷 | 走訪 | 台灣「遍歷」是遍歷理論(Ergodic theory)專用 |
結果意外乾淨 — 我寫得對的部分:
並行9 處,全部當「concurrent」用,正確平行2 處,正確當「parallel」用文件57 處,全部當「document」用(file 我都寫「檔案」)檔案115 處,正確當「file」用行程4 處,「京都行程」「旅行行程」這種行程義進程1 處是誤判(「鑽進程式碼裡」是子字串切錯)
寫錯的只有兩個:
並發7 處(「並發負載」「理論並發 7.48x」)→ 改成並行遍歷1 處(「遍歷 request.messages」)→ 改成走訪
渲染 4 處我刻意保留 — 軟體情境下廣用,連 Apple 台灣官方文件都用「渲染」,業界比教育部偏好的「算繪」更普及。
真正的收穫:三層盲點不對稱
修完 128 處後,我看著三輪命中分布想了 5 分鐘:
| 層 | 命中數 | 分布特徵 |
|---|---|---|
| 第一層(高頻陸用詞) | 84 | 大宗 — 技術名詞單詞直譯 |
| 第二層(邊界詞) | 36 | 中等 — 兩岸並存,作者判斷 |
| 第三層(同字不同義) | 8 | 最少 — 我反而寫得對 |
最危險的第三層(語意衝突,寫錯讀者會誤解)反而文章最乾淨。最不危險的第一層(讀者看到只是覺得「不夠台」)反而寫錯最多。
為什麼?
寫到「並行」「平行」這種詞時,我的腦會自動觸發「等等,這字兩邊意思不一樣」的警報 — 因為我意識到這是衝突詞。但寫到「數據」「用戶」「連接」時,警報不響 — 我覺得這只是「比較中性的詞」。
所以我的盲點不是「不知道台灣怎麼說」(我寫對了 9 次「並行」、115 次「檔案」、57 次「文件 = document」)。是「碰到陸用詞時預設不會主動懷疑」。對「危險詞」我會自我檢查,對「無感詞」我會直譯滑過去。
這跟「學更多台灣詞」沒關係 — 我已經知道。問題是自我檢查的觸發機制太敏感,只對少數詞響鈴。
解法:把自我檢查變成流程
知道盲點不對稱以後,解法很清楚:不能靠意志力把每個詞都檢查一遍,要靠檢查工具補開警報蓋不住的那些詞。
寫文前的自動檢查
我把 zhtw-mcp 接進寫文流程:
# alias in ~/.zshrc
zhtw_check() {
~/Projects/zhtw-mcp/target/release/zhtw-mcp lint "$1" \
--content-type markdown --relaxed --format compact \
| grep -E ':(W|E):cross_strait:'
}
# 寫完文章 publish 前先跑
zhtw_check content/blog/zh-TW/new-article.mdx
只看 cross_strait,跳過 punctuation / translationese — 跟我的風格習慣對齊。
把命中詞收進記憶清單
把這次發現的 14 個高頻盲點 + 7 個邊界詞 + 2 個同字不同義詞全進我的繁中盲點記憶清單。下次寫文 Claude 開新對話就會載入這張表,寫到陸用詞時主動提醒。
兩層審查疊加
我另外有一條 Codex 雙語審查流程在跑(寫完文章丟給 Codex 做敘事層的繁中校稿)。跟 zhtw-mcp 是不同顆粒度的疊加 — Codex 抓敘事腔(整段讀起來像不像台灣人寫的),zhtw-mcp 抓詞彙層的滲透(單字寫對了沒)。
教戰守則
寫繁中技術文、想避開陸用詞的人,五點實戰建議:
- 不要相信自己的「台灣感」 — 我寫文 6 個月,以為繁中寫得很乾淨,結果檢查工具一掃 207 處命中。對自己的母語直覺打折。
- 裝 zhtw-mcp —
cargo install五分鐘搞定。一個執行檔、不用 API key、Apache 2.0 授權。 - 不要直接跑
--fix全文 — 它會把 YAML 標頭裡的"..."改成「...」破壞 parser,還會強制所有標點變全形。寫個 Python 自己控制,只動內文的兩岸用詞。 - 同字不同義那層反而不是你的問題 — 並行/平行/文件/檔案這種衝突詞,你自己寫的時候會多想一秒。真正的盲點是高頻單詞(數據/用戶/連接/發送/模板...)— 這些詞看起來「中性」,警報不響。
- 建立「該主動懷疑」的詞庫 — 檢查工具掃過的命中詞收進記憶清單,下次寫文主動規避,而不是事後修。
不做什麼
- 不修翻譯腔的 456 條命中(誤判率高,需要逐篇判斷,不適合批次處理)
- 不改半形標點(ai-muninn 風格選擇 — 半形混排讓中英技術詞讀起來更像程式碼註解)
- 不改「渲染」這類業界廣用詞(教育部偏好「算繪」但連 Apple 台灣官方文件都用「渲染」,改成教育部形式反而拗口)
P.S. 連這篇文章也被自己抓出 ~50 個命中
寫完文章我順手對自己跑檢查工具,跳出 ~50 個兩岸用詞命中:數據 7 處、用戶 6 處、並發 6 處、遍歷 4 處...
但全部是引用,不是作者寫錯。第一輪那張「數據 → 資料(36 處)」表格,檢查工具在「數據」上跳警告;邊界詞那段我寫「『好消息』『收到消息』是台灣慣用語」,檢查工具在「消息」上跳警告;同字不同義那段「『進程』=『進步』」,在「進程」上跳警告。
如果我此時無腦 --fix,這篇講「不要無腦 --fix」的文章會被自己毀掉:
- 表格「數據 → 資料」會變「資料 → 資料」 — 同字兩邊,讀者完全看不懂在示範什麼
- 「『好消息』是慣用語」會變「『好訊息』是慣用語」 — 本來在解釋為什麼這慣用語不該改,結果自己改了
這正好是本篇核心論點的收尾 — 檢查工具的結果永遠需要人工檢視,引用情境是詞彙規則最常見的合法誤判。精準動刀的流程之所以勝過全文 --fix,不只是 YAML 標頭的保護,更是因為檢查規則沒有語境理解能力,人類讀者要做最後一道把關。
知道了之後,流程多一條:不只看命中數,看每個命中周圍兩行。我的 zhtw-mcp grep 改成 grep -B 1 -A 1,引用情境一眼就分得出來。
相關閱讀
- Part 5 —
/slim自動瘦身設定檔 — 上一篇,設定檔健檢 - Part 6 — Token 燒太快?8 招讓 session 撐 10 倍久
- LLM 深水區 Part 2 — TurboQuant KV Cache Benchmark — 同期掃過的硬技術文之一
- sysprog21/zhtw-mcp on GitHub
- 《重訂標點符號手冊》修訂版(教育部標點規範)
常見問題
- zhtw-mcp 是什麼?跟 OpenCC 差在哪?
- zhtw-mcp 是 [sysprog21/jserv](https://github.com/sysprog21/zhtw-mcp) 寫的繁中檢查工具,把 1100+ 詞彙規則 + 教育部標準字體 + 兩岸用詞對照表編成 Rust 執行檔。OpenCC 只做字元/詞彙層的簡轉繁,zhtw-mcp 多做語境敏感的「兩岸同字不同義」、翻譯腔偵測、半形/全形標點規則。一句話:OpenCC 把字面變繁體,zhtw-mcp 把寫法變台灣。
- 為什麼不能直接用 zhtw-mcp 的 --fix?
- 因為它會把 YAML 標頭裡的 `"..."` 字串改成 `「...」`,直接破壞 YAML 解析,文章顯示失敗。--fix 還會強制改 ai-muninn 風格刻意保留的半形混排。實務上要寫個 Python 自己控制:跳過標頭跟程式碼區塊,只在內文套兩岸用詞規則。
- 寫繁中最容易踩的陸用詞是哪幾個?
- 從 ai-muninn 72 篇文章實測,最高頻三組是:**數據(36 處)→ 資料**、**用戶(9)→ 使用者**、**連接(7)→ 連線**。這些都是技術文常用詞,我寫作時預設會直譯英文 data/user/connect 過去,不會主動懷疑。同字不同義那層反而寫得對(並行/平行/文件/檔案)— 因為這些字「看起來像陸用詞」,我反而會多想一秒。
- 檢查工具報的「翻譯腔」是什麼?要修嗎?
- 翻譯腔 = AI 寫作痕跡偵測,例如破折號用太多、否定平行句式(『不是 X、是 Y』)、語氣詞密度過高。本次只看兩岸用詞不碰翻譯腔,因為誤判率高、很多是作者風格選擇。要動的話建議逐篇判斷,不適合批次修。