--- createdAt: 2025-11-01 updatedAt: 2026-09-27 priority: 9 title: "Next.js 16 i18n with next-intl: App Router Setup Guide" description: "Set up next-intl in a Next.js 16 App Router app step by step: locale routing, per-page message loading, server and client components, and SEO metadata." keywords: - next-intl - Internationalization - Blog - Next.js - JavaScript - React slugs: - blog - nextjs-internationalization-using-next-intl applicationTemplate: https://github.com/aymericzip/next-intl-template history: - version: 7.0.0 date: 2025-11-01 changes: Initial version author: aymericzip --- # How to internationalize your Next.js application using next-intl in 2026 ## Table of Contents ## What is next-intl? **next-intl** is a popular internationalization (i18n) library designed specifically for Next.js App Router. It provides a seamless way to build multilingual Next.js applications with excellent TypeScript support and built-in optimizations. > If you prefer, you can also refer to the [next-i18next guide](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/i18n_using_next-i18next.md), or directly using [Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_nextjs_16.md). - [next-i18next guide](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/i18n_using_next-i18next.md) - [Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_nextjs_16.md) > See the comparison in [next-i18next vs next-intl vs Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/next-i18next_vs_next-intl_vs_intlayer.md). - [next-i18next vs next-intl vs Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/next-i18next_vs_next-intl_vs_intlayer.md) > To understand where these libraries come from, read the history of JavaScript i18n. - [The history of JavaScript i18n](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/history_of_i18n.md) ## What the benchmark says about next-intl on Next.js Before implementing translations, understanding the performance profile of `next-intl` is essential. The [i18n benchmark](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/nextjs.md) evaluates the same 10-page, 10-locale Next.js application across different setups and libraries to measure real bundle footprint, string leakage, and hydration overhead. - [i18n benchmark](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/nextjs.md) Key figures for `next-intl` on Next.js (gzip): | Setup | Library size | Page JS avg | Other-locale leak | Other-page leak | | :-------------------------------- | -----------: | ----------: | ----------------: | --------------: | | Base (no i18n) | - | 141.0 KB | 0.0% | 0.0% | | `next-intl` | 14.7 KB | 153.6 KB | 4.2% | 89.8% | | `@intlayer/next-intl` (compat) | 8.0 KB | 148.7 KB | 0.0% | 0.0% | | `next-intlayer` (native Intlayer) | 5.5 KB | 141.3 KB | 0.0% | 0.0% | What to take away: - **Avoid global message catalogs:** In standard setups where all messages are loaded in root layouts, ~89.8% of translated content sent to the browser belongs to other pages. Using `pick(messages, ['namespace'])` per route removes this leakage, though it requires manual maintenance. - **Runtime weight:** The `next-intl` runtime adds ~14.7 KB gzip to each page. For existing `next-intl` apps, the [`@intlayer/next-intl`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/compat/next-intl.md) compat adapter preserves the same hooks (`useTranslations`, `useFormatter`, etc.) while dropping runtime size to ~8.0 KB with 0% leak. Native [`next-intlayer`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/packages/next-intlayer/exports.md) further reduces footprint to 5.5 KB. > See the full data: [Next.js benchmark report](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/nextjs.md), and the [benchmark repository](https://github.com/intlayer-org/benchmark-i18n). - [Next.js benchmark report](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/nextjs.md) ## Feature comparison on Next.js How `next-intl` compares with `next-i18next` and Intlayer on the features a Next.js App Router project usually needs: | Feature | `next-intlayer` (Intlayer) | `next-intl` | `next-i18next` | | ------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------ | ----------------------------------------- | | **Translations near components** | ✅ Content co-located with each component | ❌ Centralized JSON | ❌ Centralized JSON | | **TypeScript integration** | ✅ Auto-generated strict types | ✅ Good, via `AppConfig` augmentation | ⚠️ Basic | | **Missing translation detection** | ✅ TypeScript errors and build-time warnings | ⚠️ Runtime fallback | ⚠️ Runtime fallback | | **Rich content (JSX, Markdown)** | ✅ Direct support | ⚠️ Tags via `t.rich`, no Markdown | ⚠️ Tags via `` | | **AI translation** | ✅ Your own provider and API key, with app context | ❌ No | ❌ No | | **Visual editor / CMS** | ✅ Local visual editor + optional CMS | ❌ Via external platforms | ❌ Via external platforms | | **Localized routing** | ✅ Built-in (Next.js and Vite) | ✅ Built-in `[locale]` segment | ✅ Built-in | | **Pluralization** | ✅ Enumeration-based | ✅ ICU | ✅ Suffix-based (`_one`, `_other`) | | **Formatting (dates, numbers, currencies)** | ✅ `Intl`-based formatters | ✅ `useFormatter` | ✅ `Intl`-based | | **Content formats** | ✅ `.ts`, `.tsx`, `.js`, `.json`, `.md`, `.yaml` | ✅ `.json`, `.js`, `.ts` | ⚠️ `.json` | | **ICU MessageFormat** | ✅ Via `format: "icu"` | ✅ Native | ⚠️ Via `i18next-icu` | | **SEO helpers (hreflang, sitemap)** | ✅ Metadata, sitemap and robots.txt helpers | ✅ Good | ✅ Good | | **Server Components** | ✅ Direct access in any Server Component | ⚠️ Pass `t` or `await getTranslations()` per component | ⚠️ Pass `t` down the component tree | | **Per-component tree-shaking** | ✅ At build time (Babel / SWC) | ⚠️ Manual, with `pick()` per route | ⚠️ Manual, with namespaces per route | | **Lazy loading** | ✅ Per locale and per dictionary | ✅ Per locale, namespaces managed by hand | ✅ Per locale, namespaces managed by hand | | **Runtime size (gzip, benchmark)** | 4.9 KB | 14.7 KB | 19.7 KB | | **Missing translations in CI** | ✅ `npx intlayer test` | ⚠️ Not built-in | ⚠️ Not built-in, `saveMissing` at runtime | | **Ecosystem / community** | ⚠️ Smaller, growing fast | ✅ Large | ✅ Very large | > Runtime sizes come from the [Next.js benchmark](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/nextjs.md). For a detailed discussion, read [next-i18next vs next-intl vs Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/next-i18next_vs_next-intl_vs_intlayer.md). - [Next.js benchmark](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/nextjs.md) - [next-i18next vs next-intl vs Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/next-i18next_vs_next-intl_vs_intlayer.md) ## Practices you should follow Before we dive into the implementation, here are some practices you should follow: - **Set HTML `lang` and `dir` attributes** In your layout, compute `dir` using `getLocaleDirection(locale)` and set `` for proper accessibility and SEO. - **Split messages by namespace** Organize JSON files per locale and namespace (e.g., `common.json`, `about.json`) to load only what you need. - **Minimize client payload** On pages, send only required namespaces to `NextIntlClientProvider` (e.g., `pick(messages, ['common', 'about'])`). - **Prefer static pages** Use static page as much as possible for better performance and SEO. - **I18n in server components** Server components, like pages or all components not marked as `client` are statics and can be pre-rendered at build time. So we will have to pass the translation functions to them as props. - **Set up TypeScript types** For your locales to ensure type safety throughout your application. - **Proxy for redirection** Use a proxy to handle the locale detection and routing and redirect the user to the appropriate locale-prefixed URL. - **Internationalization of your metadata, sitemap, robots.txt** Internationalize your metadata, sitemap, robots.txt using the `generateMetadata` function provided by Next.js to ensure a better discovery by search engines in all locales. - **Localize Links** Localize Links using the `Link` component to redirect the user to the appropriate locale-prefixed URL. It's important to ensure the discovery of your pages in all locales. - **Automate tests and translations** Automate tests and translations help loosing time to maintain your multilingual application. > See our doc listing everything you need to know about internationalization and SEO: [Internationalization (i18n) with next-intl](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/internationalization_and_SEO.md). - [Internationalization (i18n) with next-intl](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/internationalization_and_SEO.md) ## Step-by-Step Guide to Set Up next-intl in a Next.js Application