Agent skill

Migrate I18next To Lingui

by B0und in B0und/WikiSpeedrun

Migrate i18next/react-i18next projects to Lingui. An agent skill from B0und/WikiSpeedrun.

MITAuto-check passedFrontend & Design

Install Migrate I18next To Lingui

skills CLI
$ npx skills add B0und/WikiSpeedrun --skill migrate-i18next-to-lingui -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install B0und/WikiSpeedrun migrate-i18next-to-lingui --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/B0und/WikiSpeedrun.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/migrate-i18next-to-lingui .claude/skills/migrate-i18next-to-lingui && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
migrate-i18next-to-lingui
GitHub stars
133
Token cost
~3.1k tokens
SKILL.md length
645 words
Files
3 (incl. references)
Skills in repo
6
Repo updated
First seen
Licence
MIT

At a glance

Migrate i18next/react-i18next projects to Lingui. An agent skill from B0und/WikiSpeedrun.

  • Works in 11 steps: Install Lingui → Create lingui.config.js → Configure Build Tooling → …
  • The user wants to replace i18next
  • SKILL.md covers Migration Checklist, Step 1: Install Lingui, Step 2: Create lingui.config.js and Step 3: Configure Build Tooling, plus 11 more sections
  • Calls npm and npx

What it does

Migrate I18next To Lingui is an agent skill from B0und/WikiSpeedrun. Migrate i18next/react-i18next projects to Lingui. Use when the user wants to replace i18next, react-i18next, useTranslation, i18n.t(), Trans i18nKey, or i18next JSON catalogs with Lingui equivalents. Covers package installation, config setup, code transformation patterns, plural migration, namespace handling, and catalog conversion.

Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 3 other files, including reference files (for example `references/catalog-conversion.md` and `references/migration-patterns.md`).

It sits in Frontend & Design, covering Internationalization. It works with React, Vite and TypeScript. The repository describes itself as: Wikipedia Speedrun Game. The licence is MIT.

When your agent uses it

  • The user wants to replace i18next
  • I18next JSON catalogs with Lingui equivalents

Example prompts

  • “/migrate-i18next-to-lingui”

Requirements

  • Node.js

Workflow steps

11 steps, taken from the step headings in SKILL.md.

  1. Install Lingui
  2. Create lingui.config.js
  3. Configure Build Tooling
  4. Replace i18n Initialization
  5. Migrate React Components
  6. Migrate JS/TS Strings
  7. Migrate Plurals
  8. Migrate Namespaces
  9. Convert Existing Translation Catalogs
  10. Build & Verify
  11. Remove i18next

What it can do on your machine

Read from SKILL.md and the folder at commit a03d655. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npm
    • npx

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • lingui.dev

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Migrate I18next To Lingui loads about 3.1k tokens when it runs, and up to ~5.9k if it reads all its reference files. Until then it costs about 90 tokens; SKILL.md has 645 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~90
When it runs · the whole SKILL.md, loaded when a task matches
~3.1k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~5.9k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from B0und/WikiSpeedrun at commit a03d655, republished under its MIT licence (© B0und). 645 words, ~3,056 tokens.

Download SKILL.mdSave it as .claude/skills/migrate-i18next-to-lingui/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.
name
migrate-i18next-to-lingui
description
Migrate i18next/react-i18next projects to Lingui. Use when the user wants to replace i18next, react-i18next, useTranslation, i18n.t(), Trans i18nKey, or i18next JSON catalogs with Lingui equivalents. Covers package installation, config setup, code transformation patterns, plural migration, namespace handling, and catalog conversion.

Migrate i18next to Lingui

Migration Checklist

- [ ] Step 1: Install Lingui packages
- [ ] Step 2: Create lingui.config.js
- [ ] Step 3: Set up build tooling (Babel/SWC/Vite)
- [ ] Step 4: Replace i18n initialization
- [ ] Step 5: Migrate React components (useTranslation → useLingui, Trans → Trans)
- [ ] Step 6: Migrate JS/TS strings (t() → t``)
- [ ] Step 7: Migrate plurals
- [ ] Step 8: Migrate namespaces
- [ ] Step 9: Convert existing translation catalogs
- [ ] Step 10: Run lingui extract && lingui compile
- [ ] Step 11: Remove i18next packages

Step 1: Install Lingui

