For a Next.js App Router project, use next-intl. For a React SPA, or anything that might outgrow one framework, use react-i18next. If compile-time extraction and lean bundles matter more to you than ecosystem size, use Lingui. All three are runtime i18n libraries: they serve translations to your components, and none of them writes your keys or locale files for you. globalize.now is AI-powered localization infrastructure that produces those keys and catalogs from your codebase, and it works with all three libraries.
What do these three libraries actually do?
They all solve the same runtime problem: given a key and a locale, return the right string, correctly pluralized and formatted. That includes interpolation, date and number formatting, and plural rules via ICU-style messages.
What none of them does is produce the translations. A runtime library consumes a catalog that already exists. Someone still has to find every user-visible string in your components, replace it with a key, and fill a locale file per language. That is a separate layer of the stack, and keeping the two layers distinct is the fastest way to make this comparison make sense: you will pick exactly one runtime library, and it is not in competition with the tooling that fills its catalogs. Our developer docs describe that split in more detail.
When should you use next-intl?
When you are on Next.js with the App Router. next-intl is the one library of the three designed around App Router primitives: async Server Components, locale-aware navigation and routing helpers, and metadata APIs. As of September 2026 it is on version 4 and pulls about five million npm downloads a week, which makes it the default answer for new Next.js projects in practice, not just in theory.
Messages are ICU MessageFormat, so plurals, gender and interpolation follow the same standard the rest of the industry uses. If ICU syntax is new to you, we wrote a plain-English guide to ICU MessageFormat. The trade-off is coupling: next-intl is a Next.js library. If you leave Next.js, you migrate your i18n layer with it.
When should you use react-i18next?
When you are not on Next.js, or when you want the largest ecosystem behind you. react-i18next is the React binding for i18next, and at about fourteen million npm downloads a week it is the most used React i18n library by a wide margin. The i18next core has been maintained for over a decade and has plugins for nearly everything: backends that load catalogs over HTTP, language detectors, caching layers, framework bindings beyond React.
This is the library most AI coding tools reach for by default. Ask Cursor or Lovable to "add translations" to a Vite + React app and you will almost always get an i18next setup. That default is reasonable: it works everywhere, and its JSON catalog format is the closest thing the ecosystem has to a lingua franca. The trade-off is that it predates Server Components, so on the App Router it needs more wiring than next-intl and most of the translation work happens on the client unless you arrange otherwise.
When is Lingui the right choice?
When bundle size and source ergonomics are your priority. Lingui, on major version 6 as of September 2026, takes a compiler-first approach: you write messages inline with macros, and its CLI extracts them into catalogs at build time. Compiled catalogs ship without runtime parsing overhead, which keeps the i18n cost in your bundle low.
Lingui also standardizes on gettext PO files as its catalog format, which professional translators have handled for decades. Its weekly downloads sit around one and a half million, an order of magnitude below react-i18next, so expect fewer Stack Overflow answers and fewer third-party plugins. It works with React generally, not just Next.js, but like react-i18next it is not built around App Router primitives the way next-intl is.
How do they compare at a glance?
| Question | next-intl | react-i18next | Lingui |
|---|---|---|---|
| Best fit | Next.js App Router | Any React app, SPAs | Bundle-sensitive React apps |
| Server Components support | First-class | Needs extra wiring | Needs extra wiring |
| Message syntax | ICU MessageFormat | i18next JSON (ICU via plugin) | ICU via macros |
| Catalog format | JSON | JSON | PO (gettext) |
| Weekly npm downloads (Sep 2026) | ~5M | ~14M | ~1.5M |
| Current major | v4 | v17 (i18next v26) | v6 |
Which should you pick for an AI-generated codebase?
Pick by framework, same as above — but know that the library choice is not where AI-built apps go wrong. Cursor, Claude Code and Lovable all produce hardcoded English strings by default, whatever i18n library is installed, and an agent editing a component will keep adding them after you set the library up.
So the real sequencing is: choose the runtime library your framework wants, then solve extraction and catalog upkeep as its own problem. For the Next.js case we documented the full setup in adding i18n to a Cursor-built Next.js app, and the Next.js integration page covers how globalize.now prepares keys and locale files for next-intl before any runtime wiring.
Do you still need localization infrastructure with a runtime library?
Yes, because the library only reads catalogs — producing and maintaining them is the part that eats your time. globalize.now sits at that layer: connect your repository and it converts the codebase once, replacing hardcoded strings with keys and generating the locale files. After that one-time conversion, push jobs translate the new catalog entries your commits introduce.
Output is JSON or PO — JSON for next-intl and i18next setups, PO for Lingui's native format — so the catalogs land in whichever shape your runtime library already consumes. If your app already has a partial i18n setup, that is handled too: globalize.now works with existing i18n rather than replacing it. Plans and usage rates are on the pricing page.
None of the three libraries is a wrong answer. next-intl if you are on the App Router, react-i18next if you want maximum ecosystem, Lingui if you want compile-time extraction and PO catalogs. Pick one, keep your strings out of your components, and let the catalog layer do the rest.
globalize.now turns hardcoded app copy into translation-ready locale files and keeps them updated as you ship.
Try globalize.now free