Fix issues with local settings tab localization

This commit is contained in:
Atony committed 2026-08-27 19:29:12 -05:00
1 parent 28a77f96cb
commit 48aff163f9
9 files changed
+110 -10

No files matched your search

+5
View File
@@ -39,4 +39,9 @@ public interface ILocalSetting
/// <param name="last">Whether it's the last on the row.</param>
/// <returns>The created setting's <see cref="GameObject"/>.</returns>
GameObject? CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last);
/// <summary>
/// Used to refresh the setting's information, usually for localization.
/// </summary>
void RefreshOption();
}
+19 -3
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using BepInEx.Configuration;
using HarmonyLib;
using MiraAPI.LocalSettings.SettingTypes;
using MiraAPI.Patches.LocalSettings;
using MiraAPI.Translation;
using MiraAPI.Utilities;
@@ -53,6 +54,11 @@ public abstract class LocalSettingsTab(ConfigFile config)
/// </summary>
public List<ILocalSetting> Settings { get; } = [];
/// <summary>
/// Gets a collection of <see cref="TextMeshPro"/>s alongside the locale keys for them.
/// </summary>
public Dictionary<TextMeshPro, string> Labels { get; } = [];
/// <summary>
/// Gets the list of <see cref="LocalSettingsButton"/>s.
/// </summary>
@@ -74,12 +80,21 @@ public abstract class LocalSettingsTab(ConfigFile config)
}
/// <summary>
/// Attempts to open the tab.
/// Refreshes setting names upon opening the tab.
/// Override for custom behavior.
/// </summary>
public virtual void Open()
{
OptionsMenuPatches.Instance?.OpenTabGroup(TabIndex);
foreach (var setting in Settings)
{
setting.RefreshOption();
}
foreach (var label in Labels)
{
label.Key.text =
$"<font=\"LiberationSans SDF\" material=\"LiberationSans SDF - Chat Message Masked\"><b>{label.Value.Translate()}</b></font>";
}
}
/// <summary>
@@ -273,7 +288,7 @@ public abstract class LocalSettingsTab(ConfigFile config)
return tabButtonObject.gameObject;
}
private static void CreateLabel(GameObject template, Transform parent, string text, ref float offset)
private void CreateLabel(GameObject template, Transform parent, string text, ref float offset)
{
var label = Object.Instantiate(template, parent);
label.transform.localPosition = new Vector3(0, 1.85f - offset);
@@ -281,6 +296,7 @@ public abstract class LocalSettingsTab(ConfigFile config)
label.name = text;
var tmp = label.GetComponent<TextMeshPro>();
Labels.Add(tmp, text);
tmp.text = $"<font=\"LiberationSans SDF\" material=\"LiberationSans SDF - Chat Message Masked\"><b>{text.Translate()}</b></font>";
tmp.alignment = TextAlignmentOptions.Center;
@@ -26,6 +26,10 @@ public class LocalEnumSetting : LocalSettingBase<int>
/// </summary>
public string[] Values { get; }
private SpriteRenderer _highlight { get; set; }
private TextMeshPro _btnText { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="LocalEnumSetting"/> class.
/// </summary>
@@ -54,6 +58,7 @@ public class LocalEnumSetting : LocalSettingBase<int>
{
var button = Object.Instantiate(toggle, parent).GetComponent<PassiveButton>();
var tmp = button.transform.FindChild("Text_TMP").GetComponent<TextMeshPro>();
_btnText = tmp;
var rollover = button.GetComponent<ButtonRolloverHandler>();
tmp.GetComponent<TextTranslatorTMP>().Destroy();
button.gameObject.SetActive(true);
@@ -63,6 +68,7 @@ public class LocalEnumSetting : LocalSettingBase<int>
var highlight = button.transform.FindChild("ButtonHighlight")?.GetComponent<SpriteRenderer>();
if (highlight != null)
{
_highlight = highlight;
highlight.color = Tab!.TabAppearance.EnumHoverColor;
highlight.gameObject.SetActive(false);
}
@@ -125,9 +131,19 @@ public class LocalEnumSetting : LocalSettingBase<int>
return button.gameObject;
}
/// <inheritdoc/>
public override void RefreshOption()
{
_btnText.text = GetValueText();
if (_highlight)
{
_highlight.gameObject.SetActive(false);
}
}
/// <inheritdoc/>
protected override string GetValueText()
{
return $"<font=\"LiberationSans SDF\" material=\"LiberationSans SDF - Chat Message Masked\">{Name.Translate()}: <b>{Values[GetValue()]}</font></b>";
return $"<font=\"LiberationSans SDF\" material=\"LiberationSans SDF - Chat Message Masked\">{Name.Translate()}: <b>{Values[GetValue()].Translate()}</font></b>";
}
}
@@ -35,6 +35,10 @@ public class LocalNumberSetting : LocalSettingBase<float>
/// </summary>
public MiraNumberSuffixes SuffixType { get; }
private SpriteRenderer _highlight { get; set; }
private TextMeshPro _btnText { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="LocalNumberSetting"/> class.
/// </summary>
@@ -65,6 +69,7 @@ public class LocalNumberSetting : LocalSettingBase<float>
{
var button = Object.Instantiate(toggle, parent).GetComponent<PassiveButton>();
var tmp = button.transform.FindChild("Text_TMP").GetComponent<TextMeshPro>();
_btnText = tmp;
var rollover = button.GetComponent<ButtonRolloverHandler>();
tmp.GetComponent<TextTranslatorTMP>().Destroy();
button.gameObject.SetActive(true);
@@ -74,6 +79,7 @@ public class LocalNumberSetting : LocalSettingBase<float>
var highlight = button.transform.FindChild("ButtonHighlight")?.GetComponent<SpriteRenderer>();
if (highlight != null)
{
_highlight = highlight;
highlight.color = Tab!.TabAppearance.NumberHoverColor;
highlight.gameObject.SetActive(false);
}
@@ -136,6 +142,16 @@ public class LocalNumberSetting : LocalSettingBase<float>
return button.gameObject;
}
/// <inheritdoc/>
public override void RefreshOption()
{
_btnText.text = GetValueText();
if (_highlight)
{
_highlight.gameObject.SetActive(false);
}
}
/// <inheritdoc/>
protected override string GetValueText()
{
@@ -54,6 +54,9 @@ public abstract class LocalSettingBase<T> : ILocalSetting
/// <returns>The created setting.</returns>
public abstract GameObject CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last);
/// <inheritdoc/>
public abstract void RefreshOption();
/// <summary>
/// Returns the formated string to use in the text of the setting.
/// </summary>
@@ -40,6 +40,8 @@ public class LocalSliderSetting : LocalSettingBase<float>
/// </summary>
public MiraNumberSuffixes SuffixType { get; }
private SlideBar _slider { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="LocalSliderSetting"/> class.
/// </summary>
@@ -71,6 +73,7 @@ public class LocalSliderSetting : LocalSettingBase<float>
public override GameObject CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last)
{
var newSlider = Object.Instantiate(slider, parent).GetComponent<SlideBar>();
_slider = newSlider;
var rollover = newSlider.GetComponent<ButtonRolloverHandler>();
newSlider.Title = newSlider.transform.FindChild("Text_TMP").GetComponent<TextMeshPro>(); // Why the hell slider has a title property that is not even assigned???
newSlider.Title.GetComponent<TextTranslatorTMP>().Destroy();
@@ -105,6 +108,12 @@ public class LocalSliderSetting : LocalSettingBase<float>
return newSlider.gameObject;
}
/// <inheritdoc/>
public override void RefreshOption()
{
_slider.Title.text = GetValueText();
}
/// <inheritdoc/>
protected override string GetValueText()
{
@@ -15,6 +15,8 @@ namespace MiraAPI.LocalSettings.SettingTypes;
/// </summary>
public class LocalToggleSetting : LocalSettingBase<bool>
{
private ToggleButtonBehaviour _toggle { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="LocalToggleSetting"/> class.
/// </summary>
@@ -32,6 +34,7 @@ public class LocalToggleSetting : LocalSettingBase<bool>
public override GameObject CreateOption(ToggleButtonBehaviour toggle, SlideBar slider, Transform parent, ref float offset, ref int order, bool last)
{
var toggleObject = Object.Instantiate(toggle, parent).GetComponent<ToggleButtonBehaviour>();
_toggle = toggleObject;
var tmp = toggleObject.transform.FindChild("Text_TMP").GetComponent<TextMeshPro>();
var passiveButton = toggleObject.GetComponent<PassiveButton>();
var rollover = toggleObject.GetComponent<ButtonRolloverHandler>();
@@ -86,4 +89,11 @@ public class LocalToggleSetting : LocalSettingBase<bool>
return toggleObject.gameObject;
}
/// <inheritdoc/>
public override void RefreshOption()
{
_toggle.UpdateText(GetValue());
_toggle.Background.color = GetValue() ? Tab!.TabAppearance.ToggleActiveColor : Tab!.TabAppearance.ToggleInactiveColor;
}
}
@@ -213,6 +213,8 @@ public static class OptionsMenuPatches
if (background != null)
background.color = tab.TabAppearance.TabColor;
tab.Open();
}
private static void CustomClose(LocalSettingsTab tab)
{
+29 -6
View File
@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using MiraAPI.Utilities;
using Reactor.Localization.Utilities;
using UnityEngine;
@@ -97,7 +98,22 @@ public static class MiraLocaleManager
var callingAssembly = Assembly.GetCallingAssembly();
var dir = GetModLangDir(modGuid);
LoadInternalStrings(callingAssembly, modGuid, dir);
LoadInternalStrings(callingAssembly, callingAssembly.GetName().Name!, modGuid, dir);
}
/// <summary>
/// Registers translations for a mod. Copies embedded XML to mira_languages/{modGuid}/ on first run,
/// then loads all XML files from that directory into memory.
/// Call once per mod during plugin Load().
/// </summary>
/// <param name="modGuid">The mod GUID (e.g., "mira.example").</param>
/// <param name="internalName">The mod's root namespace (e.g., "mira.api").</param>
public static void Register(string modGuid, string internalName)
{
var callingAssembly = Assembly.GetCallingAssembly();
var dir = GetModLangDir(modGuid);
LoadInternalStrings(callingAssembly, internalName, modGuid, dir);
}
/// <summary>
@@ -194,7 +210,7 @@ public static class MiraLocaleManager
return newString;
}
private static void LoadInternalStrings(Assembly assembly, string modGuid, string dir)
private static void LoadInternalStrings(Assembly assembly, string internalName, string modGuid, string dir)
{
Directory.CreateDirectory(dir);
@@ -203,8 +219,9 @@ public static class MiraLocaleManager
Locale[modGuid] = [];
}
var resourcePrefix = $"{assembly.GetName().Name}.Resources.Locale.";
var resourcePrefix = $"{internalName}.Resources.Locale.";
var atLeastOneLoaded = false;
foreach (var locale in LangList)
{
using var resourceStream =
@@ -221,7 +238,8 @@ public static class MiraLocaleManager
{
var dict = ParseXmlFile(xmlContent);
Locale[modGuid][locale.Key] = dict;
Info($"Loaded {locale.Key} translation for mod {modGuid} ({dict.Count} keys)");
Info($"Loaded {locale.Key.ToDisplayString()} translation for mod {modGuid} ({dict.Count} keys)");
atLeastOneLoaded = true;
}
catch (Exception e)
{
@@ -229,6 +247,11 @@ public static class MiraLocaleManager
}
}
if (!atLeastOneLoaded)
{
Error($"No internal strings were found for {internalName}!");
}
if (!Locale.TryGetValue(modGuid, out _))
{
Locale[modGuid] = [];
@@ -247,11 +270,11 @@ public static class MiraLocaleManager
{
var dict = ParseXmlFile(filePath);
Locale[modGuid][lang] = dict;
Info($"Loaded {lang} translation for mod {modGuid} ({dict.Count} keys)");
Info($"Loaded external {lang.ToDisplayString()} translation for mod {modGuid} ({dict.Count} keys)");
}
catch (Exception e)
{
Error($"Failed to load translation {filePath}: {e.Message}");
Error($"Failed to load external translation {filePath}: {e.Message}");
}
}
}