Next.js App Router i18n: A Complete Guide to next-intl
With the growth of globalization, multi-language support (i18n) has become a standard requirement for modern web applications. For projects using the Next.js App Router, next-intl provides an efficient internationalization solution that is deeply integrated with the framework, compatible with Server-Side Rendering (SSR), and supports both Server and Client components. This article will guide you step-by-step through building a multi-language Next.js application from scratch.
🚀 I. Why Choose next-intl?
Compared to traditional i18n libraries, next-intl is deeply optimized for the Next.js App Router:
- Automatic Route Handling: Automatically handles routes with language prefixes (e.g.,
/en/page,/zh/page). - Component Support: Perfectly supports both Server Components and Client Components.
- SEO Friendly: Native support for SEO-compliant multi-language links.
- On-demand Loading: Supports on-demand loading of language resources in Server Components, reducing initial bundle size.
📁 II. Project Directory Structure
Under the App Router, the recommended directory structure is as follows (where [locale] is used for dynamic language prefix routes):
src/
├── app/
│ ├── layout.tsx ← Root layout (non-locale specific)
│ ├── middleware.ts ← next-intl middleware
│ ├── i18n/ ← Internationalization config
│ │ ├── routing.ts
│ │ ├── request.ts
│ │ └── navigation.ts
│ └── [locale]/ ← Dynamic locale prefix
│ ├── layout.tsx ← Locale layout + Intl Provider
│ ├── page.tsx ← Homepage
│ └── ...
├── components/
│ └── LocaleSwitcher.tsx ← Language switcher component
└── messages/ ← Translation resources
├── en.json
└── zh.json📌 III. Core Configuration Steps
1. Install Dependencies
npm install next-intl2. Configure Language Routes (src/app/i18n/routing.ts)
import { defineRouting } from "next-intl/routing";
export const routing = defineRouting({
locales: ["en", "zh"], // Supported languages
defaultLocale: "en", // Default language
localePrefix: "always" // Always use prefix /en /zh
});3. Load Language Resources (src/app/i18n/request.ts)
import { getRequestConfig } from "next-intl/server";
export default getRequestConfig(async ({ locale }) => {
return {
messages: (await import(`../../../messages/${locale}.json`)).default
};
});4. Configure Middleware (src/middleware.ts)
import createMiddleware from "next-intl/middleware";
import { routing } from "./app/i18n/routing";
export default createMiddleware(routing);
export const config = {
// Match all paths except API or static assets
matcher: ["/((?!api|_next|.*\\..*).*)"]
};🎨 IV. Using in Pages and Components
Locale Layout Configuration (src/app/[locale]/layout.tsx)
import { NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";
export default async function LocaleLayout({ children, params: { locale } }) {
const messages = await getMessages();
return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
);
}Translation Example
import { useTranslations } from "next-intl";
export default function Home() {
const t = useTranslations("Index");
return <h1>{t("title")}</h1>;
}🎯 V. Summary
With next-intl, we can implement multi-language support in Next.js App Router very elegantly. It not only simplifies routing logic but also provides an excellent development experience and runtime performance. If your project needs to serve international users, next-intl is definitely the most recommended choice currently.
WenHaoFree