mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-17 19:24:01 +02:00
Merge pull request #1450 from thibautbus/fix/translate-clock-and-day-of-week
This commit is contained in:
@@ -16,13 +16,56 @@
|
||||
-- it (src/ui/gen2/InitClock.lua, src/script/gen2/Specials.lua SetDayOfWeek)
|
||||
-- and World only ever reads it.
|
||||
|
||||
local Palettes = require("src.world.gen2.Palettes")
|
||||
local Runtime = require("src.mods.Runtime")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local Clock = {}
|
||||
|
||||
Clock.MINUTES_PER_DAY = 24 * 60
|
||||
Clock.DAYS = 7
|
||||
|
||||
-- data/text/day_of_week.asm order, which is wCurDay's own: SUNDAY is 0, so
|
||||
-- index 1 is SUNDAY -- matching both InitClock's `self.day + 1` and
|
||||
-- `Clock.weekday(save) + 1`. Strings.source, not Strings: built at require
|
||||
-- time, before Strings.load has a catalog, so Clock.weekdayName looks each
|
||||
-- name up at display time instead (src/battle/MoveEffects.lua's STAT_LABEL
|
||||
-- is the same pattern). One shared table and one lookup function, so
|
||||
-- InitClock's screens, the main menu clock box and the Pokegear clock card
|
||||
-- cannot drift apart on what a weekday is called.
|
||||
Clock.DAY_NAMES = {
|
||||
Strings.source("SUNDAY"), Strings.source("MONDAY"), Strings.source("TUESDAY"),
|
||||
Strings.source("WEDNESDAY"), Strings.source("THURSDAY"), Strings.source("FRIDAY"),
|
||||
Strings.source("SATURDAY"),
|
||||
}
|
||||
|
||||
-- The translated name for a 1-based weekday (SUNDAY = 1), or nil if `day` is
|
||||
-- out of range.
|
||||
function Clock.weekdayName(day)
|
||||
local name = Clock.DAY_NAMES[day]
|
||||
return name and Strings(name)
|
||||
end
|
||||
|
||||
-- The three words Palettes.clockDaytime can hand back, translated (never
|
||||
-- DARK: that one only comes out of Palettes.daytimeFor, for a PALETTE_DARK
|
||||
-- map, and is never printed as text). Strings.source, not Strings:
|
||||
-- clockDaytime's return value is also an internal key every
|
||||
-- FORCED_DAYTIME/palette lookup in Palettes.lua compares against, so THAT
|
||||
-- stays untranslated -- only this table, and Clock.daytimeLabel below, look
|
||||
-- a word up, at the UI call sites that actually print it.
|
||||
local DAYTIME_LABEL = {
|
||||
MORN = Strings.source("MORN"), DAY = Strings.source("DAY"),
|
||||
NITE = Strings.source("NITE"),
|
||||
}
|
||||
|
||||
-- clockDaytime's word, translated -- the one InitClock's clock-setting
|
||||
-- screen and the Pokegear's clock card print (DisplayHourOClock /
|
||||
-- Pokegear_UpdateClock).
|
||||
function Clock.daytimeLabel(hour)
|
||||
local daytime = Palettes.clockDaytime(hour)
|
||||
return Strings(DAYTIME_LABEL[daytime] or daytime)
|
||||
end
|
||||
|
||||
-- InitClock's own default: `ld a, 10 ; default hour = 10 AM`, with the minute
|
||||
-- buffer left at the zero ByteFill put there.
|
||||
Clock.DEFAULT_HOUR = 10
|
||||
|
||||
@@ -60,10 +60,11 @@ InitClock.TEXT = TEXT
|
||||
-- same three and has always had them right.
|
||||
local MORN_HOUR, DAY_HOUR, NITE_HOUR = 4, 10, 18
|
||||
|
||||
-- data/text/day_of_week.asm order, which is wCurDay's own: SUNDAY is 0.
|
||||
local DAYS = {
|
||||
"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY",
|
||||
}
|
||||
-- Clock.DAY_NAMES / Clock.weekdayName is the single translated home for this
|
||||
-- table: MainMenu's clock box and the Pokegear's clock card read the same
|
||||
-- weekday off the same save and must never disagree about what it is
|
||||
-- called.
|
||||
local DAYS = Clock.DAY_NAMES
|
||||
InitClock.DAYS = DAYS
|
||||
|
||||
function InitClock:wantsFillScale() return true end
|
||||
@@ -88,12 +89,15 @@ function InitClock.hourString(hour)
|
||||
local h = math.floor(hour or 0) % 24
|
||||
local display = h % 12
|
||||
if display == 0 then display = 12 end
|
||||
local word = require("src.world.gen2.Palettes").clockDaytime(h)
|
||||
-- Clock.daytimeLabel, not Palettes.clockDaytime: the printed word,
|
||||
-- translated -- this string reaches the player as-is, unlike the internal
|
||||
-- MORN/DAY/NITE key other palette code compares against.
|
||||
local word = Clock.daytimeLabel(h)
|
||||
return ("%s %d"):format(word, display)
|
||||
end
|
||||
|
||||
function InitClock.oclockString(hour)
|
||||
return InitClock.hourString(hour) .. " o'clock"
|
||||
return Strings("%s o'clock", InitClock.hourString(hour))
|
||||
end
|
||||
|
||||
function InitClock.timeString(hour, minute)
|
||||
@@ -187,7 +191,7 @@ function InitClock:question()
|
||||
return Strings(TEXT.whoaMinutes, self.minute)
|
||||
end
|
||||
if self.phase == "confirm-day" then
|
||||
return Strings(TEXT.confirmDay, DAYS[self.day + 1] or "?")
|
||||
return Strings(TEXT.confirmDay, Clock.weekdayName(self.day + 1) or "?")
|
||||
end
|
||||
if self.phase == "response" then
|
||||
return Strings(TEXT[InitClock.responseKey(self.hour)],
|
||||
@@ -196,11 +200,15 @@ function InitClock:question()
|
||||
return ""
|
||||
end
|
||||
|
||||
-- data/text/common_1.asm's "@MIN." suffix (DisplayMinutesWithMinString),
|
||||
-- separate from TEXT.whoaMinutes' own "%d min.?" confirmation line above.
|
||||
local MINUTES = Strings.source("%d min.")
|
||||
|
||||
-- The value the picker box shows, or nil while a page is up with no picker.
|
||||
function InitClock:display()
|
||||
if self.phase == "hour" then return InitClock.oclockString(self.hour) end
|
||||
if self.phase == "minute" then return ("%d min."):format(self.minute) end
|
||||
if self.phase == "day" then return DAYS[self.day + 1] or "?" end
|
||||
if self.phase == "minute" then return Strings(MINUTES, self.minute) end
|
||||
if self.phase == "day" then return Clock.weekdayName(self.day + 1) or "?" end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
@@ -29,10 +29,11 @@ local MainMenu = {}
|
||||
MainMenu.__index = MainMenu
|
||||
MainMenu.isOpaque = true
|
||||
|
||||
-- MainMenu_PrintCurrentTimeAndDay's PrintDayOfWeek strings.
|
||||
local DAYS = {
|
||||
"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY",
|
||||
}
|
||||
-- MainMenu_PrintCurrentTimeAndDay's PrintDayOfWeek strings. Clock.DAY_NAMES
|
||||
-- / Clock.weekdayName is the single translated home for this table (see
|
||||
-- InitClock.lua's DAYS), so this screen's clock box cannot drift from the
|
||||
-- Pokegear's own.
|
||||
local DAYS = Clock.DAY_NAMES
|
||||
|
||||
-- MUSIC_MAIN_MENU; resolved by name so a cache without it just stays quiet.
|
||||
local MENU_MUSIC = "Music_MainMenu"
|
||||
@@ -164,7 +165,7 @@ function MainMenu:drawClockBox()
|
||||
-- Textbox at (0,12) with 4 interior rows and 13 interior columns.
|
||||
Chrome.textbox(0, 12, 13, 4)
|
||||
local hour, minute, weekday = self:clockParts()
|
||||
Chrome.print(DAYS[weekday] or "DAY", 1, 14)
|
||||
Chrome.print(Clock.weekdayName(weekday) or "DAY", 1, 14)
|
||||
-- PrintHour prints 1-12 with no leading zero, then ':' then two zero-padded
|
||||
-- minutes; the AM/PM half is drawn by PrintHour itself.
|
||||
local display = hour % 12
|
||||
|
||||
@@ -56,10 +56,6 @@ local CARDS = {
|
||||
-- card over. One row, so `#self.cards` stays 1 and nothing pages.
|
||||
local FLY_MAP_CARD = { id = "map", label = "FLY" }
|
||||
|
||||
local DAYS = {
|
||||
"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY",
|
||||
}
|
||||
|
||||
-- ---------------------------------------------------------------- the radio
|
||||
--
|
||||
-- engine/pokegear/radio.asm is not a text table: it is a jumptable of code.
|
||||
@@ -1878,7 +1874,7 @@ function Pokegear:drawClock()
|
||||
-- Pokegear_UpdateClock: ClearBox(3,5) 5x14, the day at (6,6) and
|
||||
-- PrintHoursMins at (6,8) -- two digits, ':', two more, then AM/PM at
|
||||
-- column 12.
|
||||
self:text(DAYS[weekday] or "", 6, 6)
|
||||
self:text(Clock.weekdayName(weekday) or "", 6, 6)
|
||||
local display = hour % 12
|
||||
if display == 0 then display = 12 end
|
||||
self:text(Chrome.number(display, 2), 6, 8)
|
||||
@@ -2203,13 +2199,13 @@ function Pokegear:drawPlain()
|
||||
if id == "clock" then
|
||||
local hour, minute, weekday = self:clockParts()
|
||||
Chrome.box(1, 5, 18, 7)
|
||||
Chrome.print(DAYS[weekday] or "DAY", 3, 7)
|
||||
Chrome.print(Clock.weekdayName(weekday) or "DAY", 3, 7)
|
||||
local display = hour % 12
|
||||
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)
|
||||
Chrome.print(Palettes.clockDaytime(hour), 5, 11)
|
||||
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
|
||||
-- the screen as a list. A frequency whose test failed still gets a row:
|
||||
|
||||
@@ -18,6 +18,7 @@ require("src.core.Logger").warn = function() end
|
||||
|
||||
local Clock = require("src.core.gen2.Clock")
|
||||
local InitClock = require("src.ui.gen2.InitClock")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
-- A stub input the screen drives off, the same shape Input:wasPressed has.
|
||||
local function fakeInput()
|
||||
@@ -254,4 +255,66 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
-- Clock.DAY_NAMES / Clock.weekdayName / Clock.daytimeLabel: the single home
|
||||
-- InitClock, MainMenu and the Pokegear clock card all share, so a weekday
|
||||
-- cannot be named one way on one screen and another way on the next.
|
||||
do
|
||||
eq(Clock.weekdayName(1), "SUNDAY", "1-based, SUNDAY first")
|
||||
eq(Clock.weekdayName(6), "FRIDAY", "and the rest in wCurDay's order")
|
||||
check(Clock.weekdayName(0) == nil, "day 0 is out of range")
|
||||
check(Clock.weekdayName(8) == nil, "and so is day 8")
|
||||
|
||||
eq(Clock.daytimeLabel(4), "MORN", "daytimeLabel matches clockDaytime's word")
|
||||
eq(Clock.daytimeLabel(10), "DAY", "for every hour band")
|
||||
eq(Clock.daytimeLabel(20), "NITE", "including the wrap back to NITE")
|
||||
|
||||
local MainMenu = require("src.ui.gen2.MainMenu")
|
||||
check(MainMenu.DAYS == Clock.DAY_NAMES,
|
||||
"MainMenu reuses the same table InitClock and the Pokegear do")
|
||||
end
|
||||
|
||||
-- ------------------------------------------------- a translation mod's turn
|
||||
--
|
||||
-- DAYS, the clockDaytime word and the "o'clock"/"min." suffixes used to
|
||||
-- bypass Strings entirely, so a translation mod's `strings` registry had no
|
||||
-- seam to catch them: the picker kept printing the English day name and
|
||||
-- "o'clock" no matter the catalog (reported from a real Gold build).
|
||||
do
|
||||
Strings.load({
|
||||
strings = {
|
||||
SUNDAY = "DIMANCHE",
|
||||
MORN = "MATIN",
|
||||
["%s o'clock"] = "%s heures",
|
||||
["%d min."] = "%d min",
|
||||
},
|
||||
})
|
||||
|
||||
local wheel = InitClock.new({ input = fakeInput() }, { mode = "day", save = {} })
|
||||
eq(wheel:display(), "DIMANCHE", "a translated catalog reaches the day wheel")
|
||||
|
||||
eq(InitClock.hourString(4), "MATIN 4",
|
||||
"and the clockDaytime word, through Clock.daytimeLabel")
|
||||
eq(InitClock.oclockString(4), "MATIN 4 heures",
|
||||
"and the o'clock suffix, template and all")
|
||||
|
||||
local minutePicker = InitClock.new({ input = fakeInput() }, { save = {} })
|
||||
minutePicker.phase = "minute"
|
||||
minutePicker.minute = 30
|
||||
eq(minutePicker:display(), "30 min", "and the minutes picker's own suffix")
|
||||
|
||||
-- Palettes.clockDaytime itself must stay untranslated even with a catalog
|
||||
-- loaded: FORCED_DAYTIME and the rest of Palettes.lua's own lookups
|
||||
-- compare against its return value as an internal key, not display text.
|
||||
local Palettes = require("src.world.gen2.Palettes")
|
||||
eq(Palettes.clockDaytime(4), "MORN",
|
||||
"the internal palette key is untouched by the loaded catalog")
|
||||
|
||||
-- Module state is process-global and tests/run_tests.lua runs every suite
|
||||
-- in one process (see tests/mod_strings_tests.lua's own note): leaving the
|
||||
-- catalog loaded would translate the day/hour of every suite after this
|
||||
-- one.
|
||||
Strings.load({})
|
||||
check(not Strings.active(), "the catalog is unloaded for the suites after this one")
|
||||
end
|
||||
|
||||
S.finish()
|
||||
|
||||
Reference in New Issue
Block a user