言語ベースのルーティング

Next.js(Appルーター)での言語ベースのルーティングの設定

問題

複数の言語をサポートするアプリケーションでは、/aboutのような単一のURLは本質的に曖昧です。このURLにアクセスするユーザーはデフォルト言語でコンテンツを受け取りますが、異なる言語バージョンのページにリンクしたりブックマークしたりする方法がありません。この曖昧さは検索エンジンも混乱させ、すべての言語バージョンがインデックスされなかったり、混在したりする可能性があります。

解決策

URLパスに直接言語識別子を組み込みます(例:/en/about/fr/about)。これにより、すべてのパスが特定の言語に固有のものとなり、ユーザーと検索エンジンの両方にとっての曖昧さが解消されます。

手順

1. 動的な言語セグメントを作成する

Next.js App Routerでは、appディレクトリのルートに動的セグメントフォルダを作成して言語ルーティングを処理します。app内に[lang]という名前の新しいフォルダを作成し、メインのpage.tsxファイルをその中に移動します。

// app/[lang]/page.tsx

export default function Home({ params }: { params: { lang: string } }) {
  return (
    <div>
      <h1>Home page</h1>
      <p>Current language: {params.lang}</p>
    </div>
  );
}

この[lang]フォルダはURLの最初の部分(例:'en'や'fr')を取得し、それをparamsオブジェクト内のlangプロパティとしてページコンポーネントに渡します。これで/en/frのようなURLでページにアクセスできるようになります。

2. ルートレイアウトを更新する

ルートのlayout.tsxapp/[lang]フォルダ内に移動する必要があります。これもlangパラメータを受け取り、アクセシビリティとSEOのために<html>タグのlang属性を設定するために使用します。

// app/[lang]/layout.tsx

export default function RootLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { lang: string };
}) {
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  );
}

このレイアウトは特定の言語内のすべてのページをラップするようになりました。ここでlang属性を設定することで、ブラウザにページコンテンツがどの言語であるかを伝えます。

3. サポートする言語を定義する

Next.jsに有効な言語セグメントを伝えるには、ルートレイアウトからgenerateStaticParams関数をエクスポートします。これによりNext.jsはビルド時にこれらのルートを静的に生成できます。

// app/[lang]/layout.tsx

export async function generateStaticParams() {
  return [{ lang: 'en' }, { lang: 'es' }, { lang: 'fr' }];
}

export default function RootLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { lang: string };
}) {
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  );
}

この関数はNext.jsにアプリが/en/es/frをサポートしていることを通知します。他のパス(/deなど)へのリクエストは404 Not Foundページになります。

4. ネストされたルートを追加する

アプリの他のすべてのページは[lang]フォルダ内に作成されます。例えば、「about」ページを作成するには、app/[lang]/about/page.tsxを追加します。

// app/[lang]/about/page.tsx

export default function AboutPage({ params }: { params: { lang: string } }) {
  return (
    <div>
      <h1>About page</h1>
      <p>Current language: {params.lang}</p>
    </div>
  );
}

このファイルは自動的に/en/about/es/about/fr/aboutでアクセス可能なルートを作成します。翻訳されたコンテンツを正しく取得する必要がある場合、langパラメータはすべてのページで利用可能です。