mrkeyoor.com_
Wed 23 Sept 12:34 UTC
npmWeb Frontendupdated 23 Sept 2026

next-intl review

next-intl 4.13.7 is a Next.js-specific internationalization layer for ICU messages, locale-aware routing, number and date formatting, Server Components, and client hooks. Its plugin connects request configuration to Next.js, while separate server, navigation, routing, and middleware exports keep code on the correct side of the React boundary. The current patch pins @swc/core to the extractor-compatible range. Version 4.13 also changed generated useExtracted keys to URL-safe base64, which requires migrating existing extracted catalogs.

Verdict

next-intl 4.13.7 installed with 51 packages and produced a 15.8 KB gzipped broad browser bundle in our sandbox, while npm audit found 0 vulnerabilities. It is a strong fit when Next.js routing and Server Components are part of the translation problem; use a framework-neutral library when they are not.

We installed it

Lab card: what happened when we installed next-intlScreenshot of next-intl documentation
Install✓ · 13.7s51 packages on disk · 374 MB
ImportESM import works · require() works · ESM package with exports map
Browser15.8 KBgzipped (50.3 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does next-intl install cleanly?

Yes. In a fresh container with an empty cache, npm install next-intl finished in 14 seconds, leaving 51 packages and 374 MB on disk. npm audit reported no known vulnerabilities.

How much does next-intl add to a browser bundle?

15.8 KB gzipped (50.3 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does next-intl work with both ESM and CommonJS?

Yes. Both import 'next-intl' and require('next-intl') worked in Node 22 in our run. The package is published as ESM with an exports map.

Does next-intl include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

next-intl or next-i18next: which should you use?

next-i18next: Choose it for a Next.js codebase already organized around i18next resources, plugins, and backend loaders. next-intl 4.13.7 installed with 51 packages and produced a 15.8 KB gzipped broad browser bundle in our sandbox, while npm audit found 0 vulnerabilities.

When should you not use next-intl?

You are not using Next.js; i18next, react-intl, or the lower-level use-intl package avoids framework-specific plugin and routing code

API stability4/5The 4.x package publishes explicit server, client, routing, navigation, middleware, config, plugin, and extractor entry points through an exports map. Patch releases still track Next.js behavior closely: 4.13.6 deprecated requestLocale, 4.13.5 deprecated setRequestLocale, and 4.13.7 pinned SWC for extractor compatibility. The main message API is steady, but routing code follows Next.js changes.
Docs5/5The documentation separates App Router setup, request configuration, locale routing, navigation, middleware, Server Components, client providers, ICU messages, formatting, TypeScript augmentation, testing, and migrations. It also explains client message payloads and static rendering. Examples are version-aware enough to distinguish the Next.js 16 proxy filename from older middleware projects.
Maintenance5/5Version 4.13.7 was released on August 17, 2026, four patch releases followed 4.13.0, and GitHub records a push on August 21. The repository is active and has 4,353 stars. Its 52 open issues and pull requests are a meaningful queue, yet release notes show quick responses to Next.js 16, SWC, ICU parsing, and prefetch behavior.
Ecosystem5/5next-intl supports React 16.8 through 19 and Next.js 12 through 16 in its peer ranges, while ICU syntax connects it to established translation formats and tooling. It recorded 5,311,946 npm downloads for August 18 through 24, 2026. The extractor and routing helpers deepen the Next.js fit, although they also make the package less useful outside that framework.

Use it if

  • Your Next.js App Router project needs ICU plurals, rich text messages, formatting, and localized routes under one API
  • You want translations to work in Server Components and Client Components without maintaining two unrelated libraries
  • Compile-time checks for locale names and message keys justify typing a canonical message catalog
  • Your routing policy needs locale prefixes, translated pathnames, cookies, negotiation, and locale-aware Link wrappers
Skip it if

Setup reality

Our next-intl 4.13.7 install took 13.7 seconds and left 51 packages occupying 374 MB. npm audit reported 0 known vulnerabilities. The package has 8 direct dependencies, 2 peer dependencies, and 1,668 KB unpacked. Those peers are Next.js and React, so the sandbox total reflects a framework install rather than next-intl alone.

Create an i18n request file that returns locale, messages, and optional formats, then wrap next.config with next-intl/plugin. Locale routing adds a shared defineRouting object, generated navigation wrappers, and middleware or proxy configuration. Next.js 16 uses proxy.ts. Older releases use middleware.ts. Message catalogs, fallbacks, and translation delivery remain application responsibilities.

The package is ESM with an exports map and bundled declarations. Both require() and ESM import worked on our Node 22 box. Conditional exports provide different client and React Server Component entry points, so importing from next-intl/server or next-intl/navigation is part of correctness. Sending every message through NextIntlClientProvider exposes that catalog to the client; pass only the namespaces client components use when payload size matters.

Our broad esbuild import produced 50.3 KB minified and 15.8 KB gzipped. Actual route cost depends on imports and server placement, but client hooks and message data still enter the browser. Release 4.13.7 pins @swc/core for the extractor plugin. If useExtracted was already generating keys before 4.13, migrate the stored keys before upgrading because the generated encoding changed.

Patterns

Load a catalog for each request configure-request

// src/i18n/request.ts
import {getRequestConfig} from 'next-intl/server';

export default getRequestConfig(async ({locale}) => ({
  locale: locale ?? 'en',
  messages: (await import(`../../messages/${locale ?? 'en'}.json`)).default
}));

Version 4.13.6 deprecated the requestLocale parameter; follow the current request configuration docs when moving to Next.js root params.

Attach next-intl to Next.js enable-plugin

// next.config.ts
import createNextIntlPlugin from 'next-intl/plugin';

const withNextIntl = createNextIntlPlugin();
export default withNextIntl({});

The plugin searches for the conventional i18n request file; pass its relative path when your file lives elsewhere.

Translate in an async Server Component translate-server-component

import {getTranslations} from 'next-intl/server';

export default async function Page() {
  const t = await getTranslations('Home');
  return <h1>{t('title')}</h1>;
}

The server export keeps translation work out of the client bundle and is the correct API after an async boundary.

Provide selected messages to client code provide-client-catalog

import {NextIntlClientProvider} from 'next-intl';

export function ClientBoundary({children, messages}) {
  return <NextIntlClientProvider messages={messages}>{children}</NextIntlClientProvider>;
}

Every message passed to the provider can reach the browser; select the client namespaces instead of forwarding a full catalog.

Render an ICU plural format-plural

// en.json: {"Cart":{"items":"{count, plural, =0 {Empty} one {# item} other {# items}}"}}
const t = useTranslations('Cart');
return <p>{t('items', {count})}</p>;

The one and other branches follow the active locale's plural rules, while =0 is an exact numeric match.

Map a message tag to React render-rich-text

const t = useTranslations('Help');

return t.rich('docs', {
  link: (chunks) => <a href='/docs'>{chunks}</a>
});

Use t.rich for React elements; a plain t call expects a string and t.raw skips ICU processing.

Define locale routing once define-routing

// src/i18n/routing.ts
import {defineRouting} from 'next-intl/routing';

export const routing = defineRouting({
  locales: ['en', 'de'],
  defaultLocale: 'en',
  localePrefix: 'as-needed'
});

Share this 1 routing object with navigation and proxy code so generated links and request rewrites use the same locale policy.

Negotiate locale routes in Next.js 16 configure-proxy

// src/proxy.ts
import createMiddleware from 'next-intl/middleware';
import {routing} from './i18n/routing';

export default createMiddleware(routing);
export const config = {matcher: '/((?!api|_next|.*\..*).*)'};

Next.js 16 names this file proxy.ts; the dotted-path exclusion also skips legitimate route segments containing a period unless you add a matcher.

Create locale-aware navigation helpers create-navigation

// src/i18n/navigation.ts
import {createNavigation} from 'next-intl/navigation';
import {routing} from './routing';

export const {Link, redirect, usePathname, useRouter} = createNavigation(routing);

Use these wrappers where links and redirects must add, remove, or switch the locale prefix according to routing policy.

Type locale and message names type-message-keys

import {routing} from '@/i18n/routing';
import messages from './messages/en.json';

declare module 'next-intl' {
  interface AppConfig {
    Locale: (typeof routing.locales)[number];
    Messages: typeof messages;
  }
}

One canonical catalog drives key completion; a very large JSON type can increase TypeScript and editor work.

Alternatives

PackageRegistryPick it when
next-i18nextnpmChoose it for a Next.js codebase already organized around i18next resources, plugins, and backend loaders.
i18nextnpmChoose it when translations must span several JavaScript frameworks or need its broad plugin and backend ecosystem.
react-intlnpmChoose it for FormatJS-style ICU formatting in React when localized Next.js routing is outside the library's job.

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.