ヘルプセンター

Reactのローカライゼーションとi18next

グローバルなユーザーに向けてReactアプリケーションを構築するには、堅牢な国際化(i18n)戦略が必要です。react-i18nextは、実績のあるi18nextフレームワークを基盤とした、最も人気のあるReactローカライゼーションライブラリです。本ガイドでは、初期セットアップからAIを活用した翻訳による本番環境向けの自動化まで、Reactアプリをローカライズするために必要なすべてを順を追って解説します。

なぜReactのローカライゼーションにreact-i18nextを選ぶのか?

react-i18nextはReact国際化のデファクトスタンダードであり、世界中の何千もの本番アプリケーションで信頼されています。開発者がこれを選ぶ理由は以下の通りです:

  • HooksファーストのAPI - useTranslation()フックは、言語変更時の自動再レンダリングを伴う、クリーンで慣用的なReact統合を提供します。
  • 豊富なエコシステム - 言語検出、HTTPバックエンド、キャッシュなどのためのプラグインが用意されています。車輪の再発明をすることなく機能を拡張できます。
  • JSON翻訳フォーマット - 編集やバージョン管理が容易で、翻訳ツールやAIサービスとも統合しやすい標準的なJSONファイルを使用します。
  • 名前空間のサポート - 翻訳を論理的なグループ(認証、ダッシュボード、エラーなど)に整理することで、保守性を高め、遅延読み込みを可能にします。
  • SSRとNext.jsへの対応 - サーバーサイドレンダリング、React Server Components、Next.js App Routerとシームレスに動作します。
  • TypeScriptのサポート - 翻訳キーの完全な型安全性を実現し、オートコンプリートやコンパイル時のキー欠落の検知が可能です。

インストール

react-i18nextとコアとなるi18nextライブラリをインストールします:

npm install react-i18next i18next

オプションのプラグイン

これらの人気プラグインは、自動言語検出や翻訳の遅延読み込み機能を追加してi18nextのセットアップを強化します:

# Language detector (auto-detects user language)
npm install i18next-browser-languagedetector

# HTTP backend (load translations from server)
npm install i18next-http-backend

推奨されるプロジェクト構造

適切に整理されたプロジェクト構造は、言語を追加しても翻訳の保守性を維持するのに役立ちます:

src/
├── i18n/
│   └── i18n.ts                  ← i18next configuration
├── locales/
│   ├── en/
│   │   └── translation.json     ← English (source)
│   ├── fr/
│   │   └── translation.json     ← French
│   ├── de/
│   │   └── translation.json     ← German
│   ├── ja/
│   │   └── translation.json     ← Japanese
│   └── es/
│       └── translation.json     ← Spanish
├── components/
├── App.tsx
└── index.tsx

翻訳JSONファイルのフォーマット

react-i18nextは翻訳にネストされたJSONファイルを使用します。キーはドット記法、{{variables}}による補間、組み込みの複数形をサポートしています:

// locales/en/translation.json
{
  "welcome": {
    "title": "Welcome to our platform",
    "greeting": "Hello, {{name}}!",
    "description": "Explore features and get started."
  },
  "nav": {
    "home": "Home",
    "dashboard": "Dashboard",
    "settings": "Settings",
    "logout": "Log out"
  },
  "cart": {
    "empty": "Your cart is empty",
    "item_one": "{{count}} item in your cart",
    "item_other": "{{count}} items in your cart",
    "checkout": "Proceed to checkout"
  }
}
  • ネストされたキー - 翻訳を階層的(例:welcome.title、nav.home)に整理して、構造を明確にします。
  • 補間(Interpolation) - 実行時に挿入される動的な値には{{variableName}}構文を使用します。
  • 複数形(Pluralization) - 自動的な複数形処理のために、_oneや_otherサフィックス(複雑な言語の場合は_zero、_two、_few、_manyなど)を追加します。
  • コンテキスト - 必要に応じて、性別に応じた翻訳のために_male、_femaleサフィックスを使用します。

i18nextの設定

i18nextは、翻訳を読み込むための2つの主要なアプローチ(HTTPバックエンドによる遅延読み込みと、バンドルされたリソース)をサポートしています。アプリのニーズに合わせて選択してください。

HTTPバックエンド(大規模アプリに推奨)