Node version gate: Lingui 6 is ESM-only and requires Node.js ≥ 22.19 (or ≥ 24). On older Node, pin all @lingui/* packages to ^5.

bash
# Core (always required)
npm install @lingui/core @lingui/react

# CLI (dev)
npm install --save-dev @lingui/cli

# Macro support - pick one based on build tool:
# Babel
npm install --save-dev @lingui/babel-plugin-lingui-macro
# SWC
npm install --save-dev @lingui/swc-plugin
# Vite (also install the Babel macro plugin above — see Step 3)
npm install --save-dev @lingui/vite-plugin

Step 2: Create lingui.config.js

js
import { defineConfig } from "@lingui/cli";

export default defineConfig({
  sourceLocale: "en",
  locales: ["en", "de", "fr"], // match your existing locales
  catalogs: [
    {
      path: "<rootDir>/src/locales/{locale}/messages",
      include: ["src"],
    },
  ],
});

Step 3: Configure Build Tooling

Vite (vite.config.ts):

ts
import { lingui } from "@lingui/vite-plugin";
import react from "@vitejs/plugin-react";

export default {
  plugins: [
    react({ babel: { plugins: ["@lingui/babel-plugin-lingui-macro"] } }),
    lingui(),
  ],
};

lingui() alone does not transform macros — the Babel macro plugin inside react() does that (requires @vitejs/plugin-react@^5; v6 removed the babel option — use the SWC variant instead).

The lingui() plugin also compiles .po catalogs on the fly, so on Vite the app can import catalogs directly and skip the lingui compile step entirely:

ts
// Dynamic import; the .po extension is mandatory
const { messages } = await import(`./locales/${locale}/messages.po`);

For TypeScript, declare the module so .po imports type-check:

ts
// src/vite-env.d.ts
declare module "*.po" {
  import type { Messages } from "@lingui/core";
  export const messages: Messages;
}

Babel (.babelrc or babel.config.js):

json
{ "plugins": ["macros"] }

Next.js with SWC (next.config.js):

js
module.exports = {
  experimental: {
    swcPlugins: [["@lingui/swc-plugin", {}]],
  },
};

Build-tooling caveats: @lingui/swc-plugin must be version-matched to your SWC runtime, plugin entries must be [name, options] tuples (a bare string silently disables macros), and @vitejs/plugin-react@6 removed Babel support entirely — see the swc-plugin-compatibility skill for all three.

Step 4: Replace i18n Initialization

Before (i18next):

js
import i18next from "i18next";
import { initReactI18next } from "react-i18next";

i18next.use(initReactI18next).init({
  lng: "en",
  resources: { en: { translation: { key: "Hello world" } } },
});

After (Lingui):

js
import { i18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";
import { messages } from "./locales/en/messages";

i18n.load("en", messages);
i18n.activate("en");

function App() {
  return <I18nProvider i18n={i18n}>{/* app */}</I18nProvider>;
}

Dynamic locale switching:

js
async function changeLocale(locale) {
  const { messages } = await import(`./locales/${locale}/messages`);
  i18n.load(locale, messages);
  i18n.activate(locale);
}

Step 5: Migrate React Components

useTranslation → useLingui

Before:

jsx
import { useTranslation } from "react-i18next";

function MyComponent() {
  const { t } = useTranslation();
  return <p>{t("greeting")}</p>;
}

After:

jsx
import { useLingui } from "@lingui/react/macro";

function MyComponent() {
  const { t } = useLingui();
  return <p>{t`Hello World`}</p>;
}
Trans component

Before:

jsx
import { Trans } from "react-i18next";

<Trans i18nKey="welcome">Hello World!</Trans>

After:

jsx
import { Trans } from "@lingui/react/macro";

<Trans>Hello World!</Trans>

For explicit IDs (when preserving i18next keys):

jsx
<Trans id="welcome">Hello World!</Trans>
Trans with interpolation

Before:

jsx
<Trans i18nKey="greeting" values={{ name }}>Hello {{ name }}!</Trans>

After:

jsx
<Trans>Hello {name}!</Trans>

Step 6: Migrate JS/TS Strings

Simple strings
i18nextLingui
t('key')t\Message text``
t('key', { name })t\Hello ${name}``
t('key', { defaultValue: 'Hi' })t\Hi``

Before:

js
import i18next from "i18next";

const msg = i18next.t("greeting", { name: "Tom" });

After:

jsx
import { useLingui } from "@lingui/react/macro";

function MyComponent() {
  const { t } = useLingui();
  const msg = t`Hello ${name}`;
}

