Polyglot + next-intl: how they work together

Polyglot detects and translates. next-intl renders. Here's how to use them together for a complete Next.js i18n workflow — from finding untranslated strings to serving localized pages.

5 min read← All articles

The most common question we get from Next.js developers: "Do I use Polyglot instead of next-intl, or with it?" The answer is with it. They solve different problems and complement each other perfectly.

What each tool does

next-intl is a runtime library. It provides the useTranslations() hook, locale routing middleware, and message formatting (plurals, dates, numbers). It's what your Next.js app uses at runtime to display the right translation for the current locale.

Polyglot is a CLI tool. It scans your source code to find untranslated strings, wraps hardcoded strings in next-intl calls, translates them with context-aware LLMs for you to review, and lets you preview the results. It runs in your terminal and CI pipeline, not in your app.

They work at different layers:

Polyglotnext-intl
When it runsDevelopment / CIRuntime
What it doesDetect → Wrap → Translate → Review → PreviewRender translations
Where it livesCLI / GitHub ActionYour app bundle
OutputJSON translation filesLocalized UI

The workflow

Here's how a complete Next.js i18n workflow looks with both tools:

1. Scan for untranslated strings

polyglot scan

Polyglot lists the hardcoded UI strings it finds in your TSX files as candidates to review (output trimmed):

src/app/page.tsx  (1 string)
────────────────────────────────────────────────────────────
  L8    [text]  Welcome to our platform

src/components/nav.tsx  (3 strings)
────────────────────────────────────────────────────────────
  L12   [text]  Dashboard
  L13   [text]  Settings
  L14   [text]  Log out

Found 47 localization candidates in 12 files (64 files scanned)

2. Wrap strings with next-intl

Preview the codemod first, then apply it:

polyglot wrap --dry-run
polyglot wrap

Polyglot rewrites detected strings with next-intl's useTranslations() hook, using a namespace derived from the file path and a key derived from the text:

// Before: src/app/page.tsx (Polyglot detected this)
<h1>Welcome to our platform</h1>

// After (Polyglot wraps it with next-intl)
const t = useTranslations("src.app.page");
<h1>{t('welcome_to_our_platform')}</h1>

And it adds the source string to your messages file:

// messages/en.json
{
  "src": {
    "app": {
      "page": {
        "welcome_to_our_platform": "Welcome to our platform"
      }
    }
  }
}

Anything it can't rewrite safely is listed in polyglot-i18n-report.md with a reason, for you to handle by hand.

3. Translate with Polyglot

polyglot translate --languages fr,de,ja

Polyglot reads your messages/en.json, translates each string with LLMs (using component context, glossary terms, and translation memory), and outputs the target locale files:

// messages/fr.json
{
  "src": {
    "app": {
      "page": {
        "welcome_to_our_platform": "Bienvenue sur notre plateforme"
      }
    }
  }
}

Generated translations also wait for review in the Polyglot dashboard — automatic approval is off. Once reviewers approve or edit them, polyglot pull --approved-only writes the reviewed values back to your catalogs.

4. Preview locally

polyglot preview --lang fr

Polyglot starts your dev server with the French catalog and opens the page. Depending on your routing, you may need to switch the locale yourself; the CLI tells you which. Preview doesn't flag problems for you — it lets you spot text overflow, layout breaks, RTL issues, and wrong-context wording before you deploy.

5. Catch regressions in CI

Add the open Polyglot Action to your PR workflow:

# .github/workflows/i18n.yml
- uses: actions/checkout@v4
  with:
    fetch-depth: 0
- uses: polyglot-i18n/[email protected]
  with:
    check-mode: differential

New untranslated strings get flagged in the PR that introduces them, so hardcoded English gets caught in review. The check needs a committed polyglot.toml. See the CI/CD docs for the full set of inputs. On Team and Scale, Polyglot Automation (early access) can open a separate catalog-only translation PR after someone reviews the translations.

Configuration

Polyglot auto-detects Next.js projects and reads your polyglot.toml for project-specific settings:

# polyglot.toml
[project]
name = "my-app"
framework = "nextjs"
source_language = "en"
target_languages = ["fr", "de", "ja"]

[translation]
output_dir = "messages"
output_format = "json"

The output_dir should point to where next-intl expects your message files. Polyglot reads the source messages, translates them, and writes the target locale files to the same directory.

FAQ

Does Polyglot modify my source code? polyglot scan is read-only — it only reports untranslated strings. polyglot wrap can automatically wrap strings with translation functions, but you control when and how to run it.

Does Polyglot replace next-intl? No. next-intl is your runtime library — it handles locale routing, message formatting, and rendering. Polyglot handles detection, wrapping, and translation. You need both.

What about next-intl's own tooling? next-intl's tooling works from messages you've already written into your code with its APIs. It doesn't hunt for hardcoded strings you haven't wrapped yet. Polyglot covers the "find what I missed" step and the guarded code rewrite, with --dry-run available before it touches a file.

Can I use Polyglot with react-i18next instead of next-intl? Yes. Polyglot outputs standard JSON files. Whether your runtime library is next-intl, react-i18next, or react-intl, Polyglot's output is compatible.

What if I already have some translations? Polyglot's incremental mode only translates strings that are new or changed. Existing translations in your message files are preserved. Translation memory ensures new translations stay consistent with existing ones.

Getting started

If you already have a Next.js app with next-intl:

# Install Polyglot
curl -fsSL https://getpolyglot.ai/install.sh | bash

# Initialize
polyglot init

# Find what you've missed
polyglot scan

# Wrap hardcoded strings in next-intl calls
polyglot wrap --dry-run
polyglot wrap

# Translate new strings
polyglot translate

# Preview
polyglot preview --lang fr

If you're starting from scratch, set up next-intl first (follow their getting started guide), then use Polyglot to find strings you haven't wrapped yet and translate them.

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
Polyglot + next-intl: how they work together - Polyglot Blog | Polyglot