從即時翻譯到真正的英文內容, 為什麼做 Content-I18n
我的 Blog 原本已經有 cmpt-translate, 也就是頁面可以即時翻譯成英文
但在多倫多 coffee chat 的時候, 有人直接建議我: 如果 Blog 要當作品集的一部分, 預設語言應該是英文
這句話點到的不是功能問題, 而是內容主體問題
即時翻譯可以把頁面轉成另一種語言, 但它不等於我真的有英文內容, 也不等於我有一套可以長期維護英文文章的 workflow
所以我開始做 content-i18n
目標很明確: 把 Blog 從 “中文為主, 英文靠即時翻譯” 變成真的有英文文章可以維護
問題不是翻得更快
如果只是要先拿到英文草稿, 方法很多:
- 直接貼到 AI Chat
- 用 Google Translate 或 DeepL
- call translation API 產生初稿
- 讓 agent 幫忙改成英文
這些方法都能用, 速度也快
但技術 Blog 不是只有 prose
一篇文章通常會混在一起:
- heading 和 section 順序
- code block
- inline command
- config key
- product name
- error string
- table
- blockquote
- argument flow
我要保留的是同一篇文章, 不是只把文字換成另一種語言
所以核心規則很簡單:
- same article
- different language only
Fidelity-first 的意思
fidelity-first 不是逐字翻譯, 也不是讓英文變得很僵
它處理的是一個取捨: 當 “讀起來更順” 和 “保住原文” 開始衝突時, workflow 要先保哪一邊
我的答案是先保原文
所以 content-i18n 會檢查這些東西:
- heading hierarchy
- section order
- paragraph coverage
- list structure
- table structure
- code block
- technical inline literal
- link 和 reference
- argument flow
- conclusion scope
如果英文讀起來很順, 但少了一個 caveat, 壓掉一個例子, 或把 command 改成另一種說法, 那就不是我要的結果
這也是為什麼我後來把 translation 當成 validation problem, 而不是只看 generation quality
即時翻譯不夠的地方
最麻煩的不是模型翻得完全錯
更常見的是看起來差不多, 但內容慢慢 drift
我遇過的問題包括:
- opening paragraph 被翻得比原文更曲折, 甚至多出原文沒有的內容
- heading 變得像文章標題, 但原本要強調的點不見了
- code block 還在, 但 surrounding sentence 意思偏掉
- 某一段被 AI 覺得重複, 就自己幫我精簡
- 英文稿裡還殘留中文
這些問題不一定會讓文章看起來壞掉, 但會讓文章慢慢變成另一篇
所以我不想要每次都靠 copy-paste, 再自己從頭檢查一次
Workflow 設計
最後我需要的是 workflow, 不是一個 prompt
|
|
每一步都有自己的責任
prepare
prepare 不只是讀 source file
它在定義 translation unit:
- source path
- target path
- structure fingerprint
- glossary
- style pack
- prompt context
- target metadata
這一步會影響輸出穩定性
如果每次給 AI 或 provider 的 context 都不一樣, target 很難穩定
write target
write target 是產生草稿
草稿可以來自人, AI model, 或 provider-backed workflow
但 target file 存在不代表完成
草稿永遠只是草稿
review
review 是整條 workflow 最重要的一步
它不能只看英文順不順或文法對不對
它要檢查:
- heading 有沒有對齊
- blockquote 和 table 還在不在
- code block 有沒有被改
- technical inline literal 有沒有 drift
- 應該翻譯的地方還有沒有 source language
對知識管理內容來說, 這種 review 比單純看文法更有用
sync-status
sync-status 會把 completion 寫成正式狀態
沒有這一步, queue 很難分辨:
- 只是有人改過的草稿
- 還是真的 review 過, 且仍然跟 source 同步的 translation
Queue state
Queue state 讓這個工具開始不像一堆 command, 而比較像一個 system
content-i18n 用三種 state:
completedstalemissing
這些 state 不是手動標記, 而是從這些資料推導:
- source discovery
- expected target file
- source hash
- translation status
翻譯不是一次性任務
今天 complete 的 target, 只要 source 改了, 明天就可能 stale
我的 Blog 文章本來就會一直修: 改句子, 補段落, 調例子, 修結構
所以 workflow 不能只問有沒有翻過
它還要問現在還有沒有 match source
Completion rule
Completion 不能模糊
我最後把規則定成這樣:
- review 或 validation 要 pass
- 應該翻譯的地方不能殘留 source language
sync-status要成功
這比 “看起來差不多” 窄很多
我常遇到 structure 看起來沒問題, 但 heading, metadata, inline note 裡還殘留沒翻完整的內容
這種東西如果不擋, 很容易混進正式內容
sync-status 的價值就在這裡
它把 completion 從主觀感覺, 變成系統可以推導和追蹤的狀態
為什麼做成 standalone tool
如果只是翻譯 Blog, 幾支 script 也能用
但後來我需要這些東西:
- queue model
- provider option
- repeatable prepare / review / sync step
- stricter validation
- MCP interface 給 agent 用
這些需求一多, script 就不夠清楚
做成 standalone tool 之後, boundary 比較乾淨:
- config 留在 consumer repo
- provider secret 留在 repo 外
- workflow 邏輯留在工具裡
- site routing 和 theme 不跟 translation engine 混在一起
這樣它才比較像可以長期維護的工具, 不是只在 Blog 裡湊合著用的 script
最後整理
content-i18n 一開始要解的問題很單純: 讓 Blog 從 runtime translation, 變成真的有英文內容可以維護
但實作後, 問題變成:
- 如何保持同一篇文章
- 哪些東西必須被保住
- 什麼才算真的完成
- queue 要怎麼追蹤 translation state
最後我需要的不是一次產生英文稿, 而是一套可以長期維護英文內容的 workflow