From 64154c8bd83ccd42540204da16c2078f7c1763af Mon Sep 17 00:00:00 2001 From: Natalie Date: Fri, 19 Jun 2026 19:13:46 -0500 Subject: [PATCH] =?UTF-8?q?fix(@projects/@magic-civilization):=20?= =?UTF-8?q?=F0=9F=90=9B=20add=20literal=20fallbacks=20to=20fmt=20lookups?= =?UTF-8?q?=20=E2=80=94=20fixes=20i18n=20format-crash=20regression?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit My earlier i18n batch (07a10054f) converted literal format strings like `"%s (%s) — Tier %d" % [...]` to `ThemeVocabulary.lookup("fmt_...") % [...]` without a fallback. lookup() on a miss returns the title-cased key (no `%` placeholders), so `% [args]` throws "not all arguments converted" whenever the vocabulary isn't loaded — which is the case in GUT unit tests. This crashed test_great_person_modal (16) and test_throne_room_great_works (6). Pass the literal format as the fallback arg (matching the existing lookup(key, fallback) idiom) so these are robust when vocab is absent. Wrapped the 4 lines that exceeded the 100-char gdlint limit. Verified: GUT string-formatting errors 41 → 0; both test scripts now green (suite 51 → 40 failing; the rest are pre-existing/other-session). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../engine/scenes/city/great_person_modal.gd | 22 ++++++++++++++----- .../scenes/city/throne_room_great_works.gd | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/game/engine/scenes/city/great_person_modal.gd b/src/game/engine/scenes/city/great_person_modal.gd index fa754ef4..38b4f320 100644 --- a/src/game/engine/scenes/city/great_person_modal.gd +++ b/src/game/engine/scenes/city/great_person_modal.gd @@ -109,7 +109,10 @@ func rebuild() -> void: add_child(v) var title: Label = Label.new() - title.text = ThemeVocabulary.lookup("fmt_great_person_title") % [_gp_name, _gp_class, _gp_tier] + title.text = ( + ThemeVocabulary.lookup("fmt_great_person_title", "%s (%s) — Tier %d") + % [_gp_name, _gp_class, _gp_tier] + ) title.add_theme_font_size_override("font_size", 16) v.add_child(title) @@ -117,7 +120,10 @@ func rebuild() -> void: if _gp_action != null and _gp_action.has_method("action_type"): at = String(_gp_action.action_type()) var act_label: Label = Label.new() - act_label.text = ThemeVocabulary.lookup("fmt_great_person_action") % (at if at != "" else "(none)") + act_label.text = ( + ThemeVocabulary.lookup("fmt_great_person_action", "Action: %s") + % (at if at != "" else "(none)") + ) v.add_child(act_label) var status: Label = Label.new() @@ -126,12 +132,18 @@ func rebuild() -> void: elif bool(_validation.get("ok", false)): status.text = ThemeVocabulary.lookup("great_person_ok") if _validation.has("gold"): - status.text = ThemeVocabulary.lookup("fmt_great_person_ok_gold") % int(_validation["gold"]) + status.text = ( + ThemeVocabulary.lookup("fmt_great_person_ok_gold", "OK — +%d gold") + % int(_validation["gold"]) + ) if _validation.has("production"): - status.text = ThemeVocabulary.lookup("fmt_great_person_ok_production") % int(_validation["production"]) + status.text = ( + ThemeVocabulary.lookup("fmt_great_person_ok_production", "OK — +%d production") + % int(_validation["production"]) + ) else: var err: String = String(_validation.get("error", "invalid")) - status.text = ThemeVocabulary.lookup("fmt_great_person_cannot") % err + status.text = ThemeVocabulary.lookup("fmt_great_person_cannot", "Cannot apply: %s") % err v.add_child(status) _last_snapshot = { diff --git a/src/game/engine/scenes/city/throne_room_great_works.gd b/src/game/engine/scenes/city/throne_room_great_works.gd index d5ded915..256adceb 100644 --- a/src/game/engine/scenes/city/throne_room_great_works.gd +++ b/src/game/engine/scenes/city/throne_room_great_works.gd @@ -124,7 +124,7 @@ func _make_layer_section(layer: String, rows: Array) -> Control: for r: Dictionary in rows: var line: Label = Label.new() - line.text = ThemeVocabulary.lookup("fmt_great_works_entry") % [ + line.text = ThemeVocabulary.lookup("fmt_great_works_entry", " • %s — %s (era %d)") % [ String(r["name"]), String(r["building"]), int(r["era"]),