pogo-data-generator
Version:
Pokemon GO project data generator
899 lines (898 loc) • 44.8 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const pogo_protos_1 = require("@na-ji/pogo-protos");
const Masterfile_1 = __importDefault(require("./Masterfile"));
class Translations extends Masterfile_1.default {
options;
translationApkUrl;
translationRemoteUrl;
rawTranslations;
manualTranslations;
parsedTranslations;
codes;
masterfile;
generics;
reference;
enFallback;
collator;
constructor(options, translationApkUrl = 'https://raw.githubusercontent.com/sora10pls/holoholo-text/refs/heads/main/Release/English/en-us_raw.json', translationRemoteUrl = 'https://raw.githubusercontent.com/sora10pls/holoholo-text/refs/heads/main/Remote/English/en-us_formatted.txt') {
super();
this.collator = new Intl.Collator(undefined, {
numeric: true,
sensitivity: 'base',
});
this.options = options;
this.translationApkUrl = translationApkUrl;
this.translationRemoteUrl = translationRemoteUrl;
this.rawTranslations = {};
this.manualTranslations = {};
this.parsedTranslations = {};
this.masterfile = {};
this.codes = {
de: { name: 'German', code: 'de-de' },
en: { name: 'English', code: 'en-us' },
es: { name: 'Spanish', code: 'es-es' },
'es-mx': { name: 'Latin American Spanish', code: 'es-mx' },
fr: { name: 'French', code: 'fr-fr' },
hi: { name: 'Hindi', code: 'hi-in' },
id: { name: 'Indonesian', code: 'id-id' },
it: { name: 'Italian', code: 'it-it' },
ja: { name: 'Japanese', code: 'ja-jp' },
ko: { name: 'Korean', code: 'ko-kr' },
'pt-br': { name: 'Brazilian Portuguese', code: 'pt-br' },
ru: { name: 'Russian', code: 'ru-ru' },
th: { name: 'Thai', code: 'th-th' },
'zh-tw': { name: 'Traditional Chinese', code: 'zh-tw' },
tr: { name: 'Turkish', code: 'tr-tr' },
};
this.generics = {
de: {
none: 'Keiner',
normal: 'Normal',
unknown: 'Unbekannt',
substitute: 'Ersatz',
},
en: {
none: 'None',
normal: 'Normal',
unknown: 'Unknown',
substitute: 'Substitute',
},
es: {
none: 'Ninguno',
normal: 'Normal',
unknown: 'Desconocido',
substitute: 'Substitución',
},
'es-mx': {
none: 'Ninguno',
normal: 'Normal',
unknown: 'Desconocido',
substitute: 'Sustituto',
},
fr: {
none: 'Aucun',
normal: 'Normal',
unknown: 'Inconnu',
substitute: 'Substitution',
},
hi: {
none: 'कोई नहीं',
normal: 'सामान्य',
unknown: 'अज्ञात',
substitute: 'बदलना',
},
id: {
none: 'Tidak ada',
normal: 'Normal',
unknown: 'Tidak diketahui',
substitute: 'Pengganti',
},
it: {
none: 'Nessuno',
normal: 'Normale',
unknown: 'Sconosciuto',
substitute: 'Sostituzione',
},
ja: {
none: 'なし',
normal: '通常',
unknown: '不明',
substitute: '代替',
},
ko: {
none: '없음',
normal: '보통',
unknown: '알 수 없음',
substitute: '대체',
},
'pt-br': {
none: 'Nenhum',
normal: 'Normal',
unknown: 'Desconhecido',
substitute: 'Substituição',
},
ru: {
none: 'Нет',
normal: 'Нормальный',
unknown: 'Неизвестный',
substitute: 'Замена',
},
th: {
none: 'ไม่มี',
normal: 'ปกติ',
unknown: 'ผู้เข้าถึงไม่ทราบ',
substitute: 'คืนค้าง',
},
'zh-tw': {
none: '無',
normal: '正常',
unknown: '不明',
substitute: '代替',
},
tr: {
none: 'Hiçbiri',
normal: 'Normal',
unknown: 'Bilinmiyor',
substitute: 'Değiştir',
},
};
}
set fromApk(values) {
this.rawTranslations = values;
}
removeEscapes(str) {
return str.replace(/\r/g, '').replace(/\n/g, '').replace(/"/g, '”');
}
async fetchTranslations(locale, availableManualTranslations) {
if (!this.rawTranslations[locale]) {
this.rawTranslations[locale] = {};
}
this.parsedTranslations[locale] = {};
this.manualTranslations[locale] = {
pokemon: {},
forms: {},
costumes: {},
descriptions: {},
pokemonCategories: {},
bonuses: {},
moves: {},
items: {},
questTypes: {},
questConditions: {},
questRewardTypes: {},
questTitles: {},
evolutionQuests: {},
types: {},
weather: {},
grunts: {},
gruntQuotes: {},
characterCategories: {},
misc: {},
};
try {
if (!this.codes[locale]) {
console.warn(`Game assets unavailable for ${locale}, using English`);
}
if (!this.generics[locale]) {
this.generics[locale] = this.generics.en;
console.warn(`Generics unavailable for ${locale}, using English`);
}
const localeInfo = this.codes[locale] || {
name: 'English',
code: 'en-us',
};
const { data } = (await this.fetch(this.translationApkUrl.replace('English/en-us', `${localeInfo.name}/${localeInfo.code}`))) || { data: [] };
for (let i = 0; i < data.length; i += 2) {
this.rawTranslations[locale][data[i]] = this.removeEscapes(data[i + 1]);
}
const textFile = ['hi', 'id'].includes(locale)
? ''
: (await this.fetch(this.translationRemoteUrl.replace('English/en-us', `${localeInfo.name}/${localeInfo.code}`), true)) || '';
const splitText = textFile.split('\n');
splitText.forEach((line, i) => {
if (line?.startsWith('RESOURCE ID')) {
const key = this.removeEscapes(line.replace('RESOURCE ID: ', ''));
const value = this.removeEscapes(splitText[i + 1].replace('TEXT: ', ''));
this.rawTranslations[locale][key] = value;
}
});
}
catch (e) {
console.warn(e, '\n', `Unable to process ${locale} from GM`);
}
try {
if (this.options.manualTranslations &&
availableManualTranslations.includes(`${locale}.json`)) {
const manual = await this.fetch(`https://raw.githubusercontent.com/WatWowMap/pogo-translations/refs/heads/master/static/manual/${locale}.json`);
Object.entries(manual).forEach((pair) => {
const [key, value] = pair;
let trimmedKey;
if (key.startsWith('poke_type')) {
trimmedKey = key.replace('poke_type_', this.options.prefix.types || 'poke_type_');
this.manualTranslations[locale].types[trimmedKey] = value;
}
else if (key.startsWith('poke')) {
trimmedKey = key.replace('poke_', this.options.prefix.pokemon || 'poke_');
this.manualTranslations[locale].pokemon[trimmedKey] = value;
}
else if (key.startsWith('form')) {
trimmedKey = key.replace('form_', this.options.prefix.forms || 'form_');
this.manualTranslations[locale].forms[trimmedKey] = value;
}
else if (key.startsWith('costume')) {
trimmedKey = key.replace('costume_', this.options.prefix.costumes || 'costume_');
this.manualTranslations[locale].costumes[trimmedKey] = value;
}
else if (key.startsWith('quest_')) {
const newValue = value.includes('%{') && this.options.questVariables
? value
.replace(/%\{/g, this.options.questVariables.prefix)
.replace(/\}/g, this.options.questVariables.suffix)
: value;
if (key.startsWith('quest_condition_')) {
this.manualTranslations[locale].questConditions[key.replace('quest_condition_', this.options.prefix.questConditions || 'quest_condition_')] = newValue;
}
else if (key.startsWith('quest_reward_')) {
this.manualTranslations[locale].questRewardTypes[key.replace('quest_reward_', this.options.prefix.questRewardTypes || 'quest_reward_')] = newValue;
}
else if (key.startsWith('quest_title_')) {
this.manualTranslations[locale].questRewardTypes[key.replace('quest_title_', this.options.prefix.questTitles || 'quest_title_')] = newValue;
}
else {
this.manualTranslations[locale].questTypes[key.replace('quest_', this.options.prefix.questTypes || 'quest_')] = newValue;
}
}
else if (key.startsWith('grunt_quote_')) {
trimmedKey = key.replace('grunt_quote_', this.options.prefix.gruntQuotes || 'grunt_quote_');
this.manualTranslations[locale].gruntQuotes[trimmedKey] = value;
}
else if (key.startsWith('grunt')) {
trimmedKey = key.replace('grunt_', this.options.prefix.grunts || 'grunt_');
this.manualTranslations[locale].grunts[trimmedKey] = value;
}
else if (key.startsWith('character')) {
trimmedKey = key.replace('character_', this.options.prefix.characterCategories || 'character_category_');
this.manualTranslations[locale].characterCategories[trimmedKey] =
value;
}
else if (key.startsWith('weather')) {
trimmedKey = key.replace('weather_', this.options.prefix.weather || 'weather_');
this.manualTranslations[locale].weather[trimmedKey] = value;
}
else if (key.startsWith('throw')) {
trimmedKey = key.replace('throw_type_', this.options.prefix.throwTypes || 'throw_type_');
this.manualTranslations[locale].misc[trimmedKey] = value;
}
else {
this.manualTranslations[locale].misc[key] = value;
}
});
}
}
catch (e) {
console.warn(e, '\n', `Unable to fetch manual translations for ${locale}`);
}
}
mergeManualTranslations(locale) {
try {
if (!this.enFallback) {
this.enFallback = this.parsedTranslations.en || {};
}
const merged = {};
const sorted = {};
Object.keys(this.parsedTranslations[locale]).forEach((category) => {
merged[category] = {
...this.enFallback[category],
...this.parsedTranslations[locale][category],
...this.manualTranslations[locale][category],
};
sorted[category] = {};
const sortedKeys = Object.keys(merged[category]).sort(this.collator.compare);
sortedKeys.forEach((key) => {
sorted[category][key] = merged[category][key];
});
merged[category] = sorted[category];
});
this.parsedTranslations[locale] = merged;
}
catch (e) {
console.warn(e, '\n', `Unable to merge manual translations for ${locale}`);
}
}
languageRef(locale) {
try {
if (!this.reference) {
this.reference =
this.parsedTranslations[this.options.useLanguageAsRef];
}
const languageRef = {};
Object.keys(this.parsedTranslations[locale]).forEach((category) => {
languageRef[category] = {};
const referenceCategory = this.reference[category] || {};
Object.keys(this.parsedTranslations[locale][category]).forEach((x) => {
const referenceKey = referenceCategory[x];
if (referenceKey !== undefined) {
let outputKey = referenceKey;
if (languageRef[category][outputKey] !== undefined) {
outputKey = `${referenceKey} [${x}]`;
let dedupeCount = 2;
while (languageRef[category][outputKey] !== undefined) {
outputKey = `${referenceKey} [${x}]_${dedupeCount}`;
dedupeCount += 1;
}
}
languageRef[category][outputKey] =
this.parsedTranslations[locale][category][x];
}
});
});
this.parsedTranslations[locale] = languageRef;
}
catch (e) {
console.warn(e, '\n', `Unable to reference translations for ${locale}`);
}
}
mergeCategories(locale) {
try {
let merged = {};
Object.keys(this.parsedTranslations[locale]).forEach((category) => {
merged = {
...merged,
...this.parsedTranslations[locale][category],
};
});
this.parsedTranslations[locale] = merged;
}
catch (e) {
console.warn(e, '\n', `Unable to merge categories for ${locale}`);
}
}
translateMasterfile(data, locale, formsSeparate) {
try {
const language = this.parsedTranslations[locale];
if (language) {
Object.keys(data).forEach((category) => {
const ref = this.options.mergeCategories
? language
: language[category];
if (ref) {
this.masterfile[category] = {};
Object.keys(data[category]).forEach((id) => {
const questEvo = ref[data[category][id].assetsRef];
if (category == 'evolutionQuests' && questEvo) {
this.masterfile[category][id] = {
...data[category][id],
i18n: questEvo,
translated: questEvo
.toString()
.replace(`${this.options.questVariables.prefix}amount${this.options.questVariables.suffix}`, data[category][id].target),
};
}
else if (this.options.prefix[category]) {
const actualId = category === 'pokemon' && formsSeparate
? data[category][id].pokedexId
: id;
if (ref[`${this.options.prefix[category]}${actualId}`] !==
undefined) {
const fieldKey = category === 'pokemon' && formsSeparate
? 'pokemonName'
: Object.keys(data[category][id]).find((field) => field.includes('Name'));
if (fieldKey) {
this.masterfile[category][id] = {
...data[category][id],
[fieldKey]: ref[`${this.options.prefix[category]}${actualId}`],
};
}
else {
console.warn(`Unable to determine field key for ${id} in ${category}, proceeding with default.`);
this.masterfile[category][id] = data[category][id];
}
}
else {
console.warn(`Missing ${locale} key for id: ${id} in ${category}, proceeding with default.`);
this.masterfile[category][id] = data[category][id];
}
}
else {
console.warn(`Missing prefix for category ${category}, proceeding with default.`);
this.masterfile[category][id] = data[category][id];
}
});
}
else {
this.masterfile[category] = data[category];
}
});
}
else {
console.warn(`Missing ${locale} translation, please check your template to make sure it's being parsed.`);
}
}
catch (e) {
console.warn(e, '\n', `Unable to translate masterfile for ${locale}`);
}
}
pokemon(locale, subItems, pokemon, forms, unsetFormName) {
this.parsedTranslations[locale].pokemon = {
[`${this.options.prefix.pokemon}0`]: this.generics[locale].substitute,
};
this.parsedTranslations[locale].forms = {
[`${this.options.prefix.forms}0`]: unsetFormName === undefined
? this.generics[locale].unknown
: unsetFormName,
};
this.parsedTranslations[locale].descriptions = {
[`${this.options.prefix.descriptions}0`]: this.generics[locale].none,
};
this.parsedTranslations[locale].costumes = {};
Object.keys(pokemon).forEach((id) => {
try {
const name = this.rawTranslations[locale][`pokemon_name_${String(id).padStart(4, '0')}`] || pokemon[id].pokemonName;
const description = `pokemon_desc_${String(id).padStart(4, '0')}`;
new Array(4)
.fill(0)
.map((_, evo) => this.rawTranslations[locale][`pokemon_name_${String(id).padStart(4, '0')}_000${evo}`])
.forEach((mega, evo) => {
if (mega) {
this.parsedTranslations[locale].pokemon[`${this.options.prefix.pokemon}${id}_e${evo}`] = mega;
}
});
if (id) {
if (name && subItems.names) {
this.parsedTranslations[locale].pokemon[`${this.options.prefix.pokemon}${id}`] = name;
}
if (this.rawTranslations[locale][description] &&
subItems.descriptions) {
this.parsedTranslations[locale].descriptions[`${this.options.prefix.descriptions}${id}`] = this.rawTranslations[locale][description];
}
if (pokemon[id]?.forms) {
pokemon[id].forms.forEach((formId) => {
const formName = forms[formId].formName;
const formDescription = this.rawTranslations[locale][`${description}_${String(formId).padStart(4, '0')}`];
if (formName && subItems.forms) {
let checkAssets = formName.replace(' ', '_').toLowerCase();
if (id === '413' || id === '412')
checkAssets += '_cloak';
const formAsset = this.rawTranslations[locale][`form_${checkAssets}`];
const typeId = pogo_protos_1.Rpc.HoloPokemonType[`POKEMON_TYPE_${checkAssets.toUpperCase()}`];
if (this.parsedTranslations[locale].misc?.[formName.toLowerCase()]) {
this.parsedTranslations[locale].forms[`${this.options.prefix.forms}${formId}`] =
this.parsedTranslations[locale].misc[formName.toLowerCase()];
}
else if (formAsset && checkAssets !== 'normal') {
if (checkAssets === 'white' || checkAssets === 'black') {
this.parsedTranslations[locale].forms[`${this.options.prefix.forms}${formId}`] = formId === 147 || formId === 148 ? formAsset : formName;
}
else if (checkAssets === 'ice') {
this.parsedTranslations[locale].forms[`${this.options.prefix.forms}${formId}`] =
formId === 2540 || formId === 2541
? formAsset
: this.parsedTranslations[locale].types[`${this.options.prefix.types}${typeId}`] || formName;
}
else {
this.parsedTranslations[locale].forms[`${this.options.prefix.forms}${formId}`] = formAsset;
}
}
else if (formName === 'Normal') {
this.parsedTranslations[locale].forms[`${this.options.prefix.forms}${formId}`] = this.generics[locale].normal;
}
else if (typeId && this.parsedTranslations[locale].types) {
this.parsedTranslations[locale].forms[`${this.options.prefix.forms}${formId}`] =
this.parsedTranslations[locale].types[`${this.options.prefix.types}${typeId}`];
}
else {
this.parsedTranslations[locale].forms[`${this.options.prefix.forms}${formId}`] = formName;
}
}
if (formDescription && subItems.descriptions) {
this.parsedTranslations[locale].descriptions[`${this.options.prefix.descriptions}${id}_${formId}`] = formDescription;
}
});
}
}
}
catch (e) {
console.warn(e, '\n', `Unable to translate pokemon ${id} for ${locale}`);
}
});
Object.entries(pogo_protos_1.Rpc.PokemonDisplayProto.Costume).forEach((proto) => {
const [name, id] = proto;
this.parsedTranslations[locale].costumes[`${this.options.prefix.costumes}${id}`] = this.capitalize(name);
});
}
pokemonCategories(locale) {
try {
this.parsedTranslations[locale].pokemonCategories = {};
Object.keys(this.rawTranslations[locale]).forEach((key) => {
if (key.startsWith(`pokemon_category_`)) {
const split = key.replace('pokemon_category_', '').split('_');
this.parsedTranslations[locale].pokemonCategories[`${this.options.prefix.pokemonCategories}${split
.map((x) => +x || x)
.join('_')}`] = this.rawTranslations[locale][key];
}
});
}
catch (e) {
console.warn(e, '\n', `Unable to translate pokemon categories for ${locale}`);
}
}
bonuses(locale) {
try {
this.parsedTranslations[locale].bonuses = {};
Object.keys(this.rawTranslations[locale]).forEach((key) => {
if (key.startsWith('spawn_')) {
this.parsedTranslations[locale].bonuses[`${this.options.prefix.bonuses}${key}`] = this.rawTranslations[locale][key];
}
});
}
catch (e) {
console.warn(e, '\n', `Unable to translate bonuses for ${locale}`);
}
}
moves(locale) {
try {
this.parsedTranslations[locale].moves = {
[`${this.options.prefix.moves}0`]: this.generics[locale].unknown,
};
Object.entries(pogo_protos_1.Rpc.HoloPokemonMove).forEach((proto) => {
const [name, id] = proto;
if (!id)
return;
const move = this.rawTranslations[locale][`move_name_${String(id).padStart(4, '0')}`];
this.parsedTranslations[locale].moves[`${this.options.prefix.moves}${id}`] = move || this.capitalize(name);
});
}
catch (e) {
console.warn(e, '\n', `Unable to translate moves for ${locale}`);
}
}
items(locale) {
try {
this.parsedTranslations[locale].items = {
[`${this.options.prefix.items}0`]: this.generics[locale].unknown,
};
this.parsedTranslations[locale].lures = {};
Object.entries(pogo_protos_1.Rpc.Item).forEach((proto) => {
const [name, id] = proto;
if (!id)
return;
let item = this.rawTranslations[locale][`${name.toLowerCase()}_name`] ||
this.capitalize(name.replace('ITEM_', '').replace('TROY_DISK_', ''));
this.parsedTranslations[locale].items[`${this.options.prefix.items}${id}`] = item;
if (name.startsWith('ITEM_TROY_DISK')) {
const base = this.rawTranslations[locale].item_troy_disk_name.split(' ');
if (name === 'ITEM_TROY_DISK') {
this.parsedTranslations[locale].lures[`${this.options.prefix.lures}${id}`] = this.generics[locale].normal;
}
else {
base.forEach((word) => {
item = item.replace(word, '');
});
item = item
.replace('Item', '')
.replace('Troy', '')
.replace('Disk', '')
.replace('Mód. ', '');
this.parsedTranslations[locale].lures[`${this.options.prefix.lures}${id}`] = this.capitalize(item.replace('-', '').trim());
}
}
});
}
catch (e) {
console.warn(e, '\n', `Unable to translate items for ${locale}`);
}
}
types(locale) {
try {
this.parsedTranslations[locale].types = {
[`${this.options.prefix.types}0`]: this.generics[locale].none,
};
Object.entries(pogo_protos_1.Rpc.HoloPokemonType).forEach((proto) => {
const [name, id] = proto;
const type = this.rawTranslations[locale][`pokemon_type_${name.replace('POKEMON_TYPE_', '').toLowerCase()}`];
if (type) {
this.parsedTranslations[locale].types[`${this.options.prefix.types}${id}`] = type;
}
});
}
catch (e) {
console.warn(e, '\n', `Unable to translate types for ${locale}`);
}
}
characters(locale, parsedInvasions) {
try {
this.parsedTranslations[locale].grunts = {
[`${this.options.prefix.grunts}0`]: this.generics[locale].none,
[`${this.options.prefix.gruntsAlt}0`]: this.generics[locale].none,
};
this.parsedTranslations[locale].characterCategories = {};
Object.entries(parsedInvasions).forEach(([id, info]) => {
let assetRef;
let shortRef;
switch (info.grunt) {
case 'Grunt': {
const base = `${this.rawTranslations[locale][info.type === 'Decoy'
? 'combat_grunt_decoy_name'
: 'combat_grunt_name']} (${this.rawTranslations[locale][`gender_${info.gender === 1 ? 'male' : 'female'}`]})`;
const type = this.rawTranslations[locale][`pokemon_type_${info.type === 'Metal'
? 'steel'
: info.type.replace(' Balloon', '').toLowerCase()}`];
assetRef = type ? `${type} - ${base}` : base;
shortRef =
assetRef
.replace(` (${this.rawTranslations[locale][`gender_${info.gender === 1 ? 'male' : 'female'}`]})`, info.gender === 1 ? ' ♂' : ' ♀')
.replace(` - ${this.rawTranslations[locale]['combat_grunt_name']}`, '') || info.type;
break;
}
case 'Executive':
assetRef =
this.rawTranslations[locale][`combat_${info.type.toLowerCase()}_name`] || info.type;
break;
case 'Event':
assetRef =
this.rawTranslations[locale][`event_npc${info.type.split(' ')[1].padStart(2, '0')}_name`] || info.type;
break;
default:
assetRef =
this.rawTranslations[locale][`combat_${info.type.toLowerCase()}`] ||
this.rawTranslations[locale][`combat_${info.type.toLowerCase()}_name`] ||
info.type;
}
if (assetRef) {
this.parsedTranslations[locale].grunts[`${this.options.prefix.grunts}${id}`] = assetRef;
}
if (shortRef) {
this.parsedTranslations[locale].grunts[`${this.options.prefix.gruntsAlt}${id}`] = shortRef;
}
else if (assetRef && id !== '0') {
this.parsedTranslations[locale].grunts[`${this.options.prefix.gruntsAlt}${id}`] = assetRef;
}
});
Object.entries(pogo_protos_1.Rpc.EnumWrapper.CharacterCategory).forEach((proto) => {
const [name, id] = proto;
this.parsedTranslations[locale].characterCategories[`${this.options.prefix.characterCategories}${id}`] = this.capitalize(name);
});
}
catch (e) {
console.warn(e, '\n', `Unable to translate characters for ${locale}`);
}
}
gruntQuotes(locale) {
try {
this.parsedTranslations[locale].gruntQuotes = {};
const prefix = this.options.prefix.gruntQuotes || 'grunt_quote_';
const charQuotes = {};
const addQuote = (charId, value, quoteNumber = 1, overwrite = true) => {
if (!charQuotes[charId])
charQuotes[charId] = {};
if (overwrite || charQuotes[charId][quoteNumber] === undefined) {
charQuotes[charId][quoteNumber] = value;
}
};
const TYPE_TO_IDS = {
bug: [6, 7], dark: [10, 11], dragon: [12, 13],
electric: [49, 50], fairy: [14, 15], fighting: [16, 17],
fire: [18, 19], flying: [20, 21], ghost: [47, 48],
grass: [22, 23], ground: [24, 25], ice: [26, 27],
metal: [28, 29], steel: [28, 29], normal: [30, 31], poison: [32, 33],
psychic: [34, 35], rock: [36, 37], water: [38, 39],
};
const BALLOON_GRUNT_IDS = this.options.includeBalloons === false
? []
: Object.entries(pogo_protos_1.Rpc.EnumWrapper.InvasionCharacter)
.filter(([name]) => name.includes('BALLOON_GRUNT'))
.map(([, id]) => Number(id));
const EXEC_TO_IDS = {
cliff: [41, 527],
arlo: [42, 526],
sierra: [43, 525],
giovanni: [44, 524],
};
for (const [key, value] of Object.entries(this.rawTranslations[locale])) {
if (!value)
continue;
let match;
match = key.match(/^combat_grunt_quote_(\w+)__female_speaker$/);
if (match) {
const type = match[1];
const ids = TYPE_TO_IDS[type];
if (ids) {
addQuote(ids[0], value);
addQuote(ids[1], value);
}
continue;
}
match = key.match(/^combat_grunt_quote#(\d+)__female_speaker$/);
if (match) {
const quoteNumber = Number(match[1]);
addQuote(5, value, quoteNumber);
addQuote(4, value, quoteNumber);
continue;
}
match = key.match(/^combat_grunt_balloon_quote#(\d+)__female_speaker$/);
if (match) {
const quoteNumber = Number(match[1]);
BALLOON_GRUNT_IDS.forEach((id) => addQuote(id, value, quoteNumber));
continue;
}
match = key.match(/^grunt_b([fm])_combat_quote$/);
if (match) {
addQuote(match[1] === 'f' ? 53 : 54, value);
continue;
}
match = key.match(/^combat_(cliff|arlo|sierra|giovanni)_quote(?:#(\d+))?$/);
if (match) {
const quoteNumber = match[2] ? Number(match[2]) : 1;
EXEC_TO_IDS[match[1]].forEach((id) => addQuote(id, value, quoteNumber, !!match[2]));
continue;
}
match = key.match(/^combat_grunt_decoy_quote(?:#(\d+))?$/);
if (match) {
const quoteNumber = match[1] ? Number(match[1]) : 1;
addQuote(46, value, quoteNumber, !!match[1]);
addQuote(45, value, quoteNumber, !!match[1]);
continue;
}
}
for (const [idStr, quotes] of Object.entries(charQuotes)) {
Object.keys(quotes)
.map((quoteNumber) => Number(quoteNumber))
.sort((a, b) => a - b)
.forEach((quoteNumber) => {
const key = quoteNumber === 1
? `${prefix}${idStr}`
: `${prefix}${idStr}_${quoteNumber}`;
this.parsedTranslations[locale].gruntQuotes[key] =
quotes[quoteNumber];
});
}
}
catch (e) {
console.warn(e, '\n', `Unable to translate grunt quotes for ${locale}`);
}
}
weather(locale) {
try {
this.parsedTranslations[locale].weather = {
[`${this.options.prefix.weather}0`]: this.generics[locale].none,
};
Object.entries(pogo_protos_1.Rpc.GameplayWeatherProto.WeatherCondition).forEach((proto) => {
const [name, id] = proto;
const type = id
? this.rawTranslations[locale][`weather_${name.toLowerCase()}`]
: this.rawTranslations[locale][`weather_extreme`];
if (type) {
this.parsedTranslations[locale].weather[`${this.options.prefix.weather}${id}`] = type;
}
});
}
catch (e) {
console.warn(e, '\n', `Unable to translate weather for ${locale}`);
}
}
misc(locale) {
try {
this.parsedTranslations[locale].misc = {
gender_1: this.rawTranslations[locale].gender_male,
gender_2: this.rawTranslations[locale].gender_female,
alola: this.rawTranslations[locale].filter_key_alola,
shadow: this.rawTranslations[locale].filter_key_shadow,
purified: this.rawTranslations[locale].filter_key_purified,
legendary: this.rawTranslations[locale].filter_key_legendary,
mythical: this.rawTranslations[locale].filter_key_mythical,
};
Object.keys(this.parsedTranslations[locale].misc).forEach((entry) => {
this.parsedTranslations[locale].misc[entry] = this.capitalize(this.parsedTranslations[locale].misc[entry]);
});
const locationBackground = this.rawTranslations[locale].filter_label_location_card;
if (locationBackground) {
this.parsedTranslations[locale].misc.filter_label_location_card =
locationBackground;
}
const specialBackground = this.rawTranslations[locale].special_background_filter_header;
if (specialBackground) {
this.parsedTranslations[locale].misc.special_background_filter_header =
specialBackground;
}
for (let i = 0; i < 4; i += 1) {
const teamName = this.rawTranslations[locale][`team_name_team${i}`];
this.parsedTranslations[locale].misc[`team_a_${i}`] = teamName;
this.parsedTranslations[locale].misc[`team_${i}`] = i
? teamName.split(' ')[1] || teamName.split(' ')[0]
: teamName;
}
Object.entries(pogo_protos_1.Rpc.HoloActivityType).forEach((proto) => {
const [name, id] = proto;
if (name.endsWith('THROW') || name.endsWith('CURVEBALL')) {
this.parsedTranslations[locale].misc[`${this.options.prefix.throwTypes}${id}`] = this.capitalize(name.replace('ACTIVITY_CATCH_', '').replace('_THROW', ''));
}
});
Object.entries(pogo_protos_1.Rpc.HoloTemporaryEvolutionId).forEach((proto) => {
const [name, id] = proto;
this.parsedTranslations[locale].misc[`${this.options.prefix.evolutions}${id}`] = this.capitalize(name.replace('TEMP_EVOLUTION_', ''));
});
if (!Object.prototype.hasOwnProperty.call(pogo_protos_1.Rpc.HoloTemporaryEvolutionId, 'TEMP_EVOLUTION_MEGA_Z') &&
!this.parsedTranslations[locale].misc[`${this.options.prefix.evolutions}5`]) {
this.parsedTranslations[locale].misc[`${this.options.prefix.evolutions}5`] = this.capitalize('MEGA_Z');
}
Object.entries(pogo_protos_1.Rpc.PokemonDisplayProto.Alignment).forEach((proto) => {
const [name, id] = proto;
this.parsedTranslations[locale].misc[`${this.options.prefix.alignment}${id}`] = this.capitalize(name.replace('POKEMON_ALIGNMENT_', ''));
});
Object.entries(pogo_protos_1.Rpc.RaidLevel).forEach((proto) => {
const [name, id] = proto;
const shortened = this.capitalize(name.replace('RAID_LEVEL_', ''));
const isLevel = !!+shortened;
this.parsedTranslations[locale].misc[`${this.options.prefix.raidLevel}${id}`] = `${shortened}${isLevel ? ' Star' : ''} Raid`;
this.parsedTranslations[locale].misc[`${this.options.prefix.raidLevel}${id}_plural`] = `${shortened}${isLevel ? ' Star' : ''} Raids`;
this.parsedTranslations[locale].misc[`${this.options.prefix.eggLevel}${id}`] = `${shortened}${isLevel ? ' Star' : ''} Egg`;
this.parsedTranslations[locale].misc[`${this.options.prefix.eggLevel}${id}_plural`] = `${shortened}${isLevel ? ' Star' : ''} Eggs`;
});
Object.entries(this.rawTranslations[locale]).forEach(([key, value]) => {
if (key.startsWith('route_tag')) {
this.parsedTranslations[locale].misc[key] = value;
}
});
Object.entries(pogo_protos_1.Rpc.RouteType).forEach((proto) => {
const [name, id] = proto;
this.parsedTranslations[locale].misc[`route_type_${id}`] =
this.capitalize(name.replace('ROUTE_TYPE_', ''));
});
}
catch (e) {
console.warn(e, '\n', `Unable to translate misc for ${locale}`);
}
}
quests(locale, data) {
try {
Object.keys(data).forEach((category) => {
this.parsedTranslations[locale][category] = {};
Object.keys(data[category]).forEach((proto) => {
const value = data[category][proto].formatted.replace('With ', '');
this.parsedTranslations[locale][category][`${this.options.prefix[category]}${proto}`] = value;
});
});
this.parsedTranslations[locale].questTitles = {};
Object.keys(this.rawTranslations[locale]).forEach((key) => {
const value = this.rawTranslations[locale][key]
.replace(/{/g, `${this.options.questVariables.prefix}amount_`)
.replace(/\}/g, this.options.questVariables.suffix);
if ((key.startsWith('quest_') ||
key.startsWith('score') ||
key.startsWith('geotarget_quest') ||
key.startsWith('challenge') ||
key.endsWith('plural') ||
key.endsWith('singular')) &&
this.options.questTitleTermsToSkip.every((term) => !key.includes(term)) &&
!value.includes('%PLAYERNAME%')) {
this.parsedTranslations[locale].questTitles[`${this.options.prefix.questTitles}${key}`] = value;
}
});
}
catch (e) {
console.warn(e, '\n', `Unable to translate quests for ${locale}`);
}
}
parseEvoQuests(locale, evoQuests) {
this.parsedTranslations[locale].evolutionQuests = {};
Object.values(evoQuests).forEach((info) => {
try {
const rawValue = this.rawTranslations[locale][info.assetsRef];
if (!rawValue) {
throw new Error(`Missing translation for assetsRef: ${info.assetsRef}`);
}
const translated = rawValue.replace('{0}', `${this.options.questVariables.prefix}amount${this.options.questVariables.suffix}`);
this.parsedTranslations[locale].evolutionQuests[info.assetsRef] =
translated;
}
catch (e) {
console.warn(e, '\n', `Unable to translate evo quests for ${JSON.stringify(info)} in ${locale}`);
}
});
}
}
exports.default = Translations;