diff --git a/files.cmake b/files.cmake index eb8c62bee5..60a97526c5 100644 --- a/files.cmake +++ b/files.cmake @@ -1481,6 +1481,8 @@ set(DUSK_FILES src/dusk/ui/graphics_tuner.hpp src/dusk/ui/input.cpp src/dusk/ui/input.hpp + src/dusk/ui/i18n.cpp + src/dusk/ui/i18n.hpp src/dusk/ui/modal.cpp src/dusk/ui/modal.hpp src/dusk/ui/nav_types.hpp diff --git a/include/dusk/settings.h b/include/dusk/settings.h index bd6f30683b..5e2770a726 100644 --- a/include/dusk/settings.h +++ b/include/dusk/settings.h @@ -142,6 +142,7 @@ struct UserSettings { ConfigVar enableAchievementToasts; ConfigVar enableControllerToasts; ConfigVar enableDiscordPresence; + ConfigVar enableChineseNameKeyboard; // Graphics ConfigVar bloomMode; @@ -219,6 +220,7 @@ struct UserSettings { struct { ConfigVar isoPath; ConfigVar isoVerification; + ConfigVar uiLanguage; ConfigVar graphicsBackend; ConfigVar skipPreLaunchUI; ConfigVar showPipelineCompilation; diff --git a/res/HarmonyOS_Sans_Regular.ttf b/res/HarmonyOS_Sans_Regular.ttf new file mode 100644 index 0000000000..aff150a137 Binary files /dev/null and b/res/HarmonyOS_Sans_Regular.ttf differ diff --git a/res/HarmonyOS_Sans_SC_Regular.ttf b/res/HarmonyOS_Sans_SC_Regular.ttf new file mode 100644 index 0000000000..aff150a137 Binary files /dev/null and b/res/HarmonyOS_Sans_SC_Regular.ttf differ diff --git a/res/HarmonyOS_Sans_TC_Regular.ttf b/res/HarmonyOS_Sans_TC_Regular.ttf new file mode 100644 index 0000000000..63f7a1b0ec Binary files /dev/null and b/res/HarmonyOS_Sans_TC_Regular.ttf differ diff --git a/res/i18n/en.xml b/res/i18n/en.xml new file mode 100644 index 0000000000..ecc119e5c3 --- /dev/null +++ b/res/i18n/en.xml @@ -0,0 +1,488 @@ + + + Prelaunch + Video + Input + Audio + Gameplay + Cheats + Interface + Display + Resolution + Post-Processing + Rendering + Controller + Camera + Gyro + Tools + Volume + Effects + Tweaks + General + Difficulty + Quality of Life + Speedrunning + Resources + Abilities + Dusklight + Types + Game + UI Language + English + Simplified Chinese +
Applies to Dusklight UI text.
+ Settings + Warp + Editor + Achievements + Reset + Quit + Reset Timer + Verifying disc image + Cancelling... + Opening disc image... + Play + Select Disc Image + No disc image found. + Pending restart. + Disc ready. + Disc hash mismatch. + Disc not verified. + Disc unavailable. + Checking for updates... + Update available! + Failed to check for updates + Reset Game + Unsaved progress will be lost. + Unsaved progress will be lost.
Tip: You can also reset by holding Start+X+B
+ Cancel + Quit Dusklight + Update check failed with an unknown exception +

You may proceed at your own risk.
+ Disc verification warning + Continue anyway + Disc verification error + OK + Restart later + Restart now + Apply Options + A restart is required to apply selected options.

Restart now to apply them immediately?
+ A restart is required to apply selected options.

Close and reopen Dusklight to apply them.
+ Disc Image + Set the disc image that Dusklight uses to launch the game.

Changes require a restart.
+ Data Folder + The data folder is where Dusklight stores settings, saves, logs, texture replacements, and other app data. + Use Texture Pack + Open Data Folder + Output Resampling + Change Data Folder + Portable Mode + Reset to Default + Data will be migrated automatically on restart. + Language + German + French + Spanish + Italian +
Changes require a restart.
+ Graphics Backend + Save File Type + Open the folder where Dusklight stores settings, saves, logs, texture replacements, and other app data. + Enable installed texture replacements. + Notifications + Off + All + Some + Select All + Select None +
Choose which notifications can be displayed.
+ Crash Reporting + Dusklight can automatically send crash reports to the developers. Crash reports contain the following:
• Operating system version
• CPU architecture
• GPU model & driver version
• File paths (may include account username)
• Stack trace
+ Skip Dusklight Main Menu + When starting Dusklight, skip the main menu and boot straight into the game if a disc image is available. + Show Pipeline Compilation + Show an overlay when shaders are being compiled for your hardware. + Check for Updates + Checks GitHub releases for a new Dusklight version on startup.

No personal information is transmitted or collected.
+ Chinese Name Keyboard + Replaces the in-game name entry keyboard with common Chinese characters. Use this with disc images that include a Chinese game font. + No controller assigned + Configure controller port 1 in Settings. + 3-finger tap or + Press F1 or + to open menu + LiveSplit connected + LiveSplit disconnected + Master Volume + Keyboard + Not bound + Mouse Left + Mouse Middle + Mouse Right + Mouse X1 + Mouse X2 + Unknown + Port + Buttons + Triggers + Sticks + Rumble + Custom Action Bindings + Options + Enable Dead Zones + Apply configured dead zones to the sticks and analog triggers. + Emulate Triggers + Treat analog trigger movement as digital L and R button input. + No controllers detected + D-Pad + No controller selected + Analog + Digital + Emulated Trigger Thresholds + L Threshold + R Threshold + Control Stick + C Stick + Deadzone + Test Rumble + Start + Stop + Low Rumble Frequency + High Rumble Frequency + Configure your desired rumble intensities, then run a test to check how they feel. + A key bound to any action here will REPLACE the default control for that action. Only bind buttons here that aren't used anywhere else. + A button bound to any action here will REPLACE the default control for that action. Only bind buttons here that aren't used anywhere else. The glyphs shown for in game actions will not change. This is not recommended for regular Gamecube controllers. + Press a button... + Waiting... + Move axis or press a button... + Press a key or mouse button... + Challenge + Collection + Minigame + Misc + Glitched + Unlocked + Locked + Clear? + Actions + Clear All Achievements + Are you sure? + Achievement Unlocked! + Hero of Twilight + Deliver the finishing blow to Ganondorf. + Completionist + Complete the game after collecting all equipment, heart containers, portals, bugs, poes, and hidden skills. + The Princess of Bugs + Deliver all 24 golden bugs to Agitha. + Poe Collector + Collect all 60 Poe Souls. + Legendary Catch + Catch a Hylian Loach. + Gone Fishin' + Catch all 6 species of fish. + A Big Heart + Reach maximum health with all 20 heart containers. + Glassware Guardian + Obtain all 4 bottles. + Master of Secrets + Learn all 7 Hidden Skills. + We Deliver! + Collect all 16 postman letters. + Conqueror of Ordeals + Clear all 50 floors of the Cave of Ordeals. + Indomitable + Clear all 50 floors of the Cave of Ordeals with only 3 heart containers. + Been There Done That + Defeat Ganondorf with a total save file play time under 12 hours. + Swift Blade + Defeat Ganondorf with a total save file play time under 6 hours. + Mortal Edge + Defeat Dark Hammer in a single hit. + Deathless + Defeat Ganondorf with 0 deaths on your save file. + Untouchable + Kill 25 enemies in a row without taking damage. + Long Shot + Hit an enemy from over 100 meters away with the bow. + Thank You Berry Much + Score 61,454 points in the Plumm minigame. + Rollgoal Novice + Complete the first 8 rollgoal stages. + Lost Your Marbles + Complete all rollgoal stages. + Ranch Hand + Herd all 20 goats into the pen in under 30 seconds. + Bane of Howard + Herd all 20 goats into the pen in under 20 seconds. + King of the Ranch + Herd all 20 goats into the pen in under 18 seconds. + Downhill Dash + Finish the snowboarding minigame in under 70 seconds. + River Raider + Achieve a perfect score in the canoe minigame. + Rising Star + Complete the STAR Prize 2 minigame in under 40 seconds. + Shooting Star + Complete the STAR Prize 2 minigame in under 30 seconds. + Friendly Fire + Get hit by your own cannonball. + Long Jump Attack + Travel more than 20 meters in a single jump attack before landing. + Email Me + Read a letter during the Dark Beast Ganon fight. + Heavy Hitter + Wear the Iron Boots during the end credits. + Here Fishy Fishy + Confuse Ganondorf with the fishing rod. + Petty Theft + Steal from Trill. + Cucco Whisperer + Take control of a cucco. + Back in Time + Perform the Back in Time glitch to play on the title screen. + Early Master Sword + Obtain the Master Sword before completing Midna's Desperate Hour. + Earliest Master Sword + Obtain the Master Sword before meeting Midna. + Hero of Time + Defeat Ganondorf with a total save file play time under 4 hours. + No Fish Suit No Problem + Defeat Morpheel without equipping Zora Armor. + Null Item + Obtain the mysterious black rupee in the item wheel. + Stallord Skip + Leave Stallord's arena through the exit without defeating Stallord. + White Midna Glitch + Clear the Lakebed Temple before clearing Lanayru's Twilight. + Quick Detour + Rescue the Hidden Village before clearing Goron Mines. + Must Have Been The Wind + Complete the Forest Temple without obtaining the Gale Boomerang. + Adjusts the volume of all sounds in the game. + Allow Background Input + Allow controller input even when the game window is not focused. + Allows Wolf Link to howl and change the time of day. + Always collect Rupees even if your Wallet is too full. + Autosave + Autosaves the game when going to a new area, opening a dungeon door, or getting a new item. + Bigger Wallets + Bloom + Bloom Brightness + Bottom Left + Bottom Right + Configure Controller + Connect to LiveSplit server on localhost:16834. For this to work you must right click LiveSplit, and turn on Control -> Start TCP Server. To see IGT in LiveSplit you must change your comparison to Game Time. + Damage Multiplier + Disable Cutscene Pillarboxing + Disable Rupee Cutscenes + Disable the beeping sound when having low health. + Disables the elements of the main HUD of the game.
Useful for a more immersive experience.
+
Display the current framerate in a corner of the screen while playing.
+ Display the RTA timer. IGT is always visible. + Dusklight Menu Sounds + Emulate surround sound via HRTF. Recommended only for use with headphones! + Enable Depth of Field + Enable Mini-Map Shadows + Enable Reverb + Enable Rotating Link Doll + Enable Spatial Sound + Enable VSync + Enables gyro controls for Rollgoal in Hena's Cabin. + Enables gyro controls while in look mode, aiming a hawk, and aiming supported items.

Supported items include the Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s), Ball and Chain, and Dominion Rod.
+ Enables rotating Link in the collection menu with the C-Stick. + Enables speedrunning options while restricting certain gameplay modifiers. + Enables the reverb effect in game audio. + Enables twin-stick camera control, letting the C-Stick move the camera vertically as well as horizontally. + Faster Climbing + Faster Tears of Light + Free Camera + Free Camera Sensitivity + Gyro Aim + Gyro Deadband + Gyro Input Method + Gyro Pitch Sensitivity + Gyro Rollgoal + Gyro Smoothing + Gyro Yaw Sensitivity + Hearts will never drop from enemies, pots, and various other places. + Hold B for Instant Text + Hold Tab to increase game speed by up to 4x. + Ignores small gyro movement to reduce drift and jitter. + Instant Death + Instant Saves + Internal Resolution + Invert Camera X Axis + Invert Camera Y Axis + Invert First Person X Axis + Invert First Person Y Axis + Invert Gyro Pitch + Invert Gyro Yaw + Invert horizontal camera movement. + Invert horizontal gyro aiming. + Invert horizontal movement while aiming with items or first person camera. Applies only to the control stick (the gyroscope can be inverted in Input settings). + Invert vertical camera movement when Free Camera is enabled. + Invert vertical gyro aiming. + Invert vertical movement while aiming with items or first person camera. Applies only to the control stick (the gyroscope can be inverted in Input settings). + Link will not recoil when his sword hits walls. + LiveSplit Connection + Lock 4:3 Aspect Ratio + Lock the game's aspect ratio to the original. + Makes text scroll immediately by holding B. + Minimal HUD + Mirror Mode + Mirrors the world horizontally, matching the Wii version of the game. + Mouse + Multiplies incoming damage. + No 2nd Fish for Cat + No Climbing Miss Animation + No Heart Drops + No Low HP Sound + No Rupee Returns + No Sword Recoil + Non-Stop Midna's Lament + Open controller binding configuration. + Pause on Focus Lost + Pause the game when window focus is lost. + Play sound effects when navigating the Dusklight menu. + Press + Prevents enemy music while Midna's Lament is playing. + Prevents Link from playing a struggle animation when grabbing ledges or climbing on vines. + Quick Transform (R+Y) + Quicker climbing on ladders and vines like the HD version. + Reset Key + Restore Default Window Size + Restore Default Controls + Restores all binding configurations for the currently selected device to their defaults. + Restore Wii 1.0 Glitches + Restores patched glitches from Wii USA 1.0, the first released version. + Rollgoal Sensitivity + Rupees will not play cutscenes after you have collected them the first time. + Sensor +
Sensor reads motion directly from a supported controller's gyro via SDL.

Mouse treats mouse input as gyro, intended for use with the Steam Deck.

Mouse input cannot currently be used with Gyro Rollgoal.
+ Shadow Resolution + Show FPS Counter + Show RTA + Skip needing to catch a second fish for Sera's cat. + Skips the delay when writing to the Memory Card. + Speedrun Mode + Sun's Song (R+X) + Synchronizes the frame rate to your monitor's refresh rate. + Tears of Light dropped by Shadow Insects pop out faster like the HD version. + Toggle Fullscreen + Top Left + Top Right + Transform instantly by pressing R and Y simultaneously. + Turbo Key + Framerate Cap + Limit the frame rate to the specified value. + Unlock Framerate + Unlimited + Wallet sizes are like in the HD version. (500, 1000, 2000) + Japanese + Any hit will instantly kill you. + Controls how strongly gyro input tilts the Rollgoal table. + to reset the game. + Adjusts twin-stick camera sensitivity. + Controls vertical gyro aiming sensitivity. + Configure the sampling method used when scaling the internal resolution for final presentation. + Controls horizontal gyro aiming sensitivity. + Higher values smooth gyro input over time. + Infinite Hearts + Keeps your health full. + Infinite Arrows + Keeps your arrow count full. + Infinite Seeds + Keeps your slingshot pellets (seeds) full. + Infinite Bombs + Keeps all bomb bags full. + Infinite Oil + Keeps your lantern oil full. + Infinite Oxygen + Keeps your underwater oxygen meter full. + Infinite Rupees + Keeps your rupee count full. + No Item Timer + Item drops such as rupees and hearts will never disappear after they drop. + Moon Jump (R+A) + Hold R and A to rise into the air. + Super Clawshot + Extends Clawshot behavior beyond the normal game rules. + Always Greatspin + Allows the Great Spin attack without requiring full health. + Fast Iron Boots + Speeds up movement while wearing the Iron Boots. + Can Transform Anywhere + Allows transforming even if NPCs are looking. + Fast Roll + Makes Link's roll animation and movement twice as fast. + Fast Spinner + Speeds up Spinner movement while holding R. + Free Magic Armor + Lets the magic armor work without consuming rupees. + Invincible Enemies + Prevents enemies from taking damage. + Capped + On + None + Show Internal Names + Maps + Destination + Region + Map + Room + Point + Layer + Action + Warp to the selected destination. + Welcome to Dusklight + Choose a preset to get started. You can change any setting later from the Settings menu. + Classic + Enhancements disabled to match the GameCube version. Good for speedrunning or simple nostalgia! + Dusk + Graphics & quality of life tweaks, including some from the Wii U version. Our recommended way to play! + Send Crash Reports + Dusklight can automatically send crash reports to the developers. Crash reports contain the following:
• Operating system version
• CPU architecture
• GPU model & driver version
• File paths (may include account username)
• Stack trace

This can be changed in the Settings menu at any time.
+ Enable + Disable + Send crash reports to Dusklight developers. Reports will include the information described above. + Do not send crash reports. This may make it more difficult to resolve issues you encounter. + Current data folder: + Data Folder Not Changed + Enable Discord Rich Presence + Enable Dusk to integrate with Discord Rich Presence. This allows Discord to show your status in-game. + Enable Advanced Settings + Show advanced settings and debugging tools with Shift+F1.

WARNING: Debugging tools can easily break your game. Do not use on a regular save!
+ Show Input Viewer + Display a controller input overlay while playing. + Show Gyro Input Viewer + Show gyro sensor values in the input viewer. + Skip TV Settings Screen + Skips the TV calibration screen shown when loading a save. + Recording Mode + Disables the game HUD and all background music.

Useful for recording footage.
+ Auto + Return + Twilit Realm + presents + Version + Game Disc Images + All Files + Download + The selected disc image could not be validated. + Unable to read the selected file. + The selected file is not a valid disc image. + The selected game is not supported by Dusklight. + Dusklight currently supports GameCube USA and PAL disc images only. + Disc verification was canceled. Dusklight cannot guarantee the selected disc image is compatible. + The selected disc image did not pass hash verification. It may be corrupt or modified. + The selected disc image is valid. + Card Image + GCI Folder + Configure the resolution used for rendering the game. Higher values are more demanding on your graphics hardware. + Configure the shadow-map resolution. Higher values improve shadow quality but increase GPU and memory usage. + Configure the post-processing bloom effect. Classic uses the original bloom pass; Dusklight uses a higher-quality bloom pass. + Configure bloom intensity. Higher values make bright areas glow more strongly. + Uses inter-frame interpolation to enable higher frame rates.

May introduce minor visual artifacts or animation glitches.
+ Controller connected + Controller disconnected +
diff --git a/res/i18n/fr.xml b/res/i18n/fr.xml new file mode 100644 index 0000000000..d609b0214d --- /dev/null +++ b/res/i18n/fr.xml @@ -0,0 +1,486 @@ + + + Prelaunch + Video + Input + Audio + Gameplay + Cheats + Interface + Display + Resolution + Post-Processing + Rendering + Controller + Camera + Gyro + Tools + Volume + Effects + Tweaks + General + Difficulty + Quality of Life + Speedrunning + Resources + Abilities + Dusklight + Types + Game + UI Language + English + Simplified Chinese +
Applies to Dusklight UI text.
+ Settings + Warp + Editor + Achievements + Reset + Quit + Reset Timer + Verifying disc image + Cancelling... + Opening disc image... + Play + Select Disc Image + No disc image found. + Pending restart. + Disc ready. + Disc hash mismatch. + Disc not verified. + Disc unavailable. + Checking for updates... + Update available! + Failed to check for updates + Reset Game + Unsaved progress will be lost. + Unsaved progress will be lost.
Tip: You can also reset by holding Start+X+B
+ Cancel + Quit Dusklight + Update check failed with an unknown exception +

You may proceed at your own risk.
+ Disc verification warning + Continue anyway + Disc verification error + OK + Restart later + Restart now + Apply Options + A restart is required to apply selected options.

Restart now to apply them immediately?
+ A restart is required to apply selected options.

Close and reopen Dusklight to apply them.
+ Disc Image + Set the disc image that Dusklight uses to launch the game.

Changes require a restart.
+ Data Folder + The data folder is where Dusklight stores settings, saves, logs, texture replacements, and other app data. + Use Texture Pack + Open Data Folder + Output Resampling + Change Data Folder + Portable Mode + Reset to Default + Data will be migrated automatically on restart. + Language + German + French + Spanish + Italian +
Changes require a restart.
+ Graphics Backend + Save File Type + Open the folder where Dusklight stores settings, saves, logs, texture replacements, and other app data. + Enable installed texture replacements. + Notifications + Off + All + Some + Select All + Select None +
Choose which notifications can be displayed.
+ Crash Reporting + Dusklight can automatically send crash reports to the developers. Crash reports contain the following:
• Operating system version
• CPU architecture
• GPU model & driver version
• File paths (may include account username)
• Stack trace
+ Skip Dusklight Main Menu + When starting Dusklight, skip the main menu and boot straight into the game if a disc image is available. + Show Pipeline Compilation + Show an overlay when shaders are being compiled for your hardware. + Check for Updates + Checks GitHub releases for a new Dusklight version on startup.

No personal information is transmitted or collected.
+ No controller assigned + Configure controller port 1 in Settings. + 3-finger tap or + Press F1 or + to open menu + LiveSplit connected + LiveSplit disconnected + Master Volume + Keyboard + Not bound + Mouse Left + Mouse Middle + Mouse Right + Mouse X1 + Mouse X2 + Unknown + Port + Buttons + Triggers + Sticks + Rumble + Custom Action Bindings + Options + Enable Dead Zones + Apply configured dead zones to the sticks and analog triggers. + Emulate Triggers + Treat analog trigger movement as digital L and R button input. + No controllers detected + D-Pad + No controller selected + Analog + Digital + Emulated Trigger Thresholds + L Threshold + R Threshold + Control Stick + C Stick + Deadzone + Test Rumble + Start + Stop + Low Rumble Frequency + High Rumble Frequency + Configure your desired rumble intensities, then run a test to check how they feel. + A key bound to any action here will REPLACE the default control for that action. Only bind buttons here that aren't used anywhere else. + A button bound to any action here will REPLACE the default control for that action. Only bind buttons here that aren't used anywhere else. The glyphs shown for in game actions will not change. This is not recommended for regular Gamecube controllers. + Press a button... + Waiting... + Move axis or press a button... + Press a key or mouse button... + Challenge + Collection + Minigame + Misc + Glitched + Unlocked + Locked + Clear? + Actions + Clear All Achievements + Are you sure? + Achievement Unlocked! + Hero of Twilight + Deliver the finishing blow to Ganondorf. + Completionist + Complete the game after collecting all equipment, heart containers, portals, bugs, poes, and hidden skills. + The Princess of Bugs + Deliver all 24 golden bugs to Agitha. + Poe Collector + Collect all 60 Poe Souls. + Legendary Catch + Catch a Hylian Loach. + Gone Fishin' + Catch all 6 species of fish. + A Big Heart + Reach maximum health with all 20 heart containers. + Glassware Guardian + Obtain all 4 bottles. + Master of Secrets + Learn all 7 Hidden Skills. + We Deliver! + Collect all 16 postman letters. + Conqueror of Ordeals + Clear all 50 floors of the Cave of Ordeals. + Indomitable + Clear all 50 floors of the Cave of Ordeals with only 3 heart containers. + Been There Done That + Defeat Ganondorf with a total save file play time under 12 hours. + Swift Blade + Defeat Ganondorf with a total save file play time under 6 hours. + Mortal Edge + Defeat Dark Hammer in a single hit. + Deathless + Defeat Ganondorf with 0 deaths on your save file. + Untouchable + Kill 25 enemies in a row without taking damage. + Long Shot + Hit an enemy from over 100 meters away with the bow. + Thank You Berry Much + Score 61,454 points in the Plumm minigame. + Rollgoal Novice + Complete the first 8 rollgoal stages. + Lost Your Marbles + Complete all rollgoal stages. + Ranch Hand + Herd all 20 goats into the pen in under 30 seconds. + Bane of Howard + Herd all 20 goats into the pen in under 20 seconds. + King of the Ranch + Herd all 20 goats into the pen in under 18 seconds. + Downhill Dash + Finish the snowboarding minigame in under 70 seconds. + River Raider + Achieve a perfect score in the canoe minigame. + Rising Star + Complete the STAR Prize 2 minigame in under 40 seconds. + Shooting Star + Complete the STAR Prize 2 minigame in under 30 seconds. + Friendly Fire + Get hit by your own cannonball. + Long Jump Attack + Travel more than 20 meters in a single jump attack before landing. + Email Me + Read a letter during the Dark Beast Ganon fight. + Heavy Hitter + Wear the Iron Boots during the end credits. + Here Fishy Fishy + Confuse Ganondorf with the fishing rod. + Petty Theft + Steal from Trill. + Cucco Whisperer + Take control of a cucco. + Back in Time + Perform the Back in Time glitch to play on the title screen. + Early Master Sword + Obtain the Master Sword before completing Midna's Desperate Hour. + Earliest Master Sword + Obtain the Master Sword before meeting Midna. + Hero of Time + Defeat Ganondorf with a total save file play time under 4 hours. + No Fish Suit No Problem + Defeat Morpheel without equipping Zora Armor. + Null Item + Obtain the mysterious black rupee in the item wheel. + Stallord Skip + Leave Stallord's arena through the exit without defeating Stallord. + White Midna Glitch + Clear the Lakebed Temple before clearing Lanayru's Twilight. + Quick Detour + Rescue the Hidden Village before clearing Goron Mines. + Must Have Been The Wind + Complete the Forest Temple without obtaining the Gale Boomerang. + Adjusts the volume of all sounds in the game. + Allow Background Input + Allow controller input even when the game window is not focused. + Allows Wolf Link to howl and change the time of day. + Always collect Rupees even if your Wallet is too full. + Autosave + Autosaves the game when going to a new area, opening a dungeon door, or getting a new item. + Bigger Wallets + Bloom + Bloom Brightness + Bottom Left + Bottom Right + Configure Controller + Connect to LiveSplit server on localhost:16834. For this to work you must right click LiveSplit, and turn on Control -> Start TCP Server. To see IGT in LiveSplit you must change your comparison to Game Time. + Damage Multiplier + Disable Cutscene Pillarboxing + Disable Rupee Cutscenes + Disable the beeping sound when having low health. + Disables the elements of the main HUD of the game.
Useful for a more immersive experience.
+
Display the current framerate in a corner of the screen while playing.
+ Display the RTA timer. IGT is always visible. + Dusklight Menu Sounds + Emulate surround sound via HRTF. Recommended only for use with headphones! + Enable Depth of Field + Enable Mini-Map Shadows + Enable Reverb + Enable Rotating Link Doll + Enable Spatial Sound + Enable VSync + Enables gyro controls for Rollgoal in Hena's Cabin. + Enables gyro controls while in look mode, aiming a hawk, and aiming supported items.

Supported items include the Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s), Ball and Chain, and Dominion Rod.
+ Enables rotating Link in the collection menu with the C-Stick. + Enables speedrunning options while restricting certain gameplay modifiers. + Enables the reverb effect in game audio. + Enables twin-stick camera control, letting the C-Stick move the camera vertically as well as horizontally. + Faster Climbing + Faster Tears of Light + Free Camera + Free Camera Sensitivity + Gyro Aim + Gyro Deadband + Gyro Input Method + Gyro Pitch Sensitivity + Gyro Rollgoal + Gyro Smoothing + Gyro Yaw Sensitivity + Hearts will never drop from enemies, pots, and various other places. + Hold B for Instant Text + Hold Tab to increase game speed by up to 4x. + Ignores small gyro movement to reduce drift and jitter. + Instant Death + Instant Saves + Internal Resolution + Invert Camera X Axis + Invert Camera Y Axis + Invert First Person X Axis + Invert First Person Y Axis + Invert Gyro Pitch + Invert Gyro Yaw + Invert horizontal camera movement. + Invert horizontal gyro aiming. + Invert horizontal movement while aiming with items or first person camera. Applies only to the control stick (the gyroscope can be inverted in Input settings). + Invert vertical camera movement when Free Camera is enabled. + Invert vertical gyro aiming. + Invert vertical movement while aiming with items or first person camera. Applies only to the control stick (the gyroscope can be inverted in Input settings). + Link will not recoil when his sword hits walls. + LiveSplit Connection + Lock 4:3 Aspect Ratio + Lock the game's aspect ratio to the original. + Makes text scroll immediately by holding B. + Minimal HUD + Mirror Mode + Mirrors the world horizontally, matching the Wii version of the game. + Mouse + Multiplies incoming damage. + No 2nd Fish for Cat + No Climbing Miss Animation + No Heart Drops + No Low HP Sound + No Rupee Returns + No Sword Recoil + Non-Stop Midna's Lament + Open controller binding configuration. + Pause on Focus Lost + Pause the game when window focus is lost. + Play sound effects when navigating the Dusklight menu. + Press + Prevents enemy music while Midna's Lament is playing. + Prevents Link from playing a struggle animation when grabbing ledges or climbing on vines. + Quick Transform (R+Y) + Quicker climbing on ladders and vines like the HD version. + Reset Key + Restore Default Window Size + Restore Default Controls + Restores all binding configurations for the currently selected device to their defaults. + Restore Wii 1.0 Glitches + Restores patched glitches from Wii USA 1.0, the first released version. + Rollgoal Sensitivity + Rupees will not play cutscenes after you have collected them the first time. + Sensor +
Sensor reads motion directly from a supported controller's gyro via SDL.

