mcpField
N
next-intl-app-router

next-intl-app-router

github.com/liuchiawei開発2604 回インストール37 週間前に更新
リポジトリ

next-intl-app-router について

next-intl-app-routerは、Next.js App Routerでnext-intlを使うための設定・利用ガイドです。プレフィックス付きロケールルーティングを扱い、設定、ロケール対応ナビゲーション、静的レンダリング、翻訳の読み込みをコピー可能な例とともに説明します。

主な機能

  1. 01プレフィックス付きロケールルーティング
  2. 02プラグインとリクエスト設定
  3. 03ロケール対応ナビゲーションヘルパー
  4. 04静的レンダリングの設定
  5. 05クライアント・サーバー翻訳API
  6. 06ロケール別JSONメッセージファイル

活用シーン

  1. 01Next.jsアプリにロケール付きURLを追加
  2. 02App Routerでnext-intlを設定
  3. 03ロケール対応リンクとリダイレクトの構築
  4. 04クライアント・サーバーコンポーネントで翻訳を読み込み

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/liuchiawei/agent-skills --skill next-intl-app-router

インストール後、Claude Code で/next-intl-app-routerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

reference.md
examples/
app-locale-about-page.tsx
app-locale-layout.tsx
app-locale-page.tsx
BackToHomeButton.tsx
messages-en.json
Nav-client.tsx
next.config.ts
proxy.ts
README.md
examples/i18n/
navigation.ts
request.ts
routing.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)。

  1. hasLocale で locale を検証し、無効な場合は notFound() を呼び出します。
  2. 静的レンダリングのために setRequestLocale(locale) を呼び出します。
  3. 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 を使用する。

参考資料

コメント