diff --git a/OWML.sln b/OWML.sln index 9e523705..558f2bd0 100644 --- a/OWML.sln +++ b/OWML.sln @@ -62,6 +62,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OWML.ExampleAPI", "src\Samp EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C7F76E72-1CF2-4C0D-8A39-3D13EB868119}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig LICENSE = LICENSE .github\workflows\main.yml = .github\workflows\main.yml owmllogo.png = owmllogo.png @@ -209,7 +210,7 @@ Global {739D16FB-7848-4047-A173-500CE7C40399} = {C447A599-2700-44E1-BBFA-52880B7BFFBA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.2\lib\NET35;packages\Unity.2.1.505.0\lib\NET35 SolutionGuid = {0E767163-75F9-420A-80EB-320429543CAD} + EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.2\lib\NET35;packages\Unity.2.1.505.0\lib\NET35 EndGlobalSection EndGlobal diff --git a/src/OWML.Common/Interfaces/IModHelper.cs b/src/OWML.Common/Interfaces/IModHelper.cs index 69897b66..41b1ca80 100644 --- a/src/OWML.Common/Interfaces/IModHelper.cs +++ b/src/OWML.Common/Interfaces/IModHelper.cs @@ -1,4 +1,5 @@ -using OWML.Common.Menus; +using OWML.Common.Interfaces; +using OWML.Common.Menus; using System; namespace OWML.Common @@ -31,5 +32,7 @@ public interface IModHelper IModInteraction Interaction { get; } IMenuManager MenuHelper { get; } + + IModTranslations MenuTranslations { get; } } } diff --git a/src/OWML.Common/Interfaces/IModTranslations.cs b/src/OWML.Common/Interfaces/IModTranslations.cs new file mode 100644 index 00000000..2dd5b3ad --- /dev/null +++ b/src/OWML.Common/Interfaces/IModTranslations.cs @@ -0,0 +1,7 @@ +namespace OWML.Common.Interfaces +{ + public interface IModTranslations + { + public string GetLocalizedString(string key); + } +} diff --git a/src/OWML.ModHelper.Menus/ModConfigMenuBase.cs b/src/OWML.ModHelper.Menus/ModConfigMenuBase.cs index ce39fbcf..33182cbf 100644 --- a/src/OWML.ModHelper.Menus/ModConfigMenuBase.cs +++ b/src/OWML.ModHelper.Menus/ModConfigMenuBase.cs @@ -3,6 +3,7 @@ using OWML.Common; using OWML.Common.Menus; using OWML.Utils; +using OWML.Common.Interfaces; namespace OWML.ModHelper.Menus { @@ -19,6 +20,8 @@ public abstract class ModConfigMenuBase : ModMenuWithSelectables, IModConfigMenu private IModNumberInput _numberInputTemplate; private IModSeparator _seperatorTemplate; + private IModTranslations _translations; + protected abstract void AddInputs(); public abstract void UpdateUIValues(); @@ -28,6 +31,8 @@ protected ModConfigMenuBase(IModManifest manifest, IModStorage storage, IModCons { Manifest = manifest; Storage = storage; + + _translations = new ModTranslations(manifest, console); } public void Initialize(Menu menu, IModToggleInput toggleTemplate, IModSliderInput sliderTemplate, @@ -111,7 +116,7 @@ private void AddToggleInput(string key, int index, JObject obj = null) { var toggle = AddToggleInput(_toggleTemplate.Copy(key), index); toggle.Element.name = key; - toggle.Title = (string)obj?["title"] ?? key; + SetupTitle(toggle, (string)obj?["title"], key); SetupInputTooltip(toggle, (string)obj?["tooltip"]); toggle.Show(); } @@ -122,7 +127,7 @@ private void AddSliderInput(string key, int index, JObject obj) slider.Min = (float)obj["min"]; slider.Max = (float)obj["max"]; slider.Element.name = key; - slider.Title = (string)obj["title"] ?? key; + SetupTitle(slider, (string)obj?["title"], key); SetupInputTooltip(slider, (string)obj["tooltip"]); slider.Show(); } @@ -132,7 +137,7 @@ private void AddSelectorInput(string key, int index, JObject obj) var options = obj["options"].ToObject(); var selector = AddSelectorInput(_selectorTemplate.Copy(key), index); selector.Element.name = key; - selector.Title = (string)obj["title"] ?? key; + SetupTitle(selector, (string)obj?["title"], key); selector.Initialize((string)obj["value"], options); SetupInputTooltip(selector, (string)obj["tooltip"]); selector.Show(); @@ -142,7 +147,7 @@ private void AddTextInput(string key, int index, JObject obj = null) { var textInput = AddTextInput(_textInputTemplate.Copy(key), index); textInput.Element.name = key; - textInput.Title = (string)obj?["title"] ?? key; + SetupTitle(textInput, (string)obj?["title"], key); SetupInputTooltip(textInput, (string)obj?["tooltip"]); textInput.Show(); } @@ -151,7 +156,7 @@ private void AddNumberInput(string key, int index, JObject obj = null) { var numberInput = AddNumberInput(_numberInputTemplate.Copy(key), index); numberInput.Element.name = key; - numberInput.Title = (string)obj?["title"] ?? key; + SetupTitle(numberInput, (string)obj?["title"], key); SetupInputTooltip(numberInput, (string)obj?["tooltip"]); numberInput.Show(); } @@ -160,7 +165,7 @@ private void AddSeparator(string key, int index, JObject obj) { var separator = AddSeparator(_seperatorTemplate.Copy("Inputs"), index); separator.Element.name = key; - separator.Title = (string)obj?["title"] ?? key; + SetupTitle(separator, (string)obj?["title"], key); separator.Show(); } @@ -168,7 +173,12 @@ internal void SetupInputTooltip(IModInput input, string tooltip) { var menuOption = input.Element.GetComponent(); menuOption.SetValue("_tooltipTextType", UITextType.None); - menuOption.SetValue("_overrideTooltipText", tooltip?? ""); + menuOption.SetValue("_overrideTooltipText", _translations.GetLocalizedString(tooltip) ?? ""); + } + + internal void SetupTitle(IModInputBase input, string title, string key) + { + input.Title = title == null ? key : _translations.GetLocalizedString(title); } } } diff --git a/src/OWML.ModHelper.Menus/ModTranslations.cs b/src/OWML.ModHelper.Menus/ModTranslations.cs new file mode 100644 index 00000000..3ef496e2 --- /dev/null +++ b/src/OWML.ModHelper.Menus/ModTranslations.cs @@ -0,0 +1,94 @@ +using Newtonsoft.Json.Linq; +using OWML.Common; +using OWML.Common.Interfaces; +using System; +using System.Collections.Generic; +using System.IO; + +namespace OWML.ModHelper.Menus +{ + public class ModTranslations : IModTranslations + { + private Dictionary> _translationTable = new(); + + private IModManifest _manifest; + private IModConsole _console; + + // Menu translations are stored under UIDictionary + // This means OWML config translations follow the New Horizons format + public static readonly string UIDictionary = nameof(UIDictionary); + + private bool _initialized; + + public ModTranslations(IModManifest manifest, IModConsole console) + { + _manifest = manifest; + _console = console; + } + + private void Init() + { + try + { + var translationsFolder = Path.Combine(_manifest.ModFolderPath, "translations"); + foreach (TextTranslation.Language translation in Enum.GetValues(typeof(TextTranslation.Language))) + { + var filename = Path.Combine(translationsFolder, $"{translation}.json"); + if (File.Exists(filename)) + { + var dict = JObject.Parse(File.ReadAllText(filename)).ToObject>(); + if (dict.ContainsKey(UIDictionary)) + { + _translationTable[translation] = (Dictionary)(dict[nameof(UIDictionary)] as JObject).ToObject(typeof(Dictionary)); + } + } + } + _initialized = true; + } + catch (Exception ex) + { + _console.WriteLine(ex.ToString(), MessageType.Error); + } + } + + public string GetLocalizedString(string key) + { + if (!_initialized) + { + Init(); + } + + _console.WriteLine($"{_translationTable == null} {string.Join(", ", _translationTable.Keys)}", MessageType.Error); + + try + { + if (key == null) return null; + if (key == string.Empty) return string.Empty; + + if (!_translationTable.TryGetValue(TextTranslation.Get().m_language, out var dict)) + { + // Default to English + if (!_translationTable.TryGetValue(TextTranslation.Language.ENGLISH, out dict)) + { + // Default to key + return key; + } + } + + if (dict.TryGetValue(key, out var value)) + { + return value; + } + else + { + return key; + } + } + catch (Exception ex) + { + _console.WriteLine(ex.ToString(), MessageType.Error); + return key; + } + } + } +} diff --git a/src/OWML.ModHelper.Menus/NewMenuSystem/MenuManager.cs b/src/OWML.ModHelper.Menus/NewMenuSystem/MenuManager.cs index f16142ff..b07ec4da 100644 --- a/src/OWML.ModHelper.Menus/NewMenuSystem/MenuManager.cs +++ b/src/OWML.ModHelper.Menus/NewMenuSystem/MenuManager.cs @@ -225,12 +225,12 @@ void SaveConfig() { if (settingObject["title"] != null) { - label = settingObject["title"].ToString(); + label = mod.ModHelper.MenuTranslations.GetLocalizedString(settingObject["title"].ToString()); } if (settingObject["tooltip"] != null) { - tooltip = settingObject["tooltip"].ToString(); + tooltip = mod.ModHelper.MenuTranslations.GetLocalizedString(settingObject["tooltip"].ToString()); } } diff --git a/src/OWML.ModHelper/ModHelper.cs b/src/OWML.ModHelper/ModHelper.cs index 602118a6..1b205e01 100644 --- a/src/OWML.ModHelper/ModHelper.cs +++ b/src/OWML.ModHelper/ModHelper.cs @@ -1,4 +1,5 @@ using OWML.Common; +using OWML.Common.Interfaces; using OWML.Common.Menus; namespace OWML.ModHelper @@ -31,6 +32,8 @@ public class ModHelper : IModHelper public IMenuManager MenuHelper { get; } + public IModTranslations MenuTranslations { get; } + public ModHelper( IModLogger logger, IModConsole console, @@ -44,7 +47,8 @@ public ModHelper( IModDefaultConfig defaultConfig, IOwmlConfig owmlConfig, IModInteraction interaction, - IMenuManager menuHelper) + IMenuManager menuHelper, + IModTranslations menuTranslations) { Logger = logger; Console = console; @@ -59,6 +63,7 @@ public ModHelper( OwmlConfig = owmlConfig; Interaction = interaction; MenuHelper = menuHelper; + MenuTranslations = menuTranslations; } } } diff --git a/src/OWML.ModLoader/Owo.cs b/src/OWML.ModLoader/Owo.cs index 1f0793c4..fb50b22e 100644 --- a/src/OWML.ModLoader/Owo.cs +++ b/src/OWML.ModLoader/Owo.cs @@ -11,6 +11,7 @@ using OWML.ModHelper.Events; using OWML.ModHelper.Input; using OWML.ModHelper.Interaction; +using OWML.ModHelper.Menus; using OWML.Utils; using System; using System.Collections.Generic; @@ -245,6 +246,7 @@ private IModHelper CreateModHelper(IModData modData) => .Add() .Add() .Add() + .Add() .Add() .Resolve();