UNPKG

pogo-data-generator

Version:
899 lines (898 loc) 44.8 kB
"use strict"; 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;