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

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

```bash
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
```

## 仕組み [#how-it-works]

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

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

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

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

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

## 翻訳対象 [#what-gets-translated]

- **ページ** — デフォルトロケールの `.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`](/docs/content/meta) のタイトルが 1 回の呼び出しでまとめて翻訳されます。生成されるロケールごとの `meta.ts` には、タイトル以外のキー (`order`、`pages`、`icon`、`collapsed`) がそのままコピーされるため、各ロケールのサイドバーでも並び順が保たれます。

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

## 検証 [#validation]

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

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

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

## CI を失敗させる [#failing-ci]

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

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

```yaml .github/workflows/translations.yml
- run: npx blume translate --check
```

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

## 制限事項 [#limitations]

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

## フラグ [#flags]

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