サーバー上のJSONファイルから必要に応じて翻訳を読み込みます。これにより初期バンドルサイズを小さく保つことができ、多くの言語や大きな翻訳ファイルを持つアプリに最適です:

// src/i18n/i18n.ts
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import HttpBackend from "i18next-http-backend";

i18n
  .use(HttpBackend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: "en",
    supportedLngs: ["en", "fr", "de", "ja", "es"],
    defaultNS: "translation",
    interpolation: {
      escapeValue: false, // React already escapes by default
    },
    backend: {
      loadPath: "/locales/{{lng}}/{{ns}}.json",
    },
    detection: {
      order: ["localStorage", "navigator", "htmlTag"],
      caches: ["localStorage"],
    },
  });

export default i18n;

バンドルされたリソース(シンプルなアプローチ)

翻訳を直接バンドルにインポートします。小規模なアプリや、ネットワークリクエストなしで即座に翻訳を利用する必要がある場合に最適です:

// src/i18n/i18n.ts — Bundled approach (no HTTP backend)
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";

import en from "../locales/en/translation.json";
import fr from "../locales/fr/translation.json";
import de from "../locales/de/translation.json";

i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: "en",
    supportedLngs: ["en", "fr", "de"],
    defaultNS: "translation",
    interpolation: {
      escapeValue: false,
    },
    resources: {
      en: { translation: en },
      fr: { translation: fr },
      de: { translation: de },
    },
  });

export default i18n;

アプリでの初期化

コンポーネントをレンダリングする前に、アプリのエントリーポイントでi18n設定ファイルをインポートします。これにより、UIがレンダリングされる前に翻訳が読み込まれることが保証されます:

// src/index.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./i18n/i18n"; // Initialize i18next before rendering

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Reactコンポーネントの翻訳

react-i18nextは、コンポーネントを翻訳するための2つの主要なAPIを提供しています。プログラムによるアクセスのためのuseTranslationフックと、JSXを含むリッチテキストのためのTransコンポーネントです。

useTranslationフック

useTranslationフックは、関数コンポーネントで翻訳にアクセスするための最も一般的な方法です。t()関数を提供し、言語が変更されると自動的に再レンダリングされます:

import { useTranslation } from "react-i18next";

function WelcomeBanner() {
  const { t } = useTranslation();

  return (
    <div>
      <h1>{t("welcome.title")}</h1>
      <p>{t("welcome.greeting", { name: "Alice" })}</p>
      <p>{t("welcome.description")}</p>
    </div>
  );
}

リッチテキスト用Transコンポーネント

翻訳にHTMLやJSX要素(太字、リンクなど)が含まれる場合は、Transコンポーネントを使用します。翻訳内でReactコンポーネントツリーを保持できます:

import { Trans } from "react-i18next";

function RichTextExample() {
  return (
    <p>
      <Trans i18nKey="richText.welcome">
        Welcome to <strong>our platform</strong>.
        Visit your <a href="/dashboard">dashboard</a> to get started.
      </Trans>
    </p>
  );
}

// In the translation file:
// "richText.welcome": "Welcome to <1>our platform</1>. Visit your <3>dashboard</3> to get started."

複数形の処理

i18nextは、各言語のICU複数形ルールに基づいて複数形を自動的に処理します。countパラメータを渡すと、i18nextが正しい複数形を選択します:

// In translation JSON:
// "cart.item_one": "{{count}} item in your cart"
// "cart.item_other": "{{count}} items in your cart"

import { useTranslation } from "react-i18next";

function CartSummary({ itemCount }: { itemCount: number }) {
  const { t } = useTranslation();

  return (
    <p>{t("cart.item", { count: itemCount })}</p>
  );
}

// itemCount=0 → "0 items in your cart"
// itemCount=1 → "1 item in your cart"
// itemCount=5 → "5 items in your cart"
  • 英語の場合は、翻訳キーに_oneと_otherのサフィックスを追加します
  • 複雑な複数形ルールを持つ言語(アラビア語、ポーランド語、ロシア語など)の場合は、必要に応じて_zero、_two、_few、_manyサフィックスを追加します
  • i18nextは、ターゲット言語のCLDR複数形ルールに基づいて正しい形式を自動的に選択します

名前空間による整理

