GetTranslated.AI
AI Translation & Automation

How to Build a Translation Memory and Glossary for AI Localization (So Your LLM Stops Reinventing Every String from Scratch)

How to Build a Translation Memory and Glossary for AI Localization (So Your LLM Stops Reinventing Every String from Scratch)

Every time you run an AI translation pass without a Translation Memory, you're paying the full cost of localization — in time, money, and review burden — for strings that were already translated correctly last release. There's a structural fix for this, and it's been standard practice in professional localization tooling for decades. This post covers how to build and wire in both a Translation Memory and a Glossary so your AI pipeline stops treating every release like a blank slate.


What Is a Translation Memory and Why Should Mobile Developers Care?

A Translation Memory (TM) is a database of source-string → approved-translation pairs. The core workflow is simple: before you send a string to an LLM, you check the TM first. If the stored source string matches your current source string at or above a confidence threshold, you reuse the approved translation and skip the model call entirely.

Matches come in two flavors:

  • Exact match: the source string is character-for-character identical. Use the TM translation verbatim, no LLM involved.
  • Fuzzy match: the source string is similar but not identical — typically measured by edit distance or token-level similarity. A common threshold is 85%. At this level, you might pass the TM match to the LLM as a strong suggestion rather than a definitive answer.

The compounding benefit here is significant. A mature TM — one seeded from several real releases and continuously updated — typically covers 40–70% of strings in any given release. Most releases are incremental: new features add strings, but the bulk of your UI copy doesn't change. Without a TM, you're asking your LLM to re-translate "Save", "Cancel", "Account Settings", and every other stable string from scratch, every time. That's the failure mode described in how continuous localization differs from one-shot AI translation — and TM is the direct structural answer to it.


What Is a Localization Glossary and Why Can't You Just Prompt for It?

A Glossary is a curated map of source terms to their approved target-language equivalents, with metadata: part of speech, formality register, forbidden alternatives, and contextual notes. It's the authoritative record of how your product speaks in each language.

The instinct most teams have is to just include glossary instructions in the system prompt. This works — sometimes, partially, for a while. The problem is that it's not reliable:

  • Temperature and sampling mean the model doesn't always apply instructions uniformly across a batch of strings.
  • Context window position matters. Instructions at the top of a long prompt get less attention by the time the model is processing string 47.
  • Model updates can silently change how instructions are weighted. A prompt that worked fine on one model version may produce drift after an update.

Treating the glossary as prompt text is like posting the style guide on the wall and hoping everyone reads it before every commit. You need a enforcement mechanism, not just a suggestion.

What belongs in a glossary:

  • Product feature names: "Workspace", "Plan", "Dashboard" — terms that may have specific brand meaning
  • UI nouns and verbs: "Account", "Save", "Submit", "Tap" (not "Click" on mobile)
  • Terms that must never be translated: brand names, trademarked terms, product plan names like "Pro" or "Enterprise"
  • Terms with forbidden alternatives: if "Cuenta" is approved for "Account" in Spanish, "Perfil" and "Cuenta de usuario" should be explicitly forbidden so the model doesn't wander

Step 1: Bootstrap Your Glossary from Existing Translations

You probably already have the raw material for a glossary — it's sitting in your last shipped translation files. The process is:

  1. Extract all source strings and their approved translations from your most recent release.
  2. Identify high-frequency nouns and verbs — terms that appear across many strings, especially in onboarding, navigation, and paywall copy.
  3. Review candidates manually and promote them to glossary entries.

A minimal glossary entry as JSON:

{
  "source": "Account",
  "lang": "es",
  "approved": "Cuenta",
  "pos": "noun",
  "forbidden": ["Perfil", "Cuenta de usuario"],
  "notes": "Always use singular. Do not translate brand plan names like 'Pro Account'."
}

Store this as a versioned JSON file (or a database, once you outgrow files). One file per language pair works fine at small scale.

Prioritize glossary entries in this order:

  1. Onboarding and authentication strings — first impressions, high user visibility
  2. Paywall and subscription copy — terminology drift here has direct revenue impact
  3. Navigation and core UI verbs — these appear in dozens of strings; consistency matters

