From b6e1f423e143c8a57cdbe955c753665ce8a1c0ed Mon Sep 17 00:00:00 2001 From: AverageConsumer <35539970+AverageConsumer@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:21:30 +0200 Subject: [PATCH] Scope companion translations to Kanto Gear --- mod/kanto_gear/main.lua | 6 ++++- mod/kanto_gear/tests/compat_test.lua | 12 ++++----- translations/README.md | 4 ++- translations/kanto_gear_de/main.lua | 2 +- .../kanto_gear_de/tests/integration_test.lua | 25 +++++++++++-------- translations/kanto_gear_es/main.lua | 2 +- .../kanto_gear_es/tests/integration_test.lua | 25 +++++++++++-------- translations/kanto_gear_fr/lang/fr.lua | 2 +- translations/kanto_gear_fr/main.lua | 2 +- .../kanto_gear_fr/tests/integration_test.lua | 25 +++++++++++-------- 10 files changed, 63 insertions(+), 42 deletions(-) diff --git a/mod/kanto_gear/main.lua b/mod/kanto_gear/main.lua index c0f5cd6..96ec577 100644 --- a/mod/kanto_gear/main.lua +++ b/mod/kanto_gear/main.lua @@ -1,5 +1,6 @@ local WIDTH, HEIGHT = 160, 144 local HEADER = 20 +local STRING_PREFIX = "kanto_gear|" local G local INK, DARK, MID, PAPER @@ -98,7 +99,10 @@ function THEME:moveUnavailableReason(move) end function THEME:translate(source) - return self.strings and self.strings:get(source) or source + if not self.strings then return source end + return self.strings:get(STRING_PREFIX .. source) + or self.strings:get(source) + or source end local function formatSpecifierCount(value) diff --git a/mod/kanto_gear/tests/compat_test.lua b/mod/kanto_gear/tests/compat_test.lua index d36a47a..3eefd9b 100644 --- a/mod/kanto_gear/tests/compat_test.lua +++ b/mod/kanto_gear/tests/compat_test.lua @@ -272,16 +272,16 @@ end theme.strings = { get = function(_, source) return ({ - ["LEVEL UP"] = "LEVEL AUF", - ["Trainer battle"] = "TRAINER-KAMPF", - ["BADGES"] = "ORDEN", - ["PP %d"] = "AP", + ["kanto_gear|LEVEL UP"] = "LEVEL AUF", + ["kanto_gear|Trainer battle"] = "TRAINER-KAMPF", + ["kanto_gear|BADGES"] = "ORDEN", + ["kanto_gear|PP %d"] = "AP", ["TO LOWER"] = "KLEIN", })[source] end, } T.eq(fit("LEVEL UP", 20), "LEVEL AUF", - "Kanto Gear reads the public Recomp strings registry") + "Kanto Gear reads its scoped entries from the Recomp strings registry") T.eq(fit("Trainer battle", 20), "TRAINER-KAMPF", "battle headers use the catalog's canonical source spelling") T.eq(fit("KANTO GEAR", 20), "KANTO GEAR", @@ -291,7 +291,7 @@ T.eq(theme:format("%s %d/%d", theme:translate("BADGES"), 3, 8), T.eq(theme:format("PP %d", 12), "PP 12", "malformed dynamic translations fall back without losing values") T.eq(theme:translate("TO LOWER"), "KLEIN", - "non-tile-font controls use the same translation source") + "a full-game translation remains a compatible fallback") theme.strings = nil for _, stale in ipairs({ 'newDef.type or "STATUS"', diff --git a/translations/README.md b/translations/README.md index 9af269e..c902b5f 100644 --- a/translations/README.md +++ b/translations/README.md @@ -21,4 +21,6 @@ To add a language: catch translations that would overflow Kanto Gear's compact UI. Missing entries safely remain in English. No Kanto Gear source changes are -needed for another language. +needed for another language. The companion `main.lua` namespaces its entries +so they cannot accidentally translate matching text in the base game or +another mod. diff --git a/translations/kanto_gear_de/main.lua b/translations/kanto_gear_de/main.lua index 9ff41e5..4eef5b1 100644 --- a/translations/kanto_gear_de/main.lua +++ b/translations/kanto_gear_de/main.lua @@ -4,7 +4,7 @@ return function(mod) local translations = assert(chunk()) local count = 0 for source, translated in pairs(translations) do - mod.content.strings:override(source, translated) + mod.content.strings:override("kanto_gear|" .. source, translated) count = count + 1 end mod.log:info("Kanto Gear Deutsch: %d Texte geladen", count) diff --git a/translations/kanto_gear_de/tests/integration_test.lua b/translations/kanto_gear_de/tests/integration_test.lua index 667c3ca..73fe99a 100644 --- a/translations/kanto_gear_de/tests/integration_test.lua +++ b/translations/kanto_gear_de/tests/integration_test.lua @@ -6,30 +6,35 @@ local run = T.sdk.loadMods({ "mod/kanto_gear", "translations/kanto_gear_de", }, { root = root, data = T.fixtures.load(), generation = 2 }) +local function kg(source) + return run.data.strings["kanto_gear|" .. source] +end T.eq(#run.errors, 0, "Kanto Gear und deutsche Begleitmod laden gemeinsam unter Gold") -T.eq(run.data.strings["START GAME"], "SPIEL STARTEN", +T.eq(kg("START GAME"), "SPIEL STARTEN", "Begleitmod registriert eigene Kanto-Gear-Texte") -T.eq(run.data.strings["DEALS %d FIXED DAMAGE"], +T.eq(run.data.strings["START GAME"], nil, + "Begleitmod verändert gleich benannten Host-Text nicht") +T.eq(kg("DEALS %d FIXED DAMAGE"), "MACHT %d FESTSCHADEN", "Begleitmod registriert formatierte Attackendetails") -T.eq(run.data.strings["CANCEL"], "ABBRUCH", +T.eq(kg("CANCEL"), "ABBRUCH", "Begleitmod übersetzt Gold-Menüaktionen") -T.eq(run.data.strings["JOHTO MAP"], "JOHTO", +T.eq(kg("JOHTO MAP"), "JOHTO", "Begleitmod übersetzt Gold-Kartenüberschriften") -T.eq(run.data.strings["BATTLE VIEW"], "KAMPFANSICHT", +T.eq(kg("BATTLE VIEW"), "KAMPFANSICHT", "Begleitmod übersetzt Kanto-Gear-Einstellungen") -T.eq(run.data.strings["CLOCK"], "UHR", +T.eq(kg("CLOCK"), "UHR", "Begleitmod übersetzt die Zeitquelle") -T.eq(run.data.strings["ENEMY INFO"], "GEGNER-INFO", +T.eq(kg("ENEMY INFO"), "GEGNER-INFO", "Begleitmod übersetzt die Gegnerinformation") -T.eq(run.data.strings["WEIGHT %.1f KG"], "GEWICHT %.1f KG", +T.eq(kg("WEIGHT %.1f KG"), "GEWICHT %.1f KG", "Begleitmod übersetzt die Pokédex-Details") -T.eq(run.data.strings["DISPLAY LAYOUT"], "ANZEIGELAYOUT", +T.eq(kg("DISPLAY LAYOUT"), "ANZEIGELAYOUT", "Begleitmod übersetzt das Ein-Fenster-Layout") -T.eq(run.data.strings["SCREEN SWAP (Y)"], "SCREEN-TAUSCH (Y)", +T.eq(kg("SCREEN SWAP (Y)"), "SCREEN-TAUSCH (Y)", "Begleitmod übersetzt den optionalen Bildschirmtausch") run.release() diff --git a/translations/kanto_gear_es/main.lua b/translations/kanto_gear_es/main.lua index 10af01f..97b8d49 100644 --- a/translations/kanto_gear_es/main.lua +++ b/translations/kanto_gear_es/main.lua @@ -4,7 +4,7 @@ return function(mod) local translations = assert(chunk()) local count = 0 for source, translated in pairs(translations) do - mod.content.strings:override(source, translated) + mod.content.strings:override("kanto_gear|" .. source, translated) count = count + 1 end mod.log:info("Kanto Gear Español (España): %d textos cargados", count) diff --git a/translations/kanto_gear_es/tests/integration_test.lua b/translations/kanto_gear_es/tests/integration_test.lua index d62ac22..33b907a 100644 --- a/translations/kanto_gear_es/tests/integration_test.lua +++ b/translations/kanto_gear_es/tests/integration_test.lua @@ -6,29 +6,34 @@ local run = T.sdk.loadMods({ "mod/kanto_gear", "translations/kanto_gear_es", }, { root = root, data = T.fixtures.load(), generation = 2 }) +local function kg(source) + return run.data.strings["kanto_gear|" .. source] +end T.eq(#run.errors, 0, "Kanto Gear and the Spanish companion mod load together under Gold") -T.eq(run.data.strings["START GAME"], "INICIAR JUEGO", +T.eq(kg("START GAME"), "INICIAR JUEGO", "companion mod registers Kanto Gear text") -T.eq(run.data.strings["DEALS %d FIXED DAMAGE"], +T.eq(run.data.strings["START GAME"], nil, + "companion mod does not translate matching host text") +T.eq(kg("DEALS %d FIXED DAMAGE"), "CAUSA %d DE DAÑO FIJO", "companion mod registers formatted move details") -T.eq(run.data.strings["CANCEL"], "CANCELAR", +T.eq(kg("CANCEL"), "CANCELAR", "companion mod translates Gold menu actions") -T.eq(run.data.strings["JOHTO MAP"], "JOHTO", +T.eq(kg("JOHTO MAP"), "JOHTO", "companion mod translates Gold map headings") -T.eq(run.data.strings["BATTLE VIEW"], "VISTA DE COMBATE", +T.eq(kg("BATTLE VIEW"), "VISTA DE COMBATE", "companion mod translates Kanto Gear settings") -T.eq(run.data.strings["CLOCK"], "RELOJ", +T.eq(kg("CLOCK"), "RELOJ", "companion mod translates the clock source") -T.eq(run.data.strings["ENEMY INFO"], "INFO. RIVAL", +T.eq(kg("ENEMY INFO"), "INFO. RIVAL", "companion mod translates enemy information") -T.eq(run.data.strings["WEIGHT %.1f KG"], "PESO %.1f KG", +T.eq(kg("WEIGHT %.1f KG"), "PESO %.1f KG", "companion mod translates Pokedex details") -T.eq(run.data.strings["DISPLAY LAYOUT"], "DISEÑO DE PANTALLA", +T.eq(kg("DISPLAY LAYOUT"), "DISEÑO DE PANTALLA", "companion mod translates the single-window layout") -T.eq(run.data.strings["SCREEN SWAP (Y)"], "INTERCAMBIAR PANT. (Y)", +T.eq(kg("SCREEN SWAP (Y)"), "INTERCAMBIAR PANT. (Y)", "companion mod translates optional screen swapping") run.release() diff --git a/translations/kanto_gear_fr/lang/fr.lua b/translations/kanto_gear_fr/lang/fr.lua index 3619205..f9d16c4 100644 --- a/translations/kanto_gear_fr/lang/fr.lua +++ b/translations/kanto_gear_fr/lang/fr.lua @@ -5,7 +5,7 @@ return { ["LOADING AREA"] = "CHARGEMENT ZONE", ["KEEP EXPLORING"] = "CONTINUEZ L'EXPLORATION", ["MAP"] = "CARTE", - ["LOCAL"] = "LOCAL", + ["LOCAL"] = "PLAN", ["GUIDE"] = "GUIDE", ["AREA"] = "ZONE", ["TRAINER"] = "DRESSEUR", diff --git a/translations/kanto_gear_fr/main.lua b/translations/kanto_gear_fr/main.lua index 292086e..c6c919f 100644 --- a/translations/kanto_gear_fr/main.lua +++ b/translations/kanto_gear_fr/main.lua @@ -4,7 +4,7 @@ return function(mod) local translations = assert(chunk()) local count = 0 for source, translated in pairs(translations) do - mod.content.strings:override(source, translated) + mod.content.strings:override("kanto_gear|" .. source, translated) count = count + 1 end mod.log:info("Kanto Gear Français : %d textes chargés", count) diff --git a/translations/kanto_gear_fr/tests/integration_test.lua b/translations/kanto_gear_fr/tests/integration_test.lua index 56732ac..770ff1d 100644 --- a/translations/kanto_gear_fr/tests/integration_test.lua +++ b/translations/kanto_gear_fr/tests/integration_test.lua @@ -6,29 +6,34 @@ local run = T.sdk.loadMods({ "mod/kanto_gear", "translations/kanto_gear_fr", }, { root = root, data = T.fixtures.load(), generation = 2 }) +local function kg(source) + return run.data.strings["kanto_gear|" .. source] +end T.eq(#run.errors, 0, "Kanto Gear and the French companion mod load together under Gold") -T.eq(run.data.strings["START GAME"], "COMMENCER", +T.eq(kg("START GAME"), "COMMENCER", "companion mod registers Kanto Gear text") -T.eq(run.data.strings["DEALS %d FIXED DAMAGE"], +T.eq(run.data.strings["START GAME"], nil, + "companion mod does not translate matching host text") +T.eq(kg("DEALS %d FIXED DAMAGE"), "DÉGÂTS FIXES : %d", "companion mod registers formatted move details") -T.eq(run.data.strings["CANCEL"], "ANNULER", +T.eq(kg("CANCEL"), "ANNULER", "companion mod translates Gold menu actions") -T.eq(run.data.strings["JOHTO MAP"], "JOHTO", +T.eq(kg("JOHTO MAP"), "JOHTO", "companion mod translates Gold map headings") -T.eq(run.data.strings["BATTLE VIEW"], "VUE COMBAT", +T.eq(kg("BATTLE VIEW"), "VUE COMBAT", "companion mod translates Kanto Gear settings") -T.eq(run.data.strings["CLOCK"], "HORLOGE", +T.eq(kg("CLOCK"), "HORLOGE", "companion mod translates the clock source") -T.eq(run.data.strings["ENEMY INFO"], "INFOS ENNEMI", +T.eq(kg("ENEMY INFO"), "INFOS ENNEMI", "companion mod translates enemy information") -T.eq(run.data.strings["WEIGHT %.1f KG"], "POIDS %.1f KG", +T.eq(kg("WEIGHT %.1f KG"), "POIDS %.1f KG", "companion mod translates Pokedex details") -T.eq(run.data.strings["DISPLAY LAYOUT"], "DISPOSITION DES ÉCRANS", +T.eq(kg("DISPLAY LAYOUT"), "DISPOSITION DES ÉCRANS", "companion mod translates the single-window layout") -T.eq(run.data.strings["SCREEN SWAP (Y)"], "ÉCHANGE ÉCRANS (Y)", +T.eq(kg("SCREEN SWAP (Y)"), "ÉCHANGE ÉCRANS (Y)", "companion mod translates optional screen swapping") run.release()