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();
}