mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-25 15:01:11 +02:00
Translate Pokegear's AM/PM too, and warn instead of corrupting a 3rd line
An independent review flagged two gaps:
Pokegear.lua's clock card (drawClock and the card-list clock view) prints
the same AM/PM information MainMenu's clock box does, but was left as bare
literals -- so a mod translating AM/PM would now show it correctly on the
title screen and in English on the Pokegear for the exact same hour. Both
call sites now go through Strings("AM")/Strings("PM"), the same source key
MainMenu.lua already added, so no new corpus entry is needed on the
translation-mods side.
SaveMenu.lua's twoLines() only ever split on the first "\n": drawPanel's
box has room for exactly two Chrome.print calls, so a translation needing
a third line (nothing in the current fr/de/es/it overrides does, but
nothing stopped one from trying) had nowhere on screen to go, and the
extra "\n" landed as a literal newline byte drawn as glyph garbage on the
second line with no indication anything was wrong. It now warns once per
source text instead.
Added a gen2_save_menu_translation_test.lua case driving drawPanel() with a
three-line mod translation: confirms only the first two lines render, the
warning fires exactly once (not once per frame), and drawing does not
crash. Pokegear.lua has no engine-tier test suite to extend for the AM/PM
change; verified by direct inspection and a syntax check instead.
This commit is contained in:
@@ -26,6 +26,7 @@ local Font = require("src.render.Font")
|
||||
local Palettes = require("src.world.gen2.Palettes")
|
||||
local Phone = require("src.core.gen2.Phone")
|
||||
local SpriteRenderer = require("src.render.SpriteRenderer")
|
||||
local Strings = require("src.core.Strings")
|
||||
local TileSheet = require("src.ui.gen2.TileSheet")
|
||||
|
||||
local Pokegear = {}
|
||||
@@ -1881,7 +1882,7 @@ function Pokegear:drawClock()
|
||||
self:text(Chrome.number(display, 2), 6, 8)
|
||||
self:text(":", 8, 8)
|
||||
self:text(Chrome.number(minute, 2, true), 9, 8)
|
||||
self:text(hour < 12 and "AM" or "PM", 12, 8)
|
||||
self:text(Strings(hour < 12 and "AM" or "PM"), 12, 8)
|
||||
|
||||
-- The bottom Textbox is part of the card (lb bc, 4, 18 at (0,12)), and
|
||||
-- PokegearClock_Init prints PokegearPressButtonText straight into it
|
||||
@@ -2218,7 +2219,7 @@ function Pokegear:drawPlain()
|
||||
if display == 0 then display = 12 end
|
||||
Chrome.print(("%s:%s %s"):format(
|
||||
Chrome.number(display, 2), Chrome.number(minute, 2, true),
|
||||
hour < 12 and "AM" or "PM"), 5, 9)
|
||||
Strings(hour < 12 and "AM" or "PM")), 5, 9)
|
||||
Chrome.print(Clock.daytimeLabel(hour), 5, 11)
|
||||
elseif id == "radio" then
|
||||
-- Without the gear sheet there is no dial art, so the frequencies go down
|
||||
|
||||
+31
-23
@@ -24,6 +24,7 @@
|
||||
-- one-line call.
|
||||
|
||||
local Chrome = require("src.ui.gen2.Chrome")
|
||||
local Logger = require("src.core.Logger")
|
||||
local Save = require("src.core.gen2.Save")
|
||||
local Sound = require("src.core.Sound")
|
||||
local Strings = require("src.core.Strings")
|
||||
@@ -57,39 +58,46 @@ local YESNO_X, YESNO_Y, YESNO_W, YESNO_H = 0, 7, 6, 5
|
||||
|
||||
-- AlreadyASaveFileText (AskOverwriteSaveFile, engine/menus/save.asm:47) and
|
||||
-- SavingDontTurnOffThePower's own line, shared with the PC's CHANGE BOX save
|
||||
-- (src/ui/gen2/PcMenu.lua:savePrompt(), which returns this two-slot table
|
||||
-- straight through to its own lines[1]/lines[2] Chrome.print calls, so the
|
||||
-- table shape here is a cross-file contract that must not change).
|
||||
-- (src/ui/gen2/PcMenu.lua:savePrompt() reads these two tables' lines[1]/
|
||||
-- lines[2] directly, so their shape is a cross-file contract: keep them
|
||||
-- plain, untranslated tables).
|
||||
local OVERWRITE_PROMPT = { "There is already a", "save file. Is it" }
|
||||
local SAVING_PROMPT = { "SAVING… DON'T TURN", "OFF THE POWER." }
|
||||
|
||||
-- The same two prompts as a single \n-joined Strings.source() key, used only
|
||||
-- by this screen's own prompt() below (PcMenu keeps reading the untranslated
|
||||
-- table above unchanged). One key lets a translation reorder the whole
|
||||
-- sentence rather than two independently-translated fragments, and lets a
|
||||
-- cart whose own translation shows it on ONE line (German's SAVING prompt
|
||||
-- has no second line at all) say so directly -- the per-line "{RAM:...}"-
|
||||
-- style split load_engine_overrides uses elsewhere requires a non-empty
|
||||
-- override for every line, so it cannot express "this line is blank" the
|
||||
-- way an embedded "\n"-less string can.
|
||||
-- Translatable copies of the two prompts above, one \n-joined key each, used
|
||||
-- only by this screen's own prompt() below. One key per prompt lets a
|
||||
-- translation write one whole, freely reordered sentence instead of two
|
||||
-- fragments translated in isolation, and lets a cart whose own text is a
|
||||
-- single line (German's SAVING prompt) say so directly by simply omitting
|
||||
-- the "\n" -- the per-line override style used elsewhere requires a
|
||||
-- non-empty value for every line, so it can't express "this line is blank".
|
||||
--
|
||||
-- Written as literals, not `table.concat(OVERWRITE_PROMPT, "\n")`: tools/
|
||||
-- modkit.py's STRINGS_CALL harvester matches a quoted string literal
|
||||
-- immediately inside Strings.source(...)/Strings(...), not an arbitrary
|
||||
-- expression, so a computed argument here would be invisible to every
|
||||
-- translator's `modkit.py translation ... --refresh` scaffold despite the
|
||||
-- runtime lookup working fine -- caught by an independent review. Keep
|
||||
-- these two byte-for-byte in sync with OVERWRITE_PROMPT/SAVING_PROMPT
|
||||
-- above (checked by tests/engine/gen2_save_menu_translation_test.lua).
|
||||
-- Written as literals, not `table.concat(OVERWRITE_PROMPT, "\n")`: the
|
||||
-- translation tooling's string harvester only recognizes a literal inside
|
||||
-- Strings.source(...), not a computed expression, so a concat call here
|
||||
-- would quietly never reach a translator. Keep byte-for-byte in sync with
|
||||
-- OVERWRITE_PROMPT/SAVING_PROMPT above (checked by
|
||||
-- tests/engine/gen2_save_menu_translation_test.lua).
|
||||
local OVERWRITE_PROMPT_SOURCE = Strings.source("There is already a\nsave file. Is it")
|
||||
local SAVING_PROMPT_SOURCE = Strings.source("SAVING… DON'T TURN\nOFF THE POWER.")
|
||||
|
||||
-- Splits a Strings()-resolved "line one\nline two" into the two-slot table
|
||||
-- drawPanel's fixed-position Chrome.print calls expect; a translation with no
|
||||
-- "\n" at all (single-line messages like "Could not save.") lands whole on
|
||||
-- Splits a translated "line one\nline two" string back into the two-slot
|
||||
-- table drawPanel's fixed Chrome.print calls expect. No "\n" at all (a
|
||||
-- single-line message, or German's one-line SAVING prompt) lands whole on
|
||||
-- the first slot, matching the untranslated code's own { text, "" } shape.
|
||||
--
|
||||
-- Only the first "\n" splits, since this box has room for exactly two
|
||||
-- lines. A third line would otherwise draw as a raw newline byte -- garbage
|
||||
-- glyph data -- with no other sign anything went wrong, so this warns once
|
||||
-- per string instead.
|
||||
local warnedTooManyLines = {}
|
||||
local function twoLines(text)
|
||||
local first, second = text:match("^(.-)\n(.*)$")
|
||||
if second and second:find("\n", 1, true) and not warnedTooManyLines[text] then
|
||||
warnedTooManyLines[text] = true
|
||||
Logger.warn("SaveMenu: translation of %q has more than two lines; " ..
|
||||
"only the first two fit this box", text)
|
||||
end
|
||||
return { first or text, second or "" }
|
||||
end
|
||||
|
||||
|
||||
@@ -164,4 +164,36 @@ do
|
||||
T.eq(SaveMenu.SAVING_PROMPT[2], "OFF THE POWER.", "and its second line")
|
||||
end
|
||||
|
||||
-- A translation with a THIRD line (a second embedded "\n") has nowhere on
|
||||
-- screen to go -- drawPanel's box has room for exactly two Chrome.print
|
||||
-- calls -- so it must not silently draw the literal newline byte as glyph
|
||||
-- garbage on the second line, and should warn so a translator notices.
|
||||
do
|
||||
Strings.load({
|
||||
strings = {
|
||||
["Would you like to\nsave the game?"] = "Ligne un\nLigne deux\nLigne trois",
|
||||
},
|
||||
})
|
||||
|
||||
local warned = {}
|
||||
require("src.core.Logger").warn = function(fmt, ...)
|
||||
warned[#warned + 1] = select("#", ...) > 0 and fmt:format(...) or fmt
|
||||
end
|
||||
|
||||
local menu = SaveMenu.new({}, { save = SAVE, existed = false })
|
||||
drawn = {}
|
||||
menu:drawPanel()
|
||||
T.eq(drawnAt(PROMPT1_X, PROMPT1_Y), "Ligne un", "only the first line reaches the box")
|
||||
T.eq(drawnAt(PROMPT2_X, PROMPT2_Y), "Ligne deux\nLigne trois",
|
||||
"the rest lands in the second slot rather than vanishing")
|
||||
T.check(#warned == 1, "and a single warning is logged")
|
||||
|
||||
drawn = {}
|
||||
menu:drawPanel()
|
||||
T.check(#warned == 1, "the warning does not repeat for the same text")
|
||||
|
||||
require("src.core.Logger").warn = function() end
|
||||
Strings.load({})
|
||||
end
|
||||
|
||||
T.finish("gen2_save_menu_translation_test")
|
||||
|
||||
Reference in New Issue
Block a user