# Skill Test Spec: /localize

## Skill Summary

`/localize` manages the full localization pipeline: it extracts all player-facing
strings from source files, manages translation files in `assets/localization/`,
and validates completeness across all locale files. For new languages, it creates
a locale file skeleton with all current strings as keys and empty values. For
existing locale files, it produces a diff showing additions, removals, and
changed keys.

Translation files are written to `assets/localization/[locale-code].csv` (or
engine-appropriate format) after a "May I write" ask. No director gates apply.
Verdicts: LOCALIZATION COMPLETE (all locales are complete) or GAPS FOUND (at
least one locale is missing string keys).

---

## Static Assertions (Structural)

Verified automatically by `/skill-test static` — no fixture needed.

- [ ] Has required frontmatter fields: `name`, `description`, `argument-hint`, `user-invocable`, `allowed-tools`
- [ ] Has ≥2 phase headings
- [ ] Contains verdict keywords: LOCALIZATION COMPLETE, GAPS FOUND
- [ ] Contains "May I write" collaborative protocol language before writing locale files
- [ ] Has a next-step handoff (e.g., send locale skeletons to translators)

---

## Director Gate Checks

None. `/localize` is a pipeline utility. No director gates apply. Localization
lead agent may review separately but is not invoked within this skill.

---

## Test Cases

### Case 1: New Language — String Extraction and Locale Skeleton Created

**Fixture:**
- Source code in `src/` contains player-facing strings (UI text, tutorial messages)
- Existing locale: `assets/localization/en.csv`
- No French locale exists

**Input:** `/localize fr`

**Expected behavior:**
1. Skill extracts all player-facing strings from source files
2. Skill finds the same strings in `en.csv` as a reference
3. Skill generates `fr.csv` skeleton with all string keys and empty values
4. Skill asks "May I write to `assets/localization/fr.csv`?"
5. File written on approval; verdict is GAPS FOUND (file created but empty values)
6. Skill notes: "fr.csv created — send to translator to fill values"

**Assertions:**
- [ ] All string keys from `en.csv` are present in `fr.csv`
- [ ] All values in `fr.csv` are empty (not copied from English)
- [ ] "May I write" is asked before creating the file
- [ ] Verdict is GAPS FOUND (file is created but untranslated)

---

### Case 2: Existing Locale Diff — Additions, Removals, and Changes Listed

**Fixture:**
- `assets/localization/fr.csv` exists with 20 string keys translated
- Source code has changed: 3 new strings added, 1 string removed, 2 strings
  with changed English source text

**Input:** `/localize fr`

**Expected behavior:**
1. Skill extracts current strings from source
2. Skill diffs against existing `fr.csv`
3. Skill produces diff report:
   - 3 new keys (need translation — listed as empty in fr.csv)
   - 1 removed key (marked as obsolete — suggest removal)
   - 2 changed keys (English source changed — French may need update, flagged)
4. Skill asks "May I update `assets/localization/fr.csv`?"
5. File updated with new empty keys added, obsolete keys marked; verdict is GAPS FOUND

**Assertions:**
- [ ] New keys appear as empty in the updated file (not auto-translated)
- [ ] Removed keys are flagged as obsolete (not silently deleted)
- [ ] Changed source strings are flagged for translator review
- [ ] Verdict is GAPS FOUND (new empty keys exist)

---

### Case 3: String Missing in One Locale — GAPS FOUND With Missing Key List

**Fixture:**
- 3 locale files exist: `en.csv`, `fr.csv`, `de.csv`
- `de.csv` is missing 4 keys that exist in both `en.csv` and `fr.csv`

**Input:** `/localize`

**Expected behavior:**
1. Skill reads all 3 locale files and cross-references keys
2. `de.csv` is missing 4 keys
3. Skill produces GAPS FOUND report listing the 4 missing keys by locale:
   "de.csv missing: [key1], [key2], [key3], [key4]"
4. Skill offers to add the missing keys as empty values to `de.csv`
5. After approval: file updated; verdict remains GAPS FOUND (values still empty)

**Assertions:**
- [ ] Missing keys are listed explicitly (not just a count)
- [ ] Missing keys are attributed to the specific locale file
- [ ] Verdict is GAPS FOUND (not LOCALIZATION COMPLETE)
- [ ] Missing keys are added as empty (not auto-translated from English)

---

### Case 4: Translation File Has Syntax Error — Error With Line Reference

**Fixture:**
- `assets/localization/fr.csv` has a malformed line at line 47
  (missing quote closure)

**Input:** `/localize fr`

**Expected behavior:**
1. Skill reads `fr.csv` and encounters a parse error at line 47
2. Skill outputs: "Parse error in fr.csv at line 47: [error detail]"
3. Skill cannot diff or validate the file until the error is fixed
4. Skill does NOT attempt to overwrite or auto-fix the malformed file
5. Skill suggests fixing the file manually and re-running `/localize`

**Assertions:**
- [ ] Error message includes line number (line 47)
- [ ] Error detail describes the nature of the parse error
- [ ] Skill does NOT overwrite or modify the malformed file
- [ ] Manual fix + re-run is suggested as remediation

---

### Case 5: Director Gate Check — No gate; localization is a pipeline utility

**Fixture:**
- Source code with player-facing strings

**Input:** `/localize fr`

**Expected behavior:**
1. Skill extracts strings and manages locale files
2. No director agents are spawned
3. No gate IDs appear in output

**Assertions:**
- [ ] No director gate is invoked
- [ ] No gate skip messages appear
- [ ] Verdict is LOCALIZATION COMPLETE or GAPS FOUND — no gate verdict

---

## Protocol Compliance

- [ ] Extracts strings from source before operating on locale files
- [ ] Creates new locale files with all keys as empty values (not auto-translated)
- [ ] Diffs existing locale files against current source strings
- [ ] Flags missing keys by locale and by key name
- [ ] Asks "May I write" before creating or updating any locale file
- [ ] Verdict is LOCALIZATION COMPLETE (all locales fully translated) or GAPS FOUND

---

## Coverage Notes

- LOCALIZATION COMPLETE is only achievable when all locale files have all keys
  with non-empty values; new-language skeleton creation always results in GAPS FOUND.
- Engine-specific locale formats (Godot `.translation`, Unity `.po` files) are
  handled by the skill body; `.csv` is used as the canonical format in tests.
- The case where source strings change at a very high rate (continuous integration
  of new UI text) is not tested; the diff logic handles this case.
