@shinyaz

Next.js App Router の [locale] 配下で 404 ページを正しく表示するには catch-all ルートが必要

約1分

/ja/存在しないページ にアクセスすると、日本語の 404 ページではなく /en にリダイレクトされてしまう問題にハマった。

原因は app/not-found.tsxredirect("/en") していたこと(defaultLocale"en")。[locale] 配下にマッチしないパスがあると、[locale]/not-found.tsx ではなくルートの not-found.tsx が呼ばれてしまう。

解決策は catch-all ルートの追加だ。

src/app/[locale]/[...slug]/page.tsx
import { notFound } from "next/navigation";
 
export default function CatchAllPage() {
  notFound();
}

これだけでは不十分で、ルートの not-found.tsxredirect() ではなく 404 UI を表示するように変更する必要がある。Next.js App Router ではルートの not-found.tsx も呼ばれるケースがあるためだ。not-found.tsx 側では headers() からロケールを検出する。

src/app/[locale]/not-found.tsx
const headersList = await headers();
const pathname = headersList.get("x-pathname") ?? "";
const referer = headersList.get("referer") ?? "";
const candidate = getLocaleFromUrl(pathname) || getLocaleFromUrl(referer) || defaultLocale;
const locale = isValidLocale(candidate) ? candidate : defaultLocale;

x-pathname(ミドルウェアで設定)を優先し、取れなければ referer にフォールバックする。Vercel の公式ガイド「How to internationalise error pages in Next.js App Router」にも同じパターンが記載されている。

共有する

田原 慎也

田原 慎也

ソリューションアーキテクト @ AWS

AWS ソリューションアーキテクトとして金融業界のお客様を中心に技術支援を行っています。クラウドアーキテクチャや AI/ML に関する学びをこのサイトで発信しています。このサイトの内容は個人の見解であり、所属企業の公式な意見や見解を代表するものではありません。