コンテンツにスキップ
Blume
日本語
Esc
移動開く⌘Jプレビュー
このページの内容

翻訳

blume translate は AI エージェントを使ってロケールを埋めます — 各言語で欠けているページや古くなったページを見つけ、すでにお使いのエージェント CLI で翻訳し、翻訳のずれが生じたときに失敗する CI ゲートを提供します。

i18n を有効にすると、ソースページを編集するたびに、その翻訳は気づかないうちに古くなっていきます。blume translate はこの問題を解決します。各ロケールで欠けているページや古くなっているページを正確に割り出し、ローカルのエージェント CLI を使ってヘッドレスで翻訳し、その内容をコミット対象の台帳に記録します。これにより、次回の実行時にも CI でも、どの翻訳が最新なのかを判断できます。

blume translate --claude
blume translate  3 item(s) · 2 locale(s) · Claude Code

  ✔ docs/guides/install.mdx → fr 24.2s $0.11
  ✔ docs/guides/install.mdx → de 22.8s $0.10
  ✔ meta titles (2) → de 4.1s $0.01

  Translated 3 files into 2 locales · 1 adopted · 14 already up to date · 51.1s · $0.22

仕組み

パイプラインは Blume が管理し、エージェントはテキストの翻訳だけを担当します。Blume は、翻訳が必要なファイルごとに翻訳プロンプトを組み立てます。次に、ファイル・シェル・Web の各ツールを無効にした状態でエージェント CLI をヘッドレスで実行し、応答の構造を検証してから、ターゲットファイルを Blume 自身が書き込みます。使用するエージェントは、--claude の場合は Claude Code--codex の場合は Codex です。Blume は API キーを保持せず、モデルを直接呼び出すこともありません。

検証を通過した書き込みはすべて、プロジェクトルートの blume.translations.json に記録されます。ソースファイルとロケールの組み合わせごとに、翻訳した時点のソースのハッシュが保存されます。このファイルはコミットしてください。 再実行時に「翻訳済み」と「翻訳済みだが、その後ソースが変更された」を区別するためにこのファイルが使われます。CI ゲートもこのファイルがあるからこそ実現できています。

台帳はファイルの処理が 1 つ終わるたびに書き出されます。そのため、長時間の実行を途中で停止 (Ctrl+C) しても、失われるのは処理中だった翻訳だけです。次回の実行では中断したところから再開されます。デフォルトでは 4 ファイルずつ並列に処理されます。マシンの性能とエージェントのレート制限に余裕があれば、--concurrency で並列数を増やせます。

再実行はインクリメンタルに行われます。前回の翻訳以降に変更されていないソースはスキップされるため、1 ページを編集してから blume translate を実行すると、ロケールごとに 1 ページだけが翻訳されます。古くなったページを再翻訳する際は、既存の翻訳をエージェントに提示し、その文体・方言・用語に合わせるよう指示します。そのため、ソースを 1 段落編集した場合、翻訳もゼロから書き直されるのではなく、1 段落分だけが変更されます。

初回の翻訳には手本となる既存の翻訳がないため、ロケールの style であらかじめ方針を決めておきましょう ({ code: "pt", label: "Português", style: "Brazilian Portuguese, informal você" })。この指定はすべての翻訳プロンプトに含まれ、既存の翻訳と食い違う場合は style が優先されます。そのため、再翻訳を重ねるうちに、古いページも設定したスタイルへと近づいていきます。

翻訳対象

  • ページ — デフォルトロケールの .md/.mdx ファイルです。エージェントが翻訳するのは、本文と、読者の目に触れるフロントマターの値 (titledescriptionsidebar.labelsidebar.badgeseo.titleseo.description) だけです。出力先はパーサーの設定に従い、dir では fr/guides/install.mdxdot では guides/install.fr.mdx になります。
  • フォルダーのナビゲーションタイトルdir パーサーでは、各ロケールで必要な meta.ts のタイトルが 1 回の呼び出しでまとめて翻訳されます。生成されるロケールごとの meta.ts には、タイトル以外のキー (orderpagesiconcollapsed) がそのままコピーされるため、各ロケールのサイドバーでも並び順が保たれます。

