next-intl-app-router について
next-intl-app-routerは、Next.js App Routerでnext-intlを使うための設定・利用ガイドです。プレフィックス付きロケールルーティングを扱い、設定、ロケール対応ナビゲーション、静的レンダリング、翻訳の読み込みをコピー可能な例とともに説明します。
主な機能
- 01プレフィックス付きロケールルーティング
- 02プラグインとリクエスト設定
- 03ロケール対応ナビゲーションヘルパー
- 04静的レンダリングの設定
- 05クライアント・サーバー翻訳API
- 06ロケール別JSONメッセージファイル
活用シーン
- 01Next.jsアプリにロケール付きURLを追加
- 02App Routerでnext-intlを設定
- 03ロケール対応リンクとリダイレクトの構築
- 04クライアント・サーバーコンポーネントで翻訳を読み込み
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ liuchiawei/ agent-skills --skill next-intl-app-routerインストール後、Claude Code で/next-intl-app-routerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
reference.mdexamples/app-locale-about-page.tsxapp-locale-layout.tsxapp-locale-page.tsxBackToHomeButton.tsxmessages-en.jsonNav-client.tsxnext.config.tsproxy.tsREADME.mdexamples/i18n/navigation.tsrequest.tsrouting.ts詳細
next-intl(App Router)
next-intl をプレフィックスベースのロケールルーティング(例:/en/about、/ja/about)で設定して使用します。このスキルは、Next.js App Router を使用するすべてのプロジェクトで利用できます。
コード例: コピーして使える例は、このスキルの examples/ フォルダーにあります。各ファイルをプロジェクト内のどこに配置するかは、examples/README.md を参照してください。
ファイル構成
次の構成を維持してください。
├── messages/
│ ├── en.json
│ ├── ja.json
│ └── ...
├── next.config.ts
└── src/
├── i18n/
│ ├── request.ts
│ ├── routing.ts
│ └── navigation.ts
├── proxy.ts # Next.js 16+ (was middleware.ts)
└── app/
├── layout.tsx # Root layout, no NextIntlClientProvider here
└── [locale]/
├── layout.tsx
├── page.tsx
└── ...
ルートレイアウトでは NextIntlClientProvider でラップせず、app/[locale]/layout.tsx でのみラップします。
1. Next の設定
プラグインを接続します(デフォルトのパスは ./i18n/request.ts です)。
// next.config.ts
import type { NextConfig } from "next";
import createNextIntlPlugin from "next-intl/plugin";
const nextConfig: NextConfig = {
/* ... */
};
const withNextIntl = createNextIntlPlugin();
export default withNextIntl(nextConfig);
カスタムパス:createNextIntlPlugin('./src/i18n/request.ts')。
2. ルーティング設定
src/i18n/routing.ts に一元化した設定を記述します。
import { defineRouting } from "next-intl/routing";
export const routing = defineRouting({
locales: ["en", "ja", "zh-CN", "zh-TW"],
defaultLocale: "en",
});
3. リクエスト設定
src/i18n/request.ts で、[locale] セグメントからロケールを解決し、メッセージを読み込みます。
import { getRequestConfig } from "next-intl/server";
import { hasLocale } from "next-intl";
import { routing } from "./routing";
export default getRequestConfig(async ({ requestLocale }) => {
const requested = await requestLocale;
const locale = hasLocale(routing.locales, requested)
? requested
: routing.defaultLocale;
return {
locale,
messages: (await import(`../../messages/${locale}.json`)).default,
};
});
4. プロキシ/ミドルウェア(Next.js 16)
Next.js 16 では、middleware.ts の代わりに proxy.ts を使用します。API は同じです。
// src/proxy.ts
import createMiddleware from "next-intl/middleware";
import { routing } from "./i18n/routing";
export const proxy = createMiddleware(routing);
export const config = {
matcher: "/((?!api|trpc|_next|_vercel|.*\\..*).*)",
};
マッチャー:/api、/trpc、/_next、/_vercel、およびドットを含むパス(例:favicon.ico)を除くすべてのパス名。
5. ナビゲーションヘルパー
リンクで現在のロケールを維持するには、プロジェクトのナビゲーションラッパーを使用します。
// src/i18n/navigation.ts
import { createNavigation } from "next-intl/navigation";
import { routing } from "./routing";
export const { Link, redirect, usePathname, useRouter, getPathname } =
createNavigation(routing);
コンポーネントでは、ロケール対応 URL にするため、Link(およびその他の要素)は next/navigation や next/link からではなく、@/i18n/navigation からインポートしてください。例:examples/Nav-client.tsx、examples/BackToHomeButton.tsx。
6. ロケールレイアウトと静的レンダリング
app/[locale]/layout.tsx では、次の処理が必要です(完全なファイル:examples/app-locale-layout.tsx)。
hasLocaleでlocaleを検証し、無効な場合はnotFound()を呼び出します。- 静的レンダリングのために
setRequestLocale(locale)を呼び出します。 NextIntlClientProviderとgetMessages()で子要素をラップします。
// app/[locale]/layout.tsx
import { NextIntlClientProvider, hasLocale } from "next-intl";
import { setRequestLocale } from "next-intl/server";
import { notFound } from "next/navigation";
import { routing } from "@/i18n/routing";
import { getMessages } from "next-intl/server";
type Props = {
children: React.ReactNode;
params: Promise<{ locale: string }>;
};
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
}
export default async function LocaleLayout({ children, params }: Props) {
const { locale } = await params;
if (!hasLocale(routing.locales, locale)) notFound();
setRequestLocale(locale);
const messages = await getMessages();
return (
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
);
}
7. [locale] 配下のページ
静的レンダリングの場合、[locale] 配下で next-intl を使用するすべてのページで setRequestLocale(locale) を呼び出してください(必要に応じて use(params) を使用します)。例:app-locale-page.tsx、app-locale-about-page.tsx。(必要に応じて use(params) を使用します。)レイアウトではすでに設定されていますが、ロケールを使用するサーバーコンポーネントをレンダリングするページでも設定してください。
// app/[locale]/page.tsx
import { use } from "react";
import { setRequestLocale } from "next-intl/server";
export default function IndexPage({
params,
}: {
params: Promise<{ locale: string }>;
}) {
const { locale } = use(params);
setRequestLocale(locale);
return <TokyoPage />;
}
// app/[locale]/about/page.tsx
import { use } from "react";
import { setRequestLocale } from "next-intl/server";
import AboutContainer from "./components/AboutContainer";
export default function AboutPage({
params,
}: {
params: Promise<{ locale: string }>;
}) {
const { locale } = use(params);
setRequestLocale(locale);
return <AboutContainer />;
}
そのレイアウト/ページ内で next-intl の API を使用する前に、setRequestLocale を呼び出してください。
8. 翻訳の使用
クライアントコンポーネント: useTranslations(namespace) を使用します。
"use client";
import { useTranslations } from "next-intl";
import { Link } from "@/i18n/navigation";
export default function BackToHomeButton() {
const t = useTranslations("BackToHomeButton");
return (
<Link href="/">
<span>{t("buttonText")}</span>
</Link>
);
}
"use client";
import { useTranslations } from "next-intl";
import { Link } from "@/i18n/navigation";
export default function Nav() {
const t = useTranslations("Navigation");
return <Link href="/about">{t("links.about")}</Link>;
}
サーバーコンポーネント: next-intl/server から getTranslations を使用します(必要に応じてロケール/名前空間とともに await します)。
9. メッセージの形式
ロケールごとに 1 つの JSON ファイルを messages/ 配下に配置します。ネストしたキーは名前空間とキーに対応します。
{
"HomePage": {
"title": "Hello world!"
},
"LandingPage": {
"title": "Tokyo Sounds",
"navbar": {
"home": "Home",
"about": "About"
}
},
"BackToHomeButton": {
"buttonText": "Back to Home",
"tooltip": "Return to the main page"
}
}
useTranslations("LandingPage")→t("title")、t("navbar.about")。- 補間:
"selectColor": "Select {color} color"→t("selectColor", { color: "Blue" })。
チェックリスト
-
next.config.ts:createNextIntlPlugin()で設定をラップする。 -
src/i18n/routing.ts:localesとdefaultLocaleを指定してdefineRoutingを使用する。 -
src/i18n/request.ts:getRequestConfig、hasLocale、および動的なmessages/${locale}.jsonを使用する。 -
src/proxy.ts(またはmiddleware.ts):createMiddleware(routing)とマッチャーを設定する。 -
src/i18n/navigation.ts:createNavigation(routing)を使用し、Linkなどを再エクスポートする。 -
app/[locale]/layout.tsx:hasLocale→notFound、setRequestLocale、generateStaticParams、NextIntlClientProviderとgetMessages()を設定する。 - 各
app/[locale]/**/page.tsx:静的レンダリングを使用する場合はsetRequestLocale(locale)を呼び出す。 - クライアントコンポーネント:
useTranslations("Namespace")を使用し、リンクには@/i18n/navigationのLinkを使用する。
参考資料
- コピーして使える例: examples/ — あらゆるプロジェクトで使用できるスタンドアロンのファイル。
- 拡張設定(localePrefix、pathnames など):reference.md
- 公式ドキュメント:next-intl App Router、Routing setup