Platforms

Next.js

Localize a Next.js app through its next-intl messages. The source file is pushed from the repository and every other language is pulled before the build.

What you get

Everything the editor does, through the files you already ship.

  • AI drafts, a person verifies

    Every language is drafted against your glossary and each key's length limit. A draft never ships until someone has verified it.

  • Five checks on every save

    Placeholders, length, terminology, consistency and missing translations are flagged on the row they concern, not in production.

  • Pull a subset by tag

    Tag keys by feature or platform and pull only those, so one project can serve several apps without shipping each other's strings.

  • Runs in CI

    Push the source language on merge and pull every language before the release build, on any CI that can run a shell.

    CI pipelines

Set it up

From nothing to every language.

  1. Step 1: Wire next-intl to the messages folder

    The plugin in next.config.ts and a request config that loads messages/<locale>.json. That folder is what anylocale writes to; nothing else in the app changes.

    next.config.ts
    import createNextIntlPlugin from "next-intl/plugin";
    
    const withNextIntl = createNextIntlPlugin();
    
    export default withNextIntl({});
    src/i18n/request.ts
    import { getRequestConfig } from "next-intl/server";
    
    export default getRequestConfig(async () => {
      const locale = "de";
      return {
        locale,
        messages: (await import(`../../messages/${locale}.json`)).default,
      };
    });
  2. Step 2: Use the strings in a component

    Namespaces follow the object path in the file; plurals resolve from the count.

    src/app/page.tsx
    import { useTranslations } from "next-intl";
    
    export default function Home() {
      const t = useTranslations("paywall");
      return <button>{t("subscribe_cta")}</button>;
    }
  3. Step 3: Install the CLI and log in

    Homebrew or the one-line installer, then a token issued per project under Settings, Integrations. The read scope pulls; push writes source files and values; manage creates and deletes keys.

    shell
    brew install anylocale/tap/anylocale
    anylocale login --project my-app
  4. Step 4: Push the source file

    The push is additive: keys missing from the file stay in place, so a truncated file cannot empty a project. Descriptions in the file become translator notes.

    shell
    curl -fsS -X POST "https://anylocale.com/api/loc/push?project=my-app&format=next-intl" \
        -H "Authorization: Bearer $ANYLOCALE_TOKEN" \
        --data-binary @messages/en.json
  5. Step 5: Pull every language before the build

    A script over the project's locales, run by npm before next build through the prebuild hook. Locally it runs on demand; in CI the token comes from a secret.

    package.json
    {
      "scripts": {
        "prebuild": "sh scripts/pull-messages.sh",
        "build": "next build"
      }
    }
    scripts/pull-messages.sh
    #!/bin/sh
    set -e
    for locale in de fr ja; do
      anylocale pull --project my-app --locale $locale \
        --format next-intl --out messages/$locale.json
    done

Good to know

  • ICU plural and select syntax is stored as written and returned as written.
  • Commit the source messages file and ignore the pulled ones, or commit them all; the pull overwrites a file only when it arrived complete.
  • Every pull carries the current text of every key, verified or not. Only over-the-air delivery is limited to verified strings.

Questions

When should the pull run?
As the build's first step, so next build picks up every language. Locally, run it whenever a translation was verified and you want to see it.
App Router or Pages Router?
Both. The pull writes the messages files next-intl loads, and which router loads them makes no difference to the file.
Can the web app share a project with the mobile apps?
Yes. Tag the keys the web app uses and pull with --tag web, so the messages file carries only those.

Start with the file your app already ships.

After checkout, import one strings file and read the first drafts within minutes.

Nothing to connect and nothing to install. The CLI is optional.