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.IgnoreSymbolStoreSequencePoints)]
[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.1.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
[assembly: AssemblyVersion("1.0.1.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.1";
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.1")]
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_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Expected O, but got Unknown
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: 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 PortuguesePortugal = "pt_PT";
public const string Russian = "ru_RU";
public const string Slovak = "sk_SK";
public const string Swedish = "sv_SE";
public const string Thai = "th_TH";
public const string Turkish = "tr_TR";
public const string Ukrainian = "uk_UA";
internal static readonly string[] Known = new string[21]
{
"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", "pt_PT", "ru_RU", "sk_SK", "sv_SE", "th_TH", "tr_TR",
"uk_UA"
};
}
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_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: 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('-', '_');
if (text != null)
{
int length = text.Length;
if (length <= 2)
{
if (length == 0)
{
return "en";
}
if (length == 2)
{
switch (text[0])
{
case 'e':
break;
case 'z':
goto IL_0170;
case 'c':
if (!(text == "cs"))
{
goto IL_03fb;
}
return "cs_CZ";
case 'd':
if (!(text == "de"))
{
goto IL_03fb;
}
return "de_DE";
case 'f':
if (!(text == "fr"))
{
goto IL_03fb;
}
return "fr_FR";
case 'i':
if (!(text == "it"))
{
goto IL_03fb;
}
return "it_IT";
case 'j':
if (!(text == "ja"))
{
goto IL_03fb;
}
return "ja_JP";
case 'k':
if (!(text == "ko"))
{
goto IL_03fb;
}
return "ko_KR";
case 'n':
if (!(text == "nl"))
{
goto IL_03fb;
}
return "nl_NL";
case 'p':
goto IL_0218;
case 'r':
if (!(text == "ru"))
{
goto IL_03fb;
}
return "ru_RU";
case 's':
goto IL_0252;
case 't':
goto IL_0277;
case 'u':
if (!(text == "uk"))
{
goto IL_03fb;
}
return "uk_UA";
default:
goto IL_03fb;
}
switch (text)
{
case "en":
break;
case "el":
return "el_GR";
case "es":
return "es_ES";
default:
goto IL_03fb;
}
goto IL_037d;
}
}
else if (length != 5)
{
if (length == 7)
{
char c = text[6];
if (c != 's')
{
if (c == 't' && text == "zh_Hant")
{
goto IL_0389;
}
}
else if (text == "zh_Hans")
{
goto IL_0383;
}
}
}
else
{
switch (text[3])
{
case 'U':
break;
case 'G':
goto IL_02c6;
case 'C':
goto IL_02db;
case 'T':
goto IL_02f0;
case 'H':
goto IL_0305;
case 'M':
goto IL_0317;
case 'B':
goto IL_0329;
case 'P':
if (!(text == "pt_PT"))
{
goto IL_03fb;
}
return "pt_PT";
default:
goto IL_03fb;
}
if (text == "en_US")
{
goto IL_037d;
}
}
}
goto IL_03fb;
IL_0252:
if (!(text == "sk"))
{
if (!(text == "sv"))
{
goto IL_03fb;
}
return "sv_SE";
}
return "sk_SK";
IL_0218:
if (!(text == "pl"))
{
if (text == "pt")
{
goto IL_03cb;
}
goto IL_03fb;
}
return "pl_PL";
IL_0170:
if (text == "zh")
{
goto IL_0383;
}
goto IL_03fb;
IL_0389:
return "zh_TW";
IL_0383:
return "zh_CN";
IL_0277:
if (!(text == "th"))
{
if (!(text == "tr"))
{
goto IL_03fb;
}
return "tr_TR";
}
return "th_TH";
IL_02c6:
if (text == "en_GB")
{
goto IL_037d;
}
goto IL_03fb;
IL_02db:
if (text == "zh_CN")
{
goto IL_0383;
}
goto IL_03fb;
IL_02f0:
if (text == "zh_TW")
{
goto IL_0389;
}
goto IL_03fb;
IL_0305:
if (text == "zh_HK")
{
goto IL_0389;
}
goto IL_03fb;
IL_0317:
if (text == "zh_MO")
{
goto IL_0389;
}
goto IL_03fb;
IL_0329:
if (text == "pt_BR")
{
goto IL_03cb;
}
goto IL_03fb;
IL_03fb:
return text;
IL_037d:
return "en";
IL_03cb:
return "pt_BR";
}
internal static void OnGameLocalizationLoaded(string locale)
{
Apply(NormalizeLocale(locale), notify: true);
}
private static void RegisterBundle(string sourceId, Dictionary<string, Dictionary<string, string>> bundle)
{
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: 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_007f: 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 text = null;
try
{
object obj = typeof(Globals).GetField("ContentManager")?.GetValue(null);
text = obj?.GetType().GetProperty("RootDirectory")?.GetValue(obj) as string;
}
catch
{
}
if (string.IsNullOrWhiteSpace(text))
{
yield break;
}
string path = Path.Combine(text, "localization");
if (!Directory.Exists(path))
{
yield break;
}
string[] files = Directory.GetFiles(path, "locale_*");
for (int i = 0; i < files.Length; i++)
{
string fileName = Path.GetFileName(files[i]);
if (fileName != null && fileName.Length > "locale_".Length)
{
yield return NormalizeLocale(fileName.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";
}
if (!fileNameWithoutExtension.StartsWith("locale_", StringComparison.OrdinalIgnoreCase))
{
return NormalizeLocale(fileNameWithoutExtension);
}
return NormalizeLocale(fileNameWithoutExtension.Substring("locale_".Length));
}
private static bool IsLocaleName(string value)
{
string text = NormalizeLocale(value);
string[] known = RomesteadLocales.Known;
foreach (string b in known)
{
if (string.Equals(text, b, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
if (text.Length != 2)
{
if (text.Length >= 5)
{
return text[2] == '_';
}
return false;
}
return true;
}
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)
{
if (!key.StartsWith(sourceId + ".", StringComparison.Ordinal))
{
return sourceId + "." + key;
}
return 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);
}
}
}