百科.dev
全部条目AI 编程趋势榜开源项目技术资讯提交条目
登录
< 返回工具列表
N

next-i18next

> 前端框架
开源

将 NextJs 应用程序翻译的最简单方法

6.2K stars0 点赞0 次浏览
访问官网GitHub

工具介绍

将 NextJs 应用程序翻译的最简单方法

# next-i18next **The easiest way to translate your Next.js apps.** Supports the **App Router** (Server Components, Client Components, middleware), the **Pages Router**, and **mixed** setups where both routers coexist. If you already know i18next: next-i18next v16 is a thin layer on top of [i18next](https://www.i18next.com) and [react-i18next](https://react.i18next.com) that handles the Next.js-specific wiring — middleware, server/client split, resource hydration — so you don't have to. ## What's new in v16 - **App Router support**: `getT()` for Server Components, `useT()` for Client Components, `createProxy()` for language detection and routing - **Locale-in-path** (`/en/about`) and **no-locale-path** (cookie-based) modes - **Mixed Router**: Use both App Router and Pages Router in the same app with `basePath` scoping - **Custom Backends**: `i18next-http-backend`, `i18next-locize-backend`, `i18next-chained-backend`, etc. - **Edge-safe Proxy**: Zero Node.js dependencies in the proxy/middleware path - **Pages Router**: Existing `appWithTranslation` / `serverSideTranslations` API preserved under `next-i18next/pages` ## Advice: If you don't like to manage your translation files manually or are simply looking for a [better management solution](https://www.locize.com?utm_source=next_i18next_readme&utm_medium=github&utm_campaign=readme), take a look at [i18next-locize-backend](https://github.com/locize/i18next-locize-backend). The i18next [backend plugin](https://www.i18next.com/overview/plugins-and-utils#backends) for [Locize](https://www.locize.com?utm_source=next_i18next_readme&utm_medium=github&utm_campaign=readme) ☁️ — built by the same team behind next-i18next, with CDN delivery (works great on Vercel/serverless), AI translation, and no redeploys for copy changes. Starting from a Next.js app with hardcoded strings? Run `npx i18next-cli localize` — one command that wraps strings in `t()`, extracts keys, connects to [Locize](https://www.locize.com?from=next-i18next_readme__localize) and AI-translates your app (review the diff for server components). See the [launch post](https://www.locize.com/blog/i18next-cli-localize?from=next-i18next_readme__localize). --- ## Table of Contents - [App Router Setup](#app-router-setup) - [No-Locale-Path Mode](#no-locale-path-mode) - [Mixed Router Setup](#mixed-router-setup-app-router--pages-router) - [Pages Router Setup](#pages-router-setup) - [Custom i18next Backends](#custom-i18next-backends) - [API Reference](#api-reference) - [Examples](#examples) - [Migration from v15](#migration-from-v15) --- ## App Router Setup ### 1. Install ```bash npm install next-i18next i18next react-i18next ``` ### 2. Translation files Place JSON translation files in your project. There are two common patterns: **In `public/locales/`** (served statically, works with default config — **local/traditional hosting only**): ``` public/locales/en/common.json public/locales/en/home.json public/locales/de/common.json public/locales/de/home.json ``` > **Serverless platforms (Vercel, AWS Lambda, etc.)**: Files in `public/` are served via CDN but are **not** available on the filesystem at runtime. Use `resourceLoader` with dynamic imports instead (see below). **In `app/i18n/locales/`** (bundled via dynamic imports, requires `resourceLoader` — **works everywhere including serverless**): ``` app/i18n/locales/en/common.json app/i18n/locales/de/common.json ``` ### 3. Configuration Create a config file (e.g., `i18n.config.ts`): ```ts import type { I18nConfig } from 'next-i18next/proxy' const i18nConfig: I18nConfig = { supportedLngs: ['en', 'de'], fallbackLng: 'en', defaultNS: 'common', ns: ['common', 'home'], // Recommended: works on all platforms including Vercel/serverless resourceLoader: (language, namespace) => import(`./app/i18n/locales/${language}/${namespace}.json`), } export default i18nConfig ``` The `resourceLoader` uses dynamic `import()` which the bundler can trace, ensuring translation files are included in the serverless function bundle. If you prefer to keep translations in `public/locales/` and are **not** deploying to a serverless platform, you can omit `resourceLoader` — next-i18next will read from the filesystem at runtime. > **Tip**: Import `I18nConfig` from `next-i18next/proxy` (not from `next-i18next`) to keep the config file Edge-safe. > **Dev tip — hot-reloading translations**: set `reloadOnPrerender: process.env.NODE_ENV === 'development'` in your config to refetch translations on every render in dev so edits to locale files appear without restarting `next dev`. The flag is automatically a no-op in production, so it is safe to keep in your committed config — custom backends (HTTP, locize, chained) won't be hit per-request in production builds. > > **Caveat with `import()`-based `resourceLoader`**: dynamic `import()` of JSON is cached at the bundler level and is not reliably re-invalidated by Turbopack/Webpack HMR after the first edit, so hot-reload can stall after one change. For full hot-reload during development, gate your loader so dev uses `fs.readFile` and production keeps bundler-traceable `import()`: > ```ts > const resourceLoader: I18nConfig['resourceLoader'] = > process.env.NODE_ENV === 'development' > ? async (lng, ns) => { > const fs = await import('fs/promises') > const path = await import('path') > const content = await fs.readFile( > path.resolve(process.cwd(), `app/i18n/locales/${lng}/${ns}.json`), > 'utf-8' > ) > return JSON.parse(content) > } > : (lng, ns) => import(`./app/i18n/locales/${lng}/${ns}.json`) > ``` > Pages Router and the App Router default backend already use `fs` and are unaffected. ### 4. Proxy Create `proxy.ts` at your project root (Next.js 16+ replaces `middleware.ts` with `proxy.ts`): ```ts 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).*)'], } ``` > **Note**: `createMiddleware` from `next-i18next/middleware` is still available for projects on Next.js < 16. The proxy: - Detects language from cookie > Accept-Language header > fallback - Redirects bare URLs to locale-prefixed paths (e.g., `/about` -> `/en/about`) - Sets a custom header (`x-i18next-current-language`) for Server Components - Persists the language in a cookie, but only when it changed: 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. Set `persistCookie: false` if another system owns that cookie, and `cookieOptions` to scope it (e.g. `{ domain: '.example.com', secure: true }`) ### 5. Root Layout ``` … ``` Key points: - `initServerI18next(config)` — call once at module scope in the root layout - `getResources(i18n)` — serializes loaded translations for client hydration - `I18nProvider` — wraps children so client components can use `useT()` #### Initialization without ordering assumptions `initServerI18next(config)` is a side effect: it has to run in the process before the first `getT()`. Module scope of the root layout works because Next loads the root layout before anything below it, but nothing enforces it if a second copy of `next-i18next/server` calls `getT()` first, for example from a Route Handler, which is bundled in its own layer. If you would rather not depend on evaluation order at all, bind the config once and import from that module everywhere: ```ts // i18n.server.ts import { createServerI18next } from 'next-i18next/server' import i18nConfig from './i18n.config' export const { getT, getResources, generateI18nStaticParams } = createServerI18next(i18nConfig) ``` ```tsx // any Server Component, layout or generateMetadata import { getT } from '@/i18n.server' ``` Every caller then imports the module that holds the config, so there is no initialization step and no order to get right. Call `createServerI18next` once at module scope: each call owns its own shared i18next instance. ### 6. Server Components ```tsx // app/[lng]/page.tsx import { getT } from 'next-i18next/server' export default async function Home() { const { t } = await getT('home') return

