From c6e27794295f0f2fe7c4fefc585094ed3c85dc2f Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sun, 22 Mar 2026 09:00:51 +0100 Subject: [PATCH] =?UTF-8?q?afegit=20suport=20multiidioma=20afegida=20tradu?= =?UTF-8?q?cci=C3=B3=20al=20valenci=C3=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 3 + config/assets.yaml | 7 ++ data/locale/ca.yaml | 139 +++++++++++++++++++++++++++ data/locale/en.yaml | 138 ++++++++++++++++++++++++++ data/room/01.yaml | 3 +- data/room/02.yaml | 3 +- data/room/03.yaml | 3 +- data/room/04.yaml | 3 +- data/room/05.yaml | 3 +- data/room/06.yaml | 3 +- data/room/07.yaml | 3 +- data/room/08.yaml | 3 +- data/room/09.yaml | 3 +- data/room/10.yaml | 3 +- data/room/11.yaml | 3 +- data/room/12.yaml | 3 +- data/room/13.yaml | 3 +- data/room/14.yaml | 3 +- data/room/15.yaml | 3 +- data/room/16.yaml | 3 +- data/room/17.yaml | 3 +- data/room/18.yaml | 3 +- data/room/19.yaml | 3 +- data/room/20.yaml | 3 +- data/room/21.yaml | 3 +- data/room/22.yaml | 3 +- data/room/23.yaml | 3 +- data/room/24.yaml | 3 +- data/room/25.yaml | 3 +- data/room/26.yaml | 3 +- data/room/27.yaml | 3 +- data/room/28.yaml | 3 +- data/room/29.yaml | 3 +- data/room/30.yaml | 3 +- data/room/31.yaml | 3 +- data/room/32.yaml | 3 +- data/room/33.yaml | 3 +- data/room/34.yaml | 3 +- data/room/35.yaml | 3 +- data/room/36.yaml | 3 +- data/room/37.yaml | 3 +- data/room/38.yaml | 3 +- data/room/39.yaml | 3 +- data/room/40.yaml | 3 +- data/room/41.yaml | 3 +- data/room/42.yaml | 3 +- data/room/43.yaml | 3 +- data/room/44.yaml | 3 +- data/room/45.yaml | 3 +- data/room/46.yaml | 3 +- data/room/47.yaml | 3 +- data/room/48.yaml | 3 +- data/room/49.yaml | 3 +- data/room/50.yaml | 3 +- data/room/51.yaml | 3 +- data/room/52.yaml | 3 +- data/room/53.yaml | 3 +- data/room/54.yaml | 3 +- data/room/55.yaml | 3 +- data/room/56.yaml | 3 +- data/room/57.yaml | 3 +- data/room/58.yaml | 3 +- data/room/59.yaml | 3 +- data/room/60.yaml | 3 +- source/core/input/global_inputs.cpp | 25 ++--- source/core/locale/locale.cpp | 90 +++++++++++++++++ source/core/locale/locale.hpp | 26 +++++ source/core/system/director.cpp | 10 ++ source/game/defaults.hpp | 4 + source/game/gameplay/cheevos.cpp | 32 +++--- source/game/gameplay/room_loader.cpp | 6 +- source/game/gameplay/scoreboard.cpp | 7 +- source/game/options.cpp | 22 +++++ source/game/options.hpp | 3 + source/game/scenes/credits.cpp | 31 +++--- source/game/scenes/ending.cpp | 38 ++++---- source/game/scenes/ending2.cpp | 9 +- source/game/scenes/game.cpp | 17 ++-- source/game/scenes/game_over.cpp | 10 +- source/game/scenes/title.cpp | 46 ++++----- 80 files changed, 680 insertions(+), 163 deletions(-) create mode 100644 data/locale/ca.yaml create mode 100644 data/locale/en.yaml create mode 100644 source/core/locale/locale.cpp create mode 100644 source/core/locale/locale.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d695686..e3e31ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,9 @@ set(APP_SOURCES source/core/rendering/text.cpp source/core/rendering/texture.cpp + # Core - Locale + source/core/locale/locale.cpp + # Core - Resources source/core/resources/resource_list.cpp source/core/resources/resource_cache.cpp diff --git a/config/assets.yaml b/config/assets.yaml index fe00de9..b48470a 100644 --- a/config/assets.yaml +++ b/config/assets.yaml @@ -56,6 +56,13 @@ assets: - type: PALETTE path: ${PREFIX}/data/palette/steam-lords.pal + # LOCALE + locale: + - type: DATA + path: ${PREFIX}/data/locale/en.yaml + - type: DATA + path: ${PREFIX}/data/locale/ca.yaml + # INPUT input: - type: DATA diff --git a/data/locale/ca.yaml b/data/locale/ca.yaml new file mode 100644 index 0000000..eb3fe30 --- /dev/null +++ b/data/locale/ca.yaml @@ -0,0 +1,139 @@ +# JailDoctor's Dilemma - Catalan Locale +# lang: ca +# Nota: s'utilitzen nomes caracters ASCII per compatibilitat amb la font del joc + +title: + marquee: "EH JAILEROS!! ES EL 2022 I ENCARA HO PETEM COM EL 1998!!! HEU SENTIT? ELS JAILGAMES HAN TORNAT!! SIII HAN TORNAT!! MES DE 10 TITOLS A LA CUINA DEL JAILDOC!! AIXO ES MOLT, PERO QUIN SERA EL PRIMER? TAMBE HI HA UN NOU APARELL QUE US FARA VOLAR EL CAP AMB JAILGAMES A TOT ARREU: P.A.C.O. PERO ESPERA! QUE ES AQUELLA BELLESA QUE VEIG ALLA? OOOH AQUELLA PETITA MINIASCII ES PUR AMOR!! VULL LLEPAR CADA BYTE! OH MERDA! I NO OBLIDEU PORTAR AQUELLS VELLS I GRASSOS JAILGAMES DE MS-DOS A GITHUB PER MANTENIR-LOS VIUS!! QUIN SERA EL PROPER LLANCAMENT DEL JAILDOC? QUIN PROJECTE COBRARA VIDA?? OH NANOS NO HO SABEM PERO AQUI PODEU TROBAR LA RESPOSTA, NOMES HEU DE COMPLETAR EL DILEMA DEL JAILDOCTOR ... PODEU?" + menu: + play: "1. JUGAR" + keyboard: "2. REDEFINIR TECLAT" + joystick: "3. REDEFINIR JOYSTICK" + projects: "4. PROJECTES" + keys: + prompt0: "PREM TECLA PER ESQUERRA" + prompt1: "PREM TECLA PER DRETA" + prompt2: "PREM TECLA PER SALTAR" + defined: "TECLES DEFINIDES" + label0: "ESQUERRA: " + label1: "DRETA: " + label2: "SALT: " + invalid: "TECLA INVALIDA! PROVA UNA ALTRA" + already_used: "TECLA JA USADA! PROVA UNA ALTRA" + buttons: + prompt0: "PREM BOTO PER ESQUERRA" + prompt1: "PREM BOTO PER DRETA" + prompt2: "PREM BOTO PER SALTAR" + defined: "BOTONS DEFINITS" + already_used: "BOTO JA USAT! PROVA UN ALTRE" + projects: "PROJECTES" + +game_over: + title: "G A M E O V E R" + items: "OBJECTES: " + rooms: "SALES: " + worst_nightmare: "EL TEU PITJOR MALSON ES" + +ending: + t0: "FINALMENT HO VA ACONSEGUIR" + t1: "ARRIBAR A LA PRESO" + t2: "AMB TOTS ELS SEUS PROJECTES" + t3: "A PUNT PER SER ALLIBERATS" + t4: "TOTS ELS JAILEROS HI EREN" + t5: "ESPERANT QUE ELS JAILGAMES" + t6: "FOSSIN ALLIBERATS" + t7: "HI HAVIA FINS I TOT BARRULLS I" + t8: "PRINCIPIANTS ENTRE LA MULTITUD" + t9: "LA BRY PLORAVA..." + t10: "PERO DE SOBTE ALGUNA COSA" + t11: "VA ATREURE LA SEVA ATENCIO" + t12: "UN MUNT DE FERALLA!" + t13: "PLE DE TRASTOS QUE NO FUNCIONEN!!" + t14: "I ALESHORES," + t15: "QUARANTA NOUS PROJECTES" + t16: "VAN NEIXER..." + +ending2: + starring: "PROTAGONISTES" + jaildoctor: "JAILDOCTOR" + thank_you: "GRACIES" + for_playing: "PER JUGAR!" + +credits: + instructions: "INSTRUCCIONS:" + l0: "AJUDA AL JAILDOC A RECUPERAR" + l1: "ELS SEUS PROJECTES I ANAR A" + l2: "LA PRESO PER ACABAR-LOS" + keys: "TECLES:" + keys_move: "CURSORS PER MOURE I SALTAR" + f8: "F8 ACTIVAR/DESACTIVAR MUSICA" + f11: "F11 PAUSAR EL JOC" + f1f2: "F1-F2 MIDA DE LA FINESTRA" + f3: "F3 PANTALLA COMPLETA" + f9: "F9 VORA DE LA PANTALLA" + author: "UN JOC DE JAILDESIGNER" + date: "FET A L'ESTIU/TARDOR DEL 2022" + love: "M'ENCANTEN ELS JAILGAMES! " + +achievements: + header: "ASSOLIMENT DESBLOQUEJAT!" + c1: "COSES BRILLANTS" + d1: "Obteniu el 25% dels objectes" + c2: "A MITAT DE CAMI" + d2: "Obteniu el 50% dels objectes" + c3: "QUASI HI SOM" + d3: "Obteniu el 75% dels objectes" + c4: "EL COL LECCIONISTA" + d4: "Obteniu el 100% dels objectes" + c5: "PASSEJANT PER AQUI" + d5: "Visiteu 20 sales" + c6: "M'HE PERDUT" + d6: "Visiteu 40 sales" + c7: "M'AGRADA EXPLORAR" + d7: "Visiteu totes les sales" + c8: "ACABA EL JOC" + d8: "Completa el joc" + c9: "EM VA XUCLAR UN FORAT" + d9: "Completa el joc sense entrar a la preso" + c10: "ELS MEUS PROJECTES" + d10: "Completa el joc amb tots els objectes" + c11: "M'AGRADEN ELS MEUS AMICS DE COLORS" + d11: "Completa el joc sense morir" + c12: "PROJECTES MALS FETS DE PRESSA" + d12: "Completa el joc en menys de 30 minuts" + +ui: + press_again_menu: "PREM DE NOU PER TORNAR AL MENU" + press_again_exit: "PREM DE NOU PER SORTIR" + border_enabled: "BORDE ACTIVAT" + border_disabled: "BORDE DESACTIVAT" + fullscreen_enabled: "PANTALLA COMPLETA ACTIVADA" + fullscreen_disabled: "PANTALLA COMPLETA DESACTIVADA" + window_zoom: "ZOOM FINESTRA x" + postfx_enabled: "POSTFX ACTIVAT" + postfx_disabled: "POSTFX DESACTIVAT" + postfx: "POSTFX" + palette: "PALETA" + integer_scale_enabled: "ESCALA ENTERA ACTIVADA" + integer_scale_disabled: "ESCALA ENTERA DESACTIVADA" + vsync_enabled: "V-SYNC ACTIVAT" + vsync_disabled: "V-SYNC DESACTIVAT" + +scoreboard: + items: "Objectes col.lec. " + time: " Temps " + rooms: "Sales" + +game: + music_enabled: "MUSICA ACTIVADA" + music_disabled: "MUSICA DESACTIVADA" + paused: "JOC EN PAUSA" + running: "JOC EN MARXA" + enabled: " ACTIVAT" + disabled: " DESACTIVAT" + cheat_infinite_lives: "VIDES INFINITES" + cheat_invincible: "INVENCIBLE" + cheat_jail_open: "PRESO OBERTA" + debug_enabled: "DEBUG ACTIVAT" + debug_disabled: "DEBUG DESACTIVAT" + achievement_unlocked: "ASSOLIMENT DESBLOQUEJAT!" + c11: "M'AGRADEN ELS MEUS AMICS DE COLORS" diff --git a/data/locale/en.yaml b/data/locale/en.yaml new file mode 100644 index 0000000..d9035b2 --- /dev/null +++ b/data/locale/en.yaml @@ -0,0 +1,138 @@ +# JailDoctor's Dilemma - English Locale +# lang: en + +title: + marquee: "HEY JAILERS!! IT'S 2022 AND WE'RE STILL ROCKING LIKE IT'S 1998!!! HAVE YOU HEARD IT? JAILGAMES ARE BACK!! YEEESSS BACK!! MORE THAN 10 TITLES ON JAILDOC'S KITCHEN!! THATS A LOOOOOOT OF JAILGAMES, BUT WHICH ONE WILL STRIKE FIRST? THERE IS ALSO A NEW DEVICE TO COME THAT WILL BLOW YOUR MIND WITH JAILGAMES ON THE GO: P.A.C.O. BUT WAIT! WHAT'S THAT BEAUTY I'M SEEING RIGHT OVER THERE?? OOOH THAT TINY MINIASCII IS PURE LOVE!! I WANT TO LICK EVERY BYTE OF IT!! OH SHIT! AND DON'T FORGET TO BRING BACK THOSE OLD AND FAT MS-DOS JAILGAMES TO GITHUB TO KEEP THEM ALIVE!! WHAT WILL BE THE NEXT JAILDOC RELEASE? WHAT WILL BE THE NEXT PROJECT TO COME ALIVE?? OH BABY WE DON'T KNOW BUT HERE YOU CAN FIND THE ANSWER, YOU JUST HAVE TO COMPLETE JAILDOCTOR'S DILEMMA ... COULD YOU?" + menu: + play: "1. PLAY" + keyboard: "2. REDEFINE KEYBOARD" + joystick: "3. REDEFINE JOYSTICK" + projects: "4. PROJECTS" + keys: + prompt0: "PRESS KEY FOR LEFT" + prompt1: "PRESS KEY FOR RIGHT" + prompt2: "PRESS KEY FOR JUMP" + defined: "KEYS DEFINED" + label0: "LEFT: " + label1: "RIGHT: " + label2: "JUMP: " + invalid: "INVALID KEY! TRY ANOTHER" + already_used: "KEY ALREADY USED! TRY ANOTHER" + buttons: + prompt0: "PRESS BUTTON FOR LEFT" + prompt1: "PRESS BUTTON FOR RIGHT" + prompt2: "PRESS BUTTON FOR JUMP" + defined: "BUTTONS DEFINED" + already_used: "BUTTON ALREADY USED! TRY ANOTHER" + projects: "PROJECTS" + +game_over: + title: "G A M E O V E R" + items: "ITEMS: " + rooms: "ROOMS: " + worst_nightmare: "YOUR WORST NIGHTMARE IS" + +ending: + t0: "HE FINALLY MANAGED" + t1: "TO GET TO THE JAIL" + t2: "WITH ALL HIS PROJECTS" + t3: "READY TO BE FREED" + t4: "ALL THE JAILERS WERE THERE" + t5: "WAITING FOR THE JAILGAMES" + t6: "TO BE RELEASED" + t7: "THERE WERE EVEN BARRULLS AND" + t8: "BEGINNERS AMONG THE CROWD" + t9: "BRY WAS CRYING..." + t10: "BUT SUDDENLY SOMETHING" + t11: "CAUGHT HIS ATTENTION" + t12: "A PILE OF JUNK!" + t13: "FULL OF NON WORKING TRASH!!" + t14: "AND THEN," + t15: "FOURTY NEW PROJECTS" + t16: "WERE BORN..." + +ending2: + starring: "STARRING" + jaildoctor: "JAILDOCTOR" + thank_you: "THANK YOU" + for_playing: "FOR PLAYING!" + +credits: + instructions: "INSTRUCTIONS:" + l0: "HELP JAILDOC TO GET BACK ALL" + l1: "HIS PROJECTS AND GO TO THE" + l2: "JAIL TO FINISH THEM" + keys: "KEYS:" + keys_move: "CURSORS TO MOVE AND JUMP" + f8: "F8 TOGGLE THE MUSIC" + f11: "F11 PAUSE THE GAME" + f1f2: "F1-F2 WINDOWS SIZE" + f3: "F3 TOGGLE FULLSCREEN" + f9: "F9 TOOGLE BORDER SCREEN" + author: "A GAME BY JAILDESIGNER" + date: "MADE ON SUMMER/FALL 2022" + love: "I LOVE JAILGAMES! " + +achievements: + header: "ACHIEVEMENT UNLOCKED!" + c1: "SHINY THINGS" + d1: "Get 25% of the items" + c2: "HALF THE WORK" + d2: "Get 50% of the items" + c3: "GETTING THERE" + d3: "Get 75% of the items" + c4: "THE COLLECTOR" + d4: "Get 100% of the items" + c5: "WANDERING AROUND" + d5: "Visit 20 rooms" + c6: "I GOT LOST" + d6: "Visit 40 rooms" + c7: "I LIKE TO EXPLORE" + d7: "Visit all rooms" + c8: "FINISH THE GAME" + d8: "Complete the game" + c9: "I WAS SUCKED BY A HOLE" + d9: "Complete the game without entering the jail" + c10: "MY LITTLE PROJECTS" + d10: "Complete the game with all items" + c11: "I LIKE MY MULTICOLOURED FRIENDS" + d11: "Complete the game without dying" + c12: "SHIT PROJECTS DONE FAST" + d12: "Complete the game in under 30 minutes" + +ui: + press_again_menu: "PRESS AGAIN TO RETURN TO MENU" + press_again_exit: "PRESS AGAIN TO EXIT" + border_enabled: "BORDER ENABLED" + border_disabled: "BORDER DISABLED" + fullscreen_enabled: "FULLSCREEN ENABLED" + fullscreen_disabled: "FULLSCREEN DISABLED" + window_zoom: "WINDOW ZOOM x" + postfx_enabled: "POSTFX ENABLED" + postfx_disabled: "POSTFX DISABLED" + postfx: "POSTFX" + palette: "PALETTE" + integer_scale_enabled: "INTEGER SCALE ENABLED" + integer_scale_disabled: "INTEGER SCALE DISABLED" + vsync_enabled: "V-SYNC ENABLED" + vsync_disabled: "V-SYNC DISABLED" + +scoreboard: + items: "Items collected " + time: " Time " + rooms: "Rooms" + +game: + music_enabled: "MUSIC ENABLED" + music_disabled: "MUSIC DISABLED" + paused: "GAME PAUSED" + running: "GAME RUNNING" + enabled: " ENABLED" + disabled: " DISABLED" + cheat_infinite_lives: "INFINITE LIVES" + cheat_invincible: "INVINCIBLE" + cheat_jail_open: "JAIL IS OPEN" + debug_enabled: "DEBUG ENABLED" + debug_disabled: "DEBUG DISABLED" + achievement_unlocked: "ACHIEVEMENT UNLOCKED!" + c11: "I LIKE MY MULTICOLOURED FRIENDS" diff --git a/data/room/01.yaml b/data/room/01.yaml index 2a4fd33..753498a 100644 --- a/data/room/01.yaml +++ b/data/room/01.yaml @@ -1,6 +1,7 @@ # THE JAIL room: - name: "THE JAIL" + name_en: "THE JAIL" + name_ca: "LA PRESO" bgColor: bright_blue border: blue tileSetFile: standard.gif diff --git a/data/room/02.yaml b/data/room/02.yaml index 2a2a283..62f7b9b 100644 --- a/data/room/02.yaml +++ b/data/room/02.yaml @@ -1,6 +1,7 @@ # ROAD TO THE JAIL room: - name: "ROAD TO THE JAIL" + name_en: "ROAD TO THE JAIL" + name_ca: "CAMI A LA PRESO" bgColor: black border: blue tileSetFile: standard.gif diff --git a/data/room/03.yaml b/data/room/03.yaml index 89fe68e..dfbd896 100644 --- a/data/room/03.yaml +++ b/data/room/03.yaml @@ -1,6 +1,7 @@ # VOID MAIN room: - name: "VOID MAIN" + name_en: "VOID MAIN" + name_ca: "VOID MAIN" bgColor: black border: magenta tileSetFile: standard.gif diff --git a/data/room/04.yaml b/data/room/04.yaml index 4a8588c..ecccd1b 100644 --- a/data/room/04.yaml +++ b/data/room/04.yaml @@ -1,6 +1,7 @@ # JUMP THROUGH room: - name: "JUMP THROUGH" + name_en: "JUMP THROUGH" + name_ca: "SALTA A TRAVES" bgColor: black border: cyan tileSetFile: standard.gif diff --git a/data/room/05.yaml b/data/room/05.yaml index 76ebe5f..6e3159b 100644 --- a/data/room/05.yaml +++ b/data/room/05.yaml @@ -1,6 +1,7 @@ # BIG JUMP room: - name: "BIG JUMP" + name_en: "BIG JUMP" + name_ca: "GRAN SALT" bgColor: black border: red tileSetFile: standard.gif diff --git a/data/room/06.yaml b/data/room/06.yaml index 5fb3cc9..1dd52c7 100644 --- a/data/room/06.yaml +++ b/data/room/06.yaml @@ -1,6 +1,7 @@ # WELCOME TO MY ABBEY room: - name: "WELCOME TO MY ABBEY" + name_en: "WELCOME TO MY ABBEY" + name_ca: "BENVINGUT A LA MEVA ABADIA" bgColor: blue border: yellow tileSetFile: standard.gif diff --git a/data/room/07.yaml b/data/room/07.yaml index 133c9fa..ebe500f 100644 --- a/data/room/07.yaml +++ b/data/room/07.yaml @@ -1,6 +1,7 @@ # SIGMASUA > TELEGRAM room: - name: "SIGMASUA > TELEGRAM" + name_en: "SIGMASUA > TELEGRAM" + name_ca: "SIGMASUA > TELEGRAM" bgColor: black border: blue tileSetFile: standard.gif diff --git a/data/room/08.yaml b/data/room/08.yaml index ffc03b2..1a181fc 100644 --- a/data/room/08.yaml +++ b/data/room/08.yaml @@ -1,6 +1,7 @@ # THE GARDEN room: - name: "THE GARDEN" + name_en: "THE GARDEN" + name_ca: "EL JARDI" bgColor: black border: cyan tileSetFile: standard.gif diff --git a/data/room/09.yaml b/data/room/09.yaml index 775fc9c..a10558d 100644 --- a/data/room/09.yaml +++ b/data/room/09.yaml @@ -1,6 +1,7 @@ # THE BIG TREE room: - name: "THE BIG TREE" + name_en: "THE BIG TREE" + name_ca: "EL ARBRE GRAN" bgColor: black border: bright_blue tileSetFile: standard.gif diff --git a/data/room/10.yaml b/data/room/10.yaml index a342752..b3002c0 100644 --- a/data/room/10.yaml +++ b/data/room/10.yaml @@ -1,6 +1,7 @@ # TREE TOP room: - name: "TREE TOP" + name_en: "TREE TOP" + name_ca: "CIMA DE L'ARBRE" bgColor: bright_black border: blue tileSetFile: standard.gif diff --git a/data/room/11.yaml b/data/room/11.yaml index e2ba780..cb41b3c 100644 --- a/data/room/11.yaml +++ b/data/room/11.yaml @@ -1,6 +1,7 @@ # LAZY ROOM room: - name: "LAZY ROOM" + name_en: "LAZY ROOM" + name_ca: "SALA MANDROSA" bgColor: black border: blue tileSetFile: standard.gif diff --git a/data/room/12.yaml b/data/room/12.yaml index 4f0d3cc..1884077 100644 --- a/data/room/12.yaml +++ b/data/room/12.yaml @@ -1,6 +1,7 @@ # THE PASSAGE room: - name: "THE PASSAGE" + name_en: "THE PASSAGE" + name_ca: "EL PASSATGE" bgColor: black border: green tileSetFile: standard.gif diff --git a/data/room/13.yaml b/data/room/13.yaml index b18e415..d75f5dd 100644 --- a/data/room/13.yaml +++ b/data/room/13.yaml @@ -1,6 +1,7 @@ # TUNO KILLER room: - name: "TUNO KILLER" + name_en: "TUNO KILLER" + name_ca: "ASSASSI DE TUNERS" bgColor: black border: blue tileSetFile: standard.gif diff --git a/data/room/14.yaml b/data/room/14.yaml index 44f87dd..eda8029 100644 --- a/data/room/14.yaml +++ b/data/room/14.yaml @@ -1,6 +1,7 @@ # KILLING SPREE room: - name: "KILLING SPREE" + name_en: "KILLING SPREE" + name_ca: "MATANCA INDISCRIMINADA" bgColor: black border: blue tileSetFile: standard.gif diff --git a/data/room/15.yaml b/data/room/15.yaml index cfb9761..9185e37 100644 --- a/data/room/15.yaml +++ b/data/room/15.yaml @@ -1,6 +1,7 @@ # NOW THIS IS THE BATCAVE! room: - name: "NOW THIS IS THE BATCAVE!" + name_en: "NOW THIS IS THE BATCAVE!" + name_ca: "AQUESTA SI QUE ES LA BATCOVA!" bgColor: black border: black tileSetFile: standard.gif diff --git a/data/room/16.yaml b/data/room/16.yaml index 8e00a6a..89663aa 100644 --- a/data/room/16.yaml +++ b/data/room/16.yaml @@ -1,6 +1,7 @@ # THE FRIDGE room: - name: "THE FRIDGE" + name_en: "THE FRIDGE" + name_ca: "LA NEVERA" bgColor: blue border: blue tileSetFile: standard.gif diff --git a/data/room/17.yaml b/data/room/17.yaml index cc27cb8..2a29a4c 100644 --- a/data/room/17.yaml +++ b/data/room/17.yaml @@ -1,6 +1,7 @@ # I DID NOT COPY THIS ONE room: - name: "I DID NOT COPY THIS ONE" + name_en: "I DID NOT COPY THIS ONE" + name_ca: "AQUEST NO EL VAIG COPIAR" bgColor: black border: magenta tileSetFile: standard.gif diff --git a/data/room/18.yaml b/data/room/18.yaml index c042b63..87725c5 100644 --- a/data/room/18.yaml +++ b/data/room/18.yaml @@ -1,6 +1,7 @@ # MAKE MONEY room: - name: "MAKE MONEY" + name_en: "MAKE MONEY" + name_ca: "FES DINERS" bgColor: black border: yellow tileSetFile: standard.gif diff --git a/data/room/19.yaml b/data/room/19.yaml index 895e671..4dfcbbd 100644 --- a/data/room/19.yaml +++ b/data/room/19.yaml @@ -1,6 +1,7 @@ # THIS CAN'T BE THE BATCAVE room: - name: "THIS CAN'T BE THE BATCAVE" + name_en: "THIS CAN'T BE THE BATCAVE" + name_ca: "AQUESTA NO POT SER LA BATCOVA" bgColor: black border: cyan tileSetFile: standard.gif diff --git a/data/room/20.yaml b/data/room/20.yaml index 5810ced..842b8ae 100644 --- a/data/room/20.yaml +++ b/data/room/20.yaml @@ -1,6 +1,7 @@ # ENTRANCE TO THE VALLEY room: - name: "ENTRANCE TO THE VALLEY" + name_en: "ENTRANCE TO THE VALLEY" + name_ca: "ENTRADA A LA VALL" bgColor: black border: red tileSetFile: standard.gif diff --git a/data/room/21.yaml b/data/room/21.yaml index ca8c8fd..10072a7 100644 --- a/data/room/21.yaml +++ b/data/room/21.yaml @@ -1,6 +1,7 @@ # ENTER PAKU SIMBEL room: - name: "ENTER PAKU SIMBEL" + name_en: "ENTER PAKU SIMBEL" + name_ca: "ENTRA A PAKU SIMBEL" bgColor: bright_black border: yellow tileSetFile: standard.gif diff --git a/data/room/22.yaml b/data/room/22.yaml index 8a6bddc..f2f279d 100644 --- a/data/room/22.yaml +++ b/data/room/22.yaml @@ -1,6 +1,7 @@ # AEE REMAKE, PLEASE room: - name: "AEE REMAKE, PLEASE" + name_en: "AEE REMAKE, PLEASE" + name_ca: "AEE REMAKE, PLAU" bgColor: bright_black border: yellow tileSetFile: standard.gif diff --git a/data/room/23.yaml b/data/room/23.yaml index 25ebd75..81bfb55 100644 --- a/data/room/23.yaml +++ b/data/room/23.yaml @@ -1,6 +1,7 @@ # INNER CHAMBER room: - name: "INNER CHAMBER" + name_en: "INNER CHAMBER" + name_ca: "CAMBRA INTERIOR" bgColor: black border: bright_yellow tileSetFile: standard.gif diff --git a/data/room/24.yaml b/data/room/24.yaml index e3a7c5b..96a48a5 100644 --- a/data/room/24.yaml +++ b/data/room/24.yaml @@ -1,6 +1,7 @@ # PLAY IT AGAIN, SAM room: - name: "PLAY IT AGAIN, SAM" + name_en: "PLAY IT AGAIN, SAM" + name_ca: "TORNA A TOCAR, SAM" bgColor: black border: bright_yellow tileSetFile: standard.gif diff --git a/data/room/25.yaml b/data/room/25.yaml index db0a561..eb60ff8 100644 --- a/data/room/25.yaml +++ b/data/room/25.yaml @@ -1,6 +1,7 @@ # THE CHAPPEL room: - name: "THE CHAPPEL" + name_en: "THE CHAPPEL" + name_ca: "LA CAPELLA" bgColor: blue border: yellow tileSetFile: standard.gif diff --git a/data/room/26.yaml b/data/room/26.yaml index 72ed9a9..ac1aca7 100644 --- a/data/room/26.yaml +++ b/data/room/26.yaml @@ -1,6 +1,7 @@ # JINGLE BELLS room: - name: "JINGLE BELLS" + name_en: "JINGLE BELLS" + name_ca: "JINGLE BELLS" bgColor: blue border: yellow tileSetFile: standard.gif diff --git a/data/room/27.yaml b/data/room/27.yaml index 467189e..b0d7d55 100644 --- a/data/room/27.yaml +++ b/data/room/27.yaml @@ -1,6 +1,7 @@ # THE BACKYARD room: - name: "THE BACKYARD" + name_en: "THE BACKYARD" + name_ca: "EL PATI" bgColor: blue border: cyan tileSetFile: standard.gif diff --git a/data/room/28.yaml b/data/room/28.yaml index fb22ca4..779b0cc 100644 --- a/data/room/28.yaml +++ b/data/room/28.yaml @@ -1,6 +1,7 @@ # YOU SHALL NOT PASS room: - name: "YOU SHALL NOT PASS" + name_en: "YOU SHALL NOT PASS" + name_ca: "NO PASSARAS" bgColor: bright_black border: black tileSetFile: standard.gif diff --git a/data/room/29.yaml b/data/room/29.yaml index 39fc631..cebe349 100644 --- a/data/room/29.yaml +++ b/data/room/29.yaml @@ -1,6 +1,7 @@ # QUO VOIDIS room: - name: "QUO VOIDIS" + name_en: "QUO VOIDIS" + name_ca: "QUO VOIDIS" bgColor: blue border: bright_black tileSetFile: standard.gif diff --git a/data/room/30.yaml b/data/room/30.yaml index 01e703e..658d16d 100644 --- a/data/room/30.yaml +++ b/data/room/30.yaml @@ -1,6 +1,7 @@ # QVOID IS A JAILGAME! room: - name: "QVOID IS A JAILGAME!" + name_en: "QVOID IS A JAILGAME!" + name_ca: "QVOID ES UN JAILGAME!" bgColor: blue border: bright_black tileSetFile: standard.gif diff --git a/data/room/31.yaml b/data/room/31.yaml index f3e1a45..235ae38 100644 --- a/data/room/31.yaml +++ b/data/room/31.yaml @@ -1,6 +1,7 @@ # 256 COLORS room: - name: "256 COLORS" + name_en: "256 COLORS" + name_ca: "256 COLORS" bgColor: black border: bright_magenta tileSetFile: standard.gif diff --git a/data/room/32.yaml b/data/room/32.yaml index e8ce952..8b2f547 100644 --- a/data/room/32.yaml +++ b/data/room/32.yaml @@ -1,6 +1,7 @@ # ...? room: - name: "...?" + name_en: "...?" + name_ca: "...?" bgColor: black border: cyan tileSetFile: standard.gif diff --git a/data/room/33.yaml b/data/room/33.yaml index 7f75ad6..8d04c22 100644 --- a/data/room/33.yaml +++ b/data/room/33.yaml @@ -1,6 +1,7 @@ # } WE ALL LOVE JAILGAMES } room: - name: "} WE ALL LOVE JAILGAMES }" + name_en: "} WE ALL LOVE JAILGAMES }" + name_ca: "} TOTS ESTIMEM JAILGAMES }" bgColor: black border: bright_black tileSetFile: standard.gif diff --git a/data/room/34.yaml b/data/room/34.yaml index 77d0f4a..4922e88 100644 --- a/data/room/34.yaml +++ b/data/room/34.yaml @@ -1,6 +1,7 @@ # ULA HOP! room: - name: "ULA HOP!" + name_en: "ULA HOP!" + name_ca: "ULA HOP!" bgColor: black border: cyan tileSetFile: standard.gif diff --git a/data/room/35.yaml b/data/room/35.yaml index a83f69a..201eeda 100644 --- a/data/room/35.yaml +++ b/data/room/35.yaml @@ -1,6 +1,7 @@ # SILICON BOOBS room: - name: "SILICON BOOBS" + name_en: "SILICON BOOBS" + name_ca: "PITS DE SILICI" bgColor: black border: bright_green tileSetFile: standard.gif diff --git a/data/room/36.yaml b/data/room/36.yaml index 174e9aa..3310663 100644 --- a/data/room/36.yaml +++ b/data/room/36.yaml @@ -1,6 +1,7 @@ # BE CAREFUL WITH THE FUSE room: - name: "BE CAREFUL WITH THE FUSE" + name_en: "BE CAREFUL WITH THE FUSE" + name_ca: "VIGILA AMB EL FUSIBLE" bgColor: black border: bright_cyan tileSetFile: standard.gif diff --git a/data/room/37.yaml b/data/room/37.yaml index 449e06d..37fbd24 100644 --- a/data/room/37.yaml +++ b/data/room/37.yaml @@ -1,6 +1,7 @@ # CHIP'N CHIP room: - name: "CHIP'N CHIP" + name_en: "CHIP'N CHIP" + name_ca: "CHIP'N CHIP" bgColor: black border: bright_green tileSetFile: standard.gif diff --git a/data/room/38.yaml b/data/room/38.yaml index 39771de..0723a81 100644 --- a/data/room/38.yaml +++ b/data/room/38.yaml @@ -1,6 +1,7 @@ # THE FINAL CROSSOVER room: - name: "THE FINAL CROSSOVER" + name_en: "THE FINAL CROSSOVER" + name_ca: "EL CROSSOVER FINAL" bgColor: bright_black border: yellow tileSetFile: standard.gif diff --git a/data/room/39.yaml b/data/room/39.yaml index e5bb95d..2246fa9 100644 --- a/data/room/39.yaml +++ b/data/room/39.yaml @@ -1,6 +1,7 @@ # YOU'LL BELIEVE AROUNDER CAN FLY room: - name: "YOU'LL BELIEVE AROUNDER CAN FLY" + name_en: "YOU'LL BELIEVE AROUNDER CAN FLY" + name_ca: "CREUREU QUE AROUNDER POT VOLAR" bgColor: black border: cyan tileSetFile: standard.gif diff --git a/data/room/40.yaml b/data/room/40.yaml index b18aab7..0049bd1 100644 --- a/data/room/40.yaml +++ b/data/room/40.yaml @@ -1,6 +1,7 @@ # PREVENT THE CRISIS room: - name: "PREVENT THE CRISIS" + name_en: "PREVENT THE CRISIS" + name_ca: "PREVEU LA CRISI" bgColor: black border: bright_magenta tileSetFile: standard.gif diff --git a/data/room/41.yaml b/data/room/41.yaml index e853150..116ba63 100644 --- a/data/room/41.yaml +++ b/data/room/41.yaml @@ -1,6 +1,7 @@ # AROUND WITH ME room: - name: "AROUND WITH ME" + name_en: "AROUND WITH ME" + name_ca: "VOLTA AMB MI" bgColor: black border: blue tileSetFile: standard.gif diff --git a/data/room/42.yaml b/data/room/42.yaml index 2bf7280..d9b3bd0 100644 --- a/data/room/42.yaml +++ b/data/room/42.yaml @@ -1,6 +1,7 @@ # P.A.C.O. ON THE GO room: - name: "P.A.C.O. ON THE GO" + name_en: "P.A.C.O. ON THE GO" + name_ca: "P.A.C.O. EN MARXA" bgColor: black border: blue tileSetFile: standard.gif diff --git a/data/room/43.yaml b/data/room/43.yaml index 85f2363..e6df19a 100644 --- a/data/room/43.yaml +++ b/data/room/43.yaml @@ -1,6 +1,7 @@ # THE TUBE room: - name: "THE TUBE" + name_en: "THE TUBE" + name_ca: "EL TUB" bgColor: black border: blue tileSetFile: standard.gif diff --git a/data/room/44.yaml b/data/room/44.yaml index 63f3e43..1e6a942 100644 --- a/data/room/44.yaml +++ b/data/room/44.yaml @@ -1,6 +1,7 @@ # SANDWITCH AND COUNTER room: - name: "SANDWITCH AND COUNTER" + name_en: "SANDWITCH AND COUNTER" + name_ca: "SANDVITX I COMPTADOR" bgColor: black border: cyan tileSetFile: standard.gif diff --git a/data/room/45.yaml b/data/room/45.yaml index 105adea..bef8063 100644 --- a/data/room/45.yaml +++ b/data/room/45.yaml @@ -1,6 +1,7 @@ # FEEL THE PRESSURE room: - name: "FEEL THE PRESSURE" + name_en: "FEEL THE PRESSURE" + name_ca: "NOTA LA PRESSIO" bgColor: bright_black border: bright_yellow tileSetFile: standard.gif diff --git a/data/room/46.yaml b/data/room/46.yaml index 6eb5cd4..94c822e 100644 --- a/data/room/46.yaml +++ b/data/room/46.yaml @@ -1,6 +1,7 @@ # FEEL THE HEAT room: - name: "FEEL THE HEAT" + name_en: "FEEL THE HEAT" + name_ca: "NOTA LA CALOR" bgColor: bright_black border: bright_yellow tileSetFile: standard.gif diff --git a/data/room/47.yaml b/data/room/47.yaml index 11e0d03..70f8251 100644 --- a/data/room/47.yaml +++ b/data/room/47.yaml @@ -1,6 +1,7 @@ # THE BATTLE NEVER ENDS room: - name: "THE BATTLE NEVER ENDS" + name_en: "THE BATTLE NEVER ENDS" + name_ca: "LA BATALLA MAI ACABA" bgColor: black border: white tileSetFile: standard.gif diff --git a/data/room/48.yaml b/data/room/48.yaml index 99a6c9b..b5999df 100644 --- a/data/room/48.yaml +++ b/data/room/48.yaml @@ -1,6 +1,7 @@ # WELCOME TO THE JAILBATTLE room: - name: "WELCOME TO THE JAILBATTLE" + name_en: "WELCOME TO THE JAILBATTLE" + name_ca: "BENVINGUTS A LA JAILTAULA" bgColor: green border: bright_green tileSetFile: standard.gif diff --git a/data/room/49.yaml b/data/room/49.yaml index c8fc2be..299593a 100644 --- a/data/room/49.yaml +++ b/data/room/49.yaml @@ -1,6 +1,7 @@ # WE NEED A ROBOT room: - name: "WE NEED A ROBOT" + name_en: "WE NEED A ROBOT" + name_ca: "NECESSITEM UN ROBOT" bgColor: black border: red tileSetFile: standard.gif diff --git a/data/room/50.yaml b/data/room/50.yaml index 125870b..ae953b3 100644 --- a/data/room/50.yaml +++ b/data/room/50.yaml @@ -1,6 +1,7 @@ # STORED JAILGAMES room: - name: "STORED JAILGAMES" + name_en: "STORED JAILGAMES" + name_ca: "JAILGAMES EMMAGATZEMATS" bgColor: black border: blue tileSetFile: standard.gif diff --git a/data/room/51.yaml b/data/room/51.yaml index c4b4ea0..bf82df9 100644 --- a/data/room/51.yaml +++ b/data/room/51.yaml @@ -1,6 +1,7 @@ # MINI ASCII room: - name: "MINI ASCII" + name_en: "MINI ASCII" + name_ca: "MINI ASCII" bgColor: black border: black tileSetFile: standard.gif diff --git a/data/room/52.yaml b/data/room/52.yaml index f321e43..931a60d 100644 --- a/data/room/52.yaml +++ b/data/room/52.yaml @@ -1,6 +1,7 @@ # BREAKOUT.LUA room: - name: "BREAKOUT.LUA" + name_en: "BREAKOUT.LUA" + name_ca: "BREAKOUT.LUA" bgColor: black border: black tileSetFile: standard.gif diff --git a/data/room/53.yaml b/data/room/53.yaml index a34d7f2..4748760 100644 --- a/data/room/53.yaml +++ b/data/room/53.yaml @@ -1,6 +1,7 @@ # P.A.C.O. WORKSHOP room: - name: "P.A.C.O. WORKSHOP" + name_en: "P.A.C.O. WORKSHOP" + name_ca: "TALLER DE P.A.C.O." bgColor: black border: yellow tileSetFile: standard.gif diff --git a/data/room/54.yaml b/data/room/54.yaml index c40a2ac..53b681a 100644 --- a/data/room/54.yaml +++ b/data/room/54.yaml @@ -1,6 +1,7 @@ # THE BASEMENT room: - name: "THE BASEMENT" + name_en: "THE BASEMENT" + name_ca: "EL SOTERRANI" bgColor: black border: blue tileSetFile: standard.gif diff --git a/data/room/55.yaml b/data/room/55.yaml index 2a74b47..a7812a2 100644 --- a/data/room/55.yaml +++ b/data/room/55.yaml @@ -1,6 +1,7 @@ # THAT'S A GUITAR room: - name: "THAT'S A GUITAR" + name_en: "THAT'S A GUITAR" + name_ca: "AIXO ES UNA GUITARRA" bgColor: black border: black tileSetFile: standard.gif diff --git a/data/room/56.yaml b/data/room/56.yaml index 79eb1c4..61aa494 100644 --- a/data/room/56.yaml +++ b/data/room/56.yaml @@ -1,6 +1,7 @@ # HEAVY DEMONS ON LEGGINS room: - name: "HEAVY DEMONS ON LEGGINS" + name_en: "HEAVY DEMONS ON LEGGINS" + name_ca: "DIMONIS PESATS AMB MALLES" bgColor: black border: black tileSetFile: standard.gif diff --git a/data/room/57.yaml b/data/room/57.yaml index afac50d..7e05fa8 100644 --- a/data/room/57.yaml +++ b/data/room/57.yaml @@ -1,6 +1,7 @@ # JAILGAMES GO TO HELL room: - name: "JAILGAMES GO TO HELL" + name_en: "JAILGAMES GO TO HELL" + name_ca: "JAILGAMES ANEU A L'INFERN" bgColor: red border: bright_red tileSetFile: standard.gif diff --git a/data/room/58.yaml b/data/room/58.yaml index 910a8f7..fc8d52c 100644 --- a/data/room/58.yaml +++ b/data/room/58.yaml @@ -1,6 +1,7 @@ # CHIRPING room: - name: "CHIRPING" + name_en: "CHIRPING" + name_ca: "PIULANT" bgColor: black border: magenta tileSetFile: standard.gif diff --git a/data/room/59.yaml b/data/room/59.yaml index 7da4303..de148db 100644 --- a/data/room/59.yaml +++ b/data/room/59.yaml @@ -1,6 +1,7 @@ # STATIC room: - name: "STATIC" + name_en: "STATIC" + name_ca: "ESTATICA" bgColor: black border: bright_magenta tileSetFile: standard.gif diff --git a/data/room/60.yaml b/data/room/60.yaml index f0b2c85..1a52e55 100644 --- a/data/room/60.yaml +++ b/data/room/60.yaml @@ -1,6 +1,7 @@ # MAGNETIC FIELDS room: - name: "MAGNETIC FIELDS" + name_en: "MAGNETIC FIELDS" + name_ca: "CAMPS MAGNETICS" bgColor: black border: bright_red tileSetFile: standard.gif diff --git a/source/core/input/global_inputs.cpp b/source/core/input/global_inputs.cpp index ee9d7d1..fc64940 100644 --- a/source/core/input/global_inputs.cpp +++ b/source/core/input/global_inputs.cpp @@ -6,6 +6,7 @@ #include // Para vector #include "core/input/input.hpp" // Para Input, InputAction, Input::DO_NOT_ALLOW_REPEAT +#include "core/locale/locale.hpp" // Para Locale #include "core/rendering/screen.hpp" // Para Screen #include "game/options.hpp" // Para Options, options, OptionsVideo, Section #include "game/scene_manager.hpp" // Para SceneManager @@ -27,7 +28,7 @@ namespace GlobalInputs { if (stringInVector(Notifier::get()->getCodes(), CODE)) { SceneManager::current = SceneManager::Scene::TITLE; } else { - Notifier::get()->show({CODE}, Notifier::Style::DEFAULT, -1, true, CODE); + Notifier::get()->show({Locale::get()->get("ui.press_again_menu")}, Notifier::Style::DEFAULT, -1, true, CODE); } return; } @@ -47,7 +48,7 @@ namespace GlobalInputs { if (stringInVector(Notifier::get()->getCodes(), CODE)) { SceneManager::current = SceneManager::Scene::QUIT; } else { - Notifier::get()->show({CODE}, Notifier::Style::DEFAULT, -1, true, CODE); + Notifier::get()->show({Locale::get()->get("ui.press_again_exit")}, Notifier::Style::DEFAULT, -1, true, CODE); } } @@ -71,58 +72,58 @@ namespace GlobalInputs { void handleToggleBorder() { Screen::get()->toggleBorder(); - Notifier::get()->show({"BORDER " + std::string(Options::video.border.enabled ? "ENABLED" : "DISABLED")}); + Notifier::get()->show({Locale::get()->get(Options::video.border.enabled ? "ui.border_enabled" : "ui.border_disabled")}); } void handleToggleVideoMode() { Screen::get()->toggleVideoMode(); - Notifier::get()->show({"FULLSCREEN " + std::string(static_cast(Options::video.fullscreen) == 0 ? "DISABLED" : "ENABLED")}); + Notifier::get()->show({Locale::get()->get(static_cast(Options::video.fullscreen) == 0 ? "ui.fullscreen_disabled" : "ui.fullscreen_enabled")}); } void handleDecWindowZoom() { if (Screen::get()->decWindowZoom()) { - Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)}); + Notifier::get()->show({Locale::get()->get("ui.window_zoom") + std::to_string(Options::window.zoom)}); } } void handleIncWindowZoom() { if (Screen::get()->incWindowZoom()) { - Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)}); + Notifier::get()->show({Locale::get()->get("ui.window_zoom") + std::to_string(Options::window.zoom)}); } } void handleTogglePostFX() { Screen::get()->togglePostFX(); - Notifier::get()->show({"POSTFX " + std::string(Options::video.postfx ? "ENABLED" : "DISABLED")}); + Notifier::get()->show({Locale::get()->get(Options::video.postfx ? "ui.postfx_enabled" : "ui.postfx_disabled")}); } void handleNextPostFXPreset() { if (!Options::postfx_presets.empty()) { Options::current_postfx_preset = (Options::current_postfx_preset + 1) % static_cast(Options::postfx_presets.size()); Screen::get()->reloadPostFX(); - Notifier::get()->show({"POSTFX " + Options::postfx_presets[static_cast(Options::current_postfx_preset)].name}); + Notifier::get()->show({Locale::get()->get("ui.postfx") + " " + Options::postfx_presets[static_cast(Options::current_postfx_preset)].name}); } } void handleNextPalette() { Screen::get()->nextPalette(); - Notifier::get()->show({"PALETTE " + Options::video.palette}); + Notifier::get()->show({Locale::get()->get("ui.palette") + " " + Options::video.palette}); } void handlePreviousPalette() { Screen::get()->previousPalette(); - Notifier::get()->show({"PALETTE " + Options::video.palette}); + Notifier::get()->show({Locale::get()->get("ui.palette") + " " + Options::video.palette}); } void handleToggleIntegerScale() { Screen::get()->toggleIntegerScale(); Screen::get()->setVideoMode(Options::video.fullscreen); - Notifier::get()->show({"INTEGER SCALE " + std::string(Options::video.integer_scale ? "ENABLED" : "DISABLED")}); + Notifier::get()->show({Locale::get()->get(Options::video.integer_scale ? "ui.integer_scale_enabled" : "ui.integer_scale_disabled")}); } void handleToggleVSync() { Screen::get()->toggleVSync(); - Notifier::get()->show({"V-SYNC " + std::string(Options::video.vertical_sync ? "ENABLED" : "DISABLED")}); + Notifier::get()->show({Locale::get()->get(Options::video.vertical_sync ? "ui.vsync_enabled" : "ui.vsync_disabled")}); } #ifdef _DEBUG diff --git a/source/core/locale/locale.cpp b/source/core/locale/locale.cpp new file mode 100644 index 0000000..951e899 --- /dev/null +++ b/source/core/locale/locale.cpp @@ -0,0 +1,90 @@ +#include "core/locale/locale.hpp" + +#include +#include +#include + +#include "external/fkyaml_node.hpp" // Para fkyaml::node +#include "game/options.hpp" // Para Options::console + +// [SINGLETON] +Locale* Locale::locale_ = nullptr; + +// [SINGLETON] Crea el objeto con esta función estática +void Locale::init(const std::string& file_path) { + Locale::locale_ = new Locale(); + Locale::locale_->loadFromFile(file_path); +} + +// [SINGLETON] Destruye el objeto con esta función estática +void Locale::destroy() { + delete Locale::locale_; + Locale::locale_ = nullptr; +} + +// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él +auto Locale::get() -> Locale* { + return Locale::locale_; +} + +// Devuelve la traducción de la clave o la clave como fallback +auto Locale::get(const std::string& key) const -> std::string { + auto it = strings_.find(key); + if (it != strings_.end()) { + return it->second; + } + + if (Options::console) { + std::cerr << "Locale: clave no encontrada: " << key << '\n'; + } + return key; +} + +// Aplana un nodo YAML de forma recursiva: {a: {b: "val"}} -> {"a.b" -> "val"} +void Locale::flatten(const void* node_ptr, const std::string& prefix) { + const auto& node = *static_cast(node_ptr); + + for (auto itr = node.begin(); itr != node.end(); ++itr) { + const std::string KEY = prefix.empty() + ? itr.key().get_value() + : prefix + "." + itr.key().get_value(); + + const auto& value = itr.value(); + if (value.is_mapping()) { + flatten(&value, KEY); + } else if (value.is_string()) { + strings_[KEY] = value.get_value(); + } + } +} + +// Carga las traducciones desde el fichero YAML indicado +void Locale::loadFromFile(const std::string& file_path) { + if (file_path.empty()) { + if (Options::console) { + std::cerr << "Locale: ruta de fichero vacía, sin traducciones cargadas\n"; + } + return; + } + + std::ifstream file(file_path); + if (!file.is_open()) { + if (Options::console) { + std::cerr << "Locale: no se puede abrir " << file_path << '\n'; + } + return; + } + + try { + auto yaml = fkyaml::node::deserialize(file); + flatten(&yaml, ""); + + if (Options::console) { + std::cout << "Locale: " << strings_.size() << " traducciones cargadas desde " << file_path << '\n'; + } + } catch (const fkyaml::exception& e) { + if (Options::console) { + std::cerr << "Locale: error al parsear YAML: " << e.what() << '\n'; + } + } +} diff --git a/source/core/locale/locale.hpp b/source/core/locale/locale.hpp new file mode 100644 index 0000000..cd04fb7 --- /dev/null +++ b/source/core/locale/locale.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +// Clase Locale: gestiona las traducciones del juego (singleton) +// Las traducciones se cargan desde un fichero YAML en el inicio. +// No se permite cambio de idioma en caliente. +class Locale { + public: + static void init(const std::string& file_path); // Crea e inicializa el singleton + static void destroy(); // Destruye el singleton + static auto get() -> Locale*; // Devuelve el singleton + + // Devuelve la traducción de la clave dada. + // Si la clave no existe, devuelve la propia clave como fallback. + [[nodiscard]] auto get(const std::string& key) const -> std::string; + + private: + Locale() = default; + void loadFromFile(const std::string& file_path); + void flatten(const void* node_ptr, const std::string& prefix); // Aplana nodos YAML anidados + + static Locale* locale_; + std::unordered_map strings_; +}; diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index 7dfac50..093a4b8 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -13,6 +13,7 @@ #include "core/audio/audio.hpp" // Para Audio #include "core/input/input.hpp" // Para Input, InputAction +#include "core/locale/locale.hpp" // Para Locale #include "core/rendering/screen.hpp" // Para Screen #include "core/resources/resource_cache.hpp" // Para Resource #include "core/resources/resource_helper.hpp" // Para ResourceHelper @@ -162,6 +163,14 @@ Director::Director(std::vector const& args) { std::cout << "\n"; // Fin de inicialización de sistemas + // Inicializa el sistema de localización (antes de Cheevos que usa textos traducidos) +#ifdef RELEASE_BUILD + std::string locale_path = executable_path_ + PREFIX + "/data/locale/" + Options::language + ".yaml"; + Locale::init(locale_path); +#else + Locale::init(Resource::List::get()->get(Options::language + ".yaml")); +#endif + // Special handling for cheevos.bin - also needs filesystem path #ifdef RELEASE_BUILD std::string cheevos_path = system_folder_ + "/cheevos.bin"; @@ -177,6 +186,7 @@ Director::~Director() { // Destruye los singletones Cheevos::destroy(); + Locale::destroy(); #ifdef _DEBUG Debug::destroy(); #endif diff --git a/source/game/defaults.hpp b/source/game/defaults.hpp index 579d857..f0672a0 100644 --- a/source/game/defaults.hpp +++ b/source/game/defaults.hpp @@ -81,6 +81,10 @@ namespace Defaults::Kiosk { constexpr bool INFINITE_LIVES = false; // Vidas infinitas en modo kiosko desactivadas por defecto } // namespace Defaults::Kiosk +namespace Defaults::Localization { + constexpr const char* LANGUAGE = "en"; // Idioma por defecto (en = inglés, ca = catalán) +} // namespace Defaults::Localization + namespace Defaults::Game::Room { #ifdef _DEBUG constexpr const char* INITIAL = "51.yaml"; // Habitación de inicio en debug diff --git a/source/game/gameplay/cheevos.cpp b/source/game/gameplay/cheevos.cpp index 773c063..faa9656 100644 --- a/source/game/gameplay/cheevos.cpp +++ b/source/game/gameplay/cheevos.cpp @@ -8,8 +8,9 @@ #include // Para cout, cerr #include -#include "game/options.hpp" // Para Options, options -#include "game/ui/notifier.hpp" // Para Notifier +#include "core/locale/locale.hpp" // Para Locale +#include "game/options.hpp" // Para Options, options +#include "game/ui/notifier.hpp" // Para Notifier // [SINGLETON] Cheevos* Cheevos::cheevos = nullptr; @@ -44,18 +45,19 @@ Cheevos::~Cheevos() { // Inicializa los logros void Cheevos::init() { cheevos_list_.clear(); - cheevos_list_.emplace_back(Achievement{.id = 1, .caption = "SHINY THINGS", .description = "Get 25% of the items", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 2, .caption = "HALF THE WORK", .description = "Get 50% of the items", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 3, .caption = "GETTING THERE", .description = "Get 75% of the items", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 4, .caption = "THE COLLECTOR", .description = "Get 100% of the items", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 5, .caption = "WANDERING AROUND", .description = "Visit 20 rooms", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 6, .caption = "I GOT LOST", .description = "Visit 40 rooms", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 7, .caption = "I LIKE TO EXPLORE", .description = "Visit all rooms", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 8, .caption = "FINISH THE GAME", .description = "Complete the game", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 9, .caption = "I WAS SUCKED BY A HOLE", .description = "Complete the game without entering the jail", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 10, .caption = "MY LITTLE PROJECTS", .description = "Complete the game with all items", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 11, .caption = "I LIKE MY MULTICOLOURED FRIENDS", .description = "Complete the game without dying", .icon = 2}); - cheevos_list_.emplace_back(Achievement{.id = 12, .caption = "SHIT PROJECTS DONE FAST", .description = "Complete the game in under 30 minutes", .icon = 2}); + auto* loc = Locale::get(); + cheevos_list_.emplace_back(Achievement{.id = 1, .caption = loc->get("achievements.c1"), .description = loc->get("achievements.d1"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 2, .caption = loc->get("achievements.c2"), .description = loc->get("achievements.d2"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 3, .caption = loc->get("achievements.c3"), .description = loc->get("achievements.d3"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 4, .caption = loc->get("achievements.c4"), .description = loc->get("achievements.d4"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 5, .caption = loc->get("achievements.c5"), .description = loc->get("achievements.d5"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 6, .caption = loc->get("achievements.c6"), .description = loc->get("achievements.d6"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 7, .caption = loc->get("achievements.c7"), .description = loc->get("achievements.d7"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 8, .caption = loc->get("achievements.c8"), .description = loc->get("achievements.d8"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 9, .caption = loc->get("achievements.c9"), .description = loc->get("achievements.d9"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 10, .caption = loc->get("achievements.c10"), .description = loc->get("achievements.d10"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 11, .caption = loc->get("achievements.c11"), .description = loc->get("achievements.d11"), .icon = 2}); + cheevos_list_.emplace_back(Achievement{.id = 12, .caption = loc->get("achievements.c12"), .description = loc->get("achievements.d12"), .icon = 2}); } // Busca un logro por id y devuelve el indice @@ -82,7 +84,7 @@ void Cheevos::unlock(int id) { cheevos_list_.at(INDEX).completed = true; // Mostrar notificación en la pantalla - Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", cheevos_list_.at(INDEX).caption}, Notifier::Style::CHEEVO, -1, false); + Notifier::get()->show({Locale::get()->get("achievements.header"), cheevos_list_.at(INDEX).caption}, Notifier::Style::CHEEVO, -1, false); // Guardar el estado de los logros saveToFile(); diff --git a/source/game/gameplay/room_loader.cpp b/source/game/gameplay/room_loader.cpp index 9126656..50265d8 100644 --- a/source/game/gameplay/room_loader.cpp +++ b/source/game/gameplay/room_loader.cpp @@ -5,6 +5,7 @@ #include "core/resources/resource_helper.hpp" // Para Resource::Helper #include "external/fkyaml_node.hpp" // Para fkyaml::node +#include "game/options.hpp" // Para Options::language #include "utils/defines.hpp" // Para Tile::SIZE #include "utils/utils.hpp" // Para stringToColor @@ -63,7 +64,10 @@ void RoomLoader::parseRoomConfig(const fkyaml::node& yaml, Room::Data& room, con room.number = file_name.substr(0, file_name.find_last_of('.')); // Basic properties - if (room_node.contains("name")) { + const std::string LANG_KEY = "name_" + Options::language; + if (room_node.contains(LANG_KEY)) { + room.name = room_node[LANG_KEY].get_value(); + } else if (room_node.contains("name")) { room.name = room_node["name"].get_value(); } if (room_node.contains("bgColor")) { diff --git a/source/game/gameplay/scoreboard.cpp b/source/game/gameplay/scoreboard.cpp index 6b10e0c..c42ab74 100644 --- a/source/game/gameplay/scoreboard.cpp +++ b/source/game/gameplay/scoreboard.cpp @@ -4,6 +4,7 @@ #include +#include "core/locale/locale.hpp" // Para Locale #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite @@ -156,13 +157,13 @@ void Scoreboard::fillTexture() { auto text = Resource::Cache::get()->getText("smb2"); const std::string TIME_TEXT = std::to_string((clock_.minutes % 100) / 10) + std::to_string(clock_.minutes % 10) + clock_.separator + std::to_string((clock_.seconds % 60) / 10) + std::to_string(clock_.seconds % 10); const std::string ITEMS_TEXT = std::to_string(data_->items / 100) + std::to_string((data_->items % 100) / 10) + std::to_string(data_->items % 10); - text->writeColored(Tile::SIZE, LINE1, "Items collected ", data_->color); + text->writeColored(Tile::SIZE, LINE1, Locale::get()->get("scoreboard.items"), data_->color); text->writeColored(17 * Tile::SIZE, LINE1, ITEMS_TEXT, items_color_); - text->writeColored(20 * Tile::SIZE, LINE1, " Time ", data_->color); + text->writeColored(20 * Tile::SIZE, LINE1, Locale::get()->get("scoreboard.time"), data_->color); text->writeColored(26 * Tile::SIZE, LINE1, TIME_TEXT, stringToColor("white")); const std::string ROOMS_TEXT = std::to_string(data_->rooms / 100) + std::to_string((data_->rooms % 100) / 10) + std::to_string(data_->rooms % 10); - text->writeColored(22 * Tile::SIZE, LINE2, "Rooms", stringToColor("white")); + text->writeColored(22 * Tile::SIZE, LINE2, Locale::get()->get("scoreboard.rooms"), stringToColor("white")); text->writeColored(28 * Tile::SIZE, LINE2, ROOMS_TEXT, stringToColor("white")); // Deja el renderizador como estaba diff --git a/source/game/options.cpp b/source/game/options.cpp index de28af1..1401faf 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -487,6 +487,21 @@ namespace Options { } } + // Carga configuración de idioma desde YAML + void loadLocalizationFromYaml(const fkyaml::node& yaml) { + if (yaml.contains("localization")) { + const auto& loc = yaml["localization"]; + + if (loc.contains("language")) { + try { + language = loc["language"].get_value(); + } catch (...) { + language = Defaults::Localization::LANGUAGE; + } + } + } + } + // Crea e inicializa las opciones del programa void init() { #ifdef _DEBUG @@ -550,6 +565,7 @@ namespace Options { loadKeyboardControlsFromYaml(yaml); loadGamepadControlsFromYaml(yaml); loadKioskConfigFromYaml(yaml); + loadLocalizationFromYaml(yaml); if (console) { std::cout << "Config file loaded successfully\n\n"; @@ -640,6 +656,12 @@ namespace Options { file << " text: \"" << kiosk.text << "\"\n"; file << " infinite_lives: " << (kiosk.infinite_lives ? "true" : "false") << "\n"; + // LOCALIZATION + file << "\n"; + file << "# LOCALIZATION (en = English, ca = Catalan)\n"; + file << "localization:\n"; + file << " language: \"" << language << "\"\n"; + file.close(); if (console) { diff --git a/source/game/options.hpp b/source/game/options.hpp index c0a9c6b..87815ff 100644 --- a/source/game/options.hpp +++ b/source/game/options.hpp @@ -139,6 +139,9 @@ namespace Options { inline GamepadControls gamepad_controls{}; // Botones del gamepad usados para jugar inline Kiosk kiosk{}; // Opciones del modo kiosko + // Idioma del juego (establecido al inicio, sin cambio en caliente) + inline std::string language{Defaults::Localization::LANGUAGE}; + // Ruta completa del fichero de configuración (establecida mediante setConfigFile) inline std::string config_file_path{}; diff --git a/source/game/scenes/credits.cpp b/source/game/scenes/credits.cpp index 3812b7f..b4b24f5 100644 --- a/source/game/scenes/credits.cpp +++ b/source/game/scenes/credits.cpp @@ -5,6 +5,7 @@ #include "core/audio/audio.hpp" // Para Audio #include "core/input/global_inputs.hpp" // Para check #include "core/input/input.hpp" // Para Input +#include "core/locale/locale.hpp" // Para Locale #include "core/rendering/pixel_reveal.hpp" // Para PixelReveal #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/surface.hpp" // Para Surface @@ -52,35 +53,35 @@ void Credits::handleInput() { // Inicializa los textos void Credits::iniTexts() { - std::string keys = "CURSORS"; + auto* loc = Locale::get(); texts_.clear(); texts_.push_back({"", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"INSTRUCTIONS:", static_cast(PaletteColor::YELLOW)}); + texts_.push_back({loc->get("credits.instructions"), static_cast(PaletteColor::YELLOW)}); texts_.push_back({"", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"HELP JAILDOC TO GET BACK ALL", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"HIS PROJECTS AND GO TO THE", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"JAIL TO FINISH THEM", static_cast(PaletteColor::WHITE)}); + texts_.push_back({loc->get("credits.l0"), static_cast(PaletteColor::WHITE)}); + texts_.push_back({loc->get("credits.l1"), static_cast(PaletteColor::WHITE)}); + texts_.push_back({loc->get("credits.l2"), static_cast(PaletteColor::WHITE)}); texts_.push_back({"", static_cast(PaletteColor::WHITE)}); texts_.push_back({"", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"KEYS:", static_cast(PaletteColor::YELLOW)}); + texts_.push_back({loc->get("credits.keys"), static_cast(PaletteColor::YELLOW)}); texts_.push_back({"", static_cast(PaletteColor::WHITE)}); - texts_.push_back({keys + " TO MOVE AND JUMP", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"F8 TOGGLE THE MUSIC", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"F11 PAUSE THE GAME", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"F1-F2 WINDOWS SIZE", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"F3 TOGGLE FULLSCREEN", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"F9 TOOGLE BORDER SCREEN", static_cast(PaletteColor::WHITE)}); + texts_.push_back({loc->get("credits.keys_move"), static_cast(PaletteColor::WHITE)}); + texts_.push_back({loc->get("credits.f8"), static_cast(PaletteColor::WHITE)}); + texts_.push_back({loc->get("credits.f11"), static_cast(PaletteColor::WHITE)}); + texts_.push_back({loc->get("credits.f1f2"), static_cast(PaletteColor::WHITE)}); + texts_.push_back({loc->get("credits.f3"), static_cast(PaletteColor::WHITE)}); + texts_.push_back({loc->get("credits.f9"), static_cast(PaletteColor::WHITE)}); texts_.push_back({"", static_cast(PaletteColor::WHITE)}); texts_.push_back({"", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"A GAME BY JAILDESIGNER", static_cast(PaletteColor::YELLOW)}); - texts_.push_back({"MADE ON SUMMER/FALL 2022", static_cast(PaletteColor::YELLOW)}); + texts_.push_back({loc->get("credits.author"), static_cast(PaletteColor::YELLOW)}); + texts_.push_back({loc->get("credits.date"), static_cast(PaletteColor::YELLOW)}); texts_.push_back({"", static_cast(PaletteColor::WHITE)}); texts_.push_back({"", static_cast(PaletteColor::WHITE)}); - texts_.push_back({"I LOVE JAILGAMES! ", static_cast(PaletteColor::WHITE)}); + texts_.push_back({loc->get("credits.love"), static_cast(PaletteColor::WHITE)}); texts_.push_back({"", static_cast(PaletteColor::WHITE)}); } diff --git a/source/game/scenes/ending.cpp b/source/game/scenes/ending.cpp index 40b3612..9b64bee 100644 --- a/source/game/scenes/ending.cpp +++ b/source/game/scenes/ending.cpp @@ -5,6 +5,7 @@ #include "core/audio/audio.hpp" // Para Audio #include "core/input/global_inputs.hpp" // Para check #include "core/input/input.hpp" // Para Input +#include "core/locale/locale.hpp" // Para Locale #include "core/rendering/pixel_reveal.hpp" // Para PixelReveal #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/surface.hpp" // Para Surface @@ -170,37 +171,38 @@ void Ending::updateState(float delta_time) { // Inicializa los textos void Ending::iniTexts() { - // Vector con los textos + // Vector con los textos (traducidos según el idioma activo) std::vector texts; + auto* loc = Locale::get(); // Escena #0 - texts.push_back({"HE FINALLY MANAGED", 32}); - texts.push_back({"TO GET TO THE JAIL", 42}); - texts.push_back({"WITH ALL HIS PROJECTS", 142}); - texts.push_back({"READY TO BE FREED", 152}); + texts.push_back({loc->get("ending.t0"), 32}); + texts.push_back({loc->get("ending.t1"), 42}); + texts.push_back({loc->get("ending.t2"), 142}); + texts.push_back({loc->get("ending.t3"), 152}); // Escena #1 - texts.push_back({"ALL THE JAILERS WERE THERE", 1}); - texts.push_back({"WAITING FOR THE JAILGAMES", 11}); - texts.push_back({"TO BE RELEASED", 21}); + texts.push_back({loc->get("ending.t4"), 1}); + texts.push_back({loc->get("ending.t5"), 11}); + texts.push_back({loc->get("ending.t6"), 21}); - texts.push_back({"THERE WERE EVEN BARRULLS AND", 161}); - texts.push_back({"BEGINNERS AMONG THE CROWD", 171}); + texts.push_back({loc->get("ending.t7"), 161}); + texts.push_back({loc->get("ending.t8"), 171}); - texts.push_back({"BRY WAS CRYING...", 181}); + texts.push_back({loc->get("ending.t9"), 181}); // Escena #2 - texts.push_back({"BUT SUDDENLY SOMETHING", 19}); - texts.push_back({"CAUGHT HIS ATTENTION", 29}); + texts.push_back({loc->get("ending.t10"), 19}); + texts.push_back({loc->get("ending.t11"), 29}); // Escena #3 - texts.push_back({"A PILE OF JUNK!", 36}); - texts.push_back({"FULL OF NON WORKING TRASH!!", 46}); + texts.push_back({loc->get("ending.t12"), 36}); + texts.push_back({loc->get("ending.t13"), 46}); // Escena #4 - texts.push_back({"AND THEN,", 36}); - texts.push_back({"FOURTY NEW PROJECTS", 46}); - texts.push_back({"WERE BORN...", 158}); + texts.push_back({loc->get("ending.t14"), 36}); + texts.push_back({loc->get("ending.t15"), 46}); + texts.push_back({loc->get("ending.t16"), 158}); // Crea los sprites sprite_texts_.clear(); diff --git a/source/game/scenes/ending2.cpp b/source/game/scenes/ending2.cpp index 4e4ddd7..0a48d0e 100644 --- a/source/game/scenes/ending2.cpp +++ b/source/game/scenes/ending2.cpp @@ -7,6 +7,7 @@ #include "core/audio/audio.hpp" // Para Audio #include "core/input/global_inputs.hpp" // Para check #include "core/input/input.hpp" // Para Input +#include "core/locale/locale.hpp" // Para Locale #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/surface_dissolve_sprite.hpp" // Para SurfaceDissolveSprite @@ -403,7 +404,7 @@ void Ending2::createSpriteTexts() { std::string txt = sprite_list_[i]; std::ranges::replace(txt, '_', ' '); // Reemplaza '_' por ' ' if (txt == "player") { - txt = "JAILDOCTOR"; // Reemplaza "player" por "JAILDOCTOR" + txt = Locale::get()->get("ending2.jaildoctor"); // Reemplaza "player" por nombre localizado } // Calcula las dimensiones del texto @@ -438,7 +439,7 @@ void Ending2::createSpriteTexts() { void Ending2::createTexts() { // Crea los primeros textos std::vector list; - list.emplace_back("STARRING"); + list.emplace_back(Locale::get()->get("ending2.starring")); auto text = Resource::Cache::get()->getText("smb2"); @@ -469,8 +470,8 @@ void Ending2::createTexts() { // El primer texto va a continuación del ultimo spriteText const int START = sprite_texts_.back()->getPosY() + (text->getCharacterSize() * 15); list.clear(); - list.emplace_back("THANK YOU"); - list.emplace_back("FOR PLAYING!"); + list.emplace_back(Locale::get()->get("ending2.thank_you")); + list.emplace_back(Locale::get()->get("ending2.for_playing")); // Crea los sprites de texto a partir de la lista for (size_t i = 0; i < list.size(); ++i) { diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 25d78b2..3e0a4b3 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -9,6 +9,7 @@ #include "core/audio/audio.hpp" // Para Audio #include "core/input/global_inputs.hpp" // Para check #include "core/input/input.hpp" // Para Input, InputAction, Input::DO_NOT_ALLOW_REPEAT +#include "core/locale/locale.hpp" // Para Locale #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/text.hpp" // Para Text, Text::CENTER_FLAG, Text::COLOR_FLAG @@ -83,7 +84,7 @@ void Game::handleInput() { if (Input::get()->checkAction(InputAction::TOGGLE_MUSIC, Input::DO_NOT_ALLOW_REPEAT)) { scoreboard_data_->music = !scoreboard_data_->music; scoreboard_data_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic(); - Notifier::get()->show({"MUSIC " + std::string(scoreboard_data_->music ? "ENABLED" : "DISABLED")}); + Notifier::get()->show({scoreboard_data_->music ? Locale::get()->get("game.music_enabled") : Locale::get()->get("game.music_disabled")}); } // Durante fade/postfade, solo procesar inputs globales @@ -95,7 +96,7 @@ void Game::handleInput() { // Input de pausa solo en estado PLAYING if (Input::get()->checkAction(InputAction::PAUSE, Input::DO_NOT_ALLOW_REPEAT)) { togglePause(); - Notifier::get()->show({std::string(paused_ ? "GAME PAUSED" : "GAME RUNNING")}); + Notifier::get()->show({paused_ ? Locale::get()->get("game.paused") : Locale::get()->get("game.running")}); } GlobalInputs::handle(); @@ -370,7 +371,7 @@ void Game::renderPostFadeEnding() { static void toggleCheat(Options::Cheat::State& cheat, const std::string& label) { cheat = (cheat == Options::Cheat::State::ENABLED) ? Options::Cheat::State::DISABLED : Options::Cheat::State::ENABLED; const bool ENABLED = (cheat == Options::Cheat::State::ENABLED); - Notifier::get()->show({label + (ENABLED ? " ENABLED" : " DISABLED")}, Notifier::Style::DEFAULT, -1, true); + Notifier::get()->show({label + (ENABLED ? Locale::get()->get("game.enabled") : Locale::get()->get("game.disabled"))}, Notifier::Style::DEFAULT, -1, true); } // Pasa la información de debug @@ -415,7 +416,7 @@ void Game::handleDebugEvents(const SDL_Event& event) { switch (event.key.key) { case SDLK_F12: Debug::get()->toggleEnabled(); - Notifier::get()->show({"DEBUG " + std::string(Debug::get()->isEnabled() ? "ENABLED" : "DISABLED")}); + Notifier::get()->show({Debug::get()->isEnabled() ? Locale::get()->get("game.debug_enabled") : Locale::get()->get("game.debug_disabled")}); room_->redrawMap(); // Redibuja el tilemap para mostrar/ocultar líneas de colisión Options::cheats.invincible = static_cast(Debug::get()->isEnabled()); player_->setColor(); @@ -444,21 +445,21 @@ void Game::handleDebugEvents(const SDL_Event& event) { break; case SDLK_1: - toggleCheat(Options::cheats.infinite_lives, "INFINITE LIVES"); + toggleCheat(Options::cheats.infinite_lives, Locale::get()->get("game.cheat_infinite_lives")); player_->setColor(); break; case SDLK_2: - toggleCheat(Options::cheats.invincible, "INVINCIBLE"); + toggleCheat(Options::cheats.invincible, Locale::get()->get("game.cheat_invincible")); player_->setColor(); break; case SDLK_3: - toggleCheat(Options::cheats.jail_is_open, "JAIL IS OPEN"); + toggleCheat(Options::cheats.jail_is_open, Locale::get()->get("game.cheat_jail_open")); break; case SDLK_7: - Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, Notifier::Style::CHEEVO, -1, false, "F7"); + Notifier::get()->show({Locale::get()->get("game.achievement_unlocked"), Locale::get()->get("game.c11")}, Notifier::Style::CHEEVO, -1, false, "F7"); break; case SDLK_0: diff --git a/source/game/scenes/game_over.cpp b/source/game/scenes/game_over.cpp index 7fcc499..b329b65 100644 --- a/source/game/scenes/game_over.cpp +++ b/source/game/scenes/game_over.cpp @@ -8,6 +8,7 @@ #include "core/audio/audio.hpp" // Para Audio #include "core/input/global_inputs.hpp" // Para check #include "core/input/input.hpp" // Para Input +#include "core/locale/locale.hpp" // Para Locale #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/rendering/text.hpp" // Para Text::CENTER_FLAG, Text::COLOR_FLAG, Text @@ -68,7 +69,8 @@ void GameOver::render() { auto text = Resource::Cache::get()->getText("smb2"); // Escribe el texto de GAME OVER - text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GameCanvas::CENTER_X, TEXT_Y, "G A M E O V E R", 1, color_); + auto* loc = Locale::get(); + text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GameCanvas::CENTER_X, TEXT_Y, loc->get("game_over.title"), 1, color_); // Dibuja los sprites (ya posicionados en el constructor, solo ajustamos Y) player_sprite_->setPosY(TEXT_Y + SPRITE_Y_OFFSET); @@ -78,11 +80,11 @@ void GameOver::render() { // Escribe el texto con las habitaciones y los items const std::string ITEMS_TEXT = std::to_string(Options::stats.items / 100) + std::to_string((Options::stats.items % 100) / 10) + std::to_string(Options::stats.items % 10); const std::string ROOMS_TEXT = std::to_string(Options::stats.rooms / 100) + std::to_string((Options::stats.rooms % 100) / 10) + std::to_string(Options::stats.rooms % 10); - text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GameCanvas::CENTER_X, TEXT_Y + ITEMS_Y_OFFSET, "ITEMS: " + ITEMS_TEXT, 1, color_); - text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GameCanvas::CENTER_X, TEXT_Y + ROOMS_Y_OFFSET, "ROOMS: " + ROOMS_TEXT, 1, color_); + text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GameCanvas::CENTER_X, TEXT_Y + ITEMS_Y_OFFSET, loc->get("game_over.items") + ITEMS_TEXT, 1, color_); + text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GameCanvas::CENTER_X, TEXT_Y + ROOMS_Y_OFFSET, loc->get("game_over.rooms") + ROOMS_TEXT, 1, color_); // Escribe el texto con "Tu peor pesadilla" - text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GameCanvas::CENTER_X, TEXT_Y + NIGHTMARE_TITLE_Y_OFFSET, "YOUR WORST NIGHTMARE IS", 1, color_); + text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GameCanvas::CENTER_X, TEXT_Y + NIGHTMARE_TITLE_Y_OFFSET, loc->get("game_over.worst_nightmare"), 1, color_); text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GameCanvas::CENTER_X, TEXT_Y + NIGHTMARE_TEXT_Y_OFFSET, Options::stats.worst_nightmare, 1, color_); // Vuelca el contenido del renderizador en pantalla diff --git a/source/game/scenes/title.cpp b/source/game/scenes/title.cpp index 7eb79b0..9d5c251 100644 --- a/source/game/scenes/title.cpp +++ b/source/game/scenes/title.cpp @@ -7,6 +7,7 @@ #include "core/audio/audio.hpp" // Para Audio #include "core/input/global_inputs.hpp" // Para check #include "core/input/input.hpp" // Para Input, InputAction, Input::DO_NOT_ALLOW_REPEAT, REP... +#include "core/locale/locale.hpp" // Para Locale #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/surface_sprite.hpp" // Para SSprite @@ -57,7 +58,7 @@ Title::~Title() { // Inicializa la marquesina void Title::initMarquee() { letters_.clear(); - long_text_ = "HEY JAILERS!! IT'S 2022 AND WE'RE STILL ROCKING LIKE IT'S 1998!!! HAVE YOU HEARD IT? JAILGAMES ARE BACK!! YEEESSS BACK!! MORE THAN 10 TITLES ON JAILDOC'S KITCHEN!! THATS A LOOOOOOT OF JAILGAMES, BUT WHICH ONE WILL STRIKE FIRST? THERE IS ALSO A NEW DEVICE TO COME THAT WILL BLOW YOUR MIND WITH JAILGAMES ON THE GO: P.A.C.O. BUT WAIT! WHAT'S THAT BEAUTY I'M SEEING RIGHT OVER THERE?? OOOH THAT TINY MINIASCII IS PURE LOVE!! I WANT TO LICK EVERY BYTE OF IT!! OH SHIT! AND DON'T FORGET TO BRING BACK THOSE OLD AND FAT MS-DOS JAILGAMES TO GITHUB TO KEEP THEM ALIVE!! WHAT WILL BE THE NEXT JAILDOC RELEASE? WHAT WILL BE THE NEXT PROJECT TO COME ALIVE?? OH BABY WE DON'T KNOW BUT HERE YOU CAN FIND THE ANSWER, YOU JUST HAVE TO COMPLETE JAILDOCTOR'S DILEMMA ... COULD YOU?"; + long_text_ = Locale::get()->get("title.marquee"); // Pre-calcular anchos de caracteres para eficiencia for (size_t i = 0; i < long_text_.length(); ++i) { @@ -460,7 +461,7 @@ void Title::createCheevosTexture() { cheevos_surface_->clear(CHEEVOS_BG_COLOR); // Escribe la lista de logros en la textura - const std::string CHEEVOS_OWNER = "PROJECTS"; + const std::string CHEEVOS_OWNER = Locale::get()->get("title.projects"); const std::string CHEEVOS_LIST_CAPTION = CHEEVOS_OWNER + " (" + std::to_string(Cheevos::get()->getTotalUnlockedAchievements()) + " / " + std::to_string(Cheevos::get()->size()) + ")"; int pos = 2; TEXT->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, cheevos_surface_->getWidth() / 2, pos, CHEEVOS_LIST_CAPTION, 1, stringToColor("bright_green")); @@ -528,10 +529,11 @@ void Title::renderMainMenu() { const int TOTAL_HEIGHT = 3 * SPACING; // 3 espacios entre 4 items const int START_Y = MENU_CENTER_Y - (TOTAL_HEIGHT / 2); - menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, "1. PLAY", 1, COLOR); - menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y + SPACING, "2. REDEFINE KEYBOARD", 1, COLOR); - menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y + (2 * SPACING), "3. REDEFINE JOYSTICK", 1, COLOR); - menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y + (3 * SPACING), "4. PROJECTS", 1, COLOR); + auto* loc = Locale::get(); + menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, loc->get("title.menu.play"), 1, COLOR); + menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y + SPACING, loc->get("title.menu.keyboard"), 1, COLOR); + menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y + (2 * SPACING), loc->get("title.menu.joystick"), 1, COLOR); + menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y + (3 * SPACING), loc->get("title.menu.projects"), 1, COLOR); } // Dibuja el menu de logros @@ -582,13 +584,13 @@ void Title::handleKeyboardRemap(const SDL_Event& event) { // Valida la tecla if (!isKeyValid(scancode)) { - remap_error_message_ = "INVALID KEY! TRY ANOTHER"; + remap_error_message_ = Locale::get()->get("title.keys.invalid"); return; } // Verifica duplicados if (isKeyDuplicate(scancode, remap_step_)) { - remap_error_message_ = "KEY ALREADY USED! TRY ANOTHER"; + remap_error_message_ = Locale::get()->get("title.keys.already_used"); return; } @@ -679,29 +681,28 @@ void Title::renderKeyboardRemap() { const int START_Y = MENU_CENTER_Y - (2 * TEXT_SIZE); // Centrado aproximado // Mensaje principal: "PRESS KEY FOR [ACTION]" o "KEYS DEFINED" si completado + auto* loc = Locale::get(); if (remap_step_ >= 3) { - menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, "KEYS DEFINED", 1, COLOR); + menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, loc->get("title.keys.defined"), 1, COLOR); } else { - const std::string ACTION = getActionName(remap_step_); - const std::string MESSAGE = "PRESS KEY FOR " + ACTION; - menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, MESSAGE, 1, COLOR); + menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, loc->get("title.keys.prompt" + std::to_string(remap_step_)), 1, COLOR); } // Mostrar teclas ya capturadas (con espaciado de 2 líneas desde el mensaje principal) const int KEYS_START_Y = START_Y + (2 * LINE_SPACING); if (remap_step_ > 0) { const std::string LEFT_KEY = SDL_GetScancodeName(temp_keys_[0]); - const std::string LEFT_MSG = "LEFT: " + LEFT_KEY; + const std::string LEFT_MSG = loc->get("title.keys.label0") + LEFT_KEY; menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, KEYS_START_Y, LEFT_MSG, 1, COLOR); } if (remap_step_ > 1) { const std::string RIGHT_KEY = SDL_GetScancodeName(temp_keys_[1]); - const std::string RIGHT_MSG = "RIGHT: " + RIGHT_KEY; + const std::string RIGHT_MSG = loc->get("title.keys.label1") + RIGHT_KEY; menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, KEYS_START_Y + LINE_SPACING, RIGHT_MSG, 1, COLOR); } if (remap_step_ >= 3) { const std::string JUMP_KEY = SDL_GetScancodeName(temp_keys_[2]); - const std::string JUMP_MSG = "JUMP: " + JUMP_KEY; + const std::string JUMP_MSG = loc->get("title.keys.label2") + JUMP_KEY; menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, KEYS_START_Y + (2 * LINE_SPACING), JUMP_MSG, 1, COLOR); } @@ -728,29 +729,28 @@ void Title::renderJoystickRemap() { const int START_Y = MENU_CENTER_Y - (2 * TEXT_SIZE); // Centrado aproximado // Mensaje principal: "PRESS BUTTON FOR [ACTION]" o "BUTTONS DEFINED" si completado + auto* loc = Locale::get(); if (remap_step_ >= 3) { - menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, "BUTTONS DEFINED", 1, COLOR); + menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, loc->get("title.buttons.defined"), 1, COLOR); } else { - const std::string ACTION = getActionName(remap_step_); - const std::string MESSAGE = "PRESS BUTTON FOR " + ACTION; - menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, MESSAGE, 1, COLOR); + menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, loc->get("title.buttons.prompt" + std::to_string(remap_step_)), 1, COLOR); } // Mostrar botones ya capturados (con espaciado de 2 líneas desde el mensaje principal) const int BUTTONS_START_Y = START_Y + (2 * LINE_SPACING); if (remap_step_ > 0) { const std::string LEFT_BTN = getButtonName(temp_buttons_[0]); - const std::string LEFT_MSG = "LEFT: " + LEFT_BTN; + const std::string LEFT_MSG = loc->get("title.keys.label0") + LEFT_BTN; menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, BUTTONS_START_Y, LEFT_MSG, 1, COLOR); } if (remap_step_ > 1) { const std::string RIGHT_BTN = getButtonName(temp_buttons_[1]); - const std::string RIGHT_MSG = "RIGHT: " + RIGHT_BTN; + const std::string RIGHT_MSG = loc->get("title.keys.label1") + RIGHT_BTN; menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, BUTTONS_START_Y + LINE_SPACING, RIGHT_MSG, 1, COLOR); } if (remap_step_ >= 3) { const std::string JUMP_BTN = getButtonName(temp_buttons_[2]); - const std::string JUMP_MSG = "JUMP: " + JUMP_BTN; + const std::string JUMP_MSG = loc->get("title.keys.label2") + JUMP_BTN; menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, BUTTONS_START_Y + (2 * LINE_SPACING), JUMP_MSG, 1, COLOR); } @@ -805,7 +805,7 @@ void Title::handleJoystickRemap(const SDL_Event& event) { // Verifica duplicados if (isButtonDuplicate(captured_button, remap_step_)) { - remap_error_message_ = "BUTTON ALREADY USED! TRY ANOTHER"; + remap_error_message_ = Locale::get()->get("title.buttons.already_used"); return; }