In vanilla JS (outside components):

js
import { t } from "@lingui/core/macro";

const msg = t`Hello ${name}`;
Preserving explicit keys from i18next

If you want to keep the i18next message IDs:

js
import { t } from "@lingui/core/macro";

// i18next: t('navigation.home')
const msg = t({ id: "navigation.home", message: "Home" });
Module-level / lazy strings

Before (i18next):

js
const LABELS = {
  active: "Active",
  inactive: "Inactive",
};
// translated at render time

After (Lingui):

js
import { msg } from "@lingui/core/macro";
import { useLingui } from "@lingui/react";

const LABELS = {
  active: msg`Active`,
  inactive: msg`Inactive`,
};

function StatusDisplay({ status }) {
  const { _ } = useLingui();
  return <div>{_(LABELS[status])}</div>;
}

Step 7: Migrate Plurals

i18next uses separate keys per plural form. Lingui uses ICU MessageFormat in a single message.

Before (i18next):

json
{
  "item_one": "{{count}} item",
  "item_other": "{{count}} items"
}
js
t("item", { count });

After (Lingui) - JSX:

jsx
import { Plural } from "@lingui/react/macro";

<Plural value={count} one="# item" other="# items" />

After (Lingui) - JS strings:

js
import { plural } from "@lingui/core/macro";

const msg = plural(count, {
  one: "# item",
  other: "# items",
});

Exact matches (i18next _0):

jsx
<Plural
  value={count}
  _0="No items"
  one="# item"
  other="# items"
/>

Step 8: Migrate Namespaces

i18next namespaces (useTranslation('common')) map to Lingui catalog paths. Two approaches:

Option A - Single catalog (simplest): Remove namespaces and use one unified catalog. Update lingui.config.js to include all source directories.

Option B - Multiple catalogs (preserves namespace separation):

js
// lingui.config.js
catalogs: [
  {
    path: "<rootDir>/src/locales/{locale}/common",
    include: ["src/components/common"],
  },
  {
    path: "<rootDir>/src/locales/{locale}/auth",
    include: ["src/components/auth"],
  },
]

With multiple catalogs, load them all at startup:

js
import { messages as commonMessages } from "./locales/en/common";
import { messages as authMessages } from "./locales/en/auth";

i18n.load("en", { ...commonMessages, ...authMessages });
i18n.activate("en");

Step 9: Convert Existing Translation Catalogs

See catalog-conversion.md for and patterns.

Key concept: i18next uses JSON with dotted keys; Lingui uses .po files with the message as the ID (or an explicit ID you provide).

Step 10: Build & Verify

Run the full verification loop in this order — each stage catches what the previous one can't:

bash
npx lingui extract --clean   # extracts all messages → .po files, drops obsolete entries
npx lingui compile           # compiles .po → runtime message catalogs
npx tsc --noEmit             # type errors from changed imports/APIs
npm run build                # macro transform actually runs in the real build

On Vite with @lingui/vite-plugin importing .po catalogs directly (Step 3), skip lingui compile — the plugin compiles at dev/build time and there are no compiled catalog files to manage.

Add to package.json:

json
{
  "scripts": {
    "i18n:extract": "lingui extract",
    "i18n:compile": "lingui compile"
  }
}

For TypeScript:

bash
npx lingui compile --typescript
Show full SKILL.md (244 more words)Show less
Recall Check: Find Strings the Migration Missed

A green build only proves the migrated strings work — not that all strings were migrated. Two checks:

1. No i18next remnants. All of these should return nothing:

bash
grep -rn "from ['\"]i18next\|from ['\"]react-i18next" src/
grep -rn "useTranslation\|i18nKey\|i18next.t(" src/

2. No unwrapped user-facing strings. Run eslint-plugin-lingui's no-unlocalized-strings rule over the tree — it catches hardcoded strings that were never in i18next to begin with, plus any defaultValue text left behind as plain strings:

js
// eslint.config.js
import pluginLingui from "eslint-plugin-lingui";

export default [
  {
    plugins: { lingui: pluginLingui },
    rules: {
      "lingui/no-unlocalized-strings": ["warn", {
        ignore: ["^[A-Z0-9_-]+$"],                    // enums, constants
        ignoreNames: ["className", "src", "data-testid"],
        ignoreFunctions: ["console.*", "cn", "cva"],
      }],
    },
  },
];

