summaryrefslogtreecommitdiff
path: root/resources/js
diff options
context:
space:
mode:
authorDaniel Weipert <code@drogueronin.de>2023-08-24 14:42:12 +0200
committerDaniel Weipert <code@drogueronin.de>2023-08-24 14:42:12 +0200
commitbde5dc98ad96546b59e91f5a6e552bf80cbf48e4 (patch)
tree37196f5b5065c61ac038ae43d6f2392e29e39371 /resources/js
parent7b1c251fcb085dc37de439ea1137373f1905d82e (diff)
translations and error handling
Diffstat (limited to 'resources/js')
-rw-r--r--resources/js/classes/Area.js6
-rw-r--r--resources/js/db.js1
-rw-r--r--resources/js/game.js8
-rw-r--r--resources/js/helpers.js36
-rw-r--r--resources/js/main.js6
-rw-r--r--resources/js/memory.js1
-rw-r--r--resources/js/ui.js81
7 files changed, 102 insertions, 37 deletions
diff --git a/resources/js/classes/Area.js b/resources/js/classes/Area.js
index e8d7acc..f518f22 100644
--- a/resources/js/classes/Area.js
+++ b/resources/js/classes/Area.js
@@ -12,7 +12,11 @@ class Area {
async initialize () {}
get name () {
- return DB.areas[this.slug].name;
+ return translate(this.alternateSlug) || slugToName(this.slug);
+ }
+
+ get alternateSlug () {
+ return DB.areas[this.slug]['modules/tuxemon.slug'];
}
get encounters () {
diff --git a/resources/js/db.js b/resources/js/db.js
index f5cff6c..a04d32e 100644
--- a/resources/js/db.js
+++ b/resources/js/db.js
@@ -87,6 +87,7 @@ async function initializeDB () {
}
await fetchTranslation(Memory.state.Settings.language);
+ applyTranslation();
DB.currencies = await fetch('/db/_generated/currencies.json').then((response) => response.json());
}
diff --git a/resources/js/game.js b/resources/js/game.js
index 663e6b0..0ba5a8d 100644
--- a/resources/js/game.js
+++ b/resources/js/game.js
@@ -954,7 +954,7 @@ const Game = {
};
// Game click bindings
-UI.elements.nextTrainer.addEventListener('click', Game.encounterTrainer);
-UI.elements.battleOpponent.addEventListener('click', Game.battleClick);
-UI.elements.techniques.addEventListener('click', Game.techniqueClick);
-UI.elements.menuCatch.addEventListener('click', Game.catchMonster);
+UI.elements.nextTrainer.addEventListener('click', UI.createEventListener(Game.encounterTrainer));
+UI.elements.battleOpponent.addEventListener('click', UI.createEventListener(Game.battleClick));
+UI.elements.techniques.addEventListener('click', UI.createEventListener(Game.techniqueClick));
+UI.elements.menuCatch.addEventListener('click', UI.createEventListener(Game.catchMonster));
diff --git a/resources/js/helpers.js b/resources/js/helpers.js
index adf0bb7..58e2113 100644
--- a/resources/js/helpers.js
+++ b/resources/js/helpers.js
@@ -59,9 +59,41 @@ function randomString () {
/**
* @param {string} msgid
+ *
+ * @returns {string}
*/
-function translate (msgid) {
- return DB.translations[Memory.state.Settings.language][msgid];
+function translate (msgid, showTranslationMissing = false) {
+ let translation = DB.translations[Memory.state.Settings.language][msgid];
+
+ if (!translation && showTranslationMissing) {
+ translation = (translate('translation_missing') || 'translation_missing') + `: ${msgid}`;
+ }
+
+ return translation;
+}
+
+function applyTranslation () {
+ document.querySelectorAll('body, template').forEach((element) => {
+ let parentNode = element;
+ if (element.content) {
+ parentNode = element.content;
+ }
+
+ parentNode.querySelectorAll('[data-i18n-msgid]').forEach((node) => {
+ node.innerHTML = translate(node.dataset.i18nMsgid, true);
+ });
+
+ parentNode.querySelectorAll('[data-i18n-properties]').forEach((node) => {
+ const properties = node.dataset.i18nProperties.split(',')
+ const msgids = node.dataset.i18nPropertyMsgids.split(',')
+ for (const idx in properties) {
+ const property = properties[idx];
+ const msgid = msgids[idx];
+
+ node.setAttribute(property, translate(msgid, true))
+ }
+ });
+ });
}
/**
diff --git a/resources/js/main.js b/resources/js/main.js
index 6ea94e2..aa86423 100644
--- a/resources/js/main.js
+++ b/resources/js/main.js
@@ -1,4 +1,4 @@
-(async function () {
+UI.createEventListener(async function () {
await initializeDB();
// Start Game
@@ -7,7 +7,7 @@
const monsterSelection = UI.openStarterMonsterSelection(
await Promise.all(possibleStarterMonsters.map(async (monsterSlug) => await fetchMonster(monsterSlug)))
);
- monsterSelection.addEventListener('starter:monster:selected', async (event) => {
+ monsterSelection.addEventListener('starter:monster:selected', UI.createEventListener(async (event) => {
if (!confirm(`Select ${event.detail.monster.name}?`)) {
return;
}
@@ -35,5 +35,5 @@
UI.drawActiveTechniques();
event.detail.popup.remove();
- });
+ }));
})();
diff --git a/resources/js/memory.js b/resources/js/memory.js
index 40be4df..6023e49 100644
--- a/resources/js/memory.js
+++ b/resources/js/memory.js
@@ -173,6 +173,7 @@ const Memory = {
Memory.state.Settings.language = loadedState.Settings.language;
await fetchTranslation(Memory.state.Settings.language);
+ applyTranslation();
Memory.state.Settings.currency = loadedState.Settings.currency;
Memory.state.Settings.logMaxLength = loadedState.Settings.logMaxLength;
diff --git a/resources/js/ui.js b/resources/js/ui.js
index 6f38867..77b5b54 100644
--- a/resources/js/ui.js
+++ b/resources/js/ui.js
@@ -725,7 +725,7 @@ const UI = {
template.querySelector('[data-template-slot="heal"]').addEventListener('click', () => {
const applicableMonsters = Memory.state.player.monsters.filter((monster) => monster.hp < monster.stats.hp || monster.statusEffect);
if (applicableMonsters.length === 0) {
- alert('No applicable monsters.');
+ alert(translate('ui:no_applicable_monsters', true));
return;
}
@@ -1004,7 +1004,8 @@ const UI = {
const connection = currentArea.connections[connectionSlug];
const connectionNode = UI.createTemplate(Template.areaSelectionItem);
- connectionNode.querySelector('[data-template-slot="text"]').textContent = connection.name;
+ connectionNode.querySelector('[data-template-slot="text"]').textContent =
+ translate(connection['modules/tuxemon.slug']) || slugToName(connection['modules/tuxemon.slug']);
let canGo = true;
for (const condition of connection.conditions) {
@@ -1090,27 +1091,27 @@ const UI = {
const tabs = {
heal: {
- heading: 'Heal',
+ heading: translate('ui:inventory:tab:heal'),
items: [],
},
stats: {
- heading: 'Stats',
+ heading: translate('ui:inventory:tab:stats'),
items: [],
},
balls: {
- heading: 'Balls',
+ heading: translate('ui:inventory:tab:balls'),
items: [],
},
techniques: {
- heading: 'Techniques',
+ heading: translate('ui:inventory:tab:techniques'),
items: [],
},
other: {
- heading: 'Other',
+ heading: translate('ui:inventory:tab:other'),
items: [],
},
keyItems: {
- heading: 'Key Items',
+ heading: translate('ui:inventory:tab:key_items'),
items: [],
},
};
@@ -1180,13 +1181,13 @@ const UI = {
const popup = UI.createPopup();
const journal = UI.createTemplate(Template.menuJournal);
- journal.querySelector('[data-template-slot="save"]').addEventListener('click', () => {
+ journal.querySelector('[data-template-slot="save"]').addEventListener('click', UI.createEventListener(() => {
UI.openSaveDialog();
- });
+ }));
- journal.querySelector('[data-template-slot="load"]').addEventListener('click', () => {
+ journal.querySelector('[data-template-slot="load"]').addEventListener('click', UI.createEventListener(() => {
UI.openLoadDialog();
- });
+ }));
popup.querySelector('.popup').appendChild(journal);
UI.drawPopup(popup);
@@ -1237,9 +1238,9 @@ const UI = {
Memory.state.Settings.language = selected.value;
await fetchTranslation(Memory.state.Settings.language);
- UI.drawOpponentMonster();
- UI.drawActiveMonster();
- UI.drawActiveTechniques();
+ applyTranslation();
+
+ UI.drawArea();
});
@@ -1572,7 +1573,7 @@ const UI = {
template.classList.add('inventory__monster-selection');
if (template.children.length === 0) {
- alert('No applicable monsters.');
+ alert(translate('ui:no_applicable_monsters', true));
return;
}
@@ -1608,14 +1609,14 @@ const UI = {
const saveData = Memory.save();
dialog.querySelector('[data-template-slot="saveData"]').value = saveData;
- dialog.querySelector('[data-template-slot="saveClipboard"]').addEventListener('click', async () => {
+ dialog.querySelector('[data-template-slot="saveClipboard"]').addEventListener('click', UI.createEventListenr(async () => {
if (navigator.clipboard) {
await navigator.clipboard.writeText(saveData);
alert('Saved to clipboard!');
} else {
alert('ERROR: Browser can\'t copy to clipboard! You have to do it manually.');
}
- });
+ }));
popup.querySelector('.popup').appendChild(dialog);
UI.drawPopup(popup);
@@ -1625,24 +1626,50 @@ const UI = {
const popup = UI.createPopup();
const dialog = UI.createTemplate(Template.dialogLoad);
- dialog.querySelector('[data-template-slot="load"]').addEventListener('click', () => {
+ dialog.querySelector('[data-template-slot="load"]').addEventListener('click', UI.createEventListener(() => {
Memory.load(
dialog.querySelector('[data-template-slot="saveData"]').value.trim()
);
document.querySelectorAll('.popup__overlay').forEach((element) => element.remove())
- });
+ }));
popup.querySelector('.popup').appendChild(dialog);
UI.drawPopup(popup);
},
+
+
+ // Error
+
+ /**
+ * @param {Function} listener
+ *
+ * @returns {Function}
+ */
+ createEventListener (listener) {
+ return (event) => {
+ try {
+ listener(event);
+ } catch (exception) {
+ console.log(exception);
+ UI.showErrorMessage(exception);
+ }
+ };
+ },
+
+ /**
+ * @param {string} message
+ */
+ showErrorMessage (message) {
+ alert(message);
+ },
};
// UI element click bindings
-UI.elements.showMap.addEventListener('click', UI.openMap);
-UI.elements.changeArea.addEventListener('click', UI.openAreaSelection);
-UI.elements.menuParty.addEventListener('click', UI.openPartyMenu);
-UI.elements.menuInventory.addEventListener('click', UI.openInventoryMenu);
-UI.elements.menuLog.addEventListener('click', UI.toggleLog);
-UI.elements.menuJournal.addEventListener('click', UI.openJournalMenu);
-UI.elements.menuSettings.addEventListener('click', UI.openSettingsMenu);
+UI.elements.showMap.addEventListener('click', UI.createEventListener(UI.openMap));
+UI.elements.changeArea.addEventListener('click', UI.createEventListener(UI.createEventListener(UI.openAreaSelection)));
+UI.elements.menuParty.addEventListener('click', UI.createEventListener(UI.openPartyMenu));
+UI.elements.menuInventory.addEventListener('click', UI.createEventListener(UI.openInventoryMenu));
+UI.elements.menuLog.addEventListener('click', UI.createEventListener(UI.toggleLog));
+UI.elements.menuJournal.addEventListener('click', UI.createEventListener(UI.openJournalMenu));
+UI.elements.menuSettings.addEventListener('click', UI.createEventListener(UI.openSettingsMenu));