Featured image of post Next.js国際化:ルーティングとコンテンツ戦略 Featured image of post Next.js国際化:ルーティングとコンテンツ戦略

Next.js国際化:ルーティングとコンテンツ戦略

Next.jsの国際化(i18n)を包括的に解説。ルーティング戦略、ロケール検出、next-intl統合、多言語SEO、hreflangタグまで網羅。

はじめに

国際化(i18n)は現代のWebアプリケーションに必須の要件です。Next.jsはPages Routerの統合i18nルーティングから、App Routerのミドルウェアベースの柔軟なアプローチへと進化してきました。本記事では、ルーティング戦略、ロケール検出、コンテンツ管理、多言語SEOについて解説します。

主要な概念はロケール、デフォルトロケール、ロケール検出、そしてサブパスルーティングとドメインルーティングのトレードオフです。App Routerアプローチはより柔軟性を提供しますが、設定も増えます。

ルーティング戦略 — サブパス vs ドメイン

サブパスとドメインの選択はSEOとインフラに大きな影響を与えます。

基準サブパス(/ja/aboutドメイン(ja.example.com
SEO権威共有ドメイン権威ロケールごとに独立
ジオターゲティング弱い強い
インフラ単一デプロイ複数デプロイ
分析統一分割

ほとんどのプロジェクトでは、サブパスルーティングが推奨されます。App Routerでの実装はミドルウェアを使用してロケールプレフィックスを処理します。

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

const locales = ["ja", "en", "fr"];
const defaultLocale = "ja";

export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;
  const pathnameHasLocale = locales.some(
    (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
  );
  if (pathnameHasLocale) return;

  const locale = request.cookies.get("NEXT_LOCALE")?.value || defaultLocale;
  return NextResponse.redirect(new URL(`/${locale}${pathname}`, request.url));
}

export const config = {
  matcher: ["/((?!api|_next|favicon.ico).*)"],
};

ロケール検出とネゴシエーション

Next.jsはCookieからAccept-Languageヘッダー、デフォルトロケールの順にロケールを決定します。NEXT_LOCALE Cookieでユーザーの言語設定を永続化できます。

function getLocale(request: NextRequest): string {
  const cookieLocale = request.cookies.get("NEXT_LOCALE")?.value;
  if (cookieLocale && locales.includes(cookieLocale)) return cookieLocale;

  const acceptLanguage = request.headers.get("accept-language");
  if (acceptLanguage) {
    const preferred = acceptLanguage
      .split(",")
      .map((lang) => lang.split(";")[0].trim())
      .find((lang) => locales.includes(lang));
    if (preferred) return preferred;
  }

  return defaultLocale;
}

このネゴシエーションロジックにより、ユーザーは常に優先言語でコンテンツを表示できます。


next-intlによるコンテンツ管理

next-intlはApp Routerのi18nに推奨されるライブラリです。型安全な翻訳キー、名前空間分割、効率的なメッセージ読み込みを提供します。

// middleware.ts
import createMiddleware from "next-intl/middleware";
export default createMiddleware({ locales: ["ja", "en"], defaultLocale: "ja" });
export const config = { matcher: ["/((?!api|_next).*)"] };

翻訳ファイルは名前空間ごとに整理します:

{
  "navigation": { "home": "ホーム", "about": "概要" },
  "home": { "title": "ようこそ", "description": "ホームページへようこそ" }
}

コンポーネントではuseTranslationsフックを使用します:

import { useTranslations } from "next-intl";
function HomePage() {
  const t = useTranslations("home");
  return <h1>{t("title")}</h1>;
}

多言語サイトのSEO

クロス言語SEOには適切なhreflangタグと正規URLが必須です。各ページに自己参照と全代替hreflangリンクを含めます。

export async function generateMetadata({ params }: Props) {
  const { locale } = await params;
  return {
    alternates: {
      languages: {
        ja: "/ja/about",
        en: "/en/about",
        "x-default": "/ja/about",
      },
    },
  };
}

よくある落とし穴は、ロケール間の重複コンテンツ、hreflang戻りリンクの欠如、一貫性のないロケールURLパターンです。Googleのガイドラインでは各言語バージョンが他の全言語バージョンにリンクを戻すことが求められます。


まとめ

ほとんどのプロジェクトでは、next-intlを使用したサブパスルーティングが最適なバランスを提供します。適切なロケール検出ミドルウェア、名前空間ごとの翻訳ファイル整理、完全なhreflangメタデータの実装に投資してください。公式のNext.js i18nサンプルとnext-intlドキュメントが実装の参考になります。