Next.js(Pages Router)v16でURLのロケールパラメータを検証する方法
サポートされていないロケールコードを適切に処理する
問題
ロケールコードがURL構造の一部になると、検証が必要なユーザー入力に変わります。訪問者は、/en/aboutのような有効なロケールと同じように、/xx/aboutや/gibberish/contactと入力できます。検証がない場合、アプリケーションがクラッシュしたり、壊れたコンテンツを表示したり、混乱を招くエラーメッセージを表示したりする可能性があります。無効なロケールURLに遭遇したユーザーには、有効なロケールへのリダイレクトまたは何が問題だったかを理解できる適切な「Not Found」レスポンスを通じて、明確な進路が必要です。
解決策
リクエストがページコンポーネントに到達する前に、サポートされているロケールのリストに対して受信ロケールパラメータを検証します。Next.jsミドルウェアを使用してリクエストをインターセプトし、URL内のロケールがサポートされている値と一致するかどうかを確認し、適切に応答します。無効なロケールの場合は、ユーザーをデフォルトのロケールにリダイレクトするか、リクエストを書き換えて404ページを表示します。これにより、有効なロケールコードのみがコンテンツのレンダリングに進み、無効なコードはユーザーエクスペリエンスを損なうことなく適切に処理されます。
手順
1. Next.js設定でサポートされているロケールを定義する
next.config.jsでi18n設定を構成し、アプリケーションがサポートするロケールとデフォルトとして機能するロケールを宣言します。
module.exports = {
i18n: {
locales: ["en", "fr", "de"],
defaultLocale: "en",
localeDetection: false,
},
};
localeDetectionをfalseに設定すると、ブラウザの設定に基づく自動リダイレクトが防止され、ロケール処理を完全に制御できます。
2. ロケールパラメータを検証するミドルウェアを作成する
プロジェクトのルートにmiddleware.tsファイルを作成するか、使用している場合はsrcフォルダ内に作成します。
import { NextRequest, NextResponse } from "next/server";
const SUPPORTED_LOCALES = ["en", "fr", "de"];
const DEFAULT_LOCALE = "en";
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
const pathnameHasLocale = SUPPORTED_LOCALES.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`,
);
if (!pathnameHasLocale) {
return;
}
const localeInPath = pathname.split("/")[1];
if (!SUPPORTED_LOCALES.includes(localeInPath)) {
const url = request.nextUrl.clone();
url.pathname = pathname.replace(`/${localeInPath}`, `/${DEFAULT_LOCALE}`);
return NextResponse.redirect(url);
}
}
export const config = {
matcher: ["/((?!_next|api|favicon.ico|.*\\..*).*)"],
};
ミドルウェアはURLパスからロケールを抽出し、サポートされているロケール配列と照合して、無効なロケールをデフォルトのロケールにリダイレクトしながら、パスの残りの部分を保持します。
3. 無効なロケールを404レスポンスで処理する
リダイレクトの代わりに404ページを表示したい場合は、カスタム404ページへリクエストを書き換えます。
import { NextRequest, NextResponse } from "next/server";
const SUPPORTED_LOCALES = ["en", "fr", "de"];
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
const pathnameHasLocale = SUPPORTED_LOCALES.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`,
);
if (!pathnameHasLocale) {
return;
}
const localeInPath = pathname.split("/")[1];
if (!SUPPORTED_LOCALES.includes(localeInPath)) {
const url = request.nextUrl.clone();
url.pathname = "/404";
return NextResponse.rewrite(url);
}
}
export const config = {
matcher: ["/((?!_next|api|favicon.ico|.*\\..*).*)"],
};
ビルド時に静的に生成されるpages/404.jsにカスタム404ページを作成します。
4. カスタム404ページを作成する
export default function Custom404() {
return (
<div>
<h1>404 - Page Not Found</h1>
<p>The page you are looking for does not exist.</p>
</div>
);
}
このページは、ミドルウェアが無効なロケールリクエストを書き換えた際に表示され、リクエストされたURLが利用できないことをユーザーに明確に伝えます。