From ff6de568af35b6016a2bf0353323ab9757d9e62a Mon Sep 17 00:00:00 2001 From: Fabi <192151969+fabske0@users.noreply.github.com> Date: Wed, 10 Sep 2025 20:53:57 +0200 Subject: [PATCH] [UI/UX] Add language selection to login screen (#6302) * add language selection * Move language option up * Move language list to seperate file * fix circular dependency * Move language selection to own icon * run biome * add icon * add icon to legacy ui --- public/images/ui/language_icon.png | Bin 0 -> 294 bytes public/images/ui/legacy/language_icon.png | Bin 0 -> 294 bytes src/loading-scene.ts | 1 + src/system/settings/settings-language.ts | 101 ++++++++++++++++++++++ src/system/settings/settings.ts | 94 +------------------- src/ui/handlers/login-form-ui-handler.ts | 46 +++++++--- 6 files changed, 140 insertions(+), 102 deletions(-) create mode 100644 public/images/ui/language_icon.png create mode 100644 public/images/ui/legacy/language_icon.png create mode 100644 src/system/settings/settings-language.ts diff --git a/public/images/ui/language_icon.png b/public/images/ui/language_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ebe0671ca5115c0e1d2d59107b03ef61bd395c38 GIT binary patch literal 294 zcmV+>0oneEP)ZA>fB+Oz^~OiPFpB$*|boWR`Zhx~Ap8y=e_Nlx!YbsydG+5!GaM04z% z3p>2vH}I-Tv-Yx^QqG4gEQ%Rh#9#Gm;rS$-4wpx|pZEF>uIJVg@y5%hDlcGOUGM>0 zl7InT)Q8G@;Rwc>=M4TB&h{Oz&&3o7ZRs5_UdhTuo51BkZ>L?8!B^lqa0oneEP)ZA>fB+Oz^~OiPFpB$*|boWR`Zhx~Ap8y=e_Nlx!YbsydG+5!GaM04z% z3p>2vH}I-Tv-Yx^QqG4gEQ%Rh#9#Gm;rS$-4wpx|pZEF>uIJVg@y5%hDlcGOUGM>0 zl7InT)Q8G@;Rwc>=M4TB&h{Oz&&3o7ZRs5_UdhTuo51BkZ>L?8!B^lqa { + globalScene.ui.revertMode(); + const handler = globalScene.ui.getHandler(); + // Reset the cursor to the current language, if in the settings menu + if (handler && typeof (handler as SettingsDisplayUiHandler).setOptionCursor === "function") { + (handler as SettingsDisplayUiHandler).setOptionCursor(-1, 0, true); + } +}; + +const changeLocaleHandler = (locale: string): boolean => { + try { + i18next.changeLanguage(locale); + localStorage.setItem("prLang", locale); + cancelHandler(); + // Reload the whole game to apply the new locale since also some constants are translated + window.location.reload(); + return true; + } catch (error) { + console.error("Error changing locale:", error); + return false; + } +}; + +export const languageOptions = [ + { + label: "English", + handler: () => changeLocaleHandler("en"), + }, + { + label: "Español (ES)", + handler: () => changeLocaleHandler("es-ES"), + }, + { + label: "Español (LATAM)", + handler: () => changeLocaleHandler("es-MX"), + }, + { + label: "Français", + handler: () => changeLocaleHandler("fr"), + }, + { + label: "Deutsch", + handler: () => changeLocaleHandler("de"), + }, + { + label: "Italiano", + handler: () => changeLocaleHandler("it"), + }, + { + label: "Português (BR)", + handler: () => changeLocaleHandler("pt-BR"), + }, + { + label: "한국어", + handler: () => changeLocaleHandler("ko"), + }, + { + label: "日本語", + handler: () => changeLocaleHandler("ja"), + }, + { + label: "简体中文", + handler: () => changeLocaleHandler("zh-CN"), + }, + { + label: "繁體中文", + handler: () => changeLocaleHandler("zh-TW"), + }, + { + label: "Català (Needs Help)", + handler: () => changeLocaleHandler("ca"), + }, + { + label: "Türkçe (Needs Help)", + handler: () => changeLocaleHandler("tr"), + }, + { + label: "Русский (Needs Help)", + handler: () => changeLocaleHandler("ru"), + }, + { + label: "Dansk (Needs Help)", + handler: () => changeLocaleHandler("da"), + }, + { + label: "Română (Needs Help)", + handler: () => changeLocaleHandler("ro"), + }, + { + label: "Tagalog (Needs Help)", + handler: () => changeLocaleHandler("tl"), + }, + { + label: i18next.t("settings:back"), + handler: () => cancelHandler(), + }, +]; diff --git a/src/system/settings/settings.ts b/src/system/settings/settings.ts index c44f31f0930..78b6044b0fc 100644 --- a/src/system/settings/settings.ts +++ b/src/system/settings/settings.ts @@ -6,10 +6,10 @@ import { PlayerGender } from "#enums/player-gender"; import { ShopCursorTarget } from "#enums/shop-cursor-target"; import { UiMode } from "#enums/ui-mode"; import { CandyUpgradeNotificationChangedEvent } from "#events/battle-scene"; -import type { SettingsUiHandler } from "#ui/settings-ui-handler"; import { updateWindowType } from "#ui/ui-theme"; import { isLocal } from "#utils/common"; import i18next from "i18next"; +import { languageOptions } from "./settings-language"; const VOLUME_OPTIONS: SettingOption[] = [ { @@ -911,98 +911,8 @@ export function setSetting(setting: string, value: number): boolean { break; case SettingKeys.Language: if (value && globalScene.ui) { - const cancelHandler = () => { - globalScene.ui.revertMode(); - (globalScene.ui.getHandler() as SettingsUiHandler).setOptionCursor(-1, 0, true); - }; - const changeLocaleHandler = (locale: string): boolean => { - try { - i18next.changeLanguage(locale); - localStorage.setItem("prLang", locale); - cancelHandler(); - // Reload the whole game to apply the new locale since also some constants are translated - window.location.reload(); - return true; - } catch (error) { - console.error("Error changing locale:", error); - return false; - } - }; globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, { - options: [ - { - label: "English", - handler: () => changeLocaleHandler("en"), - }, - { - label: "Español (ES)", - handler: () => changeLocaleHandler("es-ES"), - }, - { - label: "Español (LATAM)", - handler: () => changeLocaleHandler("es-MX"), - }, - { - label: "Français", - handler: () => changeLocaleHandler("fr"), - }, - { - label: "Deutsch", - handler: () => changeLocaleHandler("de"), - }, - { - label: "Italiano", - handler: () => changeLocaleHandler("it"), - }, - { - label: "Português (BR)", - handler: () => changeLocaleHandler("pt-BR"), - }, - { - label: "한국어", - handler: () => changeLocaleHandler("ko"), - }, - { - label: "日本語", - handler: () => changeLocaleHandler("ja"), - }, - { - label: "简体中文", - handler: () => changeLocaleHandler("zh-CN"), - }, - { - label: "繁體中文", - handler: () => changeLocaleHandler("zh-TW"), - }, - { - label: "Català (Needs Help)", - handler: () => changeLocaleHandler("ca"), - }, - { - label: "Türkçe (Needs Help)", - handler: () => changeLocaleHandler("tr"), - }, - { - label: "Русский (Needs Help)", - handler: () => changeLocaleHandler("ru"), - }, - { - label: "Dansk (Needs Help)", - handler: () => changeLocaleHandler("da"), - }, - { - label: "Română (Needs Help)", - handler: () => changeLocaleHandler("ro"), - }, - { - label: "Tagalog (Needs Help)", - handler: () => changeLocaleHandler("tl"), - }, - { - label: i18next.t("settings:back"), - handler: () => cancelHandler(), - }, - ], + options: languageOptions, maxOptions: 7, }); return false; diff --git a/src/ui/handlers/login-form-ui-handler.ts b/src/ui/handlers/login-form-ui-handler.ts index aeebd23ce43..0634ae36ba8 100644 --- a/src/ui/handlers/login-form-ui-handler.ts +++ b/src/ui/handlers/login-form-ui-handler.ts @@ -2,6 +2,7 @@ import { pokerogueApi } from "#api/pokerogue-api"; import { globalScene } from "#app/global-scene"; import { TextStyle } from "#enums/text-style"; import { UiMode } from "#enums/ui-mode"; +import { languageOptions } from "#system/settings-language"; import type { OptionSelectItem } from "#ui/handlers/abstract-option-select-ui-handler"; import type { InputFieldConfig } from "#ui/handlers/form-modal-ui-handler"; import { FormModalUiHandler } from "#ui/handlers/form-modal-ui-handler"; @@ -31,6 +32,7 @@ export class LoginFormUiHandler extends FormModalUiHandler { private discordImage: Phaser.GameObjects.Image; private usernameInfoImage: Phaser.GameObjects.Image; private saveDownloadImage: Phaser.GameObjects.Image; + private changeLanguageImage: Phaser.GameObjects.Image; private externalPartyContainer: Phaser.GameObjects.Container; private infoContainer: Phaser.GameObjects.Container; private externalPartyBg: Phaser.GameObjects.NineSlice; @@ -82,8 +84,14 @@ export class LoginFormUiHandler extends FormModalUiHandler { scale: 0.75, }); + this.changeLanguageImage = this.buildInteractableImage("language_icon", "change-language-icon", { + x: 40, + scale: 0.5, + }); + this.infoContainer.add(this.usernameInfoImage); this.infoContainer.add(this.saveDownloadImage); + this.infoContainer.add(this.changeLanguageImage); this.getUi().add(this.infoContainer); this.infoContainer.setVisible(false); this.infoContainer.disableInteractive(); @@ -163,13 +171,18 @@ export class LoginFormUiHandler extends FormModalUiHandler { const [usernameInput, passwordInput] = this.inputs; - pokerogueApi.account.login({ username: usernameInput.text, password: passwordInput.text }).then(error => { - if (!error && originalLoginAction) { - originalLoginAction(); - } else { - onFail(error); - } - }); + pokerogueApi.account + .login({ + username: usernameInput.text, + password: passwordInput.text, + }) + .then(error => { + if (!error && originalLoginAction) { + originalLoginAction(); + } else { + onFail(error); + } + }); } }; @@ -185,9 +198,13 @@ export class LoginFormUiHandler extends FormModalUiHandler { this.infoContainer.setVisible(false); this.setMouseCursorStyle("default"); //reset cursor - [this.discordImage, this.googleImage, this.usernameInfoImage, this.saveDownloadImage].forEach(img => - img.off("pointerdown"), - ); + [ + this.discordImage, + this.googleImage, + this.usernameInfoImage, + this.saveDownloadImage, + this.changeLanguageImage, + ].forEach(img => img.off("pointerdown")); } private processExternalProvider(config: ModalConfig): void { @@ -206,6 +223,7 @@ export class LoginFormUiHandler extends FormModalUiHandler { this.getUi().moveTo(this.infoContainer, this.getUi().length - 1); this.usernameInfoImage.setPositionRelative(this.infoContainer, 0, 0); this.saveDownloadImage.setPositionRelative(this.infoContainer, 20, 0); + this.changeLanguageImage.setPositionRelative(this.infoContainer, 40, 0); this.discordImage.on("pointerdown", () => { const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); @@ -288,6 +306,14 @@ export class LoginFormUiHandler extends FormModalUiHandler { } }); + this.changeLanguageImage.on("pointerdown", () => { + globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, { + options: languageOptions, + maxOptions: 7, + delay: 1000, + }); + }); + this.externalPartyContainer.setAlpha(0); globalScene.tweens.add({ targets: this.externalPartyContainer,