Next.js(Pages Router)v16でロケールベースのルーティングを実装する方法

ロケールセグメントを使用したルーティングの設定

問題

多言語アプリケーションを構築する際、すべてを形作る基本的な決定事項があります。それは、アプリケーションがどの言語を表示するかをどのように判断するかということです。明示的なメカニズムがなければ、URL /aboutは曖昧になります。これはあらゆる言語のコンテンツを表す可能性があります。ユーザーは特定の言語バージョンへのリンクを共有できず、検索エンジンはどのバージョンがどのオーディエンスに属するかを理解するのに苦労します。この曖昧さは、特定の言語でコンテンツを識別またはブックマークする明確な方法がないため、ユーザーエクスペリエンスとSEOの両方に問題を引き起こします。

解決策

Next.jsの組み込みi18nルーティングサポートを設定することで、言語識別子をURLパスに直接配置します。サポートする言語とデフォルトの言語をNext.js設定で宣言します。Next.jsは自動的にルーティングを処理し、/fr/about/nl-NL/aboutのようなパスを利用可能にします。一方、デフォルトの言語にはプレフィックスが付きません。これにより、すべてのパスが特定の言語に固有のものとなり、ユーザーと検索エンジンの両方にとって曖昧さが解消されます。

手順

1. next.config.jsにi18n設定を追加する

next.config.jsファイルにi18n設定を追加して、アプリケーションがサポートする言語を宣言します。

module.exports = {
  i18n: {
    locales: ["en-US", "fr", "nl-NL"],
    defaultLocale: "en-US",
  },
};

ロケールはUTSロケール識別子であり、ロケールを定義するための標準化された形式で、一般的にダッシュで区切られた言語、地域、スクリプトで構成されます。defaultLocaleは、ロケールプレフィックスのないパスにアクセスする際に使用されます。

2. ページでロケール情報にアクセスする

useRouter()フックを使用して、ページコンポーネント内でロケール情報にアクセスします。

import { useRouter } from "next/router";

export default function AboutPage() {
  const router = useRouter();
  const { locale, locales, defaultLocale } = router;

  return (
    <div>
      <h1>About Us</h1>
      <p>Current locale: {locale}</p>
    </div>
  );
}

localeプロパティには現在アクティブなロケールが含まれ、localesには設定されたすべてのロケールが含まれ、defaultLocaleには設定されたデフォルトロケールが含まれます。

3. データ取得関数でロケールにアクセスする

getStaticPropsまたはgetServerSidePropsでページを事前レンダリングする場合、ロケール情報はコンテキストで提供されます。

import { GetStaticProps } from "next";

export const getStaticProps: GetStaticProps = async (context) => {
  const { locale } = context;

  const messages = await import(`../messages/${locale}.json`);

  return {
    props: {
      messages: messages.default,
    },
  };
};

これにより、アクティブなロケールに基づいて、ビルド時またはリクエスト時にロケール固有のデータを読み込むことができます。

4. ロケール間のリンク

next/linkをlocaleプロパティと共に使用して、別のロケールに遷移します。

import Link from "next/link";

export default function LanguageSwitcher() {
  return (
    <nav>
      <Link href="/about" locale="en-US">
        English
      </Link>
      <Link href="/about" locale="fr">
        Français
      </Link>
      <Link href="/about" locale="nl-NL">
        Nederlands
      </Link>
    </nav>
  );
}

localeプロパティが指定されていない場合、クライアント遷移中は現在アクティブなロケールが使用されます。localeプロパティを使用すると、ユーザーは同じ論理ページに留まりながら言語を切り替えることができます。

5. すべてのロケールの静的パスを生成する

getStaticPathsを活用する場合、設定されたロケールはコンテキストパラメータのlocalesで提供され、設定されたデフォルトロケールはdefaultLocaleで提供されます。

import { GetStaticPaths } from "next";

export const getStaticPaths: GetStaticPaths = async (context) => {
  const { locales } = context;

  const paths = locales.flatMap((locale) => [
    { params: { slug: "getting-started" }, locale },
    { params: { slug: "advanced" }, locale },
  ]);

  return {
    paths,
    fallback: false,
  };
};

これにより、動的ページのすべてのロケールバージョンがビルド時に事前レンダリングされます。