翻訳
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 は翻訳プロンプトを組み立て、ファイル・シェル・ウェブの各ツールを無効化した状態でエージェント CLI をヘッドレスに実行し、応答の構造を検証したうえで、ターゲットファイルを自ら書き込みます。--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ファイル。エージェントは本文と、人間が目にするフロントマターの値(title、description、sidebar.label、sidebar.badge、seo.title、seo.description)のみを翻訳します。出力先はパーサーに従います。dirではfr/guides/install.mdx、dotではguides/install.fr.mdxです。 - フォルダーのナビゲーションタイトル —
dirパーサーでは、各ロケールで必要なmeta.tsのタイトルが 1 回のバッチ呼び出しで翻訳され、生成されるロケールごとのmeta.tsはその他のキー(order、pages、icon、collapsed)をそのままコピーするため、そのロケールのサイドバーは並び順を保ちます。
手作業で書いた翻訳は採用され、上書きされることはありません。翻訳が存在するのに台帳エントリがない場合は、最新としてスタンプされ、そのまま残されます。再翻訳するのは --force のときだけです。
検証
構造の面でエージェントが信頼されることはありません。書き込む前に、Blume は各応答をチェックし、ソースからファイルを再構築します。
- フロントマターはソースファイルのデータから再構築され、翻訳可能な 6 つの値だけが上書きされます。エージェントが勝手に作ったキーは破棄され、削除されたキーは復元され、
slug、icon、order、および日付は構造上ソースそのままになります。 - コードフェンスの数がソースと一致していること、本文が空でないこと、フロントマターがパースできることが必要です。
検証に失敗した応答は何も書き込みません。その項目は失敗として報告され、実行は次へ進みます。成功したものはすべて台帳にスタンプされたまま残るため、再実行では失敗分だけが再試行されます。
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 --json、blume audit --json、blume eval --json と同じ diagnostics + summary の形式で、ずれはロケールごとにグループ化されます。手作業で書かれた(追跡対象外の)翻訳がゲートを失敗させることはありません。
制限事項
- メタタイトルの翻訳は
dirパーサー専用です。dotパーサーにはロケールごとのmeta.tsの仕組みがありません。関数をデフォルトエクスポートしているmeta.tsは警告付きでスキップされるため、そのロケール用のファイルは手作業で書いてください。 - リモートおよび CMS 由来のソースはスキップされます。翻訳を書き込むローカルファイルが存在しないためです。
- ヘッダーのタブラベルはコンテンツではなく
blume.config.tsにあります。ロケールごとのラベルマップでそちらをローカライズしてください。 - 翻訳の品質はエージェント次第です。他のコントリビューションと同じように出力をレビューしてください。台帳が保証するのは鮮度だけであり、流暢さではありません。
フラグ
--claude/--codex— どのエージェント CLI で翻訳するか。ちょうど 1 つの指定が必須です(--checkの場合を除く)。--check— ずれを報告して非ゼロで終了します。何も書き込みません。--concurrency <n>— 並列に実行するエージェントセッション数。デフォルトは4、最大は16です。--locale <codes>— カンマ区切りのターゲットロケール(デフォルトはデフォルト以外のすべてのロケール)。--force— 最新のファイルや手作業で書かれたファイルも含め、すべてを再翻訳します。--timeout <seconds>— ファイルごとのエージェントの時間制限。デフォルトは600です。この上限はハングしたエージェントを検出するためのもので、大きなページでも完了する余裕があります。--json— どちらのモードでも、レポートを JSON として標準出力に出力します。