4.9 KiB
| id | title | priority | status | scope | updated_at | owner | evidence | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| p2-04 | Localization audit — no hardcoded strings | p2 | done | game1 | 2026-04-17 | shipwright |
|
Summary
ThemeVocabulary is architected for localization. This objective audits every
player-facing GDScript file (.gd) AND Godot scene file (.tscn) under
src/game/engine/scenes/ for hardcoded user-visible strings, routes each
through ThemeVocabulary.lookup(), and wires a validator into ./run verify.
The .gd scan is clean: 57 scenes scanned, 0 hits. The validator was extended
to also scan .tscn inspector text = "..." defaults (skipping node name =
identifiers, which are structural, not user-visible). That extension surfaced
234 remaining hits across 29 scene files — the first-pass .gd audit
missed these because Godot scene files store inspector defaults as raw
strings even when the controller overrides them at runtime.
Status: done. All three acceptance bullets pass. The .tscn grind
closed the remaining 234 hits across 29 files by adding 144 new vocab keys
to public/games/age-of-dwarves/vocabulary.json, adding %-unique
accessors where nodes lacked them, and routing every static label/button
text through ThemeVocabulary.lookup() at _ready() time. Hardcoded
text = "..." inspector defaults were stripped. Final validator run:
OK: 102 scenes scanned, 0 hardcoded UI strings.
Acceptance
grep -rE '"[A-Z][a-z ]{4,}"' src/game/engine/scenes/turns up zero user-visible hardcoded strings outsidevocabulary.jsonlookups. ✓ (Validator now covers both.gdand.tscn; cited run:python3 tools/validate-i18n.py→OK: 102 scenes scanned, 0 hardcoded UI strings.)tools/validate-i18n.py(new) fails if a.gdUI file contains a literal user-visible string. ✓ (.gdscan +.tscnscan viascan_tscn()both exit 0; combined102 scenes scanned.)./run verifyruns the validator as step 1. ✓
Completion pattern (applied)
For each of the 29 .tscn files:
- Opened the scene's
.gdcontroller and checked_ready()for existing<node>.text = ThemeVocabulary.lookup(...)overrides. - For each hit that was already overridden at runtime → deleted the
inspector
text = "..."default from the.tscn(dead cruft). - For each hit not yet overridden → added a vocab key to
public/games/age-of-dwarves/vocabulary.json, addedunique_name_in_owner = truewhere the node lacked a%-accessor, added<node>.text = ThemeVocabulary.lookup("key")in_ready(), and deleted the inspector default from the.tscn. - Re-ran
python3 tools/validate-i18n.pyafter each file; progression: 234 → 184 → 151 → 125 → 92 → 49 → 0.
Files closed (29)
scenes/menus/options.tscn— 50 hits → 0scenes/city/city_screen.tscn— 33 → 0scenes/hud/overlay_panel.tscn— 14 → 0scenes/combat/combat_preview.tscn— 14 → 0scenes/menus/game_setup.tscn— 11 → 0scenes/menus/victory_screen.tscn— 8 → 0scenes/menus/how_to_play.tscn— 8 → 0scenes/menus/about.tscn— 8 → 0scenes/overviews/demographics.tscn— 7 → 0scenes/menus/settings.tscn— 7 → 0scenes/hud/diplomacy_panel.tscn— 7 → 0scenes/menus/defeat_screen.tscn— 6 → 0scenes/combat/promotion_picker.tscn— 6 → 0scenes/combat/combat_result.tscn— 6 → 0scenes/overviews/end_game_stats.tscn— 5 → 0scenes/menus/load_game.tscn— 5 → 0scenes/treasury/treasury_tab.tscn— 4 → 0scenes/magic/spellbook.tscn— 4 → 0scenes/hud/crafting_complete_modal.tscn— 4 → 0scenes/encyclopedia/encyclopedia_panel.tscn— 4 → 0scenes/menus/throne_room_spoils.tscn— 3 → 0scenes/menus/loading_screen.tscn— 3 → 0scenes/magic/mana_panel.tscn— 3 → 0scenes/hud/top_bar.tscn— 3 → 0scenes/hud/climate_indicator.tscn— 3 → 0scenes/overviews/victory_screen.tscn— 2 → 0scenes/menus/throne_room.tscn— 2 → 0scenes/menus/credits.tscn— 2 → 0scenes/hud/debug_menu.tscn— 2 → 0
Actual: 144 new vocab keys added.