# General Translation Knowledge Base: Markdown と MDX の構文を壊さずに翻訳するには？
URL: https://generaltranslation.com/ja/kb/translate-markdown-files.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 実行可能なコード、インポート文、JSX コンポーネント名、機械が参照する識別子はそのまま残し、読者向けのテキストだけを翻訳します。General Translation は Markdown と MDX を直接処理でき、表示テキストを持つ props やフロントマターのタイトルも翻訳対象に含めます。ドキュメントが更新されても、一致する既存の翻訳を再利用します。公開前には、ローカライズされたファイルをレビューし、サイトのビルドを実行してください。
Category: 翻訳
Last updated: 2026-10-30
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

Markdown ファイルでは、本文と技術的な構文が混在しています。MDX ではさらに、`import` 行、JSX コンポーネント、`{expressions}` によって JavaScript が入り込み、これらは翻訳後もコンパイラが解析できる状態でなければなりません。翻訳を始める前に、どのフィールドが表示テキストを持つのかを見極めておきましょう。たとえば、コンポーネントの `title` は翻訳が必要になることがありますが、`id` は変更してはいけません。

## Video

The video is narrated in English, with English captions.

[How do I translate Markdown and MDX without breaking syntax?](https://caxecubb9c64cezv.public.blob.vercel-storage.com/films/kb-translate-markdown-files.mp4) (48 秒)

Translate prose, image alt text, frontmatter titles and descriptions, and display-text component props. Keep code blocks, inline code, imports, JSX component names, frontmatter keys, and link URLs unchanged, quote translated YAML values, then run your site's build. With General Translation, add an mdx or md entry under files in `gt.config.json` and run `npx gt translate`.

## 汎用翻訳ツールに Markdown を通すと何が壊れるか

ファイルをプレーンテキストとして扱う翻訳ツールは、その内容をすべて自然言語とみなして翻訳します。確認すべき不具合は次のとおりです。

* **コードブロックとインラインコード。** コマンドや識別子まで翻訳され、`npm install` が `npm installer` になって返ってくることがあります。
* **リンクの URL とアンカー。** リンク内のスラッグや `#fragment` が翻訳されると、リンク切れになります。また、見出しを翻訳すると自動生成される ID も変わるため、その見出しへの `#anchor` リンクがすべて壊れます。このため Docusaurus では[明示的な見出し ID](https://docusaurus.io/docs/i18n/tutorial#translate-markdown-files) の使用を推奨しています。
* **フロントマター。** `title` などのキーが翻訳されたり、`slug` の値が変わったり、翻訳後の値が原因で YAML が壊れたりすることがあります。フランス語ではコロンの前にスペースを入れるため、`title: Installer la CLI : guide rapide` は無効な YAML になります (`yaml` パーサーはネストしたマッピングとして報告します) 。この値は引用符で囲む必要があります。
* **HTML 属性。** `alt` と `title` のテキストは翻訳します。`class` などの識別子はそのまま残し、`src` や `href` は、ローカライズ済みアセットや URL の明示的なマッピングを介する場合にのみ変更します。
* **MDX のインポートと JSX。** `import Tabs from '@theme/Tabs'` が文章として翻訳されたり、`<Tabs>` が `<Onglets>` になったりすると、ビルドが失敗します。[Docusaurus の Crowdin ガイド](https://docusaurus.io/docs/i18n/crowdin#mdx)では、JSX を HTML として読み取るツールは無効な JSX を生成する可能性があり、特にオブジェクトや配列の値を持つ props で失敗しやすいと注意を促しています。
* **アドモニション。** Docusaurus は `:::note`、`:::tip`、`:::info`、`:::warning`、`:::danger` を[キーワード](https://docusaurus.io/docs/markdown-features/admonitions)として認識します。翻訳された `:::astuce` はキーワードとして認識されないため、コールアウトがプレーンテキストとしてレンダリングされてしまいます。
* **テーブル。** GFM のテーブルは、ヘッダー行のセル数が区切り行のセル数と一致する場合にのみ認識されます。また、セル内のパイプ文字は `\|` としてエスケープする必要があります ([GFM 仕様](https://github.github.com/gfm/#tables-extension-)) 。翻訳ツールがセル内にパイプや改行を追加すると、その行が崩れます。

以下に、ソースファイルと、上記の不具合をすべて含む出力の例を示します。問題を一か所にまとめた説明用の例であり、特定のツールの出力ではありません。

```mdx
---
title: Install the CLI
slug: /install
---

import Tabs from '@theme/Tabs';

## Install the CLI {/* #install */}

Run `npm install my-cli`, then read the [setup guide](/docs/setup#api-keys).

:::tip
Use <Tabs groupId="pm">a package manager</Tabs> you already have.
:::
```

```mdx
---
titre: Installer la CLI : guide rapide
slug: /installer
---

importer Tabs depuis '@theme/Tabs';

## Installer la CLI {/* #installer */}

Exécutez `npm installer my-cli`, puis lisez le [guide](/docs/configuration#cles-api).

:::astuce
Utilisez <Onglets groupId="gp">un gestionnaire de paquets</Onglets> que vous avez déjà.
:::
```

2つ目のファイルには、翻訳されてしまったフロントマターのキー、不正なYAML、変更されたスラッグ、MDXでは解析できないimport、新たに付与された見出しID、壊れたコマンド、リンク切れ、未定義のアドモニション、そして存在しないコンポーネントが含まれています。

## Markdown と MDX を翻訳する方法

### a) Google または DeepL のドキュメント翻訳

[Google Cloud Translation](https://docs.cloud.google.com/translate/docs/supported-formats) のドキュメント翻訳 (Advanced エディション) が対応しているのは Word、PDF、PowerPoint、Excel ファイルで、Markdown には対応していません。テキスト翻訳のほうは、プレーンテキストまたは HTML を入力として受け付けます。[DeepL API](https://developers.deepl.com/docs/api-reference/document) では Markdown (`.md`) のドキュメント翻訳がベータ版として記載されていますが、MDX の記載はありません。どちらを使う場合でも、コードブロックやフロントマターを含むファイルの翻訳を任せる前に、実際のファイルで出力を確認してください。

### b) AST を使って本文と構文を分離する

[remark](https://github.com/remarkjs/remark) は Markdown を解析して [mdast](https://github.com/syntax-tree/mdast) ツリーに変換します。以下の抽出デモでは、`text` ノードを走査し、コード、属性、フロントマター はスキップします。コンテンツを調べる出発点としては役立ちますが、完全な翻訳パイプラインではありません。

```js
// extract.mjs: npm i unified remark-parse remark-stringify remark-mdx
//   remark-frontmatter remark-gfm remark-directive unist-util-visit
import { readFileSync } from 'node:fs';
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkFrontmatter from 'remark-frontmatter';
import remarkGfm from 'remark-gfm';
import remarkMdx from 'remark-mdx';
import remarkDirective from 'remark-directive';
import remarkStringify from 'remark-stringify';
import { visit } from 'unist-util-visit';

const processor = unified()
  .use(remarkParse)
  .use(remarkFrontmatter, ['yaml']) // frontmatter は 1 つの `yaml` ノードにまとめられる
  .use(remarkGfm)                   // テーブル
  .use(remarkMdx)                   // import/export と JSX
  .use(remarkDirective)             // :::tip 注記ブロック
  .use(remarkStringify);

const tree = processor.parse(readFileSync(process.argv[2], 'utf8'));

// このデモでは text ノードのみを抽出します。属性や frontmatter 内の表示テキストは、
// 本番用の翻訳ツールでは別途処理する必要があります。
const segments = [];
visit(tree, 'text', (node) => {
  if (node.value.trim()) segments.push(node);
});

console.log(segments.map((n) => JSON.stringify(n.value)).join('\n'));

// 翻訳 API 呼び出しの代わりに、各セグメントをインプレースで置き換える
for (const node of segments) node.value = node.value.toUpperCase();
console.log('\n' + processor.stringify(tree));
```

上記のソースファイルに、フェンス付きの `bash` ブロックと2列の表を追加したものを対象に `node extract.mjs guide.mdx` を実行すると、次のセグメントが出力されました (抜粋) ：

```text
"Install the CLI "
"Run "
", then read the "
"setup guide"
"."
"Use "
"a package manager"
" you already have."
```

再シリアライズしたファイルでは、テキストノードが大文字化される一方で、フロントマターの内容、import、見出し ID、インラインコード、リンク先、アドモニション名、JSX 属性、コードブロックの内容は保持されていました。ただし、フォーマットがバイト単位ですべて保持されたわけではありません。次の 3 つの制約が見つかりました。

* **文が断片に分かれて届く。** 「Run … then read the … setup guide」は 5 つのセグメントに分割されるため、翻訳者はコードやリンクをまたいで語順を入れ替えることができません。本番環境で使うスクリプトでは、インラインノードをプレースホルダーに置き換えたうえで段落全体を翻訳します。
* **一部の文章は `text` ノードに含まれない。** 画像の `alt` テキスト、`title` プロパティのような JSX 属性値、`title` などのフロントマターの値は、それぞれ個別に処理する必要があります。
* **出力が再フォーマットされる。** `remark-stringify` がテーブルの列の余白を詰め直すため、変更していない行まで差分に表示されます。

パースすることで、構文エラーを早い段階で検出することもできます。MDX では波括弧が JavaScript の式の開始を意味するため、Mintlify 形式の `{#install}` という見出しのサフィックスがあると、`remark-mdx` が「Could not parse expression with acorn」というエラーで失敗しました。Docusaurus ではコメント形式の `{/* #install */}` も使用でき、`docusaurus write-heading-ids --syntax mdx-comment` を使えば自動で書き込めます。

大文字への置換は、パーサーがどのテキストを選択するかを確認するためのものであり、翻訳品質を測るものではありません。翻訳パイプラインを使用する前に、保護対象のフィールドを翻訳元と比較し、YAML と MDX の構文を検証したうえで、サイトの実際のビルドを実行し、壊れた import やリンク、フレームワーク固有のコンポーネントの問題を検出してください。

### c) 翻訳管理システム

翻訳管理システム (TMS) を使えば、ファイルの解析を任せられます。Crowdin は [Markdown](https://store.crowdin.com/md) と [MDX](https://store.crowdin.com/mdx) をネイティブにサポートしており、[パーサー設定](https://support.crowdin.com/parsers-configuration/)でコードブロックや指定したフロントマター要素を除外できます。MDX ファイルはデフォルトで MDX v1 としてアップロードされ、v2 を使うには `mdx_v2` タイプを指定します。ただし、翻訳元と出力先のパスのマッピング、CI でのファイル同期、パーサーが誤って解釈する JSX への対処は、引き続き自分で行う必要があります。

### d) ルールを指定してLLMにプロンプトする

ファイル全体をモデルに渡せば、段落の文脈を保ったまま翻訳できます。本文、画像の alt テキスト、フロントマターの `title` と `description`、特定のコンポーネントの props など、翻訳対象とする表示テキストのフィールドを指定してください。コード、構造上のキー、import 文、JSX のコンポーネント名、`:::` キーワードは変更しないよう指示し、URL の変更はロケールマッピングに基づく場合のみ許可し、YAML のクォートが正しく保たれるよう求めてください。プロンプトで指定したルールが守られる保証はないため、出力をパースし、MDX をコンパイルしたうえで、保護対象のコンテンツを翻訳元と照合してください。

### 比較

| アプローチ                      | Markdown の構造を理解するか                 | MDX と JSX                          | フロントマター              | 翻訳の同期を維持できるか    | 必要な作業量                       |
| -------------------------- | ---------------------------------- | ---------------------------------- | -------------------- | --------------- | ---------------------------- |
| Google または DeepL のドキュメント翻訳 | DeepL は `.md` にベータ版で対応、Google は非対応 | 記載なし                               | 未検証 (要確認)            | ファイルごとに再実行      | 少ない (ただし確認作業が必要)             |
| remark スクリプト               | 対応 (対象ノードは自分で決める)                  | `remark-mdx` を使えば対応                | 自分で処理する              | 変更検出を自分で実装      | 多い                           |
| TMS (Crowdin)              | 対応                                 | ネイティブ対応 (JSX に関する注意点がドキュメントに記載あり)  | 指定したキーを除外            | CI で CLI による同期  | 中程度                          |
| ルール付きの LLM                 | 指示次第                               | 指示次第                               | 指示次第                 | 自分でスクリプトを書く     | 中程度 (ただし確認作業が必要)             |
| General Translation CLI    | 専用の Markdown 処理                    | 専用の MDX 処理                         | Mintlify のタイトルと説明を翻訳 | 再実行時に一致する翻訳を再利用 | 翻訳元のパスの設定、出力のレビュー、サイトのビルドの実行 |

手作業でレビューする単発の `.md` ファイルなら、DeepL のベータ版 Markdown サポートが適しています。少数で変更の少ないファイル群を細かく制御したい場合は、remark スクリプトを書きましょう。翻訳者が TMS のエディターで作業するなら TMS、差分で確認する前提の手早い下書きなら LLM のプロンプトが向いています。リリースのたびに更新されるドキュメントには General Translation を選びましょう。翻訳済みファイルはリポジトリ内に置いたまま、生成と再利用を任せられます。

## General Translation で Markdown と MDX を翻訳する方法

頻繁に変更されるリポジトリで Markdown や MDX を管理している場合は、General Translation の CLI である `gt` を使うと、実行のたびに自動で翻訳できます。`gt` は [MDX および Markdown ファイル](/docs/cli/reference/formats/mdx-md-files)の構文やフォーマットを保持したまま翻訳します。[CLI クイックスタート](/docs/cli/quickstart)に沿って [`npx gt init`](/docs/cli/reference/commands/init) を実行したら、`gt.config.json` の `files` に `mdx` または `md` エントリを追加します。

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["fr", "ja"],
  "files": {
    "mdx": { "include": ["docs/[locale]/**/*.mdx"] },
    "md": { "include": ["docs/[locale]/**/*.md"] }
  }
}
```

次に、[`npx gt translate`](/docs/cli/reference/commands/translate) を実行します。CLI は `docs/en/` から翻訳元を読み込み、翻訳を `docs/fr/` と `docs/ja/` に書き出します。ドキュメントの翻訳では、次の動作に注意してください。

* **見出しID。** Mintlify 形式の `{#id}` サフィックスは、対応する見出しに付いたまま保持されます (`gt` 2.17.3 以降) 。
* **フロントマター。** Mintlify サイトでは、フロントマターのタイトルと説明も翻訳されます。
* **増分実行。** 以前の実行で一致した翻訳は再利用され、新規または変更されたコンテンツのみが翻訳・課金されます。`--force` を指定するとすべてを再翻訳し、ローカルでの編集は上書きされます。
* **手動編集。** 編集内容の同期はオプトインです。[`npx gt translate --save-local`](/docs/cli/reference/commands/translate) または [`npx gt save-local`](/docs/cli/reference/commands/save-local) を使用してください。
* **リンクとインポート。** ロケールごとの URL、インポート、アセットパスの書き換えは実験的機能で、`--experimental-localize-static-urls` などのフラグで有効化します。

ビルドの前に [CI で](/docs/cli/guides/generating-translations)実行し、プロダクト用語はアプリと共通の[用語集](/docs/platform/dashboard/guides/defining-context-for-translations)で管理し、表現は[ダッシュボードのエディター](/docs/platform/dashboard/guides/reviewing-translations)でレビューしましょう。公開前には、すべてのロケールでビルドとリンクチェックを実行してください。 (より広い観点での比較については、[General Translation vs. Google Translate](/kb/general-translation-vs-google-translate) および [General Translation vs. Crowdin](/kb/general-translation-vs-crowdin) を参照してください。)

### MDX コンポーネントのどの部分を翻訳すべきか？

General Translation は、読者が目にするテキストと、サイトが内部で使用する識別子を区別します。
次の翻訳元の例では、コールアウトの本文だけでなく、タイトルも同じように翻訳が必要です：

```mdx title="docs/en/deployment.mdx"
---
title: Deployment guide
slug: deployment-guide
---

import { Callout } from '@/components/Callout';

<Callout id="backup" type="warning" title="Back up your database first">
  Keep a backup before deploying.
</Callout>
```

| 翻訳元の要素                            | 扱い                                     |
| --------------------------------- | -------------------------------------- |
| フロントマターの `title`                  | ページタイトルを翻訳する                           |
| コールアウトの `title` と本文               | 表示される文言を翻訳する                           |
| フロントマターの `slug` とコールアウトの `id`     | ルートやリンクで使われる識別子として保持する                 |
| `Callout`、プロパティ名、`type="warning"` | コンポーネントの仕様 (コントラクト) として保持する            |
| インポートパス                           | 設定済みのローカライゼーションルールで書き換える場合を除き、そのまま保持する |

コードフェンス内でも同じ考え方が当てはまります。説明用のコメントは
翻訳してかまいませんが、コマンドや識別子はそのまま残します。翻訳済みファイルを翻訳元と比較する際は、
すべてのブロックがバイト単位で一致することを求めず、フェンスブロック内のコメントの文言には差異を許容してください。結果は、インポートされたコンポーネントとその props が定義されているドキュメントサイトのビルドで
コンパイルし、各ロケールでレンダリングされたコールアウトとそのアンカーを確認してください。スタンドアロンの
MDX 構文チェックでは、サイトのコンポーネントやルーティングまでは解決されません。

## 重要なポイント

* 完全な文に加え、alt テキスト、フロントマター の値、関連する props など、選択した表示テキストのフィールドを翻訳します。技術的な構文や識別子はそのまま保持し、URL の書き換えは設定済みのマッピングを介してのみ行います。
* フランス語の `" : "` という句読点の使い方は、引用符で囲まれていない YAML フロントマター を壊すおそれがあります。また、`{#id}` 形式の見出しサフィックスは、標準的な MDX パーサーではエラーになります。
* Google のドキュメント翻訳は Markdown に対応していません。DeepL は `.md` をベータ版として記載しており、MDX は記載していません。
* remark のデモではテキストノードを取り出せますが、完全なパイプラインでは文の文脈を保持したうえで、それらのノード以外にある表示テキストも処理する必要があります。
* General Translation の CLI は、構文を保持したまま `md` および `mdx` ファイルを翻訳し、2 回目以降の実行ではマッチングした既存の翻訳を再利用します。

## Related questions

- [i18n の JSON ファイルを翻訳するには？](https://generaltranslation.com/ja/kb/translate-json-files.mdx): JSON ロケールファイルでは、文字列の値だけを翻訳します。複数形以外のキー、{{name}} などのプレースホルダー、タグは変更せずに残しますが、複数形のキーは言語によって異なる点に注意が必要です。たとえばポーランド語では inbox_few と inbox_many が必要になります。ファイル形式に対応したツールや API を使い、レビューの前に出力をパースして検証してください。
- [YAML のロケールファイルはどのように翻訳すればよいですか？](https://generaltranslation.com/ja/kb/translate-yaml-files.mdx): 翻訳するのは文字列の値だけにし、キー、%{name} や {{name}} などのプレースホルダー、アンカーはそのまま残します。コロンを含む値や % または { で始まる値は引用符で囲み、各ファイルのロケールのルートキーまたはファイル名を設定し、対象言語に必要な複数形キーを追加します。General Translation の CLI は YAML の値をインプレースで翻訳し、キーには手を加えません。
- [ウェブサイトを多言語化するにはどうすればよいですか？](https://generaltranslation.com/ja/kb/make-website-multilingual.mdx): 翻訳をどこで管理するか（プロキシ、CMSプラグイン、サイトビルダー、または自前のコード）を選び、Googleの推奨どおり言語ごとに専用のURLを用意します。ページ全体に加えてタイトルとメタディスクリプションも翻訳し、hreflangで各言語版を関連付けます。また、訪問者を自動でリダイレクトするのではなく、言語切り替え機能を設置しましょう。
- [Google 翻訳の代替：General Translation と Google 翻訳の比較](https://generaltranslation.com/ja/kb/general-translation-vs-google-translate.mdx): Google 翻訳は、単発のテキストをすばやく翻訳するのに便利ですが、製品を別の言語でリリースするには、各文字列を文脈に沿って翻訳し、用語を統一し、変数や複数形を正しく扱い、レビューを行い、リリースプロセスを整える必要があります。General Translation はコード内の各文字列の文脈を理解し、コードからレビュー、そして毎回のリリースまで、ローカライゼーションのワークフロー全体を自動化します。
- [Crowdin の代替ツール：General Translation と Crowdin の比較](https://generaltranslation.com/ja/kb/general-translation-vs-crowdin.mdx): テキストをコンポーネント内に置いたまま、ビルドとあわせて翻訳を生成したいなら General Translation がおすすめです。Crowdin はリソースファイル、翻訳者、レビューワークフローを中心に翻訳プロジェクトを管理するツールで、エンジニアがそれらをアプリに接続し、プロダクトの変化に合わせて保守していく必要があります。なお、オープンソースのコミュニティ翻訳やベンダー主導の翻訳プログラムでは、Crowdin は今も有力な選択肢です。

## Previous and next questions

- Previous question: [ICUメッセージ形式とは？](https://generaltranslation.com/ja/kb/icu-message-format.mdx)
- Next question: [SRT 字幕のタイミングを崩さずに翻訳するには？](https://generaltranslation.com/ja/kb/translate-srt-subtitles.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/ja/kb/sitemap.md) for every article.
