| name | ags-localize |
| description | Full localization pipeline: scan for hardcoded strings, extract and manage string tables, validate translations, generate translator briefings, run cultural/sensitivity review, manage VO localization, test RTL/platform requirements, enforce string freeze, and report coverage. |
| argument-hint | [scan|extract|validate|status|brief|cultural-review|vo-pipeline|rtl-check|freeze|qa] |
| user-invocable | true |
| agent | narrative-director |
| allowed-tools | Read, Glob, Grep, Write, Bash, Task, AskUserQuestion |
Language: Talk to user in language from .ags/project/user-interaction.md. Fall back to English if file missing. Files on disk always English per .ags/rules/user-interaction.md.
Localization Pipeline
Full pipeline for making game feel native in every language and region. Covers
string extraction through cultural review, VO recording, RTL layout testing,
and localization QA sign-off.
Modes:
scan โ Find hardcoded strings and localization anti-patterns (read-only)
extract โ Extract strings and generate translation-ready tables
validate โ Check translations for completeness, placeholders, and length
status โ Coverage matrix across all locales
brief โ Generate translator context briefing document for an external team
cultural-review โ Flag culturally sensitive content, symbols, colours, idioms
vo-pipeline โ Manage voice-over localization: scripts, recording specs, integration
rtl-check โ Validate RTL language layout, mirroring, and font support
freeze โ Enforce string freeze; lock source strings before translation begins
qa โ Run the full localization QA cycle before release
If no subcommand is provided, output usage and stop. Verdict: FAIL โ missing required subcommand.
Phase 0: Prerequisites
| Artifact | Created by | If missing |
|---|
| Engine source code | engine init | STOP. "No engine source โ nothing to scan for strings." |
.ags/rules/technical-preferences.md (locale list) | /ags-setup-engine | WARN: localize uses defaults if locale list missing. |
If STOP triggers, exit verdict BLOCKED.
Phase 1: Combined Review Loop (applies to every write-producing mode)
Per .ags/rules/review-workflow.md. For every mode below that produces a writable artifact (extracted strings bundle, translator brief, cultural review, VO scripts, RTL report, freeze snapshot, QA verdict report), apply this loop before the mode's May I write... prompt. Aggregator: narrative-director (skill-designated lead).
Each iteration N (start N=1):
- Resolve severity floor: Nโค2 โ
low; N=3..4 โ high; Nโฅ5 โ critical.
- Persist current artifact draft to
.ags/project/reviews/.tmp/localize-[mode]-iter[N]-draft.md.
- Spawn in parallel (single message, multiple Task calls + Bash):
narrative-director (and producer for scope / cert questions) via Task to review the drafted artifact against locale list, accessibility tier, cert constraints, writing samples. Pass iteration N + severity floor.
/ags-external-review localize [draft-path] --embedded-parallel --iteration [N] --min-severity [floor]. Codex unavailable โ returns skipped: codex-unavailable; aggregator logs skip in decisions-log and continues with internal pool only.
- Aggregator (
narrative-director) merges findings, drops nitpicks + below-floor.
- Loop exit: filtered set empty โ proceed to
May I write.... Non-empty โ surface kept findings, user revises, N++, repeat.
No iteration cap. No user-confirm gate before external โ runs every iteration automatically. This policy is invoked once per artifact generated โ re-applied per mode invocation, not per string row.
Phase 2A: Scan Mode
Search Assets/Scripts/ for hardcoded user-facing strings:
- String literals in UI code not wrapped in a localization function (
tr(), Tr(), NSLocalizedString, GetText, etc.)
- Concatenated strings that should be parameterized
- Strings with positional placeholders (
%s, %d) instead of named ones ({playerName})
- Format strings that mix locale-sensitive data (numbers, dates, currencies) without locale-aware formatting
Search for localization anti-patterns:
- Date/time formatting not using locale-aware functions
- Number formatting without locale awareness (
1,000 vs 1.000)
- Text embedded in images or textures (flag asset files in
assets/)
- Strings that assume left-to-right text direction (positional layout, string assembly order)
- Gender/plurality assumptions baked into string logic (must use plural forms or gender tokens)
- Hardcoded punctuation (e.g.
"You won!" โ exclamation styles vary by locale)
Report all findings with file paths and line numbers. This mode is read-only โ no files are written.
Phase 2B: Extract Mode
- Scan all source files for localized string references
- Compare against the existing string table in
assets/data/strings/
- Generate new entries for strings not yet keyed
- Suggest key names following the convention:
[category].[subcategory].[description]
- Example:
ui.hud.health_label, dialogue.npc.merchant.greeting, menu.main.play_button
- Each new entry must include a
context field โ a translator comment explaining:
- Where it appears (which screen, which scene)
- Maximum character length
- Any placeholder meaning (
{playerName} = the player's chosen display name)
- Gender/plurality context if applicable
Output a diff of new strings to add to the string table.
Present the diff to the user. Ask: "May I write these new entries to assets/data/strings/strings-en.json?"
If yes, write only the diff (new entries), not a full replacement. Verdict: COMPLETE โ strings extracted and written.
Phase 2C: Validate Mode
Read all string table files in assets/data/strings/. For each locale, check:
- Completeness โ key exists in source (en) but no translation for this locale
- Placeholder mismatches โ source has
{name} but translation omits it or adds extras
- String length violations โ translation exceeds the character limit recorded in the source
context field
- Plural form count โ locale requires N plural forms; translation provides fewer
- Orphaned keys โ translation exists but nothing in
Assets/Scripts/ references the key
- Stale translations โ source string changed after translation was written (flag for re-translation)
- Encoding โ non-ASCII characters present and font atlas supports them (flag if uncertain)
Report validation results grouped by locale and severity. This mode is read-only โ no files are written.
Phase 2D: Status Mode
- Count total localizable strings in the source table
- Per locale: count translated, untranslated, stale (source changed since translation)
- Generate a coverage matrix:
## Localization Status
Generated: [Date]
String freeze: [Active / Not yet called / Lifted]
| Locale | Total | Translated | Missing | Stale | Coverage |
|--------|-------|-----------|---------|-------|----------|
| en (source) | [N] | [N] | 0 | 0 | 100% |
| [locale] | [N] | [N] | [N] | [N] | [X]% |
### Issues
- [N] hardcoded strings found in source code (run /ags-localize scan)
- [N] strings exceeding character limits
- [N] placeholder mismatches
- [N] orphaned keys
- [N] strings added after freeze was called (freeze violations)
This mode is read-only โ no files are written.
Phase 2E: Brief Mode
Generate a translator context briefing document. This document is sent to the
external translation team or localisation vendor alongside the string table export.
Read:
design/gdd/ โ extract game genre, tone, setting, character names
assets/data/strings/strings-en.json โ the source string table
- Any existing lore or narrative documents in
design/narrative/
Generate .ags/project/localization/translator-brief-[locale]-[date].md:
# Translator Brief โ [Game Name] โ [Locale]
## Game Overview
[2-3 paragraph summary of the game, genre, tone, and audience]
## Tone and Voice
- **Overall tone**: [e.g., "Darkly comic, not slapstick โ think Terry Pratchett, not Looney Tunes"]
- **Player address**: [e.g., "Second person, informal. Never formal 'vous' โ always 'tu' for French"]
- **Profanity policy**: [e.g., "Mild โ PG-13 equivalent. Match intensity to source, do not soften or escalate"]
- **Humour**: [e.g., "Wordplay exists โ if a pun cannot translate, invent an equivalent local joke; do not translate literally"]
## Character Glossary
| Name | Role | Personality | Notes |
|------|------|-------------|-------|
| [Name] | [Role] | [Personality] | [Do not translate / transliterate as X] |
## World Glossary
| Term | Meaning | Notes |
|------|---------|-------|
| [Term] | [What it means] | [Keep in English / translate as X] |
## Do Not Translate List
The following must appear verbatim in all locales:
- [Game name]
- [UI terms that match in-engine labels]
- [Brand or trademark names]
## Placeholder Reference
| Placeholder | What it represents | Example |
|-------------|-------------------|---------|
| `{playerName}` | Player's chosen display name | "Shadowblade" |
| `{count}` | Integer quantity | "3" |
## Character Limits
Tight UI fields with hard limits are marked in the string table `context` field.
Where no limit is stated, target ยฑ30% of the English length as a guideline.
## Contact
Direct questions to: [placeholder for user/team contact]
Delivery format: JSON, same schema as strings-en.json
Ask: "May I write this translator brief to .ags/project/localization/translator-brief-[locale]-[date].md?"
Phase 2F: Cultural Review Mode
Spawn narrative-director via Task. Ask them to audit the following for cultural sensitivity across the target locales (read from assets/data/strings/ and assets/):
Content Areas to Review
Symbols and gestures
- Thumbs up, OK hand, peace sign โ meanings vary by region
- Religious or spiritual symbols in art, UI, or audio
- National flags, map representations, disputed territories
Colours
- White (mourning in some Asian cultures), green (political associations in some regions), red (luck vs danger)
- Alert/warning colours that conflict with cultural associations
Numbers
- 4 (death in Japanese/Chinese), 13, 666 โ flag use in UI (room numbers, item counts, prices)
Humour and idioms
- Idioms that translate as offensive in other locales
- Toilet/bodily humour that is inappropriate in some markets (notably Japan, Germany, Middle East)
- Dark humour around topics that are culturally sensitive in specific regions
Violence and content ratings
- Content that would require ratings changes in DE (Germany), AU (Australia), CN (China), or AE (UAE)
- Blood colour, gore level, drug references โ flag all for region-specific asset variants if needed
Names and representations
- Character names that are offensive, profane, or carry negative meaning in target locales
- Stereotyped representation of nationalities, religions, or ethnic groups
Present findings as a table:
| Finding | Locale(s) Affected | Severity | Recommended Action |
|---|
| [Description] | [Locale] | [BLOCKING / ADVISORY / NOTE] | [Change / Flag for review / Accept] |
BLOCKING = must fix before shipping that locale. ADVISORY = recommend change. NOTE = informational only.
Ask: "May I write this cultural review report to .ags/project/localization/cultural-review-[date].md?"
Phase 2G: VO Pipeline Mode
Manage the voice-over localization process. Determine the sub-task from the argument:
vo-pipeline scan โ identify all dialogue lines that require VO recording
vo-pipeline script โ generate recording scripts with director notes
vo-pipeline validate โ check that all recorded VO files are present and correctly named
vo-pipeline integrate โ verify VO files are correctly referenced in code/assets
VO Pipeline: Scan
Read assets/data/strings/ and design/narrative/. Identify:
- All dialogue lines (keys matching
dialogue.*) with source text
- Lines already recorded (audio file exists in
assets/audio/vo/)
- Lines not yet recorded
Output a recording manifest:
## VO Recording Manifest โ [Date]
| Key | Character | Source Line | Status |
|-----|-----------|-------------|--------|
| dialogue.npc.merchant.greeting | Merchant | "Welcome, traveller." | Recorded |
| dialogue.npc.merchant.haggle | Merchant | "That's my final offer." | Needs recording |
VO Pipeline: Script
Generate a recording script document for each character, grouped by scene. Include:
- Character name and brief personality note
- Full dialogue line with pronunciation guide for unusual proper nouns
- Emotion/direction note for each line (
[Warm, welcoming], [Annoyed, clipped])
- Any lines that are responses in a conversation (provide context: "Player just said X")
Ask: "May I write the VO recording scripts to .ags/project/localization/vo-scripts-[locale]-[date].md?"
VO Pipeline: Validate
Glob assets/audio/vo/[locale]/ for all .wav/.ogg files. Cross-reference against the VO manifest. Report:
- Missing files (line in script, no audio file)
- Extra files (audio file exists, no matching string key)
- Naming convention violations
VO Pipeline: Integrate
Grep Assets/Scripts/ for VO audio references. Verify each referenced path exists in assets/audio/vo/[locale]/. Report broken references.
Phase 2H: RTL Check Mode
Right-to-left languages (Arabic, Hebrew, Persian, Urdu) require layout mirroring beyond
just translating text. This mode validates the implementation.
Read .ags/rules/technical-preferences.md to determine the engine. Then check:
Layout mirroring
- Is RTL layout enabled in Unity? (TextMeshPro RTL Adjuster, UI Toolkit
direction: rtl USS, or the Unity Localization package's direction settings)
- Are all UI containers set to auto-mirror, or are positions hardcoded?
- Do progress bars, health bars, and directional indicators mirror correctly?
Text rendering
- Are fonts loaded that support Arabic/Hebrew character sets?
- Is Arabic text rendered with correct ligatures (connected script)?
- Are numbers displayed as Eastern Arabic numerals where required?
String assembly
- Are there any string concatenations that assume left-to-right reading order?
- Do
{placeholder} positions in sentences work correctly when sentence structure is reversed?
Asset review
- Are there UI icons with directional arrows or asymmetric designs that need mirrored variants?
- Do any text-in-image assets exist that require RTL versions?
Grep patterns to check:
- Engine-specific RTL flags in scene/prefab files
- Any
HBoxContainer, LinearLayout, HorizontalBox nodes โ verify layout_direction settings
- String concatenation with
+ near dialogue or UI code
Report findings. Flag BLOCKING issues (content unreadable without fix) vs ADVISORY (cosmetic improvements).
Ask: "May I write this RTL check report to .ags/project/localization/rtl-check-[date].md?"
Phase 2I: Freeze Mode
String freeze locks the source (English) string table so that translations can proceed
without the source changing under the translators.
freeze call
Check current freeze status in .ags/project/localization/freeze-status.md (if it exists).
If already frozen:
"String freeze is currently ACTIVE (called [date]). [N] strings have been added or modified since freeze. These are freeze violations โ they require re-translation or an approved freeze lift."
If not frozen, present the pre-freeze checklist:
Pre-Freeze Checklist
[ ] All planned UI screens are implemented
[ ] All dialogue lines are final (no further narrative revisions planned)
[ ] All system strings (error messages, tutorial text) are complete
[ ] /ags-localize scan shows zero hardcoded strings
[ ] /ags-localize validate shows no placeholder mismatches in source (en)
[ ] Marketing strings (store description, achievements) are final
Use AskUserQuestion:
- Prompt: "Are all items above confirmed? Calling string freeze locks the source table."
- Options:
[A] Yes โ call string freeze now / [B] No โ I still have strings to add
If [A]: Write .ags/project/localization/freeze-status.md:
# String Freeze Status
**Status**: ACTIVE
**Called**: [date]
**Called by**: [user]
**Total strings at freeze**: [N]
## Post-Freeze Changes
[Any strings added or modified after freeze are listed here automatically by /ags-localize extract]
freeze lift
If argument includes lift: update freeze-status.md Status to LIFTED, record the reason and date. Warn: "Lifting the freeze requires re-translation of all modified strings. Notify the translation team."
freeze check (auto-integrated into extract)
When extract mode finds new or modified strings and freeze-status.md shows Status: ACTIVE โ append the new keys to ## Post-Freeze Changes and warn:
"โ ๏ธ String freeze is active. [N] new/modified strings have been added. These are freeze violations. Notify your localization vendor before proceeding."
Phase 2J: QA Mode
Localization QA is a dedicated pass that runs after translations are delivered but
before any locale ships. This is not the same as /validate (which checks completeness)
โ this is a structured playthrough-based quality check.
Spawn narrative-director via Task with:
- The target locale(s) to QA
- The list of all screens/flows in the game (from
design/gdd/ or /ags-content-audit output)
- The current
/ags-localize validate report
- The cultural review report (if it exists)
Ask the narrative-director to produce a QA plan covering:
- Functional string check โ every string displays in-game without truncation, placeholder errors, or encoding corruption
- UI overflow check โ translated strings that exceed UI bounds (even if within character limits, some languages expand)
- Contextual accuracy โ a sample of 10% of strings reviewed in-game for translation accuracy and natural phrasing
- Cultural review items โ verify all BLOCKING items from the cultural review are resolved
- VO sync check โ if VO exists, verify lip sync or subtitle timing is acceptable after translation
- Platform cert requirements โ check platform-specific localization requirements (age ratings text, legal notices, ESRB/PEGI/CERO text)
Output a QA verdict per locale:
## Localization QA Verdict โ [Locale]
**Status**: PASS / PASS WITH CONDITIONS / FAIL
**Reviewed by**: narrative-director
**Date**: [date]
### Findings
| ID | Area | Description | Severity | Status |
|----|------|-------------|----------|--------|
| LOC-001 | UI Overflow | "Settings" button text overflows on [Screen] | BLOCKING | Open |
| LOC-002 | Translation | [Key] translation is literal โ sounds unnatural | ADVISORY | Open |
### Conditions (if PASS WITH CONDITIONS)
- [Condition 1 โ must resolve before ship]
### Sign-Off
[ ] All BLOCKING findings resolved
[ ] Producer approves shipping [Locale]
Ask: "May I write this localization QA report to .ags/project/localization/loc-qa-[locale]-[date].md?"
Gate integration: The Polish โ Release gate requires a PASS or PASS WITH CONDITIONS verdict for every locale being shipped. A FAIL blocks release for that locale only โ other locales may still proceed if their QA passes.
Phase 3: Rules and Next Steps
Rules
- English (en) is always the source locale
- Every string table entry must include a
context field with translator notes, character limits, and placeholder meaning
- Never modify translation files directly โ generate diffs for review
- Character limits must be defined per-UI-element and enforced in validate mode
- String freeze must be called before sending strings to translators โ never translate a moving target
- RTL support must be designed in from the start โ retrofitting RTL layout is expensive
- Cultural review is required for any locale where the game will be sold commercially
- VO scripts must include director notes โ raw dialogue lines produce flat recordings
Recommended Workflow
/ags-localize scan โ find hardcoded strings
/ags-localize extract โ build string table
/ags-localize freeze โ lock source before sending to translators
/ags-localize brief โ generate translator briefing document
[Send to translators]
/ags-localize validate โ check returned translations
/ags-localize cultural-review โ flag culturally sensitive content
/ags-localize rtl-check โ if shipping Arabic / Hebrew / Persian
/ags-localize vo-pipeline โ if shipping dubbed VO
/ags-localize qa โ full localization QA pass
After qa returns PASS for all shipping locales, include the QA report path when running /ags-gate-check release.