mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-09-07 00:35:29 -05:00
Fix translated forme names
Official pokemon names look like: "Galarian Darmanitan (Zen Mode)" Which is hard to fit into tables and also don't work well because we already put them in parentheses in battle text. "Go! Darmy (Galarian Darmanitan (Zen Mode))!" So we no longer use parentheses in other languages, and also do a straightforward find/replace to make the names short. These aren't official but official names are insane and I don't think anyone really uses them.
This commit is contained in:
@@ -23,6 +23,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
ability: "Fähigkeit", // NEEDS QC
|
||||
abilities: "Fähigkeiten", // NEEDS QC
|
||||
hiddenability: "Versteckte Fähigkeit", // NEEDS QC
|
||||
team: "Team",
|
||||
teams: "Teams",
|
||||
teamslist: "Teamliste", // NEEDS QC
|
||||
|
||||
type: "Typ",
|
||||
types: "Typen",
|
||||
@@ -34,11 +37,16 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
egggroup: "Ei-Gruppe", // NEEDS QC
|
||||
egggroups: "Ei-Gruppen", // NEEDS QC
|
||||
tag: "Etikett", // NEEDS QC
|
||||
article: "Artikel", // NEEDS QC
|
||||
articles: "Artikel", // NEEDS QC
|
||||
tier: "Tier",
|
||||
tiers: "Tiers",
|
||||
color: "Farbe",
|
||||
form: "Form", // NEEDS QC
|
||||
forme: "Form", // NEEDS QC
|
||||
dexnum: "Pokédex-Nr.", // NEEDS QC
|
||||
gen: "Generation", // NEEDS QC
|
||||
generation: "Generation",
|
||||
gennum: "Gen [NUMBER]",
|
||||
evolution: "Entwicklung", // NEEDS QC
|
||||
preevolution: "Vorentwicklung", // NEEDS QC
|
||||
doesnotevolve: "Entwickelt sich nicht", // NEEDS QC
|
||||
@@ -64,6 +72,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
weak: "Schwäche", // NEEDS QC: unofficial
|
||||
resist: "Resistenz", // NEEDS QC: unofficial
|
||||
immune: "Immunität", // NEEDS QC: unofficial
|
||||
|
||||
nicknamespecies: "[NICKNAME] ([SPECIES])",
|
||||
speciesforme: "[FORME]-[SPECIES]", // NEEDS QC
|
||||
};
|
||||
|
||||
export const StatNames: { [id: string]: TranslationString } = {
|
||||
File diff suppressed because it is too large
Load Diff
5157
data/text/de/pokedex.ts
Normal file
5157
data/text/de/pokedex.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
ability: "Habilidad", // NEEDS QC
|
||||
abilities: "Habilidades", // NEEDS QC
|
||||
hiddenability: "Habilidad oculta", // NEEDS QC
|
||||
team: "Equipo", // NEEDS QC
|
||||
teams: "Equipos", // NEEDS QC
|
||||
teamslist: "Lista de equipos", // NEEDS QC
|
||||
|
||||
type: "Tipo",
|
||||
types: "Tipos",
|
||||
@@ -34,11 +37,16 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
egggroup: "Grupo Huevo", // NEEDS QC
|
||||
egggroups: "Grupos Huevo", // NEEDS QC
|
||||
tag: "Etiqueta", // NEEDS QC
|
||||
article: "Artículo", // NEEDS QC
|
||||
articles: "Artículos", // NEEDS QC
|
||||
tier: "Tier",
|
||||
tiers: "Tiers",
|
||||
color: "Color",
|
||||
form: "Forma", // NEEDS QC
|
||||
forme: "Forma", // NEEDS QC
|
||||
dexnum: "N.º Pokédex", // NEEDS QC
|
||||
gen: "Generación", // NEEDS QC
|
||||
generation: "Generación", // NEEDS QC
|
||||
gennum: "Gen [NUMBER]",
|
||||
evolution: "Evolución", // NEEDS QC
|
||||
preevolution: "Preevolución", // NEEDS QC
|
||||
doesnotevolve: "No evoluciona", // NEEDS QC
|
||||
@@ -64,6 +72,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
weak: "Debilidad", // NEEDS QC: unofficial
|
||||
resist: "Resistencia", // NEEDS QC: unofficial
|
||||
immune: "Inmunidad", // NEEDS QC: unofficial
|
||||
|
||||
nicknamespecies: "[NICKNAME] ([SPECIES])",
|
||||
speciesforme: "[SPECIES] [FORME]", // NEEDS QC
|
||||
};
|
||||
|
||||
export const StatNames: { [id: string]: TranslationString } = {
|
||||
File diff suppressed because it is too large
Load Diff
5076
data/text/es/pokedex.ts
Normal file
5076
data/text/es/pokedex.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
ability: "Talent", // NEEDS QC
|
||||
abilities: "Talents", // NEEDS QC
|
||||
hiddenability: "Talent caché", // NEEDS QC
|
||||
team: "Équipe", // NEEDS QC
|
||||
teams: "Équipes", // NEEDS QC
|
||||
teamslist: "Liste des équipes", // NEEDS QC
|
||||
|
||||
type: "Type",
|
||||
types: "Types",
|
||||
@@ -34,11 +37,16 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
egggroup: "Groupe d’Œuf", // NEEDS QC
|
||||
egggroups: "Groupes d’Œufs", // NEEDS QC
|
||||
tag: "Étiquette", // NEEDS QC
|
||||
article: "Article",
|
||||
articles: "Articles",
|
||||
tier: "Tier",
|
||||
tiers: "Tiers",
|
||||
color: "Couleur",
|
||||
form: "Forme", // NEEDS QC
|
||||
forme: "Forme", // NEEDS QC
|
||||
dexnum: "N° Pokédex", // NEEDS QC
|
||||
gen: "Génération", // NEEDS QC
|
||||
generation: "Génération", // NEEDS QC
|
||||
gennum: "Gen [NUMBER]",
|
||||
evolution: "Évolution", // NEEDS QC
|
||||
preevolution: "Pré-évolution", // NEEDS QC
|
||||
doesnotevolve: "N'évolue pas", // NEEDS QC
|
||||
@@ -64,6 +72,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
weak: "Faiblesse", // NEEDS QC: unofficial
|
||||
resist: "Résistance", // NEEDS QC: unofficial
|
||||
immune: "Immunité", // NEEDS QC: unofficial
|
||||
|
||||
nicknamespecies: "[NICKNAME] ([SPECIES])",
|
||||
speciesforme: "[SPECIES] [FORME]", // NEEDS QC
|
||||
};
|
||||
|
||||
export const StatNames: { [id: string]: TranslationString } = {
|
||||
File diff suppressed because it is too large
Load Diff
5157
data/text/fr/pokedex.ts
Normal file
5157
data/text/fr/pokedex.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
ability: "Abilità", // NEEDS QC
|
||||
abilities: "Abilità", // NEEDS QC
|
||||
hiddenability: "Abilità speciale", // NEEDS QC
|
||||
team: "Squadra", // NEEDS QC
|
||||
teams: "Squadre", // NEEDS QC
|
||||
teamslist: "Elenco squadre", // NEEDS QC
|
||||
|
||||
type: "Tipo",
|
||||
types: "Tipi",
|
||||
@@ -34,11 +37,16 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
egggroup: "Gruppo Uova", // NEEDS QC
|
||||
egggroups: "Gruppi Uova", // NEEDS QC
|
||||
tag: "Etichetta", // NEEDS QC
|
||||
article: "Articolo", // NEEDS QC
|
||||
articles: "Articoli", // NEEDS QC
|
||||
tier: "Tier",
|
||||
tiers: "Tier", // NEEDS QC
|
||||
color: "Colore",
|
||||
form: "Forma", // NEEDS QC
|
||||
forme: "Forma", // NEEDS QC
|
||||
dexnum: "N. Pokédex", // NEEDS QC
|
||||
gen: "Generazione", // NEEDS QC
|
||||
generation: "Generazione", // NEEDS QC
|
||||
gennum: "Gen [NUMBER]",
|
||||
evolution: "Evoluzione", // NEEDS QC
|
||||
preevolution: "Preevoluzione", // NEEDS QC
|
||||
doesnotevolve: "Non si evolve", // NEEDS QC
|
||||
@@ -64,6 +72,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
weak: "Debolezza", // NEEDS QC: unofficial
|
||||
resist: "Resistenza", // NEEDS QC: unofficial
|
||||
immune: "Immunità", // NEEDS QC: unofficial
|
||||
|
||||
nicknamespecies: "[NICKNAME] ([SPECIES])",
|
||||
speciesforme: "[SPECIES] [FORME]", // NEEDS QC
|
||||
};
|
||||
|
||||
export const StatNames: { [id: string]: TranslationString } = {
|
||||
File diff suppressed because it is too large
Load Diff
5079
data/text/it/pokedex.ts
Normal file
5079
data/text/it/pokedex.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
ability: "特性", // NEEDS QC
|
||||
abilities: "特性", // NEEDS QC
|
||||
hiddenability: "隠れ特性", // NEEDS QC
|
||||
team: "チーム", // NEEDS QC
|
||||
teams: "チーム", // NEEDS QC
|
||||
teamslist: "チーム一覧", // NEEDS QC
|
||||
|
||||
type: "タイプ",
|
||||
types: "タイプ",
|
||||
@@ -34,11 +37,16 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
egggroup: "タマゴグループ", // NEEDS QC
|
||||
egggroups: "タマゴグループ", // NEEDS QC
|
||||
tag: "タグ", // NEEDS QC
|
||||
article: "記事", // NEEDS QC
|
||||
articles: "記事", // NEEDS QC
|
||||
tier: "ティア", // NEEDS QC
|
||||
tiers: "ティア", // NEEDS QC
|
||||
color: "色",
|
||||
form: "すがた", // NEEDS QC
|
||||
forme: "フォルム", // NEEDS QC
|
||||
dexnum: "図鑑No.", // NEEDS QC
|
||||
gen: "世代", // NEEDS QC
|
||||
generation: "世代", // NEEDS QC
|
||||
gennum: "[NUMBER]世代", // NEEDS QC
|
||||
evolution: "進化", // NEEDS QC
|
||||
preevolution: "進化前", // NEEDS QC
|
||||
doesnotevolve: "進化しない", // NEEDS QC
|
||||
@@ -64,6 +72,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
weak: "弱点", // NEEDS QC: unofficial
|
||||
resist: "半減", // NEEDS QC: unofficial
|
||||
immune: "無効", // NEEDS QC: unofficial
|
||||
|
||||
nicknamespecies: "[NICKNAME]([SPECIES])", // NEEDS QC
|
||||
speciesforme: "[SPECIES]・[FORME]", // NEEDS QC
|
||||
};
|
||||
|
||||
export const StatNames: { [id: string]: TranslationString } = {
|
||||
File diff suppressed because it is too large
Load Diff
5181
data/text/ja/pokedex.ts
Normal file
5181
data/text/ja/pokedex.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
ability: "특성", // NEEDS QC
|
||||
abilities: "특성", // NEEDS QC
|
||||
hiddenability: "숨겨진 특성", // NEEDS QC
|
||||
team: "팀", // NEEDS QC
|
||||
teams: "팀", // NEEDS QC
|
||||
teamslist: "팀 목록", // NEEDS QC
|
||||
|
||||
type: "타입",
|
||||
types: "타입",
|
||||
@@ -34,11 +37,16 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
egggroup: "알그룹", // NEEDS QC
|
||||
egggroups: "알그룹", // NEEDS QC
|
||||
tag: "태그", // NEEDS QC
|
||||
article: "기사", // NEEDS QC
|
||||
articles: "기사", // NEEDS QC
|
||||
tier: "티어", // NEEDS QC
|
||||
tiers: "티어", // NEEDS QC
|
||||
color: "색",
|
||||
form: "모습", // NEEDS QC
|
||||
forme: "폼", // NEEDS QC
|
||||
dexnum: "도감 No.", // NEEDS QC
|
||||
gen: "세대", // NEEDS QC
|
||||
generation: "세대", // NEEDS QC
|
||||
gennum: "[NUMBER]세대", // NEEDS QC
|
||||
evolution: "진화", // NEEDS QC
|
||||
preevolution: "진화 전", // NEEDS QC
|
||||
doesnotevolve: "진화하지 않음", // NEEDS QC
|
||||
@@ -64,6 +72,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
weak: "약점", // NEEDS QC: unofficial
|
||||
resist: "반감", // NEEDS QC: unofficial
|
||||
immune: "무효", // NEEDS QC: unofficial
|
||||
|
||||
nicknamespecies: "[NICKNAME]([SPECIES])", // NEEDS QC
|
||||
speciesforme: "[SPECIES]-[FORME]",
|
||||
};
|
||||
|
||||
export const StatNames: { [id: string]: TranslationString } = {
|
||||
File diff suppressed because it is too large
Load Diff
5181
data/text/ko/pokedex.ts
Normal file
5181
data/text/ko/pokedex.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
ability: "Ability",
|
||||
abilities: "Abilities",
|
||||
hiddenability: "Hidden Ability",
|
||||
team: "Team",
|
||||
teams: "Teams",
|
||||
teamslist: "Teams List",
|
||||
|
||||
type: "Type",
|
||||
types: "Types",
|
||||
@@ -37,11 +40,16 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
egggroup: "Egg Group",
|
||||
egggroups: "Egg Groups",
|
||||
tag: "Tag",
|
||||
article: "Article",
|
||||
articles: "Articles",
|
||||
tier: "Tier",
|
||||
tiers: "Tiers",
|
||||
color: "Color",
|
||||
form: "Form",
|
||||
forme: "Forme",
|
||||
dexnum: "Dex#",
|
||||
gen: "Gen",
|
||||
generation: "Generation",
|
||||
gennum: "Gen [NUMBER]",
|
||||
evolution: "Evolution",
|
||||
preevolution: "Pre-Evolution",
|
||||
doesnotevolve: "Does Not Evolve",
|
||||
@@ -67,6 +75,11 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
weak: "Weak",
|
||||
resist: "Resist",
|
||||
immune: "Immune",
|
||||
|
||||
// used in switch-in messages in battles
|
||||
nicknamespecies: "[NICKNAME] ([SPECIES])",
|
||||
// this one's not used in code; just a reference for how pokedex.ts should be filled
|
||||
speciesforme: "[SPECIES]-[FORME]",
|
||||
};
|
||||
|
||||
export const StatNames: { [id: string]: TranslationString } = {
|
||||
File diff suppressed because it is too large
Load Diff
5218
data/text/pokedex.ts
Normal file
5218
data/text/pokedex.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
ability: "特性", // NEEDS QC
|
||||
abilities: "特性", // NEEDS QC
|
||||
hiddenability: "隐藏特性", // NEEDS QC
|
||||
team: "队伍", // NEEDS QC
|
||||
teams: "队伍", // NEEDS QC
|
||||
teamslist: "队伍列表", // NEEDS QC
|
||||
|
||||
type: "属性",
|
||||
types: "属性",
|
||||
@@ -34,11 +37,16 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
egggroup: "蛋组", // NEEDS QC
|
||||
egggroups: "蛋组", // NEEDS QC
|
||||
tag: "标签", // NEEDS QC
|
||||
article: "文章", // NEEDS QC
|
||||
articles: "文章", // NEEDS QC
|
||||
tier: "级别", // NEEDS QC
|
||||
tiers: "分级", // NEEDS QC
|
||||
color: "颜色",
|
||||
form: "样子", // NEEDS QC
|
||||
forme: "形态", // NEEDS QC
|
||||
dexnum: "图鉴No.", // NEEDS QC
|
||||
gen: "世代", // NEEDS QC
|
||||
generation: "世代", // NEEDS QC
|
||||
gennum: "[NUMBER]代", // NEEDS QC
|
||||
evolution: "进化", // NEEDS QC
|
||||
preevolution: "进化前", // NEEDS QC
|
||||
doesnotevolve: "不进化", // NEEDS QC
|
||||
@@ -64,6 +72,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
weak: "弱点", // NEEDS QC: unofficial
|
||||
resist: "抵抗", // NEEDS QC: unofficial
|
||||
immune: "免疫", // NEEDS QC: unofficial
|
||||
|
||||
nicknamespecies: "[NICKNAME]([SPECIES])", // NEEDS QC
|
||||
speciesforme: "[SPECIES]-[FORME]",
|
||||
};
|
||||
|
||||
export const StatNames: { [id: string]: TranslationString } = {
|
||||
File diff suppressed because it is too large
Load Diff
5181
data/text/zh-cn/pokedex.ts
Normal file
5181
data/text/zh-cn/pokedex.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
ability: "特性", // NEEDS QC
|
||||
abilities: "特性", // NEEDS QC
|
||||
hiddenability: "隱藏特性", // NEEDS QC
|
||||
team: "隊伍", // NEEDS QC
|
||||
teams: "隊伍", // NEEDS QC
|
||||
teamslist: "隊伍列表", // NEEDS QC
|
||||
|
||||
type: "屬性",
|
||||
types: "屬性",
|
||||
@@ -34,11 +37,16 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
egggroup: "蛋群", // NEEDS QC
|
||||
egggroups: "蛋群", // NEEDS QC
|
||||
tag: "標籤", // NEEDS QC
|
||||
article: "文章", // NEEDS QC
|
||||
articles: "文章", // NEEDS QC
|
||||
tier: "級別", // NEEDS QC
|
||||
tiers: "分級", // NEEDS QC
|
||||
color: "顏色",
|
||||
form: "樣子", // NEEDS QC
|
||||
forme: "形態", // NEEDS QC
|
||||
dexnum: "圖鑑No.", // NEEDS QC
|
||||
gen: "世代", // NEEDS QC
|
||||
generation: "世代", // NEEDS QC
|
||||
gennum: "[NUMBER]代", // NEEDS QC
|
||||
evolution: "進化", // NEEDS QC
|
||||
preevolution: "進化前", // NEEDS QC
|
||||
doesnotevolve: "不進化", // NEEDS QC
|
||||
@@ -64,6 +72,9 @@ export const TermNames: { [id: string]: TranslationString } = {
|
||||
weak: "弱點", // NEEDS QC: unofficial
|
||||
resist: "抵抗", // NEEDS QC: unofficial
|
||||
immune: "免疫", // NEEDS QC: unofficial
|
||||
|
||||
nicknamespecies: "[NICKNAME]([SPECIES])", // NEEDS QC
|
||||
speciesforme: "[SPECIES]-[FORME]",
|
||||
};
|
||||
|
||||
export const StatNames: { [id: string]: TranslationString } = {
|
||||
File diff suppressed because it is too large
Load Diff
5181
data/text/zh-tw/pokedex.ts
Normal file
5181
data/text/zh-tw/pokedex.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -664,7 +664,7 @@ export const commands: Chat.ChatCommands = {
|
||||
}
|
||||
details = {
|
||||
[TL.term.dexnum]: String(pokemon.num),
|
||||
[TL.term.gen]: String(pokemon.gen) || 'CAP',
|
||||
[TL.term.generation]: String(pokemon.gen) || 'CAP',
|
||||
[TL.term.height]: TL.term.numm.replace('[NUMBER]', `${pokemon.heightm}`),
|
||||
};
|
||||
details[TL.term.weight] = `${TL.term.numkg.replace('[NUMBER]', `${pokemon.weighthg / 10}`)} <em>(${weighthit} BP)</em>`;
|
||||
@@ -726,7 +726,7 @@ export const commands: Chat.ChatCommands = {
|
||||
if (showDetails) {
|
||||
description = dex.text.get(item, textLanguage).desc;
|
||||
details = {
|
||||
[TL.term.gen]: String(item.gen),
|
||||
[TL.term.generation]: String(item.gen),
|
||||
};
|
||||
|
||||
if (dex.gen >= 4) {
|
||||
@@ -764,7 +764,7 @@ export const commands: Chat.ChatCommands = {
|
||||
description = dex.text.get(move, textLanguage).desc;
|
||||
details = {
|
||||
[TL.tag.priority]: String(move.priority),
|
||||
[TL.term.gen]: String(move.gen) || 'CAP',
|
||||
[TL.term.generation]: String(move.gen) || 'CAP',
|
||||
};
|
||||
|
||||
const pastGensOnly = (move.isNonstandard === "Past" && dex.gen >= 8);
|
||||
@@ -856,7 +856,7 @@ export const commands: Chat.ChatCommands = {
|
||||
if (showDetails) {
|
||||
description = dex.text.get(ability, textLanguage).desc;
|
||||
details = {
|
||||
[TL.term.gen]: String(ability.gen) || 'CAP',
|
||||
[TL.term.generation]: String(ability.gen) || 'CAP',
|
||||
};
|
||||
if (ability.flags['cantsuppress']) details["✓ Not affected by Gastro Acid"] = "";
|
||||
if (ability.flags['breakable']) details["✓ Ignored by Mold Breaker"] = "";
|
||||
|
||||
@@ -318,6 +318,9 @@ export type Translator = {
|
||||
color: { [id: string]: string },
|
||||
status: { [id: string]: string },
|
||||
target: { [id: string]: string },
|
||||
stat: { [id: string]: string },
|
||||
statShort: { [id: string]: string },
|
||||
statMedium: { [id: string]: string },
|
||||
};
|
||||
|
||||
// These classes need to be declared here because they aren't hoisted
|
||||
@@ -1829,6 +1832,9 @@ export const Chat = new class {
|
||||
color: text.ColorNames,
|
||||
status: text.StatusNames,
|
||||
target: text.TargetNames,
|
||||
stat: text.StatNames,
|
||||
statShort: text.StatShortNames,
|
||||
statMedium: text.StatMediumNames,
|
||||
}
|
||||
);
|
||||
this.translators.set(lang, translator);
|
||||
|
||||
@@ -41,7 +41,8 @@ export function assignMissingFields(self: AnyObject, data: AnyObject) {
|
||||
}
|
||||
}
|
||||
|
||||
export type EffectText = ResolvedAbilityText | ResolvedItemText | ResolvedMoveText | ResolvedNameText;
|
||||
export type EffectText =
|
||||
ResolvedAbilityText | ResolvedItemText | ResolvedMoveText | ResolvedNameText | ResolvedSpeciesText;
|
||||
export type TextLanguage = 'en' | 'en-afd' | 'de' | 'es' | 'fr' | 'it' | 'ja' | 'ko' | 'zh-cn' | 'zh-tw';
|
||||
|
||||
export const OTHER_NAME_TABLES = [
|
||||
@@ -71,7 +72,8 @@ export class DexText {
|
||||
get(effect: Item, lang?: TextLanguage): ResolvedItemText;
|
||||
get(effect: Ability, lang?: TextLanguage): ResolvedAbilityText;
|
||||
get(effect: Move, lang?: TextLanguage): ResolvedMoveText;
|
||||
get(effect: Species | Nature | TypeInfo | TagData, lang?: TextLanguage): ResolvedNameText;
|
||||
get(effect: Species, lang?: TextLanguage): ResolvedSpeciesText;
|
||||
get(effect: Nature | TypeInfo | TagData, lang?: TextLanguage): ResolvedNameText;
|
||||
get(effect: TextEffect, lang?: TextLanguage): EffectText;
|
||||
get(
|
||||
effect: TextEffect, lang: TextLanguage = 'en'
|
||||
@@ -82,8 +84,12 @@ export class DexText {
|
||||
let table: EffectTextTable;
|
||||
switch (effect.effectType) {
|
||||
case 'Pokemon': {
|
||||
const name = this.dex.loadTextData(lang).PokedexNames[effect.id] || effect.name;
|
||||
return { name };
|
||||
const species = effect;
|
||||
return this.dex.loadTextData(lang).Pokedex[effect.id] || {
|
||||
name: species.name,
|
||||
baseSpecies: species.baseSpecies,
|
||||
...(species.forme ? { forme: species.forme } : {}),
|
||||
};
|
||||
}
|
||||
case 'Nature': return { name: this.otherName('NatureNames', effect.name, lang) };
|
||||
case 'Type': case 'EffectType': return { name: this.otherName('TypeNames', effect.name, lang) };
|
||||
|
||||
50
sim/dex.ts
50
sim/dex.ts
@@ -89,14 +89,14 @@ interface RawTextTableData extends Record<OtherNameTable, DexTable<TranslationSt
|
||||
Abilities: DexTable<AbilityText>;
|
||||
Items: DexTable<ItemText>;
|
||||
Moves: DexTable<MoveText>;
|
||||
PokedexNames: DexTable<TranslationString>;
|
||||
Pokedex: DexTable<SpeciesText>;
|
||||
Default: DexTable<DefaultText>;
|
||||
}
|
||||
interface TextTableData extends Record<OtherNameTable, DexTable<string>> {
|
||||
Abilities: DexTable<ResolvedAbilityText>;
|
||||
Items: DexTable<ResolvedItemText>;
|
||||
Moves: DexTable<ResolvedMoveText>;
|
||||
PokedexNames: DexTable<string>;
|
||||
Pokedex: DexTable<ResolvedSpeciesText>;
|
||||
Default: DexTable<DefaultText>;
|
||||
}
|
||||
|
||||
@@ -518,12 +518,12 @@ export class ModdedDex {
|
||||
const englishData = this.loadRawTextData();
|
||||
const localizedData = lang === 'en' ? englishData : this.loadRawTextData(lang);
|
||||
return (dexes['base'].textCache[cacheKey] = {
|
||||
PokedexNames: this.resolveNameTable(englishData.PokedexNames, localizedData.PokedexNames),
|
||||
...this.resolveOtherNameTables(englishData, localizedData),
|
||||
Pokedex: this.resolvePokedexTable(englishData.Pokedex, localizedData.Pokedex),
|
||||
Moves: this.resolveTextTable(englishData.Moves, localizedData.Moves),
|
||||
Abilities: this.resolveTextTable(englishData.Abilities, localizedData.Abilities),
|
||||
Items: this.resolveTextTable(englishData.Items, localizedData.Items),
|
||||
Default: localizedData.Default,
|
||||
...this.resolveOtherNameTables(englishData, localizedData),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -533,12 +533,12 @@ export class ModdedDex {
|
||||
const langDir = lang === 'en' ? `` : `${lang}/`;
|
||||
const optional = lang !== 'en';
|
||||
const otherNameTables = Object.fromEntries(OTHER_NAME_TABLES.map(table => [
|
||||
table, this.loadTextFile(`${langDir}other-names`, table, optional) || {},
|
||||
table, this.loadTextFile(`${langDir}names`, table, optional) || {},
|
||||
])) as Pick<RawTextTableData, OtherNameTable>;
|
||||
const data: RawTextTableData = {
|
||||
PokedexNames: this.loadTextFile(
|
||||
`${langDir}pokedex-names`, 'PokedexNames', optional
|
||||
) as Record<string, TranslationString>,
|
||||
Pokedex: this.loadTextFile(
|
||||
`${langDir}pokedex`, 'PokedexText', optional
|
||||
) as DexTable<SpeciesText>,
|
||||
...otherNameTables,
|
||||
Moves: this.loadTextFile(`${langDir}moves`, 'MovesText', optional) as DexTable<MoveText>,
|
||||
Abilities: this.loadTextFile(`${langDir}abilities`, 'AbilitiesText', optional) as DexTable<AbilityText>,
|
||||
@@ -549,6 +549,40 @@ export class ModdedDex {
|
||||
return (dexes['base'].rawTextCache[lang] = data);
|
||||
}
|
||||
|
||||
private resolvePokedexTable(
|
||||
englishTable: DexTable<SpeciesText>, localizedTable: DexTable<SpeciesText>
|
||||
): DexTable<ResolvedSpeciesText> {
|
||||
const FIELDS = ['name', 'baseSpecies', 'forme', 'grammar'] as const;
|
||||
const merge = (english?: SpeciesText, localized?: SpeciesText) => {
|
||||
const entry: Partial<ResolvedSpeciesText> = {};
|
||||
for (const field of FIELDS) {
|
||||
const value = localized?.[field] ?? english?.[field];
|
||||
if (value) entry[field] = value;
|
||||
}
|
||||
return entry;
|
||||
};
|
||||
const mergedTable: DexTable<Partial<ResolvedSpeciesText>> = {};
|
||||
for (const id in englishTable) {
|
||||
mergedTable[id] = merge(englishTable[id], localizedTable[id]);
|
||||
}
|
||||
for (const id in localizedTable) {
|
||||
if (!(id in englishTable)) mergedTable[id] = merge(undefined, localizedTable[id]);
|
||||
}
|
||||
|
||||
const table: DexTable<ResolvedSpeciesText> = {};
|
||||
for (const id in mergedTable) {
|
||||
const entry = mergedTable[id];
|
||||
const species = this.species.get(id);
|
||||
const baseEntry = mergedTable[toID(species.baseSpecies)];
|
||||
table[id] = {
|
||||
...entry,
|
||||
name: entry.name || species.name,
|
||||
baseSpecies: baseEntry?.baseSpecies ?? baseEntry?.name ?? species.baseSpecies,
|
||||
};
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
private resolveNameTable(
|
||||
englishTable: Record<string, TranslationString>, localizedTable: Record<string, TranslationString>
|
||||
): Record<string, string> {
|
||||
|
||||
@@ -487,6 +487,22 @@ type AbilityText = TextFile<ConditionTextData & {
|
||||
}>;
|
||||
type MoveText = TextFile<MoveTextData>;
|
||||
type ItemText = TextFile<ConditionTextData>;
|
||||
interface SpeciesText {
|
||||
/**
|
||||
* Full species + short forme name - "Wormadam-Plant"
|
||||
*
|
||||
* Not the actual full official name, but the one Showdown uses that's
|
||||
* reasonably concise and mostly fits into teambuilder. Includes formes for
|
||||
* many but not all base formes. Can't contain parentheses because it's
|
||||
* designed to be used like "Go! Planty (Wormadam-Plant)".
|
||||
*/
|
||||
name?: TranslationString;
|
||||
/** Species name by itself, without forme - "Wormadam" */
|
||||
baseSpecies?: TranslationString;
|
||||
/** Official forme name - "Plant Cloak" */
|
||||
forme?: TranslationString;
|
||||
grammar?: TranslationString;
|
||||
}
|
||||
type DefaultText = AnyObject;
|
||||
|
||||
type ResolvedText<T extends BasicTextData> = T & { name: string, desc: string, shortDesc: string };
|
||||
@@ -494,6 +510,7 @@ type ResolvedAbilityText = ResolvedText<AbilityText>;
|
||||
type ResolvedItemText = ResolvedText<ItemText>;
|
||||
type ResolvedMoveText = ResolvedText<MoveText>;
|
||||
type ResolvedNameText = { name: string };
|
||||
type ResolvedSpeciesText = { name: string, baseSpecies: string, forme?: string, grammar?: string };
|
||||
|
||||
declare namespace RandomTeamsTypes {
|
||||
export interface TeamDetails {
|
||||
|
||||
@@ -27,6 +27,23 @@ describe('Chat', () => {
|
||||
assert.equal(TL(Dex.items.get('Leftovers')), 'たべのこし');
|
||||
assert.equal(TL(Dex.moves.get('Tackle')), 'たいあたり');
|
||||
assert.equal(TL(Dex.species.get('Pikachu')), 'ピカチュウ');
|
||||
const text = Dex.loadTextData('ja');
|
||||
for (const [property, table] of Object.entries({
|
||||
term: 'TermNames',
|
||||
type: 'TypeNames',
|
||||
nature: 'NatureNames',
|
||||
gender: 'GenderNames',
|
||||
egggroup: 'EggGroupNames',
|
||||
tag: 'TagNames',
|
||||
color: 'ColorNames',
|
||||
status: 'StatusNames',
|
||||
target: 'TargetNames',
|
||||
stat: 'StatNames',
|
||||
statShort: 'StatShortNames',
|
||||
statMedium: 'StatMediumNames',
|
||||
})) {
|
||||
assert.equal(TL[property], text[table]);
|
||||
}
|
||||
});
|
||||
|
||||
it('should localize data HTML', () => {
|
||||
|
||||
@@ -126,6 +126,59 @@ describe('Dex data', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should have unique Pokedex names and formes within each species', () => {
|
||||
const languages = ['en', ...fs.readdirSync(`${Dex.dataDir}/text`, { withFileTypes: true })
|
||||
.filter(entry => entry.isDirectory())
|
||||
.map(entry => entry.name)];
|
||||
for (const language of languages) {
|
||||
const text = Dex.loadTextData(language).Pokedex;
|
||||
const speciesValues = new Map();
|
||||
for (const id in text) {
|
||||
const entry = text[id];
|
||||
const species = Dex.species.get(id);
|
||||
let values = speciesValues.get(species.baseSpecies);
|
||||
if (!values) {
|
||||
values = { name: new Map(), forme: new Map() };
|
||||
speciesValues.set(species.baseSpecies, values);
|
||||
}
|
||||
for (const field of ['name', 'forme']) {
|
||||
const value = entry[field];
|
||||
if (typeof value !== 'string') continue;
|
||||
const duplicate = values[field].get(value);
|
||||
assert.equal(
|
||||
duplicate, undefined,
|
||||
`${language} ${species.baseSpecies} formes ${duplicate} and ${id} have the same ${field} "${value}"`
|
||||
);
|
||||
values[field].set(value, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should only have necessary baseSpecies text on base species entries', () => {
|
||||
const languages = ['en', ...fs.readdirSync(`${Dex.dataDir}/text`, { withFileTypes: true })
|
||||
.filter(entry => entry.isDirectory())
|
||||
.map(entry => entry.name)];
|
||||
for (const language of languages) {
|
||||
const path = language === 'en' ? 'pokedex' : `${language}/pokedex`;
|
||||
const rawText = Dex.loadTextFile(path, 'PokedexText', language !== 'en');
|
||||
for (const id in rawText) {
|
||||
const entry = rawText[id];
|
||||
const species = Dex.species.get(id);
|
||||
if (entry.baseSpecies !== undefined) {
|
||||
assert.equal(
|
||||
species.name, species.baseSpecies,
|
||||
`${language} ${id} has baseSpecies text, but is not a base species entry`
|
||||
);
|
||||
assert.notEqual(
|
||||
entry.baseSpecies, entry.name,
|
||||
`${language} ${id} should omit baseSpecies text when it is the same as its name`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should have valid Items entries', () => {
|
||||
const Items = Dex.data.Items;
|
||||
for (const itemid in Items) {
|
||||
|
||||
@@ -91,8 +91,14 @@ describe('Dex#getMove', () => {
|
||||
|
||||
describe('DexText#get', () => {
|
||||
it(`should translate species, items, abilities, and moves`, () => {
|
||||
assert.deepEqual(Dex.text.get(Dex.species.get('Pikachu'), 'ja'), { name: 'ピカチュウ' });
|
||||
assert.equal(Dex.loadTextData('ja').PokedexNames.pikachu, 'ピカチュウ');
|
||||
const pikachuText = Dex.loadTextData('ja').Pokedex.pikachu;
|
||||
assert.deepEqual(pikachuText, {
|
||||
name: 'ピカチュウ', baseSpecies: 'ピカチュウ',
|
||||
});
|
||||
assert.equal(Dex.text.get(Dex.species.get('Pikachu'), 'ja'), pikachuText);
|
||||
assert.deepEqual(Dex.loadTextData('ja').Pokedex.unownb, {
|
||||
name: 'アンノーン-B', baseSpecies: 'アンノーン', forme: 'B',
|
||||
});
|
||||
assert.equal(Dex.text.get(Dex.items.get('Leftovers'), 'ja').name, 'たべのこし');
|
||||
assert.equal(Dex.text.get(Dex.abilities.get('Levitate'), 'ja').name, 'ふゆう');
|
||||
assert.equal(Dex.text.get(Dex.moves.get('Tackle'), 'ja').name, 'たいあたり');
|
||||
|
||||
Reference in New Issue
Block a user