From b81175a34eed0b0a5901cf0e9cdae58b1d7d5b24 Mon Sep 17 00:00:00 2001 From: Christopher Lees Date: Thu, 18 Jan 2024 19:25:57 +0000 Subject: [PATCH] WIP language selection --- source/OpenBVE/Game/Menu/Menu.MenuCaption.cs | 11 ++- source/OpenBVE/Game/Menu/Menu.MenuCommand.cs | 14 ++- source/OpenBVE/Game/Menu/Menu.MenuEntry.cs | 14 ++- source/OpenBVE/Game/Menu/Menu.SingleMenu.cs | 92 ++++++++++--------- source/OpenBVE/Game/Menu/Menu.cs | 9 ++ source/OpenBVE/Game/Menu/MenuTag.cs | 6 +- source/OpenBVE/Game/Menu/MenuType.cs | 4 +- .../Interface/Translations/LanguageFile.cs | 3 +- 8 files changed, 106 insertions(+), 47 deletions(-) diff --git a/source/OpenBVE/Game/Menu/Menu.MenuCaption.cs b/source/OpenBVE/Game/Menu/Menu.MenuCaption.cs index ed513eec6c..92a6e03d3a 100644 --- a/source/OpenBVE/Game/Menu/Menu.MenuCaption.cs +++ b/source/OpenBVE/Game/Menu/Menu.MenuCaption.cs @@ -1,10 +1,19 @@ -namespace OpenBve +using OpenBveApi.Hosts; +using OpenBveApi.Interface; + +namespace OpenBve { public sealed partial class Menu { /// A caption to be rendered at the top of the menu private class MenuCaption : MenuEntry { + internal MenuCaption(string[] translationPath) + { + this.TranslationPath = translationPath; + languageCode = Interface.CurrentOptions.LanguageCode; + this.Text = Translations.GetInterfaceString(HostApplication.OpenBve, translationPath); + } internal MenuCaption(string Text) { this.Text = Text; diff --git a/source/OpenBVE/Game/Menu/Menu.MenuCommand.cs b/source/OpenBVE/Game/Menu/Menu.MenuCommand.cs index 9df4850889..65d5f34905 100644 --- a/source/OpenBVE/Game/Menu/Menu.MenuCommand.cs +++ b/source/OpenBVE/Game/Menu/Menu.MenuCommand.cs @@ -1,4 +1,6 @@ -using OpenBveApi.Textures; +using OpenBveApi.Hosts; +using OpenBveApi.Interface; +using OpenBveApi.Textures; namespace OpenBve { @@ -12,6 +14,16 @@ private class MenuCommand : MenuEntry /// The optional data to be passed with the command internal readonly object Data; + internal MenuCommand(string[] translationPath, MenuTag Tag, object Data) + { + TranslationPath = translationPath; + Text = Translations.GetInterfaceString(HostApplication.OpenBve, translationPath); + languageCode = Interface.CurrentOptions.LanguageCode; + this.Tag = Tag; + this.Data = Data; + this.Icon = null; + } + internal MenuCommand(string Text, MenuTag Tag, object Data) { this.Text = Text; diff --git a/source/OpenBVE/Game/Menu/Menu.MenuEntry.cs b/source/OpenBVE/Game/Menu/Menu.MenuEntry.cs index f250e14cfe..7954481ba7 100644 --- a/source/OpenBVE/Game/Menu/Menu.MenuEntry.cs +++ b/source/OpenBVE/Game/Menu/Menu.MenuEntry.cs @@ -1,4 +1,6 @@ -using OpenBveApi.Textures; +using OpenBveApi.Hosts; +using OpenBveApi.Interface; +using OpenBveApi.Textures; namespace OpenBve { @@ -7,11 +9,21 @@ public sealed partial class Menu /// The base abstract Menu Entry class private abstract class MenuEntry { + /// The translation path + internal string[] TranslationPath; /// The base text of the menu entry internal string Text; + /// The language code for the cached string + internal string languageCode; /// The display text of the menu entry internal string DisplayText(double TimeElapsed) { + if (TranslationPath != null && Interface.CurrentOptions.LanguageCode != languageCode) + { + // user has changed the in-game language, so we'll need to update our cached string + Text = Translations.GetInterfaceString(HostApplication.OpenBve, TranslationPath); + languageCode = Interface.CurrentOptions.LanguageCode; + } if (DisplayLength == 0) { return Text; diff --git a/source/OpenBVE/Game/Menu/Menu.SingleMenu.cs b/source/OpenBVE/Game/Menu/Menu.SingleMenu.cs index 8f334afd5e..2c317af532 100644 --- a/source/OpenBVE/Game/Menu/Menu.SingleMenu.cs +++ b/source/OpenBVE/Game/Menu/Menu.SingleMenu.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Drawing; using System.IO; +using System.Linq; using DavyKager; using OpenBveApi.Graphics; using OpenBveApi.Hosts; @@ -95,10 +96,10 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) if (!Interface.CurrentOptions.KioskMode) { //Don't allow quitting or customisation of the controls in kiosk mode - Items[1] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","title"}), MenuTag.Options, 0); - Items[2] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","customize_controls"}), MenuTag.MenuControls, 0); - Items[3] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","title"}), MenuTag.Packages, 0); - Items[4] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","quit"}), MenuTag.MenuQuit, 0); + Items[1] = new MenuCommand(new[] {"options","title"}, MenuTag.Options, 0); + Items[2] = new MenuCommand(new[] {"menu","customize_controls"}, MenuTag.MenuControls, 0); + Items[3] = new MenuCommand(new[] {"packages","title"}, MenuTag.Packages, 0); + Items[4] = new MenuCommand(new[] {"menu","quit"}, MenuTag.MenuQuit, 0); } else { @@ -109,25 +110,25 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) break; case MenuType.Packages: Items = new MenuEntry[4]; - Items[0] = new MenuCaption(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","title"})); - Items[1] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","install_header"}), MenuTag.PackageInstall, 0); - Items[2] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","uninstall_button"}), MenuTag.PackageUninstall, 0); - Items[3] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","button_cancel"}), MenuTag.MenuBack, 0); + Items[0] = new MenuCaption(new[] {"packages","title"}); + Items[1] = new MenuCommand(new[] {"packages","install_header"}, MenuTag.PackageInstall, 0); + Items[2] = new MenuCommand(new[] {"packages","uninstall_button"}, MenuTag.PackageUninstall, 0); + Items[3] = new MenuCommand(new[] {"packages","button_cancel"}, MenuTag.MenuBack, 0); Align = TextAlignment.TopLeft; break; case MenuType.PackageUninstall: routeDescriptionBox.Text = string.Empty; Items = new MenuEntry[5]; - Items[0] = new MenuCaption(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","list_type"})); - Items[1] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","type_route"}), MenuTag.UninstallRoute, 0); - Items[2] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","type_train"}), MenuTag.UninstallTrain, 0); - Items[3] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","type_other"}), MenuTag.UninstallOther, 0); - Items[4] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","button_cancel"}), MenuTag.MenuBack, 0); + Items[0] = new MenuCaption(new[] {"packages","list_type"}); + Items[1] = new MenuCommand(new[] {"packages","type_route"}, MenuTag.UninstallRoute, 0); + Items[2] = new MenuCommand(new[] {"packages","type_train"}, MenuTag.UninstallTrain, 0); + Items[3] = new MenuCommand(new[] {"packages","type_other"}, MenuTag.UninstallOther, 0); + Items[4] = new MenuCommand(new[] {"packages","button_cancel"}, MenuTag.MenuBack, 0); Align = TextAlignment.TopLeft; break; case MenuType.UninstallRoute: Items = new MenuEntry[Database.currentDatabase.InstalledRoutes.Count + 1]; - Items[0] = new MenuCaption(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","list"})); + Items[0] = new MenuCaption(new[] {"packages","list"}); for (int j = 0; j < Database.currentDatabase.InstalledRoutes.Count; j++) { Items[j + 1] = new MenuCommand(Database.currentDatabase.InstalledRoutes[j].Name, MenuTag.Package, Database.currentDatabase.InstalledRoutes[j]); @@ -136,7 +137,7 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) break; case MenuType.UninstallTrain: Items = new MenuEntry[Database.currentDatabase.InstalledTrains.Count + 1]; - Items[0] = new MenuCaption(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","list"})); + Items[0] = new MenuCaption(new[] {"packages","list"}); for (int j = 0; j < Database.currentDatabase.InstalledTrains.Count; j++) { Items[j + 1] = new MenuCommand(Database.currentDatabase.InstalledTrains[j].Name, MenuTag.Package, Database.currentDatabase.InstalledTrains[j]); @@ -145,7 +146,7 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) break; case MenuType.UninstallOther: Items = new MenuEntry[Database.currentDatabase.InstalledOther.Count + 1]; - Items[0] = new MenuCaption(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"packages","list"})); + Items[0] = new MenuCaption(new[] {"packages","list"}); for (int j = 0; j < Database.currentDatabase.InstalledOther.Count; j++) { Items[j + 1] = new MenuCommand(Database.currentDatabase.InstalledOther[j].Name, MenuTag.Package, Database.currentDatabase.InstalledOther[j]); @@ -242,8 +243,8 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) Align = TextAlignment.TopLeft; break; case MenuType.Options: - Items = new MenuEntry[8]; - Items[0] = new MenuCaption(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"panel","options"})); + Items = new MenuEntry[9]; + Items[0] = new MenuCaption( new[] {"panel","options"}); Items[1] = new MenuOption(MenuOptionType.ScreenResolution, Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","resolution"}), Program.Renderer.Screen.AvailableResolutions.ToArray()); Items[2] = new MenuOption(MenuOptionType.FullScreen, Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","display_mode_fullscreen"}), new[] { "true", "false" }); Items[3] = new MenuOption(MenuOptionType.Interpolation, Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","quality_interpolation"}), new[] @@ -258,7 +259,8 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) Items[4] = new MenuOption(MenuOptionType.AnisotropicLevel, Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","quality_interpolation_anisotropic_level"}), new[] { "0", "2", "4", "8", "16" }); Items[5] = new MenuOption(MenuOptionType.AntialiasingLevel, Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","quality_interpolation_antialiasing_level"}), new[] { "0", "2", "4", "8", "16" }); Items[6] = new MenuOption(MenuOptionType.ViewingDistance, Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","quality_distance_viewingdistance"}), new[] { "400", "600", "800", "1000", "1500", "2000" }); - Items[7] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","back"}), MenuTag.MenuBack, 0); + Items[7] = new MenuCommand("Language", MenuTag.LanguageList, 0); + Items[8] = new MenuCommand(new[] {"menu","back"}, MenuTag.MenuBack, 0); Align = TextAlignment.TopLeft; break; case MenuType.RouteList: @@ -414,15 +416,15 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) break; } Items = new MenuEntry[4 + jump]; - Items[0] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","resume"}), MenuTag.BackToSim, 0); + Items[0] = new MenuCommand(new[] {"menu","resume"}, MenuTag.BackToSim, 0); if (jump > 0) - Items[1] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","jump"}), MenuTag.MenuJumpToStation, 0); + Items[1] = new MenuCommand(new[] {"menu","jump"}, MenuTag.MenuJumpToStation, 0); if (!Interface.CurrentOptions.KioskMode) { //Don't allow quitting or customisation of the controls in kiosk mode - Items[1 + jump] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","exit"}), MenuTag.MenuExitToMainMenu, 0); - Items[2 + jump] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","customize_controls"}), MenuTag.MenuControls, 0); - Items[3 + jump] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","quit"}), MenuTag.MenuQuit, 0); + Items[1 + jump] = new MenuCommand(new[] {"menu","exit"}, MenuTag.MenuExitToMainMenu, 0); + Items[2 + jump] = new MenuCommand(new[] {"menu","customize_controls"}, MenuTag.MenuControls, 0); + Items[3 + jump] = new MenuCommand(new[] {"menu","quit"}, MenuTag.MenuQuit, 0); } else { @@ -438,7 +440,7 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) // list available stations, selecting the next station as predefined choice jump = 0; // no jump found yet Items = new MenuEntry[menuItem + 1]; - Items[0] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","back"}), MenuTag.MenuBack, 0); + Items[0] = new MenuCommand(new[] {"menu","back"}, MenuTag.MenuBack, 0); menuItem = 1; for (i = 0; i < Program.CurrentRoute.Stations.Length; i++) if (Program.CurrentRoute.Stations[i].PlayerStops() & Program.CurrentRoute.Stations[i].Stops.Length > 0) @@ -457,17 +459,17 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) case MenuType.ExitToMainMenu: Items = new MenuEntry[3]; - Items[0] = new MenuCaption(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","exit_question"})); - Items[1] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","exit_no"}), MenuTag.MenuBack, 0); - Items[2] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","exit_yes"}), MenuTag.ExitToMainMenu, 0); + Items[0] = new MenuCaption(new[] {"menu","exit_question"}); + Items[1] = new MenuCommand(new[] {"menu","exit_no"}, MenuTag.MenuBack, 0); + Items[2] = new MenuCommand(new[] {"menu","exit_yes"}, MenuTag.ExitToMainMenu, 0); Selection = 1; break; case MenuType.Quit: // ask for quit confirmation Items = new MenuEntry[3]; - Items[0] = new MenuCaption(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","quit_question"})); - Items[1] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","quit_no"}), MenuTag.MenuBack, 0); - Items[2] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","quit_yes"}), MenuTag.Quit, 0); + Items[0] = new MenuCaption(new[] {"menu","quit_question"}); + Items[1] = new MenuCommand(new[] {"menu","quit_no"}, MenuTag.MenuBack, 0); + Items[2] = new MenuCommand(new[] {"menu","quit_yes"}, MenuTag.Quit, 0); Selection = 1; break; @@ -475,8 +477,8 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) //Refresh the joystick list Program.Joysticks.RefreshJoysticks(); Items = new MenuEntry[Interface.CurrentControls.Length + 2]; - Items[0] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","back"}), MenuTag.MenuBack, 0); - Items[1] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","reset"}), MenuTag.ControlReset, 0); + Items[0] = new MenuCommand(new[] {"menu","back"}, MenuTag.MenuBack, 0); + Items[1] = new MenuCommand(new[] {"menu","reset"}, MenuTag.ControlReset, 0); int ci = 2; for (i = 0; i < Interface.CurrentControls.Length; i++) { @@ -490,7 +492,6 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) // method pictures mean we need top left at all times Align = TextAlignment.TopLeft; break; - case MenuType.Control: //Refresh the joystick list Program.Joysticks.RefreshJoysticks(); @@ -504,13 +505,13 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) string str = GetControlDescription(data); Items[1] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","assignment_current"}) + " " + str, MenuTag.None, 0); Items[2] = new MenuCommand(" ", MenuTag.None, 0); - Items[3] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","assign"}), MenuTag.None, 0); + Items[3] = new MenuCommand(new[] {"menu","assign"}, MenuTag.None, 0); break; case MenuType.ControlReset: Items = new MenuEntry[3]; - Items[0] = new MenuCaption(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","reset_question"})); - Items[1] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","train_default_yes"}), MenuTag.Yes, 0); - Items[2] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","train_default_no"}), MenuTag.No, 0); + Items[0] = new MenuCaption(new[] {"menu","reset_question"}); + Items[1] = new MenuCommand(new[] {"menu","train_default_yes"}, MenuTag.Yes, 0); + Items[2] = new MenuCommand(new[] {"menu","train_default_no"}, MenuTag.No, 0); Selection = 1; break; case MenuType.TrainDefault: @@ -528,9 +529,9 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) if (canLoad) { Items = new MenuEntry[3]; - Items[0] = new MenuCaption(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","train_default"})); - Items[1] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","train_default_yes"}), MenuTag.Yes, 0); - Items[2] = new MenuCommand(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"menu","train_default_no"}), MenuTag.No, 0); + Items[0] = new MenuCaption(new[] {"menu","train_default"}); + Items[1] = new MenuCommand(new[] {"menu","train_default_yes"}, MenuTag.Yes, 0); + Items[2] = new MenuCommand(new[] {"menu","train_default_no"}, MenuTag.No, 0); Selection = 1; } else @@ -540,6 +541,15 @@ public SingleMenu(MenuType menuType, int data = 0, double MaxWidth = 0) Instance.PushMenu(MenuType.TrainList); } break; + case MenuType.LanguageList: + Items = new MenuEntry[Translations.AvailableNewLanguages.Count + 1]; + Items[0] = new MenuCaption("Select Language:"); + for (int j = 1; j < Translations.AvailableNewLanguages.Count; j++) + { + string key = Translations.AvailableNewLanguages.ElementAt(j).Key; + Items[j] = new MenuCommand(Translations.AvailableNewLanguages[key].ToString(), MenuTag.LanguageSelect, key); + } + break; } // compute menu extent for (i = 0; i < Items.Length; i++) diff --git a/source/OpenBVE/Game/Menu/Menu.cs b/source/OpenBVE/Game/Menu/Menu.cs index 1b179778dd..dfd1495d39 100644 --- a/source/OpenBVE/Game/Menu/Menu.cs +++ b/source/OpenBVE/Game/Menu/Menu.cs @@ -645,6 +645,15 @@ internal void ProcessCommand(Translations.Command cmd, double timeElapsed) case MenuTag.Options: Menu.instance.PushMenu(MenuType.Options); break; + case MenuTag.LanguageList: + Menu.Instance.PushMenu(MenuType.LanguageList); + break; + case MenuTag.LanguageSelect: + MenuCommand c = menu.Items[menu.Selection] as MenuCommand; + Interface.CurrentOptions.LanguageCode = (string)c.Data; + Translations.CurrentLanguageCode = (string)c.Data; + Menu.Instance.PopMenu(); + break; case MenuTag.RouteList: // TO ROUTE LIST MENU Menu.instance.PushMenu(MenuType.RouteList); routeDescriptionBox.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"errors","route_please_select"}); diff --git a/source/OpenBVE/Game/Menu/MenuTag.cs b/source/OpenBVE/Game/Menu/MenuTag.cs index c7c85325ef..39d8453c77 100644 --- a/source/OpenBVE/Game/Menu/MenuTag.cs +++ b/source/OpenBVE/Game/Menu/MenuTag.cs @@ -63,6 +63,10 @@ public enum MenuTag /// Uninstalls anything else UninstallOther, /// Shows the options menu - Options + Options, + /// Shows the language list menu + LanguageList, + /// Selects a language + LanguageSelect } } diff --git a/source/OpenBVE/Game/Menu/MenuType.cs b/source/OpenBVE/Game/Menu/MenuType.cs index 4f8c64bda7..a153a9d9e3 100644 --- a/source/OpenBVE/Game/Menu/MenuType.cs +++ b/source/OpenBVE/Game/Menu/MenuType.cs @@ -40,7 +40,9 @@ public enum MenuType /// Uninstalls anything else UninstallOther, /// The options menu - Options + Options, + /// A selectable list of languages + LanguageList } } diff --git a/source/OpenBveApi/Interface/Translations/LanguageFile.cs b/source/OpenBveApi/Interface/Translations/LanguageFile.cs index 35998c6205..0418e3def5 100644 --- a/source/OpenBveApi/Interface/Translations/LanguageFile.cs +++ b/source/OpenBveApi/Interface/Translations/LanguageFile.cs @@ -134,7 +134,8 @@ public static bool SelectedLanguage(ref string CurrentLanguageCodeArgument, Comb return true; } - internal static readonly Dictionary AvailableNewLanguages = new Dictionary(); + /// The list of available languages + public static readonly Dictionary AvailableNewLanguages = new Dictionary(); }