{t('title')}

} export async function generateMetadata() { const { t } = await getT('home') return { title: t('meta_title') } } ``` On Next.js 16.3+ `getT()` resolves the language from the `[lng]` root param (via `next/root-params`) before falling back to the proxy header and cookie. Reading a root param does not opt the route out of static prerendering, so `getT()` is safe in prerendered routes (including with `cacheComponents: true`). Route Handlers and Server Actions have no root params — pass `{ lng }` explicitly there. For the `Trans` component in Server Components, use `react-i18next/TransWithoutContext` and pass both `t` and `i18n`: ```tsx import { Trans } from 'react-i18next/TransWithoutContext' import { getT } from 'next-i18next/server' export default async function Page() { const { t, i18n } = await getT() return ( Welcome to next-i18next ) } ``` ### 7. Client Components ```tsx 'use client' import { useT } from 'next-i18next/client' export default function Counter() { const { t } = useT('home') return {t('click_me')} } ``` `useT` works in both locale-in-path (`/en/about`) and no-locale-path modes. It accepts `[lng]` or `[locale]` as the dynamic route param name. For the `Trans` component in Client Components: ```tsx 'use client' import { Trans, useT } from 'next-i18next/client' export default function Greeting() { const { t } = useT() return Hello world } ``` ### 8. Language Switching (locale-in-path) When the locale is part of the URL path (e.g., `/en/about` → `/de/about`), switch languages by navigating to the new locale prefix: ```tsx 'use client' import { usePathname, useRouter } from 'next/navigation' export function LanguageSwitcher({ supportedLngs }: { supportedLngs: string[] }) { const pathname = usePathname() const router = useRouter() const switchLocale = (locale: string) => { const segments = pathname.split('/') segments[1] = locale router.push(segments.join('/')) } return ( ) } ``` For the no-locale-path mode (cookie-based), see `useChangeLanguage` [below](#no-locale-path-mode). --- ## Hide Default Locale If you want clean URLs for the default language while keeping locale prefixes for other languages, set `hideDefaultLocale: true`: ```ts const i18nConfig: I18nConfig = { supportedLngs: ['en', 'de'], fallbackLng: 'en', hideDefaultLocale: true, } ``` In this mode: - `/about` serves the default language (English) — no prefix needed - `/de/about` serves German — non-default locales keep their prefix - `/en/about` automatically redirects to `/about` (canonical clean URL) - The `[lng]` folder structure stays the same — the proxy rewrites internally --- ## No-Locale-Path Mode If you prefer clean URLs without a locale prefix for **all** languages (e.g., `/about` instead of `/en/about`), set `localeInPath: false`: ```ts const i18nConfig: I18nConfig = { supportedLngs: ['en', 'de'], fallbackLng: 'en', localeInPath: false, resourceLoader: (language, namespace) => import(`./app/i18n/locales/${language}/${namespace}.json`), } ``` In this mode: - Routes live directly under `app/` (no `[lng]` segment) - The middleware detects language from cookies / Accept-Language, sets the header, but does **not** redirect - Server Components use `getT()` as usual (language is read from the header) - Client Components use `useT()` as usual (language comes from `I18nProvider`) - Use `useChangeLanguage()` for language s

Issues· 0 开放

查看全部 Issues在 GitHub 打开

暂无开放 Issues,或尚未同步最近议题。

> 标签

TypeScripti18nextnextnextjsnow

暂无评论,来聊聊你的看法吧

> 工具信息

发布日期2026年8月1日
最后更新2026年9月17日
分类前端框架
定价开源

> 相关工具

R
React
用于构建用户界面的 JavaScript 库
V
Vue.js
渐进式 JavaScript 框架
N
Next.js
基于 React 的全栈 Web 框架