lingui-framework-setup

v2026.09.24

Set up Lingui in a React framework. Use when adding Lingui to a Next.js App Router, Vite, React Router 7, Remix, or TanStack Start project, when wiring locale detection, locale-prefixed URLs, or SSR locale resolution, or when a working setup breaks after a framework or build-tool upgrade.

GitHub
安装命令
npx skhub add lingui/lingui-framework-setup
Markdown
SKILL.md

Lingui Framework Setup

Correct Lingui setup is framework-shaped: what works in a Vite SPA breaks in React Server Components, and a module-level i18n singleton that is fine in the browser bleeds locales across requests under SSR. This skill routes to a framework-native recipe instead of a generic I18nProvider answer.

Work in this order: detect the stack → apply the common steps → follow the framework reference → run the verification sequence.

Step 1 — Detect the stack

Read package.json and the build config before recommending anything. Never guess the compiler — the macro transform silently does nothing when wired into the wrong one.

SignalStackReference
next in deps, app/ or src/app/ with layout.tsxNext.js App Routernextjs-app-router.md
next in deps, pages/ with _app.tsx, no app/Next.js Pages RouterSupported by Lingui, brief notes in nextjs-app-router.md
@tanstack/react-start in depsTanStack Start (SSR)tanstack-start.md
@react-router/dev in devDeps + react-router.config.*React Router 7 framework mode (SSR)react-router-remix.md
@remix-run/dev ≥ 2.7 in devDeps + viteRemix v2 (Vite build, SSR)react-router-remix.md
vite + react, none of the aboveVite SPA (incl. declarative React Router, TanStack Router)vite-spa.md

Compiler detection (decides which macro-transform package to install):

SignalCompilerMacro transform
@vitejs/plugin-react-swcSWC@lingui/swc-plugin (pin exactly — see the swc-plugin-compatibility skill)
@vitejs/plugin-react ^5 or lowerBabel@lingui/babel-plugin-lingui-macro via the plugin's babel option
@vitejs/plugin-react ^6+, Vite 8Babel, standalone passv6 removed the babel option — run the macro as its own pass: @rolldown/plugin-babel + linguiTransformerBabelPreset(). Keeps the stock React plugin
@vitejs/plugin-react ^6+, Vite ≤ 7Babel, standalone passSame, via vite-plugin-babel (no Rolldown). Switching to @vitejs/plugin-react-swc also works, at the cost of an exact pin
Next.js, no .babelrcSWC@lingui/swc-plugin via experimental.swcPlugins
Next.js with .babelrcBabel@lingui/babel-plugin-lingui-macro in .babelrc (a Babel config disables Next's SWC)

One more distinction that changes everything: react-router in deps without @react-router/dev is a declarative SPA (<Routes> in JSX) — that is the Vite SPA reference, not the framework-mode one. Route-module loader/+types code written into a declarative SPA is dead on arrival.

Step 2 — Common steps (every framework)

Version gate. Lingui 6 is current: ESM-only, requires Node ≥ 22.19 (or ≥ 24). Install @lingui/core@^6 @lingui/react@^6 and dev @lingui/cli@^6. If the project cannot meet the Node requirement, pin every @lingui/* package to ^5 — do not mix majors. Do not install @lingui/macro: since v5 the macros live at @lingui/react/macro and @lingui/core/macro.

Per-stack extras (details in each reference):

StackExtra runtimeExtra dev
Next.js App Router—@lingui/swc-plugin (exact pin)
Vite SPA@lingui/detect-locale@lingui/vite-plugin + transform plugin per compiler
React Router 7 / Remix—@lingui/vite-plugin, @lingui/format-po, transform plugin
TanStack Start—@lingui/vite-plugin, transform plugin

@lingui/detect-locale is browser-only (navigator, localStorage, window.location). Never install it on an SSR stack — it throws on the server or desyncs hydration; SSR stacks resolve locale from the request (cookie / Accept-Language) instead.

Config and catalogs. Create lingui.config.ts with sourceLocale, locales, and one catalogs entry; the lingui-best-practices skill owns catalog hygiene (build-script wiring, gitignore rules, CI drift check) and the single-sourced locale module (locales.ts with resolveLocale, getDirection, localeDisplayName) — reuse both, do not re-derive them.

Two catalog-loading models. On Vite-based stacks, @lingui/vite-plugin compiles .po on import — await import('./locales/en/messages.po') just works, there are no compiled artifacts to script or gitignore. Next.js has no Vite pipeline: run lingui compile prepended to dev/build scripts and import the compiled catalogs (@lingui/loader is webpack-only and Turbopack is the Next 15/16 default, so a loader-based setup is a trap).

Step 3 — Framework reference

Read the matching reference file fully before editing the project. Every reference follows the same section contract, in order:

packages → build-tool integration → lingui.config → locale resolution → provider/layout wiring → routing strategies → language switcher → gotchas → verification

If the project needs locale-prefixed URLs, every reference offers the same three strategies — unprefixed source locale, all locales prefixed, or no URL locale (cookie/storage only). Restructuring routes is invasive: ask the user which strategy they want before moving files.

Step 4 — Verify

Run in this order; each step must pass before the next:

npx lingui extract --clean   # catalogs regenerate; count matches expectations
npx lingui compile           # only on stacks with compiled catalogs (Next.js)
npx tsc --noEmit             # types resolve, incl. catalog imports
npm run build                # macro wiring errors surface here

Then prove the transform ran. A green build does not: a mis-wired macro transform is silently a no-op and the app ships in the source language. Translate one string in a non-source catalog, run the app in that locale, and confirm the translation reaches the browser (each reference gives the stack's exact check — curl the server-rendered HTML on SSR stacks, hard-load a deep link on the SPA). The setup is done when you have seen a translated string, not when the build is green.

Raw untranslated text at that point is a compiler wiring problem — wrong plugin, bare-string SWC entry, or the @vitejs/plugin-react@6 babel trap; see the swc-plugin-compatibility skill.

Adding a new framework

Another stack (a new meta-framework, a new build tool) costs two edits: one row in the Step 1 detection table, and one file under references/ following the Step 3 section contract. Framework-specific facts go in the reference; anything true of every stack — the version gate, the two catalog-loading models, the SSR detect-locale rule — stays here, stated once. Every non-obvious rule carries a one-sentence why.

Related skills

  • lingui-best-practices — macro selection, catalog hygiene, the shared locale module. This skill assumes it; don't duplicate it.
  • swc-plugin-compatibility — SWC plugin version pinning and the silent-failure modes of a mis-wired transform.
  • migrate-i18next-to-lingui — if the project already has i18next, migrate first, then return here for framework wiring.
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

2026年9月24日

分类

未分类

许可证

MIT

源路径

skills/lingui-framework-setup

默认分支

main

最新提交

a623188

Tree SHA

2c3ee38