The scan is deliberately over-inclusive — review each hit and either wrap it or confirm it's a non-UI string (class names, keys, URLs). Keep the plugin installed afterwards as a permanent guardrail. Report any strings you deliberately leave unwrapped rather than silently skipping them.

For the full audit loop — tuned scanner config, bounded fix rounds, residual reporting — use the find-unwrapped-strings skill. The check above is its migration-scoped subset.

Step 11: Remove i18next

bash
npm uninstall i18next react-i18next

Common Patterns Reference

Date/Number Formatting

Before (i18next):

js
t("intlDateTime", { val: new Date() });

After (Lingui):

jsx
import { useLingui } from "@lingui/react/macro";

function Component() {
  const { i18n } = useLingui();
  return <span>{new Intl.DateTimeFormat(i18n.locale).format(date)}</span>;
}
Context (disambiguation)

Before (i18next):

js
t("right", { context: "direction" });

After (Lingui):

jsx
<Trans context="direction">right</Trans>
// or
t({ message: "right", context: "direction" });
Gender / Select

Before (i18next):

json
{ "pronoun_male": "He", "pronoun_female": "She", "pronoun_other": "They" }

After (Lingui):

js
import { select } from "@lingui/core/macro";

const pronoun = select(gender, {
  male: "He",
  female: "She",
  other: "They",
});

Pitfalls

  • Don't call t\...`` at module level. Use msg\...`instead and translate with_(descriptor)` at render time.
  • After locale change, call both i18n.load(locale, messages) and i18n.activate(locale).
  • Wrap the entire app in <I18nProvider i18n={i18n}> before any component uses useLingui or Trans.
  • Always run lingui compile before building for production; the app imports compiled .js catalogs, not .po files.
  • Generated IDs change if message text changes. If stability matters, use explicit id props.

Additional Resources

© B0und, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 2 other files (references) in .agents/skills/migrate-i18next-to-lingui of B0und/WikiSpeedrun.

  • SKILL.md
  • references/catalog-conversion.md
  • references/migration-patterns.md

Open the folder on GitHubat commit a03d655

Compare with similar skills

Migrate I18next To Lingui next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Migrate I18next To Lingui compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Migrate I18next To Lingui this skillB0und/WikiSpeedrun133—~3.1kAutomated safety check: PassMIT
Admin Template Project Initializersouthliu/south-admin-react580—~519Automated safety check: PassMIT
Web Artifacts Builderanthropics/skills180k40 repos~769Automated safety check: PassApache-2.0
Lobe Designlobehub/lobe-ui2.2k—~2.2kAutomated safety check: PassMIT
Frontend Build Timing Auditopenops-cloud/openops1.1k—~2.3kAutomated safety check: PassCustom licence
Design To CodeMigoXLab/coderio1142 repos~1.2kAutomated safety check: PassApache-2.0

