mods: a Spanish translation of the app's own text

A LANGUAGE-profile mod filling the `strings` registry -- the seam #791 opened
up, used for the thing it was opened for. 566 keys: the launcher, OPTIONS,
the save-slot and profile screens, the mod manager, the naming screen, and
the battle menu.

WHAT IT DOES NOT TOUCH is the cartridge. Dialogue, species, items, moves and
places all come out of the player's ROM and stay exactly as they are, so an
English cartridge is still an English adventure with Spanish menus around
it. The lang/ tables for those ship empty on purpose rather than absent:
they are where a full translation would go, and an empty value falls through
to English, so anyone continuing this can fill one row at a time and the
game stays playable throughout.

THE FONT IS THE CONSTRAINT, and it decided the wording. The 8x8 charmap has
no N-tilde, no accented vowels and no inverted punctuation -- the sole
exception in the whole atlas is the small e-acute of POKeMON. So every value
on an 8x8 surface is plain A-Z: DISENO COMBATE, MESETA ANIL, SEGURO? OTRA
VEZ. Not a spelling preference; a glyph that is missing renders as a hole,
which is how the first cut of this shipped "ESPA OL" to a phone. The
launcher draws with a real font and keeps proper Spanish, inverted marks and
all -- the split is by surface, not by taste.

Adding the glyphs to the atlas would let the 8x8 side read properly too, and
lang/font.lua and lang/charmap.lua are already the place that would hook
into. I have not done it here: it is a separate change with its own taste
questions, and it should not ride in on a catalog.

