Files
Claude-Code-Game-Studios/CCGS Skill Testing Framework/skills/utility/localize.md
T
DonchitosandClaude Opus 5.5 b21fa0f7f2 Release 1.1.2 — the default path works end to end
Fix release for 1.1.1: the minimal path end to end, engine commands that
run on Godot, Unity and Unreal, hook warnings you can see, and verdicts
that say when they could not check. Details in CHANGELOG.md; upgrade
steps in UPGRADING.md (v1.1.1 → v1.1.2).

Fixes #67
Fixes #131

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WuJn2FdynEybfL5KC697nJ
2026-09-29 21:32:19 +10:00

10 KiB

Skill Test Spec: /localize

Skill Summary

/localize runs the localization pipeline through one required subcommand: scan, extract, validate, status, brief, cultural-review, vo-pipeline, rtl-check, freeze or qa. It works on a single source string table under assets/data/strings/ (strings-en.json is the English source; the other locales sit beside it) and writes reports under production/localization/.

scan, validate and status are read-only. extract shows a diff of new keyed entries and asks "May I write these new entries to assets/data/strings/strings-en.json?" before appending only the diff; its verdict is COMPLETE. With no subcommand the skill prints usage and stops with verdict FAIL — missing required subcommand. A scan whose code root cannot be resolved reports NOT ASSESSED — code root unresolved; a status run with no string table reports NOT ASSESSED — no string table found. cultural-review and qa spawn localization-lead; qa issues a per-locale PASS / PASS WITH CONDITIONS / NOT ASSESSED / FAIL verdict, first match FAIL → NOT ASSESSED → PASS WITH CONDITIONS → PASS. Its checks are playthrough-based, so a locale nobody has played is NOT ASSESSED, and the release gate does not count it as passed. No director gates apply.


Static Assertions (Structural)

Checked against the SKILL.md by /skill-test spec — no fixture needed.

  • Has required frontmatter fields: name, description, argument-hint, user-invocable, allowed-tools
  • Has ≥2 phase headings
  • Contains verdict keywords: COMPLETE, FAIL, NOT ASSESSED, PASS WITH CONDITIONS
  • Contains "May I write" collaborative protocol language before writing the string table or a report
  • Has a next-step handoff (the Recommended Workflow chain ending in /gate-check release)
  • The QA gate note is tiered: at workflow: full the Polish → Release gate requires PASS or PASS WITH CONDITIONS for every translated locale being shipped (recommended at standard, dropped at minimal)
  • The freeze question names the file it writes — "This writes production/localization/freeze-status.md" — before the user answers

Director Gate Checks

None. /localize is a pipeline utility and spawns no director. The only agent it spawns is localization-lead (an operations-tier agent), and only in the cultural-review and qa modes.


Test Cases

Case 1: Extract — New Strings Keyed and Appended After Approval

Fixture:

  • project.yaml has engine.name: Godot, so the code root is src/
  • src/ui/hud.gd wraps three strings in tr() that have no entry in assets/data/strings/strings-en.json
  • No production/localization/freeze-status.md exists

Input: /localize extract

Expected behavior:

  1. Skill scans source files for localized string references and compares them against the table in assets/data/strings/
  2. Skill proposes one new entry per unkeyed string, with a key in the form [category].[subcategory].[description] (e.g. ui.hud.health_label)
  3. Each new entry carries a context field: where it appears, maximum length, placeholder meaning
  4. Skill presents the diff and asks "May I write these new entries to assets/data/strings/strings-en.json?"
  5. On approval it writes only the new entries (not a full replacement); verdict is COMPLETE

Assertions:

  • Proposed keys follow [category].[subcategory].[description]
  • Every new entry includes a context field
  • The diff is shown and "May I write" names assets/data/strings/strings-en.json before any write
  • Only the three new entries are written — existing entries are not rewritten
  • Verdict is COMPLETE

Case 2: No Subcommand — Usage and FAIL

Fixture:

  • Any project state

Input: /localize

Expected behavior:

  1. Skill finds no subcommand in the argument
  2. Skill outputs usage (the ten modes) and stops
  3. Verdict is FAIL — missing required subcommand

Assertions:

  • Usage listing the available modes is printed
  • Verdict is FAIL with the reason "missing required subcommand"
  • No scan, extract or validation work is performed
  • No file is written and no "May I write" ask appears

Case 3: Validate — Gaps Reported by Locale, Nothing Written

Fixture:

  • assets/data/strings/ holds strings-en.json, strings-fr.json and strings-de.json
  • strings-de.json lacks 4 keys present in the English source
  • One French entry omits the {playerName} placeholder its English source has

Input: /localize validate

Expected behavior:

  1. Skill reads every string table file in assets/data/strings/
  2. For de it reports the 4 keys as Completeness gaps
  3. For fr it reports a Placeholder mismatch on the affected key
  4. Results are grouped by locale and severity
  5. Skill writes nothing — validate is read-only

