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. ロケールパラメータを検証するミドルウェアを作成する
プロジェクトのルートまたはsrcフォルダを使用している場合はその中にmiddleware.tsファイルを作成します。
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 - ページが見つかりません</h1>
<p>お探しのページは存在しません。</p>
</div>
);
}
このページは、ミドルウェアが無効なロケールリクエストを書き換えるときに表示され、リクエストされたURLが利用できないことをユーザーに明確に伝えます。