| name | next-intl-app-router |
| description | Configures and uses next-intl for Next.js App Router with locale-based routing. Use when adding or changing i18n, locale routing, translations, next-intl plugin, middleware/proxy, or message files in Next.js App Router projects. |
next-intl (App Router)
Setup and usage of next-intl with prefix-based locale routing (e.g. /en/about, /ja/about). Use this skill in any Next.js App Router project.
Example code: Copy-paste examples live in this skill's examples/ folder. See examples/README.md for where each file goes in your project.
File layout
Keep this structure:
├── 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
└── ...
Root layout does not wrap with NextIntlClientProvider; only app/[locale]/layout.tsx does.
1. Next config
Wire the plugin (default path ./i18n/request.ts):
import type { NextConfig } from 'next';
import createNextIntlPlugin from 'next-intl/plugin';
const nextConfig: NextConfig = {
};
const withNextIntl = createNextIntlPlugin();
export default withNextIntl(nextConfig);
Custom path: createNextIntlPlugin('./src/i18n/request.ts').
2. Routing config
Central config in src/i18n/routing.ts:
import { defineRouting } from 'next-intl/routing';
export const routing = defineRouting({
locales: ['en', 'ja', 'zh-CN', 'zh-TW'],
defaultLocale: 'en',
});
3. Request config
src/i18n/request.ts: resolve locale from the [locale] segment and load messages.
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. Proxy / middleware (Next.js 16)
Next.js 16 uses proxy.ts instead of middleware.ts. Same API:
import createMiddleware from 'next-intl/middleware';
import { routing } from './i18n/routing';
export const proxy = createMiddleware(routing);
export const config = {
matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
};
Matcher: all pathnames except /api, /trpc, /_next, /_vercel, and paths containing a dot (e.g. favicon.ico).
5. Navigation helpers
Use project navigation wrappers so links keep the current locale:
import { createNavigation } from 'next-intl/navigation';
import { routing } from './routing';
export const { Link, redirect, usePathname, useRouter, getPathname } = createNavigation(routing);
In components: import Link (and others) from @/i18n/navigation, not from next/navigation or next/link, for locale-aware URLs. Example: examples/Nav-client.tsx, examples/BackToHomeButton.tsx.
6. Locale layout and static rendering
app/[locale]/layout.tsx must (full file: examples/app-locale-layout.tsx):
- Validate
locale with hasLocale → notFound() if invalid.
- Call
setRequestLocale(locale) for static rendering.
- Wrap children with
NextIntlClientProvider and getMessages().
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. Pages under [locale]
For static rendering, every page under [locale] that uses next-intl must call setRequestLocale(locale) (and use use(params) if needed). Examples: app-locale-page.tsx, app-locale-about-page.tsx. (and use use(params) if needed). Layout already sets it; pages that render server components using locale should set it too.
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 />;
}
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 />;
}
Call setRequestLocale before any next-intl APIs in that layout/page.
8. Using translations
Client components: 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>;
}
Server components: use getTranslations from next-intl/server (await with locale/namespace as needed).
9. Messages format
One JSON file per locale under messages/. Nested keys map to namespaces and keys:
{
"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").
- Interpolation:
"selectColor": "Select {color} color" → t("selectColor", { color: "Blue" }).
Checklist
Reference