手動で書いた翻訳はそのまま採用され、上書きされることはありません。翻訳ファイルが存在するのに台帳にエントリがない場合、その翻訳は最新として記録され、変更されずに残ります。これを再翻訳するのは --force を指定した場合だけです。

検証

エージェントに構造を任せることはありません。Blume は書き込む前に各応答をチェックし、ソースを基にファイルを組み立て直します。

  • フロントマターはソースファイルのデータから組み立て直され、翻訳対象の 6 つの値だけが翻訳で置き換えられます。エージェントが追加したキーは削除され、エージェントが削除したキーは復元されます。slugiconorder、日付は、この仕組みによって常にソースと同じ値になります。
  • コードフェンスの数がソースと一致していること、本文が空でないこと、フロントマターをパースできることが必須です。
  • 各見出しには、末尾に [#id] マーカー を付けて、対応するソースの見出しと同じアンカー ID が固定されます。ただし、翻訳側ですでにマーカーが付いている場合は除きます。これにより、#fragment リンクはどの言語でも同じ見出しを指します。見出しは出現順で対応付けられるため、見出しの構造がソースと一致しない翻訳にはマーカーが付きません。

検証に失敗した応答は書き込まれず、その項目は失敗として報告され、実行は次の項目へ進みます。成功した項目はすべて台帳に記録されたまま残るため、再実行すると失敗した項目だけが再試行されます。

CI を失敗させる

blume translate --check は読み取り専用のゲートです。欠けている翻訳と古くなった翻訳をすべて報告し、ずれがあればゼロ以外の終了コードで終了します。エージェントの実行やファイルの書き込みは一切行いません。

blume translate --check           # exit 1 when translations are missing or stale
blume translate --check --json    # machine-readable drift report on stdout
- run: npx blume translate --check

JSON レポートは、blume validate --jsonblume audit --jsonblume eval --json と同じ diagnostics + summary の形式で、ずれはロケールごとにまとめられます。欠けている翻訳や古くなった翻訳は、それぞれエラー診断 (BLUME_TRANSLATE_MISSINGBLUME_TRANSLATE_STALE) として報告されるため、summary.error は終了コードと一致します。手動で作成した (台帳で追跡されていない) 翻訳が原因でゲートが失敗することはありません。

制限事項

  • メタタイトルの翻訳は dir パーサーでのみ利用できます。dot パーサーには、ロケールごとに meta.ts を用意する仕組みがないためです。関数を default export している meta.ts は、警告を出したうえでスキップされます。そのロケール用のファイルは手動で作成してください。
  • リモートのソースや CMS から取得するソースはスキップされます。翻訳を書き込むローカルファイルがないためです。
  • ヘッダーのタブラベルはコンテンツではなく blume.config.ts で定義されています。ローカライズは、ロケールごとのラベルマップ を使って blume.config.ts で行ってください。
  • 翻訳の品質はエージェント次第です。他の人が書いた変更と同じように、出力をレビューしてください。台帳が保証するのは翻訳が最新であることだけで、訳文の自然さまでは保証しません。

フラグ

  • --claude / --codex — 翻訳に使用するエージェント CLI です。どちらか 1 つだけを指定する必要があります (--check 使用時を除く)。
  • --check — ファイルを書き込まずにずれを報告し、ゼロ以外の終了コードで終了します。
  • --concurrency <n> — 並列に実行するエージェントセッションの数です。デフォルトは 4、最大は 16 です。
  • --locale <codes> — 翻訳先のロケールをカンマ区切りで指定します (デフォルトは、デフォルトロケール以外のすべてのロケールです)。
  • --force — 最新のファイルや手動で作成したファイルも含め、すべてを再翻訳します。
  • --timeout <seconds> — ファイルごとのエージェントの制限時間です。デフォルトは 600 です。この上限は応答しなくなったエージェントを止めるためのものなので、大きなページでも時間内に処理を終えられます。
  • --json — どちらのモードでも、レポートを JSON 形式で標準出力に出力します。

最終更新 2026年9月24日

このページは役に立ちましたか?