Docs / tech

Next.js サイトでの多言語化

2025-07-08 2025-07-29 |

Next.js を利用したサイトにおいて、多言語サイトを展開する際のポイントをこの記事ではまとめておきます。

前提条件

今回構築をするサイトでは日本語と英語の2つの言語のサイトとして構築していきます。このため、前提条件を以下のように記載しています。

  • Next.js 15.x App Router
  • 対象は日本語( ja )と英語( en )とする
  • ブラウザの言語が日本語の場合は ja を優先する、それ以外は英語
  • 各言語のURL は /ja/ および /en/ とする

新しいプロジェクトを作成する

早速ですが、新しいプロジェクトを作成します。

npx create-next-app

プロジェクトを作成する際の各設定は以下のようにしました。

しばらくすると、Next.js の新しいプロジェクトが作成されます。主要なファイルに関しては、以下のように作成されています。

src
- app
  - favicon.ico
  - globals.css
  - layout.tsx
  - page.tsx

多言語対応の実装

それでは実際に多言語対応ができるように、いくつかの作業を進めていきます。

Dynamic Route

Next.js には URL のパスを値として利用することが可能な Dynamic Route という仕組みがあります。

例えば [lang] というフォルダを作成して、その中に page.tsx のファイルを配置すれば、[lang] に対して設定された値を利用してページを表示することが可能となります。今回はこの仕組みを利用して /ja や /en の表示ができるように作成をしていきます。

これに向けていくつかのファイルを移動させていきます。

  • [lang] フォルダを app フォルダの下に作成
  • src/app/layout.tsx および src/app/page.tsx のファイルを [lang] フォルダに移動する

これで基本的なファイルの移動ができました。合わせてスタイルシートのファイルも移動したいと思います。

  • styles フォルダを src の直下に作成
  • globals.css のファイルを上記のフォルダに移動します

スタイルシートの場所が変わっているため、src/app/[lang]/layout.tsx の import のコードを変更します。

src/app/[lang]/layout.tsx
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "@/styles/globals.css";

上記の変更を実施すると、以下のような動作となります。

まずは Dynamic Router が正しく動作していることを確認して、次に進みます。

middleware.ts を追加する

Next.js ではミドルウェアを利用することで、リクエストの実行をする前のコードを実装することができます。そこで、今回は src/middleware.ts のファイルを作成して、以下のコードを追加します。

src/middleware.ts
import { NextRequest, NextResponse } from "next/server";

export function middleware(request: NextRequest) {
	const { pathname } = request.nextUrl;

	if (pathname !== "/") {
		return NextResponse.next();
	}

	const acceptLang = request.headers.get("accept-language") || "";
	const isJapanese = acceptLang.toLowerCase().startsWith("ja");

	const locale = isJapanese ? "ja" : "en";

	const redirectUrl = new URL(`/${locale}`, request.url);
	return NextResponse.redirect(redirectUrl);
}

export const config = {
	matcher: ["/"],
};

処理としては以下のような内容です。

  • / のパスの処理を実行する
  • ブラウザの accept-language を取得する
  • ja で始まっているかどうかの判定
  • 判定結果を利用して、各言語のページを表示する

上記のファイルを追加すると、http://localhost:3000 にアクセスをしたときに、ブラウザの設定が日本語の場合は ja を、それ以外は en にリダイレクトができました。

言語を指定する

今回は日本語と英語のサイトとするために、ja と en 以外の [lang] を指定され時は 404 エラーを表示するように追加の実装を進めます。

利用する言語に関しては、今後の拡張を想定して src/constants/build.ts というファイルを作成して、以下の定義を追加します。

src/constants/build.ts
export const LANGS = ["ja", "en"];

この値を利用して、src/app/[lang]/page.tsx のファイルを以下のように書き換えます。return 以降は変更をしていません。

src/app/[lang]/page.tsx
import Image from "next/image";
import { LANGS } from "@/constants/build";
import { notFound } from "next/navigation";

type Props = {
	params: Promise<{ lang: string }>;
};

export default async function Home({ params }: Props) {
	const { lang } = await params;

	if (!LANGS.includes(lang)) {
		notFound();
	}

	return (

このコードは以下の動作を実装しています。

  • LANGS を読み込み
  • Next.js が提供している notFound の読み込み
  • [lang] の値を params で受け取り、params.lang で LANGS に含まれているか確認
  • 含まれていない場合は notFound() を実行

変更後、 /en および /ja は表示されますが、それ以外の言語を指定した場合は 404 エラーが表示されるようになります。

Layout.tsx を更新する

HTML の html に最初の状態では lang=“en” が記載されていますが、これに関しても [lang] の値を利用して値を変更するように実装します。

layout.tsx のファイルの RootLayout を以下のように更新してください。

src/app/[lang]/layout.tsx
export default async function RootLayout({
	children,
	params,
}: Readonly<{
	children: React.ReactNode;
	params: Promise<{ lang: string }>;
}>) {
	const { lang } = await params;

	return (
		<html lang={lang}>

変更点は以下の通りです。

  • 利用する値に params を追加
  • lang の値を取得する
  • html lang で利用できるように変更する

これで /ja の時に lang=“ja” が設定されるようになります。

URL の制御

今の段階で ja および en のページにアクセスすることができるようになっています。合わせて URL に関しての制御を以下のように設定していきます。

  • /ja ではなく /ja/ と後ろに / を必ず付与する
  • ついていいない場合はリダイレクトをする

これに関しては Next.js の機能を利用します。

この設定は、next.config.ts のファイルに設定を追加するだけで対応できます。

next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
	trailingSlash: true,
};

export default nextConfig;

これで、URL に関しての一貫性のあるルールを追加することができます。

まとめ

標準の Next.js のプロジェクトを改良して、URL に言語のパスを追加し、また関連する処理を追加することで多言語で利用するためのベースの処理を確認することができました。

最終的に変更したファイル、および新しいパスは以下のようになります。

src
- app
  - [lang]
    - layout.tsx
    - page.tsx
  - favicon.ico
  - constants
    - build.ts
  - styles
    - globals.css
  - middleware.ts
next.config.ts

サンプルのコードは、以下のリポジトリに公開しています。