Skip to content
Back to skills

Lingui Framework Setup

ASecurity

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.

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 24, 2026
developmentgobashreactnextjsnodegit

Works with

  • cli

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned September 24, 2026

npx -y skills add lingui/skills --skill lingui-framework-setup --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Lingui Framework Setup?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Lingui Framework Setup
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lingui-lingui-framework-setup/badge)](https://www.skillsdirectory.com/skills/lingui-lingui-framework-setup)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: lingui-framework-setup
description: 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.
---

# 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.

| Signal | Stack | Reference |
|---|---|---|
| `next` in deps, `app/` or `src/app/` with `layout.tsx` | Next.js App Router | [nextjs-app-router.md](references/nextjs-app-router.md) |
| `next` in deps, `pages/` with `_app.tsx`, no `app/` | Next.js Pages Router | Supported by Lingui, brief notes in [nextjs-app-router.md](references/nextjs-app-router.md) |
| `@tanstack/react-start` in deps | TanStack Start (SSR) | [tanstack-start.md](references/tanstack-start.md) |
| `@react-router/dev` in devDeps + `react-router.config.*` | React Router 7 framework mode (SSR) | [react-router-remix.md](references/react-router-remix.md) |
| `@remix-run/dev` ≥ 2.7 in devDeps + `vite` | Remix v2 (Vite build, SSR) | [react-router-remix.md](references/react-router-remix.md) |
| `vite` + `react`, none of the above | Vite SPA (incl. declarative React Router, TanStack Router) | [vite-spa.md](references/vite-spa.md) |

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

| Signal | Compiler | Macro transform |
|---|---|---|
| `@vitejs/plugin-react-swc` | SWC | `@lingui/swc-plugin` (pin exactly — see the swc-plugin-compatibility skill) |
| `@vitejs/plugin-react` `^5` or lower | Babel | `@lingui/babel-plugin-lingui-macro` via the plugin's `babel` option |
| `@vitejs/plugin-react` `^6`+, Vite 8 | Babel, standalone pass | v6 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 ≤ 7 | Babel, standalone pass | Same, via `vite-plugin-babel` (no Rolldown). Switching to `@vitejs/plugin-react-swc` also works, at the cost of an exact pin |
| Next.js, no `.babelrc` | SWC | `@lingui/swc-plugin` via `experimental.swcPlugins` |
| Next.js with `.babelrc` | Babel | `@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):

| Stack | Extra runtime | Extra 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:

```bash
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.

Files in this skill

  • SKILL.md7.5 KB
  • references/nextjs-app-router.md14.9 KB
  • references/react-router-remix.md12 KB
  • references/tanstack-start.md13.2 KB
  • references/vite-spa.md10.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.