next-intl vs next-i18next: Choosing the Right i18n Library for Next.js
Next.js developers choosing an i18n solution will likely narrow it down to two libraries: next-intl and next-i18next. Both support the App Router and Server Components. Both are actively maintained. But they take fundamentally different architectural approaches.
This post compares them on the things that matter for a real project: how translations are loaded, how they integrate with your stack, and what workflows they enable. (Need the bigger picture beyond Next.js? Our JavaScript localization guide covers React, Vue, Angular, Svelte, and vanilla JS too.)
Architecture at a glance
| next-intl | next-i18next | |
|---|---|---|
| Core | Standalone library (built on intl-messageformat) | Built on i18next (the most widely used JavaScript i18n framework) with react-i18next |
| Message format | ICU MessageFormat | i18next JSON format (the most common format in the JS ecosystem) |
| App Router | Supported | Supported via getT() / useT() |
| Pages Router | Limited/legacy | Full support via next-i18next/pages |
| Server Components | Supported | Supported |
| Translation loading | Custom async loader function (you build it) | Backend plugin ecosystem (drop-in packages for CDN, filesystem, Locize, chained caching) |
| Bundle size | Minimal runtime via ICU precompilation | Flexible, tree-shakeable, scales with features used |
| Type safety | Build-time catalog extraction | Full TypeScript support with selector API |
How translations are loaded
This is the most important architectural difference.
next-intl: custom loader function
next-intl uses a request-scoped configuration function (i18n/request.ts) where you define how to load messages:
// i18n/request.ts
import { getRequestConfig } from 'next-intl/server'
export default getRequestConfig(async ({ locale }) => ({
messages: (await import(`../../messages/${locale}.json`)).default
}))You can load from local files, a CDN, a CMS, or any async source. There is no plugin system; you write the loader yourself. This is flexible but means every integration is custom code.
next-i18next: backend plugin ecosystem
next-i18next inherits the full i18next backend plugin ecosystem:
import i18next from 'i18next'
import Backend from 'i18next-locize-backend'
i18next.use(Backend).init({
backend: {
projectId: 'YOUR_PROJECT_ID'
}
})Available backends include:
- i18next-http-backend: load from any HTTP/CDN endpoint
- i18next-locize-backend: direct Locize CDN integration with saveMissing
- i18next-fs-backend: load from filesystem (Node.js)
- i18next-chained-backend: chain multiple backends (e.g., localStorage cache + remote)
This plugin architecture means integrations with TMS platforms, CDNs, and caching layers are available as drop-in packages rather than custom code.
Message format
next-intl: ICU MessageFormat
{
"greeting": "Hello, {name}!",
"items": "You have {count, plural, one {# item} other {# items}} in your cart."
}ICU MessageFormat is an industry standard supported by many TMS platforms. next-intl includes a precompilation step (icu-minify) that reduces the runtime to under 1KB.
next-i18next: i18next format
{
"greeting": "Hello, {{name}}!",
"items_one": "You have {{count}} item in your cart.",
"items_other": "You have {{count}} items in your cart."
}i18next uses its own JSON format with {{interpolation}} syntax and key-based pluralization (suffix _one, _other, _few, etc.). This format is natively understood by Locize and other i18next-compatible tools. It is also widely adopted: i18next is the most downloaded i18n library in the JavaScript ecosystem.
Both formats handle plurals, interpolation, and nesting. The choice is largely about ecosystem compatibility.
saveMissing: automatic key discovery
next-i18next supports i18next's saveMissing feature. When your app encounters a translation key that doesn't exist yet, it can automatically report it to your TMS:
i18next.init({
saveMissing: true,
backend: {
projectId: 'YOUR_PROJECT_ID',
apiKey: 'YOUR_API_KEY'
}
})With the Locize backend, missing keys are batched and sent automatically. Combined with automatic translation, this creates a fully automated pipeline: write code → keys appear in Locize → AI translates → live on CDN.
next-intl does not support saveMissing. Key management is manual; you add keys to your JSON files or TMS yourself.
Translation management integration
next-i18next integrates directly with Locize via the dedicated i18next-locize-backend plugin. This provides:
- CDN delivery at runtime (translations update without redeploy)
- saveMissing (automatic key discovery)
- InContext editor (translate on your running app)
- Branches (translation CI/CD)
- Multi-tenancy (per-tenant overrides)
The Locize backend is maintained by the same team that wrote i18next and next-i18next.
next-intl does not have a dedicated TMS plugin. You can integrate with any TMS by writing a custom loader in i18n/request.ts, but the integration is your responsibility. next-intl's documentation mentions Crowdin as a compatible TMS.
Routing and middleware
Both libraries handle locale routing via Next.js middleware:
next-intl uses createNavigation() and next-intl/middleware:
- URL-based routing with dynamic
[locale]segments - Domain-based routing supported
- Built-in locale detection (URL, cookies, Accept-Language)
next-i18next (v16+) uses createProxy() (Next.js 16+) or createMiddleware():
- Cookie-based locale detection
- Mixed Router support (App Router + Pages Router coexisting)
basePathscoping for multi-router setups
Both approaches work well. The routing mechanism is rarely the deciding factor.
When to choose next-intl
- You prefer ICU MessageFormat and want it built into the framework
- You want a standalone, self-contained library with no external dependencies
- You prefer to write custom loader functions for translation sources
- You are building a Next.js-only project with no need to share i18n setup across other platforms
When to choose next-i18next
- You want access to the largest i18n plugin ecosystem: drop-in backends for CDN, filesystem, caching, and managed services
- You want saveMissing: automatic key discovery from your running app, no manual extraction needed
- You want CDN delivery: translations that update without redeploying your app
- You want a managed translation backend with AI translation, review workflows, and a translator UI via Locize
- You need branches and multi-tenancy for complex localization workflows
- You want to share the same i18n setup across React, Vue, Node.js, React Native, or other platforms in your stack
- You want the proven maturity of i18next: 15+ years, most downloaded i18n library in JavaScript
Summary
Both next-intl and next-i18next are production-ready libraries for Next.js internationalization. The choice comes down to what you need beyond basic translation:
- next-intl is a self-contained solution with ICU message format. Good for Next.js-only projects where you want to manage everything yourself.
- next-i18next connects you to the i18next ecosystem: the most widely adopted i18n infrastructure in JavaScript. Backend plugins, saveMissing, CDN delivery, AI-powered translation, and a managed backend via Locize are all available as drop-in additions, not custom code you write and maintain.
For teams that want their translations to work across multiple platforms, update without redeploying, and scale with managed infrastructure, next-i18next with Locize is the most complete setup available.
Further reading
- next-i18next v16 guide: complete setup for App Router and Pages Router
- Next.js App Router i18n guide: detailed App Router tutorial
- i18next vs alternatives: broader comparison
- Locize + next-i18next integration: example repository