Check seven things before you ship an app that Codex, Claude Code or Cursor translated in one prompt: whether long strings fit, whether plural forms match each language, whether variables survived, whether terms stay consistent, whether the tone reads right to a native speaker, whether every key exists in every locale, and whether the next feature will get translated at all. globalize.now is AI-powered localization infrastructure, and most of what we see go wrong after a one-shot translation is mechanical, which is good news: mechanical problems can be checked.
The first pass is rarely the problem. Modern agents produce readable translations quickly. What a single prompt does not include is any step that verifies the output, and these checks are that step.
Does text fit after translation?
Often not, and buttons fail first. The W3C's guidance on text size in translation notes that the shorter the source message, the greater the likely expansion, so a two-word button label grows proportionally more than a paragraph. It also points out that compound nouns in languages like German may not wrap, and that some scripts need more horizontal or vertical room than Latin text.
An agent translating strings in a JSON file never sees the screen, so it cannot know that "Save changes" now fills the button edge to edge. Run the app in the longest locale you ship, walk the main flows, and look for clipped text, wrapped buttons and truncated table headers. If you support right-to-left languages, do the same pass in one of them; the Arabic and RTL guide for Lovable apps covers direction, which overflow checks alone will not.
The durable fix is layout, not shorter translations: let containers grow, avoid fixed widths on text, and stop abbreviating to fit. Ask your agent to do that part, because it is code.
Do plural forms match the target language?
Check this early, because it fails silently. Unicode CLDR defines six plural categories: zero, one, two, few, many and other. English uses only one and other. Russian uses one, few, many and other. Welsh uses all six, and i18next's documentation shows Arabic with all six plural keys too.
An agent that copies the English pair into a Russian or Arabic file produces a catalog that parses and renders, and shows the wrong form for every number that needs a category the file lacks. It will not error. With i18next, remember that the variable must be named count exactly, and the documentation states there is no fallback to the plain key if it is missing. The same agent writing count === 1 ? 'item' : 'items' in a component has the same bug before translation even starts; what ICU MessageFormat is and why it trips AI-generated apps covers the syntax side.
The check is mechanical: for each locale, compare the plural keys against the categories that language requires.
Did the interpolation variables survive?
Not always, and a script settles it. Interpolation variables such as {{name}} or {count} must appear in every translation exactly as written. Agents translating a long file sometimes reword a variable, drop one when the sentence reads better without it, or translate the contents of a tag. The result renders as a blank, a literal brace, or a crash.
Compare the set of variables in each translated string against its source string. This short Node script does that and also reports keys that exist in English but not in another locale:
import fs from "node:fs";
const [src, ...targets] = process.argv.slice(2);
const read = (f) => JSON.parse(fs.readFileSync(f, "utf8"));
const vars = (s) =>
[...String(s).matchAll(/\{\{?\s*[\w.]+\s*\}?\}/g)].map((m) => m[0]).sort().join(",");
const base = read(src);
let problems = 0;
for (const file of targets) {
const loc = read(file);
for (const [key, text] of Object.entries(base)) {
if (!(key in loc)) { console.log(file, "missing", key); problems++; continue; }
if (typeof text === "string" && vars(text) !== vars(loc[key])) {
console.log(file, "variable mismatch", key); problems++;
}
}
}
process.exit(problems ? 1 : 0);
Run it as node check-locales.mjs locales/en.json locales/de.json locales/ru.json in CI. It assumes single-level key files; adapt the loop if your catalog is nested.
Is the terminology consistent?
It is consistent inside one response and drifts across several. If the translation of a large app is split across files, sessions or batches, nothing enforces that "workspace", "project" and your product name come out the same way each time. You end up with a button that says one thing and a help page that says another.
Write the terms down once: a glossary of product names, feature names and words that must not be translated, and make the translation step read it. globalize.now generates a shared glossary when the codebase is converted, so the terms exist as data before any translation happens. Without a tool, a short glossary file referenced from your agent instructions is the minimum; the AGENTS.md rules post shows where those instructions live.
Does it sound right to a native speaker?
This is the one check a script cannot do. Register, formality and casing are where one-shot translations read as machine-made: the wrong level of formal address, imperative buttons that sound like commands, a headline in capitals in a language where that reads as shouting.
Do not review every string. Pick one language per language family you ship, and have a native speaker read the first-run screens, the checkout or signup flow, and the error messages. Those are the screens where tone costs you users. Record their corrections in the glossary so the next run starts from them.
Does every key exist, and did every string make it into the catalog?
Two different gaps look the same on screen. A key can exist in English and be missing in a locale, which the script above catches. Or a string can have been hardcoded in the component, never reaching the catalog at all, so no translation could cover it. Agents leave the second kind in attributes, toasts and error messages more often than in visible text; why agents keep adding hardcoded strings covers the pattern and the lint rule that catches it.
Switch the app to a non-English locale and click through it. Any English that remains is either a missing key or a string that never entered the system, and the fix differs.
Will the next feature get translated?
Only if translation is part of how code ships, and this is the check a one-prompt run cannot pass. The prompt translated the app as it was that afternoon. The next feature your agent builds arrives in English, in the same files, and the locales fall behind a feature at a time. Why translation files drift out of sync describes how that accumulates.
This is where the one-shot approach and a pipeline separate. Localization moving upstream into the dev loop lays out the position argument; the practical version is that conversion happens once and later changes are translated where they are made. With globalize.now you connect the repository in the app, the codebase is converted once, and push jobs translate new catalog units after that, with the results delivered as changes you review and merge. The runtime library and catalog format stay yours. Teams that already have a human translator keep that review step; it just stops being the only thing between English-only code and a release.
If you would rather keep it in your own scripts, the minimum is the script above running in CI plus a rule that new strings go through the catalog. How to localize an app an AI generated walks the whole path, and the Claude Code guide covers that agent specifically.
Where do you start?
Run the script against your current locale files today; it takes a minute and tells you whether the structure is sound. Then open the app in your longest locale and click through the first-run flow. If you shipped an AI-built app and want the conversion, translation and later updates handled rather than maintained by hand, the vibe coders page is the overview, the developer reference covers agent setups, and pricing sits on its own page.
globalize.now turns hardcoded app copy into translation-ready locale files and keeps them updated as you ship.
Try globalize.now free