From 34148499b71752a8a90ea45af08f8e5b92ac94f8 Mon Sep 17 00:00:00 2001
From: Atony <75191600+AtonyGit@users.noreply.github.com>
Date: Tue, 25 Aug 2026 18:26:54 -0500
Subject: [PATCH] Fix up system registration for the most part
---
.../English.xml => Locale/en_US.xml} | 0
.../SChinese.xml => Locale/zh_CN.xml} | 0
MiraAPI/Colors/CustomColor.cs | 6 +++---
MiraAPI/Colors/PaletteManager.cs | 5 +----
MiraAPI/GameModes/GameModeOption.cs | 9 +++++----
.../OptionTypes/ModdedEnumOption.cs | 9 +++++----
.../GameOptions/OptionTypes/ModdedOption.cs | 2 +-
.../OptionTypes/ModdedStringOption.cs | 5 +++--
.../SettingTypes/LocalToggleSetting.cs | 2 +-
.../Patches/Options/GameOptionsMenuPatch.cs | 4 ++--
.../Patches/Options/LobbyViewPanePatches.cs | 13 +++----------
.../Patches/Options/RoleSettingMenuPatches.cs | 10 ++--------
MiraAPI/Resources/Locale/en_US.xml | 10 +++++++---
MiraAPI/Roles/CustomRoleManager.cs | 7 ++++---
MiraAPI/Roles/ICustomRole.cs | 13 +++++++------
MiraAPI/Roles/RoleOptionsGroup.cs | 6 +++---
MiraAPI/Translation/MiraLocaleManager.cs | 19 ++++++++++++++++++-
.../Translation/MiraLocalizationProvider.cs | 15 +++------------
18 files changed, 68 insertions(+), 67 deletions(-)
rename MiraAPI.Example/Resources/{Translations/English.xml => Locale/en_US.xml} (100%)
rename MiraAPI.Example/Resources/{Translations/SChinese.xml => Locale/zh_CN.xml} (100%)
diff --git a/MiraAPI.Example/Resources/Translations/English.xml b/MiraAPI.Example/Resources/Locale/en_US.xml
similarity index 100%
rename from MiraAPI.Example/Resources/Translations/English.xml
rename to MiraAPI.Example/Resources/Locale/en_US.xml
diff --git a/MiraAPI.Example/Resources/Translations/SChinese.xml b/MiraAPI.Example/Resources/Locale/zh_CN.xml
similarity index 100%
rename from MiraAPI.Example/Resources/Translations/SChinese.xml
rename to MiraAPI.Example/Resources/Locale/zh_CN.xml
diff --git a/MiraAPI/Colors/CustomColor.cs b/MiraAPI/Colors/CustomColor.cs
index 89663d1..f1b5c49 100644
--- a/MiraAPI/Colors/CustomColor.cs
+++ b/MiraAPI/Colors/CustomColor.cs
@@ -1,5 +1,5 @@
-using MiraAPI.Utilities;
-using Reactor.Localization.Utilities;
+using MiraAPI.Translation;
+using MiraAPI.Utilities;
using UnityEngine;
namespace MiraAPI.Colors;
@@ -43,7 +43,7 @@ public sealed class CustomColor(StringNames name, Color32 mainColor, Color32 sha
}
///
- public CustomColor(string name, Color32 mainColor, Color32 shadowColor) : this(CustomStringName.CreateAndRegister(name), mainColor, shadowColor)
+ public CustomColor(string name, Color32 mainColor, Color32 shadowColor) : this(MiraLocaleManager.GetOrCreateLocaleString(name), mainColor, shadowColor)
{
}
}
diff --git a/MiraAPI/Colors/PaletteManager.cs b/MiraAPI/Colors/PaletteManager.cs
index c8ae990..3d25b33 100644
--- a/MiraAPI/Colors/PaletteManager.cs
+++ b/MiraAPI/Colors/PaletteManager.cs
@@ -1,8 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using HarmonyLib;
-using MiraAPI.Translation;
-using Reactor.Localization.Utilities;
namespace MiraAPI.Colors;
@@ -23,8 +21,7 @@ public static class PaletteManager
var colors = CustomColors.Select(x => x.MainColor).ToArray();
var shadowColors = CustomColors.Select(x => x.ShadowColor).ToArray();
var stringNames = CustomColors.Select(x =>
- CustomStringName.CreateAndRegister(TranslationController.Instance.GetString(x.Name).Translate())
- ).ToArray();
+ x.Name).ToArray();
Palette.PlayerColors = Palette.PlayerColors.ToArray().AddRangeToArray(colors);
Palette.ShadowColors = Palette.ShadowColors.ToArray().AddRangeToArray(shadowColors);
diff --git a/MiraAPI/GameModes/GameModeOption.cs b/MiraAPI/GameModes/GameModeOption.cs
index 95acd9c..180103d 100644
--- a/MiraAPI/GameModes/GameModeOption.cs
+++ b/MiraAPI/GameModes/GameModeOption.cs
@@ -6,6 +6,7 @@ using MiraAPI.GameOptions;
using MiraAPI.Networking;
using MiraAPI.Patches.GameModes;
using MiraAPI.Patches.Options;
+using MiraAPI.Translation;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Localization.Utilities;
@@ -48,17 +49,17 @@ public static class GameModeOption
internal static StringOption OptionBehaviour { get; set; } = null!;
internal static int _lastValue;
- internal static readonly StringNames GamemodeName = CustomStringName.CreateAndRegister("Gamemode");
- internal static readonly StringNames CustomName = CustomStringName.CreateAndRegister("Custom");
+ internal static readonly StringNames GamemodeName = MiraLocaleManager.GetOrCreateLocaleString("Gamemode");
+ internal static readonly StringNames CustomName = MiraLocaleManager.GetOrCreateLocaleString("Custom");
internal static readonly Dictionary Values = new()
{
- [0] = CustomStringName.CreateAndRegister("Classic"),
+ [0] = MiraLocaleManager.GetOrCreateLocaleString("Classic"),
};
internal static void AddOption(AbstractGameMode mode)
{
if (!Values.ContainsKey(mode.ID))
- Values.Add(mode.ID, CustomStringName.CreateAndRegister(mode.ColoredName));
+ Values.Add(mode.ID, MiraLocaleManager.GetOrCreateLocaleString(mode + ".colored"));
}
/*[HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.CreateSettings))]
[HarmonyPostfix]
diff --git a/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs b/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs
index 30809bd..4e512af 100644
--- a/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs
+++ b/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MiraAPI.Networking;
+using MiraAPI.Translation;
using Reactor.Localization.Utilities;
using UnityEngine;
using Object = UnityEngine.Object;
@@ -37,8 +38,8 @@ public class ModdedEnumOption : ModdedOption
data.Title = StringName;
data.Type = global::OptionTypes.String;
data.Values = values is null ?
- Enum.GetNames(enumType).Select(CustomStringName.CreateAndRegister).ToArray()
- : [.. values.Select(CustomStringName.CreateAndRegister)];
+ Enum.GetNames(enumType).Select(MiraLocaleManager.GetOrCreateLocaleString).ToArray()
+ : [.. values.Select(MiraLocaleManager.GetOrCreateLocaleString)];
data.Index = Value;
}
@@ -136,8 +137,8 @@ public class ModdedEnumOption : ModdedOption where T : Enum
data.Title = StringName;
data.Type = global::OptionTypes.String;
data.Values = values is null ?
- Enum.GetNames(typeof(T)).Select(CustomStringName.CreateAndRegister).ToArray()
- : [.. values.Select(CustomStringName.CreateAndRegister)];
+ Enum.GetNames(typeof(T)).Select(MiraLocaleManager.GetOrCreateLocaleString).ToArray()
+ : [.. values.Select(MiraLocaleManager.GetOrCreateLocaleString)];
data.Index = Convert.ToInt32(Value, NumberFormatInfo.InvariantInfo);
}
diff --git a/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs b/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs
index 6178eff..5fa0ceb 100644
--- a/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs
+++ b/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs
@@ -82,7 +82,7 @@ public abstract class ModdedOption : IModdedOption
Title = title.Translate();
DefaultValue = defaultValue;
Value = defaultValue;
- StringName = CustomStringName.CreateAndRegister(Title.Translate());
+ StringName = MiraLocaleManager.GetOrCreateLocaleString(Title);
Visible = () => true;
IncludeInPreset = includeInPreset;
}
diff --git a/MiraAPI/GameOptions/OptionTypes/ModdedStringOption.cs b/MiraAPI/GameOptions/OptionTypes/ModdedStringOption.cs
index 62d07cf..630a9ec 100644
--- a/MiraAPI/GameOptions/OptionTypes/ModdedStringOption.cs
+++ b/MiraAPI/GameOptions/OptionTypes/ModdedStringOption.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MiraAPI.Networking;
+using MiraAPI.Translation;
using Reactor.Localization.Utilities;
using UnityEngine;
using Object = UnityEngine.Object;
@@ -56,7 +57,7 @@ public class ModdedStringOption : ModdedOption
newVals.Insert(index, value);
Values = newVals.ToArray();
var newStrVals = StringNameValues.ToList();
- newStrVals.Insert(index, CustomStringName.CreateAndRegister(value));
+ newStrVals.Insert(index, MiraLocaleManager.GetOrCreateLocaleString(value));
StringNameValues = newStrVals.ToArray();
}
@@ -108,7 +109,7 @@ public class ModdedStringOption : ModdedOption
data.Title = StringName;
data.Type = global::OptionTypes.String;
- StringNameValues = values.Select(CustomStringName.CreateAndRegister).ToArray();
+ StringNameValues = values.Select(MiraLocaleManager.GetOrCreateLocaleString).ToArray();
data.Values = StringNameValues;
data.Index = GetIndex(Value, 3);
diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs b/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs
index 3a1e507..3cb02e3 100644
--- a/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs
+++ b/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs
@@ -47,7 +47,7 @@ public class LocalToggleSetting : LocalSettingBase
toggleObject.transform.localPosition = new Vector3(order == 1 ? -1.185f : 1.185f, 1.85f - offset, -7);
}
- toggleObject.BaseText = CustomStringName.CreateAndRegister(Name.Translate());
+ toggleObject.BaseText = MiraLocaleManager.GetOrCreateLocaleString(Name);
toggleObject.UpdateText(GetValue());
toggleObject.name = Name.Translate();
toggleObject.Background.color = GetValue() ? Tab!.TabAppearance.ToggleActiveColor : Tab!.TabAppearance.ToggleInactiveColor;
diff --git a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs
index bfaf1c4..dec15b6 100644
--- a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs
+++ b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs
@@ -457,7 +457,7 @@ internal static class GameOptionsMenuPatch
num -= 0.58f;
- categoryHeaderMasked.SetHeader(CustomStringName.CreateAndRegister(group.GroupName), 20);
+ categoryHeaderMasked.SetHeader(MiraLocaleManager.GetOrCreateLocaleString(group.GroupName), 20);
categoryHeaderMasked.Background.color = group.GroupColor;
categoryHeaderMasked.Divider.color = group.GroupColor;
categoryHeaderMasked.Title.color = group.GroupColor.Equals(MiraApiPlugin.DefaultHeaderColor)
@@ -697,7 +697,7 @@ internal static class GameOptionsMenuPatch
Quaternion.identity,
container);
- categoryHeaderMasked.SetHeader(CustomStringName.CreateAndRegister(group.GroupName.Translate()), 20);
+ categoryHeaderMasked.SetHeader(MiraLocaleManager.GetOrCreateLocaleString(group.GroupName), 20);
categoryHeaderMasked.Background.color = group.GroupColor;
categoryHeaderMasked.Divider.color = group.GroupColor;
categoryHeaderMasked.Title.color = group.GroupColor.Equals(MiraApiPlugin.DefaultHeaderColor)
diff --git a/MiraAPI/Patches/Options/LobbyViewPanePatches.cs b/MiraAPI/Patches/Options/LobbyViewPanePatches.cs
index 6ee00cd..0a5acee 100644
--- a/MiraAPI/Patches/Options/LobbyViewPanePatches.cs
+++ b/MiraAPI/Patches/Options/LobbyViewPanePatches.cs
@@ -32,8 +32,7 @@ public static class LobbyViewPanePatches
: Plugins[SelectedModIdx - 1];
private static PassiveButton? ModifiersTabButton { get; set; }
-
- private static StringNames ModifiersTabName { get; } = CustomStringName.CreateAndRegister("ModifiersTab");
+ internal static StringNames ModifiersTabName { get; } = MiraLocaleManager.GetOrCreateLocaleString("ModifiersTab");
private static AbstractGameMode? GetCustomGamemode()
{
@@ -455,7 +454,7 @@ public static class LobbyViewPanePatches
// sort the groups by priority
var sortedRoleGroups = roleGroups
.OrderBy(x => x.Key.Priority)
- .ThenBy(x => x.Key.Name);
+ .ThenBy(x => x.Key.Name.Translate());
foreach (var grouping in sortedRoleGroups)
{
@@ -466,13 +465,7 @@ public static class LobbyViewPanePatches
var group = grouping.Key;
- var translatedName = group.Name.Translate();
- var name = translatedName switch
- {
- "Crewmate" => StringNames.CrewmateRolesHeader,
- "Impostor" => StringNames.ImpostorRolesHeader,
- _ => CustomStringName.CreateAndRegister(translatedName),
- };
+ var name = MiraLocaleManager.GetOrCreateLocaleString(group.Name);
var categoryHeaderRoleVariant = Object.Instantiate(instance.categoryHeaderRoleOrigin, instance.settingsContainer, true);
categoryHeaderRoleVariant.SetHeader(name, 61);
diff --git a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
index d08961e..ac444da 100644
--- a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
+++ b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
@@ -196,7 +196,7 @@ public static class RoleSettingMenuPatches
// sort the groups by priority
var sortedRoleGroups = roleGroups
.OrderBy(x => x.Key.Priority)
- .ThenBy(x => x.Key.Name);
+ .ThenBy(x => x.Key.Name.Translate());
var quotaThing = roleMenu.categoryHeaderEditRoleOrigin.transform.FindChild("QuotaHeader");
var usingNewQuota = false;
@@ -215,13 +215,7 @@ public static class RoleSettingMenuPatches
RoleGroupHidden.TryAdd(group, false);
- var translatedName = group.Name.Translate();
- var name = translatedName switch
- {
- "Crewmate" => StringNames.CrewmateRolesHeader,
- "Impostor" => StringNames.ImpostorRolesHeader,
- _ => CustomStringName.CreateAndRegister(translatedName),
- };
+ var name = MiraLocaleManager.GetOrCreateLocaleString(group.Name);
var categoryHeaderMasked = Object.Instantiate(
template,
diff --git a/MiraAPI/Resources/Locale/en_US.xml b/MiraAPI/Resources/Locale/en_US.xml
index 7f3a2b0..5ee4b83 100644
--- a/MiraAPI/Resources/Locale/en_US.xml
+++ b/MiraAPI/Resources/Locale/en_US.xml
@@ -29,10 +29,14 @@ Outlive the timer or eliminate the crew.
Save
Roles
Modifiers
- Crewmate
+ Crewmate
Crew
- Impostor
+ Crewmate Roles
+ Impostor
Imp
- Neutral
+ Impostor Roles
+ Neutral
Neut
+ Neutral Roles
+ Other
diff --git a/MiraAPI/Roles/CustomRoleManager.cs b/MiraAPI/Roles/CustomRoleManager.cs
index a54c439..0f4e839 100644
--- a/MiraAPI/Roles/CustomRoleManager.cs
+++ b/MiraAPI/Roles/CustomRoleManager.cs
@@ -132,9 +132,10 @@ public static class CustomRoleManager
roleBehaviour.Role = (RoleTypes)roleId;
roleBehaviour.TeamType = customRole.Team == ModdedRoleTeams.Custom ? RoleTeamTypes.Crewmate : (RoleTeamTypes)customRole.Team;
roleBehaviour.NameColor = customRole.RoleColor;
- roleBehaviour.StringName = CustomStringName.CreateAndRegister(customRole.RoleName.Translate());
- roleBehaviour.BlurbName = CustomStringName.CreateAndRegister(customRole.RoleDescription.Translate());
- roleBehaviour.BlurbNameLong = CustomStringName.CreateAndRegister(customRole.RoleLongDescription.Translate());
+ roleBehaviour.StringName = MiraLocaleManager.GetOrCreateLocaleString(customRole.RoleName);
+ roleBehaviour.BlurbName = MiraLocaleManager.GetOrCreateLocaleString(customRole.RoleDescription);
+ roleBehaviour.BlurbNameMed = MiraLocaleManager.GetOrCreateLocaleString(customRole.RoleMedDescription);
+ roleBehaviour.BlurbNameLong = MiraLocaleManager.GetOrCreateLocaleString(customRole.RoleLongDescription);
roleBehaviour.AffectedByLightAffectors = customRole.Configuration.AffectedByLightOnAirship;
roleBehaviour.CanBeKilled = customRole.Configuration.CanGetKilled;
roleBehaviour.CanUseKillButton = customRole.Configuration.UseVanillaKillButton;
diff --git a/MiraAPI/Roles/ICustomRole.cs b/MiraAPI/Roles/ICustomRole.cs
index 8e233b8..77d4ce8 100644
--- a/MiraAPI/Roles/ICustomRole.cs
+++ b/MiraAPI/Roles/ICustomRole.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using System.Text;
using BepInEx.Configuration;
using MiraAPI.GameOptions;
@@ -17,7 +18,7 @@ public interface ICustomRole : IOptionable
///
/// Gets the id part used to build the role's translation keys.
///
- string IdPart => GetType().Name.ToLower();
+ string IdPart => GetType().Name.ToLower(CultureInfo.InvariantCulture);
///
/// Gets the name of the role.
@@ -44,10 +45,10 @@ public interface ICustomRole : IOptionable
///
string RoleFactionTitle => Team switch
{
- ModdedRoleTeams.Crewmate => TranslationController.Instance.GetString(StringNames.Crewmate),
- ModdedRoleTeams.Impostor => TranslationController.Instance.GetString(StringNames.Impostor),
- ModdedRoleTeams.Custom => "Neutral",
- _ => "Other",
+ ModdedRoleTeams.Crewmate => MiraLocaleManager.Get("roleTeam.crewmate"),
+ ModdedRoleTeams.Impostor => MiraLocaleManager.Get("roleTeam.impostor"),
+ ModdedRoleTeams.Custom => MiraLocaleManager.Get("roleTeam.neutral"),
+ _ => MiraLocaleManager.Get("roleTeam.other"),
};
///
@@ -78,7 +79,7 @@ public interface ICustomRole : IOptionable
ModdedRoleTeams.Crewmate => RoleOptionsGroup.Crewmate,
ModdedRoleTeams.Impostor => RoleOptionsGroup.Impostor,
ModdedRoleTeams.Custom => RoleOptionsGroup.Neutral,
- _ => new RoleOptionsGroup(RoleName.Translate(), RoleColor),
+ _ => new RoleOptionsGroup(RoleName, RoleColor),
};
///
diff --git a/MiraAPI/Roles/RoleOptionsGroup.cs b/MiraAPI/Roles/RoleOptionsGroup.cs
index 46b6067..a53ea95 100644
--- a/MiraAPI/Roles/RoleOptionsGroup.cs
+++ b/MiraAPI/Roles/RoleOptionsGroup.cs
@@ -13,15 +13,15 @@ public record struct RoleOptionsGroup(string Name, Color Color, int Priority = 0
///
/// Gets the default group for crewmates.
///
- public static RoleOptionsGroup Crewmate { get; } = new("Crewmate", Palette.CrewmateBlue, -2);
+ public static RoleOptionsGroup Crewmate { get; } = new("roleTeam.crewmate.group", Palette.CrewmateBlue, -2);
///
/// Gets the default group for impostors.
///
- public static RoleOptionsGroup Impostor { get; } = new("Impostor", Palette.ImpostorRed, -1);
+ public static RoleOptionsGroup Impostor { get; } = new("roleTeam.impostor.group", Palette.ImpostorRed, -1);
///
/// Gets the default group for neutral roles.
///
- public static RoleOptionsGroup Neutral { get; } = new("Neutral Roles", Color.gray);
+ public static RoleOptionsGroup Neutral { get; } = new("roleTeam.neutral.group", Color.gray);
}
diff --git a/MiraAPI/Translation/MiraLocaleManager.cs b/MiraAPI/Translation/MiraLocaleManager.cs
index ee6b1d8..9f9bfd7 100644
--- a/MiraAPI/Translation/MiraLocaleManager.cs
+++ b/MiraAPI/Translation/MiraLocaleManager.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
+using Reactor.Localization.Utilities;
using UnityEngine;
namespace MiraAPI.Translation;
@@ -12,7 +13,10 @@ public static class MiraLocaleManager
{
private const string LangDirectory = "mira_languages";
- private static readonly Dictionary>> Locale = [];
+ public static readonly Dictionary>> Locale = [];
+
+ public static readonly Dictionary RegisteredStringNames = [];
+ internal static readonly Dictionary StringNamesLookup = [];
public static Dictionary LangList { get; } = new()
{
@@ -177,6 +181,19 @@ public static class MiraLocaleManager
return Path.Combine(Application.persistentDataPath, LangDirectory, modGuid);
}
+ public static StringNames GetOrCreateLocaleString(string name)
+ {
+ if (RegisteredStringNames.TryGetValue(name, out var stringName))
+ {
+ return stringName;
+ }
+
+ var newString = CustomStringName.CreateAndRegister(name);
+ RegisteredStringNames.Add(name, newString);
+ StringNamesLookup.Add(newString, name);
+ return newString;
+ }
+
private static void LoadInternalStrings(Assembly assembly, string modGuid, string dir)
{
Directory.CreateDirectory(dir);
diff --git a/MiraAPI/Translation/MiraLocalizationProvider.cs b/MiraAPI/Translation/MiraLocalizationProvider.cs
index 20b80ed..7505855 100644
--- a/MiraAPI/Translation/MiraLocalizationProvider.cs
+++ b/MiraAPI/Translation/MiraLocalizationProvider.cs
@@ -13,19 +13,10 @@ public class MiraLocalizationProvider : LocalizationProvider
public override bool TryGetText(StringNames stringName, out string? result)
{
- if (_reactorProvider != null && (int)stringName < 0 && _reactorProvider.TryGetText(stringName, out var reactorText))
+ if (MiraLocaleManager.StringNamesLookup.TryGetValue(stringName, out var key))
{
- if (reactorText.IsNullOrWhiteSpace())
- {
- result = "STRMISS";
- return true;
- }
- var localeText = MiraLocaleManager.Get(reactorText!);
- if (localeText != reactorText)
- {
- result = localeText;
- return true;
- }
+ result = MiraLocaleManager.Get(key);
+ return true;
}
result = null;
return false;