Quick answer: A translation memory stores every past source-target pair so you never pay to translate the same string twice. Add a glossary for domain terms, use fuzzy matching to catch near-duplicates across updates, and mark machine-assisted translations explicitly for review. The savings compound every patch.

Localization is one of those expenses that quietly doubles every time you add a language or ship a content update. For an indie game shipping in eight languages, each new 1,000-word patch can cost a few thousand dollars before you include QA. A well-designed translation memory cuts that number by 50–80% over the life of the game — not by cutting quality, but by not paying twice for the same work.

What a TM Actually Stores

At the simplest level, a TM is a table of source strings and their translations. The useful version stores a lot more:

# translation_memory.tmx — trimmed example
<tu tuid="hud.ammo.remaining" datatype="plaintext">
  <prop type="context">hud,ammo,combat</prop>
  <prop type="version">1.3.0</prop>
  <prop type="verified">true</prop>
  <tuv xml:lang="en"><seg>Ammo: {count}</seg></tuv>
  <tuv xml:lang="fr"><seg>Munitions : {count}</seg></tuv>
  <tuv xml:lang="ja"><seg>弧数: {count}</seg></tuv>
</tu>

Three things matter: the stable key (so you can reference the same translation unit across builds), the context props (so translators know this is HUD text and not dialogue), and the verified flag (so unverified machine fills are visible).

Normalize Source Strings

Before you can look a string up, you need to normalize it. Trim leading/trailing whitespace. Replace interpolation placeholders with a canonical token ({count} -> {0} or leave them as named placeholders, but be consistent). Strip trailing punctuation that varies by language — or better, keep it, but know that small punctuation differences can cause fuzzy misses.

For plural handling, use ICU MessageFormat or equivalent so your source string encodes the plural structure and the target language can apply its own rules. A TM that stores English “1 apple / N apples” as two separate entries will not translate cleanly into Russian, which has three plural forms.

Fuzzy Matching

Exact matches are 95% of the value. Fuzzy matches are the next 4%. When you change a source string — “You have 3 lives remaining” becomes “You have {count} lives left” — the TM should surface the old translation with a similarity score so the translator can confirm or edit rather than start from scratch.

Levenshtein distance is the baseline fuzzy metric. More sophisticated matchers use token-based similarity (the Dice coefficient on bi-grams works well) and handle placeholder differences gracefully. Set a threshold: above 85% similarity, auto-apply; 70–85% flag for review; under 70% treat as new.

Glossary

A glossary is a second layer sitting beside the TM. It defines domain terms that must be translated consistently — character names, ability names, faction names, in-game jargon. The glossary is enforced: if a translator uses a different target than what the glossary specifies, the QA tool flags it.

Write the glossary carefully. Decide early whether you translate character names (usually no for fantasy, sometimes yes for narrative games). Decide whether ability names are translated or transliterated. These decisions are small if you make them at the start and large if you defer them until you’re three updates deep.

String Versioning

Every localized string should carry a version number or hash tied to the source. When the English copy changes, bump the version. Every target language entry for that key is now stale. The TM shows the previous translation and the new source, and the translator updates the target.

class StringEntry:
    key: str
    source: str
    source_hash: str
    targets: dict[str, TranslatedString]

class TranslatedString:
    text: str
    source_hash_at_translation: str    # lets us detect stale
    verified: bool
    translator: str

def is_stale(entry, lang):
    t = entry.targets.get(lang)
    return t is None or t.source_hash_at_translation != entry.source_hash

The stale flag drives the translator workflow. An export to the translator includes every stale entry; their return imports and marks the entries fresh again.

Translator Workflow

Translators do not want to work in your game repo. They want a tool that shows source, target, context, glossary hits, and fuzzy suggestions side-by-side. Export to XLIFF or TMX, send to the translation team, re-import the results. Your build script handles the round-trip.

Include screenshots of context where possible. A string like “Click” can mean a dozen different things depending on where it appears. If your localization export includes a screenshot URL for each string, quality goes up and reviewer questions go down.

The single best thing we did for localization quality was auto-attaching a screenshot to every string export. Our French translator caught six context-mismatched translations in the first week that had been wrong in the game for two years.

Machine-Assisted Fills

Modern LLMs and MT services produce decent first-draft translations for common languages. Use them to accelerate the translator, not replace them. When a new string has no fuzzy match, request a machine translation, store it in the TM marked verified=false, and route it to the translator for review. The translator confirms (flipping the verified flag) or edits.

Never ship unverified entries in released builds. A gate in CI that refuses to build if any target language contains unverified strings for more than 48 hours catches this consistently. Yes, it means your pre-release patches wait for the translator; that is exactly the point.

QA in-Game

TM matches don’t catch text that overflows the UI, mistranslates UI-critical labels, or breaks on specific character sets. Run an automated pass that loads every localized string into a test harness, renders it in the actual UI, and captures screenshots for review. A native speaker’s eye on a 200-screenshot contact sheet takes an hour. A native speaker playing through the whole game takes a week.

Related Issues

For content management adjacent to localization, see bug reporting best practices for game teams. For translator workflow context, read bug report template for game QA testers.

Never pay to translate the same sentence twice. Everything else in localization is details on top of that idea.