Blog

Oct 9, 2026

Can an AI coding agent add a new language to your React app by itself?

Asking Claude Code or Cursor to 'add Portuguese' usually ends with a half-translated JSON file and keys that don't match. Here's the loop that makes it actually work: extract, translate, pull typed files, check.

Ask an AI coding agent to “add Portuguese to the app” and it’ll happily try. It opens en.json, writes a pt.json next to it, translates a few hundred strings in one go, and tells you it’s done. Then you run the app and find the hardcoded strings it never touched, the {count} that became {contagem}, and three keys that exist in English but not in Portuguese because the context window ran out halfway through the file.

The agent isn’t the problem. It’s doing translation, file bookkeeping and code edits in one pass, with nothing checking its work.

I build i1n, so I’ve watched this fail a lot of times. What works is splitting the job so the agent does the part it’s good at (reading your components and deciding what’s user-facing) and hands the rest to tools that don’t get tired at key number 412.

The loop

There are four steps, and the agent can run all of them through MCP tools:

  1. Find hardcoded strings in the component and replace them with keys.
  2. Push those keys and translate them into every active language.
  3. Pull the translated locale files and the generated types back into the repo.
  4. Check that every locale has every key and every placeholder survived.

With the i1n MCP server installed, step 1 is the agent’s job and steps 2 and 3 are a single tool call:

// what the agent sends to i1n_extract_and_translate
{
  strings: [
    { key: "checkout.title", value: "Review your order", namespace: "checkout" },
    { key: "checkout.items", value: "{count} items in your cart", namespace: "checkout" }
  ]
}

i1n pushes the keys, translates them with your brand voice and terminology rules, waits for the translations, and pulls the files plus i1n.d.ts back into the project. The agent then swaps the hardcoded text for t('checkout.title'), and your editor already knows that key exists.

Adding the language itself

Adding Portuguese is a different tool call, i1n_add_language, with pt_br. It adds the locale, translates every existing key into it, and pulls the new file. No giant prompt with your whole en.json pasted in.

The part I like is that the translation doesn’t depend on what fits in the agent’s context. The agent never sees all 2,000 strings. It sees the result.

The check that catches the rest

Before the agent opens a PR, it runs i1n_check (or you run npx i1n check in CI):

npx i1n check --min-coverage 95

It’s offline, so it’s cheap to run on every commit. It fails when a locale is missing keys or when a translated value has different placeholders than the source, which is exactly the {contagem} bug from the top of this post.

What it doesn’t do

The agent still decides what counts as user-facing text, and it’ll sometimes extract a string that should have stayed hardcoded (a log message, an internal label). Review the diff like any other PR. And if the people who own the copy aren’t engineers, they’ll want to fix wording in the dashboard instead of in a PR. That works too: their edits come back on the next i1n pull.

If you’ve tried letting an agent handle i18n end to end, where did it break for you, the extraction or the translation?

i1n keeps your locale files in sync: AI translation, typed keys, CI checks.

Get started free