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

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

問題

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

解決策

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

手順

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>
  );
}

この関数は、アプリが/en/es/frをサポートしていることをNext.jsに通知します。他のパス(/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パラメータはすべてのページで利用できます。