next-i18next v16: App Router Translation Wiring for Next.js
The easiest way to translate your NextJs apps.
At a glance
- What is it?
- next-i18next v16 is a thin layer over i18next and react-i18next that handles the Next.js-specific parts: proxy-based language detection, server/client resource split and hydration. It fits teams already on i18next, and its serverless story depends on how you load translation files.
- Who is it for?
- Adopt next-i18next if you already use i18next or react-i18next and want the Next.js wiring done for you, and if your app is on the App Router, the Pages Router or both. Skip it if you want a translation framework with its own message format and no i18next dependency, or if you cannot accept dynamic import() as the way locale JSON reaches a serverless bundle.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The Next.js wiring problem next-i18next exists to remove
i18next is a translation runtime. react-i18next binds it to React. Neither knows anything about Next.js, which is where the awkward parts live: detecting a language before a request renders, deciding whether the locale belongs in the URL, keeping server and client translation state from diverging, and getting translation JSON into a serverless function bundle.
next-i18next is aimed at teams who have already chosen i18next and do not want to rebuild that plumbing per project. The README frames v16 as "a thin layer on top of i18next and react-i18next that handles the Next.js-specific wiring". The practical audience is a Next.js codebase with an existing i18next setup, or one where the team has decided i18next's namespace and interpolation model is what they want.
It supports three shapes: App Router, Pages Router, and mixed setups where both coexist. That last case matters more than it sounds. Many production Next.js apps are mid-migration, and a library that forces an all-or-nothing router decision is unusable in that window.
How the proxy, server components and client components divide the work
The v16 architecture has three moving parts. The first is the proxy, created with createProxy() and exported from a proxy.ts file at the project root. Next.js 16 replaced middleware.ts with proxy.ts; createMiddleware from next-i18next/middleware remains available for projects on Next.js below 16. The proxy detects language in a fixed order: cookie, then Accept-Language header, then fallback. It redirects bare URLs to locale-prefixed paths, so /about becomes /en/about. It sets an x-i18next-current-language header that Server Components read, and it writes the language to a cookie, but only when the language actually changed. That detail is deliberate: the README states a cookie written by the proxy counts as a modified cookie for Next, and a modified cookie makes every Server Action revalidate and refetch the page.
The second part is the server/client split. Server Components use getT(), Client Components use useT(). The README describes the proxy path as Edge-safe with zero Node.js dependencies, which is why the config type, I18nConfig, is imported from next-i18next/proxy rather than from the package root.
The third part is resource loading. There are two patterns. Files in public/locales are served statically and work with the default config on local or traditional hosting. Files bundled via dynamic imports, with a resourceLoader function in the config, work on serverless platforms. The README is explicit that on Vercel and AWS Lambda, files in public/ are served through the CDN but are not available on the filesystem at runtime. That single sentence explains most of the deployment bugs people hit with this library.
Installing next-i18next and getting one translated page running
Install the three packages together. next-i18next does not ship i18next or react-i18next as the only thing you need to think about; the README lists all three in the install command.
npm install next-i18next i18next react-i18nextNext, place translation JSON somewhere the bundler can trace. The serverless-safe pattern uses app/i18n/locales, with one file per language and namespace.
mkdir -p app/i18n/locales/en app/i18n/locales/deCreate i18n.config.ts at the project root. The resourceLoader uses dynamic import() so the bundler includes the JSON in the serverless function bundle.
import type { I18nConfig } from 'next-i18next/proxy'
const i18nConfig: I18nConfig = {
supportedLngs: ['en', 'de'],
fallbackLng: 'en',
defaultNS: 'common',
ns: ['common', 'home'],
resourceLoader: (language, namespace) =>
import(`./app/i18n/locales/${language}/${namespace}.json`),
}
export default i18nConfigThen create proxy.ts at the project root. The matcher below is the one the README gives, and it excludes API routes, static assets and a few common files from language handling.
import { createProxy } from 'next-i18next/proxy'
import i18nConfig from './i18n.config'
export const proxy = createProxy(i18nConfig)
export const config = {
matcher: ['/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js|site.webmanifest).*)'],
}After this, a request to /about should redirect to /en/about, and the proxy should set the x-i18next-current-language header. If you are keeping translations in public/locales and are not deploying to a serverless platform, the README says you can omit resourceLoader entirely and next-i18next will read from the filesystem at runtime.
Hot reload stalls, cookie revalidation and other sharp edges
The most concrete limitation is documented rather than hidden. Dynamic import() of JSON is cached at the bundler level and is not reliably re-invalidated by Turbopack or Webpack HMR after the first edit, so hot reload can stall after one change to a locale file. The README's own workaround gates the loader: development uses fs.readFile, production keeps the bundler-traceable import(). That is a real cost. You maintain two loading paths, and the development one does not exercise the code that runs in production. Pages Router and the App Router default backend already use fs and are unaffected.
The cookie behaviour is the second edge. Because a proxy-written cookie marks the response as modified and triggers Server Action revalidation and page refetch, the library only writes it when the language changed. If another system owns that cookie, set persistCookie: false. If you need the cookie scoped to a parent domain, cookieOptions accepts values such as { domain: '.example.com' }, per the README.
There is also a hosting constraint that is easy to miss until deploy time. Translations in public/locales are the simpler setup, but on Vercel or AWS Lambda they are not on the filesystem at runtime. A project that works locally and returns missing keys in production is usually this, not an i18next bug.
Finally, the README recommends i18next-locize-backend and includes a note that npx i18next-cli localize connects to Locize and AI-translates an app. Locize is built by the same team behind next-i18next and is linked from the funding section. That does not make the core library dependent on it, but it does mean the most prominent translation-management advice in the README points at a commercial service.
next-i18next compared with next-intl and the Pages Router API
The comparison people search for is next-i18next versus next-intl, and the difference is mostly about what you are already committed to. next-i18next is a Next.js adapter for i18next. If your team knows i18next namespaces, interpolation, plural rules and backend plugins, the mental model transfers directly, and you can plug in i18next-http-backend, i18next-locize-backend or i18next-chained-backend as custom backends. The trade-off is that you inherit i18next's configuration surface along with its flexibility. next-intl takes the opposite position: a smaller, Next.js-first API with its own message conventions, rather than a general runtime with a framework layer on top. If you have no existing i18next investment and want fewer concepts, that is the more direct route. If you have an i18next setup and a translation pipeline already, rewriting onto a different runtime is the larger cost.
The other comparison is internal, between v16's App Router API and the older Pages Router API. The README states the existing appWithTranslation and serverSideTranslations API is preserved under next-i18next/pages. So serverSideTranslations is not gone; it moved. If you are searching for next-i18next serverSideTranslations and finding v16 documentation about getT(), that is why. The mixed-router setup uses basePath scoping so both routers can coexist in one app, which is the migration path for a codebase that cannot move all routes at once.
Licence, release cadence and what upgrades cost
next-i18next is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. The repository also lists funding links to Locize and to the i18next FAQ support page. Those are voluntary contributions, not licence terms. Nothing in the licence text should be read as an obligation, and this is not legal advice; check the LICENSE file in the repository for the exact wording.
The package.json shows version 16.3.1 with dual ESM and CJS exports, including subpath exports for ./proxy, ./middleware, ./server and ./client. That granular export map is what keeps the proxy path free of Node.js dependencies, and it also means deep imports outside those subpaths are not part of the public surface. The repository layout includes separate tsconfig.appRouter.json and tsconfig.pagesRouter.json files, which reflects that the two router APIs are built and typed independently.
On maintenance: the last push was on 2026-09-13, and the three most recent releases (v16.2.0, v16.3.0, v16.3.1) landed within the ten days before that. The repository is not archived. Upgrade cost between v16 minor releases is hard to assess without reading the changelog; the README includes a Migration from v15 section, and CHANGELOG.md is the file to read before bumping. The larger cost is not the version bump but the router migration: moving from serverSideTranslations to getT() and useT() touches every page that loads translations.
Editorial conclusion
Adopt next-i18next if you already use i18next or react-i18next and want the Next.js wiring done for you, and if your app is on the App Router, the Pages Router or both. Skip it if you want a translation framework with its own message format and no i18next dependency, or if you cannot accept dynamic import() as the way locale JSON reaches a serverless bundle. Before committing, verify three things in a branch: that your deployment target serves public/locales at runtime, that your dev hot-reload path uses fs.readFile rather than import(), and that your cookie ownership rules match persistCookie and cookieOptions. The repository's TROUBLESHOOT.md and the examples/ directory are the first places to look when the proxy and the resource loader disagree.
Frequently asked questions
What is next-i18next?
It is a Next.js integration layer for i18next and react-i18next. The README describes v16 as a thin layer that handles the Next.js-specific wiring: middleware or proxy, the server/client split, and resource hydration. It supports the App Router, the Pages Router and mixed setups.
How do I use next-i18next?
Install next-i18next, i18next and react-i18next, put translation JSON where the bundler can trace it, define an I18nConfig with supportedLngs and a resourceLoader, then export createProxy(i18nConfig) from proxy.ts at the project root. Server Components call getT() and Client Components call useT().
How is next-i18next different from react-i18next?
react-i18next binds i18next to React components and has no concept of Next.js routing or server rendering. next-i18next sits on top of both and adds the Next.js parts: proxy-based language detection, locale-prefixed URL redirects, the x-i18next-current-language header for Server Components, and resource loading that works with serverless bundles.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/i18next-next-i18next)