著者:
    作成:2024-03-07最終更新:2026-06-23

    既存の Vite および React アプリケーションを後から多言語化 (i18n) する方法 (i18n ガイド 2026)

    www.youtube.com
    ide.intlayer.org
    intlayer-vite-react-template.vercel.app

    GitHub で アプリケーションテンプレート を見る。

    目次

    なぜ既存のアプリケーションを国際化するのは難しいのか?

    単一言語向けに構築されたアプリに複数の言語を追加しようとしたことがあるなら、その苦労がわかるでしょう。それは単に「難しい」だけでなく、「面倒」です。すべてのファイルを調べ、すべてのテキスト文字列を探し出し、それらを個別の辞書ファイルに移動する必要があります。

    次にリスクの高い部分が来ます。レイアウトやロジックを壊さずに、これらすべてのテキストをコードフックに置き換えることです。これは、新しい機能の開発を数週間停止させ、終わりのないリファクタリングのように感じられる種類の作業です。

    Intlayer Compiler とは?

    Intlayer Compiler は、その手作業をスキップするために構築されました。手動で文字列を抽出する代わりに、コンパイラが自動的に行います。コードをスキャンしてテキストを見つけ、バックグラウンドで AI を使用して辞書を生成します。 その後、ビルド中にコードを変更して、必要な i18n フックを注入します。基本的には、単一言語であるかのようにアプリを書き続け、コンパイラが多言語への変換を自動的に処理します。

    Doc Compiler: /ja/doc/compiler

    制限事項

    コンパイラは、コンパイル時にコード分析と変換 (フックの挿入と辞書の生成) を実行するため、アプリケーションのビルドプロセスが遅くなる可能性があります。

    開発中のこの影響を軽減するために、コンパイラを 'build-only' モードで実行するように構成するか、不要なときに無効にすることができます。


    Vite および React アプリケーションに Intlayer を設定するためのステップバイステップガイド

    1. 依存関係のインストール

      npm を使用して必要なパッケージをインストールします。

      bash
      npx intlayer init --interactive
      
      --interactive フラグはオプションです。AI エージェントの場合は intlayer-cli init を使用してください。
      このコマンドは環境を検出し、必要なパッケージをインストールします。例えば:
      bash
      npm install intlayer react-intlayer
      npm install vite-intlayer --save-dev
      
      • intlayer 設定管理、翻訳、コンテンツ宣言、トランスパイル、および CLI コマンド のための国際化ツールを提供するコアパッケージ。

      • react-intlayer Intlayer を React アプリケーションと統合するパッケージ。React の国際化のためのコンテキストプロバイダーとフックを提供します。

      • vite-intlayer Intlayer を Vite バンドラー と統合するための Vite プラグイン、およびユーザーの優先ロケールの検出、クッキーの管理、URL リダイレクトの処理のためのミドルウェアが含まれています。

    2. プロジェクトの構成

      アプリケーションの言語を構成するための構成ファイルを作成します。

      intlayer.config.ts
      import { Locales, type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
          defaultLocale: Locales.ENGLISH,
        },
        compiler: {
          /**
           * コンパイラを有効にするかどうかを示します。
           */
          enabled: true,
      
          /**
           * 最適化された辞書の出力ディレクトリ。
           */
          output: ({ locale, key }) => `compiler/${locale}/${key}.json`,
      
          /**
           * キーなしで、生成されたファイルにコンテンツのみを挿入します。
           */
          noMetadata: false,
      
          /**
           * 辞書キーのプレフィックス
           */
          dictionaryKeyPrefix: "", // Remove base prefix
      
          /**
           * 変換後にコンポーネントを保存するかどうかを示します。
           * これにより、コンパイラを1回だけ実行してアプリを変換し、その後削除することができます。
           */
          saveComponents: false,
        },
        ai: {
          provider: "openai",
          model: "gpt-5-mini",
          apiKey: process.env.OPEN_AI_API_KEY,
          applicationContext: "This app is an map app", // 注意: このアプリの説明をカスタマイズできます
        },
      };
      
      export default config;
      
      注意: 環境変数に OPEN_AI_API_KEY が設定されていることを確認してください。
      この構成ファイルを通じて、ローカライズされた URL、ミドルウェアのリダイレクト、クッキー名、コンテンツ宣言の場所と拡張子、コンソールでの Intlayer ログの無効化などを設定できます。利用可能なパラメータの完全なリストについては、構成ドキュメント を参照してください。
    3. Vite 構成に Intlayer を統合する

      構成に intlayer プラグインを追加します。

      vite.config.ts
      import { defineConfig } from "vite";
      import react from "@vitejs/plugin-react-swc";
      import { intlayer } from "vite-intlayer";
      
      // https://vitejs.dev/config/
      export default defineConfig({
        plugins: [
          react(),
          intlayer({
            proxy: {
              ignore: (req) => req.url?.startsWith("/api"),
            },
          }),
        ],
      });
      
      intlayer() Vite プラグインは、Intlayer を Vite と統合するために使用されます。コンテンツ宣言ファイルの構築を確実にし、開発モードでそれらを監視します。Vite アプリケーション内で Intlayer 環境変数を定義します。さらに、パフォーマンスを最適化するためのエイリアスを提供します。
      intlayerCompiler() Vite プラグインは、コンポーネントからコンテンツを抽出し、.content ファイルを書き出すために使用されます。
      Intlayer v9 以降、コンパイラは intlayer() プラグインに直接バンドルされており、compiler.enabledcompiler.output パスで設定されると自動的に有効になります。下記に示すように intlayerCompiler() を個別に登録することはオプションになりました — また追加された場合は自動的に重複排除されます。v9 リリースノートを参照してください。
    4. コードをコンパイルする

      デフォルトのロケールでハードコードされた文字列を使用してコンポーネントを記述するだけです。残りはコンパイラが処理します。

      ページの表示例:

      src/App.tsx
      import { useState, type FC } from "react";
      import reactLogo from "./assets/react.svg";
      import viteLogo from "/vite.svg";
      import "./App.css";
      import { IntlayerProvider } from "react-intlayer";
      
      const AppContent: FC = () => {
        const [count, setCount] = useState(0);
      
        return (
          <>
            <div>
              <a href="https://vitejs.dev" target="_blank">
                <img src={viteLogo} className="logo" alt="Vite logo" />
              </a>
              <a href="https://react.dev" target="_blank">
                <img src={reactLogo} className="logo react" alt="React logo" />
              </a>
            </div>
            <h1>Vite + React</h1>
            <div className="card">
              <button onClick={() => setCount((count) => count + 1)}>
                count is {count}
              </button>
              <p>
                Edit <code>src/App.tsx</code> and save to test HMR
              </p>
            </div>
            <p className="read-the-docs">
              Click on the Vite and React logos to learn more
            </p>
          </>
        );
      };
      
      const App: FC = () => (
        <IntlayerProvider>
          <AppContent />
        </IntlayerProvider>
      );
      
      export default App;
      
      i18n/app-content.content.json
      {
        key: "app-content",
        content: {
          nodeType: "translation",
          translation: {
            en: {
              viteLogo: "Vite logo",
              reactLogo: "React logo",
              title: "Vite + React",
              countButton: "count is",
              editMessage: "Edit",
              hmrMessage: "and save to test HMR",
              readTheDocs: "Click on the Vite and React logos to learn more",
            },
            fr: {
              viteLogo: "Logo Vite",
              reactLogo: "Logo React",
              title: "Vite + React",
              countButton: "compte est",
              editMessage: "Modifier",
              hmrMessage: "et enregistrer pour tester HMR",
              readTheDocs: "Cliquez sur les logos Vite et React pour en savoir plus",
            },
          }
        }
      }
      
      src/App.tsx
      import { useState, type FC } from "react";
      import reactLogo from "./assets/react.svg";
      import viteLogo from "/vite.svg";
      import "./App.css";
      import { IntlayerProvider, useIntlayer } from "react-intlayer";
      
      const AppContent: FC = () => {
        const [count, setCount] = useState(0);
        const content = useIntlayer("app-content");
      
        return (
          <>
            <div>
              <a href="https://vitejs.dev" target="_blank">
                <img src={viteLogo} className="logo" alt={content.viteLogo.value} />
              </a>
              <a href="https://react.dev" target="_blank">
                <img
                  src={reactLogo}
                  className="logo react"
                  alt={content.reactLogo.value}
                />
              </a>
            </div>
            <h1>{content.title}</h1>
            <div className="card">
              <button onClick={() => setCount((count) => count + 1)}>
                {content.countButton} {count}
              </button>
              <p>
                {content.editMessage} <code>src/App.tsx</code> {content.hmrMessage}
              </p>
            </div>
            <p className="read-the-docs">{content.readTheDocs}</p>
          </>
        );
      };
      
      const App: FC = () => (
        <IntlayerProvider>
          <AppContent />
        </IntlayerProvider>
      );
      
      export default App;
      
      • IntlayerProvider は、ネストされたコンポーネントにロケールを提供するために使用されます。
    5. コンテンツの言語を変更する

      オプション

      コンテンツの言語を変更するには、useLocale フックによって提供される setLocale 関数を使用できます。この関数を使用すると、アプリケーションのロケールを設定し、それに応じてコンテンツを更新できます。

      src/components/LocaleSwitcher.tsx
      import type { FC } from "react";
      import { Locales } from "intlayer";
      import { useLocale } from "react-intlayer";
      
      const LocaleSwitcher: FC = () => {
        const { setLocale } = useLocale();
      
        return (
          <button onClick={() => setLocale(Locales.English)}>
            Change Language to English
          </button>
        );
      };
      
      useLocale フックの詳細については、ドキュメント を参照してください。
    6. 欠落した翻訳を埋める

      オプション

      Intlayerは、欠落した翻訳を埋めるためのCLIツールを提供しています。intlayerコマンドを使用して、コードから欠落した翻訳をテストおよび埋めることができます。

      bash
      npx intlayer test         # 欠落した翻訳があるかテストする
      
      bash
      npx intlayer fill         # 欠落した翻訳を埋める
      

      詳細については、CLIドキュメントを参照してください。

    (任意)サイトマップと robots.txt(ビルド時生成)

    Intlayer は generateSitemapgetMultilingualUrls により、クローラ向けに整形した多言語の sitemap.xmlrobots.txtpublic/ に自動で書き出せます。通常は Vite よりに小さな Node スクリプトを走らせます(例: npm の predev / prebuild)。

    サイトマップ

    Intlayer のサイトマップ生成はロケール設定を踏まえ、クローラ向けのメタデータを含めます。

    生成されるサイトマップは xhtml:link(hreflang)をサポートします。単純な URL 列挙ではなく、各ページの言語版同士を双方向で結びます(例: /about/fr/about/about?lang=fr などルーティングに依存)。

    Robots.txt

    getMultilingualUrlsDisallow を、機微パスのすべての言語 URLに効かせます。

    1. プロジェクトルートに generate-seo.mjs を置く

    generate-seo.mjs
    import fs from "fs";
    import path from "path";
    import { fileURLToPath } from "url";
    import { generateSitemap, getMultilingualUrls } from "intlayer";
    
    const __dirname = path.dirname(fileURLToPath(import.meta.url));
    
    const SITE_URL = (process.env.SITE_URL || "http://localhost:5173").replace(
      /\/$/,
      ""
    );
    
    const pathList = [
      { path: "/", changefreq: "daily", priority: 1.0 },
      { path: "/about", changefreq: "monthly", priority: 0.7 },
    ];
    
    const sitemapXml = generateSitemap(pathList, { siteUrl: SITE_URL });
    fs.writeFileSync(path.join(__dirname, "public", "sitemap.xml"), sitemapXml);
    
    const getAllMultilingualUrls = (urls) =>
      urls.flatMap((url) => Object.values(getMultilingualUrls(url)));
    
    const disallowedPaths = getAllMultilingualUrls(["/admin", "/private"]);
    
    const robotsTxt = [
      "User-agent: *",
      "Allow: /",
      ...disallowedPaths.map((path) => `Disallow: ${path}`),
      "",
      `Sitemap: ${SITE_URL}/sitemap.xml`,
    ].join("\n");
    
    fs.writeFileSync(path.join(__dirname, "public", "robots.txt"), robotsTxt);
    
    console.log("SEO files generated successfully.");
    

    intlayer がインストールされている必要があります。本番では環境変数 SITE_URL を設定してください(CI など)。

    Node の ESM では generate-seo.mjs を推奨します。generate-seo.js にする場合は package.json"type": "module" などで ESM を有効にしてください。

    2. Vite より前にスクリプトを実行する

    package.json
    {
      "scripts": {
        "dev": "vite",
        "prebuild": "node generate-seo.mjs",
        "build": "vite build",
        "preview": "vite preview"
      }
    }
    

    pnpm や yarn を使う場合はコマンドを読み替えてください。CI から呼び出しても構いません。

    Git の構成

    Intlayer によって生成されたファイルを無視することをお勧めします。これにより、Git リポジトリへのコミットを避けることができます。

    これを行うには、.gitignore ファイルに次の指示を追加します。

    .gitignore
    # Intlayer によって生成されたファイルを無視する
    .intlayer
    

    VS Code 拡張機能

    Intlayer での開発体験を向上させるために、公式の Intlayer VS Code 拡張機能 をインストールできます。

    VS Code Marketplace からインストール

    この拡張機能は以下を提供します:

    • 翻訳キーの自動補完
    • 欠落している翻訳のリアルタイムエラー検出
    • 翻訳されたコンテンツのインラインプレビュー
    • 翻訳を簡単に作成および更新するためのクイックアクション

    拡張機能の使用方法の詳細については、Intlayer VS Code 拡張機能のドキュメント を参照してください。

    さらに進む

    さらに進むには、ビジュアルエディタ を実装するか、CMS を使用してコンテンツを外部化できます。