Tested end to end on iOS and macOS.
This commit is contained in:
hernan
2026-08-07 22:16:06 -04:00
parent cab62ff7b3
commit 83f93c27a1
15 changed files with 1001 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
# spanish_ui
A Espanol translation of the game.
Generated with `python3 tools/modkit.py translation spanish_ui`. See
`TRANSLATING.md` for how to work on it.
## Status
Nothing is translated yet: 601 strings are waiting in `lang/`.
| Catalog | Entries |
|---|---|
| `lang/dialogue.lua` | 6 |
| `lang/strings.lua` | 577 |
| `lang/species_names.lua` | 3 |
| `lang/move_names.lua` | 4 |
| `lang/item_names.lua` | 5 |
| `lang/trainer_names.lua` | 1 |
| `lang/status_labels.lua` | 5 |
## Layout
- `manifest.json` - identity and the engine version range
- `main.lua` - registers whatever is filled in and skips whatever is not
- `lang/` - the catalogs; this is the whole job
- `assets/font/` - your glyph sheet
+111
View File
@@ -0,0 +1,111 @@
# Translating into Espanol
Everything the player can read is one of two kinds of string, and they live
in different places for a reason.
| lang/ file | What it is | Key |
|---|---|---|
| `dialogue.lua` | Every line of extracted script text | the original label, e.g. `_PalletTownText1` |
| `strings.lua` | Text the engine itself writes: battle messages, menus, link play | the English source string |
| `species.lua` `moves.lua` `items.lua` `trainers.lua` | Names | the vanilla id |
| `statuses.lua` | `PSN`, `BRN`, ... as they appear in the HUD | the status id |
| `font.lua` `charmap.lua` | Your glyph sheet and what draws what | see below |
| `naming.lua` | The letter grid for entering names | - |
Fill in a value and it takes effect. Leave it `""` and that string stays in
English, so the game is playable at every point along the way.
## Where the English is
The catalogs hold keys and *your* text, never the original English. The
English lives next door, in `spanish_ui-worksheet/`, one tab-separated file per
catalog:
```
"_AbandonLearningText" "Abandon learning\n{RAM:wStringBuffer}?"
```
That directory is deliberately outside the mod. Extracted script text and
the vanilla names are ROM content, and `modkit pack` zips everything under
the mod directory, so a worksheet kept inside would end up in your release
whatever a `.gitignore` said. Keep it beside the mod, never in it.
`lang/strings.lua` is the exception: those sources are the engine's own Lua
rather than anything out of the ROM, so there the key *is* the English and
you can translate straight from it.
## Start with the font, not the text
The engine draws from **glyph pages**: an image of 8x8 cells plus a charmap
saying which byte sequence draws which cell. The vanilla pages sit at `$60`
and `$80`. Anything from `0x100` up is free, so a new alphabet is added
rather than swapped in:
```lua
-- lang/font.lua
return {
spanish_ui = {
image = "assets/font/spanish_ui.png",
base = 0x100, -- first code this page owns
glyphsPerRow = 16,
-- advance = 8, -- set this if your glyphs are not 8px wide
},
}
```
```lua
-- lang/charmap.lua: sequence -> code, in the same order as the sheet
return {
["A"] = 0x100,
["B"] = 0x101,
}
```
The sheet is a plain PNG, 16 glyphs to a row by default, each cell 8x8,
black on white like `assets/generated/font.png`. Codes run left to right,
top to bottom from `base`.
Sequences are matched **longest first**, so a multi-byte character and a
multi-character ligature both work and neither shadows the other:
```lua
["\u{3042}"] = 0x120, -- one 3-byte character, one glyph
["ch"] = 0x121, -- two ASCII letters, one glyph
```
## Line length is counted in glyphs
The dialogue box fits 18 glyphs a line, not 18 bytes. A 3-byte character
costs one column, and the engine will never cut a character in half. Your
own `\n` line breaks are respected exactly as written, so break lines where
they read best rather than where they fit English.
If your glyphs are not 8px wide, set `advance` on the page and the box
re-measures.
## Format directives must survive
Some sources carry `%s` or `%d`:
```lua
["Wild %s\nappeared!"] = "...",
```
Keep every directive, in a count that matches. Word order is yours to
change; the engine substitutes in the order the directives appear, so if
your language needs the name last, write the sentence with the `%s` last.
A translation whose directive count does not match the English is refused
at runtime and the English is drawn instead, with a line in the log saying
so - it will not crash a battle.
## Checking your work
```sh
python3 tools/modkit.py validate spanish_ui --base imported
python3 tools/modkit.py translation spanish_ui --refresh # pick up new engine strings
POKEPORT_DEV=1 scripts/run.sh # F5 hot-reloads lang/
```
`--refresh` rewrites the catalogs from the current engine, keeping every
translation you have already written and reporting what changed. Run it
after pulling a new engine version.
+11
View File
@@ -0,0 +1,11 @@
Put your glyph sheet here.
A page is a PNG of 8x8 cells, 16 per row by default, black on white. Codes
run left to right and top to bottom starting at the page's `base`, so the
first cell is `base`, the second `base + 1`, and so on.
`assets/generated/font.png` in the player's cache is the vanilla sheet at
the same scale; open it alongside yours to match weight and baseline.
Declare the sheet in `lang/font.lua` and map sequences to codes in
`lang/charmap.lua`.
+10
View File
@@ -0,0 +1,10 @@
-- Which byte sequence draws which glyph code.
--
-- Sequences are matched longest-first, so a multi-byte character and a
-- multi-character ligature both work: "ch" can be one glyph even though
-- "c" is also mapped. Codes here must land inside a page declared in
-- lang/font.lua.
return {
-- ["A"] = 0x100,
-- ["B"] = 0x101,
}
+12
View File
@@ -0,0 +1,12 @@
-- Script text
--
-- Keyed by the original text label. The English is in the comment.
return {
["_FixMartText"] = "",
["_FixRouteTrainerAfterText"] = "",
["_FixRouteTrainerBattleText"] = "",
["_FixRouteTrainerEndText"] = "",
["_FixTownGreeterText"] = "",
["_FixTownSignText"] = "",
}
+13
View File
@@ -0,0 +1,13 @@
-- Glyph pages this translation adds. Delete the entry if the vanilla
-- alphabet already covers your language.
--
-- base is the first glyph code the page owns. 0x100 and up is free space
-- above the vanilla $60/$80 pages, so this adds an alphabet rather than
-- replacing one. Set `advance` if your glyphs are not 8px wide.
return {
-- spanish_ui = {
-- image = "assets/font/spanish_ui.png",
-- base = 0x100,
-- glyphsPerRow = 16,
-- },
}
+11
View File
@@ -0,0 +1,11 @@
-- Item names
--
-- Item names for Espanol.
return {
["FIX_BADGE_1"] = "",
["FIX_BADGE_2"] = "",
["FIX_BALL"] = "",
["FIX_POTION"] = "",
["FIX_TM"] = "",
}
+10
View File
@@ -0,0 +1,10 @@
-- Move names
--
-- Move names for Espanol.
return {
["FIX_CUT"] = "",
["FIX_EMBERISH"] = "",
["FIX_SCRATCH"] = "",
["FIX_TACKLE"] = "",
}
+41
View File
@@ -0,0 +1,41 @@
-- The naming screen's letter grid. Return an empty table to keep the
-- English alphabet.
--
-- Each entry is a row of cells; a cell is whatever sequence your charmap
-- maps, so a multi-byte character is one cell. The row holding a single
-- "lower case" / "UPPER CASE" cell is the case switch, and the cell
-- spelled "ED" is the confirm.
--
-- The screen is 160x144 and NamingScreen draws cell `c` of row `r` at
-- (c * 16, 32 + r * 16), so the grid is capped at **9 columns and 6 rows**:
-- a 10th column lands at x=160 and a 7th row at y=144, both off screen.
-- That leaves 44 usable cells, exactly what vanilla uses, so Spanish
-- letters have to displace something rather than being added.
--
-- What gives way is vanilla's `× ( ) : ; [ ]` row. Those are legal in a
-- Gen-1 nickname but nobody reaches for them, whereas Ñ is not optional in
-- Spanish -- and here it sits in its alphabetical place after N, which is
-- where a Spanish speaker will look for it. Space, <PK> and <MN> are kept.
--
-- These glyphs exist in the Spanish cartridge's font ($CA Ñ, $BF Á, $C7 É,
-- $C9 Í, $CC Ó, $CE Ú, $C2 Ü and their lowercase). On an English ROM they
-- do not, so main.lua checks the running game's charmap first and keeps the
-- English grid rather than drawing blank cells.
return {
upper = {
{ "A", "B", "C", "D", "E", "F", "G", "H", "I" },
{ "J", "K", "L", "M", "N", "Ñ", "O", "P", "Q" },
{ "R", "S", "T", "U", "V", "W", "X", "Y", "Z" },
{ "Á", "É", "Í", "Ó", "Ú", "Ü", " ", "<PK>", "<MN>" },
{ "-", "?", "!", "", "", "/", ".", ",", "ED" },
{ "lower case" },
},
lower = {
{ "a", "b", "c", "d", "e", "f", "g", "h", "i" },
{ "j", "k", "l", "m", "n", "ñ", "o", "p", "q" },
{ "r", "s", "t", "u", "v", "w", "x", "y", "z" },
{ "á", "é", "í", "ó", "ú", "ü", " ", "<PK>", "<MN>" },
{ "-", "?", "!", "", "", "/", ".", ",", "ED" },
{ "UPPER CASE" },
},
}
+9
View File
@@ -0,0 +1,9 @@
-- Species names
--
-- Species names for Espanol.
return {
["FIXMON_A"] = "",
["FIXMON_B"] = "",
["FIXMON_C"] = "",
}
+11
View File
@@ -0,0 +1,11 @@
-- Status labels
--
-- Short enough for the battle HUD: the vanilla ones are three glyphs.
return {
["BRN"] = "",
["FRZ"] = "",
["PAR"] = "",
["PSN"] = "",
["SLP"] = "",
}
+584
View File
@@ -0,0 +1,584 @@
-- Engine text
--
-- Keyed by the English source, which is also what draws if you leave
-- an entry empty. Keep any %s / %d directives.
return {
["%s\nflew up high!"] = "¡%s\nvoló muy alto!",
["%s\ndug a hole!"] = "¡%s\ncavó un hoyo!",
["%s\nmade a whirlwind!"] = "¡%s\ncreó un torbellino!",
["%s\ntook in sunlight!"] = "¡%s\nabsorbió luz!",
["%s\nlowered its head!"] = "¡%s\nbajó la cabeza!",
["%s\nis glowing!"] = "¡%s\nestá brillando!",
["The hooked\n%s\nattacked!"] = "¡El %s\nenganchado atacó!",
["Wild %s\nappeared!"] = "¡Un %s\nsalvaje apareció!",
["%s wants\nto fight!"] = "¡%s\nquiere luchar!",
["The GHOST\nappeared!"] = "¡Apareció el\nFANTASMA!",
["Go! %s!"] = "¡Ve, %s!",
["Do it! %s!"] = "¡Hazlo, %s!",
["Get'm! %s!"] = "¡A por él, %s!",
["The enemy's weak!\nGet'm! %s!"] = "¡Está débil!\n¡A por él, %s!",
["%s is out of\nuseable POKéMON!"] = "¡%s no tiene\nPOKéMON útiles!",
["%s blacked\nout!"] = "¡%s se\ndebilitó!",
["%s sent\nout %s!"] = "¡%s envió\na %s!",
["PA: You're out of\nSAFARI BALLs!\nGame over!"] = "AV: ¡No te quedan\nSAFARI BALLs!\n¡Fin del juego!",
["%s is too\nscared to move!"] = "¡%s tiene\ndemasiado miedo!",
["%s has no\nmoves left!"] = "¡%s no tiene\nmovimientos!",
["The move is\ndisabled!"] = "¡El movimiento\nestá anulado!",
["No PP left for\nthis move!"] = "¡No quedan PP para\neste movimiento!",
["But, it failed!"] = "¡Pero falló!",
["%s\nlearned\n%s!"] = "¡%s\naprendió\n%s!",
["POKé BALL"] = "POKé BALL",
["%s used\nPOKé BALL!"] = "¡%s usó\nPOKé BALL!",
["All right!\n%s was\ncaught!"] = "¡Bien!\n¡%s fue\ncapturado!",
["GHOST: Get out...\nGet out..."] = "FANTASMA: Fuera...\nFuera...",
["%s with-\ndrew %s!"] = "¡%s retiró\na %s!",
["%s\nmust recharge!"] = "¡%s debe\nrecargarse!",
["%s\nis fast asleep!"] = "¡%s está\nprofundamente dormido!",
["%s\nis confused!"] = "¡%s está\nconfuso!",
["%s\nwoke up!"] = "¡%s se\ndespertó!",
["%s\nis frozen solid!"] = "¡%s está\ncongelado!",
["%s\ncan't move!"] = "¡%s no\npuede moverse!",
["%s\nflinched!"] = "¡%s se\namedrentó!",
["It hurt itself in\nits confusion!"] = "¡Se hirió a sí\nmismo por confusión!",
["%s\nused %s!"] = "¡%s usó\n%s!",
["%s\nis charging up!"] = "¡%s está\ncargando energía!",
["%s's\nattack missed!"] = "¡El ataque de %s\nfalló!",
["%s's\nattack continues!"] = "¡El ataque de %s\ncontinúa!",
["%s\nis storing energy!"] = "¡%s está\nacumulando energía!",
["%s\nunleashed energy!"] = "¡%s liberó\nsu energía!",
["%s's\nSUBSTITUTE broke!"] = "¡El SUSTITUTO de\n%s se rompió!",
["The SUBSTITUTE\ntook damage for\n%s!"] = "¡El SUSTITUTO\nrecibió el daño\nde %s!",
["%s's\nRAGE is building!"] = "¡La FURIA de %s\nva creciendo!",
["%s\nfainted!"] = "¡%s se\ndebilitó!",
["%s gained\n%d EXP. Points!"] = "¡%s ganó\n%d P. EXP.!",
["%s gained\nwith EXP.ALL,\v%d EXP. Points!"] = "¡%s ganó\ncon EXP.TODOS,\v%d P. EXP.!",
["%s gained\na boosted\v%d EXP. Points!"] = "¡%s ganó\nun extra de\v%d P. EXP.!",
["%s grew\nto level %d!"] = "¡%s subió\nal nivel %d!",
["%s is\nabout to use"] = "%s va a usar",
["%s!"] = "¡%s!",
["Will %s\nchange POKéMON?"] = "¿%s va a\ncambiar de POKéMON?",
["%s defeated\n%s!"] = "¡%s venció\na %s!",
["%s got ¥%d\nfor winning!"] = "¡%s ganó\n¥%d!",
["%s learned\n%s!"] = "¡%s aprendió\n%s!",
["{RIVAL}: Yeah! Am\nI great or what?"] = "{RIVAL}: ¡Sí! ¿Soy\ngenial o qué?",
["Use next POKéMON?"] = "¿Sacar al siguiente?",
["Got away safely!"] = "¡Escapaste!",
["Can't escape!"] = "¡No puedes escapar!",
["There's no will\nto fight!"] = "¡No hay ganas de\nluchar!",
["%s used\nSAFARI BALL!"] = "¡%s usó\nSAFARI BALL!",
["%s threw some\nBAIT."] = "%s echó\nCEBO.",
["%s threw a\nROCK."] = "%s tiró una\nPIEDRA.",
["Wild %s\nis eating!"] = "¡El %s\nsalvaje come!",
["Wild %s\nis angry!"] = "¡El %s\nsalvaje se enfadó!",
["Wild %s\nran!"] = "¡El %s\nsalvaje huyó!",
["No! There's no\nrunning from a\vtrainer battle!"] = "¡No! ¡No puedes\nhuir de un combate\vcontra un entrenador!",
["You missed the\nPOKéMON!"] = "¡Fallaste el tiro!",
["Darn! The POKéMON\nbroke free!"] = "¡Vaya! ¡El POKéMON\nse escapó!",
["Aww! It appeared\nto be caught!"] = "¡Oh! ¡Parecía que\nestaba capturado!",
["Shoot! It was so\nclose too!"] = "¡Vaya! ¡Estuvo\nmuy cerca!",
["Do you want to\ngive a nickname\nto %s?"] = "¿Quieres poner un\nmote a\n%s?",
["NICKNAME?"] = "MOTE?",
["New POKéDEX data\nwill be added for\n%s!"] = "¡Se añadirán datos\nnuevos a la POKéDEX\nde %s!",
["someone's PC"] = "el PC de alguien",
["%s was\ntransferred to\n%s!"] = "¡%s fue\ntransferido a\n%s!",
["But every BOX\nis full!"] = "¡Pero todas las\nCAJAS están llenas!",
["%s used\n%s!"] = "¡%s usó\n%s!",
["The trainer\nblocked the BALL!"] = "¡El entrenador\nbloqueó la BALL!",
["Don't be a thief!"] = "¡No seas ladrón!",
["It dodged the\nthrown BALL!"] = "¡Esquivó la BALL!",
["This POKéMON\ncan't be caught!"] = "¡Este POKéMON no\nse puede capturar!",
["%s is\nalready out!"] = "¡%s ya\nestá fuera!",
["%s picked up\n¥%d!"] = "¡%s recogió\n¥%d!",
["FIGHT"] = "LUCHAR",
["ITEM"] = "OBJETO",
["RUN"] = "HUIR",
["BALLx"] = "BALLx",
["BAIT"] = "CEBO",
["THROW ROCK"] = "TIRAR PIEDRA",
["disabled!"] = "¡anulado!",
["TYPE/"] = "TIPO/",
["It doesn't affect\n%s!"] = "¡No afecta a\n%s!",
["Critical hit!"] = "¡Golpe crítico!",
["One-hit KO!"] = "¡KO en un golpe!",
["It's super\neffective!"] = "¡Es muy eficaz!",
["It's not very\neffective..."] = "¡No es muy\neficaz...",
["Hit the enemy\n%d times!"] = "¡Golpeó al enemigo\n%d veces!",
["Hit %d times!"] = "¡Golpeó %d veces!",
["%s's\nhit with recoil!"] = "¡%s sufrió\nel retroceso!",
["%s is\nprotected by MIST!"] = "¡%s está\nprotegido por NIEBLA!",
["Nothing happened!"] = "¡No pasó nada!",
["%s's\n%s\ngreatly rose!"] = "¡%s\nmejoró mucho su\n%s!",
["%s's\n%s rose!"] = "¡%s mejoró\nsu %s!",
["%s's\n%s fell!"] = "¡%s bajó\nsu %s!",
["%s's\n%s\ngreatly fell!"] = "¡%s\nbajó mucho su\n%s!",
["Fire defrosted\n%s!"] = "¡El fuego descongeló\na %s!",
["%s\nbecame confused!"] = "¡%s se\nconfundió!",
["%s\nwas seeded!"] = "¡%s recibió\nla DRENADORA!",
["%s\nstarted sleeping!"] = "¡%s se\nquedó dormido!",
["%s\nregained health!"] = "¡%s recuperó\nsalud!",
["%s's\nprotected against\nspecial attacks!"] = "¡%s está\nprotegido de los\nataques especiales!",
["%s\ngained armor!"] = "¡%s ganó\narmadura!",
["%s's\nshrouded in mist!"] = "¡%s se\ncubrió de niebla!",
["%s's\ngetting pumped!"] = "¡%s se\nestá animando!",
["All STATUS changes\nare eliminated!"] = "¡Los cambios de\nESTADO desaparecen!",
["%s\nhas a SUBSTITUTE!"] = "¡%s tiene\nun SUSTITUTO!",
["Too weak to make\na SUBSTITUTE!"] = "¡Muy débil para\nhacer un SUSTITUTO!",
["It created a\nSUBSTITUTE!"] = "¡Creó un SUSTITUTO!",
["Converted type to\n%s's!"] = "¡Cambió su tipo al\nde %s!",
["%s\ntransformed into\n%s!"] = "¡%s se\ntransformó en\n%s!",
["%s's\n%s was\ndisabled!"] = "¡El %s\nde %s\nfue anulado!",
["No effect!"] = "¡Sin efecto!",
["Sucked health from\n%s!"] = "¡Absorbió salud de\n%s!",
["%s's\ndream was eaten!"] = "¡Devoró el sueño\nde %s!",
["%s\nkept going and\ncrashed!"] = "¡%s siguió\nadelante y se\nestrelló!",
["Coins scattered\neverywhere!"] = "¡Las monedas se\ndesparramaron!",
["%s\nran away scared!"] = "¡%s huyó\nasustado!",
["%s\nwas blown away!"] = "¡%s salió\nvolando!",
["%s\nran from battle!"] = "¡%s huyó\ndel combate!",
["It didn't affect\n%s!"] = "¡No afectó a\n%s!",
["%s\nis unaffected!"] = "¡%s no se\nvio afectado!",
["The MIRROR MOVE\nfailed!"] = "¡El MOVIMIENTO\nESPEJO falló!",
["%s\nfell asleep!"] = "¡%s se\nquedó dormido!",
["%s\nwas frozen solid!"] = "¡%s se\ncongeló!",
["%s's\nhurt by poison!"] = "¡El veneno hiere a\n%s!",
["%s's\nbadly poisoned!"] = "¡%s está\ngravemente envenenado!",
["%s\nwas poisoned!"] = "¡%s fue\nenvenenado!",
["%s's\nhurt by the burn!"] = "¡La quemadura hiere\na %s!",
["%s\nwas burned!"] = "¡%s se\nquemó!",
["%s's\nfully paralyzed!"] = "¡%s está\ntotalmente paralizado!",
["%s's\nparalyzed! It may\nnot attack!"] = "¡%s está\nparalizado! ¡Puede\nque no ataque!",
["%s's\ndisabled no more!"] = "¡%s ya no\nestá anulado!",
["%s\nsnapped out of\nconfusion!"] = "¡%s salió\nde su confusión!",
["LEECH SEED saps\n%s!"] = "¡La DRENADORA\nabsorbe a %s!",
["%s\nwas afflicted\nby %s!"] = "¡%s sufre\n%s!",
["%s's\nprotected against\nstat changes!"] = "¡%s está\nprotegido de los\ncambios de estado!",
["What will"] = "¿Qué va a hacer",
[" do?"] = "?",
["You can't get off\nhere."] = "No puedes bajarte\naquí.",
["%s got off\nthe BICYCLE."] = "%s se bajó\nde la BICICLETA.",
["%s got on\nthe BICYCLE!"] = "¡%s se subió\na la BICICLETA!",
["No cycling\nallowed here."] = "No se puede montar\naquí.",
["No good! It's not\neven near water."] = "¡No sirve! No hay\nagua cerca.",
["OAK: %s!\nThis isn't the\ntime to use that!"] = "OAK: ¡%s!\n¡No es momento\nde usar eso!",
["The TOWN MAP is\nunreadable here."] = "El MAPA PUEBLO no\nse puede leer aquí.",
["Yes! ITEMFINDER\nindicates there's\nan item nearby."] = "¡Sí! El BUSCAOBJ.\nindica que hay algo\ncerca.",
["Nope! ITEMFINDER\nisn't responding."] = "¡No! El BUSCAOBJ.\nno responde.",
["Booted up a TM!"] = "¡Se activó una MT!",
["It contained\n%s!"] = "¡Contenía\n%s!",
["USE"] = "USAR",
["TOSS"] = "TIRAR",
["That's too impor-\ntant to toss!"] = "¡Es demasiado\nimportante!",
["Threw away\n%s."] = "Tiraste\n%s.",
["PRESS A BUTTON"] = "PULSA UN BOTON",
["ESC TO CANCEL"] = "ESC PARA CANCELAR",
["%s :L%d"] = "%s :N%d",
["STATS"] = "DATOS",
["CANCEL"] = "CANCELAR",
["What? There are\nno POKéMON here!"] = "¿Qué? ¡Aquí no hay\nningún POKéMON!",
["You can't take\nany more POKéMON.\fDeposit POKéMON\nfirst."] = "No puedes llevar\nmás POKéMON.\fGuarda alguno\nprimero.",
["BOX %d (WITHDRAW)"] = "CAJA %d (RETIRAR)",
["%s is\ntaken out.\vGot %s."] = "Retirado\n%s.\vRecibes %s.",
["You can't deposit\nthe last POKéMON!"] = "¡No puedes guardar\nel último POKéMON!",
["Oops! This Box is\nfull of POKéMON."] = "¡Uups! Esta CAJA\nestá llena.",
["You need at least\none POKéMON!"] = "¡Necesitas al menos\nun POKéMON!",
["BOX %d is full!"] = "¡La CAJA %d está\nllena!",
["%s was\nstored in Box %s."] = "%s se\nguardó en la CAJA %s.",
["BOX %d (RELEASE)"] = "CAJA %d (SOLTAR)",
["Once released,\n%s is\ngone forever. OK?"] = "Si lo sueltas,\n%s se\nirá para siempre. ¿OK?",
["%s was\nreleased outside.\fBye %s!"] = "%s fue\nliberado.\f¡Adiós, %s!",
["%sBOX %2d"] = "%sCAJA %2d",
["When you change a\nPOKéMON BOX, data\nwill be saved. OK?"] = "Al cambiar de CAJA\nse guardarán los\ndatos. ¿OK?",
["What?"] = "¿Qué?",
["BOX No."] = "CAJA No.",
["BOX No.%d"] = "CAJA No.%d",
["Empty."] = "Vacía.",
[":L%d No.%03d"] = ":N%d No.%03d",
["Printed BOX %d!\fSaved as\n%s\vin the save\nfolder."] = "¡CAJA %d impresa!\fGuardada como\n%s\ven la carpeta de\nguardado.",
["Printer error!\n%s"] = "¡Error de impresión!\n%s",
["WITHDRAW <PK><MN>"] = "RETIRAR <PK><MN>",
["DEPOSIT <PK><MN>"] = "GUARDAR <PK><MN>",
["RELEASE <PK><MN>"] = "SOLTAR <PK><MN>",
["CHANGE BOX"] = "CAMBIAR CAJA",
["PRINT BOX"] = "IMPRIMIR CAJA",
["SEE YA!"] = "HASTA LUEGO!",
["YES"] = "SI",
["NO"] = "NO",
["GAME FREAK"] = "",
["Nintendo"] = "",
["Creatures inc."] = "",
["GAME FREAK inc."] = "",
["T H E E N D"] = "F I N",
["HT %d%02d″"] = "AL %d%02d″",
["WT %.1flb"] = "PE %.1flb",
["Data unknown."] = "Datos desconocidos.",
["<Diploma>"] = "<Diploma>",
["Player"] = "Jugador",
["Huh? %s\nstopped evolving!"] = "¿Eh? ¡%s\ndejó de evolucionar!",
["Congratulations!\nYour %s\nevolved into\n%s!"] = "¡Enhorabuena!\n¡Tu %s\nevolucionó a\n%s!",
["evolving!"] = "evolucionando",
["POKéDEX Seen:{NUM:wDexRatingNumMonsSeen, 1, 3}\n Owned:{NUM:wDexRatingNumMonsOwned, 1, 3}"] = "POKéDEX Vistos:{NUM:wDexRatingNumMonsSeen, 1, 3}\n Capturados:{NUM:wDexRatingNumMonsOwned, 1, 3}",
["POKéDEX Rating{COLON}"] = "Nota POKéDEX{COLON}",
["Keep it up!"] = "¡Sigue así!",
["LEVEL/"] = "NIVEL/",
["TYPE1/"] = "TIPO1/",
["TYPE2/"] = "TIPO2/",
["HALL OF FAME"] = "SALON DE LA FAMA",
["PLAY TIME"] = "TIEMPO",
["MONEY"] = "DINERO",
["bois club games"] = "bois club games",
["GENGAR VS NIDORINO"] = "",
["bois club"] = "bois club",
["Nothing here."] = "Aquí no hay nada.",
["%s is\ntrying to learn\v%s!\fBut, %s\ncan't learn more\vthan 4 moves!\f"] = "¡%s está\nintentando aprender\v%s!\f¡Pero %s\nno puede aprender\vmás de 4!\f",
["Delete an older\nmove to make room\vfor %s?"] = "¿Borrar un movi-\nmiento antiguo para\vaprender %s?",
["HM techniques\ncan't be deleted!"] = "¡Los movimientos MO\nno se pueden borrar!",
["Abandon learning\n%s?"] = "¿Dejar de aprender\n%s?",
["1, 2 and... Poof!\f%s forgot\n%s!\fAnd...\f%s learned\n%s!"] = "¡1, 2 y... plaf!\f¡%s olvidó\n%s!\f¡Y...\f%s aprendió\n%s!",
["%s\ndid not learn\v%s!"] = "¡%s no\naprendió\v%s!",
["Which move should"] = "¿Qué movimiento",
["be forgotten?"] = "hay que olvidar?",
["YOUR NAME?"] = "TU NOMBRE?",
["NEW NAME"] = "NUEVO NOMBRE",
["Hello there!\nWelcome to the\vworld of POKéMON!\fMy name is OAK!\nPeople call me\vthe POKéMON PROF!"] = "¡Hola!\n¡Bienvenido al\vmundo POKéMON!\fMe llamo OAK.\nMe llaman el\vPROF. POKéMON.",
["This world is\ninhabited by\vcreatures called\vPOKéMON!"] = "¡Este mundo está\nhabitado por unas\vcriaturas llamadas\vPOKéMON!",
["\fFor some people,\nPOKéMON are\vpets. Others use\vthem for fights.\fMyself...\fI study POKéMON\nas a profession."] = "\fPara algunos, los\nPOKéMON son masco-\vtas. Otros luchan\vcon ellos.\fYo...\fEstudio los POKéMON\ncomo profesión.",
["{PLAYER}!\fYour very own\nPOKéMON legend is\vabout to unfold!\fA world of dreams\nand adventures\vwith POKéMON\vawaits! Let's go!"] = "¡{PLAYER}!\f¡Tu propia leyenda\nPOKéMON está a\vpunto de comenzar!\f¡Un mundo de sueños\ny aventuras con\vPOKéMON te espera!\v¡Vamos!",
["First, what is\nyour name?"] = "¿Cómo te llamas?",
["This is my grand-\nson. He's been\vyour rival since\vyou were a baby.\f...Erm, what is\nhis name again?"] = "Este es mi nieto.\nHa sido tu rival\vdesde que erais\vbebés.\f...Mmm, ¿cómo se\nllamaba?",
["HIS NAME?"] = "SU NOMBRE?",
["_OakSpeechText2A"] = "",
["TEXT SPEED"] = "VEL TEXTO",
["BATTLE ANIMATION"] = "ANIMACIONES",
["OFF"] = "NO",
["ON"] = "SI",
["BATTLE STYLE"] = "ESTILO COMBATE",
["SET"] = "FIJO",
["SHIFT"] = "CAMBIO",
["BATTLE LAYOUT"] = "DISENO COMBATE",
["WIDE"] = "ANCHO",
["OG"] = "OG",
["RULESET"] = "REGLAS",
["MUSIC VOL"] = "VOL MUSICA",
["SFX VOL"] = "VOL SONIDO",
["PIKACHU VOL"] = "VOL PIKACHU",
["MUSIC FILTER"] = "FILTRO MUSICA",
["COLORS"] = "COLORES",
["TILT"] = "INCLINACION",
["GBC FX"] = "EFECTO GBC",
["ZOOM"] = "ZOOM",
["VOID FILL"] = "RELLENO VACIO",
["VIDEO MODE"] = "MODO VIDEO",
["MAX FPS"] = "FPS MAXIMO",
["GAME SPEED"] = "VELOCIDAD JUEGO",
["MODS"] = "MODS",
["%d INSTALLED"] = "%d INSTALADOS",
["CONTROLS"] = "CONTROLES",
["TOUCH PAD"] = "CONTROL TACTIL",
["SURE? AGAIN"] = "SEGURO? OTRA VEZ",
["AUTO HIDE PAD"] = "OCULTAR AUTO",
["A blinding FLASH\nlights the area!"] = "¡Un DESTELLO\nilumina la zona!",
["No SURFing here!"] = "¡Aquí no se puede\nSURFEAR!",
["Nothing to CUT!"] = "¡Nada que CORTAR!",
["{RAM:wNameBuffer} used\nSTRENGTH."] = "{RAM:wNameBuffer} usó\nFUERZA.",
["{RAM:wNameBuffer} can\nmove boulders."] = "{RAM:wNameBuffer} puede\nmover rocas.",
["It won't have\nany effect."] = "No tendrá ningún\nefecto.",
["%s's HP\nwas restored!"] = "¡Los PS de %s\nse recuperaron!",
["SWITCH"] = "CAMBIAR",
["FLY"] = "VUELO",
["FLASH"] = "DESTELLO",
["CUT"] = "CORTE",
["SURF"] = "SURF",
["STRENGTH"] = "FUERZA",
["SOFTBOILED"] = "HUEVO SUERTE",
["TELEPORT"] = "TELETRANSPORTE",
["DIG"] = "EXCAVAR",
["Use TM on which\nPOKéMON?"] = "¿Usar la MT en qué\nPOKéMON?",
["Bring out which\nPOKéMON?"] = "¿Qué POKéMON\nquieres sacar?",
["Choose a POKéMON."] = "Elige un POKéMON.",
["No POKéMON!"] = "¡Ningún POKéMON!",
["ABLE"] = "PUEDE",
["NOT ABLE"] = "NO PUEDE",
["FNT"] = "DEB",
["Move to where?"] = "¿Mover a dónde?",
["Use on which one?"] = "¿Usar en cuál?",
["You can't carry\nany more items."] = "No puedes llevar\nmás objetos.",
["Withdrew\n%s."] = "Retirado\n%s.",
["No room left to\nstore items."] = "No queda sitio para\nguardar objetos.",
["%s was\nstored via PC."] = "%s se\nguardó en el PC.",
["Toss %s?"] = "¿Tirar %s?",
["Threw away %s."] = "Tiraste %s.",
["WITHDRAW ITEM"] = "RETIRAR OBJETO",
["DEPOSIT ITEM"] = "GUARDAR OBJETO",
["TOSS ITEM"] = "TIRAR OBJETO",
["LOG OFF"] = "SALIR",
["SEEN %d OWNED %d"] = "VISTOS %d CAPT. %d",
["DATA"] = "DATOS",
["CRY"] = "VOZ",
["AREA"] = "ZONA",
["PRNT"] = "IMPR",
["Printed %s's\ndata!\fSaved as\n%s\vin the save\nfolder."] = "¡Datos de %s\nimpresos!\fGuardado como\n%s\ven la carpeta de\nguardado.",
["QUIT"] = "SALIR",
["%s (%s)"] = "%s (%s)",
["%s x%d"] = "%s x%d",
["%s to box %d"] = "%s a caja %d",
["LOAD REPORT"] = "CARGAR PARTIDA",
["A:CONTINUE"] = "A:CONTINUAR",
["You don't have\nenough money."] = "No tienes dinero\nsuficiente.",
["%s?\nThat will be\n¥%d. OK?"] = "¿%s?\nSon ¥%d.\n¿OK?",
["Here you are!\nThank you!"] = "¡Aquí tienes!\n¡Gracias!",
["I can't put a\nprice on that."] = "No puedo ponerle\nprecio a eso.",
["I can pay you\n¥%d for that."] = "Te doy ¥%d\npor eso.",
["BUY"] = "COMPRAR",
["SELL"] = "VENDER",
["%s lined up!\nScored %d coins!"] = "¡%s alineados!\n¡%d fichas!",
["Darn!\nRan out of coins!"] = "¡Vaya!\n¡Sin fichas!",
["Not enough\ncoins!"] = "¡Fichas\ninsuficientes!",
["SLOT MACHINE"] = "MAQUINA TRAGAPERRAS",
["COINS %4d"] = "FICHAS %4d",
["POKéDEX"] = "POKéDEX",
["POKéMON"] = "POKéMON",
["SAVE"] = "GUARDAR",
["PLAYER %s\nBADGES %d\nPOKéDEX %3d\nTIME %6d:%02d"] = "JUGADOR %s\nMEDALLAS %d\nPOKéDEX %3d\nTIEMPO %6d:%02d",
["\fWould you like to\nSAVE the game?"] = "\f¿Quieres GUARDAR\nla partida?",
["Now saving..."] = "Guardando...",
["%s saved\nthe game!"] = "¡%s guardó\nla partida!",
["OPTION"] = "OPCION",
["LINK"] = "LINK",
["RETURN TO MAIN\nMENU?"] = "¿VOLVER AL MENU\nPRINCIPAL?",
["BALL"] = "BALL",
["STATUS/"] = "ESTADO/",
["OT/"] = "EO/",
["EXP POINTS"] = "P. EXP.",
["LEVEL UP"] = "SUBE NIVEL",
["PP"] = "PP",
["SCORE %d"] = "PUNTOS %d",
["New record!"] = "¡Nuevo récord!",
["HI %d"] = "MAX %d",
["A: done"] = "A: listo",
["PLAYER"] = "JUGADOR",
["BADGES"] = "MEDALLAS",
["TIME"] = "TIEMPO",
["CONTINUE"] = "CONTINUAR",
["NEW GAME"] = "NUEVA PARTIDA",
["EXIT GAME"] = "SALIR DEL JUEGO",
["POKéMON RED"] = "",
["2026 bois club games"] = "",
["OT/%s"] = "EO/%s",
["NAME/%s"] = "NOMBRE/%s",
["In battle"] = "En combate",
["Wild battle"] = "Combate salvaje",
["Trainer battle"] = "Combate entrenador",
["Link battle"] = "Combate link",
["Title screen"] = "Pantalla de título",
["Level %d"] = "Nivel %d",
["What?\n%s is\nevolving!\fCongratulations!\nYour %s\nevolved into\n%s!"] = "¿Qué?\n¡%s está\nevolucionando!\f¡Enhorabuena!\n¡Tu %s\nevolucionó a\n%s!",
["Not even a nibble!"] = "¡Ni un mordisco!",
["Oh!\nIt's a bite!"] = "¡Oh!\n¡Ha picado!",
["It's a sculpture\nof DIGLETT."] = "Es una escultura\nde DIGLETT.",
["Crammed full of\nPOKéMON books!"] = "¡Repleto de libros\nsobre POKéMON!",
["There's a slew of\nPOKéMON stuff!"] = "¡Hay un montón de\ncosas POKéMON!",
["An elevator!"] = "¡Un ascensor!",
["INDIGO PLATEAU"] = "MESETA ANIL",
["POKéMON LEAGUE HQ"] = "SEDE DE LA LIGA\nPOKéMON",
["You can't carry\nany more items!"] = "¡No puedes llevar\nmás objetos!",
["%s found\n%s!"] = "¡%s encontró\n%s!",
["%s found\n%d coins!"] = "¡%s encontró\n%d fichas!",
["OUT OF ORDER\nThis is broken."] = "FUERA DE SERVICIO\nEsto está roto.",
["OUT TO LUNCH\nThis is reserved."] = "CERRADO POR COMIDA\nEsto está reservado.",
["Someone's keys!\nThey'll be back."] = "¡Las llaves de\nalguien! Volverá.",
["A COIN CASE is\nrequired!"] = "¡Se necesita un\nMONEDERO!",
["You don't have\nany coins!"] = "¡No tienes fichas!",
["{RAM}\nPOKéMON GYM\nLEADER: {RAM}"] = "{RAM}\nGIMNASIO POKéMON\nLIDER: {RAM}",
["Nope, there's\nonly trash here."] = "No, aquí solo hay\nbasura.",
["Darn! It needs a\nCARD KEY!"] = "¡Vaya! ¡Necesita\nuna LLAVE MAGNET.!",
["Bingo!"] = "¡Bingo!",
["\nThe CARD KEY\nopened the door!"] = "\n¡La LLAVE MAGNET.\nabrió la puerta!",
["Hey! There's a\nswitch under the\ntrash!\fThe 1st electric\nlock opened!"] = "¡Hay un interruptor\nbajo la basura!\f¡Se abrió el 1er\ncierre eléctrico!",
["The 2nd electric\nlock opened!\fThe motorized door\nopened!"] = "¡Se abrió el 2o\ncierre eléctrico!\f¡La puerta se\nabrió!",
["Nope! There's\nonly trash here.\fHey! The electric\nlocks were reset!"] = "¡No! Aquí solo hay\nbasura.\f¡Los cierres se\nreiniciaron!",
["TELEPORTER is\ndisplayed on the\nPC monitor."] = "El TELETRANSPORTE\naparece en el\nmonitor del PC.",
["{PLAYER} initiated\nTELEPORTER's Cell\nSeparator!"] = "¡{PLAYER} activó el\nSeparador de Células\ndel TELETRANSPORTE!",
["BILL's favorite\nPOKéMON list!"] = "¡La lista de POKéMON\nfavoritos de BILL!",
["{PLAYER} got on\n{RAM:wNameBuffer}!"] = "¡{PLAYER} se subió\na {RAM:wNameBuffer}!",
["{RAM:wNameBuffer} hacked\naway with CUT!"] = "¡{RAM:wNameBuffer} cortó\ncon CORTE!",
["Gyaoo!"] = "¡Gyaoo!",
["Hi there!\nMay I help you?"] = "¡Hola!\n¿Puedo ayudarte?",
["SOMEONE'S PC"] = "EL PC DE ALGUIEN",
["PROF.OAK's PC"] = "EL PC DEL PROF.OAK",
["POKéDEX comp-\nletion is:\f{NUM:hDexRatingNumMonsSeen} POKéMON seen\n{NUM:hDexRatingNumMonsOwned} POKéMON owned\fPROF.OAK's\nRating:"] = "La POKéDEX está\nasí:\f{NUM:hDexRatingNumMonsSeen} POKéMON vistos\n{NUM:hDexRatingNumMonsOwned} POKéMON capturados\fNota del\nPROF.OAK:",
["We hope to see\nyou again!"] = "¡Esperamos verte\nde nuevo!",
["Welcome to our\nPOKéMON CENTER!"] = "¡Bienvenido a\nnuestro CENTRO\nPOKéMON!",
["Shall we heal your\nPOKéMON?"] = "¿Curamos a tus\nPOKéMON?",
["OK. We'll need\nyour POKéMON."] = "Bien. Necesitamos\ntus POKéMON.",
["Your POKéMON are\nfighting fit!"] = "¡Tus POKéMON están\nen plena forma!",
["Welcome to the\nCable Club!"] = "¡Bienvenido al Club\nde Cable!",
["We're making\npreparations.\vPlease wait."] = "Estamos preparando\ntodo.\vEspera un momento.",
["Please apply here.\fBefore opening\nthe link, we have\vto save the game."] = "Solicítalo aquí.\fAntes de abrir el\nlink hay que\vguardar la partida.",
["Please come\nagain!"] = "¡Vuelve pronto!",
["I like shorts!\nThey're comfy and\neasy to wear!"] = "¡Me gustan los\npantalones cortos!\n¡Son cómodos!",
["%s received\nthe %s!"] = "¡%s recibió\nel %s!",
["%s received\n%s!"] = "¡%s recibió\n%s!",
["REPEL's effect\nwore off."] = "El efecto del REPEL\nse ha pasado.",
["Go right ahead!"] = "¡Adelante!",
["You don't have the\nBOULDERBADGE yet!"] = "¡Aún no tienes la\nMEDALLA ROCA!",
["Oh! That is the\n{RAM}!"] = "¡Oh! ¡Eso es el\n{RAM}!",
["You don't have the\n{RAM} yet!"] = "¡Aún no tienes el\n{RAM}!",
["You need a\nBICYCLE for the\nCycling Road!"] = "¡Necesitas una\nBICICLETA para el\nCarril Bici!",
["The boulder fell\nthrough the hole!"] = "¡La roca cayó por\nel agujero!",
["PA: Ding-dong!\nTime's up!"] = "AV: ¡Ding-dong!\n¡Se acabó el tiempo!",
["PA: Your SAFARI\nGAME is over!"] = "AV: ¡Tu JUEGO\nSAFARI ha terminado!",
["PA: You're out of\nSAFARI BALLs!"] = "AV: ¡No te quedan\nSAFARI BALLs!",
["{PLAYER} got\n%s!"] = "¡{PLAYER} consiguió\n%s!",
["There's no more\nroom for POKéMON!\v%s was\vsent to POKéMON\vBOX %s on PC!"] = "¡No hay sitio para\nmás POKéMON!\v¡%s fue\venviado a la CAJA\vPOKéMON %s del PC!",
["contribution is not a table"] = "",
[" [%s %s.%s]"] = " [%s %s.%s]",
["Link battle needs\nthe same mods on\nboth games."] = "El combate link\nnecesita los mismos\nmods en los dos\njuegos.",
["Your %s can't\nbattle on the\nother game."] = "Tu %s no puede\nluchar en el otro\njuego.",
["Their %s isn't\nin this game.\n(%s)"] = "Su %s no está\nen este juego.\n(%s)",
["%s wants\nto battle!"] = "¡%s quiere\nluchar!",
["Link desync!\n%s differs.\fAre both games\nrunning the same\nmods?"] = "¡Link desincroni-\nzado!\n%s difiere.\f¿Están los dos\njuegos con los\nmismos mods?",
["%s ran from\nthe battle!"] = "¡%s huyó del\ncombate!",
["Items can't be\nused in a link\nbattle!"] = "¡No se pueden usar\nobjetos en un\ncombate link!",
["%s is out of\nPOKéMON!\f%s wins!"] = "¡%s no tiene\nPOKéMON!\f¡%s gana!",
["%s left the\nbattle."] = "%s dejó el\ncombate.",
["%s ran out of\ntime!"] = "¡%s se quedó\nsin tiempo!",
["Time's up! You\nforfeit the match."] = "¡Se acabó el tiempo!\nPierdes el combate.",
["%s's %s can't\nbattle on this\ngame."] = "El %s de %s\nno puede luchar en\neste juego.",
["%s's %s can't\nbattle on this\ngame.\n(%s)"] = "El %s de %s\nno puede luchar en\neste juego.\n(%s)",
["%s vs %s!"] = "¡%s contra %s!",
["Link error:\n%s"] = "Error de link:\n%s",
["Online play runs\nvanilla for both\nplayers.\fTurn off %s\nand restart?"] = "El juego en línea\nva sin mods para\nlos dos jugadores.\f¿Desactivar %s\ny reiniciar?",
["The link was\nbroken."] = "Se ha perdido el\nlink.",
["Link battle\ncan't start."] = "El combate link no\npuede empezar.",
["The trade stopped:\n%s."] = "El intercambio se\ndetuvo:\n%s.",
["The trade was\ncancelled."] = "El intercambio se\nha cancelado.",
["Trade completed!\f%s received\n%s!"] = "¡Intercambio hecho!\f¡%s recibió\n%s!",
["LINK CABLE (LAN)"] = "CABLE LINK (LAN)",
["ONLINE MATCH"] = "PARTIDA EN LINEA",
["TOURNAMENT"] = "TORNEO",
["HOST A GAME"] = "CREAR PARTIDA",
["JOIN A GAME"] = "UNIRSE A PARTIDA",
["UDP port %s"] = "Puerto UDP %s",
["HOST ONLINE"] = "CREAR EN LINEA",
["JOIN ONLINE"] = "UNIRSE EN LINEA",
["Tell your friend"] = "Dile a tu amigo",
["the code:"] = "el código:",
["Waiting for join..."] = "Esperando...",
["A: connect B: back"] = "A: conectar B: atrás",
["Calling..."] = "Llamando...",
["Friend joins at:"] = "Tu amigo entra en:",
["Port: %s"] = "Puerto: %s",
["TRADE"] = "INTERCAMBIO",
["BATTLE"] = "COMBATE",
["LEVELS:"] = "NIVELES:",
["A: continue B: back"] = "A: seguir B: atrás",
["Checking the"] = "Comprobando el",
["other game..."] = "otro juego...",
["Waiting for the"] = "Esperando a que",
["host to choose..."] = "el anfitrión elija...",
["A: trade anyway"] = "A: intercambiar igual",
["YOURS"] = "TUYO",
["THEIRS"] = "SUYO",
["X: not on theirs"] = "X: no en el suyo",
["A: trade B: cancel"] = "A: cambiar B: cancelar",
["Exchanging data..."] = "Intercambiando...",
["can't reach relay %s:%d\n(%s)"] = "",
["That code wasn't\nfound."] = "Ese código no se\nha encontrado.",
["That game already\nhas two players."] = "Esa partida ya\ntiene dos jugadores.",
["That code has\nexpired."] = "Ese código ha\ncaducado.",
["Couldn't join:\n%s"] = "No se pudo unir:\n%s",
["no answer from\n%s"] = "",
["That tournament\nhas already begun."] = "Ese torneo ya ha\nempezado.",
["Can't host:\nneed %d Pokemon\nLv %s-%s."] = "No puedes crearlo:\nnecesitas %d Pokemon\nNv %s-%s.",
["Couldn't host\nthat tournament."] = "No se pudo crear\nese torneo.",
["Your party needs\n%d Pokemon, Lv\n%s-%s."] = "Tu equipo necesita\n%d Pokemon, Nv\n%s-%s.",
["Couldn't join\nthat tournament."] = "No se pudo unir a\nese torneo.",
["Link error:\nversion mismatch\nwith opponent."] = "Error de link:\nversión distinta a\nla del rival.",
["The tournament\nconnection was\nlost."] = "Se perdió la\nconexión del torneo.",
["Can't watch this\nmatch."] = "No se puede ver\neste combate.",
["HOST"] = "CREAR",
["JOIN"] = "UNIRSE",
["START: create"] = "START: crear",
["A: join B: back"] = "A: unirse B: atrás",
["B: cancel"] = "B: cancelar",
["TOURNAMENT %s"] = "TORNEO %s",
["ROUND %d"] = "RONDA %d",
["%s (bye)"] = "%s (pasa)",
["%s%s vs %s%s"] = "%s%s contra %s%s",
["(organizing --"] = "(organizando --",
["not playing)"] = "no juega)",
["Waiting for"] = "Esperando a que",
["players to join:"] = "entren jugadores:",
["A: START B: cancel"] = "A: START B: cancelar",
["%s is the"] = "¡%s es el",
["champion!"] = "campeón!",
["A: continue"] = "A: continuar",
["{PLAYER} played the\nPOKé FLUTE."] = "{PLAYER} tocó la\nFLAUTA POKé.",
["Played the POKé\nFLUTE.\fNow, that's a\ncatchy tune!"] = "Tocaste la FLAUTA\nPOKé.\f¡Qué melodía tan\npegadiza!",
["%s played the\nPOKé FLUTE."] = "%s tocó la\nFLAUTA POKé.",
["All sleeping\nPOKéMON woke up!"] = "¡Todos los POKéMON\ndormidos despertaron!",
["%s's\nhits will never\nmiss!"] = "¡Los golpes de %s\nnunca fallarán!",
["The wild POKéMON\nran away!"] = "¡El POKéMON salvaje\nhuyó!",
["%s's PP\nwas restored!"] = "¡Los PP de %s\nse recuperaron!",
["%s's\nstatus returned\nto normal!"] = "¡El estado de %s\nvolvió a la\nnormalidad!",
["%s\nis revitalized!"] = "¡%s se ha\nrevitalizado!",
["%s\nis refusing!"] = "¡%s se\nniega!",
["%s's %s\nrose!"] = "¡El %s de %s\nsubió!",
["%s's PP\nincreased!"] = "¡Los PP de %s\naumentaron!",
["%s can't\nlearn that move!"] = "¡%s no puede\naprender ese\nmovimiento!",
["It knows that\nmove already!"] = "¡Ya conoce ese\nmovimiento!",
["Coin count:\n%d"] = "Fichas:\n%d",
["NO MODS INSTALLED"] = "NO HAY MODS",
["SAVE CURRENT AS.."] = "GUARDAR ACTUAL..",
["OPTIONS.."] = "OPCIONES..",
["PERMISSIONS.."] = "PERMISOS..",
["VIEW ERROR.."] = "VER ERROR..",
["BACK"] = "ATRAS",
["APPLY & RESTART"] = "APLICAR Y REINICIAR",
["DISCARD CHANGES"] = "DESCARTAR CAMBIOS",
["DATA & API ONLY"] = "SOLO DATOS Y API",
["DISABLE BOTH?"] = "DESACTIVAR AMBOS?",
["PROFILE NAME?"] = "NOMBRE DEL PERFIL?",
["RENAME?"] = "RENOMBRAR?",
["RESET DEFAULTS"] = "VALORES POR DEFECTO",
["NO CHANGES"] = "SIN CAMBIOS",
["A:OK"] = "A:OK",
["B:DONE (NO RESTART)"] = "B:LISTO (SIN REINICIAR)",
["MOD MANAGER"] = "GESTOR DE MODS",
["Choose a mod .zip"] = "Elige un .zip de mod",
["Choose a .sav save file"] = "Elige un archivo .sav",
["An update is available"] = "Hay una actualización",
["Name save slot"] = "Nombra la ranura",
["Enter to save - Esc to cancel - empty clears"] = "Enter para guardar - Esc para cancelar - vacío la borra",
["Add a mod index"] = "Añadir un índice de mods",
["Paste the index URL, or its owner/repo."] = "Pega la URL del índice, o su owner/repo.",
["Enter to add - Esc to cancel"] = "Enter para añadir - Esc para cancelar",
["Import a ROM to play"] = "Importa una ROM para jugar",
["RED"] = "ROJO",
["BLUE"] = "AZUL",
["YELLOW"] = "AMARILLO",
["FIND MODS"] = "BUSCAR MODS",
["%d of 3 ready"] = "%d de 3 listos",
["Or drop the .gb/.gbc file here."] = "O arrastra aquí el archivo .gb/.gbc.",
["ROM imported"] = "ROM importada",
["That ROM could not be imported."] = "No se pudo importar esa ROM.",
["Open folder"] = "Abrir carpeta",
["%d badges - %s - %d caught"] = "%d medallas - %s - %d capturados",
["%d of %d enabled"] = "%d de %d activados",
["Or drop a mod .zip onto the window."] = "O arrastra un .zip de mod a la ventana.",
["No mods installed - drop a mod .zip here to add one."] = "No hay mods - arrastra aquí un .zip para añadir uno.",
["Refreshed - %d mods listed"] = "Actualizado - %d mods listados",
["Added %s"] = "Añadido %s",
["Index removed"] = "Índice eliminado",
["Downloading %s..."] = "Descargando %s...",
["Installed %s %s"] = "Instalado %s %s",
["%d mods listed"] = "%d mods listados",
["%d of %d mods"] = "%d de %d mods",
["Mods here are listed, not reviewed - read the source and trust the author."] = "Los mods aquí se listan, no se revisan - lee el código y confía en el autor.",
["No mod index added"] = "No hay índice de mods",
["Add an index to browse mods. An index is a published list; paste its URL or its owner/repo."] = "Añade un índice para explorar mods. Un índice es una lista publicada; pega su URL o su owner/repo.",
["Search mods"] = "Buscar mods",
["This index lists no mods yet."] = "Este índice aún no lista mods.",
["No mods match that search."] = "Ningún mod coincide con esa búsqueda.",
}
+7
View File
@@ -0,0 +1,7 @@
-- Trainer class names
--
-- Trainer class names for Espanol.
return {
["OPP_FIX_YOUNGSTER"] = "",
}
+127
View File
@@ -0,0 +1,127 @@
-- spanish_ui: a translation of the game into Espanol.
--
-- Nothing here is translated yet. Every table under lang/ starts with
-- empty strings; fill one in and it takes effect on the next boot, and
-- anything still empty keeps rendering in English. That means a
-- half-finished translation is always playable, so you can ship early and
-- fill the long tail in later.
--
-- Read TRANSLATING.md before the first edit; the font is the part people
-- get wrong.
return function(mod)
-- mod:read is the supported way into your own directory; the catalogs are
-- plain Lua tables, so read and run them rather than require()ing them.
local function catalog(name)
local rel = "lang/" .. name .. ".lua"
local body = mod:read(rel)
if not body then return {} end
local chunk, err = loadstring(body, rel)
if not chunk then
mod.log:warn("%s has a syntax error: %s", rel, tostring(err))
return {}
end
local ok, table_ = pcall(chunk)
if not ok or type(table_) ~= "table" then
mod.log:warn("%s did not return a table: %s", rel, tostring(table_))
return {}
end
return table_
end
-- An empty value means "not translated yet", never "translate to blank".
local function each(name, apply)
local n = 0
for key, value in pairs(catalog(name)) do
if type(value) == "string" and value ~= "" then
apply(key, value)
n = n + 1
end
end
return n
end
-- ---- glyphs -------------------------------------------------------
-- Register the sheet BEFORE anything asks for a glyph on it. base is
-- the first code the page owns; 0x100 and up is free space above the
-- vanilla pages, so a new alphabet never collides with them.
for id, page in pairs(catalog("font")) do
mod.content.font:register(id, page)
end
-- charmap: which byte sequence draws which code
for seq, code in pairs(catalog("charmap")) do
mod.content.font:register("charmap:" .. seq, { seq = seq, code = code })
end
-- ---- text ---------------------------------------------------------
local counts = {}
counts.dialogue = each("dialogue", function(id, value)
mod.content.text:override(id, value)
end)
counts.strings = each("strings", function(source, value)
mod.content.strings:override(source, value)
end)
counts.species = each("species_names", function(id, value)
mod.content.pokemon:patch(id, { name = value })
end)
counts.moves = each("move_names", function(id, value)
mod.content.moves:patch(id, { name = value })
end)
counts.items = each("item_names", function(id, value)
mod.content.items:patch(id, { name = value })
end)
counts.trainers = each("trainer_names", function(id, value)
mod.content.trainers:patch(id, { name = value })
end)
counts.statuses = each("status_labels", function(id, value)
mod.content.statuses:patch(id, { label = value })
end)
-- ---- name entry ---------------------------------------------------
-- The naming screen's letter grid. Leave lang/naming.lua returning nil
-- to keep the English alphabet.
local grid = catalog("naming")
if grid.upper then
-- Only offer the accented cells when the running cartridge can actually
-- draw them. A Spanish ROM has Ñ and the accented vowels in its font
-- and the manifest maps them; an English one does not, and an
-- unmappable cell renders blank -- a naming screen with six empty keys
-- is worse than an English one. So check the charmap and fall back.
local function drawable(cells, ctx)
local font = ((ctx.game or {}).data or {}).font
local charmap = font and font.charmap
if not charmap then return false end
local have = {}
for _, entry in ipairs(charmap) do have[entry.seq] = true end
for _, row in ipairs(cells) do
for _, cell in ipairs(row) do
-- Only the non-ASCII cells are at risk; A-Z and punctuation are
-- on every page.
if cell:byte(1) and cell:byte(1) > 127 and not have[cell] then
return false
end
end
end
return true
end
local warned = false
mod.hooks:on("ui.naming.grid", function(base, ctx)
local want = ctx.lower and grid.lower or grid.upper
if not want then return base end
if not drawable(want, ctx) then
if not warned then
warned = true
mod.log:info("naming grid: this ROM has no accented glyphs, "
.. "keeping the English alphabet")
end
return base
end
return want
end)
end
mod.events:on("game.ready", function()
local total = 0
for _, n in pairs(counts) do total = total + n end
mod.log:info("Espanol: %d strings translated", total)
end)
end
+17
View File
@@ -0,0 +1,17 @@
{
"id": "spanish_ui",
"name": "Espanol (interfaz)",
"version": "0.1.0",
"api": 2,
"entry": "main.lua",
"profile": "content",
"game_version": ">=0.0.0-dev <1.0.0",
"category": "LANGUAGE",
"priority": 100,
"dependencies": [],
"optional_dependencies": [],
"conflicts": [],
"incompatible": [],
"experimental": false,
"description": "Spanish for the app's own settings and menus. The game's text comes from your ROM and is untouched, so an English cartridge stays an English adventure with Spanish menus."
}