Mouse treats mouse input as gyro, intended for use with the Steam Deck.

Mouse input cannot currently be used with Gyro Rollgoal.
+ Shadow Resolution + Show FPS Counter + Show RTA + Skip needing to catch a second fish for Sera's cat. + Skips the delay when writing to the Memory Card. + Speedrun Mode + Sun's Song (R+X) + Synchronizes the frame rate to your monitor's refresh rate. + Tears of Light dropped by Shadow Insects pop out faster like the HD version. + Toggle Fullscreen + Top Left + Top Right + Transform instantly by pressing R and Y simultaneously. + Turbo Key + Limite de framerate + Limit the frame rate to the specified value. + Unlock Framerate + Illimité + Wallet sizes are like in the HD version. (500, 1000, 2000) + Japanese + Any hit will instantly kill you. + Controls how strongly gyro input tilts the Rollgoal table. + to reset the game. + Adjusts twin-stick camera sensitivity. + Controls vertical gyro aiming sensitivity. + Configure the sampling method used when scaling the internal resolution for final presentation. + Controls horizontal gyro aiming sensitivity. + Higher values smooth gyro input over time. + Infinite Hearts + Keeps your health full. + Infinite Arrows + Keeps your arrow count full. + Infinite Seeds + Keeps your slingshot pellets (seeds) full. + Infinite Bombs + Keeps all bomb bags full. + Infinite Oil + Keeps your lantern oil full. + Infinite Oxygen + Keeps your underwater oxygen meter full. + Infinite Rupees + Keeps your rupee count full. + No Item Timer + Item drops such as rupees and hearts will never disappear after they drop. + Moon Jump (R+A) + Hold R and A to rise into the air. + Super Clawshot + Extends Clawshot behavior beyond the normal game rules. + Always Greatspin + Allows the Great Spin attack without requiring full health. + Fast Iron Boots + Speeds up movement while wearing the Iron Boots. + Can Transform Anywhere + Allows transforming even if NPCs are looking. + Fast Roll + Makes Link's roll animation and movement twice as fast. + Fast Spinner + Speeds up Spinner movement while holding R. + Free Magic Armor + Lets the magic armor work without consuming rupees. + Invincible Enemies + Prevents enemies from taking damage. + Limité + On + None + Show Internal Names + Maps + Destination + Region + Map + Room + Point + Layer + Action + Warp to the selected destination. + Welcome to Dusklight + Choose a preset to get started. You can change any setting later from the Settings menu. + Classic + Enhancements disabled to match the GameCube version. Good for speedrunning or simple nostalgia! + Dusk + Graphics & quality of life tweaks, including some from the Wii U version. Our recommended way to play! + Send Crash Reports + Dusklight can automatically send crash reports to the developers. Crash reports contain the following:
• Operating system version
• CPU architecture
• GPU model & driver version
• File paths (may include account username)
• Stack trace