Don't try to build a complete glossary up front. Start with 50–100 terms per language and grow it from there. A small, accurate glossary is worth more than a large, stale one.


Step 2: Bootstrap Your Translation Memory from Approved Release Files

Your existing strings.xml, Localizable.strings, and JSON files are already TM-ready — they've been human-reviewed and shipped. Seed your TM from them immediately.

Android (strings.xml): For plural resources, each <item quantity> is a separate TM segment, not the whole <plurals> block:

<!-- Store each of these as an independent TM entry -->
<plurals name="items_selected">
  <item quantity="one">%d item selected</item>
  <item quantity="other">%d items selected</item>
</plurals>

TM key for the one entry: items_selected::one → "1 elemento seleccionado" (in es). Keying by name::quantity keeps plural variants addressable independently.

iOS (.stringsdict): Don't store entries at the plist level. Extract the format-key strings inside each NSStringLocalizedFormatKey or NSStringFormatValueTypeKey and store those as segments. The surrounding plist structure is format scaffolding, not translatable content. If you've run into LLM corruption of .stringsdict files before, this breakdown of how AI corrupts stringsdict entries explains exactly why the format level matters.

React Native (ICU JSON): ICU message strings with embedded plural rules need to be normalized before matching. Strip the ICU syntax scaffolding, store the message skeleton and variants separately, and reassemble after translation. Fuzzy matching against un-normalized ICU strings produces unreliable results.

// Source string with ICU plural rule
"items_in_cart": "{count, plural, one {# item in cart} other {# items in cart}}"

// Store in TM as separate segments:
// items_in_cart::one → "# item in cart"
// items_in_cart::other → "# items in cart"

Fuzzy match guidance: Trust exact matches completely — pass them through without an LLM call. For fuzzy matches in the 85–95% range, include the TM match as a strong suggestion in the prompt but let the model confirm or adjust. Below 85%, treat it as context only.


Step 3: Wire TM and Glossary into Your AI Translation Prompt

The construction pattern for a TM and glossary-aware prompt looks like this:

[System prompt: translation instructions, output format, target locale]

[TM context block]
The following strings have approved translations. Pass them through verbatim without modification:
- "Save changes" → "Guardar cambios"
- "Cancel" → "Cancelar"

[Glossary block]
Use the following approved term translations. Do not use alternatives:
- "Account" → "Cuenta" (not "Perfil" or "Cuenta de usuario")
- "Workspace" → "Espacio de trabajo"
- "Tap" → "Toca" (not "Haz clic")

[Strings to translate]
...

A few rules for this to work reliably:

On exact TM matches: Don't include them in the "strings to translate" section at all — inject them directly into the output after the LLM call. If you ask the model to "pass through" strings and also include them in the translation batch, it will often make small changes anyway. The safest approach is to exclude exact matches from the LLM call entirely and merge them back into the result set in code.

On glossary injection: Only include glossary terms that actually appear in the current batch. Dumping the entire glossary into every prompt wastes tokens and makes the instructions harder to parse. A simple string-match pass over your source strings before prompt construction is enough to filter to relevant terms.

On prompt length: If your batch is large enough that the glossary block is pushing source strings toward the end of the context window, split the batch. Context position matters; instructions buried under 3,000 tokens of source strings get less reliable adherence.


Step 4: Update TM and Glossary After Human Review

The TM and Glossary are only as good as the review feedback that goes into them. The feedback loop is:

  1. AI produces a translation.
  2. A human reviewer corrects it.
  3. The correction is written back to the TM as the new approved entry.
  4. If the correction involves a term, the glossary is updated or the forbidden list is extended.

This is where the compound-interest analogy holds: each review cycle makes future cycles cheaper, because the TM coverage grows and the LLM gets better source material to work from.

Versioning TM entries: Tag each entry with the app version in which it was introduced. This gives you an audit trail and lets you identify when a translation was changed and by whom.

