using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.NET.Common;
using Candide;
using Candide.GameModels.Helpers;
using HarmonyLib;
using RomesteadLocalizationAPI.Api;
using Shared.Text;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Romestead Localization API")]
[assembly: AssemblyDescription("Romestead Localization API by Ice Box Studio")]
[assembly: AssemblyCompany("Ice Box Studio")]
[assembly: AssemblyProduct("Romestead Localization API")]
[assembly: AssemblyCopyright("Copyright (C) 2026 Ice Box Studio All rights reserved.")]
[assembly: ComVisible(false)]
[assembly: Guid("6f52443b-3b87-402a-9965-44b01b12c078")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace RomesteadLocalizationAPI
{
public static class PluginInfo
{
public const string PLUGIN_GUID = "IceBoxStudio.Romestead.LocalizationAPI";
public const string PLUGIN_NAME = "Romestead Localization API";
public const string PLUGIN_VERSION = "1.0.0";
public const string PLUGIN_AUTHOR = "Ice Box Studio";
public const string PLUGIN_AUTHOR_URL = "https://steamcommunity.com/id/ibox666/";
}
[BepInPlugin("IceBoxStudio.Romestead.LocalizationAPI", "Romestead Localization API", "1.0.0")]
public sealed class RomesteadLocalizationAPI : BasePlugin
{
private Harmony _harmony;
public static RomesteadLocalizationAPI Instance { get; private set; }
internal static ManualLogSource Logger { get; private set; }
public override void Load()
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
Instance = this;
Logger = ((BasePlugin)this).Log;
bool flag = default(bool);
try
{
_harmony = new Harmony("IceBoxStudio.Romestead.LocalizationAPI");
_harmony.PatchAll(Assembly.GetExecutingAssembly());
RomesteadLocalization.Apply();
ManualLogSource logger = Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Romestead Localization API");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" initialized.");
}
logger.LogInfo(val);
}
catch (Exception ex)
{
ManualLogSource logger2 = Logger;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(24, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("Romestead Localization API");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" initialization error: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("\n");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.StackTrace);
}
logger2.LogError(val2);
}
}
}
}
namespace RomesteadLocalizationAPI.Patches
{
[HarmonyPatch(typeof(LocalizationManager), "SetLocalization")]
internal static class LocalizationManagerPatch
{
private static void Postfix(string locale)
{
RomesteadLocalization.OnGameLocalizationLoaded(locale);
}
}
}
namespace RomesteadLocalizationAPI.Api
{
public static class RomesteadLocales
{
public const string English = "en";
public const string ChineseSimplified = "zh_CN";
public const string ChineseTraditional = "zh_TW";
public const string Czech = "cs_CZ";
public const string German = "de_DE";
public const string Greek = "el_GR";
public const string Spanish = "es_ES";
public const string French = "fr_FR";
public const string Italian = "it_IT";
public const string Japanese = "ja_JP";
public const string Korean = "ko_KR";
public const string Dutch = "nl_NL";
public const string Polish = "pl_PL";
public const string PortugueseBrazil = "pt_BR";
public const string Russian = "ru_RU";
public const string Slovak = "sk_SK";
public const string Swedish = "sv_SE";
public const string Turkish = "tr_TR";
internal static readonly string[] Known = new string[18]
{
"en", "zh_CN", "zh_TW", "cs_CZ", "de_DE", "el_GR", "es_ES", "fr_FR", "it_IT", "ja_JP",
"ko_KR", "nl_NL", "pl_PL", "pt_BR", "ru_RU", "sk_SK", "sv_SE", "tr_TR"
};
}
public static class RomesteadLocalization
{
private sealed class Entry
{
public string SourceId;
public readonly Dictionary<string, string> Texts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public Entry(string sourceId)
{
SourceId = sourceId;
}
}
private const string TestingLocale = "<testing>";
private static readonly object Sync = new object();
private static readonly Dictionary<string, Entry> Entries = new Dictionary<string, Entry>(StringComparer.Ordinal);
private static string _currentLocale = "en";
public static string CurrentLocale => DetectCurrentLocale();
public static event Action<string> LanguageChanged;
public static event Action<string> LocalizationApplied;
public static RomesteadLocalizer For(string sourceId)
{
ValidateSourceId(sourceId);
return new RomesteadLocalizer(sourceId);
}
public static void RegisterJsonDirectory(string sourceId, string directory)
{
ValidateSourceId(sourceId);
if (string.IsNullOrWhiteSpace(directory))
{
throw new ArgumentException("Localization directory cannot be empty.", "directory");
}
if (!Directory.Exists(directory))
{
throw new DirectoryNotFoundException(directory);
}
Dictionary<string, Dictionary<string, string>> dictionary = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
string[] files = Directory.GetFiles(directory, "*.json", SearchOption.TopDirectoryOnly);
Array.Sort(files, (IComparer<string>?)StringComparer.OrdinalIgnoreCase);
string[] array = files;
foreach (string path in array)
{
string localeFromJsonFile = GetLocaleFromJsonFile(path);
foreach (KeyValuePair<string, string> item in ReadJsonTextMap(path))
{
AddBundleText(dictionary, localeFromJsonFile, item.Key, item.Value);
}
}
RegisterBundle(sourceId, dictionary);
}
public static void RegisterJson(string sourceId, string path)
{
ValidateSourceId(sourceId);
RegisterBundle(sourceId, ReadJsonBundle(path));
}
public static void RegisterText(string sourceId, string locale, string key, string text)
{
ValidateSourceId(sourceId);
ValidateLocale(locale);
ValidateKey(key);
if (text == null)
{
throw new ArgumentNullException("text");
}
Dictionary<string, Dictionary<string, string>> dictionary = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
AddBundleText(dictionary, locale, key, text);
RegisterBundle(sourceId, dictionary);
}
public static void RegisterTexts(string sourceId, string locale, IReadOnlyDictionary<string, string> texts)
{
ValidateSourceId(sourceId);
ValidateLocale(locale);
if (texts == null)
{
throw new ArgumentNullException("texts");
}
Dictionary<string, Dictionary<string, string>> dictionary = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
foreach (KeyValuePair<string, string> text in texts)
{
ValidateKey(text.Key);
if (text.Value == null)
{
throw new ArgumentException("Localization text cannot be null: " + text.Key, "texts");
}
AddBundleText(dictionary, locale, text.Key, text.Value);
}
RegisterBundle(sourceId, dictionary);
}
public static void RegisterTexts(string sourceId, params (string Locale, string Key, string Text)[] texts)
{
ValidateSourceId(sourceId);
if (texts == null)
{
throw new ArgumentNullException("texts");
}
Dictionary<string, Dictionary<string, string>> dictionary = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < texts.Length; i++)
{
(string, string, string) tuple = texts[i];
ValidateLocale(tuple.Item1);
ValidateKey(tuple.Item2);
if (tuple.Item3 == null)
{
throw new ArgumentException("Localization text cannot be null: " + tuple.Item1 + "." + tuple.Item2, "texts");
}
AddBundleText(dictionary, tuple.Item1, tuple.Item2, tuple.Item3);
}
RegisterBundle(sourceId, dictionary);
}
public static string Text(string key, params object[] args)
{
return GetText(key, args);
}
public static string TextFor(string sourceId, string key, params object[] args)
{
return GetTextFor(sourceId, key, args);
}
public static string GetText(string key, params object[] args)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Expected O, but got Unknown
if (string.IsNullOrEmpty(key))
{
return "<key_not_set>";
}
string text = TryGetRegisteredText(key, CurrentLocale) ?? TryGetGameText(key) ?? key;
if (args == null || args.Length == 0)
{
return text;
}
try
{
return string.Format(text, args);
}
catch (Exception ex)
{
ManualLogSource logger = RomesteadLocalizationAPI.Logger;
if (logger != null)
{
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(39, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Faulty localization format string at ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(key);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
return text;
}
}
public static string GetTextFor(string sourceId, string key, params object[] args)
{
ValidateSourceId(sourceId);
if (string.IsNullOrEmpty(key))
{
return "<key_not_set>";
}
return GetText(ScopeKey(sourceId, key), args);
}
public static void Apply()
{
Apply(DetectCurrentLocale(), notify: false);
}
public static IReadOnlyList<string> GetSupportedLocales()
{
HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
string[] known = RomesteadLocales.Known;
foreach (string item in known)
{
hashSet.Add(item);
}
try
{
foreach (string key in Globals.SupportedLanguageCodes.Keys)
{
if (!string.Equals(key, "<testing>", StringComparison.OrdinalIgnoreCase))
{
hashSet.Add(NormalizeLocale(key));
}
}
}
catch
{
}
foreach (string contentLocale in GetContentLocales())
{
hashSet.Add(contentLocale);
}
List<string> list = new List<string>(hashSet);
list.Sort(StringComparer.OrdinalIgnoreCase);
return list;
}
public static string NormalizeLocale(string locale)
{
string text = (locale ?? string.Empty).Trim().Replace('-', '_');
switch (text)
{
case "":
return "en";
case "en":
case "en_US":
case "en_GB":
return "en";
case "zh":
case "zh_CN":
case "zh_Hans":
return "zh_CN";
case "zh_TW":
case "zh_HK":
case "zh_MO":
case "zh_Hant":
return "zh_TW";
case "cs":
return "cs_CZ";
case "de":
return "de_DE";
case "el":
return "el_GR";
case "es":
return "es_ES";
case "fr":
return "fr_FR";
case "it":
return "it_IT";
case "ja":
return "ja_JP";
case "ko":
return "ko_KR";
case "nl":
return "nl_NL";
case "pl":
return "pl_PL";
case "pt":
case "pt_PT":
return "pt_BR";
case "ru":
return "ru_RU";
case "sk":
return "sk_SK";
case "sv":
return "sv_SE";
case "tr":
return "tr_TR";
default:
return text;
}
}
internal static void OnGameLocalizationLoaded(string locale)
{
Apply(NormalizeLocale(locale), notify: true);
}
private static void RegisterBundle(string sourceId, Dictionary<string, Dictionary<string, string>> bundle)
{
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Expected O, but got Unknown
lock (Sync)
{
bool flag = default(bool);
foreach (KeyValuePair<string, Dictionary<string, string>> item in bundle)
{
string key = NormalizeLocale(item.Key);
foreach (KeyValuePair<string, string> item2 in item.Value)
{
string text = ScopeKey(sourceId, item2.Key);
if (!Entries.TryGetValue(text, out var value))
{
value = new Entry(sourceId);
Entries[text] = value;
}
else if (!string.Equals(value.SourceId, sourceId, StringComparison.Ordinal))
{
ManualLogSource logger = RomesteadLocalizationAPI.Logger;
if (logger != null)
{
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(35, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Localization key ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" from ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(sourceId);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" overrides ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(value.SourceId);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
logger.LogWarning(val);
}
value.SourceId = sourceId;
}
value.Texts[key] = item2.Value;
}
}
}
Apply();
}
private static void Apply(string locale, bool notify)
{
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
string text = NormalizeLocale(locale);
bool flag = false;
lock (Sync)
{
flag = !string.Equals(_currentLocale, text, StringComparison.OrdinalIgnoreCase);
_currentLocale = text;
if (string.Equals(text, "<testing>", StringComparison.OrdinalIgnoreCase))
{
return;
}
foreach (KeyValuePair<string, Entry> entry in Entries)
{
string text2 = SelectText(entry.Value.Texts, text);
if (text2 != null)
{
StringDefinitions.Strings[entry.Key] = new StringDefinition(text2);
}
}
}
if (notify)
{
RomesteadLocalization.LocalizationApplied?.Invoke(text);
if (flag)
{
RomesteadLocalization.LanguageChanged?.Invoke(text);
}
}
}
private static string TryGetRegisteredText(string key, string locale)
{
lock (Sync)
{
Entry value;
return Entries.TryGetValue(key, out value) ? SelectText(value.Texts, locale) : null;
}
}
private static string TryGetGameText(string key)
{
try
{
string text = default(string);
return StringDefinitions.TryGetString(key, ref text) ? text : null;
}
catch
{
return null;
}
}
private static string SelectText(Dictionary<string, string> texts, string locale)
{
string text = NormalizeLocale(locale);
if (string.Equals(text, "<testing>", StringComparison.OrdinalIgnoreCase))
{
return null;
}
if (texts.TryGetValue(text, out var value))
{
return value;
}
if (texts.TryGetValue("en", out var value2))
{
return value2;
}
if (texts.TryGetValue("zh_CN", out var value3))
{
return value3;
}
using (Dictionary<string, string>.ValueCollection.Enumerator enumerator = texts.Values.GetEnumerator())
{
if (enumerator.MoveNext())
{
return enumerator.Current;
}
}
return null;
}
private static string DetectCurrentLocale()
{
if (!string.IsNullOrWhiteSpace(StringDefinitions.CurrentLanguageCode))
{
return NormalizeLocale(StringDefinitions.CurrentLanguageCode);
}
try
{
if (!string.IsNullOrWhiteSpace(Globals.LanguageCode))
{
return NormalizeLocale(Globals.LanguageCode);
}
}
catch
{
}
string text = ReadSavedLocale();
if (!string.IsNullOrWhiteSpace(text))
{
return NormalizeLocale(text);
}
string text2 = NormalizeLocale(CultureInfo.CurrentCulture.Name);
string[] known = RomesteadLocales.Known;
foreach (string b in known)
{
if (string.Equals(text2, b, StringComparison.OrdinalIgnoreCase))
{
return text2;
}
}
return _currentLocale;
}
private static string ReadSavedLocale()
{
try
{
string path = Path.Combine(GamePathHelper.GetFolderPath((GameFolder)1, false), "localization.json");
if (!File.Exists(path))
{
return null;
}
using FileStream utf8Json = File.OpenRead(path);
using JsonDocument jsonDocument = JsonDocument.Parse((Stream)utf8Json, new JsonDocumentOptions
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip
});
JsonElement value;
return (jsonDocument.RootElement.TryGetProperty("LanguageCode", out value) && value.ValueKind == JsonValueKind.String) ? value.GetString() : null;
}
catch
{
return null;
}
}
private static IEnumerable<string> GetContentLocales()
{
string root = null;
try
{
object manager = typeof(Globals).GetField("ContentManager")?.GetValue(null);
root = manager?.GetType().GetProperty("RootDirectory")?.GetValue(manager) as string;
}
catch
{
}
if (string.IsNullOrWhiteSpace(root))
{
yield break;
}
string path = Path.Combine(root, "localization");
if (!Directory.Exists(path))
{
yield break;
}
string[] files = Directory.GetFiles(path, "locale_*");
foreach (string file in files)
{
string name = Path.GetFileName(file);
if (name != null && name.Length > "locale_".Length)
{
yield return NormalizeLocale(name.Substring("locale_".Length));
}
}
}
private static Dictionary<string, string> ReadJsonTextMap(string path)
{
if (string.IsNullOrWhiteSpace(path))
{
throw new ArgumentException("Localization file path cannot be empty.", "path");
}
if (!File.Exists(path))
{
throw new FileNotFoundException("Localization file was not found.", path);
}
using FileStream utf8Json = File.OpenRead(path);
using JsonDocument jsonDocument = JsonDocument.Parse((Stream)utf8Json, new JsonDocumentOptions
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip
});
if (jsonDocument.RootElement.ValueKind != JsonValueKind.Object)
{
throw new JsonException("Localization file must contain a JSON object: " + path);
}
Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
foreach (JsonProperty item in jsonDocument.RootElement.EnumerateObject())
{
if (item.Value.ValueKind != JsonValueKind.String)
{
throw new JsonException("Localization value must be a string: " + path + " -> " + item.Name);
}
dictionary[item.Name] = item.Value.GetString();
}
return dictionary;
}
private static Dictionary<string, Dictionary<string, string>> ReadJsonBundle(string path)
{
if (string.IsNullOrWhiteSpace(path))
{
throw new ArgumentException("Localization bundle path cannot be empty.", "path");
}
if (!File.Exists(path))
{
throw new FileNotFoundException("Localization bundle was not found.", path);
}
using FileStream utf8Json = File.OpenRead(path);
using JsonDocument jsonDocument = JsonDocument.Parse((Stream)utf8Json, new JsonDocumentOptions
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip
});
if (jsonDocument.RootElement.ValueKind != JsonValueKind.Object)
{
throw new JsonException("Localization bundle must contain a JSON object: " + path);
}
Dictionary<string, Dictionary<string, string>> result = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
foreach (JsonProperty item in jsonDocument.RootElement.EnumerateObject())
{
if (!IsLocaleName(item.Name))
{
throw new JsonException("Localization bundle top-level key must be a locale: " + path + " -> " + item.Name);
}
if (item.Value.ValueKind != JsonValueKind.Object)
{
throw new JsonException("Localization locale value must be an object: " + path + " -> " + item.Name);
}
foreach (JsonProperty item2 in item.Value.EnumerateObject())
{
AddBundleText(result, item.Name, item2.Name, item2.Value, path);
}
}
return result;
}
private static string GetLocaleFromJsonFile(string path)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
if (fileNameWithoutExtension == null)
{
return "en";
}
return fileNameWithoutExtension.StartsWith("locale_", StringComparison.OrdinalIgnoreCase) ? NormalizeLocale(fileNameWithoutExtension.Substring("locale_".Length)) : NormalizeLocale(fileNameWithoutExtension);
}
private static bool IsLocaleName(string value)
{
string a = NormalizeLocale(value);
string[] known = RomesteadLocales.Known;
foreach (string b in known)
{
if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return value.Length == 2 || (value.Length == 5 && value[2] == '_') || (value.Length == 7 && value[2] == '_');
}
private static void AddBundleText(Dictionary<string, Dictionary<string, string>> result, string locale, string key, JsonElement value, string path)
{
if (value.ValueKind != JsonValueKind.String)
{
throw new JsonException($"Localization value must be a string: {path} -> {locale}.{key}");
}
AddBundleText(result, locale, key, value.GetString());
}
private static void AddBundleText(Dictionary<string, Dictionary<string, string>> result, string locale, string key, string text)
{
if (text == null)
{
throw new ArgumentNullException("text");
}
string key2 = NormalizeLocale(locale);
if (!result.TryGetValue(key2, out var value))
{
value = (result[key2] = new Dictionary<string, string>(StringComparer.Ordinal));
}
value[key] = text;
}
private static string ScopeKey(string sourceId, string key)
{
return key.StartsWith(sourceId + ".", StringComparison.Ordinal) ? key : (sourceId + "." + key);
}
private static void ValidateSourceId(string sourceId)
{
if (string.IsNullOrWhiteSpace(sourceId))
{
throw new ArgumentException("Source id cannot be empty.", "sourceId");
}
}
private static void ValidateLocale(string locale)
{
if (string.IsNullOrWhiteSpace(locale))
{
throw new ArgumentException("Locale cannot be empty.", "locale");
}
}
private static void ValidateKey(string key)
{
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentException("Localization key cannot be empty.", "key");
}
}
}
public sealed class RomesteadLocalizer
{
public string SourceId { get; }
public string CurrentLocale => RomesteadLocalization.CurrentLocale;
public event Action<string> LanguageChanged
{
add
{
RomesteadLocalization.LanguageChanged += value;
}
remove
{
RomesteadLocalization.LanguageChanged -= value;
}
}
internal RomesteadLocalizer(string sourceId)
{
SourceId = sourceId;
}
public RomesteadLocalizer RegisterJson(string path)
{
RomesteadLocalization.RegisterJson(SourceId, path);
return this;
}
public RomesteadLocalizer RegisterJsonDirectory(string directory)
{
RomesteadLocalization.RegisterJsonDirectory(SourceId, directory);
return this;
}
public RomesteadLocalizer RegisterText(string locale, string key, string text)
{
RomesteadLocalization.RegisterText(SourceId, locale, key, text);
return this;
}
public RomesteadLocalizer RegisterTexts(string locale, IReadOnlyDictionary<string, string> texts)
{
RomesteadLocalization.RegisterTexts(SourceId, locale, texts);
return this;
}
public RomesteadLocalizer RegisterTexts(params (string Locale, string Key, string Text)[] texts)
{
RomesteadLocalization.RegisterTexts(SourceId, texts);
return this;
}
public string Text(string key, params object[] args)
{
return RomesteadLocalization.TextFor(SourceId, key, args);
}
public string GetText(string key, params object[] args)
{
return RomesteadLocalization.GetTextFor(SourceId, key, args);
}
}
}