This can be changed in the Settings menu at any time.
+ Enable + Disable + Send crash reports to Dusklight developers. Reports will include the information described above. + Do not send crash reports. This may make it more difficult to resolve issues you encounter. + Current data folder: + Data Folder Not Changed + Enable Discord Rich Presence + Enable Dusk to integrate with Discord Rich Presence. This allows Discord to show your status in-game. + Enable Advanced Settings + Show advanced settings and debugging tools with Shift+F1.

WARNING: Debugging tools can easily break your game. Do not use on a regular save!
+ Show Input Viewer + Display a controller input overlay while playing. + Show Gyro Input Viewer + Show gyro sensor values in the input viewer. + Skip TV Settings Screen + Skips the TV calibration screen shown when loading a save. + Recording Mode + Disables the game HUD and all background music.

Useful for recording footage.
+ Auto + Return + Twilit Realm + presents + Version + Game Disc Images + All Files + Download + The selected disc image could not be validated. + Unable to read the selected file. + The selected file is not a valid disc image. + The selected game is not supported by Dusklight. + Dusklight currently supports GameCube USA and PAL disc images only. + Disc verification was canceled. Dusklight cannot guarantee the selected disc image is compatible. + The selected disc image did not pass hash verification. It may be corrupt or modified. + The selected disc image is valid. + Card Image + GCI Folder + Configure the resolution used for rendering the game. Higher values are more demanding on your graphics hardware. + Configure the shadow-map resolution. Higher values improve shadow quality but increase GPU and memory usage. + Configure the post-processing bloom effect. Classic uses the original bloom pass; Dusklight uses a higher-quality bloom pass. + Configure bloom intensity. Higher values make bright areas glow more strongly. + Uses inter-frame interpolation to enable higher frame rates.

May introduce minor visual artifacts or animation glitches.
+ Controller connected + Controller disconnected +
diff --git a/res/i18n/ja.xml b/res/i18n/ja.xml new file mode 100644 index 0000000000..9c636545a5 --- /dev/null +++ b/res/i18n/ja.xml @@ -0,0 +1,486 @@ + + + Prelaunch + Video + Input + Audio + Gameplay + Cheats + Interface + Display + Resolution + Post-Processing + Rendering + Controller + Camera + Gyro + Tools + Volume + Effects + Tweaks + General + Difficulty + Quality of Life + Speedrunning + Resources + Abilities + Dusklight + Types + Game + UI Language + English + Simplified Chinese +
Applies to Dusklight UI text.
+ Settings + Warp + Editor + Achievements + Reset + Quit + Reset Timer + Verifying disc image + Cancelling... + Opening disc image... + Play + Select Disc Image + No disc image found. + Pending restart. + Disc ready. + Disc hash mismatch. + Disc not verified. + Disc unavailable. + Checking for updates... + Update available! + Failed to check for updates + Reset Game + Unsaved progress will be lost. + Unsaved progress will be lost.
Tip: You can also reset by holding Start+X+B
+ Cancel + Quit Dusklight + Update check failed with an unknown exception +

You may proceed at your own risk.
+ Disc verification warning + Continue anyway + Disc verification error + OK + Restart later + Restart now + Apply Options + A restart is required to apply selected options.

Restart now to apply them immediately?
+ A restart is required to apply selected options.

Close and reopen Dusklight to apply them.
+ Disc Image + Set the disc image that Dusklight uses to launch the game.

Changes require a restart.
+ Data Folder + The data folder is where Dusklight stores settings, saves, logs, texture replacements, and other app data. + Use Texture Pack + Open Data Folder + Output Resampling + Change Data Folder + Portable Mode + Reset to Default + Data will be migrated automatically on restart. + Language + German + French + Spanish + Italian +
Changes require a restart.
+ Graphics Backend + Save File Type + Open the folder where Dusklight stores settings, saves, logs, texture replacements, and other app data. + Enable installed texture replacements. + Notifications + Off + All + Some + Select All + Select None +
Choose which notifications can be displayed.
+ Crash Reporting + Dusklight can automatically send crash reports to the developers. Crash reports contain the following:
• Operating system version
• CPU architecture
• GPU model & driver version
• File paths (may include account username)
• Stack trace
+ Skip Dusklight Main Menu + When starting Dusklight, skip the main menu and boot straight into the game if a disc image is available. + Show Pipeline Compilation + Show an overlay when shaders are being compiled for your hardware. + Check for Updates + Checks GitHub releases for a new Dusklight version on startup.

No personal information is transmitted or collected.
+ No controller assigned + Configure controller port 1 in Settings. + 3-finger tap or + Press F1 or + to open menu + LiveSplit connected + LiveSplit disconnected + Master Volume + Keyboard + Not bound + Mouse Left + Mouse Middle + Mouse Right + Mouse X1 + Mouse X2 + Unknown + Port + Buttons + Triggers + Sticks + Rumble + Custom Action Bindings + Options + Enable Dead Zones + Apply configured dead zones to the sticks and analog triggers. + Emulate Triggers + Treat analog trigger movement as digital L and R button input. + No controllers detected + D-Pad + No controller selected + Analog + Digital + Emulated Trigger Thresholds + L Threshold + R Threshold + Control Stick + C Stick + Deadzone + Test Rumble + Start + Stop + Low Rumble Frequency + High Rumble Frequency + Configure your desired rumble intensities, then run a test to check how they feel. + A key bound to any action here will REPLACE the default control for that action. Only bind buttons here that aren't used anywhere else. + A button bound to any action here will REPLACE the default control for that action. Only bind buttons here that aren't used anywhere else. The glyphs shown for in game actions will not change. This is not recommended for regular Gamecube controllers. + Press a button... + Waiting... + Move axis or press a button... + Press a key or mouse button... + Challenge + Collection + Minigame + Misc + Glitched + Unlocked + Locked + Clear? + Actions + Clear All Achievements + Are you sure? + Achievement Unlocked! + Hero of Twilight + Deliver the finishing blow to Ganondorf. + Completionist + Complete the game after collecting all equipment, heart containers, portals, bugs, poes, and hidden skills. + The Princess of Bugs + Deliver all 24 golden bugs to Agitha. + Poe Collector + Collect all 60 Poe Souls. + Legendary Catch + Catch a Hylian Loach. + Gone Fishin' + Catch all 6 species of fish. + A Big Heart + Reach maximum health with all 20 heart containers. + Glassware Guardian + Obtain all 4 bottles. + Master of Secrets + Learn all 7 Hidden Skills. + We Deliver! + Collect all 16 postman letters. + Conqueror of Ordeals + Clear all 50 floors of the Cave of Ordeals. + Indomitable + Clear all 50 floors of the Cave of Ordeals with only 3 heart containers. + Been There Done That + Defeat Ganondorf with a total save file play time under 12 hours. + Swift Blade + Defeat Ganondorf with a total save file play time under 6 hours. + Mortal Edge + Defeat Dark Hammer in a single hit. + Deathless + Defeat Ganondorf with 0 deaths on your save file. + Untouchable + Kill 25 enemies in a row without taking damage. + Long Shot + Hit an enemy from over 100 meters away with the bow. + Thank You Berry Much + Score 61,454 points in the Plumm minigame. + Rollgoal Novice + Complete the first 8 rollgoal stages. + Lost Your Marbles + Complete all rollgoal stages. + Ranch Hand + Herd all 20 goats into the pen in under 30 seconds. + Bane of Howard + Herd all 20 goats into the pen in under 20 seconds. + King of the Ranch + Herd all 20 goats into the pen in under 18 seconds. + Downhill Dash + Finish the snowboarding minigame in under 70 seconds. + River Raider + Achieve a perfect score in the canoe minigame. + Rising Star + Complete the STAR Prize 2 minigame in under 40 seconds. + Shooting Star + Complete the STAR Prize 2 minigame in under 30 seconds. + Friendly Fire + Get hit by your own cannonball. + Long Jump Attack + Travel more than 20 meters in a single jump attack before landing. + Email Me + Read a letter during the Dark Beast Ganon fight. + Heavy Hitter + Wear the Iron Boots during the end credits. + Here Fishy Fishy + Confuse Ganondorf with the fishing rod. + Petty Theft + Steal from Trill. + Cucco Whisperer + Take control of a cucco. + Back in Time + Perform the Back in Time glitch to play on the title screen. + Early Master Sword + Obtain the Master Sword before completing Midna's Desperate Hour. + Earliest Master Sword + Obtain the Master Sword before meeting Midna. + Hero of Time + Defeat Ganondorf with a total save file play time under 4 hours. + No Fish Suit No Problem + Defeat Morpheel without equipping Zora Armor. + Null Item + Obtain the mysterious black rupee in the item wheel. + Stallord Skip + Leave Stallord's arena through the exit without defeating Stallord. + White Midna Glitch + Clear the Lakebed Temple before clearing Lanayru's Twilight. + Quick Detour + Rescue the Hidden Village before clearing Goron Mines. + Must Have Been The Wind + Complete the Forest Temple without obtaining the Gale Boomerang. + Adjusts the volume of all sounds in the game. + Allow Background Input + Allow controller input even when the game window is not focused. + Allows Wolf Link to howl and change the time of day. + Always collect Rupees even if your Wallet is too full. + Autosave + Autosaves the game when going to a new area, opening a dungeon door, or getting a new item. + Bigger Wallets + Bloom + Bloom Brightness + Bottom Left + Bottom Right + Configure Controller + Connect to LiveSplit server on localhost:16834. For this to work you must right click LiveSplit, and turn on Control -> Start TCP Server. To see IGT in LiveSplit you must change your comparison to Game Time. + Damage Multiplier + Disable Cutscene Pillarboxing + Disable Rupee Cutscenes + Disable the beeping sound when having low health. + Disables the elements of the main HUD of the game.
Useful for a more immersive experience.
+
Display the current framerate in a corner of the screen while playing.
+ Display the RTA timer. IGT is always visible. + Dusklight Menu Sounds + Emulate surround sound via HRTF. Recommended only for use with headphones! + Enable Depth of Field + Enable Mini-Map Shadows + Enable Reverb + Enable Rotating Link Doll + Enable Spatial Sound + Enable VSync + Enables gyro controls for Rollgoal in Hena's Cabin. + Enables gyro controls while in look mode, aiming a hawk, and aiming supported items.

Supported items include the Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s), Ball and Chain, and Dominion Rod.
+ Enables rotating Link in the collection menu with the C-Stick. + Enables speedrunning options while restricting certain gameplay modifiers. + Enables the reverb effect in game audio. + Enables twin-stick camera control, letting the C-Stick move the camera vertically as well as horizontally. + Faster Climbing + Faster Tears of Light + Free Camera + Free Camera Sensitivity + Gyro Aim + Gyro Deadband + Gyro Input Method + Gyro Pitch Sensitivity + Gyro Rollgoal + Gyro Smoothing + Gyro Yaw Sensitivity + Hearts will never drop from enemies, pots, and various other places. + Hold B for Instant Text + Hold Tab to increase game speed by up to 4x. + Ignores small gyro movement to reduce drift and jitter. + Instant Death + Instant Saves + Internal Resolution + Invert Camera X Axis + Invert Camera Y Axis + Invert First Person X Axis + Invert First Person Y Axis + Invert Gyro Pitch + Invert Gyro Yaw + Invert horizontal camera movement. + Invert horizontal gyro aiming. + Invert horizontal movement while aiming with items or first person camera. Applies only to the control stick (the gyroscope can be inverted in Input settings). + Invert vertical camera movement when Free Camera is enabled. + Invert vertical gyro aiming. + Invert vertical movement while aiming with items or first person camera. Applies only to the control stick (the gyroscope can be inverted in Input settings). + Link will not recoil when his sword hits walls. + LiveSplit Connection + Lock 4:3 Aspect Ratio + Lock the game's aspect ratio to the original. + Makes text scroll immediately by holding B. + Minimal HUD + Mirror Mode + Mirrors the world horizontally, matching the Wii version of the game. + Mouse + Multiplies incoming damage. + No 2nd Fish for Cat + No Climbing Miss Animation + No Heart Drops + No Low HP Sound + No Rupee Returns + No Sword Recoil + Non-Stop Midna's Lament + Open controller binding configuration. + Pause on Focus Lost + Pause the game when window focus is lost. + Play sound effects when navigating the Dusklight menu. + Press + Prevents enemy music while Midna's Lament is playing. + Prevents Link from playing a struggle animation when grabbing ledges or climbing on vines. + Quick Transform (R+Y) + Quicker climbing on ladders and vines like the HD version. + Reset Key + Restore Default Window Size + Restore Default Controls + Restores all binding configurations for the currently selected device to their defaults. + Restore Wii 1.0 Glitches + Restores patched glitches from Wii USA 1.0, the first released version. + Rollgoal Sensitivity + Rupees will not play cutscenes after you have collected them the first time. + Sensor +
Sensor reads motion directly from a supported controller's gyro via SDL.

Mouse treats mouse input as gyro, intended for use with the Steam Deck.

