[Next.js]

Wrap strings for react-intl with defaultMessage included

Polyglot emits formatMessage({ id, defaultMessage }) — self-contained calls that render correctly even before your extraction pipeline runs.

react-intl is an extraction-pipeline ecosystem: catalogs are generated from source by formatjs extract. So the correct wrap isn't a bare ID — it's a self-contained call that carries the text:

The transformation

Before — src/app/page.tsx
"use client";

export default function Page() {
    return (
        <main>
            <h1>Welcome back</h1>
            <p>Your projects are ready</p>
            <input placeholder="Search projects" />
        </main>
    );
}
After — src/app/page.tsx
"use client";
import { useIntl } from "react-intl";

export default function Page() {
  const intl = useIntl();
    return (
        <main>
            <h1>{intl.formatMessage({ id: "src.app.page.welcome_back", defaultMessage: "Welcome back" })}</h1>
            <p>{intl.formatMessage({ id: "src.app.page.your_projects_are_ready", defaultMessage: "Your projects are ready" })}</p>
            <input placeholder={intl.formatMessage({ id: "src.app.page.search_projects", defaultMessage: "Search projects" })} />
        </main>
    );
}

Every call includes defaultMessage. That means:

  • It renders correctly immediately — even in an app whose IntlProvider has no entry for the new ID yet. No raw IDs in production, ever.
  • formatjs extract collects it — your existing pipeline keeps working; Polyglot's calls are exactly what a careful react-intl developer writes by hand.
  • ICU safety is guaranteed by construction: the inline text is the same ICU-escaped value written to the catalog, so the two can never disagree about braces or apostrophes.

Hooks and scaffolding

useIntl() is injected into each component that needs it (client components only — server components are protected), and the catalog is written alongside:

Written — messages/en.json
{
  "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"
}
Translated — messages/de.json
{
  "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"
}
Translated — messages/fr.json
{
  "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"
}
✓ 3 strings auto-wrapped · 0 flagged for manual review · 0 unsafe transforms → polyglot-i18n-report.md
✓ wiring checks passed (1 injected import(s), 3 catalog value(s), 1 catalog file(s))

Try it

$ curl -fsSL https://getpolyglot.ai/install.sh | bash
$ polyglot init --framework nextjs
$ polyglot scan
$ polyglot wrap
$ polyglot translate --languages de   # 50 strings free, no signup

Start in your terminal

Stop hunting for untranslated strings.

Install the CLI, run a scan, and see exactly what you're missing. Free, no account required.

$curl -fsSL https://getpolyglot.ai/install.sh | bash
Wrap strings for react-intl with defaultMessage included | Polyglot