# General Translation Knowledge Base: i18n の JSON ファイルを翻訳するには？
URL: https://generaltranslation.com/ja/kb/translate-json-files.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: JSON ロケールファイルでは、文字列の値だけを翻訳します。複数形以外のキー、{{name}} などのプレースホルダー、タグは変更せずに残しますが、複数形のキーは言語によって異なる点に注意が必要です。たとえばポーランド語では inbox_few と inbox_many が必要になります。ファイル形式に対応したツールや API を使い、レビューの前に出力をパースして検証してください。
Category: 翻訳
Last updated: 2026-10-20
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

ここでは、i18next、react-intl、next-intl、vue-i18n などの i18n ライブラリが読み込むロケールファイル、つまり各キーが UI の文字列に対応するファイルを扱います。任意のデータ JSON (API レスポンスや商品カタログなど) の場合は、どのフィールドを翻訳するかを 1 つずつ判断する必要があるため、別のアプローチが求められます。

## JSON ロケールファイルの構造

ほとんどのロケールファイルは、以下のようにキーをオブジェクトでグループ化したネスト構造になっています。フラットなファイルでは、同じパスを `"nav.home": "Home"` のように、ドットで区切った1つのキーとして記述します。

```json title="locales/en/common.json"
{
  "nav": { "home": "Home", "save": "Save" },
  "greeting": "Hello, {{name}}!",
  "inbox_one": "You have {{count}} new message",
  "inbox_other": "You have {{count}} new messages",
  "terms": "Read our <1>terms</1> before you continue."
}
```

中に書かれる文字列の構文はライブラリごとに異なり、翻訳時にはその構文を崩さずに残す必要があります。