名前空間を使用すると、機能やドメインごとに翻訳を別々のファイルに分割できます。これにより保守性が向上し、翻訳バンドルの遅延読み込みが可能になります:

// src/i18n/i18n.ts
i18n.init({
  defaultNS: "common",
  ns: ["common", "dashboard", "auth", "errors"],
  backend: {
    loadPath: "/locales/{{lng}}/{{ns}}.json",
  },
});

// Usage in components:
import { useTranslation } from "react-i18next";

function DashboardPage() {
  // Load specific namespace
  const { t } = useTranslation("dashboard");

  return <h1>{t("title")}</h1>;
}

function LoginForm() {
  // Load multiple namespaces
  const { t } = useTranslation(["auth", "common"]);

  return (
    <form>
      <h2>{t("auth:login.title")}</h2>
      <button>{t("common:submit")}</button>
    </form>
  );
}

動的な言語切り替え

react-i18nextを使えば、言語の切り替えはシームレスです。i18n.changeLanguage()を呼び出すだけで、useTranslationを使用しているすべてのコンポーネントが新しい言語で自動的に再レンダリングされます:

import { useTranslation } from "react-i18next";

const LANGUAGES = [
  { code: "en", label: "English" },
  { code: "fr", label: "Français" },
  { code: "de", label: "Deutsch" },
  { code: "ja", label: "日本語" },
  { code: "es", label: "Español" },
];

function LanguageSwitcher() {
  const { i18n } = useTranslation();

  const changeLanguage = (lng: string) => {
    i18n.changeLanguage(lng);
  };

  return (
    <select
      value={i18n.language}
      onChange={(e) => changeLanguage(e.target.value)}
    >
      {LANGUAGES.map(({ code, label }) => (
        <option key={code} value={code}>
          {label}
        </option>
      ))}
    </select>
  );
}

React Suspenseと遅延読み込み

react-i18nextはReact Suspenseと統合されており、非同期の翻訳読み込みを適切に処理します。HTTPバックエンドを使用する場合、翻訳の取得中にSuspenseがクリーンな読み込み状態を提供します:

import { Suspense } from "react";
import { useTranslation } from "react-i18next";

// i18next supports React Suspense for async translation loading
function App() {
  return (
    <Suspense fallback={<div>Loading translations...</div>}>
      <MainContent />
    </Suspense>
  );
}

function MainContent() {
  const { t, ready } = useTranslation();

  // With Suspense, 'ready' is always true here
  return <h1>{t("welcome.title")}</h1>;
}

TypeScriptによる翻訳キーの型安全性

i18nextは完全なTypeScript統合をサポートしています。i18nextモジュールを拡張することで、すべての翻訳キーに対してオートコンプリートとコンパイル時のチェックが可能になり、タイプミスや翻訳の欠落を防ぐことができます:

// src/i18n/types.ts
import "i18next";
import translation from "../locales/en/translation.json";

declare module "i18next" {
  interface CustomTypeOptions {
    defaultNS: "translation";
    resources: {
      translation: typeof translation;
    };
  }
}

// Now t() calls are fully type-safe:
// t("welcome.title")       ✅ Autocomplete works
// t("welcome.greeting")    ✅ Valid key
// t("invalid.key")         ❌ TypeScript error
型安全なキーは、useTranslation、Transコンポーネント、およびすべてのi18next APIで機能します。欠落しているキーや誤字があるキーは、IDE上でTypeScriptエラーとしてフラグが立てられます。

Next.jsによるサーバーサイドレンダリング

App Routerを使用するNext.jsアプリケーションでは、サーバーコンポーネントとクライアントコンポーネントの両方でi18nextを使用できます。リクエスト間で状態が共有されないように、サーバーサイド翻訳用に個別のi18nextインスタンスを作成してください:

// next-i18next.config.js (Next.js App Router)
// For Next.js 13+ with App Router, use next-intl or i18next directly

// src/i18n/server.ts
import { createInstance } from "i18next";
import { initReactI18next } from "react-i18next/initReactI18next";

export async function getServerTranslation(lng: string) {
  const i18nInstance = createInstance();
  await i18nInstance.use(initReactI18next).init({
    lng,
    fallbackLng: "en",
    resources: {
      [lng]: {
        translation: (await import(`../locales/${lng}/translation.json`)).default,
      },
    },
  });
  return i18nInstance;
}