{
  "source": "Save changes",
  "lang": "de",
  "approved": "Änderungen speichern",
  "added_version": "4.2.0",
  "last_reviewed": "2025-01-15",
  "reviewed_by": "human"
}

Staleness detection: When a source string changes, compare it to the TM entry's source. If the edit distance exceeds a threshold (a common choice is ~20% of string length), mark the TM entry for re-review rather than auto-applying it. A string that changed from "Save changes" to "Save and continue" is close enough that the TM entry is probably still useful as a suggestion, but not close enough to trust without review.


Step 5: Enforce Glossary at the Validation Gate

The glossary check belongs in your CI pipeline, not just in your prompt. This is Gate 4 from the pre-release validation checklist — a post-translation scan that compares output files against the glossary and fails the build if a forbidden term appears or an approved term is missing where expected.

A basic Python implementation:

import json
import re

def load_glossary(path):
    with open(path) as f:
        return json.load(f)

def check_string(source, translation, lang, glossary):
    errors = []
    for entry in glossary:
        if entry["lang"] != lang:
            continue
        term = entry["source"]
        if term.lower() not in source.lower():
            continue
        approved = entry["approved"]
        forbidden = entry.get("forbidden", [])
        if approved.lower() not in translation.lower():
            errors.append(f"Missing approved term '{approved}' for source term '{term}'")
        for f_term in forbidden:
            if f_term.lower() in translation.lower():
                errors.append(f"Forbidden term '{f_term}' found in translation of '{term}'")
    return errors

# Usage
glossary = load_glossary("glossary/es.json")
errors = check_string("Your Account settings", "Tu Perfil de configuración", "es", glossary)
# → ["Missing approved term 'Cuenta' for source term 'Account'",
#    "Forbidden term 'Perfil' found in translation of 'Account'"]

The same logic applies in Node if your pipeline runs on JS. Tokenize, look up, assert. This isn't a complete solution to AI translation quality — for that, see the full list of pre-release checks — but it's a fast, deterministic check that catches the most common glossary drift before it ships.


Build vs. Buy: When a Spreadsheet Glossary Breaks Down

A shared Google Sheet works fine when you have one target language and a few hundred strings. It starts breaking down around 5 languages and 5,000 strings, and it's well and truly broken by the time you hit 10 languages.

The signs you've outgrown a DIY setup:

  • Reviewers are overwriting each other's TM entries with no audit trail
  • TM mismatches are shipping because the lookup logic lives in someone's local script
  • The glossary has conflicting entries for the same term in the same language
  • You have no way to isolate TM per locale — a German reviewer's corrections are colliding with the French TM

What managed platforms provide that a JSON file doesn't:

  • Fuzzy matching engine: edit-distance matching at scale, with per-locale tuning
  • Per-language TM isolation: changes in one language don't pollute others
  • Review workflow integration: corrections feed back into TM automatically, with attribution
  • Automatic glossary injection: terms are identified and injected per-batch without manual prompt construction

The tradeoffs between DIY and managed localization infrastructure are covered in more depth at /solutions/safe-ai-translation/ and /solutions/ai-translation-problems/. The short version: the crossover point where a managed platform pays for itself comes earlier than most teams expect, usually around the third or fourth target language.


Takeaway

Translation Memory and Glossary are the compound interest of localization. The first release where you maintain them is the most expensive; every release after that is incrementally cheaper, faster, and lower-risk. The TM grows, glossary coverage improves, and the percentage of strings that need LLM involvement keeps shrinking.

To recap the arc of this series: the first posts established what breaks when you treat AI translation as a stateless, one-shot operation. The validation and CI posts covered how to catch those breaks before they reach users. This post closes the loop: TM and Glossary are the upstream investment that reduces how often the gates have anything to catch.

Practical next step: pull your last shipped translation files and run a frequency analysis on your source strings. Identify the top 50 nouns and verbs by occurrence count. Those are your first glossary entries. Seed your TM from the same files. You don't need a platform to start — you need a JSON file and the discipline to update it after every review cycle. Start there, and scale the tooling as the data grows.

Ready to localize your app?

Get started free — no credit card required.

Start Translating →