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)
|
-- it (src/ui/gen2/InitClock.lua, src/script/gen2/Specials.lua SetDayOfWeek)
|
||||||
-- and World only ever reads it.
|
-- and World only ever reads it.
|
||||||
|
|
||||||
|
local Palettes = require("src.world.gen2.Palettes")
|
||||||
local Runtime = require("src.mods.Runtime")
|
local Runtime = require("src.mods.Runtime")
|
||||||
|
local Strings = require("src.core.Strings")
|
||||||
|
|
||||||
local Clock = {}
|
local Clock = {}
|
||||||
|
|
||||||
Clock.MINUTES_PER_DAY = 24 * 60
|
Clock.MINUTES_PER_DAY = 24 * 60
|
||||||
Clock.DAYS = 7
|
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
|
-- InitClock's own default: `ld a, 10 ; default hour = 10 AM`, with the minute
|
||||||
-- buffer left at the zero ByteFill put there.
|
-- buffer left at the zero ByteFill put there.
|
||||||
Clock.DEFAULT_HOUR = 10
|
Clock.DEFAULT_HOUR = 10
|
||||||
|
|||||||
@@ -60,10 +60,11 @@ InitClock.TEXT = TEXT
|
|||||||
-- same three and has always had them right.
|
-- same three and has always had them right.
|
||||||
local MORN_HOUR, DAY_HOUR, NITE_HOUR = 4, 10, 18
|
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.
|
-- Clock.DAY_NAMES / Clock.weekdayName is the single translated home for this
|
||||||
local DAYS = {
|
-- table: MainMenu's clock box and the Pokegear's clock card read the same
|
||||||
"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY",
|
-- weekday off the same save and must never disagree about what it is
|
||||||
}
|
-- called.
|
||||||
|
local DAYS = Clock.DAY_NAMES
|
||||||
InitClock.DAYS = DAYS
|
InitClock.DAYS = DAYS
|
||||||
|
|
||||||
function InitClock:wantsFillScale() return true end
|
function InitClock:wantsFillScale() return true end
|
||||||
@@ -88,12 +89,15 @@ function InitClock.hourString(hour)
|
|||||||
local h = math.floor(hour or 0) % 24
|
local h = math.floor(hour or 0) % 24
|
||||||
local display = h % 12
|
local display = h % 12
|
||||||
if display == 0 then display = 12 end
|
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)
|
return ("%s %d"):format(word, display)
|
||||||
end
|
end
|
||||||
|
|
||||||
function InitClock.oclockString(hour)
|
function InitClock.oclockString(hour)
|
||||||
return InitClock.hourString(hour) .. " o'clock"
|
return Strings("%s o'clock", InitClock.hourString(hour))
|
||||||
end
|
end
|
||||||
|
|
||||||
function InitClock.timeString(hour, minute)
|
function InitClock.timeString(hour, minute)
|
||||||
@@ -187,7 +191,7 @@ function InitClock:question()
|
|||||||
return Strings(TEXT.whoaMinutes, self.minute)
|
return Strings(TEXT.whoaMinutes, self.minute)
|
||||||
end
|
end
|
||||||
if self.phase == "confirm-day" then
|
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
|
end
|
||||||
if self.phase == "response" then
|
if self.phase == "response" then
|
||||||
return Strings(TEXT[InitClock.responseKey(self.hour)],
|
return Strings(TEXT[InitClock.responseKey(self.hour)],
|
||||||
@@ -196,11 +200,15 @@ function InitClock:question()
|
|||||||
return ""
|
return ""
|
||||||
end
|
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.
|
-- The value the picker box shows, or nil while a page is up with no picker.
|
||||||
function InitClock:display()
|
function InitClock:display()
|
||||||
if self.phase == "hour" then return InitClock.oclockString(self.hour) end
|
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 == "minute" then return Strings(MINUTES, self.minute) end
|
||||||
if self.phase == "day" then return DAYS[self.day + 1] or "?" end
|
if self.phase == "day" then return Clock.weekdayName(self.day + 1) or "?" end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -29,10 +29,11 @@ local MainMenu = {}
|
|||||||
MainMenu.__index = MainMenu
|
MainMenu.__index = MainMenu
|
||||||
MainMenu.isOpaque = true
|
MainMenu.isOpaque = true
|
||||||
|
|
||||||
-- MainMenu_PrintCurrentTimeAndDay's PrintDayOfWeek strings.
|
-- MainMenu_PrintCurrentTimeAndDay's PrintDayOfWeek strings. Clock.DAY_NAMES
|
||||||
local DAYS = {
|
-- / Clock.weekdayName is the single translated home for this table (see
|
||||||
"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY",
|
-- 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.
|
-- MUSIC_MAIN_MENU; resolved by name so a cache without it just stays quiet.
|
||||||
local MENU_MUSIC = "Music_MainMenu"
|
local MENU_MUSIC = "Music_MainMenu"
|
||||||
@@ -164,7 +165,7 @@ function MainMenu:drawClockBox()
|
|||||||
-- Textbox at (0,12) with 4 interior rows and 13 interior columns.
|
-- Textbox at (0,12) with 4 interior rows and 13 interior columns.
|
||||||
Chrome.textbox(0, 12, 13, 4)
|
Chrome.textbox(0, 12, 13, 4)
|
||||||
local hour, minute, weekday = self:clockParts()
|
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
|
-- PrintHour prints 1-12 with no leading zero, then ':' then two zero-padded
|
||||||
-- minutes; the AM/PM half is drawn by PrintHour itself.
|
-- minutes; the AM/PM half is drawn by PrintHour itself.
|
||||||
local display = hour % 12
|
local display = hour % 12
|
||||||
|
|||||||
@@ -56,10 +56,6 @@ local CARDS = {
|
|||||||
-- card over. One row, so `#self.cards` stays 1 and nothing pages.
|
-- card over. One row, so `#self.cards` stays 1 and nothing pages.
|
||||||
local FLY_MAP_CARD = { id = "map", label = "FLY" }
|
local FLY_MAP_CARD = { id = "map", label = "FLY" }
|
||||||
|
|
||||||
local DAYS = {
|
|
||||||
"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY",
|
|
||||||
}
|
|
||||||
|
|
||||||
-- ---------------------------------------------------------------- the radio
|
-- ---------------------------------------------------------------- the radio
|
||||||
--
|
--
|
||||||
-- engine/pokegear/radio.asm is not a text table: it is a jumptable of code.
|
-- 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
|
-- Pokegear_UpdateClock: ClearBox(3,5) 5x14, the day at (6,6) and
|
||||||
-- PrintHoursMins at (6,8) -- two digits, ':', two more, then AM/PM at
|
-- PrintHoursMins at (6,8) -- two digits, ':', two more, then AM/PM at
|
||||||
-- column 12.
|
-- column 12.
|
||||||
self:text(DAYS[weekday] or "", 6, 6)
|
self:text(Clock.weekdayName(weekday) or "", 6, 6)
|
||||||
local display = hour % 12
|
local display = hour % 12
|
||||||
if display == 0 then display = 12 end
|
if display == 0 then display = 12 end
|
||||||
self:text(Chrome.number(display, 2), 6, 8)
|
self:text(Chrome.number(display, 2), 6, 8)
|
||||||
@@ -2203,13 +2199,13 @@ function Pokegear:drawPlain()
|
|||||||
if id == "clock" then
|
if id == "clock" then
|
||||||
local hour, minute, weekday = self:clockParts()
|
local hour, minute, weekday = self:clockParts()
|
||||||
Chrome.box(1, 5, 18, 7)
|
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
|
local display = hour % 12
|
||||||
if display == 0 then display = 12 end
|
if display == 0 then display = 12 end
|
||||||
Chrome.print(("%s:%s %s"):format(
|
Chrome.print(("%s:%s %s"):format(
|
||||||
Chrome.number(display, 2), Chrome.number(minute, 2, true),
|
Chrome.number(display, 2), Chrome.number(minute, 2, true),
|
||||||
hour < 12 and "AM" or "PM"), 5, 9)
|
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
|
elseif id == "radio" then
|
||||||
-- Without the gear sheet there is no dial art, so the frequencies go down
|
-- 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:
|
-- 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 Clock = require("src.core.gen2.Clock")
|
||||||
local InitClock = require("src.ui.gen2.InitClock")
|
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.
|
-- A stub input the screen drives off, the same shape Input:wasPressed has.
|
||||||
local function fakeInput()
|
local function fakeInput()
|
||||||
@@ -254,4 +255,66 @@ do
|
|||||||
end
|
end
|
||||||
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()
|
S.finish()
|
||||||
|
|||||||
Reference in New Issue
Block a user