DEV Community

Hugo Bernardo Cardoso
Hugo Bernardo Cardoso

Posted on

How to Translate Game Localization Files (.JSON / .PO) Without Breaking Code Variables

Introduction: The Scale vs. Code Integrity Dilemma
Localizing an indie game or a software product is no longer optional. On platforms like Steam, offering the standard 28-language catalogue (including Simplified Chinese, Japanese, Korean, German, and Brazilian Portuguese) routinely unlocks over 50% of a game's total revenue potential.
Yet, indie game developers face a brutal trade-off:
Human Translation Agencies: Charging $\$0.10$ to $\$0.20$ per word. Localizing a modest 20,000-word game into 28 languages can easily cost $\$30,000+$, completely pricing out solo developers and small teams.
Traditional Enterprise SaaS (Lokalise, Crowdin): Charging $\$50$ to $\$200+$ per month just for workspace access, forcing developers into bloated workflows and complex account setups.
Naïve Single-Pass AI (Raw ChatGPT/Claude): Fast and cheap, but destructive to game builds.

This article explores the technical breakdown of why standard LLMs fail when processing code files, and details the engineering architecture required to build a code-safe, zero-friction localization pipeline.
Section 1: Anatomy of a Build Crash - Why Raw LLMs Corrupt Code
Large Language Models (LLMs) are statistical text predictors designed for natural human prose. They lack an internal compiler or Abstract Syntax Tree (AST) context when reading a raw file.
When you paste a .json, .po, .yaml, or .csv file into a standard LLM, five distinct failure modes occur:

  1. Variable & Token Mutation Game engines rely on runtime string interpolation. When an LLM encounters: JSON "hud_gold": "You collected {gold_amount} coins from {monster_type}." It frequently translates the variable names inside the brackets: JSON "hud_gold": "Você coletou {quantidade_ouro} moedas de {tipo_monstro}." // ❌ CRASH: Engine looks for {gold_amount}
  2. Positional & Printf Specifier Mangling C-style formatting specifiers like %s, %d, %f, or :user are often dropped, reordered without positional indexes, or spaced out: JSON "save_slot": "Save file %s loaded." -> "Save file % s loaded." // ❌ PARSE ERROR
  3. ICU Plural Rule Destruction Complex game strings use ICU plural syntax to handle numerical agreement: Plaintext {count, plural, =0 {No items} =1 {One item} other {# items}} Standard LLMs frequently translate the structural control keywords (plural, other), breaking the engine's localization parser entirely.
  4. Rich Text & HTML Tag Pollution Game engines (like Unity's TextMeshPro or Godot's RichTextLabel) use inline markup like or [b]. LLMs often translate color names (), drop closing tags, or convert angle brackets into unescaped HTML entities (<color>).
  5. Unescaped Quotes and Structural Syntax Errors In JSON or YAML files, if a translated French or Spanish string contains an unescaped double quote (e.g., "desc": "L'épée de l' "héros" "), the resulting output becomes invalid JSON, breaking the entire game build at boot. Section 2: Architecture of an Engine-Aware Localization Engine To guarantee zero build breaks, the translation process must be decoupled from the raw file structure. The LLM must never be allowed to touch raw code variables. Here is the technical architecture behind LocaFile AI: Plaintext ┌────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐ │ Source File │ ──> │ Engine Regex Parser │ ──> │ Token Masking │ │ (JSON/PO/CSV) │ │ Auto-Detect Format │ │ {var} ──> [[LOCK_0]] │ └────────────────┘ └───────────────────────┘ └───────────────────────┘ │ ┌────────────────┐ ┌───────────────────────┐ ▼ │ Delivered ZIP │ <── │ Post-Processing QA │ <── ┌───────────────────────┐ │ (28 Languages) │ │ AST Validation & Fix │ │ 3-Pass AI Engine │ └────────────────┘ └───────────────────────┘ │ + Lore & Tone Rules │ └───────────────────────┘ A. Engine Format Auto-Detection & AST Parsing The system supports 9 engine formats out of the box: Godot: .po, Godot .csv (multi-column Unity: Unity .csv, i18n .json Unreal & Mobile: XLIFF, iOS .strings, Android .xml Web Frameworks: .yaml, .tsv, Laravel PHP lang arrays

An AST parser extracts translatable values while maintaining the exact key mapping, structural nested hierarchy, and array index positions.
B. The Immutable Variable Locker
Before any prompt is constructed, a multi-stage Regex scanner identifies all control variables, HTML/rich-text tags, positional specifiers, and ICU blocks:
Detection: Identifies patterns matching {...}, %s, %d, :key, , [tag], and indexed placeholders {0}.
Replacement: Replaces each detected variable with an immutable, deterministic lock token: [[LOCK_0]], [[LOCK_1]], etc.
Why Double Square Brackets? Double square bracket tokens ([[LOCK_N]]) do not naturally occur in legitimate game dialogue or software strings. They prevent LLM tokenization distortion and survive the AI translation pass untouched.

C. Lore Glossaries & Prompt Injection Protection
Game lore uses proper nouns (character names, fictional planets, unique spells) that must remain identical across all languages.
Lore Glossary Engine: Developers can pass up to 2,000 characters of proper nouns (e.g., "CyberCore, Eldoria, X-400").
Security: Glossaries are validated against strict prompt-injection detection patterns before being appended as immutable system constraints.

D. Context & Tone Customization
Language register heavily impacts player immersion. A medieval RPG demands formal or archaic phrasing, while a modern shooter requires punchy, casual dialogue.
Developers can specify target registers:
Standard: Clean, neutral UI phrasing.
Casual: Natural, conversational registers (e.g., informal "tu" in French/Spanish).
Fantasy / Heroic: Immersive register for RPGs and story-driven titles.
Sci-Fi / Cyberpunk: Stylized technical phrasing.

Section 3: The Automated Post-Processing QA & Auto-Fix Pipeline
Even with prompt constraints, an production-grade system cannot rely solely on the LLM's output. A dedicated post-processing engine must validate every single key before packaging.

  1. Linguistic Variable Checker (Regex AST Validator)

    Before delivering the final ZIP bundle, a dedicated post-processing engine compares the source string against the target translation across 5 variable patterns:

    Curly Brackets: {player_name}

    Colon Specifiers: :attribute

    Printf Tokens: %s, %d

    Markup Tags: ,

    Indexed Tokens: {0}, {1}


  2. Defect Detection & Auto-Fix Engine

    The QA validator flags three types of issues:

    Missing Variables: The source string had {count}, but the translation dropped it.

    Corrupted Variables: The AI altered the internal token (e.g., [[LOCK_0]] became [[LOCK_0_ES]]).

    Extra Variables: Unsanitized tokens present in translation but absent in source.


Automated Re-Injection: When a missing variable is detected, the engine calculates its semantic position relative to surrounding words and automatically re-injects the missing {variable} into the translated string before generating a detailed report (quality-report.json).
Section 4: Pay-Per-Pass vs. Monthly Subscriptions
The SaaS industry is saturated with recurring monthly subscriptions that penalize developers during idle development phases. Indie game development is inherently bursty: you might localize heavily during a major launch or playtest, and then go months without needing translation updates.
Why Pay-Per-Pass Wins for Indie Game Devs:
PRICING COMPARISON:
Human Agencies : $0.10 - $0.20/word | High Cost | Manual Variable Handling
Enterprise SaaS : $50 - $200+/month | Subscription| Complex Workspace Setup
LocaFile AI : From $19 (Flat) | Pay-per-Pass| Automated Variable Protection
Indie Starter ($19): 3 runs, up to 5,000 words/file across 6 core languages (EFIGS + CJK).
Steam Launchpad ($99): 10 runs, up to 25,000 words/file across all 28 Steam catalogue languages.
Studio Pass ($249): 35 runs, up to 100,000 words/file for large-scale RPGs and studio pipelines.

Section 5: Hands-On Tutorial - Localizing a Game in 3 Steps
Step 1: Prepare Your Game File
Ensure your string keys are separated from translatable values in a supported format:
JSON
{
"quest_header": "Quest: Defeat {boss_name}",
"item_reward": "You earned {amount} gold coins!",
"dialogue_intro": "Welcome to Eldoria, traveler."
}
Step 2: Test Variable Protection (Zero-Cost Live Preview)
Navigate to locafileai.com and use the zero-cost Variable Protection Preview tool on the homepage.
Paste your raw JSON snippet to observe the production VariableLocker instantly convert {boss_name} and into protected [[LOCK_N]] tokens in real-time before initiating any pass.
JSON
// Real-time Variable Masking Output:
{
"quest_header": "Quest: Defeat [[LOCK_0]]",
"item_reward": "You earned [[LOCK_1]][[LOCK_2]][[LOCK_3]] gold coins!",
"dialogue_intro": "Welcome to Eldoria, traveler."
}
Step 3: Run the Pass & Import to Engine
Drop File or ZIP Batch: Drag your .json, .po, or .csv files directly onto the dropzone.
Set Glossaries & Tone: Add proper nouns to your Lore Glossary and select your game's tone (e.g., Fantasy or Casual).
Execute Pass: Select your target languages (or full 28 Steam catalogue) and watch live real-time WebSocket progress via Laravel Reverb.
Export & Build: Download your validated ZIP bundle and drop it directly into your Godot res:// or Unity Assets/Resources/ directories. Zero syntax errors, zero build breaks.

Conclusion
Game localization should not require thousands of dollars in agency fees or hours spent debugging broken JSON brackets and mangled variable names. By isolating variables through pre-parsing AST Regex lockers, applying post-processing QA validation, and offering a fair pay-per-pass pricing model, developers can expand their games to a global Steam audience with total code safety.
Test the real-time variable protection preview today at locafileai.com!

Top comments (0)