Topics

放棄Google翻譯API,改用LLM翻譯的故事 ― 使用Claude API + R2差分快取實現多語言化

  • column

之前,我寫過一篇用 Google 翻譯 API 對 Astro SSG 網站進行多語言化的文章。這是一種使用 Google Cloud Translation API、在構建後將靜態 HTML 翻譯以生成各語言版本的方法。作為控制成本的簡易多語言化方案,它的實用性是足夠的。

不過,運作了一段時間後,在 SEO 和翻譯品質兩個方面都出現了一些令人在意的問題。關於「為什麼要放棄 Google 翻譯」的討論,請參閱另一篇文章。

文章:將機器翻譯從 Google 翻譯遷移到 Claude API

本篇文章是關於「那麼實際上是怎麼重新製作的呢」的實作說明。我們將引擎從 Google 翻譯改為 LLM(Claude API),同時也一併消除了上次遺留下來的手工操作工作。

在構建時用 LLM 翻譯,差分快取存放在 R2

基本方針與上次相同,翻譯在構建時(伺服器端)完成。不會從瀏覽器呼叫 Claude API。不同之處在於翻譯引擎和快取存放位置。

構建流程是這樣的。

npm run build
  ├── fetch-microcms   (microCMSから記事データ取得)
  ├── astro build      (日本語HTMLを生成 → dist/)
  ├── translate        (各ロケールのHTMLを生成 → dist/{locale}/)
  └── update-xml       (sitemap更新)

translate 的內容(translate-html-llm.mjs)做的事情大致上是按照這個順序的。

  1. 從 Cloudflare R2 下載翻譯快取(單一的 JSON 檔案)
  2. 使用 cheerio 讀取 dist/ 目錄下的各個 HTML 檔案,並提取需要翻譯的文字
  3. 如果快取中有,就使用該快取;沒有的部分才提交到 Claude API
  4. 使用翻譯結果替換文字,並寫入到 dist/{locale}/
  5. 將新翻譯的內容合併到快取中,並上傳到 R2

重點在於「只翻譯變更的部分」的差異翻譯,以及將該快取放置在 R2 上這兩個方面。

① 如何自然地處理跨越內嵌標籤的翻譯

這次最想改善的就是這一點。

例如,假設本文中有像這樣的 HTML。

<p>私たちは<strong>ウェブアクセシビリティ</strong>を重視しています</p>

如果按照一般的翻譯方式處理,我們 / 重視網路無障礙 / 的理念 這三個片段會被分別翻譯。由於日語和英語的語序不同,當將翻譯後的片段放回原本的位置時,<strong>作用的位置可能會出現偏差,或者整句話本身就變得不自然。內嵌標籤越多的句子,崩壞的情況就越嚴重。這是舊系統最令人不滿的地方。

改善方法分為以下兩個步驟。

第一:以塊級元素為單位進行分塊。翻譯的最小單位不是「標籤之間」,而是將p、h1~h6、li、td、blockquote等塊級元素的內容(innerHTML)作為整體。不分割句子。

第二:將內聯標籤置換為標記,將整個文本作為一個翻譯單位進行傳輸。塊級內容中的<strong>或<a>暫時置換為...這樣的標記。

私たちは[[T1]]ウェブアクセシビリティ[[/T1]]を重視しています

我們指示語言模型:「這是一個句子。自然地翻譯它,並可以在應該強調的詞上重新附加相同的標記。標記位置可以根據譯文的詞序移動。」翻譯返回後,將標記還原為原始的<strong><strong>或<a href="..."><a href="...">。屬性(如href或class)保持不變。

這樣一來,<strong>在英文版本中也能正確地修飾單詞,句子也變得自然了。

② 差分翻譯與 R2 快取的設計

如果每次都翻譯所有內容,再多的預算也不夠。之前也有使用translate-cache.json快取,但這次我們重新檢視了快取鍵的生成方式和儲存位置。

修改提示詞後,重新生成翻譯的機制

快取的鍵是由「原始日文 + 語言代碼 + 翻譯提示詞內容」組合產生的。這樣一來,如果原始日文改變,只有那個條目會被視為「快取中沒有」並重新翻譯;如果改變翻譯指示或用語政策(提示詞),所有條目都會自動被視為「快取中沒有」並重新翻譯。

目的是防止「改進提示詞後,舊的翻譯仍然保留在快取中」的問題。實際上,我們會將這些組合用sha256進行雜湊處理,將產生的字符串作為鍵。

快取的結構是這樣的。

{"<sha256のキー>":{"value":"翻訳結果(マーカー込み)","locale":"en","model":"claude-haiku-4-5-20251001","translatedAt":"2026-06-12T..."}}

將快取放在 R2 上,消除了手動作業

這是前次遺留工作的補救。

前次我們是用儲存庫內的 JSON 檔案來管理快取。因此,當在 CMS 中新增文章並透過部署 Webhook 觸發構建時,伺服器只能看到 Git 上的舊快取。無奈之下,我們只好遵循「新增文章後在本地端構建,然後將更新後的快取檔案 push 到 Git」的運作規則。

