next-intl

Type-safe internationalization for Next.js, built for App Router, Server Components, and static rendering.

Library
npm
v4.14.9
4,384 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
87 /100 Excellent
Development Activity 84
Maintenance 100
Community 64
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
84 /100 Excellent
Architecture 88
Code Quality 90
Innovation 78
Learning Curve 80

next-intl gives Next.js applications a complete internationalization toolkit built specifically around the App Router’s rendering model. Rather than bolting i18n onto Next.js as an afterthought, it ships separate entry points for React Server Components and client components (index.react-server vs index.react-client), so translations, formatting, and locale resolution work correctly whether a component renders on the server or hydrates on the client.

At its core sits use-intl, a framework-agnostic ICU message formatting engine handling interpolation, cardinal and ordinal plurals, rich text, and date/time/number formatting with timezone awareness. next-intl layers Next.js-specific concerns on top: a locale-resolving middleware with cookie sync and alternate-links headers, a routing configuration system supporting locale prefixes and per-locale pathnames, and a build-time plugin/extractor pipeline for compiling and minifying ICU message catalogs.

The project is maintained by a single lead maintainer (amannn) with sponsorship from Crowdin, backed by 90 contributors and a monorepo covering the core library, a Rust-based SWC extractor plugin, and an ICU minifier, all developed with strict TypeScript, comprehensive Vitest coverage, and a documentation site with versioned guides.

What You Get

  • Dual rendering entry points - separate react-server and react-client builds so useTranslations/useFormatter behave correctly whether a component is a Server Component or a Client Component.
  • ICU message formatting via use-intl - interpolation, cardinal/ordinal plurals, enum-based selects, and rich text formatting powered by a dedicated core package usable outside Next.js too.
  • Locale-aware routing - a typed routing.ts config for locale prefixes (always/as-needed/never), per-locale pathnames, and multi-domain locale mapping, paired with typed Link/redirect/usePathname navigation APIs.
  • Middleware for locale resolution - createMiddleware handles locale negotiation, cookie persistence, alternate-links headers for SEO, and malicious-pathname sanitization.
  • Build-time message extraction and compilation - a plugin system (including a Rust/SWC-based extractor) that extracts, catalogs, and minifies ICU messages ahead of time rather than parsing them at runtime.
  • Type-safe translation keys - message keys and interpolation arguments are checked at compile time against the app’s message catalogs, catching typos and missing arguments before runtime.

Common Use Cases

  • Adding multi-language support to a Next.js App Router application with Server Components.
  • Localizing URLs per-language (e.g. /en/about vs /de/ueber-uns) for SEO-friendly internationalized routing.
  • Formatting dates, numbers, and relative times consistently across server and client without timezone mismatches.
  • Serving locale-specific static pages via generateStaticParams while keeping full type safety on message keys.
  • Migrating an existing single-locale Next.js app to multi-locale support without rewriting page-level logic.

Under The Hood

Architecture

next-intl is structured around the React Server Components boundary: index.react-server.tsx and index.react-client.tsx are separate public entry points that re-export from react-server/ and react-client/ directories respectively, so bundlers resolve the correct implementation of hooks like useTranslations depending on where a component executes. Routing concerns are isolated in a routing/ module with a strongly generic RoutingConfig<AppLocales, AppLocalePrefixMode, AppPathnames, AppDomains> type that createMiddleware and the navigation helpers all consume, giving compile-time guarantees that locale prefixes and pathname maps stay in sync. The middleware pipeline (middleware/middleware.tsx) explicitly sanitizes and decodes incoming pathnames before resolving a locale via resolveLocale.tsx, applying cookie sync and alternate-links headers as discrete, separately-tested steps rather than one monolithic function. A build-time plugin/ and extractor/ subsystem, backed by a separate Rust/SWC crate in the monorepo (next-intl-swc-plugin-extractor) and an icu-minify package, moves ICU message parsing and catalog compilation out of the request path entirely.

Tech Stack

The monorepo (managed with pnpm workspaces, Lerna, and Turborepo) is written in strict TypeScript, targeting React 16.8 through 19 and Next.js 12 through 16 as peer dependencies. Message formatting depends on @formatjs/intl-localematcher for locale negotiation and the shared use-intl package for ICU formatting logic; locale detection and content-negotiation use negotiator. The extractor pipeline is built with @swc/core and a dedicated Rust crate compiled via @parcel/watcher for file watching. The package builds to ESM and CJS dual output via Rollup with per-entry-point conditional exports (react-server vs default) declared in package.json, and ships publint/@arethetypeswrong/cli checks to catch packaging mistakes before publish.

Code Quality

Tests are colocated with source as *.test.tsx files and run with Vitest against an Edge Runtime VM (@edge-runtime/vm) to approximate Next.js middleware execution; @testing-library/react covers component-level behavior. ESLint is configured with eslint-config-molindo’s TypeScript and React presets plus eslint-plugin-react-compiler, and enforces consistent-type-imports, consistent-type-exports, and explicit-member-accessibility rules, indicating a codebase that takes type-only imports and public API surfaces seriously. CI runs across a GitHub Actions workflow (main.yml) covering lint, type-check, and test steps, plus a separate release workflow.

What Makes It Unique

What distinguishes next-intl from generic i18n libraries retrofitted onto Next.js is that its API surface is designed around the RSC/client split from the start, rather than requiring a context provider workaround for Server Components. Its build-time message extraction and ICU minification pipeline (including a native Rust/SWC plugin) is unusual among JS i18n libraries, most of which parse ICU messages at runtime on every render; compiling them ahead of time is a deliberate performance trade next-intl makes that competitors in this space generally don’t.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers