mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-25 23:11:15 +02:00
Merge pull request #1735 from thibautbus/fix/translate-gold-options-menu
Translate Gold's in-game OPTION screen
This commit is contained in:
+67
-49
@@ -22,6 +22,7 @@ local Chrome = require("src.ui.gen2.Chrome")
|
|||||||
local Logger = require("src.core.Logger")
|
local Logger = require("src.core.Logger")
|
||||||
local Runtime = require("src.mods.Runtime")
|
local Runtime = require("src.mods.Runtime")
|
||||||
local Save = require("src.core.gen2.Save")
|
local Save = require("src.core.gen2.Save")
|
||||||
|
local Strings = require("src.core.Strings")
|
||||||
|
|
||||||
local OptionsMenu = {}
|
local OptionsMenu = {}
|
||||||
OptionsMenu.__index = OptionsMenu
|
OptionsMenu.__index = OptionsMenu
|
||||||
@@ -42,43 +43,60 @@ end
|
|||||||
-- Each row: the label, the option key it edits, and the cycle of values with
|
-- Each row: the label, the option key it edits, and the cycle of values with
|
||||||
-- the exact strings the cart prints (trailing spaces included -- they are what
|
-- the exact strings the cart prints (trailing spaces included -- they are what
|
||||||
-- blank the longer previous value, e.g. "MID " over "SLOW").
|
-- blank the longer previous value, e.g. "MID " over "SLOW").
|
||||||
|
-- Labels and cart-original display strings are wrapped in Strings.source so
|
||||||
|
-- the catalog generator harvests them even though this table is built once
|
||||||
|
-- at require time, before any mod's Strings.load has a catalog to answer
|
||||||
|
-- from (src/core/Strings.lua's own note on this). The lookup itself happens
|
||||||
|
-- live, in drawPanel, through plain Strings(...) calls.
|
||||||
local ROWS = {
|
local ROWS = {
|
||||||
{
|
{
|
||||||
label = "TEXT SPEED", key = "textSpeed",
|
label = Strings.source("TEXT SPEED"), key = "textSpeed",
|
||||||
values = { "FAST", "MID", "SLOW" },
|
values = { "FAST", "MID", "SLOW" },
|
||||||
display = { FAST = "FAST", MID = "MID ", SLOW = "SLOW" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label = "BATTLE SCENE", key = "battleScene",
|
|
||||||
values = { true, false },
|
|
||||||
display = { [true] = "ON ", [false] = "OFF" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label = "BATTLE STYLE", key = "battleStyle",
|
|
||||||
values = { "SHIFT", "SET" },
|
|
||||||
display = { SHIFT = "SHIFT", SET = "SET " },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label = "SOUND", key = "sound",
|
|
||||||
values = { "MONO", "STEREO" },
|
|
||||||
display = { MONO = "MONO ", STEREO = "STEREO" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label = "PRINT", key = "print",
|
|
||||||
values = { "LIGHTEST", "LIGHTER", "NORMAL", "DARKER", "DARKEST" },
|
|
||||||
display = {
|
display = {
|
||||||
LIGHTEST = "LIGHTEST", LIGHTER = "LIGHTER ", NORMAL = "NORMAL ",
|
FAST = Strings.source("FAST"), MID = Strings.source("MID "),
|
||||||
DARKER = "DARKER ", DARKEST = "DARKEST ",
|
SLOW = Strings.source("SLOW"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label = "MENU ACCOUNT", key = "menuAccount",
|
label = Strings.source("BATTLE SCENE"), key = "battleScene",
|
||||||
|
values = { true, false },
|
||||||
|
display = {
|
||||||
|
[true] = Strings.source("ON "), [false] = Strings.source("OFF"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label = Strings.source("BATTLE STYLE"), key = "battleStyle",
|
||||||
|
values = { "SHIFT", "SET" },
|
||||||
|
display = {
|
||||||
|
SHIFT = Strings.source("SHIFT"), SET = Strings.source("SET "),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label = Strings.source("SOUND"), key = "sound",
|
||||||
|
values = { "MONO", "STEREO" },
|
||||||
|
display = {
|
||||||
|
MONO = Strings.source("MONO "), STEREO = Strings.source("STEREO"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label = Strings.source("PRINT"), key = "print",
|
||||||
|
values = { "LIGHTEST", "LIGHTER", "NORMAL", "DARKER", "DARKEST" },
|
||||||
|
display = {
|
||||||
|
LIGHTEST = Strings.source("LIGHTEST"), LIGHTER = Strings.source("LIGHTER "),
|
||||||
|
NORMAL = Strings.source("NORMAL "), DARKER = Strings.source("DARKER "),
|
||||||
|
DARKEST = Strings.source("DARKEST "),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label = Strings.source("MENU ACCOUNT"), key = "menuAccount",
|
||||||
values = { false, true },
|
values = { false, true },
|
||||||
display = { [false] = "OFF", [true] = "ON " },
|
display = {
|
||||||
|
[false] = Strings.source("OFF"), [true] = Strings.source("ON "),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
-- FRAME is the textbox border style, 1-8, and prints its number after the
|
-- FRAME is the textbox border style, 1-8, and prints its number after the
|
||||||
-- word TYPE rather than in the shared value column.
|
-- word TYPE rather than in the shared value column.
|
||||||
{ label = "FRAME", key = "frame", frame = true },
|
{ label = Strings.source("FRAME"), key = "frame", frame = true },
|
||||||
-- Everything from here down is the port's, not the cart's. They are the
|
-- Everything from here down is the port's, not the cart's. They are the
|
||||||
-- same settings the Gen 1 OPTION screen carries and they drive the same
|
-- same settings the Gen 1 OPTION screen carries and they drive the same
|
||||||
-- shared modules, so a player who learns them in Red knows them here. The
|
-- shared modules, so a player who learns them in Red knows them here. The
|
||||||
@@ -86,17 +104,17 @@ local ROWS = {
|
|||||||
--
|
--
|
||||||
-- The two volume rows clamp at the ends rather than wrapping, the way
|
-- The two volume rows clamp at the ends rather than wrapping, the way
|
||||||
-- pokered's text-speed cursor does, so holding left reaches OFF and stays.
|
-- pokered's text-speed cursor does, so holding left reaches OFF and stays.
|
||||||
{ id = "controls", label = "CONTROLS", port = true,
|
{ id = "controls", label = Strings.source("CONTROLS"), port = true,
|
||||||
activate = function(game)
|
activate = function(game)
|
||||||
require("src.ui.Screens").push(game, "BindingsMenu")
|
require("src.ui.Screens").push(game, "BindingsMenu")
|
||||||
end },
|
end },
|
||||||
{ label = "MUSIC VOL", key = "musicVol", port = true,
|
{ label = Strings.source("MUSIC VOL"), key = "musicVol", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
options.musicVol = stepVolume(options.musicVol, delta)
|
options.musicVol = stepVolume(options.musicVol, delta)
|
||||||
require("src.core.Music").setVolumeLevel(options.musicVol)
|
require("src.core.Music").setVolumeLevel(options.musicVol)
|
||||||
end,
|
end,
|
||||||
text = function(options) return volLabel(options.musicVol) end },
|
text = function(options) return volLabel(options.musicVol) end },
|
||||||
{ label = "SFX VOL", key = "sfxVol", port = true,
|
{ label = Strings.source("SFX VOL"), key = "sfxVol", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
options.sfxVol = stepVolume(options.sfxVol, delta)
|
options.sfxVol = stepVolume(options.sfxVol, delta)
|
||||||
require("src.core.Sound").setVolumeLevel(options.sfxVol)
|
require("src.core.Sound").setVolumeLevel(options.sfxVol)
|
||||||
@@ -104,7 +122,7 @@ local ROWS = {
|
|||||||
text = function(options) return volLabel(options.sfxVol) end },
|
text = function(options) return volLabel(options.sfxVol) end },
|
||||||
-- Each filter step keeps 40% of the previous step's treble, so 2X and 3X
|
-- Each filter step keeps 40% of the previous step's treble, so 2X and 3X
|
||||||
-- are the 1X low-pass applied twice and three times over.
|
-- are the 1X low-pass applied twice and three times over.
|
||||||
{ label = "MUSIC FILTER", key = "musicFilter", port = true,
|
{ label = Strings.source("MUSIC FILTER"), key = "musicFilter", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
options.musicFilter = ((options.musicFilter or 0) + delta) % #FILTERS
|
options.musicFilter = ((options.musicFilter or 0) + delta) % #FILTERS
|
||||||
require("src.core.Music").setFilterLevel(options.musicFilter)
|
require("src.core.Music").setFilterLevel(options.musicFilter)
|
||||||
@@ -112,7 +130,7 @@ local ROWS = {
|
|||||||
text = function(options)
|
text = function(options)
|
||||||
return FILTERS[(options.musicFilter or 0) + 1]
|
return FILTERS[(options.musicFilter or 0) + 1]
|
||||||
end },
|
end },
|
||||||
{ label = "GAME SPEED", key = "speed", port = true,
|
{ label = Strings.source("GAME SPEED"), key = "speed", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
local GameSpeed = require("src.core.GameSpeed")
|
local GameSpeed = require("src.core.GameSpeed")
|
||||||
options.speed = GameSpeed.cycle(options.speed, delta)
|
options.speed = GameSpeed.cycle(options.speed, delta)
|
||||||
@@ -120,7 +138,7 @@ local ROWS = {
|
|||||||
text = function(options)
|
text = function(options)
|
||||||
return require("src.core.GameSpeed").levelLabel(options.speed)
|
return require("src.core.GameSpeed").levelLabel(options.speed)
|
||||||
end },
|
end },
|
||||||
{ label = "ZOOM", key = "zoom", port = true,
|
{ label = Strings.source("ZOOM"), key = "zoom", port = true,
|
||||||
cycle = function(options, delta, game)
|
cycle = function(options, delta, game)
|
||||||
local Zoom = require("src.render.Zoom")
|
local Zoom = require("src.render.Zoom")
|
||||||
local scale = Zoom.windowFitScale()
|
local scale = Zoom.windowFitScale()
|
||||||
@@ -136,7 +154,7 @@ local ROWS = {
|
|||||||
-- a boundary; WATER / TREES force one outdoor block; BLACK is a flat void.
|
-- a boundary; WATER / TREES force one outdoor block; BLACK is a flat void.
|
||||||
-- #1418. Same key the Gen 1 OPTION screen uses, different ladder (FADE
|
-- #1418. Same key the Gen 1 OPTION screen uses, different ladder (FADE
|
||||||
-- is Gold's default because that is already what the maps call for).
|
-- is Gold's default because that is already what the maps call for).
|
||||||
{ label = "VOID FILL", key = "voidFill", port = true,
|
{ label = Strings.source("VOID FILL"), key = "voidFill", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
local BorderFill = require("src.world.gen2.BorderFill")
|
local BorderFill = require("src.world.gen2.BorderFill")
|
||||||
BorderFill.setVoidFill(options.voidFill or "fade")
|
BorderFill.setVoidFill(options.voidFill or "fade")
|
||||||
@@ -145,7 +163,7 @@ local ROWS = {
|
|||||||
text = function(options)
|
text = function(options)
|
||||||
return require("src.world.gen2.BorderFill").voidFillLabel(options.voidFill)
|
return require("src.world.gen2.BorderFill").voidFillLabel(options.voidFill)
|
||||||
end },
|
end },
|
||||||
{ label = "TILT", key = "tilt", port = true,
|
{ label = Strings.source("TILT"), key = "tilt", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
local Tilt = require("src.render.Tilt")
|
local Tilt = require("src.render.Tilt")
|
||||||
-- Four levels (OFF, 15, 35, 50); left steps back through them.
|
-- Four levels (OFF, 15, 35, 50); left steps back through them.
|
||||||
@@ -160,7 +178,7 @@ local ROWS = {
|
|||||||
-- CGB game whose colour comes from its own palettes, so there are no packs
|
-- CGB game whose colour comes from its own palettes, so there are no packs
|
||||||
-- to swap -- what there is instead is the choice to turn that colour OFF,
|
-- to swap -- what there is instead is the choice to turn that colour OFF,
|
||||||
-- down to the grey Game Boy or the green one. GBC is the default.
|
-- down to the grey Game Boy or the green one. GBC is the default.
|
||||||
{ label = "COLOR", key = "color", port = true,
|
{ label = Strings.source("COLOR"), key = "color", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
local GbcPalette = require("src.render.GbcPalette")
|
local GbcPalette = require("src.render.GbcPalette")
|
||||||
GbcPalette.setMode(options.color or "gbc")
|
GbcPalette.setMode(options.color or "gbc")
|
||||||
@@ -169,7 +187,7 @@ local ROWS = {
|
|||||||
text = function(options)
|
text = function(options)
|
||||||
return require("src.render.GbcPalette").modeLabel(options.color or "gbc")
|
return require("src.render.GbcPalette").modeLabel(options.color or "gbc")
|
||||||
end },
|
end },
|
||||||
{ label = "GBC FX", key = "gbcfx", port = true,
|
{ label = Strings.source("GBC FX"), key = "gbcfx", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
local GBCFX = require("src.render.GBCFX")
|
local GBCFX = require("src.render.GBCFX")
|
||||||
if not GBCFX.isSupported() then
|
if not GBCFX.isSupported() then
|
||||||
@@ -183,7 +201,7 @@ local ROWS = {
|
|||||||
text = function(options)
|
text = function(options)
|
||||||
return require("src.render.GBCFX").levelLabel(options.gbcfx or 0)
|
return require("src.render.GBCFX").levelLabel(options.gbcfx or 0)
|
||||||
end },
|
end },
|
||||||
{ label = "VIDEO MODE", key = "videoMode", port = true,
|
{ label = Strings.source("VIDEO MODE"), key = "videoMode", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
local VideoMode = require("src.core.VideoMode")
|
local VideoMode = require("src.core.VideoMode")
|
||||||
options.videoMode = VideoMode.cycle(options.videoMode, delta)
|
options.videoMode = VideoMode.cycle(options.videoMode, delta)
|
||||||
@@ -194,20 +212,20 @@ local ROWS = {
|
|||||||
return VideoMode.normalize(options.videoMode) == "borderless"
|
return VideoMode.normalize(options.videoMode) == "borderless"
|
||||||
and "FULL" or "WINDOWED"
|
and "FULL" or "WINDOWED"
|
||||||
end },
|
end },
|
||||||
{ label = "SCREEN POS", key = "screenPos", port = true,
|
{ label = Strings.source("SCREEN POS"), key = "screenPos", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
local ScreenPosition = require("src.core.ScreenPosition")
|
local ScreenPosition = require("src.core.ScreenPosition")
|
||||||
options.screenPos = ScreenPosition.cycle(options.screenPos, delta)
|
options.screenPos = ScreenPosition.cycle(options.screenPos, delta)
|
||||||
ScreenPosition.setMode(options.screenPos)
|
ScreenPosition.setMode(options.screenPos)
|
||||||
end,
|
end,
|
||||||
text = function(options)
|
text = function(options)
|
||||||
return require("src.core.ScreenPosition").label(options.screenPos)
|
return Strings(require("src.core.ScreenPosition").label(options.screenPos))
|
||||||
end },
|
end },
|
||||||
{ id = "touchControls", label = "TOUCH PAD", port = true,
|
{ id = "touchControls", label = Strings.source("TOUCH PAD"), port = true,
|
||||||
text = function(options)
|
text = function(options)
|
||||||
local tc = options.touchControls
|
local tc = options.touchControls
|
||||||
local on = not (type(tc) == "table" and tc.enabled == false)
|
local on = not (type(tc) == "table" and tc.enabled == false)
|
||||||
return on and "ON" or "OFF"
|
return on and Strings("ON") or Strings("OFF")
|
||||||
end,
|
end,
|
||||||
cycle = function(options, _delta, game)
|
cycle = function(options, _delta, game)
|
||||||
local tc = type(options.touchControls) == "table" and options.touchControls or {}
|
local tc = type(options.touchControls) == "table" and options.touchControls or {}
|
||||||
@@ -216,13 +234,13 @@ local ROWS = {
|
|||||||
require("src.core.TouchControls"):applyOptions(options)
|
require("src.core.TouchControls"):applyOptions(options)
|
||||||
if game and game.persistOptions then game:persistOptions() end
|
if game and game.persistOptions then game:persistOptions() end
|
||||||
end },
|
end },
|
||||||
{ id = "touchLayout", label = "TOUCH LAYOUT", port = true,
|
{ id = "touchLayout", label = Strings.source("TOUCH LAYOUT"), port = true,
|
||||||
activate = function(game)
|
activate = function(game)
|
||||||
game.stack:push(require("src.ui.TouchControlsEditor").new(game))
|
game.stack:push(require("src.ui.TouchControlsEditor").new(game))
|
||||||
end },
|
end },
|
||||||
{ id = "haptics", label = "VIBRATION", port = true,
|
{ id = "haptics", label = Strings.source("VIBRATION"), port = true,
|
||||||
text = function(options)
|
text = function(options)
|
||||||
return require("src.core.TouchControls").hapticLabel(options.haptics)
|
return Strings(require("src.core.TouchControls").hapticLabel(options.haptics))
|
||||||
end,
|
end,
|
||||||
cycle = function(options, delta, game)
|
cycle = function(options, delta, game)
|
||||||
local TC = require("src.core.TouchControls")
|
local TC = require("src.core.TouchControls")
|
||||||
@@ -231,7 +249,7 @@ local ROWS = {
|
|||||||
TC.buzz(options.haptics)
|
TC.buzz(options.haptics)
|
||||||
if game and game.persistOptions then game:persistOptions() end
|
if game and game.persistOptions then game:persistOptions() end
|
||||||
end },
|
end },
|
||||||
{ label = "MAX FPS", key = "fpsCap", port = true,
|
{ label = Strings.source("MAX FPS"), key = "fpsCap", port = true,
|
||||||
cycle = function(options, delta)
|
cycle = function(options, delta)
|
||||||
local FrameCap = require("src.core.FrameCap")
|
local FrameCap = require("src.core.FrameCap")
|
||||||
options.fpsCap = FrameCap.cycle(options.fpsCap, delta)
|
options.fpsCap = FrameCap.cycle(options.fpsCap, delta)
|
||||||
@@ -240,7 +258,7 @@ local ROWS = {
|
|||||||
text = function(options)
|
text = function(options)
|
||||||
return require("src.core.FrameCap").label(options.fpsCap)
|
return require("src.core.FrameCap").label(options.fpsCap)
|
||||||
end },
|
end },
|
||||||
{ label = "CANCEL", cancel = true },
|
{ label = Strings.source("CANCEL"), cancel = true },
|
||||||
}
|
}
|
||||||
|
|
||||||
-- The cart's screen is one full-height textbox with every row on it. This one
|
-- The cart's screen is one full-height textbox with every row on it. This one
|
||||||
@@ -424,9 +442,9 @@ function OptionsMenu:drawPanel()
|
|||||||
local row = self.rows[i]
|
local row = self.rows[i]
|
||||||
if row then
|
if row then
|
||||||
local labelY = 2 + (slot - 1) * 2
|
local labelY = 2 + (slot - 1) * 2
|
||||||
Chrome.print(row.label, 2, labelY)
|
Chrome.print(Strings(row.label), 2, labelY)
|
||||||
if row.frame then
|
if row.frame then
|
||||||
Chrome.print(":TYPE", 10, labelY + 1)
|
Chrome.print(Strings(":TYPE"), 10, labelY + 1)
|
||||||
Chrome.print(tostring(self.options.frame or 1), 16, labelY + 1)
|
Chrome.print(tostring(self.options.frame or 1), 16, labelY + 1)
|
||||||
elseif row.text then
|
elseif row.text then
|
||||||
Chrome.print(":", 10, labelY + 1)
|
Chrome.print(":", 10, labelY + 1)
|
||||||
@@ -434,7 +452,7 @@ function OptionsMenu:drawPanel()
|
|||||||
elseif row.values then
|
elseif row.values then
|
||||||
Chrome.print(":", 10, labelY + 1)
|
Chrome.print(":", 10, labelY + 1)
|
||||||
local value = self.options[row.key]
|
local value = self.options[row.key]
|
||||||
local text = row.display and row.display[value] or tostring(value)
|
local text = row.display and Strings(row.display[value]) or tostring(value)
|
||||||
Chrome.print(text, 11, labelY + 1)
|
Chrome.print(text, 11, labelY + 1)
|
||||||
elseif type(row.value) == "function" then
|
elseif type(row.value) == "function" then
|
||||||
-- the Gen 1 row's value reader (src/ui/OptionRows.lua:4), so a mod row
|
-- the Gen 1 row's value reader (src/ui/OptionRows.lua:4), so a mod row
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
-- Gold's OPTION screen (src/ui/gen2/OptionsMenu.lua) used to draw every row
|
||||||
|
-- label -- and the cart-original value strings (FAST/MID/SLOW, ON/OFF,
|
||||||
|
-- SHIFT/SET, ...) -- as bare literals baked into the module-level ROWS
|
||||||
|
-- table, invisible to a translation mod's `strings` registry (reported
|
||||||
|
-- against a real Gold build, gen1recomp#1642). This drives
|
||||||
|
-- OptionsMenu:drawPanel() with a mod-loaded Strings catalog and checks the
|
||||||
|
-- translated text reaches Font.draw, for both a cart-original row (label +
|
||||||
|
-- display value) and a port-added row (label only -- its value already
|
||||||
|
-- comes pre-translated from the shared module it calls, same as the Gen 1
|
||||||
|
-- OPTION screen's equivalent rows), plus a vanilla no-mod case proving the
|
||||||
|
-- fallback is unchanged.
|
||||||
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||||
|
|
||||||
|
local T = require("tests.harness")
|
||||||
|
|
||||||
|
love = require("tests.love_stub")
|
||||||
|
|
||||||
|
require("src.core.Logger").warn = function() end
|
||||||
|
|
||||||
|
-- Chrome.print (the only draw call this screen makes) goes straight to
|
||||||
|
-- Font.draw, so recording that call is enough to see exactly what text
|
||||||
|
-- reached the screen -- same technique as
|
||||||
|
-- tests/engine/status_abbreviation_translation_test.lua. Stubbed before
|
||||||
|
-- OptionsMenu (and the Chrome module it requires) ever loads, so Chrome's
|
||||||
|
-- own `local Font = require(...)` captures this stub instead of the real
|
||||||
|
-- module.
|
||||||
|
local drawn
|
||||||
|
package.loaded["src.render.Font"] = {
|
||||||
|
draw = function(text, x, y)
|
||||||
|
drawn[#drawn + 1] = { text = text, x = x, y = y }
|
||||||
|
end,
|
||||||
|
drawCode = function() end,
|
||||||
|
drawBox = function() end,
|
||||||
|
}
|
||||||
|
|
||||||
|
local OptionsMenu = require("src.ui.gen2.OptionsMenu")
|
||||||
|
local Strings = require("src.core.Strings")
|
||||||
|
|
||||||
|
local function drawnAt(x, y)
|
||||||
|
for _, d in ipairs(drawn) do
|
||||||
|
if d.x == x and d.y == y then return d.text end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Chrome.print multiplies tile coordinates by 8 (src/ui/gen2/Chrome.lua);
|
||||||
|
-- drawPanel puts labels at tile x=2 and values at tile x=11.
|
||||||
|
local LABEL_X = 2 * 8
|
||||||
|
local VALUE_X = 11 * 8
|
||||||
|
|
||||||
|
local function rowIndex(rows, id)
|
||||||
|
for i, row in ipairs(rows) do
|
||||||
|
if row.id == id then return i end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---------------------------------------------- vanilla: no mod catalog
|
||||||
|
do
|
||||||
|
local menu = OptionsMenu.new({})
|
||||||
|
drawn = {}
|
||||||
|
menu:drawPanel()
|
||||||
|
T.eq(drawnAt(LABEL_X, 2 * 8), "TEXT SPEED",
|
||||||
|
"row 1's label draws in English with no mod loaded")
|
||||||
|
-- Save.DEFAULT_OPTIONS.textSpeed is "MID", the cart's own default.
|
||||||
|
T.eq(drawnAt(VALUE_X, 3 * 8), "MID ",
|
||||||
|
"and its cart-original display value too")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ------------------------------------------------- a translation mod's turn
|
||||||
|
do
|
||||||
|
Strings.load({
|
||||||
|
strings = {
|
||||||
|
["TEXT SPEED"] = "VITESSE TEXTE",
|
||||||
|
["MID "] = "MOY ",
|
||||||
|
["CONTROLS"] = "COMMANDES",
|
||||||
|
["CANCEL"] = "ANNULER",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
local menu = OptionsMenu.new({})
|
||||||
|
drawn = {}
|
||||||
|
menu:drawPanel()
|
||||||
|
T.eq(drawnAt(LABEL_X, 2 * 8), "VITESSE TEXTE",
|
||||||
|
"a mod catalog reaches a cart-original row's label")
|
||||||
|
T.eq(drawnAt(VALUE_X, 3 * 8), "MOY ",
|
||||||
|
"and its cart-original display value")
|
||||||
|
|
||||||
|
-- CONTROLS is the first port-added row; scroll to it so it lands in the
|
||||||
|
-- VISIBLE_ROWS=7 window drawPanel actually draws.
|
||||||
|
local index = rowIndex(menu.rows, "controls")
|
||||||
|
T.check(index ~= nil, "CONTROLS is one of the rows")
|
||||||
|
menu.index = index
|
||||||
|
menu:ensureVisible()
|
||||||
|
drawn = {}
|
||||||
|
menu:drawPanel()
|
||||||
|
local slot = index - menu.scroll
|
||||||
|
T.eq(drawnAt(LABEL_X, (2 + (slot - 1) * 2) * 8), "COMMANDES",
|
||||||
|
"and a port-added row's label is translated too")
|
||||||
|
|
||||||
|
-- CANCEL is the last row, built into ROWS like any other -- there is no
|
||||||
|
-- separate hook to fall through if this one row is missed.
|
||||||
|
local cancelMenu = OptionsMenu.new({})
|
||||||
|
local cancelIndex = #cancelMenu.rows
|
||||||
|
T.check(cancelMenu.rows[cancelIndex].cancel, "the last row is CANCEL")
|
||||||
|
cancelMenu.index = cancelIndex
|
||||||
|
cancelMenu:ensureVisible()
|
||||||
|
drawn = {}
|
||||||
|
cancelMenu:drawPanel()
|
||||||
|
local cancelSlot = cancelIndex - cancelMenu.scroll
|
||||||
|
T.eq(drawnAt(LABEL_X, (2 + (cancelSlot - 1) * 2) * 8), "ANNULER",
|
||||||
|
"CANCEL, the way out of the menu, is translated too")
|
||||||
|
|
||||||
|
-- Module state is process-global (see tests/gen2_clock_test.lua's own
|
||||||
|
-- note); this suite gets its own process from tests/tier_runner.lua, but
|
||||||
|
-- leaving the catalog loaded past this point would still mistranslate
|
||||||
|
-- every check below it in this file.
|
||||||
|
Strings.load({})
|
||||||
|
T.check(not Strings.active(), "the catalog is unloaded for the checks after this one")
|
||||||
|
end
|
||||||
|
|
||||||
|
T.finish("gen2_options_menu_translation_test")
|
||||||
Reference in New Issue
Block a user