LLM Translation: Placeholders, Glossaries and Register
Machine translation is solved enough. What breaks in software localisation is interpolation syntax, terminology drift and missing context, not language quality.
The quality of a model's French is not your problem. Your problem is that it translated the word inside a variable placeholder, used three different words for "workspace" across four screens, and rendered a button label as a nine-word sentence that overflows the button.
Localisation is an engineering task with a linguistic component, and the engineering half is where the failures live. Treat it accordingly.
Placeholders are the number one bug
Interpolation syntax is not natural language, and a model translating a string containing it will sometimes translate it, reorder it, change its case or drop it. In an ICU message the plural keywords are literal syntax; translate "other" into the target language and the message fails to compile.
Never validate this by reading. Validate it by parsing. Extract the set of placeholders from the source, extract the set from the translation, and require that they match exactly. For ICU messages, compile the result with the same formatter your application uses, in the target locale.
src = extract_placeholders(source) # {count, name}
out = extract_placeholders(target)
assert src == out, f"placeholder mismatch: {src ^ out}"
icu.parse(target, locale=target_locale) # must compile
Reordering placeholders is legitimate and often required, since word order differs. What must be preserved is the set and the names, not the sequence. A validator that enforces order will reject correct translations, which erodes trust in the validator and it stops being used.
Plural rules are not a translation problem
English has two plural forms. Polish has four. Arabic has six. Japanese has one. A model translating a two-form English message into Polish must invent two forms that never existed in the source, and it has no information about what they should say.
The consequence is that per-string translation of plural messages is structurally unable to be correct. You have to supply the target language's plural categories explicitly and ask for each one, then validate that every required category for that locale is present.
The same applies to gendered forms and to formality distinctions the source language does not encode. English "you" maps to two or more forms in most European languages, and the model will pick one based on nothing. Decide the register once as a project rule, put it in the prompt, and check it, rather than discovering that half your interface addresses users formally and half informally.
Terminology consistency needs a glossary and a check
Translated independently, the same source term will come back differently across strings. "Workspace" becomes espace de travail in one string and espace in another; users notice, and support articles stop matching the interface.
Maintain a glossary of terms that must translate a specific way, including the terms that must not be translated at all — product names, feature names, technical identifiers. Inject the relevant glossary entries into the prompt for each string rather than the whole glossary, both to save tokens and to keep the model's attention on the terms that actually appear.
Then verify. For every glossary term present in the source, check the mandated target term appears in the translation. This is a substring check with morphological tolerance, imperfect in inflected languages, and still catches the majority of drift. Treat the glossary as a versioned artefact with the same discipline as any other prompt input, per versioning prompt inputs so you can trace an output.
Strings without context are untranslatable
"Open" is a verb on a button and an adjective on a status badge. "Post" is a noun or a verb. In English the string is identical; in German the translations are unrelated words. A model given only the string guesses, and it will be wrong roughly as often as the ambiguity occurs.
The fix is upstream of the model. Your string catalogue needs a context field, populated by whoever writes the string, describing where it appears and what part of speech it is. Screenshot references work even better where your tooling supports them.
Supply the key path too. A key like settings.billing.actions.cancel carries real information about role and location that the string alone does not. Feed the surrounding strings in the same screen as well, since neighbouring labels disambiguate more effectively than most descriptions do. If your catalogue has no context field, adding one will improve translation quality more than any model change available to you.
Length and layout constraints
German and Finnish expand relative to English, frequently by a third or more. A label that fits a fixed-width button in English will not fit after translation, and the model has no idea a button exists.
Pass the constraint into the prompt as a hard limit in characters, and validate the output length. When a translation exceeds the limit, ask again for a shorter form rather than truncating, since truncation produces a nonsense word and truncation with an ellipsis produces a label nobody can read.
Some concepts genuinely cannot be expressed within an English-sized button in some languages. Those cases need a design change, not another retry, and surfacing them early as a list of strings that failed the length check is more useful than discovering them in a screenshot review.
Reviewing translations you cannot read
Round-trip translation — translate back to English and compare — is the technique everyone tries first, and it detects only gross errors. It fails in both directions: a bad translation can round-trip cleanly, and a good idiomatic one often round-trips into something that looks wrong.
Structural checks are far more reliable and fully automatable: placeholder sets match, ICU compiles, plural categories complete, glossary terms honoured, length within budget, no untranslated source text left in the output, no target text in the wrong script. That battery catches most shippable-looking failures without any language knowledge.
For meaning, there is no substitute for a native speaker, and the practical question is how to spend that review time well. Prioritise high-visibility strings, anything with legal or safety implications, and anything the structural checks flagged. Using a second model as a reviewer catches some real problems and inherits the same blind spots, with the caveats set out in using a model as a judge and calibrating it first.
Translation memory still matters
The cheapest translation is the one you already have. Before calling a model, look the source string up in your existing translation memory, and reuse an exact match unconditionally.
Near matches are useful as prompt input rather than as output: supplying the closest previously approved translations alongside the new string produces output consistent with what shipped before, which is most of what consistency means in practice. This is example selection under a different name, subject to the same caveats in choosing and rotating few-shot examples.
It also constrains cost. Only genuinely new strings hit the model, and at typical release cadence that is a small fraction of the catalogue. Batching those into a single call per locale, with the glossary in a cached prefix, keeps a full localisation pass to a rounding error, and the mechanics of that prefix reuse are in how prefix caching matches tokens.
Common questions
How do I stop the model translating my variable placeholders?
Do not rely on instructions. Extract the placeholder set from source and output and require they match, then compile ICU messages in the target locale. Allow reordering; enforce the set, not the sequence.
Why are the same terms translated differently across screens?
Because each string was translated independently. Maintain a glossary of mandated terms, inject the relevant entries per string, and verify the mandated term appears in the output.
Can I review translations without speaking the language?
Partly. Structural checks catch most shippable-looking failures: placeholder match, ICU compilation, complete plural categories, glossary terms, length limits. Meaning still needs a native speaker on the strings that matter.