Skip to content

Commit

Permalink
Merge pull request #579 from ow-mods/translations
Browse files Browse the repository at this point in the history
Implement translation support for config options
  • Loading branch information
xen-42 authored Apr 18, 2024
2 parents f414bdd + fcb8574 commit a85aa7e
Show file tree
Hide file tree
Showing 12 changed files with 233 additions and 13 deletions.
72 changes: 72 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@

[*.{cs,vb}]
#### Naming styles ####

# Naming rules

dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i

dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case

dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case

# Symbol specifications

dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =

dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =

dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =

# Naming styles

dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case

dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case

dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
indent_size = 4
end_of_line = crlf
dotnet_style_null_propagation = true:suggestion
indent_style = tab

[*.cs]
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_indent_labels = one_less_than_current
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
"everytime",
"overridable",
"Untarget"
],
"githubPullRequests.ignoredPullRequestBranches": [
"master"
]
}
3 changes: 2 additions & 1 deletion OWML.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
4 changes: 4 additions & 0 deletions schemas/manifest_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"dependencies": {
"type": "array",
"description": "The dependencies of the mod",
"default": [],
"items": {
"type": "string",
"description": "The uniqueName of the dependency",
Expand All @@ -91,6 +92,7 @@
"minGameVersion": {
"type": "string",
"description": "The minimum version of the game that this mod is compatible with",
"default": "",
"pattern": "^\\d+\\.\\d+\\.\\d+\\.\\d+$",
"examples": [
"1.0.0",
Expand All @@ -101,6 +103,7 @@
"maxGameVersion": {
"type": "string",
"description": "The maximum version of the game that this mod is compatible with",
"default": "",
"pattern": "^\\d+\\.\\d+\\.\\d+\\.\\d+$",
"examples": [
"1.0.0",
Expand All @@ -116,6 +119,7 @@
"incompatibleVendors": {
"type": "array",
"description": "The vendors this mod does not work on",
"default": [],
"items": {
"type": "string",
"enum": [
Expand Down
5 changes: 4 additions & 1 deletion src/OWML.Common/Interfaces/IModHelper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OWML.Common.Menus;
using OWML.Common.Interfaces;
using OWML.Common.Menus;
using System;

namespace OWML.Common
Expand Down Expand Up @@ -31,5 +32,7 @@ public interface IModHelper
IModInteraction Interaction { get; }

IMenuManager MenuHelper { get; }

IModTranslations MenuTranslations { get; }
}
}
7 changes: 7 additions & 0 deletions src/OWML.Common/Interfaces/IModTranslations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace OWML.Common.Interfaces
{
public interface IModTranslations
{
public string GetLocalizedString(string key);
}
}
24 changes: 17 additions & 7 deletions src/OWML.ModHelper.Menus/ModConfigMenuBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using OWML.Common;
using OWML.Common.Menus;
using OWML.Utils;
using OWML.Common.Interfaces;

namespace OWML.ModHelper.Menus
{
Expand All @@ -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();
Expand All @@ -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,
Expand Down Expand Up @@ -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();
}
Expand All @@ -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();
}
Expand All @@ -132,7 +137,7 @@ private void AddSelectorInput(string key, int index, JObject obj)
var options = obj["options"].ToObject<string[]>();
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();
Expand All @@ -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();
}
Expand All @@ -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();
}
Expand All @@ -160,15 +165,20 @@ 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();
}

internal void SetupInputTooltip<T>(IModInput<T> input, string tooltip)
{
var menuOption = input.Element.GetComponent<MenuOption>();
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);
}
}
}
92 changes: 92 additions & 0 deletions src/OWML.ModHelper.Menus/ModTranslations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
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<TextTranslation.Language, Dictionary<string, string>> _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<Dictionary<string, object>>();
if (dict.ContainsKey(UIDictionary))
{
_translationTable[translation] = (Dictionary<string, string>)(dict[nameof(UIDictionary)] as JObject).ToObject(typeof(Dictionary<string, string>));
}
}
}
_initialized = true;
}
catch (Exception ex)
{
_console.WriteLine($"Failed to initialize mod option translations {ex}", MessageType.Error);
}
}

public string GetLocalizedString(string key)
{
if (!_initialized)
{
Init();
}

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($"Failed to load options translation: {ex}", MessageType.Error);
return key;
}
}
}
}
6 changes: 3 additions & 3 deletions src/OWML.ModHelper.Menus/NewMenuSystem/MenuManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ void SaveConfig()
foreach (var (name, setting) in mod.ModHelper.Config.Settings)
{
var settingType = GetSettingType(setting);
var label = name;
var label = mod.ModHelper.MenuTranslations.GetLocalizedString(name);
var tooltip = "";

var settingObject = setting as JObject;
Expand All @@ -233,12 +233,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());
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/OWML.ModHelper/ModHelper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OWML.Common;
using OWML.Common.Interfaces;
using OWML.Common.Menus;

namespace OWML.ModHelper
Expand Down Expand Up @@ -31,6 +32,8 @@ public class ModHelper : IModHelper

public IMenuManager MenuHelper { get; }

public IModTranslations MenuTranslations { get; }

public ModHelper(
IModLogger logger,
IModConsole console,
Expand All @@ -44,7 +47,8 @@ public ModHelper(
IModDefaultConfig defaultConfig,
IOwmlConfig owmlConfig,
IModInteraction interaction,
IMenuManager menuHelper)
IMenuManager menuHelper,
IModTranslations menuTranslations)
{
Logger = logger;
Console = console;
Expand All @@ -59,6 +63,7 @@ public ModHelper(
OwmlConfig = owmlConfig;
Interaction = interaction;
MenuHelper = menuHelper;
MenuTranslations = menuTranslations;
}
}
}
Loading

0 comments on commit a85aa7e

Please sign in to comment.