Mouse input cannot currently be used with Gyro Rollgoal.
+ Shadow Resolution + Show FPS Counter + Show RTA + Skip needing to catch a second fish for Sera's cat. + Skips the delay when writing to the Memory Card. + Speedrun Mode + Sun's Song (R+X) + Synchronizes the frame rate to your monitor's refresh rate. + Tears of Light dropped by Shadow Insects pop out faster like the HD version. + Toggle Fullscreen + Top Left + Top Right + Transform instantly by pressing R and Y simultaneously. + Turbo Key + フレームレート上限 + Limit the frame rate to the specified value. + Unlock Framerate + 無制限 + Wallet sizes are like in the HD version. (500, 1000, 2000) + Japanese + Any hit will instantly kill you. + Controls how strongly gyro input tilts the Rollgoal table. + to reset the game. + Adjusts twin-stick camera sensitivity. + Controls vertical gyro aiming sensitivity. + Configure the sampling method used when scaling the internal resolution for final presentation. + Controls horizontal gyro aiming sensitivity. + Higher values smooth gyro input over time. + Infinite Hearts + Keeps your health full. + Infinite Arrows + Keeps your arrow count full. + Infinite Seeds + Keeps your slingshot pellets (seeds) full. + Infinite Bombs + Keeps all bomb bags full. + Infinite Oil + Keeps your lantern oil full. + Infinite Oxygen + Keeps your underwater oxygen meter full. + Infinite Rupees + Keeps your rupee count full. + No Item Timer + Item drops such as rupees and hearts will never disappear after they drop. + Moon Jump (R+A) + Hold R and A to rise into the air. + Super Clawshot + Extends Clawshot behavior beyond the normal game rules. + Always Greatspin + Allows the Great Spin attack without requiring full health. + Fast Iron Boots + Speeds up movement while wearing the Iron Boots. + Can Transform Anywhere + Allows transforming even if NPCs are looking. + Fast Roll + Makes Link's roll animation and movement twice as fast. + Fast Spinner + Speeds up Spinner movement while holding R. + Free Magic Armor + Lets the magic armor work without consuming rupees. + Invincible Enemies + Prevents enemies from taking damage. + 上限 + On + None + Show Internal Names + Maps + Destination + Region + Map + Room + Point + Layer + Action + Warp to the selected destination. + Welcome to Dusklight + Choose a preset to get started. You can change any setting later from the Settings menu. + Classic + Enhancements disabled to match the GameCube version. Good for speedrunning or simple nostalgia! + Dusk + Graphics & quality of life tweaks, including some from the Wii U version. Our recommended way to play! + Send Crash Reports + Dusklight can automatically send crash reports to the developers. Crash reports contain the following:
• Operating system version
• CPU architecture
• GPU model & driver version
• File paths (may include account username)
• Stack trace

This can be changed in the Settings menu at any time.
+ Enable + Disable + Send crash reports to Dusklight developers. Reports will include the information described above. + Do not send crash reports. This may make it more difficult to resolve issues you encounter. + Current data folder: + Data Folder Not Changed + Enable Discord Rich Presence + Enable Dusk to integrate with Discord Rich Presence. This allows Discord to show your status in-game. + Enable Advanced Settings + Show advanced settings and debugging tools with Shift+F1.

WARNING: Debugging tools can easily break your game. Do not use on a regular save!
+ Show Input Viewer + Display a controller input overlay while playing. + Show Gyro Input Viewer + Show gyro sensor values in the input viewer. + Skip TV Settings Screen + Skips the TV calibration screen shown when loading a save. + Recording Mode + Disables the game HUD and all background music.

Useful for recording footage.
+ Auto + Return + Twilit Realm + presents + Version + Game Disc Images + All Files + Download + The selected disc image could not be validated. + Unable to read the selected file. + The selected file is not a valid disc image. + The selected game is not supported by Dusklight. + Dusklight currently supports GameCube USA and PAL disc images only. + Disc verification was canceled. Dusklight cannot guarantee the selected disc image is compatible. + The selected disc image did not pass hash verification. It may be corrupt or modified. + The selected disc image is valid. + Card Image + GCI Folder + Configure the resolution used for rendering the game. Higher values are more demanding on your graphics hardware. + Configure the shadow-map resolution. Higher values improve shadow quality but increase GPU and memory usage. + Configure the post-processing bloom effect. Classic uses the original bloom pass; Dusklight uses a higher-quality bloom pass. + Configure bloom intensity. Higher values make bright areas glow more strongly. + Uses inter-frame interpolation to enable higher frame rates.

May introduce minor visual artifacts or animation glitches.
+ Controller connected + Controller disconnected +
diff --git a/res/i18n/zh-cn.xml b/res/i18n/zh-cn.xml new file mode 100644 index 0000000000..c02c9812c0 --- /dev/null +++ b/res/i18n/zh-cn.xml @@ -0,0 +1,488 @@ + + + 启动菜单 + 视频 + 输入 + 音频 + 游戏玩法 + 作弊 + 界面 + 显示 + 分辨率 + 后处理 + 渲染 + 手柄 + 视角 + 陀螺仪 + 工具 + 音量 + 特效 + 功能微调 + 通用 + 难度设置 + 体验优化 + 速通 + 资源 + 能力 + 暮色之光 + 类型 + 游戏 + 界面语言 + 英语 + 简体中文 +
适用于暮色之光界面文本。
+ 设置 + 传送 + 编辑器 + 成就 + 重置 + 退出 + 重置计时器 + 正在验证光盘镜像 + 正在取消... + 正在打开光盘镜像... + 开始 + 选择光盘镜像 + 未找到光盘镜像。 + 待重启。 + 光盘就绪。 + 光盘哈希不匹配。 + 光盘未验证。 + 光盘不可用。 + 正在检查更新... + 有可用更新! + 检查更新失败 + 重置游戏 + 未保存的进度将会丢失。 + 未保存的进度将会丢失。
提示:你也可以按住Start+X+B键重置
+ 取消 + 退出暮色之光 + 检查更新时发生未知异常 +

风险自负,请自行决定。
+ 光盘验证警告 + 仍然继续 + 光盘验证错误 + 确定 + 稍后重启 + 立即重启 + 应用选项 + 需要重启才能应用所选选项。

立即重启以应用更改?
+ 需要重启才能应用所选选项。

请关闭并重新打开暮色之光以应用更改。
+ 光盘镜像 + 设置暮色之光用于启动游戏的光盘镜像。
更改需要重启。
+ 数据文件夹 + 数据文件夹是暮色之光存储设置、
存档、日志、纹理替换
和其他应用数据的地方。
+ 使用纹理包 + 打开数据文件夹 + 输出重采样 + 更改数据文件夹 + 便携模式 + 重置为默认 + 重启后数据将自动迁移。 + 语言 + 德语 + 法语 + 西班牙语 + 意大利语 +
更改需要重启。
+ 图形后端 + 存档文件类型 + 打开暮色之光存储设置、存档、
日志、纹理替换和
其他应用数据的文件夹。
+ 启用已安装的纹理替换。 + 通知 + 关闭 + 全部 + 部分 + 全选 + 全不选 +
选择可以显示哪些通知。
+ 崩溃报告 + 暮色之光可以自动向开发者
发送崩溃报告。
崩溃报告包含以下内容:
• 操作系统版本
• CPU 架构
• GPU 型号和驱动版本
• 文件路径(可能包含账户名)
• 堆栈跟踪
+ 跳过暮色之光主菜单 + 启动暮色之光时跳过主菜单,
如果有光盘镜像则直接启动游戏。
+ 显示着色器编译 + 当为你的硬件编译着色器时
显示叠加层。
+ 检查更新 + 启动时检查GitHub发布
是否有暮色之光新版本。
不会传输或收集任何个人信息。
+ 中文姓名键盘 + 将游戏内姓名输入键盘
替换为常见中文字符。
请配合包含中文字库的镜像使用。
+ 未分配手柄 + 在设置中配置手柄端口1。 + 三指点击或 + 按F1或 + 打开菜单 + LiveSplit已连接 + LiveSplit已断开 + 主音量 + 键盘 + 未绑定 + 鼠标左键 + 鼠标中键 + 鼠标右键 + 鼠标侧键1 + 鼠标侧键2 + 未知 + 端口 + 按键 + 扳机键 + 摇杆 + 震动 + 自定义按键绑定 + 选项 + 启用死区 + 将配置的死区应用到摇杆
和模拟扳机。
+ 模拟扳机键 + 将摇杆模拟触发视为
L/R按键数字输入。
+ 未检测到控制器 + 十字键 + 未选择控制器 + 模拟 + 数字 + 模拟扳机阈值 + 左扳机阈值 + 右扳机阈值 + 控制摇杆 + C摇杆 + 死区 + 测试震动 + 开始 + 停止 + 低频震动 + 高频震动 + 设置震动强度,
再进行测试确认效果。
+ 在此为任意操作绑定按键
将覆盖该操作的默认按键设置。
请绑定未被占用的按键。
+ 在此为任意操作绑定按键
将覆盖该操作的默认按键设置。
请绑定未被占用的按键。
游戏内操作图标不会随之变更。
不建议普通GameCube手柄启用该功能。
+ 按下任意按键... + 等待中... + 移动摇杆或按下按键... + 按下键盘或鼠标按键... + 挑战 + 收集 + 小游戏 + 杂项 + 漏洞技巧 + 已解锁 + 未解锁 + 清除? + 操作 + 清除全部成就 + 确定吗? + 成就已解锁! + 黄昏勇者 + 给予盖农多夫最后一击。 + 全收集大师 + 集齐全部装备、心之容器、
传送点、金色昆虫、幽灵之魂
和秘技后通关游戏。
+ 虫国公主 + 将24只金色昆虫
全部交给凤蝶。
+ 幽灵之魂收藏家 + 收集全部60个幽灵之魂。 + 海利亚泥鳅猎手 + 钓到海利亚泥鳅。 + 垂钓达人 + 钓到全部6种鱼。 + 满心勇者 + 集齐20个心之容器
达成生命值上限。
+ 宝瓶全收 + 获得全部4个瓶子。 + 秘技大师 + 学会全部7个秘技。 + 邮务达人 + 集齐全部16封邮差信件。 + 试炼征服者 + 通过试炼洞窟全部50层。 + 不屈之心 + 仅用3个心之容器
通过试炼洞窟全部50层。
+ 到此一游 + 存档总游玩时间
12小时内击败盖农多夫。
+ 迅捷之刃 + 存档总游玩时间
6小时内击败盖农多夫。
+ 致命锋芒 + 一击击败链锤武士。 + 一命通关 + 存档死亡次数为0时
击败盖农多夫。
+ 毫发无伤 + 连续击杀25个敌人
不受到伤害。
+ 百步穿杨 + 用勇者之弓命中100米外的敌人。 + 莓果高手 + 在花李儿小游戏中
取得61,454分。
+ 滚弹珠新手 + 通关前8个滚弹珠关卡。 + 滚弹珠高手 + 通关全部滚弹珠关卡。 + 牧场帮手 + 在30秒内把20只山羊
全部赶进围栏。
+ 赶羊高手 + 在20秒内把20只山羊
全部赶进围栏。
+ 牧场之王 + 在18秒内把20只山羊
全部赶进围栏。
+ 雪原速降 + 在70秒内完成滑雪小游戏。 + 激流泛舟 + 在独木舟小游戏中
取得满分成绩。
+ 新星初现 + 在40秒内完成
明星游戏。
+ 超级巨星 + 在30秒内完成
明星游戏。
+ 误伤 + 被自己发射的炮弹击中。 + 超远跳斩 + 单次跳斩落地前
移动超过20米。
+ 写信给我 + 在魔兽加农战中读一封信。 + 重量级勇者 + 在结尾字幕期间穿着铁靴。 + 鱼儿鱼儿来 + 用钓竿迷惑加农多夫。 + 顺手牵羊 + 偷走特里尔的东西。 + 咕咕驯兽师 + 控制一只咕咕鸡。 + 时空回溯 + 利用时空回溯漏洞,
在标题画面进入游戏。
+ 提前大师剑 + 在完成米多娜绝望时刻前
获得大师剑。
+ 最早大师剑 + 在遇见米多娜之前获得大师剑。 + 时之勇者 + 存档总游玩时间
低于四小时击败盖农多夫。
+ 无鱼服也无妨 + 不装备卓拉服击败八爪鳗。 + 虚空道具 + 在物品轮盘中获得
神秘的黑卢比。
+ 遁离王陵 + 未击败哈拉·吉冈托,
从它的竞技场出口离开。
+ 白米多娜漏洞 + 未清除拉聂尔黄昏
通关湖底神殿。
+ 秘境先知 + 在清除鼓隆矿山前
拯救忘却之村。
+ 风无归刃 + 未获得疾风飞旋镖
完成森之神殿。
+ 调整游戏中所有声音的音量。 + 允许后台输入 + 游戏窗口未激活时
也允许手柄输入。
+ 允许狼形态林克嚎叫并改变时间。 + 即使钱包已满仍继续收集卢比。 + 自动存档 + 进入新区域、打开迷宫门、
获得新物品时自动存档。
+ 更大的钱包 + 泛光 + 泛光亮度 + 左下角 + 右下角 + 配置手柄 + 连接到localhost:16834上的
LiveSplit服务器。为此,
你必须右键点击 LiveSplit,
开启 控制 -> 启动TCP服务器。
要在LiveSplit中查看IGT,
请将比较方式改为游戏时间。
+ 伤害倍率 + 禁用过场黑边 + 去除卢比过场动画 + 关闭低血量时的哔哔声。 + 隐藏游戏主HUD的元素。
提升游戏沉浸感。
+
游戏中在屏幕角落显示当前帧率。
+ 显示RTA计时器。IGT始终可见。 + 暮色之光菜单音效 + 通过HRTF模拟环绕声。
建议配合耳机使用!
+ 启用景深 + 启用小地图阴影 + 启用混响 + 启用旋转林克模型 + 启用空间音效 + 启用垂直同步 + 在海娜的小屋中
为滚弹珠小游戏启用陀螺仪控制。
+ 在观察模式、瞄准鹰
和瞄准支持的物品时
启用陀螺仪控制。