// In a Server Component:
export default async function Page({ params }: { params: { lng: string } }) {
  const i18n = await getServerTranslation(params.lng);
  const t = i18n.t.bind(i18n);

  return <h1>{t("welcome.title")}</h1>;
}
  • ユーザー間での状態の漏洩を防ぐため、サーバー上でリクエストごとに新しいi18nextインスタンスを作成します
  • サーバーレンダリングとクライアントレンダリングの両方で同じ翻訳JSONファイルを使用します
  • 複雑なNext.jsのセットアップには、i18next-resources-to-backendやnext-intlの利用を検討してください

AIによる翻訳の加速

react-i18nextのセットアップは半分に過ぎません。すべてのターゲット言語に対して高品質な翻訳が必要です。数十個のJSONファイルを手動で翻訳するのは時間がかかり、コストが高く、ミスも発生しやすくなります。AIを活用した翻訳がその状況を一変させます。

React i18nextにl10n.devを使う理由

l10n.devは開発者のローカライゼーションワークフローのために特別に構築されました。JSON翻訳ファイルをネイティブに理解し、機械的ではない自然な翻訳を生成します:

  • ネイティブJSONサポート — translation.jsonをアップロードするだけで、完璧にフォーマットされたすぐに使えるJSONファイルが返されます
  • コンテキスト認識AI — アプリのドメインを理解し、言語を超えて専門用語やブランドのトーンを維持します
  • 補間セーフ — {{variables}}、複数形サフィックス(_one、_other)、ネストされたキー構造を保持します
  • 一括翻訳 — 数日ではなく数秒で10以上の言語に翻訳します
  • CI/CD統合 — ai-l10n npmパッケージを使用して、ビルドパイプラインの一部として翻訳を自動化します

AI翻訳ワークフロー

  1. ソースとなるtranslation.jsonを英語(またはベースとなる言語)で作成します
  2. l10n.devにアップロードするか、ai-l10n CLIを実行して翻訳します
  3. AIがすべてのターゲット言語に対して文脈的に正確な翻訳を生成します
  4. 翻訳されたJSONファイルをlocales/ディレクトリに配置してデプロイします

ai-l10n CLIによる翻訳の自動化

ai-l10n npmパッケージは、AI翻訳を開発ワークフローに直接統合します。コマンドラインからJSONファイルを翻訳しましょう:

# Install the l10n.dev CLI
npm install ai-l10n

# Translate your JSON files to multiple languages at once
npx ai-l10n translate src/locales/en/translation.json \
  --languages fr,de,ja,es,ko,zh-CN

ビルド統合

翻訳が常に最新の状態になるよう、ビルドパイプラインに翻訳の自動化を追加します:

package.json スクリプト

{
  "scripts": {
    "translate": "ai-l10n translate src/locales/en/translation.json --languages fr,de,ja,es,ko --update",
    "pretranslate": "npm run translate",
    "dev": "vite",
    "build": "npm run translate && vite build"
  }
}

Makefile

LANGUAGES = fr,de,ja,es,ko,zh-CN

translate:
	npx ai-l10n translate src/locales/en/translation.json --languages $(LANGUAGES) --update

dev: translate
	npx vite

build: translate
	npx vite build

CI/CD統合と自動化の詳細については、以下を参照してください:ローカライゼーション自動化ガイド

JSON翻訳用VS Code拡張機能

React i18nextのJSONファイルをVS Codeから直接翻訳できます。l10n.dev拡張機能を使えば、エディタを離れることなくファイルを翻訳可能です:

仕組み

  1. VS Code Marketplaceからl10n.dev拡張機能をインストールします
  2. ソースとなるtranslation.jsonファイルを開きます
  3. 右クリックして「Translate with l10n.dev」を選択します
  4. ターゲット言語を選択すると、即座に翻訳されたファイルが取得できます

今すぐReactアプリのローカライズを始めましょう

これで、react-i18nextを使用して完全にローカライズされたReactアプリケーションを構築するために必要なすべてが揃いました。i18nextの成熟したエコシステムの力とAIを活用した翻訳を組み合わせて、あらゆる言語のアプリを迅速にリリースしましょう。