這次我們將快取放在 Cloudflare R2 上的單一 JSON blob。每次構建時從 R2 獲取,完成後寫回。這樣一來,即使透過 Webhook 觸發的構建也能使快取持久化,本地端構建 → push 的手動作業完全消除了。只要新增文章並 push,增加的部分就會被翻譯,快取也會自動更新。

翻譯優先順序

譯語的偏差(公司名稱 Liberogic 的表記不一致等)在前次也是個難題。這次我們用 4 個階段來處理。

  1. 手動覆蓋(data-i18n-key) ― HTML 側附加 data-i18n-key 的元素會用預先準備好的手寫譯文固定。不交給 LLM 也不交給辭書,能達到「這個地方一定要用這個譯法」的效果。
  2. 用語辭書(glossary) ― 導覽或頁面標題這類重複出現的固定標籤,用 JSON 辭書固定譯語。修改辭書後重新構建即可立即反映。
  3. R2 快取 ― 上述兩者都沒有的話就查看快取。
  4. Claude API ― 只有以上都沒有的內容,最後才送給 LLM。

文中出現的術語統一無法用針對性的字典完全涵蓋(不支援部分比對),因此我們透過系統提示詞中的術語提示來寬鬆地保持一致。

與 LLM 的「習性」共存

機器翻譯輸出錯誤的譯文不是第一次,但 LLM 有其獨特的習性。我將介紹在實際運用中發現的幾個問題。

  • 技術性的文本整句保留為英文。因為在「不翻譯的術語」清單(如 API、React、Vue)上過度適用,有時會將整個句子以英文的形式返回。我們透過在使用者提示詞中強調「必須以目標語言輸出」來處理。
  • 標記位置的語義發生逆轉。對應該強調的詞判斷錯誤,導致 <strong>標記套用的範圍不當。只要刪除該條目並重新翻譯通常就能解決。
  • CJK 語言的回應在中途被截斷。漢字每個字的 Token 消耗量較大,一次投遞過多內容會導致輸出達到上限,JSON 檔案毀損。我們透過提高 max_tokens 和減少每批次的件數來處理。
  • 字面值中的 和 CJK 日期格式錯亂。改行以字串 的形式混入,或 2026 年 05 月 22 日 般出現多餘空格。這些都透過後處理指令碼統一清理。

一個有效的運用心得是:逐一刪除有問題的項目並重新翻譯,成功率最高。嘗試一次修正多個問題時,LLM 傾向於以相同的方式對相同的結構進行相同的誤判。反而是欲速則不達。

成本相關的考量

我們統一使用 Claude Haiku 4.5 引擎。採取成本優先的方針,若品質出現問題則優先透過提示詞和字典進行改善。系統提示詞啟用 prompt caching,壓縮每次相同固定部分的成本。

實際成本大致如下。

內容

成本

單一語言的首次完整翻譯

約 $2.5~3

所有語言的首次完整翻譯

約 $20

常規部署(僅快取命中)

幾乎 $0

新增一篇文章(少量翻譯)

約 $0.01

日常的部署幾乎免費,新增文章也只需1元到數元。雖然初期的重新開發需要一筆較大的費用,但度過這個階段後,營運成本反而比以前更輕了。

總結

從Google翻譯改用LLM翻譯,營運成本沒有大幅增加,翻譯品質卻大幅提升。

LLM並不是完全自動且完美無缺的。我們仍需持續進行耐心的微調工作,找出並消除各種特性問題。不過,由於調整的地點集中在提示詞和字典這些容易理解的位置上,改進的迴圈變得更容易推進了。

本文作者

從 DTP 跨足 Web 世界,轉眼間便掌握了標記語言、frontend 開發、專案指導,以及 accessibility 等各項技能——是名真正的「技術高人」。自 Liberogic 創立初期便展現多才多藝的能力,如今儼然成為公司內的活字典。最近正沉迷於利用 AI 提示詞探索「accessibility 對應能否更多依靠 AI?」的效率化研究。技術與思維都在不斷進化中。

二俣 歩

IAAP 認證網頁無障礙專家(WAS)/ 標記語言工程師 / Frontend 工程師 / 網頁總監

查看此員工的文章

信心十足的團隊體制與迅速的應對能力是我們的優勢

Liberogic 擁有經驗豐富的人員積極推進專案,因而獲得客戶的高度評價。
我們恰當地安排專案經理和總監,致力於順利推進整個專案。 我們避免不必要的全面投入而導致成本增加,而是採用適材適所配置資源的方式,因此在業務把握到估價制作與提交的速度上也備受好評。

※ 請注意,我們不積極進行 SES 形式的駐場業務。

Slack、Teams、Redmine、Backlog、Asana、Jira、Notion、Google Workspace、Zoom、Webex 等幾乎所有主要的專案管理工具和聊天工具都可供您使用。

請諮詢我們解決您的網站問題。

案例分析