支持的物品包括弹弓、
疾风飞旋镖、勇者之弓、
钩爪、链锤和操纵杖。
+ 在收藏菜单中用C摇杆
旋转林克。
+ 启用速通选项,
同时限制某些游戏修改器。
+ 启用游戏音频中的混响效果。 + 启用双摇杆视角控制,
使C摇杆可以上下左右移动视角。
+ 更快地攀爬 + 更快的光之滴 + 自由视角 + 自由视角灵敏度 + 陀螺仪瞄准 + 陀螺仪死区 + 陀螺仪输入方式 + 陀螺仪俯仰灵敏度 + 陀螺仪滚弹珠 + 陀螺仪平滑 + 陀螺仪偏航灵敏度 + 敌人、罐子和其他地方
将不会掉落生命之心。
+ 按住B键快速跳过对话 + 按住Tab键将游戏速度
提升至最多4倍。
+ 忽略微小的陀螺仪移动,
以减少漂移和抖动。
+ 一击即死 + 快速写入存档 + 内部分辨率 + 反转视角X轴 + 反转视角Y轴 + 反转第一人称X轴 + 反转第一人称Y轴 + 反转陀螺仪俯仰轴 + 反转陀螺仪偏航轴 + 反转水平视角移动。 + 反转水平陀螺仪瞄准。 + 在使用物品瞄准或
第一人称视角时反转水平移动。
仅适用于摇杆
(陀螺仪可在输入设置中反转)。
+ 启用自由视角时
反转垂直视角移动。
+ 反转垂直陀螺仪瞄准。 + 在使用物品瞄准或
第一人称视角时反转垂直移动。
仅适用于摇杆
(陀螺仪可在输入设置中反转)。
+ 林克的剑击中墙壁时不会硬直。 + LiveSplit连接 + 锁定4:3宽高比 + 将游戏的宽高比锁定为原始比例。 + 按住B键使文本立即滚动。 + 极简HUD + 镜像模式 + 水平镜像世界,
与Wii版本一致。
+ 鼠标 + 受到伤害倍率加成。 + 无需为猫钓第二条鱼 + 攀爬无失误动作 + 无生命之心掉落 + 无低血量音效 + 禁止卢比回收 + 剑击无硬直后仰 + 米多娜的悲歌不间断 + 打开手柄按键配置。 + 失去焦点时暂停 + 窗口失去焦点时暂停游戏。 + 在暮色之光菜单中导航时播放音效。 + 按下 + 在米多娜的悲歌播放时
屏蔽敌人音乐。
+ 防止林克在抓住边缘
或攀爬藤蔓时播放挣扎动画。
+ 快速变身(R+Y) + 在梯子和藤蔓上攀爬更快,
与HD版本一样。
+ 重置键( + 恢复默认窗口大小 + 恢复默认控制 + 将当前所选设备的所有绑定配置恢复为默认值。 + 恢复Wii 1.0漏洞 + 恢复Wii美版1.0
(首个发布版本)中
已被修复的漏洞。
+ 滚弹珠灵敏度 + 卢比在首次收集后
不再播放过场动画。
+ 传感器 +
传感器通过SDL直接读取
受支持手柄的陀螺仪运动。

鼠标将鼠标输入视为陀螺仪,
适用于Steam Deck。

鼠标输入目前不能
用于陀螺仪滚弹珠。
+ 阴影分辨率 + 显示FPS计数器 + 显示RTA + 跳过为塞拉的猫
钓第二条鱼的需求。
+ 跳过写入记忆卡时的延迟。 + 速通模式 + 太阳之歌(R+X) + 将帧率与显示器刷新率同步。 + 影虫掉落的光之滴
弹出速度更快,与HD版本一样。
+ 切换全屏 + 左上角 + 右上角 + 同时按下R键和Y键立即变身。 + 连发键 + 帧率上限 + 将帧率限制为指定数值。 + 解锁帧率 + 无限制 + 钱包容量与HD版本一样。
(500、1000、2000)
+ 日语 + 任何攻击都会立即杀死你。 + 控制陀螺仪输入
倾斜滚弹珠桌面的力度。
+ 重置游戏。 + 调整双摇杆视角灵敏度。 + 控制垂直陀螺仪瞄准灵敏度。 + 设置将内部分辨率缩放到最终画面时使用的采样方式。 + 控制水平陀螺仪瞄准灵敏度。 + 这个数值越高,陀螺仪输入越平滑。 + 无限生命之心 + 保持你的血量全满。 + 无限箭矢 + 保持你的箭矢数量全满。 + 无限种子 + 保持你的弹弓弹丸(种子)全满。 + 无限炸弹 + 保持所有炸弹袋全满。 + 无限灯油 + 保持你的灯油全满。 + 无限氧气 + 保持你的水下氧气值全满。 + 无限卢比 + 保持你的卢比数量全满。 + 物品无计时 + 掉落的物品如卢比和生命之心
将不会消失。
+ 月亮跳(R+A) + 按住R键和A键上升到空中。 + 超级钩爪 + 强化钩爪性能,
突破原版游戏限制。
+ 永久大回旋斩 + 无需满血即可使用大回旋斩。 + 快速铁靴 + 穿戴铁靴时加快移动速度。 + 随时变身 + 即使NPC在看也能变身。 + 快速翻滚 + 林克的翻滚动画和移动速度加倍。 + 快速齿轮陀螺 + 按住R键时加快齿轮陀螺的移动速度。 + 免费魔法铠甲 + 魔法铠甲无需消耗卢比。 + 敌人无敌 + 敌人不会受到伤害。 + 上限 + 开启 + + 显示内部名称 + 地图 + 目的地 + 区域 + 地图 + 房间 + + + 动作 + 传送到选定的目的地。 + 欢迎来到暮色之光 + 选择一个预设开始。
你可以稍后在设置菜单中
更改任何设置。
+ 经典 + 禁用增强功能以匹配
GameCube版本。
适合速通或纯粹怀旧!
+ 暮色 + 图形和生活质量微调,
包括一些来自Wii U版本的功能。
这是我们推荐的游玩方式!
+ 发送崩溃报告 + 暮色之光可以自动向开发者
发送崩溃报告。
崩溃报告包含以下内容:
• 操作系统版本
• CPU 架构
• GPU 型号和驱动版本
• 文件路径(可能包含账户名)
• 堆栈跟踪

你可以随时在设置菜单中更改。
+ 启用 + 禁用 + 向暮色之光开发者发送崩溃报告。
报告将包含上述信息。
+ 不发送崩溃报告。
这可能会使解决你遇到的问题
变得更加困难。
+ 当前数据文件夹: + 数据文件夹未更改 + 启用Discord状态显示 + 启用暮色之光与Discord状态显示集成。
允许Discord显示你的游戏状态。
+ 启用高级设置 + 使用Shift+F1显示高级设置
和调试工具。

警告:调试工具
很容易破坏你的游戏。
不要在常规存档上使用!
+ 显示输入查看器 + 在游戏时显示手柄输入叠加层。 + 显示陀螺仪输入查看器 + 在输入查看器中
显示陀螺仪传感器数值。
+ 跳过电视设置画面 + 跳过加载存档时
显示的电视校准画面。
+ 录制模式 + 禁用游戏HUD和所有背景音乐。
适用于录制视频。
+ 自动 + 返回 + Twilit Realm + 出品 + 版本 + 游戏光盘镜像 + 全部文件 + 下载 + 所选光盘镜像验证失败。 + 无法读取所选文件。 + 所选文件并非有效光盘镜像。 + 所选游戏不受暮色之光(dusklight)支持。 + 暮色之光目前仅支持GameCube美版及PAL版光盘镜像。 + 光盘镜像验证已取消,暮色之光无法保证所选镜像兼容可用。 + 所选光盘镜像未通过哈希校验,文件可能已损坏或被修改。 + 所选光盘镜像校验通过。 + Card镜像 + GCI文件夹 + 设置游戏渲染分辨率,数值越高对显卡性能要求越高。 + 设置阴影贴图分辨率,数值越高阴影画质越好,
但会增加显卡与内存占用。
+ 设置后期泛光特效:经典模式为原版泛光,
暮色之光模式采用更高画质泛光。
+ 设置泛光强度,数值越高,高亮区域发光效果越强烈。 + 启用帧间插值提升帧率,可能会出现轻微画面异常,
或动画卡顿。
+ 手柄已连接 + 手柄已断开连接 +
diff --git a/res/rml/overlay.rcss b/res/rml/overlay.rcss index 8927e1a01c..d87515a336 100644 --- a/res/rml/overlay.rcss +++ b/res/rml/overlay.rcss @@ -20,6 +20,14 @@ body { pointer-events: none; } +.lang-zh-cn body, +.lang-zh-cn body toast, +.lang-zh-cn body toast heading, +.lang-zh-cn body toast message, +.lang-zh-cn body fps { + font-family: "HarmonyOS Sans SC", "HarmonyOS Sans TC", "Microsoft YaHei", "Microsoft JhengHei", "Yu Gothic UI", "Malgun Gothic", "Noto Sans CJK SC", "Noto Sans CJK TC", "Noto Sans CJK JP", "Noto Sans CJK KR", "Noto Sans SC", "Noto Sans TC", "Noto Sans JP", "Noto Sans KR", "SimHei", sans-serif; +} + fps, toast { position: absolute; @@ -324,3 +332,10 @@ logo img.outer { top: 20dp; } } + +/* Keep CJK font override at end so it wins over per-widget font-family rules. */ +.lang-zh-cn body toast heading, +.lang-zh-cn body speedrun-timer, +.lang-zh-cn body fps { + font-family: "HarmonyOS Sans SC", "HarmonyOS Sans TC", "Microsoft YaHei", "Microsoft JhengHei", "Yu Gothic UI", "Malgun Gothic", "Noto Sans CJK SC", "Noto Sans CJK TC", "Noto Sans CJK JP", "Noto Sans CJK KR", "Noto Sans SC", "Noto Sans TC", "Noto Sans JP", "Noto Sans KR", "SimHei", sans-serif; +} diff --git a/res/rml/prelaunch.rcss b/res/rml/prelaunch.rcss index f5d7240d56..b639713526 100644 --- a/res/rml/prelaunch.rcss +++ b/res/rml/prelaunch.rcss @@ -14,6 +14,14 @@ body { z-index: -1; } +.lang-zh-cn body, +.lang-zh-cn body menu, +.lang-zh-cn body menu button, +.lang-zh-cn body disc-info, +.lang-zh-cn body version-info { + font-family: "HarmonyOS Sans SC", "HarmonyOS Sans TC", "Microsoft YaHei", "Microsoft JhengHei", "Yu Gothic UI", "Malgun Gothic", "Noto Sans CJK SC", "Noto Sans CJK TC", "Noto Sans CJK JP", "Noto Sans CJK KR", "Noto Sans SC", "Noto Sans TC", "Noto Sans JP", "Noto Sans KR", "SimHei", sans-serif; +} + .gradient { position: absolute; width: 100%; @@ -494,3 +502,14 @@ body.animate-in .intro-item { justify-content: flex-start; } } + +/* Keep CJK font override at end so it wins over per-widget font-family rules. */ +.lang-zh-cn body eyebrow, +.lang-zh-cn body #menu-list button, +.lang-zh-cn body disc-info, +.lang-zh-cn body version-info, +.lang-zh-cn body #disc-version, +.lang-zh-cn body .update, +.lang-zh-cn body .detail { + font-family: "HarmonyOS Sans SC", "HarmonyOS Sans TC", "Microsoft YaHei", "Microsoft JhengHei", "Yu Gothic UI", "Malgun Gothic", "Noto Sans CJK SC", "Noto Sans CJK TC", "Noto Sans CJK JP", "Noto Sans CJK KR", "Noto Sans SC", "Noto Sans TC", "Noto Sans JP", "Noto Sans KR", "SimHei", sans-serif; +} diff --git a/res/rml/window.rcss b/res/rml/window.rcss index ab338e97c7..407af9d1bb 100644 --- a/res/rml/window.rcss +++ b/res/rml/window.rcss @@ -14,8 +14,11 @@ body { color: #E0DBC8; } -b { - font-weight: bold; +.lang-zh-cn body, +.lang-zh-cn body window tab-bar, +.lang-zh-cn body window content pane, +.lang-zh-cn body window content pane:last-of-type > div { + font-family: "HarmonyOS Sans SC", "HarmonyOS Sans TC", "Microsoft YaHei", "Microsoft JhengHei", "Yu Gothic UI", "Malgun Gothic", "Noto Sans CJK SC", "Noto Sans CJK TC", "Noto Sans CJK JP", "Noto Sans CJK KR", "Noto Sans SC", "Noto Sans TC", "Noto Sans JP", "Noto Sans KR", "SimHei", sans-serif; } window { @@ -519,3 +522,12 @@ progress.verification-progress-bar { flex: 0 0 auto; padding-top: 4dp; } + +/* Keep CJK font override at end so it wins over per-widget font-family rules. */ +.lang-zh-cn body .section-heading, +.lang-zh-cn body window tab-bar, +.lang-zh-cn body select-button key, +.lang-zh-cn body .modal-title, +.lang-zh-cn body .achievement-total { + font-family: "HarmonyOS Sans SC", "HarmonyOS Sans TC", "Microsoft YaHei", "Microsoft JhengHei", "Yu Gothic UI", "Malgun Gothic", "Noto Sans CJK SC", "Noto Sans CJK TC", "Noto Sans CJK JP", "Noto Sans CJK KR", "Noto Sans SC", "Noto Sans TC", "Noto Sans JP", "Noto Sans KR", "SimHei", sans-serif; +} diff --git a/src/dusk/achievements.cpp b/src/dusk/achievements.cpp index a8e4ff3916..2f7288342f 100644 --- a/src/dusk/achievements.cpp +++ b/src/dusk/achievements.cpp @@ -52,8 +52,8 @@ std::vector AchievementSystem::makeEntries() { { { "hero_of_twilight", - "Hero of Twilight", - "Deliver the finishing blow to Ganondorf.", + "[ACHIEVEMENT_HERO_OF_TWILIGHT_NAME]", + "[ACHIEVEMENT_HERO_OF_TWILIGHT_DESC]", AchievementCategory::Challenge, false, 0, 0, false }, @@ -68,8 +68,8 @@ std::vector AchievementSystem::makeEntries() { { { "completionist", - "Completionist", - "Complete the game after collecting all equipment, heart containers, portals, bugs, poes, and hidden skills.", + "[ACHIEVEMENT_COMPLETIONIST_NAME]", + "[ACHIEVEMENT_COMPLETIONIST_DESC]", AchievementCategory::Challenge, false, 0, 0, false }, @@ -238,8 +238,8 @@ std::vector AchievementSystem::makeEntries() { { { "princess_of_bugs", - "The Princess of Bugs", - "Deliver all 24 golden bugs to Agitha.", + "[ACHIEVEMENT_PRINCESS_OF_BUGS_NAME]", + "[ACHIEVEMENT_PRINCESS_OF_BUGS_DESC]", AchievementCategory::Collection, true, 24, 0, false }, @@ -251,8 +251,8 @@ std::vector AchievementSystem::makeEntries() { { { "all_poes", - "Poe Collector", - "Collect all 60 Poe Souls.", + "[ACHIEVEMENT_ALL_POES_NAME]", + "[ACHIEVEMENT_ALL_POES_DESC]", AchievementCategory::Collection, true, 60, 0, false }, @@ -264,8 +264,8 @@ std::vector AchievementSystem::makeEntries() { { { "hylian_loach", - "Legendary Catch", - "Catch a Hylian Loach.", + "[ACHIEVEMENT_HYLIAN_LOACH_NAME]", + "[ACHIEVEMENT_HYLIAN_LOACH_DESC]", AchievementCategory::Collection, false, 0, 0, false }, @@ -279,8 +279,8 @@ std::vector AchievementSystem::makeEntries() { { { "all_fish", - "Gone Fishin'", - "Catch all 6 species of fish.", + "[ACHIEVEMENT_ALL_FISH_NAME]", + "[ACHIEVEMENT_ALL_FISH_DESC]", AchievementCategory::Collection, true, 6, 0, false }, @@ -298,8 +298,8 @@ std::vector AchievementSystem::makeEntries() { { { "a_big_heart", - "A Big Heart", - "Reach maximum health with all 20 heart containers.", + "[ACHIEVEMENT_A_BIG_HEART_NAME]", + "[ACHIEVEMENT_A_BIG_HEART_DESC]", AchievementCategory::Collection, true, 20, 0, false }, @@ -311,8 +311,8 @@ std::vector AchievementSystem::makeEntries() { { { "all_bottles", - "Glassware Guardian", - "Obtain all 4 bottles.", + "[ACHIEVEMENT_ALL_BOTTLES_NAME]", + "[ACHIEVEMENT_ALL_BOTTLES_DESC]", AchievementCategory::Collection, true, 4, 0, false }, @@ -333,8 +333,8 @@ std::vector AchievementSystem::makeEntries() { { { "all_hidden_skills", - "Master of Secrets", - "Learn all 7 Hidden Skills.", + "[ACHIEVEMENT_ALL_HIDDEN_SKILLS_NAME]", + "[ACHIEVEMENT_ALL_HIDDEN_SKILLS_DESC]", AchievementCategory::Collection, true, 7, 0, false }, @@ -358,8 +358,8 @@ std::vector AchievementSystem::makeEntries() { { { "all_letters", - "We Deliver!", - "Collect all 16 postman letters.", + "[ACHIEVEMENT_ALL_LETTERS_NAME]", + "[ACHIEVEMENT_ALL_LETTERS_DESC]", AchievementCategory::Collection, true, 16, 0, false }, @@ -371,8 +371,8 @@ std::vector AchievementSystem::makeEntries() { { { "cave_of_ordeals", - "Conqueror of Ordeals", - "Clear all 50 floors of the Cave of Ordeals.", + "[ACHIEVEMENT_CAVE_OF_ORDEALS_NAME]", + "[ACHIEVEMENT_CAVE_OF_ORDEALS_DESC]", AchievementCategory::Challenge, false, 0, 0, false }, @@ -386,8 +386,8 @@ std::vector AchievementSystem::makeEntries() { { { "cave_of_ordeals_heartless", - "Indomitable", - "Clear all 50 floors of the Cave of Ordeals with only 3 heart containers.", + "[ACHIEVEMENT_CAVE_OF_ORDEALS_HEARTLESS_NAME]", + "[ACHIEVEMENT_CAVE_OF_ORDEALS_HEARTLESS_DESC]", AchievementCategory::Challenge, false, 0, 0, false }, @@ -401,8 +401,8 @@ std::vector AchievementSystem::makeEntries() { { { "speedrun_12h", - "Been There Done That", - "Defeat Ganondorf with a total save file play time under 12 hours.", + "[ACHIEVEMENT_SPEEDRUN_12H_NAME]", + "[ACHIEVEMENT_SPEEDRUN_12H_DESC]", AchievementCategory::Challenge, false, 0, 0, false }, @@ -421,8 +421,8 @@ std::vector AchievementSystem::makeEntries() { { { "speedrun_8h", - "Swift Blade", - "Defeat Ganondorf with a total save file play time under 6 hours.", + "[ACHIEVEMENT_SPEEDRUN_8H_NAME]", + "[ACHIEVEMENT_SPEEDRUN_8H_DESC]", AchievementCategory::Challenge, false, 0, 0, false }, @@ -441,8 +441,8 @@ std::vector AchievementSystem::makeEntries() { { { "dark_hammer_one_hit", - "Mortal Edge", - "Defeat Dark Hammer in a single hit.", + "[ACHIEVEMENT_DARK_HAMMER_ONE_HIT_NAME]", + "[ACHIEVEMENT_DARK_HAMMER_ONE_HIT_DESC]", AchievementCategory::Misc, false, 0, 0, false }, @@ -456,8 +456,8 @@ std::vector AchievementSystem::makeEntries() { { { "no_deaths_clear", - "Deathless", - "Defeat Ganondorf with 0 deaths on your save file.", + "[ACHIEVEMENT_NO_DEATHS_CLEAR_NAME]", + "[ACHIEVEMENT_NO_DEATHS_CLEAR_DESC]", AchievementCategory::Challenge, false, 0, 0, false }, @@ -475,8 +475,8 @@ std::vector AchievementSystem::makeEntries() { { { "untouchable", - "Untouchable", - "Kill 25 enemies in a row without taking damage.", + "[ACHIEVEMENT_UNTOUCHABLE_NAME]", + "[ACHIEVEMENT_UNTOUCHABLE_DESC]", AchievementCategory::Challenge, true, 25, 0, false }, @@ -494,8 +494,8 @@ std::vector AchievementSystem::makeEntries() { { { "bow_100m_hit", - "Long Shot", - "Hit an enemy from over 100 meters away with the bow.", + "[ACHIEVEMENT_BOW_100M_HIT_NAME]", + "[ACHIEVEMENT_BOW_100M_HIT_DESC]", AchievementCategory::Misc, false, 0, 0, false }, @@ -510,8 +510,8 @@ std::vector AchievementSystem::makeEntries() { { { "plumm_max", - "Thank You Berry Much", - "Score 61,454 points in the Plumm minigame.", + "[ACHIEVEMENT_PLUMM_MAX_NAME]", + "[ACHIEVEMENT_PLUMM_MAX_DESC]", AchievementCategory::Minigame, false, 0, 0, false }, @@ -525,8 +525,8 @@ std::vector AchievementSystem::makeEntries() { { { "rollgoal_8", - "Rollgoal Novice", - "Complete the first 8 rollgoal stages.", + "[ACHIEVEMENT_ROLLGOAL_8_NAME]", + "[ACHIEVEMENT_ROLLGOAL_8_DESC]", AchievementCategory::Minigame, true, 8, 0, false }, @@ -538,8 +538,8 @@ std::vector AchievementSystem::makeEntries() { { { "rollgoal_all", - "Lost Your Marbles", - "Complete all rollgoal stages.", + "[ACHIEVEMENT_ROLLGOAL_ALL_NAME]", + "[ACHIEVEMENT_ROLLGOAL_ALL_DESC]", AchievementCategory::Minigame, true, 64, 0, false }, @@ -555,8 +555,8 @@ std::vector AchievementSystem::makeEntries() { { { "goat_30s", - "Ranch Hand", - "Herd all 20 goats into the pen in under 30 seconds.", + "[ACHIEVEMENT_GOAT_30S_NAME]", + "[ACHIEVEMENT_GOAT_30S_DESC]", AchievementCategory::Minigame, false, 0, 0, false }, @@ -568,8 +568,8 @@ std::vector AchievementSystem::makeEntries() { { { "goat_20s", - "Bane of Howard", - "Herd all 20 goats into the pen in under 20 seconds.", + "[ACHIEVEMENT_GOAT_20S_NAME]", + "[ACHIEVEMENT_GOAT_20S_DESC]", AchievementCategory::Minigame, false, 0, 0, false }, @@ -581,8 +581,8 @@ std::vector AchievementSystem::makeEntries() { { { "goat_18s", - "King of the Ranch", - "Herd all 20 goats into the pen in under 18 seconds.", + "[ACHIEVEMENT_GOAT_18S_NAME]", + "[ACHIEVEMENT_GOAT_18S_DESC]", AchievementCategory::Minigame, false, 0, 0, false }, @@ -594,8 +594,8 @@ std::vector AchievementSystem::makeEntries() { { { "snowboard_70s", - "Downhill Dash", - "Finish the snowboarding minigame in under 70 seconds.", + "[ACHIEVEMENT_SNOWBOARD_70S_NAME]", + "[ACHIEVEMENT_SNOWBOARD_70S_DESC]", AchievementCategory::Minigame, false, 0, 0, false }, @@ -611,8 +611,8 @@ std::vector AchievementSystem::makeEntries() { { { "canoe_perfect", - "River Raider", - "Achieve a perfect score in the canoe minigame.", + "[ACHIEVEMENT_CANOE_PERFECT_NAME]", + "[ACHIEVEMENT_CANOE_PERFECT_DESC]", AchievementCategory::Minigame, false, 0, 0, false }, @@ -634,8 +634,8 @@ std::vector AchievementSystem::makeEntries() { { { "star_2_under_40s", - "Rising Star", - "Complete the STAR Prize 2 minigame in under 40 seconds.", + "[ACHIEVEMENT_STAR_2_UNDER_40S_NAME]", + "[ACHIEVEMENT_STAR_2_UNDER_40S_DESC]", AchievementCategory::Minigame, false, 0, 0, false }, @@ -649,8 +649,8 @@ std::vector AchievementSystem::makeEntries() { { { "star_2_under_30s", - "Shooting Star", - "Complete the STAR Prize 2 minigame in under 30 seconds.", + "[ACHIEVEMENT_STAR_2_UNDER_30S_NAME]", + "[ACHIEVEMENT_STAR_2_UNDER_30S_DESC]", AchievementCategory::Minigame, false, 0, 0, false }, @@ -665,8 +665,8 @@ std::vector AchievementSystem::makeEntries() { { { "friendly_fire", - "Friendly Fire", - "Get hit by your own cannonball.", + "[ACHIEVEMENT_FRIENDLY_FIRE_NAME]", + "[ACHIEVEMENT_FRIENDLY_FIRE_DESC]", AchievementCategory::Misc, false, 0, 0, false }, @@ -680,8 +680,8 @@ std::vector AchievementSystem::makeEntries() { { { "long_jump_attack", - "Long Jump Attack", - "Travel more than 20 meters in a single jump attack before landing.", + "[ACHIEVEMENT_LONG_JUMP_ATTACK_NAME]", + "[ACHIEVEMENT_LONG_JUMP_ATTACK_DESC]", AchievementCategory::Misc, false, 0, 0, false }, @@ -723,8 +723,8 @@ std::vector AchievementSystem::makeEntries() { { { "email_me", - "Email Me", - "Read a letter during the Dark Beast Ganon fight.", + "[ACHIEVEMENT_EMAIL_ME_NAME]", + "[ACHIEVEMENT_EMAIL_ME_DESC]", AchievementCategory::Misc, false, 0, 0, false }, @@ -739,8 +739,8 @@ std::vector AchievementSystem::makeEntries() { { { "heavy_hitter", - "Heavy Hitter", - "Wear the Iron Boots during the end credits.", + "[ACHIEVEMENT_HEAVY_HITTER_NAME]", + "[ACHIEVEMENT_HEAVY_HITTER_DESC]", AchievementCategory::Misc, false, 0, 0, false }, @@ -758,8 +758,8 @@ std::vector AchievementSystem::makeEntries() { { { "fishing_rod_ganondorf", - "Here Fishy Fishy", - "Confuse Ganondorf with the fishing rod.", + "[ACHIEVEMENT_FISHING_ROD_GANONDORF_NAME]", + "[ACHIEVEMENT_FISHING_ROD_GANONDORF_DESC]", AchievementCategory::Misc, false, 0, 0, false }, @@ -773,8 +773,8 @@ std::vector AchievementSystem::makeEntries() { { { "steal_from_trill", - "Petty Theft", - "Steal from Trill.", + "[ACHIEVEMENT_STEAL_FROM_TRILL_NAME]", + "[ACHIEVEMENT_STEAL_FROM_TRILL_DESC]", AchievementCategory::Misc, false, 0, 0, false }, @@ -788,8 +788,8 @@ std::vector AchievementSystem::makeEntries() { { { "cucco_control", - "Cucco Whisperer", - "Take control of a cucco.", + "[ACHIEVEMENT_CUCCO_CONTROL_NAME]", + "[ACHIEVEMENT_CUCCO_CONTROL_DESC]", AchievementCategory::Misc, false, 0, 0, false }, @@ -804,8 +804,8 @@ std::vector AchievementSystem::makeEntries() { { { "back_in_time", - "Back in Time", - "Perform the Back in Time glitch to play on the title screen.", + "[ACHIEVEMENT_BACK_IN_TIME_NAME]", + "[ACHIEVEMENT_BACK_IN_TIME_DESC]", AchievementCategory::Glitched, false, 0, 0, false }, @@ -824,8 +824,8 @@ std::vector AchievementSystem::makeEntries() { { { "early_master_sword", - "Early Master Sword", - "Obtain the Master Sword before completing Midna's Desperate Hour.", + "[ACHIEVEMENT_EARLY_MASTER_SWORD_NAME]", + "[ACHIEVEMENT_EARLY_MASTER_SWORD_DESC]", AchievementCategory::Glitched, false, 0, 0, false }, @@ -839,8 +839,8 @@ std::vector AchievementSystem::makeEntries() { { { "earliest_master_sword", - "Earliest Master Sword", - "Obtain the Master Sword before meeting Midna.", + "[ACHIEVEMENT_EARLIEST_MASTER_SWORD_NAME]", + "[ACHIEVEMENT_EARLIEST_MASTER_SWORD_DESC]", AchievementCategory::Glitched, false, 0, 0, false }, @@ -854,8 +854,8 @@ std::vector AchievementSystem::makeEntries() { { { "speedrun_4h", - "Hero of Time", - "Defeat Ganondorf with a total save file play time under 4 hours.", + "[ACHIEVEMENT_SPEEDRUN_4H_NAME]", + "[ACHIEVEMENT_SPEEDRUN_4H_DESC]", AchievementCategory::Glitched, false, 0, 0, false }, @@ -874,8 +874,8 @@ std::vector AchievementSystem::makeEntries() { { { "no_fish_suit", - "No Fish Suit No Problem", - "Defeat Morpheel without equipping Zora Armor.", + "[ACHIEVEMENT_NO_FISH_SUIT_NAME]", + "[ACHIEVEMENT_NO_FISH_SUIT_DESC]", AchievementCategory::Glitched, false, 0, 0, false }, @@ -910,8 +910,8 @@ std::vector AchievementSystem::makeEntries() { { { "null_item", - "Null Item", - "Obtain the mysterious black rupee in the item wheel.", + "[ACHIEVEMENT_NULL_ITEM_NAME]", + "[ACHIEVEMENT_NULL_ITEM_DESC]", AchievementCategory::Glitched, false, 0, 0, false }, @@ -931,8 +931,8 @@ std::vector AchievementSystem::makeEntries() { { { "stallord_skip", - "Stallord Skip", - "Leave Stallord's arena through the exit without defeating Stallord.", + "[ACHIEVEMENT_STALLORD_SKIP_NAME]", + "[ACHIEVEMENT_STALLORD_SKIP_DESC]", AchievementCategory::Glitched, false, 0, 0, false }, @@ -960,8 +960,8 @@ std::vector AchievementSystem::makeEntries() { { { "lakebed_before_lanayru", - "White Midna Glitch", - "Clear the Lakebed Temple before clearing Lanayru's Twilight.", + "[ACHIEVEMENT_LAKEBED_BEFORE_LANAYRU_NAME]", + "[ACHIEVEMENT_LAKEBED_BEFORE_LANAYRU_DESC]", AchievementCategory::Glitched, false, 0, 0, false }, @@ -976,8 +976,8 @@ std::vector AchievementSystem::makeEntries() { { { "early_hidden_village", - "Quick Detour", - "Rescue the Hidden Village before clearing Goron Mines.", + "[ACHIEVEMENT_EARLY_HIDDEN_VILLAGE_NAME]", + "[ACHIEVEMENT_EARLY_HIDDEN_VILLAGE_DESC]", AchievementCategory::Glitched, false, 0, 0, false }, @@ -992,8 +992,8 @@ std::vector AchievementSystem::makeEntries() { { { "forest_temple_no_boomerang", - "Must Have Been The Wind", - "Complete the Forest Temple without obtaining the Gale Boomerang.", + "[ACHIEVEMENT_FOREST_TEMPLE_NO_BOOMERANG_NAME]", + "[ACHIEVEMENT_FOREST_TEMPLE_NO_BOOMERANG_DESC]", AchievementCategory::Glitched, false, 0, 0, false }, @@ -1125,7 +1125,7 @@ void AchievementSystem::processEntry(Entry& e) { if (getSettings().game.enableAchievementToasts) { ui::push_toast({ .type = "achievement", - .title = "Achievement Unlocked!", + .title = "[ACHIEVEMENT_UNLOCKED_TOAST]", .content = e.achievement.name, .duration = std::chrono::seconds(5), }); diff --git a/src/dusk/settings.cpp b/src/dusk/settings.cpp index 5861241fe3..beb22fa247 100644 --- a/src/dusk/settings.cpp +++ b/src/dusk/settings.cpp @@ -54,6 +54,7 @@ UserSettings g_userSettings = { .enableAchievementToasts {"game.enableAchievementToasts", true}, .enableControllerToasts {"game.enableControllerToasts", true}, .enableDiscordPresence {"game.enableDiscordPresence", true}, + .enableChineseNameKeyboard {"game.enableChineseNameKeyboard", false}, // Graphics .bloomMode {"game.bloomMode", BloomMode::Dusk}, @@ -131,6 +132,7 @@ UserSettings g_userSettings = { .backend = { .isoPath {"backend.isoPath", ""}, .isoVerification {"backend.isoVerification", DiscVerificationState::Unknown}, + .uiLanguage {"backend.uiLanguage", "en"}, .graphicsBackend {"backend.graphicsBackend", "auto"}, .skipPreLaunchUI {"backend.skipPreLaunchUI", false}, .showPipelineCompilation {"backend.showPipelineCompilation", false}, @@ -237,6 +239,7 @@ void registerSettings() { Register(g_userSettings.game.enableLinkDollRotation); Register(g_userSettings.game.enableAchievementToasts); Register(g_userSettings.game.enableControllerToasts); + Register(g_userSettings.game.enableChineseNameKeyboard); Register(g_userSettings.game.noMissClimbing); Register(g_userSettings.game.noLowHpSound); Register(g_userSettings.game.midnasLamentNonStop); @@ -279,6 +282,7 @@ void registerSettings() { Register(g_userSettings.backend.isoPath); Register(g_userSettings.backend.isoVerification); + Register(g_userSettings.backend.uiLanguage); Register(g_userSettings.backend.graphicsBackend); Register(g_userSettings.backend.skipPreLaunchUI); Register(g_userSettings.backend.showPipelineCompilation); diff --git a/src/dusk/ui/achievements.cpp b/src/dusk/ui/achievements.cpp index b631d444f5..9077271797 100644 --- a/src/dusk/ui/achievements.cpp +++ b/src/dusk/ui/achievements.cpp @@ -16,11 +16,11 @@ struct CategoryInfo { }; constexpr CategoryInfo kCategories[] = { - {AchievementCategory::Challenge, "Challenge"}, - {AchievementCategory::Collection, "Collection"}, - {AchievementCategory::Minigame, "Minigame"}, - {AchievementCategory::Misc, "Misc"}, - {AchievementCategory::Glitched, "Glitched"}, + {AchievementCategory::Challenge, "[CHALLENGE]"}, + {AchievementCategory::Collection, "[COLLECTION]"}, + {AchievementCategory::Minigame, "[MINIGAME]"}, + {AchievementCategory::Misc, "[MISC]"}, + {AchievementCategory::Glitched, "[GLITCHED]"}, }; Rml::String build_achievement_info_rml(const Achievement& a) { @@ -33,7 +33,7 @@ Rml::String build_achievement_info_rml(const Achievement& a) { a.unlocked ? " unlocked" : "", a.name, a.unlocked ? " unlocked" : " locked", - a.unlocked ? "Unlocked" : "Locked", + a.unlocked ? "[UNLOCKED]" : "[LOCKED]", a.description ); @@ -69,7 +69,7 @@ class AchievementRow : public FluentComponent { resetConfirm(); } else { mConfirming = true; - mClearButton->set_text("Clear?"); + mClearButton->set_text("[CLEAR_QUESTION]"); } return true; } @@ -146,7 +146,7 @@ AchievementsWindow::AchievementsWindow() { auto& pane = add_child(content, Pane::Type::Controlled); - pane.add_section(fmt::format("{} / {} unlocked", unlocked, total)); + pane.add_section(fmt::format("{} / {} [UNLOCKED]", unlocked, total)); for (const auto& a : achievements) { if (a.category != cat) { @@ -155,9 +155,9 @@ AchievementsWindow::AchievementsWindow() { pane.add_child(a); } - pane.add_section("Actions"); + pane.add_section("[ACTIONS]"); - auto& clearAllBtn = pane.add_button("Clear All Achievements"); + auto& clearAllBtn = pane.add_button("[CLEAR_ALL_ACHIEVEMENTS]"); auto* clearAllPtr = &clearAllBtn; auto confirmingAll = std::make_shared(false); @@ -167,23 +167,23 @@ AchievementsWindow::AchievementsWindow() { mDoAud_seStartMenu(kSoundClick); AchievementSystem::get().clearAll(); *confirmingAll = false; - clearAllPtr->set_text("Clear All Achievements"); + clearAllPtr->set_text("[CLEAR_ALL_ACHIEVEMENTS]"); } else { *confirmingAll = true; - clearAllPtr->set_text("Are you sure?"); + clearAllPtr->set_text("[ARE_YOU_SURE]"); } return true; } if (cmd == NavCommand::Cancel && *confirmingAll) { *confirmingAll = false; - clearAllPtr->set_text("Clear All Achievements"); + clearAllPtr->set_text("[CLEAR_ALL_ACHIEVEMENTS]"); return true; } return false; }); clearAllBtn.listen(Rml::EventId::Blur, [clearAllPtr, confirmingAll](Rml::Event&) { *confirmingAll = false; - clearAllPtr->set_text("Clear All Achievements"); + clearAllPtr->set_text("[CLEAR_ALL_ACHIEVEMENTS]"); }); pane.finalize(); diff --git a/src/dusk/ui/bool_button.cpp b/src/dusk/ui/bool_button.cpp index 2ed088542a..9e0cef1f6a 100644 --- a/src/dusk/ui/bool_button.cpp +++ b/src/dusk/ui/bool_button.cpp @@ -29,7 +29,7 @@ bool BoolButton::disabled() const { } Rml::String BoolButton::format_value() { - return mGetValue() ? "On" : "Off"; + return mGetValue() ? "[ON]" : "[OFF]"; } bool BoolButton::handle_nav_command(NavCommand cmd) { @@ -42,4 +42,4 @@ bool BoolButton::handle_nav_command(NavCommand cmd) { return false; } -} // namespace dusk::ui \ No newline at end of file +} // namespace dusk::ui diff --git a/src/dusk/ui/controller_config.cpp b/src/dusk/ui/controller_config.cpp index a0b2b6baa9..3ce1a99551 100644 --- a/src/dusk/ui/controller_config.cpp +++ b/src/dusk/ui/controller_config.cpp @@ -17,6 +17,7 @@ #include "dusk/action_bindings.h" #include "dusk/config.hpp" +#include "dusk/settings.h" namespace dusk::ui { namespace { @@ -31,13 +32,13 @@ Rml::String current_controller_name(int port) { if (name != nullptr) { return name; } - return keyboard_active(port) ? "Keyboard" : "None"; + return keyboard_active(port) ? "[KEYBOARD]" : "[NONE]"; } Rml::String controller_index_name(u32 index) { const char* name = PADGetNameForControllerIndex(index); if (name == nullptr) { - return fmt::format("Device {}", index + 1); + return fmt::format("[CONTROLLER] {}", index + 1); } return name; } @@ -124,7 +125,7 @@ Rml::String native_axis_name(const PADAxisMapping& mapping, SDL_Gamepad* gamepad return native_button_name(gamepad, static_cast(mapping.nativeButton)); } - return "Not Bound"; + return "[NOT_BOUND]"; } bool is_dpad_button(PADButton button) { @@ -162,28 +163,28 @@ bool keyboard_escape_pressed() { Rml::String keyboard_key_name(s32 scancode) { if (scancode == PAD_KEY_INVALID) { - return "Not Bound"; + return "[NOT_BOUND]"; } switch (scancode) { case PAD_KEY_MOUSE_LEFT: - return "Mouse Left"; + return "[MOUSE_LEFT]"; case PAD_KEY_MOUSE_MIDDLE: - return "Mouse Middle"; + return "[MOUSE_MIDDLE]"; case PAD_KEY_MOUSE_RIGHT: - return "Mouse Right"; + return "[MOUSE_RIGHT]"; case PAD_KEY_MOUSE_X1: - return "Mouse X1"; + return "[MOUSE_X1]"; case PAD_KEY_MOUSE_X2: - return "Mouse X2"; + return "[MOUSE_X2]"; default: break; } if (scancode < 0) { - return "Unknown"; + return "[UNKNOWN]"; } const char* name = SDL_GetScancodeName(static_cast(scancode)); if (name == nullptr || name[0] == '\0') { - return "Unknown"; + return "[UNKNOWN]"; } return name; } @@ -263,7 +264,7 @@ ControllerConfigWindow::ControllerConfigWindow(bool prelaunch) { } for (int port = PAD_CHAN0; port < PAD_CHANMAX; ++port) { - add_tab(fmt::format("Port {}", port + 1), [this, port](Rml::Element* content) { + add_tab(fmt::format("[PORT] {}", port + 1), [this, port](Rml::Element* content) { if (mPendingPort != -1 && mPendingPort != port) { cancel_pending_binding(); } @@ -303,16 +304,16 @@ void ControllerConfigWindow::build_port_tab(Rml::Element* content, int port) { }); }; - addPageButton(Page::Controller, "Device", [port] { return current_controller_name(port); }, [] { return false; }); - addPageButton(Page::Buttons, "Buttons", [] { return Rml::String(">"); }, [] { return false; }); - addPageButton(Page::Triggers, "Triggers", [] { return Rml::String(">"); }, [] { return false; }); - addPageButton(Page::Sticks, "Sticks", [] { return Rml::String(">"); }, [] { return false; }); - addPageButton(Page::Rumble, "Rumble", [] { return Rml::String(">"); }, [port] { return !PADSupportsRumbleIntensity(static_cast(port)); }); - addPageButton(Page::Actions, "Custom Action Bindings", [] {return Rml::String(">"); }, [] { return false; }); + addPageButton(Page::Controller, "[CONTROLLER]", [port] { return current_controller_name(port); }, [] { return false; }); + addPageButton(Page::Buttons, "[BUTTONS]", [] { return Rml::String(">"); }, [] { return false; }); + addPageButton(Page::Triggers, "[TRIGGERS]", [] { return Rml::String(">"); }, [] { return false; }); + addPageButton(Page::Sticks, "[STICKS]", [] { return Rml::String(">"); }, [] { return false; }); + addPageButton(Page::Rumble, "[RUMBLE]", [] { return Rml::String(">"); }, [port] { return !PADSupportsRumbleIntensity(static_cast(port)); }); + addPageButton(Page::Actions, "[CUSTOM_ACTION_BINDINGS]", [] {return Rml::String(">"); }, [] { return false; }); - leftPane.add_section("Options"); + leftPane.add_section("[OPTIONS]"); leftPane.register_control(leftPane.add_child(BoolButton::Props{ - .key = "Enable Dead Zones", + .key = "[ENABLE_DEAD_ZONES]", .getValue = [port] { PADDeadZones* deadZones = PADGetDeadZones(port); @@ -328,10 +329,10 @@ void ControllerConfigWindow::build_port_tab(Rml::Element* content, int port) { .isDisabled = [port] { return PADGetDeadZones(port) == nullptr; }, }), rightPane, [](Pane& pane) { - pane.add_text("Apply configured dead zones to the sticks and analog triggers."); + pane.add_text("[APPLY_CONFIGURED_DEAD_ZONES_TO_THE_STICKS_AND_ANALOG_TRIGGERS]"); }); leftPane.register_control(leftPane.add_child(BoolButton::Props{ - .key = "Emulate Triggers", + .key = "[EMULATE_TRIGGERS]", .getValue = [port] { PADDeadZones* deadZones = PADGetDeadZones(port); @@ -347,16 +348,18 @@ void ControllerConfigWindow::build_port_tab(Rml::Element* content, int port) { .isDisabled = [port] { return PADGetDeadZones(port) == nullptr; }, }), rightPane, [](Pane& pane) { - pane.add_text("Treat analog trigger movement as digital L and R button input."); + pane.add_text("[TREAT_ANALOG_TRIGGER_MOVEMENT_AS_DIGITAL_L_AND_R_BUTTON_INPUT]"); }); - leftPane.register_control(leftPane.add_button("Restore Default Controls").on_pressed([this, port] { + + leftPane.register_control(leftPane.add_button("[RESTORE_DEFAULT_CONTROLS]").on_pressed([this, port] { mDoAud_seStartMenu(kSoundClick); PADRestoreDefaultMapping(port); }), - rightPane, [](Pane& pane) { - pane.clear(); - pane.add_text("Restores all binding configurations for the currently selected device to their defaults."); + rightPane, [](Pane& pane) { + pane.clear(); + pane.add_text("[RESTORES_ALL_BINDING_CONFIGURATIONS_FOR_THE_CURRENTLY_SELECTED_DEVICE_TO_THEIR_DEFAULTS]"); }); + render_page(rightPane, port, mPage); } @@ -367,7 +370,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { case Page::Controller: { pane.add_button( { - .text = "None", + .text = "[NONE]", .isSelected = [port] { return PADGetIndexForPort(port) < 0 && !keyboard_active(port); }, }) @@ -381,7 +384,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { }); pane.add_button({ - .text = "Keyboard", + .text = "[KEYBOARD]", .isSelected = [port] { return keyboard_active(port); }, }) .on_pressed([this, port] { @@ -395,7 +398,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { const u32 controllerCount = PADCount(); if (controllerCount == 0) { - pane.add_text("No Device Detected"); + pane.add_text("[NO_CONTROLLERS_DETECTED]"); break; } @@ -432,14 +435,14 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { PADKeyButtonBinding* bindings = PADGetKeyButtonBindings(static_cast(port), &count); if (bindings == nullptr) { - return Rml::String("Not Bound"); + return Rml::String("[NOT_BOUND]"); } for (u32 i = 0; i < PAD_BUTTON_COUNT; ++i) { if (bindings[i].padButton == button) { return keyboard_key_name(bindings[i].scancode); } } - return Rml::String("Not Bound"); + return Rml::String("[NOT_BOUND]"); }, }) .on_pressed([this, port, button] { @@ -451,7 +454,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { }); }; - pane.add_section("Buttons"); + pane.add_section("[BUTTONS]"); addKeyButton(PAD_BUTTON_A); addKeyButton(PAD_BUTTON_B); addKeyButton(PAD_BUTTON_X); @@ -459,7 +462,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { addKeyButton(PAD_BUTTON_START); addKeyButton(PAD_TRIGGER_Z); - pane.add_section("D-Pad"); + pane.add_section("[D_PAD]"); addKeyButton(PAD_BUTTON_UP); addKeyButton(PAD_BUTTON_DOWN); addKeyButton(PAD_BUTTON_LEFT); @@ -470,12 +473,12 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { u32 buttonCount = 0; PADButtonMapping* mappings = PADGetButtonMappings(port, &buttonCount); if (mappings == nullptr) { - pane.add_text("No Device Selected"); + pane.add_text("[NO_CONTROLLER_SELECTED]"); break; } SDL_Gamepad* gamepad = gamepad_for_port(port); - pane.add_section("Buttons"); + pane.add_section("[BUTTONS]"); for (u32 i = 0; i < buttonCount; ++i) { PADButtonMapping& mapping = mappings[i]; if (!is_action_button(mapping.padButton)) { @@ -492,7 +495,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { return native_button_name( gamepad, mapping.nativeButton); }, - }) + }) .on_pressed([this, port, &mapping] { mDoAud_seStartMenu(kSoundClick); cancel_pending_binding(); @@ -502,7 +505,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { }); } - pane.add_section("D-Pad"); + pane.add_section("[D_PAD]"); for (u32 i = 0; i < buttonCount; ++i) { PADButtonMapping& mapping = mappings[i]; if (!is_dpad_button(mapping.padButton)) { @@ -545,14 +548,14 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { PADKeyButtonBinding* bindings = PADGetKeyButtonBindings(static_cast(port), &count); if (bindings == nullptr) { - return Rml::String("Not Bound"); + return Rml::String("[NOT_BOUND]"); } for (u32 i = 0; i < PAD_BUTTON_COUNT; ++i) { if (bindings[i].padButton == button) { return keyboard_key_name(bindings[i].scancode); } } - return Rml::String("Not Bound"); + return Rml::String("[NOT_BOUND]"); }, }) .on_pressed([this, port, button] { @@ -577,30 +580,30 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { PADKeyAxisBinding* bindings = PADGetKeyAxisBindings(static_cast(port), &count); if (bindings == nullptr) { - return Rml::String("Not Bound"); + return Rml::String("[NOT_BOUND]"); } for (u32 i = 0; i < PAD_AXIS_COUNT; ++i) { if (bindings[i].padAxis == axis) { return keyboard_key_name(bindings[i].scancode); } } - return Rml::String("Not Bound"); + return Rml::String("[NOT_BOUND]"); }, - }) - .on_pressed([this, port, axis] { - mDoAud_seStartMenu(kSoundClick); - cancel_pending_binding(); - mPendingPort = port; - mPendingBindingArmed = false; + }) + .on_pressed([this, port, axis] { + mDoAud_seStartMenu(kSoundClick); + cancel_pending_binding(); + mPendingPort = port; + mPendingBindingArmed = false; mPendingKeyAxis = static_cast(axis); }); }; - pane.add_section("Analog"); + pane.add_section("[ANALOG]"); addKeyAxis(PAD_AXIS_TRIGGER_L); addKeyAxis(PAD_AXIS_TRIGGER_R); - pane.add_section("Digital"); + pane.add_section("[DIGITAL]"); addKeyButton(PAD_TRIGGER_L); addKeyButton(PAD_TRIGGER_R); break; @@ -611,12 +614,12 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { u32 buttonCount = 0; PADButtonMapping* buttons = PADGetButtonMappings(port, &buttonCount); if (axes == nullptr && buttons == nullptr) { - pane.add_text("No Device Selected"); + pane.add_text("[NO_CONTROLLER_SELECTED]"); break; } SDL_Gamepad* gamepad = gamepad_for_port(port); - pane.add_section("Analog"); + pane.add_section("[ANALOG]"); constexpr std::array kTriggerAxes = {PAD_AXIS_TRIGGER_L, PAD_AXIS_TRIGGER_R}; if (axes != nullptr) { for (PADAxis axis : kTriggerAxes) { @@ -633,19 +636,19 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { } return native_axis_name(mapping, gamepad); }, - }) - .on_pressed([this, port, &mapping] { - mDoAud_seStartMenu(kSoundClick); - cancel_pending_binding(); - mPendingPort = port; - mPendingBindingArmed = false; + }) + .on_pressed([this, port, &mapping] { + mDoAud_seStartMenu(kSoundClick); + cancel_pending_binding(); + mPendingPort = port; + mPendingBindingArmed = false; mPendingAxisMapping = &mapping; }); } } if (getSettings().backend.enableAdvancedSettings) { - pane.add_section("Digital"); + pane.add_section("[DIGITAL]"); if (buttons != nullptr) { for (u32 i = 0; i < buttonCount; ++i) { PADButtonMapping& mapping = buttons[i]; @@ -675,9 +678,9 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { } if (PADDeadZones* deadZones = PADGetDeadZones(port)) { - pane.add_section("Emulated Trigger Thresholds"); + pane.add_section("[EMULATED_TRIGGER_THRESHOLDS]"); pane.add_child(NumberButton::Props{ - .key = "L Threshold", + .key = "[L_THRESHOLD]", .getValue = [deadZones] { return deadzone_raw_to_percent(deadZones->leftTriggerActivationZone); }, .setValue = [deadZones](int value) { @@ -691,7 +694,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { .suffix = "%", }); pane.add_child(NumberButton::Props{ - .key = "R Threshold", + .key = "[R_THRESHOLD]", .getValue = [deadZones] { return deadzone_raw_to_percent(deadZones->rightTriggerActivationZone); }, .setValue = [deadZones](int value) { @@ -722,32 +725,32 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { PADKeyAxisBinding* bindings = PADGetKeyAxisBindings(static_cast(port), &count); if (bindings == nullptr) { - return Rml::String("Not Bound"); + return Rml::String("[NOT_BOUND]"); } for (u32 i = 0; i < PAD_AXIS_COUNT; ++i) { if (bindings[i].padAxis == axis) { return keyboard_key_name(bindings[i].scancode); } } - return Rml::String("Not Bound"); + return Rml::String("[NOT_BOUND]"); }, - }) - .on_pressed([this, port, axis] { - mDoAud_seStartMenu(kSoundClick); - cancel_pending_binding(); - mPendingPort = port; - mPendingBindingArmed = false; + }) + .on_pressed([this, port, axis] { + mDoAud_seStartMenu(kSoundClick); + cancel_pending_binding(); + mPendingPort = port; + mPendingBindingArmed = false; mPendingKeyAxis = static_cast(axis); }); }; - pane.add_section("Control Stick"); + pane.add_section("[CONTROL_STICK]"); addKeyAxis(PAD_AXIS_LEFT_Y_POS); addKeyAxis(PAD_AXIS_LEFT_Y_NEG); addKeyAxis(PAD_AXIS_LEFT_X_NEG); addKeyAxis(PAD_AXIS_LEFT_X_POS); - pane.add_section("C Stick"); + pane.add_section("[C_STICK]"); addKeyAxis(PAD_AXIS_RIGHT_Y_POS); addKeyAxis(PAD_AXIS_RIGHT_Y_NEG); addKeyAxis(PAD_AXIS_RIGHT_X_NEG); @@ -758,7 +761,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { u32 axisCount = 0; PADAxisMapping* axes = PADGetAxisMappings(port, &axisCount); if (axes == nullptr) { - pane.add_text("No Device Selected"); + pane.add_text("[NO_CONTROLLER_SELECTED]"); break; } @@ -787,14 +790,14 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { }); }; - pane.add_section("Control Stick"); + pane.add_section("[CONTROL_STICK]"); addAxis(PAD_AXIS_LEFT_Y_POS); addAxis(PAD_AXIS_LEFT_Y_NEG); addAxis(PAD_AXIS_LEFT_X_NEG); addAxis(PAD_AXIS_LEFT_X_POS); if (PADDeadZones* deadZones = PADGetDeadZones(port)) { pane.add_child(NumberButton::Props{ - .key = "Deadzone", + .key = "[DEADZONE]", .getValue = [deadZones] { return deadzone_raw_to_percent(deadZones->stickDeadZone); }, .setValue = [deadZones](int value) { @@ -809,14 +812,14 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { }); } - pane.add_section("C Stick"); + pane.add_section("[C_STICK]"); addAxis(PAD_AXIS_RIGHT_Y_POS); addAxis(PAD_AXIS_RIGHT_Y_NEG); addAxis(PAD_AXIS_RIGHT_X_NEG); addAxis(PAD_AXIS_RIGHT_X_POS); if (PADDeadZones* deadZones = PADGetDeadZones(port)) { pane.add_child(NumberButton::Props{ - .key = "Deadzone", + .key = "[DEADZONE]", .getValue = [deadZones] { return deadzone_raw_to_percent(deadZones->substickDeadZone); }, .setValue = [deadZones](int value) { @@ -835,11 +838,11 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { } case Page::Rumble: { auto& rumbleTest = pane.add_select_button({ - .key = "Test Rumble", + .key = "[TEST_RUMBLE]", .getValue = [this, port] { - return (mRumbleTestActive && mRumbleTestPort == port) ? Rml::String("Stop") - : Rml::String("Start"); + return (mRumbleTestActive && mRumbleTestPort == port) ? Rml::String("[STOP]") + : Rml::String("[START]"); }, }); rumbleTest.on_pressed([this, port] { @@ -861,7 +864,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { } }); pane.add_child(NumberButton::Props{ - .key = "Low Rumble Frequency", + .key = "[LOW_RUMBLE_FREQUENCY]", .getValue = [port] { u16 low = 0; @@ -884,7 +887,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { .suffix = "%", }); pane.add_child(NumberButton::Props{ - .key = "High Rumble Frequency", + .key = "[HIGH_RUMBLE_FREQUENCY]", .getValue = [port] { u16 low = 0; @@ -906,7 +909,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { .step = 1, .suffix = "%", }); - pane.add_text("Configure your desired rumble intensities, then run a test to check how they feel."); + pane.add_text("[CONFIGURE_YOUR_DESIRED_RUMBLE_INTENSITIES_THEN_RUN_A_TEST_TO_CHECK]"); break; } case Page::Actions: { @@ -923,19 +926,18 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { return keyboard_key_name(actionBind->getValue()); }, - }) - .on_pressed([this, port, actionBind] { - mDoAud_seStartMenu(kSoundClick); - cancel_pending_binding(); - mPendingPort = port; - mPendingBindingArmed = false; + }) + .on_pressed([this, port, actionBind] { + mDoAud_seStartMenu(kSoundClick); + cancel_pending_binding(); + mPendingPort = port; + mPendingBindingArmed = false; mPendingActionBinding = actionBind; }); }; - pane.add_section("Custom Action Bindings"); - pane.add_text("A key bound to any action here will REPLACE the default control for" - " that action. Only bind buttons here that aren't used anywhere else."); + pane.add_section("[CUSTOM_ACTION_BINDINGS]"); + pane.add_text("[A_KEY_BOUND_TO_ANY_ACTION_HERE_WILL_REPLACE_THE_DEFAULT_CONTROL_FOR]"); for (auto& [configVars, actionName] : getActionBinds() | std::views::values) { addActionBinding(&configVars->at(port), actionName); } @@ -945,16 +947,13 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { u32 buttonCount = 0; PADButtonMapping* mappings = PADGetButtonMappings(port, &buttonCount); if (mappings == nullptr) { - pane.add_text("No Device Selected"); + pane.add_text("[NO_CONTROLLER_SELECTED]"); break; } SDL_Gamepad* gamepad = gamepad_for_port(port); - pane.add_section("Custom Action Bindings"); - pane.add_text("A button bound to any action here will REPLACE the default control for" - " that action. Only bind buttons here that aren't used anywhere else. The glyphs" - " shown for in game actions will not change. This is not recommended for " - " regular Gamecube controllers."); + pane.add_section("[CUSTOM_ACTION_BINDINGS]"); + pane.add_text("[A_BUTTON_BOUND_TO_ANY_ACTION_HERE_WILL_REPLACE_THE_DEFAULT_CONTROL_FOR]"); auto addActionBinding = [&](auto actionBind, const std::string& key) { pane.add_select_button({ .key = key, @@ -1145,11 +1144,11 @@ bool ControllerConfigWindow::pending_input_neutral() const { } Rml::String ControllerConfigWindow::pending_button_label() const { - return mPendingBindingArmed ? "Press a Key or Button..." : "Waiting..."; + return mPendingBindingArmed ? "[PRESS_A_BUTTON]" : "[WAITING]"; } Rml::String ControllerConfigWindow::pending_axis_label() const { - return mPendingBindingArmed ? "Move Axis or press a Key or Button..." : "Waiting..."; + return mPendingBindingArmed ? "[MOVE_AXIS_OR_PRESS_A_BUTTON]" : "[WAITING]"; } void ControllerConfigWindow::cancel_pending_binding() { @@ -1178,7 +1177,7 @@ void ControllerConfigWindow::finish_pending_key_binding() { } Rml::String ControllerConfigWindow::pending_key_label() const { - return mPendingBindingArmed ? "Press a Key or Mouse Button..." : "Waiting..."; + return mPendingBindingArmed ? "[PRESS_A_KEY_OR_MOUSE_BUTTON]" : "[WAITING]"; } void ControllerConfigWindow::stop_rumble_test() { @@ -1194,7 +1193,7 @@ void ControllerConfigWindow::stop_rumble_test() { Rml::String native_button_name(SDL_Gamepad* gamepad, u32 buttonUntyped) { if (buttonUntyped == PAD_NATIVE_BUTTON_INVALID) { - return "Not Bound"; + return "[NOT_BOUND]"; } auto button = static_cast(buttonUntyped); @@ -1251,7 +1250,7 @@ Rml::String native_button_name(SDL_Gamepad* gamepad, u32 buttonUntyped) { if (const char* name = PADGetNativeButtonName(buttonUntyped)) { return name; } - return "Unknown"; + return "[UNKNOWN]"; } } // namespace dusk::ui diff --git a/src/dusk/ui/graphics_tuner.cpp b/src/dusk/ui/graphics_tuner.cpp index 0b75b27a89..76e5d0bfce 100644 --- a/src/dusk/ui/graphics_tuner.cpp +++ b/src/dusk/ui/graphics_tuner.cpp @@ -189,7 +189,7 @@ Rml::String format_graphics_setting_value(GraphicsOption option, int value) { u32 height = 0; AuroraGetRenderSize(&width, &height); if (value <= 0) { - return fmt::format("Auto ({}×{})", width, height); + return fmt::format("[AUTO] ({}×{})", width, height); } else { return fmt::format("{}× ({}×{})", value, width, height); } @@ -207,11 +207,11 @@ Rml::String format_graphics_setting_value(GraphicsOption option, int value) { case GraphicsOption::BloomMode: switch (static_cast(value)) { case BloomMode::Off: - return "Off"; + return "[OFF]"; case BloomMode::Classic: - return "Classic"; + return "[CLASSIC]"; case BloomMode::Dusk: - return "Dusklight"; + return "[DUSK]"; } break; case GraphicsOption::BloomMultiplier: @@ -247,11 +247,11 @@ GraphicsTuner::GraphicsTuner(GraphicsTunerProps props, bool prelaunch) } if (auto* footer = mDocument->GetElementById("footer")) { - auto& returnButton = add_component