Creation:2026-01-10Last update:2026-05-31

    Next.js 16 ウェブサイトを翻訳する(ページパスに [locale] を含めない). Intlayer を使った国際化 (i18n)

    www.youtube.com

    GitHub の アプリケーションテンプレート を参照してください。

    目次

    代替手段ではなく Interlayer を使用する理由

    「next-intl」や「i18next」などの主要なソリューションと比較して、Intlayer は次のような統合された最適化を備えたソリューションです。

    Next.js を完全にカバー

    Intlayer は、効率的なレンダリングのために サーバー コンポーネント と連携するように最適化されており、Turbopack と完全に互換性があります。静的レンダリングをブロックせず、ミドルウェアとスケーリング国際化 (i18n) に必要なすべての機能を提供します。

    Intlayer は Next.js 12、13、14、15、および 16 と互換性があります。 Next.js Pages Router を使用している場合は、この ガイド を参照してください。 ロケール ルーティングは、SEO、バンドル サイズ、パフォーマンスに役立ちます。必要ない場合は、このガイドを参照してください。 App Router を使用した Next.js 12、13、14、および 15 については、この ガイド を参照してください。

    バンドルサイズ

    大量の JSON ファイルをページにロードするのではなく、必要なコンテンツのみをロードします。 Intlayer は、バンドルとページのサイズを最大 50% 削減するのに役立ちます。

    保守性

    アプリケーションのコンテンツのスコープを設定すると、大規模なアプリケーションの メンテナンスが容易になります。コンテンツ コードベース全体を確認するという精神的な負担を負うことなく、単一の機能フォルダーを複製または削除できます。さらに、Intlayer は完全に型指定されており、コンテンツの正確性を保証します。

    AI エージェント

    コンテンツを同じ場所に配置すると、大規模言語モデル (LLM) によって 必要なコンテキストが削減されます。 Intlayer には、翻訳の欠落をテストする CLILSPMCP などのツール スイートも付属しています。および エージェント スキル により、AI エージェントの開発者エクスペリエンス (DX) がさらにスムーズになります。

    オートメーション

    AI プロバイダーの費用で、選択した LLM を使用して CI/CD パイプラインで自動化を変換します。 Intlayer は、コンテンツ抽出を自動化する コンパイラー と、バックグラウンドでの翻訳を支援する Web プラットフォーム も提供します。

    パフォーマンス

    大量の JSON ファイルをコンポーネントに接続すると、パフォーマンスと反応性の問題が発生する可能性があります。 Intlayer は、ビルド時のコンテンツの読み込みを最適化します。

    非開発によるスケーリング

    Intlayer は単なる i18n ソリューションではなく、自己ホスト型 ビジュアル エディター完全な CMS を提供します。 リアルタイムで多言語コンテンツを管理できるようになり、翻訳者、コピーライター、その他のチーム メンバーとのコラボレーションがシームレスになります。コンテンツはローカルおよび/またはリモートに保存できます。


    Next.js アプリケーションで Intlayer をセットアップする手順

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

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

      bash
      npm install intlayer next-intlayernpx intlayer init
      • intlayer

        国際化(internationalization)向けのコアパッケージで、設定管理、翻訳、コンテンツ宣言、transpilation、そして[CLIコマンド](/ja/doc/concept/cli)用のツールを提供します。

      • next-intlayer

      IntlayerをNext.jsと統合するパッケージです。Next.js向けの国際化のためのコンテキストプロバイダーとフックを提供します。さらに、WebpackTurbopackとIntlayerを統合するためのNext.jsプラグイン、およびユーザーの優先ロケールの検出、クッキー管理、URLリダイレクト処理のためのプロキシも含まれます。

    2. プロジェクトを設定する

      以下が作成する最終的な構成です:

      bash
      .├── src│   ├── app│   │   ├── layout.tsx│   │   ├── page.content.ts│   │   └── page.tsx│   ├── components│   │   ├── clientComponentExample│   │   │   ├── client-component-example.content.ts│   │   │   └── ClientComponentExample.tsx│   │   ├── localeSwitcher│   │   │   ├── localeSwitcher.content.ts│   │   │   └── LocaleSwitcher.tsx│   │   └── serverComponentExample│   │       ├── server-component-example.content.ts│   │       └── ServerComponentExample.tsx│   └── proxy.ts├── intlayer.config.ts├── next.config.ts├── package.json└── tsconfig.json
      ロケールルーティングを使用したくない場合、intlayerは単純なプロバイダー/フックとして使用できます。詳細はこのガイドを参照してください。

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

      intlayer.config.ts
      import { Locales, type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [
            Locales.ENGLISH,
            Locales.FRENCH,
            Locales.SPANISH,
            // 他のロケール
          ],
          defaultLocale: Locales.ENGLISH,
        },
        routing: {
          mode: "search-params", // または `no-prefix` - ミドルウェア検出に便利
        },
      };
      
      export default config;
      この設定ファイルを使って、ローカライズされた URL、プロキシリダイレクト、クッキー名、コンテンツ宣言の場所と拡張子、コンソール上の Intlayer ログの無効化などを設定できます。利用可能なパラメータの完全な一覧は、設定ドキュメント を参照してください。
    3. Next.js の設定に Intlayer を統合する

      Intlayer を使用するよう Next.js の設定を構成します:

      next.config.ts
      import type { NextConfig } from "next";
      import { withIntlayer } from "next-intlayer/server";
      
      const nextConfig: NextConfig = {
        /* ここに設定オプションを記述 */
      };
      
      export default withIntlayer(nextConfig);
      withIntlayer() の Next.js プラグインは Intlayer を Next.js に統合するために使用されます。コンテンツ宣言ファイルの生成を行い、開発モードでそれらを監視します。Webpack または Turbopack 環境内で Intlayer の環境変数を定義します。さらに、パフォーマンス最適化のためのエイリアスを提供し、サーバーコンポーネントとの互換性を確保します。

      withIntlayer() 関数は Promise 関数です。ビルド開始前に Intlayer の辞書を準備することを可能にします。他のプラグインと一緒に使用する場合は、await できます。例:

      ts
      const nextConfig = await withIntlayer(nextConfig);const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);export default nextConfigWithOtherPlugins;

      同期的に使用したい場合は、withIntlayerSync() 関数を使用できます。例:

      ts
      const nextConfig = withIntlayerSync(nextConfig);const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);export default nextConfigWithOtherPlugins;

      Intlayer は、コマンドラインフラグ(--webpack--turbo、または --turbopack)や現在の Next.js のバージョンに基づいて、プロジェクトが webpack または Turbopack のどちらを使用しているかを自動的に検出します。

      next>=16 以降、Rspack を使用している場合は、Turbopack を無効化して Intlayer に webpack 設定を明示的に使用させる必要があります:

      ts
      withRspack(withIntlayer(nextConfig, { enableTurbopack: false }));
    4. 動的ロケールルートを定義する

      RootLayout の中身をすべて削除し、次のコードに置き換えてください:

      src/app/layout.tsx
      import type { Metadata } from "next";
      import type { ReactNode } from "react";
      import "./globals.css";
      import { IntlayerClientProvider, LocalPromiseParams } from "next-intlayer";
      import { getHTMLTextDir, getIntlayer } from "intlayer";
      import { getLocale } from "next-intlayer/server";
      export { generateStaticParams } from "next-intlayer";
      
      export const generateMetadata = async (): Promise<Metadata> => {
        const locale = await getLocale();
        const { title, description, keywords } = getIntlayer("metadata", locale);
      
        return {
          title,
          description,
          keywords,
        };
      };
      
      const RootLayout = async ({
        children,
      }: Readonly<{
        children: ReactNode;
      }>) => {
        const locale = await getLocale();
      
        return (
          <html lang={locale} dir={getHTMLTextDir(locale)}>
            <IntlayerClientProvider defaultLocale={locale}>
              <body>{children}</body>
            </IntlayerClientProvider>
          </html>
        );
      };
      
      export default RootLayout;
      src/app/metadata.content.ts
      import { t, type Dictionary } from "intlayer";
      import type { Metadata } from "next";
      
      const metadataContent = {
        key: "metadata",
        content: {
          title: t({
            ja: "ワークフローを合理化する私のプロジェクトのタイトル",
            en: "My Project Title",
            fr: "Le Titre de mon Projet",
            es: "El Título de mi Proyecto",
          }),
      
          description: t({
            ja: "ワークフローを効率化し、生産性を向上させるために設計された革新的なプラットフォームをご紹介します。",
            en: "Discover our innovative platform designed to streamline your workflow and boost productivity.",
            fr: "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",
            es: "Descubra nuestra plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad.",
          }),
      
          keywords: t({
            ja: ["イノベーション", "生産性", "ワークフロー", "SaaS"],
            en: ["innovation", "productivity", "workflow", "SaaS"],
            fr: ["innovation", "productivité", "flux de travail", "SaaS"],
            es: ["innovación", "productividad", "flujo de trabajo", "SaaS"],
          }),
        },
      } satisfies Dictionary<Metadata>;
      
      export default metadataContent;
      src/app/page.content.ts
      import { t, type Dictionary } from "intlayer";
      
      const pageContent = {
        key: "page",
        content: {
          getStarted: {
            main: t({
              ja: "編集して始めましょう",
              en: "Get started by editing",
              fr: "Commencez par éditer",
              es: "Comience por editar",
            }),
            pageLink: "src/app/page.tsx",
          },
        },
      } satisfies Dictionary;
      
      export default pageContent;
      コンテンツの宣言は、アプリケーション内の任意の場所に定義できます。ただし、それらが contentDir ディレクトリ(デフォルトは ./src)に含まれており、コンテンツ宣言ファイルの拡張子が一致している必要があります(デフォルト: .content.{json,ts,tsx,js,jsx,mjs,cjs,md,mdx,yaml,yml})。
      詳細は、コンテンツ宣言のドキュメント を参照してください。
    5. コード内でコンテンツを利用する

      アプリケーション全体からコンテンツ辞書にアクセスします:

      src/app/page.tsx
      import type { FC } from "react";
      import { ClientComponentExample } from "@components/clientComponentExample/ClientComponentExample";
      import { ServerComponentExample } from "@components/serverComponentExample/ServerComponentExample";
      import {
        IntlayerServerProvider,
        useIntlayer,
        getLocale,
      } from "next-intlayer/server";
      import { NextPage } from "next";
      import { headers, cookies } from "next/headers";
      
      const PageContent: FC = () => {
        const content = useIntlayer("page");
      
        return (
          <>
            <p>{content.getStarted.main}</p>
            <code>{content.getStarted.pageLink}</code>
          </>
        );
      };
      
      const Page: NextPage = async () => {
        // Next.js 15+ では headers と cookies を await してください
        const headerList = await headers();
        const cookieList = await cookies();
      
        const locale = await getLocale({
          // まず intlayer のクッキーを確認します(デフォルト: 'INTLAYER_LOCALE')
          getCookie: (name) => cookieList.get(name)?.value,
      
          // 次に intlayer ヘッダーを確認します(デフォルト: 'x-intlayer-locale')
          // 最後に accept-language ヘッダーを確認します('accept-language')
          getHeader: (name) => headerList.get(name),
        });
      
        return (
          <IntlayerServerProvider locale={locale}>
            <PageContent />
            <ServerComponentExample />
            <ClientComponentExample />
          </IntlayerServerProvider>
        );
      };
      
      export default Page;
      src/components/serverComponentExample/ServerComponentExample.tsx
      import type { FC } from "react";
      import { useIntlayer } from "next-intlayer/server";
      
      export const ServerComponentExample: FC = () => {
        const content = useIntlayer("server-component-example"); // 関連コンテンツの宣言を作成
      
        return (
          <div>
            <h2>{content.title}</h2>
            <p>{content.content}</p>
          </div>
        );
      };
      alttitlehrefaria-label などの string 属性でコンテンツを使用する場合は、関数の値を呼び出す必要があります。例えば:
      html
      <img src="{content.image.src.value}" alt="{content.image.value}" /><img src="{content.image.src.toString()}" alt="{content.image.toString()}" /><img src="{String(content.image.src)}" alt="{String(content.image)}" />
      useIntlayer フックの詳細はドキュメントを参照してください。
    6. ロケール検出のためにプロキシを設定

      ユーザーの優先ロケールを検出するようにプロキシを設定します:

      src/proxy.ts
      export { intlayerProxy as proxy } from "next-intlayer/proxy";
      
      export const config = {
        matcher:
          "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
      };
      intlayerProxy はユーザーの優先ロケールを検出し、設定に記載された適切な URL へリダイレクトするために使用されます。さらに、ユーザーの優先ロケールをクッキーに保存することも可能にします。
      複数のプロキシを連結する必要がある場合(例えば、認証やカスタムプロキシと intlayerProxy を組み合わせる場合)、Intlayer は multipleProxies というヘルパーを提供しています。
      ts
      import { multipleProxies, intlayerProxy } from "next-intlayer/proxy";import { customProxy } from "@utils/customProxy";export const proxy = multipleProxies([intlayerProxy, customProxy]);
    7. コンテンツの言語を変更する

      Next.jsでコンテンツの言語を切り替えるには、推奨される方法はLinkコンポーネントを使用してユーザーを適切なローカライズされたページにリダイレクトすることです。Linkコンポーネントはページのプリフェッチを可能にし、フルページのリロードを回避するのに役立ちます。

      src/components/localeSwitcher/LocaleSwitcher.tsx
      "use client";
      
      import type { FC } from "react";
      import { Locales, getHTMLTextDir, getLocaleName } from "intlayer";
      import { useLocale } from "next-intlayer";
      
      export const LocaleSwitcher: FC = () => {
        const { locale, availableLocales, setLocale } = useLocale();
      
        return (
          <div>
            <button popoverTarget="localePopover">{getLocaleName(locale)}</button>
            <div id="localePopover" popover="auto">
              {availableLocales.map((localeItem) => (
                <button
                  key={localeItem}
                  aria-current={locale === localeItem ? "page" : undefined}
                  onClick={() => setLocale(localeItem)}
                >
                  <span>
                    {/* ロケール - 例: FR */}
                    {localeItem}
                  </span>
                  <span>
                    {/* 自身のロケールでの言語名 - 例: Français */}
                    {getLocaleName(localeItem, locale)}
                  </span>
                  <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
                    {/* 現在のロケールでの言語名 - 例: 現在のロケールが Locales.SPANISH の場合: Francés */}
                    {getLocaleName(localeItem)}
                  </span>
                  <span dir="ltr" lang={Locales.ENGLISH}>
              {availableLocales.map((localeItem) => (
                <button
                  key={localeItem}
                  aria-current={locale === localeItem ? "page" : undefined}
                  onClick={() => setLocale(localeItem)}
                >
                  <span>
                    {/* ロケール - 例: FR */}
                    {localeItem}
                  </span>
                  <span>
                    {/* 自身のロケールでの言語名 - 例: Français */}
                    {getLocaleName(localeItem, locale)}
                  </span>
                  <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
                    {/* 現在のロケールでの言語名 - 例: 現在のロケールが Locales.SPANISH の場合: Francés */}
                    {getLocaleName(localeItem)}
                  </span>
                  <span dir="ltr" lang={Locales.ENGLISH}>
                    {/* 英語での言語名, 例: French */}
                    {getLocaleName(localeItem, Locales.ENGLISH)}
                  </span>
                </button>
              ))}
            </div>
          </div>
        );
      };
      代替方法として、useLocale フックが提供する setLocale 関数を使用できます。この関数はページのプリフェッチを許可しません。詳細は useLocale フックのドキュメント を参照してください。

      ドキュメント参照:

    8. Server Actions で現在のロケールを取得する

      Server Action の内部でアクティブなロケールが必要な場合(例: メールのローカライズやロケール対応のロジックを実行する場合)、next-intlayer/server から getLocale を呼び出してください:

      src/app/actions/getLocale.ts
      "use server";import { getLocale } from "next-intlayer/server";export const myServerAction = async () => {  const locale = await getLocale();  // ロケールを使って処理を行います};

      getLocale 関数はユーザーのロケールを決定するためにカスケード戦略を採用します:

      1. まず、プロキシによって設定されている可能性のあるロケール値についてリクエストヘッダーを確認します
      2. ヘッダーにロケールが見つからない場合、クッキーに保存されたロケールを探します
      3. クッキーが見つからない場合、ブラウザ設定からユーザーの優先言語を検出しようとします
      4. 最後の手段として、アプリケーションで設定されたデフォルトロケールにフォールバックします

      これにより、利用可能なコンテキストに基づいて最も適切なロケールが選択されます。

    9. バンドルサイズを最適化する

      next-intlayer を使用すると、辞書はデフォルトで各ページのバンドルに含まれます。バンドルサイズを最適化するために、Intlayer はマクロを使用して useIntlayer の呼び出しをインテリジェントに置き換えるオプションの SWC プラグインを提供しています。これにより、辞書は実際にそれらを使用するページのバンドルにのみ含まれるようになります。

      この最適化を有効にするには、@intlayer/swc パッケージをインストールしてください。インストール後、next-intlayer は自動的にプラグインを検出して使用します:

      bash
      npm install @intlayer/swc --save-dev
      注意: この最適化は Next.js 13 以降でのみ利用可能です。
      注意: SWCプラグインは Next.js 上でまだ実験的なため、このパッケージはデフォルトでインストールされません。将来的に変更される可能性があります。

      注意: オプションを importMode: 'dynamic' または importMode: 'fetch' に設定すると、Suspense に依存するため、useIntlayer の呼び出しを Suspense 境界でラップする必要があります。つまり、Page / Layout コンポーネントのトップレベルで useIntlayer を直接使用することはできません。

    Turbopackで辞書の変更を監視する

    Turbopackを開発サーバーとしてnext devコマンドで使用している場合、辞書の変更はデフォルトでは自動的に検出されません。

    この制限は、Turbopackがコンテンツファイルの変更を監視するためのwebpackプラグインを並列で実行できないために発生します。回避するには、intlayer watchコマンドを使用して、開発サーバーとIntlayerのビルドウォッチャーを同時に実行する必要があります。

    package.json
    {  // ... 既存の package.json 設定  "scripts": {    // ... 既存の scripts 設定    "dev": "intlayer watch --with 'next dev'",  },}
    next-intlayer@<=6.x.x を使用している場合、Next.js 16 アプリケーションを Turbopack と正しく動作させるために --turbopack フラグを維持する必要があります。この制約を回避するには next-intlayer@>=7.x.x の使用を推奨します。

    TypeScript の設定

    Intlayer は TypeScript の利点を活かすためにモジュール拡張 (module augmentation) を使用し、コードベースをより堅牢にします。

    オートコンプリート

    翻訳エラー

    TypeScript の設定に自動生成された型が含まれていることを確認してください。

    tsconfig.json
    {  // ... 既存の TypeScript 設定  "include": [    // ... 既存의 TypeScript 設定    ".intlayer/**/*.ts", // 自動生成された型を含める  ],}

    Git 設定

    Intlayer によって生成されたファイルは無視することを推奨します。これにより、これらのファイルを Git リポジトリにコミットすることを避けられます。

    これを行うには、次の内容を .gitignore ファイルに追加してください:

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

    VS Code 拡張機能

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

    VS Code Marketplace からインストール

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

    • Autocompletion: 翻訳キーの補完。
    • リアルタイムのエラーチェック: 翻訳が欠落している箇所の検出。
    • 翻訳されたコンテンツのインラインプレビュー
    • 翻訳を簡単に作成・更新するためのクイックアクション

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

    さらに進む

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