Polyglot emits i18n._(id, {}, { message }) — Lingui's documented fallback shape — so wrapped strings render correctly before lingui extract ever runs.
Lingui, like react-intl, generates catalogs from source with lingui extract. Polyglot therefore wraps with Lingui's documented runtime-fallback shape — the message travels with the call:
"use client";
export default function Page() {
return (
<main>
<h1>Welcome back</h1>
<p>Your projects are ready</p>
<input placeholder="Search projects" />
</main>
);
}"use client";
import { useLingui } from "@lingui/react";
export default function Page() {
const { i18n } = useLingui();
return (
<main>
<h1>{i18n._("src.app.page.welcome_back", {}, { message: "Welcome back" })}</h1>
<p>{i18n._("src.app.page.your_projects_are_ready", {}, { message: "Your projects are ready" })}</p>
<input placeholder={i18n._("src.app.page.search_projects", {}, { message: "Search projects" })} />
</main>
);
}message renders when the ID isn't in the active catalog — new strings are correct in production from the moment the wrap lands.useLingui() is injected where needed; rich inline formatting uses Lingui's <Trans> component, whose children are the message.lingui extract picks the calls up like hand-written ones.{
"src.app.page.search_projects": "Search projects",
"src.app.page.welcome_back": "Welcome back",
"src.app.page.your_projects_are_ready": "Your projects are ready"
}{
"src.app.page.search_projects": "Projekte suchen",
"src.app.page.welcome_back": "Willkommen zurück",
"src.app.page.your_projects_are_ready": "Ihre Projekte sind bereit"
}{
"src.app.page.search_projects": "Rechercher des projets",
"src.app.page.welcome_back": "Bon retour",
"src.app.page.your_projects_are_ready": "Vos projets sont prêts"
}$ curl -fsSL https://getpolyglot.ai/install.sh | bash
$ polyglot init --framework nextjs
$ polyglot scan
$ polyglot wrap
$ polyglot translate --languages de # 50 strings free, no signupStart in your terminal
Install the CLI, run a scan, and see exactly what you're missing. Free, no account required.