* **i18next** は二重波括弧 (`{{name}}`) で補間を行います。複数形は各言語の複数形規則に従い、`_one`、`_few`、`_many`、`_other` などの[サフィックス](https://www.i18next.com/translation-function/plurals)を付けた別々のキーとして保存されます。また、react-i18next の `<Trans>` コンポーネントでは、`<1>terms</1>` のような番号付きタグが追加されます。
* **react-intl と next-intl** は ICU メッセージを保存します。プレースホルダーには単一の波括弧を使い、複数形は文字列の中に記述します：`{count, plural, one {# message} other {# messages}}`。 ([ICUメッセージ形式とは？](/kb/icu-message-format)を参照してください。) 
* **vue-i18n** は単一の波括弧でプレースホルダーを表し、複数形をパイプで区切ります：`no apples | one apple | {count} apples` ([vue-i18n の複数形処理](https://vue-i18n.intlify.dev/guide/essentials/pluralization)) 。

キーの命名も重要です。翻訳者にはキーと値しか見えないことが多いからです。 ([i18n の翻訳キーはどのように命名すべきか？](/kb/i18n-key-naming)を参照してください。)

## JSONを翻訳ツールに貼り付けると何が起こるか

汎用の翻訳ツールはファイルを単なるテキストとして扱うため、構造が壊れるおそれがあります。

* **キーまで翻訳される。** `"nav"` が `"nawigacja"` になり、アプリがその文字列を見つけられなくなります。
* **プレースホルダーが変わる。** `{{name}}` が `{{nombre}}` になったり、波括弧が欠けたりして、実行時に補間が失敗します。
* **タグが壊れる。** `<1>terms</1>` が翻訳されたり、番号が振り直されたり、削除されたりして、リンクが本来の語句をラップしなくなります。
* **ファイルが有効なJSONでなくなる。** スマートクォート (曲がった引用符) 、翻訳後の文字列内でエスケープされていない `"`、末尾のカンマなどが原因で、ファイル全体のパースに失敗します。
* **複数形のキーが足りなくなる。** `inbox_one` と `inbox_other` をキーごとに翻訳しても、ポーランド語で i18next が必要とする `inbox_few` と `inbox_many` のキーは生成されません。そのため、「5 messages」を表す正しいポーランド語の形がなくなります。 (各言語の複数形カテゴリについては [ICUメッセージ形式とは？](/kb/icu-message-format) を参照してください。) 
* **短い文字列は意味が曖昧になる。** `"save": "Save"` はドイツ語では *speichern* (ファイルを保存する) にも *sparen* (節約する) にも訳せますが、キーだけではどちらの意味かを判断できないことがほとんどです。

## JSON ロケールファイルを翻訳する方法

| 方法                                              | キーとプレースホルダー                                                              | 複数形                              | 短い文字列の文脈                                       | 変更への追従                        |
| ----------------------------------------------- | ------------------------------------------------------------------------ | -------------------------------- | ---------------------------------------------- | ----------------------------- |
| 手作業、または翻訳者がファイルを直接編集                            | 作業者が注意深ければ安全                                                             | 作業者がルールを知っていれば追加する               | 作業者が質問できる                                      | 変更のたびに手作業                     |
| オンライン JSON 翻訳ツール (ファイルをアップロードし、翻訳をダウンロード)       | ツールによって異なる。まずプレースホルダーの多いファイルで試す                                          | ツールによって異なる                       | ツールによって異なる                                     | 変更のたびにファイルを再アップロード            |
| DeepL または Google Cloud Translation API を使うスクリプト | JSON を走査して値のみを送信する。DeepL のドキュメント API は `.json` も受け付け、デフォルトでプレースホルダーを保護する | 不足しているキーを自分で生成する                 | DeepL の `context` パラメータ。Google には文字列ごとの指定方法がない | スクリプトを再実行し、出力の差分を取る           |
| LLM にファイルを渡してプロンプトで指示する                         | 通常は保持されるが、保証はない                                                          | 依頼時にカテゴリを指定すれば追加される              | プロンプトに含めた内容次第                                  | プロンプトを再実行し、毎回結果を検証する          |
| General Translation CLI                         | JSON の構造を読み取り、値を翻訳する                                                     | 既存のエントリを翻訳する。対象言語の複数形キー群を確認すること | キーごとのメモと文字数制限、共有の用語集とカスタムプロンプト                 | 一致する翻訳を再利用し、ビルド前に更新を生成する      |
| 翻訳管理システム (TMS)                                  | 形式に応じて解析されるため、キーは安全                                                      | TMS とファイル形式による                   | キーごとのスクリーンショット、コメント、説明                         | TMS のリポジトリインテグレーションでファイルを同期する |

スクリプトを使う方法のうち 2 つについては、もう少し説明が必要です。DeepL の[ドキュメント API](https://developers.deepl.com/api-reference/document) は対応形式として `json` を挙げており、デフォルトで `{stars}` や `{{userName}}` などのプレースホルダーをそのまま保持し、ICU の複数形 skeleton も保護してブランチ内のテキストだけを翻訳します。一方、Google の[ドキュメント翻訳](https://docs.cloud.google.com/translate/docs/advanced/translate-documents)は Office ファイルや PDF には対応していますが JSON には対応しておらず、一般向けの Google 翻訳サイトでアップロードできるのも `.docx`、`.pdf`、`.pptx`、`.xlsx` だけです。そのため Google を使う場合は、文字列の値を自分で抽出してテキスト API に送る必要があります。

小さなファイルを一度だけ翻訳するなら、丁寧な手作業か DeepL のドキュメント API で十分です。検証と再実行を自分で担えるなら、スクリプトや LLM プロンプトが向いています。既存のレンダリングライブラリはそのままに、生成・レビュー済みのカタログをコードの変更と一緒にリリースしたい場合は General Translation を使いましょう。翻訳者チームがコードベースの外で作業する場合は、[翻訳管理システム](/kb/what-is-a-translation-management-system)が適しています。

## General Translation で JSON ファイルを翻訳する方法

ファイルがリポジトリ内にあり、リリースのたびに変更される場合は、ビルドにコマンドを組み込んでおけば常に最新の状態に保てます。General Translation の CLI である `gt` は、i18next や ICU ベースのカタログを含む JSON ロケールファイルを翻訳します。レンダリングに使っているライブラリはそのまま使い続けられます。`npm install gt --save-dev` でインストールし、[`npx gt init`](/docs/cli/reference/commands/init) を実行して `gt.config.json` の作成とサインインを済ませたら、`files.json.include` で原文ファイルを指定します。`[locale]` プレースホルダーは、CLI がソースロケールをどこから読み込み、各対象ロケールをどこへ書き出すかを示します。

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["de"],
  "files": {
    "json": {
      "include": ["locales/[locale]/*.json"]
    }
  }
}
```

既存のプロジェクトの場合は、まず [`npx gt upload`](/docs/cli/reference/commands/upload) を実行して、翻訳元とレビュー済みの翻訳をインポートします。

次に [`npx gt translate`](/docs/cli/reference/commands/translate) を実行すると、`locales/en/` 配下のすべてのファイルが読み込まれ、ドイツ語のファイルが `locales/de/` に書き出されます。書き出されたファイルはそのままレビューしてコミットできます。`--dry-run` を付けると、API を呼び出さずに検出されたファイルの一覧だけを表示できます。この例では英語とドイツ語を使用しており、どちらも基数メッセージでは上記の `one` と `other` カテゴリを使用します。2 回目以降の実行では、一致する翻訳が再利用されることがあります。

`package.json` で `i18next` または `next-intl` が宣言されている場合、CLI は ICU メッセージを含め、そのライブラリの文字列構文を保持します ([JSON 形式のリファレンス](/docs/cli/reference/formats/json-files)を参照) 。「Save」のような短い文字列の意味を明確にするには、同じキーを持つ対応ファイル `common.metadata.json` を追加し、文字列ごとに `context` のメモまたは `maxChars` の上限を指定します ([キーごとのメタデータ](/docs/cli/reference/keyed-metadata)を参照) 。たとえば `nav.save` には「編集したドキュメントをディスクに保存する」のようなメモを付けておけば、サービスは曖昧なラベルだけに頼らずに翻訳できます。プロジェクトのコンテキストグループに含まれる用語集の用語やカスタムプロンプトも適用されます。

生成された文言は [ダッシュボードのエディター](/docs/platform/dashboard/guides/reviewing-translations) でレビューしてください。レビュー担当者がダウンロードしたファイルを編集する場合は、[`npx gt save-local`](/docs/cli/reference/commands/save-local) を使用します。以下のチェックは、こうした言語面のレビューとは別に、メッセージの構造を検証するものです。

## リリース前に翻訳済みファイルを確認する

アプリケーションで使用しているものと同じメッセージ形式とロケールのルールで、出力を検証します。

* **JSON をパースし、複数形以外のキーを比較します。** トップレベルのキーだけでなく、ネストされたキーのパスも確認してください。JSON としてパースできても、キーの欠落や名前の変更があると参照が失敗することがあります。配列や文字列以外の値は、アプリケーションのスキーマに従って扱ってください。
* **i18next の複数形はキーのまとまりとして確認します。** `inbox_one` や `inbox_other` などのキーをベースキーごとにグループ化し、対象ロケールのカテゴリを確認します。ポーランド語では `inbox_few` と `inbox_many` も必要です。これらは想定外のキーではなく、必須の追加キーです。日本語では `inbox_other` だけで足ります。i18next は `Intl.PluralRules` に準拠しており、特殊な `_zero` 形式も使用できます。基数メッセージか序数メッセージかに応じて、適切なルールを使用してください ([i18next の複数形規則](https://www.i18next.com/translation-function/plurals)を参照) 。
* **すべての翻訳形式でプレースホルダーとタグを維持します。** 新たに追加した複数形も確認してください。`{{name}}` は引き続き `name` を参照している必要があり、番号付きタグは順序が入れ替わっても、意図したコンポーネントを指している必要があります。
* **ICU メッセージをパースし、引数を比較します。** ネストされた波括弧の処理には正規表現ではなく、[FormatJS ICU message parser](https://formatjs.github.io/docs/icu-messageformat-parser/) などのパーサーを使用してください。ただし、パースだけでは不十分です。複数形の引数を `count` から `total` に変更しても構文上は有効ですが、アプリケーションが渡す値とは一致しなくなります。引数の名前と型、リッチテキストタグ、select のケース、`=0` などの完全一致セレクター、複数形のオフセットを確認してください。ロケール固有の複数形カテゴリは許容してください。ICU では `other` ブランチが必須でフォールバックとして機能するため、ICU メッセージにすべての CLDR カテゴリを含める必要はありません。

複数形キーが欠落していても、はっきりとしたエラーにはなりません。次のポーランド語ファイルには 4 つのカテゴリがすべて揃っていますが、キーを 1 つずつ翻訳するだけでは `inbox_one` と `inbox_other` で終わっていたはずです。

```json title="locales/pl/common.json"
{
  "inbox_one": "Masz {{count}} nową wiadomość",
  "inbox_few": "Masz {{count}} nowe wiadomości",
  "inbox_many": "Masz {{count}} nowych wiadomości",
  "inbox_other": "Masz {{count}} nowej wiadomości"
}
```

i18next 26.5.3 で `fallbackLng: 'en'` を指定して読み込むと、キー単位で翻訳したファイルでは、`few` または `many` が必要となるすべての数値について、ポーランド語の `other` 形式ではなく英語にフォールバックします。

```text title="Output"
count  category  key-by-key file              complete file
1      one       Masz 1 nową wiadomość        Masz 1 nową wiadomość
2      few       You have 2 new messages      Masz 2 nowe wiadomości
5      many      You have 5 new messages      Masz 5 nowych wiadomości
22     few       You have 22 new messages     Masz 22 nowe wiadomości
1.5    other     Masz 1.5 nowej wiadomości    Masz 1.5 nowej wiadomości
```

この値は数値として書式設定されていないため、小数は `1.5` と表示されます。小数になる可能性がある場合は、ロケールに合わせて書式設定してください。最後に、アプリケーションのi18nライブラリでメッセージを読み込み、実際の文脈で確認します。各複数形が選択される数値を試し、必要に応じてゼロや小数も確認してください。構文チェックだけでは、翻訳が正確かどうかや、テキストがインターフェースに収まるかどうかまでは判断できません。独自の補間ルールや vue-i18n のパイプ構文については、それぞれの形式に合わせたチェックが必要です。

## 重要なポイント

* メッセージ構文を保ったまま値を翻訳します。複数形でないキーはそのまま維持されますが、複数形のキーは言語によって異なる場合があります。
* 複数形カテゴリは言語によって異なります。たとえばポーランド語では、英語の翻訳元にはない `_few` と `_many` のキーが必要です。
* DeepL のドキュメント API は JSON に対応しており、デフォルトでプレースホルダーを保護します。一方、Google のドキュメント翻訳は JSON に対応していません。
* `gt` CLI で翻訳するには、`files.json.include` に `[locale]` パターンを設定して [`npx gt translate`](/docs/cli/reference/commands/translate) を実行します。キーごとのメタデータを使えば、文字列単位で文脈や文字数制限を追加できます。
* i18next の複数形キー群は対象ロケールごとに検証してください。ICU メッセージは、ネストされた構文を正規表現でチェックするのではなく、パースして検証してください。

## Related questions

- [ICUメッセージ形式とは？](https://generaltranslation.com/ja/kb/icu-message-format.mdx): ICUメッセージ形式は、変数、複数形、select による選択、序数を1つの翻訳可能な文字列で表現するための構文です（例：{count, plural, one {# file} other {# files}}）。各言語は必要な CLDR の複数形カテゴリだけを使用します。英語では one と other を使い、ポーランド語ではさらに few と many が加わります。
- [i18n の翻訳キーはどのように命名すべきですか？](https://generaltranslation.com/ja/kb/i18n-key-naming.mdx): キーは英語の文言ではなく、テキストが表示される場所と意味に基づいて命名します（例: checkout.summary.title）。英語が同じでも、用途が異なるものにはそれぞれ別のキーを割り当ててください。たとえばドイツ語では、ボタンの Open は Öffnen、ステータスの Open は Offen と訳されます。
- [General Translation vs. i18next、react-intl、next-intl：どのi18nライブラリを使うべきか？](https://generaltranslation.com/ja/kb/general-translation-vs-i18n-libraries.mdx): i18next、react-intl、next-intlなどのオープンソースライブラリ自体は、翻訳を一切行いません。これらが行うのは、あなた自身や翻訳者、あるいは別のサービスが作成し、言語ごとのカタログファイルに用意した翻訳を表示することだけです。General Translationのライブラリも同じくオープンソースで同じ役割を果たしますが、General Translationはさらに、コードを文脈として活用しながら翻訳そのものも行います。
- [翻訳ファイルなしでi18nは実現できますか？](https://generaltranslation.com/ja/kb/i18n-without-translation-files.mdx): はい。General Translationの gt-react と gt-next ライブラリを使えば、翻訳キーも、言語ごとに管理するJSONファイルもなしで、ReactとNext.jsのi18nを実現できます。文言は `<T>` コンポーネント内のJSXにインラインで記述したままで、gt translate コマンドがコードから得た文脈をもとに、ビルド時に各言語の翻訳を生成します。さらにLocadexを使えば、プルリクエストを通じて翻訳を常に最新の状態に保てます。
- [AI翻訳は本番環境のアプリで使えるほど正確か？](https://generaltranslation.com/ja/kb/is-ai-translation-accurate.mdx): 広く話されている言語であれば多くの場合は十分な精度がありますが、それは自社の対象言語、UI文字列、リスクの高いコンテンツで評価をクリアしてからの話です。WMT25では、Gemini 2.5 Proが16の言語ペアのうち10で人間による参照訳と同等以上の評価を得ました。しかし、文書単位のベンチマークからは、短いインターフェース文字列をそのままリリースできるかどうかまではわかりません。

## Previous and next questions

- Previous question: [hreflang とは？設定方法を解説](https://generaltranslation.com/ja/kb/what-is-hreflang.mdx)
- Next question: [i18n の翻訳キーはどのように命名すべきですか？](https://generaltranslation.com/ja/kb/i18n-key-naming.mdx)

## Sitemap

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