Assertions:

  • The 4 missing keys are named and attributed to the de locale
  • The placeholder mismatch is reported against the fr locale and its key
  • Output is grouped by locale and severity
  • No file is written or modified, and no "May I write" ask appears

Case 4: Status With No String Table — NOT ASSESSED

Fixture:

  • assets/data/strings/ does not exist

Input: /localize status

Expected behavior:

  1. Skill looks for the source string table and finds none
  2. The whole status output is NOT ASSESSED — no string table found
  3. Skill does not produce a coverage matrix of zeros, and does not pre-fill the source row as 100%

Assertions:

  • Output is NOT ASSESSED — no string table found
  • No coverage matrix with zero counts is produced
  • The source locale is not reported as 100% coverage
  • No file is written (status is read-only)

Case 5: Director Gate Check — None; Cultural Review Uses localization-lead

Fixture:

  • assets/data/strings/strings-en.json exists with player-facing strings
  • Any review mode

Input: /localize cultural-review

Expected behavior:

  1. Skill spawns localization-lead to audit strings and assets for cultural sensitivity
  2. Findings are presented as a table with a severity of BLOCKING, ADVISORY or NOTE per finding
  3. Skill asks "May I write this cultural review report to production/localization/cultural-review-[date].md?"
  4. No director agent is spawned and no gate ID appears in output

Assertions:

  • localization-lead is the only agent spawned
  • No director gate (creative, technical, producer, art) is invoked and no gate skip message appears
  • Each finding carries BLOCKING, ADVISORY or NOTE severity
  • "May I write" names production/localization/cultural-review-[date].md before the report is written

Case 6: Scan With an Unresolved Code Root — NOT ASSESSED, never "no hardcoded strings"

Fixture:

  • project.yaml has no engine.name; .claude/docs/technical-preferences.md reads [TO BE CONFIGURED]
  • Both src/ and Assets/ exist and hold UI code with hardcoded strings (ambiguous tree)

Input: /localize scan

Expected behavior:

  1. Skill tries to resolve the code root and cannot (no engine, two candidate roots)
  2. It reports NOT ASSESSED — code root unresolved for the hardcoded-string search and says which checks did not run
  3. It does not guess src/, and does not report zero hits or "no hardcoded strings found" — that would read as "nothing to localize"
  4. Nothing is written — scan is read-only

Assertions:

  • Output reads NOT ASSESSED — code root unresolved for the code search
  • No "no hardcoded strings" or zero-hit result is reported
  • The code root is not assumed to be src/
  • No file is written and no "May I write" ask appears

Case 7: QA on a Locale Nobody Has Played — NOT ASSESSED

Fixture:

  • assets/data/strings/strings-en.json and strings-fr.json exist and validate cleanly
  • No one has played the French build: there are no in-game observations for the functional, overflow, contextual-accuracy or VO checks

Input: /localize qa

Expected behavior:

  1. Skill spawns localization-lead for the QA plan
  2. The playthrough-based checks have no results, and no BLOCKING finding is open, so the French verdict is NOT ASSESSED, naming each check that did not run
  3. The verdict is not PASS or PASS WITH CONDITIONS on the strength of the string tables alone
  4. Skill asks "May I write this localization QA report to production/localization/loc-qa-fr-[date].md?"; the report says the locale has not passed QA for the release gate

Assertions:

  • The French Status is NOT ASSESSED, with the unrun checks named
  • No PASS or PASS WITH CONDITIONS is issued for an unplayed locale
  • "May I write" names the loc-qa report path before it is written
  • The report does not present the locale as cleared for the Polish → Release gate

Protocol Compliance

  • Stops with usage and verdict FAIL when no subcommand is given
  • scan, validate and status write no files
  • Asks "May I write" with the target path before writing the string table (extract) or any report (brief, cultural-review, vo-pipeline script, rtl-check, qa)
  • Extract writes only the diff of new entries, never a full replacement of the table
  • Reports NOT ASSESSED instead of zero results when the code root or the string table is missing
  • qa issues PASS, PASS WITH CONDITIONS, NOT ASSESSED or FAIL per locale, first match FAIL → NOT ASSESSED → PASS WITH CONDITIONS → PASS
  • Ends with the Recommended Workflow chain / /gate-check release handoff

Coverage Notes

  • scan with a resolved code root (findings with file paths and line numbers) is not separately tested; Case 6 covers the unresolved root.
  • extract while freeze-status.md shows Status: ACTIVE (new keys appended to ## Post-Freeze Changes with a freeze-violation warning) is not tested.
  • freeze (pre-freeze checklist and AskUserQuestion [A]/[B]), brief, vo-pipeline and rtl-check are not exercised by a dedicated case; qa is covered only for its NOT ASSESSED branch (Case 7).
  • The qa gate note — a FAIL blocks release for that locale only — needs a live run with multiple locales to verify.