Similar skills

  • Admin Template Project Initializer

    southliu/south-admin-react

    Removes the south-admin-react template's demo pages, components and menu entries, after a dry-run preview and your confirmation, and cleans up the matching imports.

    580 GitHub stars~519 tokensUpdated 21 days ago
    Frontend & DesignAuto-check passed
  • Web Artifacts Builder

    anthropics/skills

    Official

    Builds multi-component claude.ai HTML artifacts as a small React, TypeScript and Tailwind project, then bundles it into one shareable HTML file.

    180k GitHub starsUsed in 40 repos~769 tokens
    Frontend & DesignAuto-check passed
  • Lobe Design

    lobehub/lobe-ui

    Build UI with the LobeHub design system — @lobehub/ui/base-ui, the controlled form at @lobehub/ui/base-ui/form, and the chat, mobile, dashboard, awesome, brand, mdx, and i18n namespaces, plus…

    2.2k GitHub stars~2.2k tokensUpdated today
    Frontend & DesignAuto-check passed
  • Frontend Build Timing Audit

    openops-cloud/openops

    Detects and diagnoses chunk-evaluation timing bugs in the Vite/rolldown production build of react-ui (works-in-dev / broken-in-build i18n regressions, missing UI labels, module-scope t()…

    1.1k GitHub stars~2.3k tokensUpdated yesterday
    Frontend & DesignAuto-check passed
  • Design To Code

    MigoXLab/coderio

    Pixel-perfect Figma to React conversion using coderio. An agent skill from MigoXLab/coderio.

    114 GitHub starsUsed in 2 repos~1.2k tokens
    Frontend & DesignAuto-check passed
  • South Admin CRUD Generator

    southliu/south-admin-react

    Generates a full CRUD page - page component, data model and API client - from the south-admin-react project's own VS Code snippet templates.

    580 GitHub stars~1.7k tokensUpdated 21 days ago
    Frontend & DesignAuto-check passed

More from B0und/WikiSpeedrun

  • Lingui Best Practices

    B0und/WikiSpeedrun

    Implement internationalization with Lingui in React and JavaScript applications.

    133 GitHub starsUsed in 2 repos~4.2k tokens
    Auto-check passed
  • Find Unwrapped Strings

    B0und/WikiSpeedrun

    Audit a Lingui project for hardcoded user-facing strings that were never wrapped in macros.

    133 GitHub stars~2.1k tokensUpdated 21 days ago
    Auto-check passed
  • Lingui Framework Setup

    B0und/WikiSpeedrun

    Set up Lingui in a React framework. An agent skill from B0und/WikiSpeedrun.

    133 GitHub stars~1.9k tokensUpdated 21 days ago
    Auto-check passed
  • Enhanced Message Context

    B0und/WikiSpeedrun

    Add translator comments to Lingui messages so translations are accurate.

    133 GitHub stars~3.3k tokensUpdated 21 days ago
    Auto-check passed
  • Swc Plugin Compatibility

    B0und/WikiSpeedrun

    Diagnose and fix Lingui SWC plugin compatibility errors with Next.js, Vite, Rspack, or other SWC runtimes.

    133 GitHub stars~2.3k tokensUpdated 21 days ago
    Auto-check passed

Questions about Migrate I18next To Lingui

What does Migrate I18next To Lingui do?

Migrate i18next/react-i18next projects to Lingui. An agent skill from B0und/WikiSpeedrun. Migrate I18next To Lingui is an agent skill from B0und/WikiSpeedrun. Migrate i18next/react-i18next projects to Lingui.

When should I use Migrate I18next To Lingui?

Migrate I18next To Lingui fits situations like: the user wants to replace i18next; I18next JSON catalogs with Lingui equivalents.

How do I install Migrate I18next To Lingui in Claude Code?

Run `npx skills add B0und/WikiSpeedrun --skill migrate-i18next-to-lingui -a claude-code`. Or copy the skill folder (.agents/skills/migrate-i18next-to-lingui in B0und/WikiSpeedrun) into .claude/skills/migrate-i18next-to-lingui in your project. Claude Code loads it when a task matches its description.

How do I install Migrate I18next To Lingui in Codex?

Run `npx skills add B0und/WikiSpeedrun --skill migrate-i18next-to-lingui -a codex`. Or copy the skill folder (.agents/skills/migrate-i18next-to-lingui in B0und/WikiSpeedrun) into .agents/skills/migrate-i18next-to-lingui in your project. Codex loads it when a task matches its description.

Can I use Migrate I18next To Lingui in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add B0und/WikiSpeedrun --skill migrate-i18next-to-lingui -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/migrate-i18next-to-lingui, .gemini/skills/migrate-i18next-to-lingui, .github/skills/migrate-i18next-to-lingui and .opencode/skills/migrate-i18next-to-lingui in your project.

What does Migrate I18next To Lingui need to run?

Going by SKILL.md and its folder, Migrate I18next To Lingui needs the command-line tools its instructions call (npm and npx). Our summary lists: Node.js.

Does Migrate I18next To Lingui access the network?

SKILL.md names 1 domain. As links in the text: lingui.dev. This is read from the text; nothing was executed.

Is Migrate I18next To Lingui safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Migrate I18next To Lingui use?

Migrate I18next To Lingui is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Migrate I18next To Lingui use?

About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 2.9k tokens, read only when the agent opens those files.

What are the alternatives to Migrate I18next To Lingui?

Skills that share tags, products or a category with Migrate I18next To Lingui: Admin Template Project Initializer (southliu/south-admin-react, 580 stars), Web Artifacts Builder (anthropics/skills, 180k stars), Lobe Design (lobehub/lobe-ui, 2.2k stars) and Frontend Build Timing Audit (openops-cloud/openops, 1.1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Migrate I18next To Lingui?

B0und (a GitHub user) maintains it in B0und/WikiSpeedrun, which has 133 GitHub stars. The repository holds 6 skills in this directory. The repository was last updated on September 19, 2026.

Source: B0und/WikiSpeedrun on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.