using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using Febucci.UI;
using Febucci.UI.Core;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.LowLevel;
using UnityEngine.PlayerLoop;
using UnityEngine.UI;
using WKMSTranslation.Core;
using WKMSTranslation.Utils;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("WKMSTranslation")]
[assembly: AssemblyDescription("Русификатор под White Knuckle")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Musya Team")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyFileVersion("1.3.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace WKMSTranslation
{
[BepInPlugin("com.musya.wk.translation", "WKMSTranslation", "1.3.3")]
public class Plugin : BaseUnityPlugin
{
private void Awake()
{
string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
TranslationEngine.Initialize(directoryName);
FontManager.Initialize(((BaseUnityPlugin)this).Logger, directoryName);
Exporter.Initialize(directoryName);
Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, (string)null);
PlayerLoopHelper.Inject(typeof(Plugin), MyUpdate);
}
private void MyUpdate()
{
if (Input.GetKeyDown((KeyCode)290))
{
TranslationEngine.IsEnabled = !TranslationEngine.IsEnabled;
RefreshUI(forceReset: true);
}
if (Input.GetKeyDown((KeyCode)291))
{
TranslationEngine.Load();
RefreshUI(forceReset: false);
}
if (Input.GetKeyDown((KeyCode)292))
{
Exporter.Save();
}
}
private void RefreshUI(bool forceReset)
{
TextProcessor.IsPatching = true;
TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
foreach (TMP_Text val in array)
{
if (!((Component)val).gameObject.activeInHierarchy || !IsSafe((Component)(object)val))
{
continue;
}
string original = TranslationEngine.GetOriginal(val, val.text);
string text = (TranslationEngine.IsEnabled ? TranslationEngine.GetTranslation(original) : original);
TAnimCore component = ((Component)val).GetComponent<TAnimCore>();
if ((Object)(object)component != (Object)null)
{
if (HasTypewriter((Component)(object)val))
{
continue;
}
if (TranslationEngine.IsAssignedTranslation(val, text))
{
if (TranslationEngine.IsEnabled)
{
FontManager.TryReplace(val);
}
continue;
}
TranslationEngine.SetAssignedTranslation(val, text);
component.textFull = text;
if (TranslationEngine.IsEnabled)
{
FontManager.TryReplace(val);
}
continue;
}
if (TranslationEngine.IsAssignedTranslation(val, text))
{
if (TranslationEngine.IsEnabled)
{
FontManager.TryReplace(val);
if (TranslationEngine.IsFitRequired(original.GetExactKey()))
{
TextProcessor.FitTMP(val);
}
}
continue;
}
TranslationEngine.SetAssignedTranslation(val, text);
val.text = text;
if (TranslationEngine.IsEnabled)
{
FontManager.TryReplace(val);
if (TranslationEngine.IsFitRequired(original.GetExactKey()))
{
TextProcessor.FitTMP(val);
}
}
val.ForceMeshUpdate(true, true);
}
Text[] array2 = Resources.FindObjectsOfTypeAll<Text>();
foreach (Text val2 in array2)
{
if (!((Component)val2).gameObject.activeInHierarchy || !IsSafe((Component)(object)val2))
{
continue;
}
string original2 = TranslationEngine.GetOriginal(val2, val2.text);
string text2 = (TranslationEngine.IsEnabled ? TranslationEngine.GetTranslation(original2) : original2);
if (TranslationEngine.IsAssignedTranslation(val2, text2))
{
if (TranslationEngine.IsEnabled && TranslationEngine.IsFitRequired(original2.GetExactKey()))
{
FitLegacyTextManually(val2);
}
continue;
}
TranslationEngine.SetAssignedTranslation(val2, text2);
val2.text = text2;
if (TranslationEngine.IsEnabled && TranslationEngine.IsFitRequired(original2.GetExactKey()))
{
FitLegacyTextManually(val2);
}
((Behaviour)val2).enabled = false;
((Behaviour)val2).enabled = true;
try
{
val2.FontTextureChanged();
}
catch
{
}
}
InputField[] array3 = Resources.FindObjectsOfTypeAll<InputField>();
foreach (InputField val3 in array3)
{
if (((Component)val3).gameObject.activeInHierarchy)
{
string original3 = TranslationEngine.GetOriginal(val3, val3.text);
string text3 = (TranslationEngine.IsEnabled ? TranslationEngine.GetTranslation(original3) : original3);
if (!TranslationEngine.IsAssignedTranslation(val3, text3))
{
TranslationEngine.SetAssignedTranslation(val3, text3);
val3.text = text3;
}
}
}
TMP_InputField[] array4 = Resources.FindObjectsOfTypeAll<TMP_InputField>();
foreach (TMP_InputField val4 in array4)
{
if (((Component)val4).gameObject.activeInHierarchy)
{
string original4 = TranslationEngine.GetOriginal(val4, val4.text);
string text4 = (TranslationEngine.IsEnabled ? TranslationEngine.GetTranslation(original4) : original4);
if (!TranslationEngine.IsAssignedTranslation(val4, text4))
{
TranslationEngine.SetAssignedTranslation(val4, text4);
val4.text = text4;
}
}
}
TextProcessor.IsPatching = false;
}
private void FitLegacyTextManually(Text t)
{
if ((Object)(object)t == (Object)null)
{
return;
}
try
{
ContentSizeFitter component = ((Component)t).GetComponent<ContentSizeFitter>();
if ((Object)(object)component != (Object)null)
{
component.horizontalFit = (FitMode)0;
}
t.horizontalOverflow = (HorizontalWrapMode)0;
t.verticalOverflow = (VerticalWrapMode)0;
if (!t.resizeTextForBestFit)
{
t.resizeTextMinSize = Mathf.Max(1, Mathf.RoundToInt((float)t.fontSize * 0.4f));
t.resizeTextMaxSize = t.fontSize;
t.resizeTextForBestFit = true;
}
}
catch
{
}
}
private bool HasTypewriter(Component c)
{
if ((Object)(object)c == (Object)null || (Object)(object)c.gameObject == (Object)null)
{
return false;
}
Component[] components = c.gameObject.GetComponents<Component>();
foreach (Component val in components)
{
if ((Object)(object)val != (Object)null && ((object)val).GetType().Name.Contains("Typewriter"))
{
return true;
}
}
return false;
}
private bool IsSafe(Component c)
{
UT_TextScrawl val = c.GetComponentInParent<UT_TextScrawl>() ?? c.GetComponent<UT_TextScrawl>();
if ((Object)(object)val == (Object)null)
{
return true;
}
FieldInfo field = typeof(UT_TextScrawl).GetField("typing", BindingFlags.Instance | BindingFlags.NonPublic);
return field == null || (bool)field.GetValue(val);
}
}
}
namespace WKMSTranslation.Utils
{
public static class Extensions
{
public static string GetExactKey(this string str)
{
if (string.IsNullOrEmpty(str))
{
return string.Empty;
}
return str.Replace("\r\n", "\\n").Replace("\n", "\\n").Replace("\r", "")
.Replace("\0", "")
.Replace("\u200b", "")
.Replace("\u00a0", "")
.Replace("<noparse></noparse>", "")
.Trim();
}
}
public static class PlayerLoopHelper
{
public static void Inject(Type ownerType, Action updateAction)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_010f: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Expected O, but got Unknown
//IL_00fa: Expected O, but got Unknown
PlayerLoopSystem currentPlayerLoop = PlayerLoop.GetCurrentPlayerLoop();
UpdateFunction val2 = default(UpdateFunction);
for (int i = 0; i < currentPlayerLoop.subSystemList.Length; i++)
{
if (!(currentPlayerLoop.subSystemList[i].type == typeof(Update)))
{
continue;
}
List<PlayerLoopSystem> list = new List<PlayerLoopSystem>();
if (currentPlayerLoop.subSystemList[i].subSystemList != null)
{
list.AddRange(currentPlayerLoop.subSystemList[i].subSystemList);
}
foreach (PlayerLoopSystem item2 in list)
{
if (item2.type == ownerType)
{
return;
}
}
PlayerLoopSystem val = new PlayerLoopSystem
{
type = ownerType
};
UpdateFunction obj = val2;
if (obj == null)
{
UpdateFunction val3 = delegate
{
updateAction();
};
UpdateFunction val4 = val3;
val2 = val3;
obj = val4;
}
val.updateDelegate = obj;
PlayerLoopSystem item = val;
list.Add(item);
currentPlayerLoop.subSystemList[i].subSystemList = list.ToArray();
PlayerLoop.SetPlayerLoop(currentPlayerLoop);
Debug.Log((object)("[WKMSTranslation] PlayerLoop injected successfully for " + ownerType.Name));
break;
}
}
}
}
namespace WKMSTranslation.Hooks
{
public static class ThirdPartyHooks
{
[HarmonyPatch(typeof(UT_TextScrawl), "ShowText")]
public static class ScrawlHook
{
[HarmonyPrefix]
public static void Prefix(ref string s)
{
if (!string.IsNullOrWhiteSpace(s))
{
s = TranslationEngine.GetTranslation(s);
}
ThirdPartyDepth++;
}
[HarmonyFinalizer]
public static void Finalizer()
{
ThirdPartyDepth--;
}
}
[HarmonyPatch(typeof(TypewriterCore), "ShowText", new Type[] { typeof(string) })]
public static class TypewriterCore_ShowText_Hook
{
[HarmonyPrefix]
public static void Prefix(ref string text)
{
if (!string.IsNullOrWhiteSpace(text))
{
text = TranslationEngine.GetTranslation(text);
}
ThirdPartyDepth++;
}
[HarmonyFinalizer]
public static void Finalizer()
{
ThirdPartyDepth--;
}
}
[HarmonyPatch(typeof(TAnimCore), "ConvertText")]
public static class TAnimCore_ConvertText_Hook
{
[HarmonyPrefix]
public static void Prefix(ref string textToParse)
{
if (!string.IsNullOrWhiteSpace(textToParse))
{
textToParse = TranslationEngine.GetTranslation(textToParse);
}
ThirdPartyDepth++;
}
[HarmonyFinalizer]
public static void Finalizer()
{
ThirdPartyDepth--;
}
}
[HarmonyPatch(typeof(TextAnimator_TMP), "SetTextToSource")]
public static class TextAnimator_SetText_Hook
{
[HarmonyPrefix]
public static void Prefix()
{
ThirdPartyDepth++;
}
[HarmonyFinalizer]
public static void Finalizer(TextAnimator_TMP __instance)
{
ThirdPartyDepth--;
if ((Object)(object)__instance != (Object)null && (Object)(object)__instance.TMProComponent != (Object)null && TranslationEngine.IsEnabled)
{
FontManager.TryReplace(__instance.TMProComponent);
}
}
}
[ThreadStatic]
public static int ThirdPartyDepth;
}
[HarmonyPatch]
public static class UnityHooks
{
[HarmonyPatch(typeof(TextMeshProUGUI), "Awake")]
[HarmonyPostfix]
public static void UGUI_Awake(TextMeshProUGUI __instance)
{
SyncTMP((TMP_Text)(object)__instance);
}
[HarmonyPatch(typeof(TextMeshProUGUI), "OnEnable")]
[HarmonyPostfix]
public static void UGUI_Enable(TextMeshProUGUI __instance)
{
SyncTMP((TMP_Text)(object)__instance);
}
[HarmonyPatch(typeof(TextMeshPro), "Awake")]
[HarmonyPostfix]
public static void World_Awake(TextMeshPro __instance)
{
SyncTMP((TMP_Text)(object)__instance);
}
[HarmonyPatch(typeof(TextMeshPro), "OnEnable")]
[HarmonyPostfix]
public static void World_Enable(TextMeshPro __instance)
{
SyncTMP((TMP_Text)(object)__instance);
}
[HarmonyPatch(typeof(Text), "OnEnable")]
[HarmonyPostfix]
public static void Legacy_Enable(Text __instance)
{
SyncLegacy(__instance);
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPrefix]
public static void TMP_Setter_Prefix(TMP_Text __instance, ref string value)
{
if (ThirdPartyHooks.ThirdPartyDepth <= 0)
{
TextProcessor.Process(__instance, ref value);
}
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPrefix]
public static void Legacy_Setter_Prefix(Text __instance, ref string value)
{
TextProcessor.Process(__instance, ref value);
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPostfix]
public static void Legacy_Setter_Postfix(Text __instance)
{
TextProcessor.PostProcess(__instance);
try
{
if (__instance != null)
{
__instance.FontTextureChanged();
}
}
catch
{
}
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPrefix]
public static void LegacyInputField_Setter_Prefix(InputField __instance, ref string value)
{
if (ThirdPartyHooks.ThirdPartyDepth <= 0)
{
TextProcessor.Process(__instance, ref value);
}
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPrefix]
public static void TMPInputField_Setter_Prefix(TMP_InputField __instance, ref string value)
{
if (ThirdPartyHooks.ThirdPartyDepth <= 0)
{
TextProcessor.Process(__instance, ref value);
}
}
private static void SyncTMP(TMP_Text component)
{
if (!((Object)(object)component == (Object)null))
{
string text = component.text;
TextProcessor.Process(component, ref text);
if (text != component.text)
{
TextProcessor.IsPatching = true;
component.text = text;
TextProcessor.IsPatching = false;
}
TextProcessor.PostProcess(component);
}
}
private static void SyncLegacy(Text component)
{
if ((Object)(object)component == (Object)null)
{
return;
}
string text = component.text;
TextProcessor.Process(component, ref text);
if (text != component.text)
{
TextProcessor.IsPatching = true;
component.text = text;
TextProcessor.IsPatching = false;
}
TextProcessor.PostProcess(component);
try
{
component.FontTextureChanged();
}
catch
{
}
}
}
}
namespace WKMSTranslation.Core
{
public static class Exporter
{
private static string _folder = "";
private static readonly HashSet<string> _exported = new HashSet<string>(StringComparer.Ordinal);
private static readonly Regex _numFinder = new Regex("\\d+(?:[.,]\\d+)?", RegexOptions.Compiled);
private static readonly Regex _ghostFilter = new Regex("[a-zA-Z]\\d+$", RegexOptions.Compiled);
private static readonly Regex _gameTokenFinder = new Regex("\\{[a-zA-Z_][a-zA-Z0-9_]*\\}", RegexOptions.Compiled);
private static readonly Regex _garbageFilter = new Regex("^[.\\-_~=\\s\\/\\\\|:;()\\[\\]{}*+?!@#$%^&<>,\"']*$", RegexOptions.Compiled);
private static readonly HashSet<string> _ignoredKeywords = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Shift", "Tab", "Space", "Ctrl", "Alt", "Enter", "Escape", "Caps", "Backspace", "LMB",
"RMB", "MMB", "Wheel", "WheelUp", "WheelDown", "M4", "M5", "Up", "Down", "Left",
"Right", "W", "A", "S", "D", "Insert", "Delete", "Home", "End", "PageUp",
"PageDown", "PrintScreen", "ScrollLock", "Pause", "NumLock", "NumSlash", "NumStar", "NumMinus", "NumPlus", "NumEnter",
"Num0", "Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9",
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",
"F11", "F12", "Win", "Cmd", "Fn", "Tilde", "LB", "RB", "LT", "RT",
"L1", "R1", "L2", "R2", "L3", "R3", "D-PadUp", "D-PadDown", "D-PadLeft", "D-PadRight",
"A", "B", "X", "Y", "Cross", "Circle", "Square", "Triangle", "LS", "RS",
"LS-Click", "RS-Click", "LeftStick", "RightStick", "Start", "Select", "Back", "Options", "Share", "Menu",
"View", "Guide", "Home", "Touchpad"
};
public static void Initialize(string path)
{
_folder = path;
}
public static void Register(string text)
{
if (string.IsNullOrWhiteSpace(text) || Regex.IsMatch(text, "[а-яА-Я]"))
{
return;
}
string exactKey = text.GetExactKey();
if (exactKey.Length <= 1 || _garbageFilter.IsMatch(exactKey) || (exactKey.StartsWith("<") && exactKey.EndsWith(">") && !exactKey.Contains(" ")) || _ignoredKeywords.Contains(exactKey) || Regex.IsMatch(exactKey, "^[+-]?\\d+(?:[.,]\\d+)?$") || Regex.IsMatch(exactKey, "^\\d{1,2}(?::\\d{1,2}){1,3}$") || _ghostFilter.IsMatch(exactKey) || _gameTokenFinder.IsMatch(exactKey) || TranslationEngine.IsTranslated(text))
{
return;
}
string text2 = ConvertToTemplate(exactKey);
if (TranslationEngine.IsTranslated(text2))
{
return;
}
lock (_exported)
{
_exported.Add(text2);
}
}
private static string ConvertToTemplate(string text)
{
if (string.IsNullOrEmpty(text))
{
return text;
}
if (!Regex.IsMatch(text, "\\d"))
{
return text;
}
int index = 0;
return _numFinder.Replace(text, (Match m) => $"{{{index++}}}");
}
public static void Save()
{
CollectFromMemory();
try
{
if (string.IsNullOrEmpty(_folder))
{
return;
}
Directory.CreateDirectory(_folder);
string path = Path.Combine(_folder, "DumpedTexts.json");
Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
if (File.Exists(path))
{
try
{
Dictionary<string, string> dictionary2 = JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(path));
if (dictionary2 != null)
{
dictionary = dictionary2;
}
}
catch
{
}
}
int num = 0;
lock (_exported)
{
foreach (string item in _exported)
{
if (!dictionary.ContainsKey(item) && !TranslationEngine.IsTranslatedDeep(item))
{
dictionary[item] = "";
num++;
}
}
}
File.WriteAllText(path, JsonConvert.SerializeObject((object)dictionary, (Formatting)1));
Debug.Log((object)$"[Exporter] Saved {num} new strings. Total: {dictionary.Count}");
}
catch (Exception ex)
{
Debug.LogError((object)ex);
}
}
private static void CollectFromMemory()
{
try
{
TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
foreach (TMP_Text val in array)
{
if (((Component)val).gameObject.activeInHierarchy && !string.IsNullOrEmpty(val.text))
{
Register(val.text);
}
}
Text[] array2 = Resources.FindObjectsOfTypeAll<Text>();
foreach (Text val2 in array2)
{
if (((Component)val2).gameObject.activeInHierarchy && !string.IsNullOrEmpty(val2.text))
{
Register(val2.text);
}
}
}
catch
{
}
}
}
public static class FontManager
{
private static readonly Dictionary<string, TMP_FontAsset> _tmpCache = new Dictionary<string, TMP_FontAsset>(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<string, Font> _legacyCache = new Dictionary<string, Font>(StringComparer.OrdinalIgnoreCase);
private static ManualLogSource _log;
public static void Initialize(ManualLogSource log, string path)
{
_log = log;
string text = Path.Combine(path, "customfonts");
if (!File.Exists(text))
{
return;
}
AssetBundle val = AssetBundle.LoadFromFile(text);
if (!((Object)(object)val == (Object)null))
{
TMP_FontAsset[] array = val.LoadAllAssets<TMP_FontAsset>();
foreach (TMP_FontAsset val2 in array)
{
string text2 = ((Object)val2).name.Trim();
_tmpCache[text2] = val2;
_log.LogInfo((object)("Loaded TMP font: " + text2));
}
Font[] array2 = val.LoadAllAssets<Font>();
foreach (Font val3 in array2)
{
string text3 = ((Object)val3).name.Trim();
_legacyCache[text3] = val3;
_log.LogInfo((object)("Loaded Legacy font: " + text3));
}
val.Unload(false);
}
}
public static void TryReplace(TMP_Text text)
{
if (!((Object)(object)text == (Object)null) && _tmpCache.Count != 0)
{
string key = (((Object)(object)text.font != (Object)null) ? ((Object)text.font).name.Trim() : "");
if ((_tmpCache.TryGetValue(key, out TMP_FontAsset value) || _tmpCache.TryGetValue("default", out value)) && (Object)(object)text.font != (Object)(object)value)
{
text.font = value;
}
}
}
public static void TryReplace(Text text)
{
if (!((Object)(object)text == (Object)null) && _legacyCache != null && _legacyCache.Count != 0)
{
string key = (((Object)(object)text.font != (Object)null) ? ((Object)text.font).name.Trim() : "");
if ((_legacyCache.TryGetValue(key, out Font value) || _legacyCache.TryGetValue("default", out value)) && (Object)(object)text.font != (Object)(object)value)
{
text.font = value;
}
}
}
}
public static class TextProcessor
{
[ThreadStatic]
public static bool IsPatching;
[ThreadStatic]
private static bool _tmpNeedsFit;
public static void Process(object component, ref string text)
{
if (IsPatching || component == null || string.IsNullOrWhiteSpace(text) || !Regex.IsMatch(text, "[a-zA-Zа-яА-ЯёЁ]") || TranslationEngine.IsAssignedTranslation(component, text))
{
return;
}
if (!TranslationEngine.RegisterOriginal(component, text))
{
TranslationEngine.SetAssignedTranslation(component, text);
ReplaceFontSafe(component);
}
else if (TranslationEngine.IsEnabled)
{
string original = TranslationEngine.GetOriginal(component, text);
string translation = TranslationEngine.GetTranslation(original);
if (!(translation == original) && !(translation == text) && (!translation.Contains("{0}") || original.Contains("{0}")))
{
text = translation;
TranslationEngine.SetAssignedTranslation(component, text);
_tmpNeedsFit = TranslationEngine.IsFitRequired(original.GetExactKey());
ReplaceFontSafe(component);
}
}
}
public static void PostProcess(object component)
{
if (!_tmpNeedsFit || component == null)
{
return;
}
_tmpNeedsFit = false;
try
{
IsPatching = true;
TMP_Text val = (TMP_Text)((component is TMP_Text) ? component : null);
if (val != null)
{
if ((Object)(object)((Component)val).GetComponent<TAnimCore>() == (Object)null)
{
FitTMP(val);
}
return;
}
Text val2 = (Text)((component is Text) ? component : null);
if (val2 != null)
{
FitLegacy(val2);
return;
}
InputField val3 = (InputField)((component is InputField) ? component : null);
if (val3 != null && (Object)(object)val3.textComponent != (Object)null)
{
FitLegacy(val3.textComponent);
return;
}
TMP_InputField val4 = (TMP_InputField)((component is TMP_InputField) ? component : null);
if (val4 != null && (Object)(object)val4.textComponent != (Object)null && (Object)(object)((Component)val4.textComponent).GetComponent<TAnimCore>() == (Object)null)
{
FitTMP(val4.textComponent);
}
}
finally
{
IsPatching = false;
}
}
private static void ReplaceFontSafe(object component)
{
TMP_Text val = (TMP_Text)((component is TMP_Text) ? component : null);
if (val != null)
{
FontManager.TryReplace(val);
return;
}
Text val2 = (Text)((component is Text) ? component : null);
if (val2 != null)
{
FontManager.TryReplace(val2);
return;
}
InputField val3 = (InputField)((component is InputField) ? component : null);
if (val3 != null && (Object)(object)val3.textComponent != (Object)null)
{
FontManager.TryReplace(val3.textComponent);
return;
}
TMP_InputField val4 = (TMP_InputField)((component is TMP_InputField) ? component : null);
if (val4 != null && (Object)(object)val4.textComponent != (Object)null)
{
FontManager.TryReplace(val4.textComponent);
}
}
public static void FitTMP(TMP_Text t)
{
if ((Object)(object)t == (Object)null)
{
return;
}
try
{
t.enableWordWrapping = false;
ContentSizeFitter component = ((Component)t).GetComponent<ContentSizeFitter>();
if ((Object)(object)component != (Object)null)
{
component.horizontalFit = (FitMode)0;
}
if (!t.enableAutoSizing)
{
t.fontSizeMin = Mathf.Max(4f, t.fontSize * 0.4f);
t.fontSizeMax = t.fontSize;
t.enableAutoSizing = true;
}
t.overflowMode = (TextOverflowModes)0;
t.ForceMeshUpdate(true, false);
}
catch
{
}
}
private static void FitLegacy(Text t)
{
if ((Object)(object)t == (Object)null)
{
return;
}
try
{
ContentSizeFitter component = ((Component)t).GetComponent<ContentSizeFitter>();
if ((Object)(object)component != (Object)null)
{
component.horizontalFit = (FitMode)0;
}
t.horizontalOverflow = (HorizontalWrapMode)0;
t.verticalOverflow = (VerticalWrapMode)0;
if (!t.resizeTextForBestFit)
{
t.resizeTextMinSize = Mathf.Max(1, Mathf.RoundToInt((float)t.fontSize * 0.4f));
t.resizeTextMaxSize = t.fontSize;
t.resizeTextForBestFit = true;
}
}
catch
{
}
}
}
public static class TranslationEngine
{
private class TemplateEntry
{
public Regex CompiledRegex;
public string TranslationTemplate;
public string OriginalPattern;
public List<string> GroupPlaceholders;
public string AnchorAnchorText;
}
private class SampleTemplateEntry
{
public string OriginalKey;
public Regex CompiledRegex;
public string TranslationTemplate;
public List<string> Placeholders;
public bool IsAtomic;
public bool IsLiteral;
public string AnchorAnchorText;
}
private class SampleGroupEntry
{
public List<string> Headers = new List<string>();
public List<SampleTemplateEntry> Rules = new List<SampleTemplateEntry>();
}
private class SampleREntry
{
public int RequiredGroupCount;
public List<SampleTemplateEntry> MandatoryRules = new List<SampleTemplateEntry>();
public Dictionary<int, List<SampleTemplateEntry>> IndexedRules = new Dictionary<int, List<SampleTemplateEntry>>();
}
private static string _lastPath = "";
private static readonly HashSet<string> _allKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private static readonly HashSet<string> _allValues = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<string, string> _exact = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
private static readonly List<TemplateEntry> _templates = new List<TemplateEntry>();
private static readonly ConditionalWeakTable<object, string> _originals = new ConditionalWeakTable<object, string>();
private static readonly HashSet<string> _fitKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<string, string> _cache = new Dictionary<string, string>(StringComparer.Ordinal);
private static readonly ConditionalWeakTable<object, string> _assignedTranslations = new ConditionalWeakTable<object, string>();
private static readonly List<SampleTemplateEntry> _sampleTemplates = new List<SampleTemplateEntry>();
private static readonly List<SampleGroupEntry> _groupTemplates = new List<SampleGroupEntry>();
private static readonly List<SampleREntry> _conditionalTemplates = new List<SampleREntry>();
public static bool IsEnabled { get; set; } = true;
public static void Initialize(string path)
{
_lastPath = path;
Load();
}
public static void Load()
{
_exact.Clear();
_templates.Clear();
_allKeys.Clear();
_allValues.Clear();
_fitKeys.Clear();
_cache.Clear();
_sampleTemplates.Clear();
_groupTemplates.Clear();
_conditionalTemplates.Clear();
if (!Directory.Exists(_lastPath))
{
Directory.CreateDirectory(_lastPath);
}
string[] files = Directory.GetFiles(_lastPath, "*.json");
foreach (string path in files)
{
if (Path.GetFileName(path).Equals("DumpedTexts.json", StringComparison.OrdinalIgnoreCase))
{
continue;
}
try
{
JObject val = JObject.Parse(File.ReadAllText(path));
foreach (JProperty item in val.Properties())
{
ProcessToken(item.Value, item.Name);
}
}
catch
{
}
}
_sampleTemplates.Sort((SampleTemplateEntry a, SampleTemplateEntry b) => (a.IsAtomic != b.IsAtomic) ? a.IsAtomic.CompareTo(b.IsAtomic) : b.TranslationTemplate.Length.CompareTo(a.TranslationTemplate.Length));
Debug.Log((object)$"[WKTranslator] Loaded {_exact.Count} exact, {_templates.Count} templates, {_sampleTemplates.Count} samples, {_groupTemplates.Count} groups.");
}
private static void ProcessToken(JToken token, string keyName)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Invalid comparison between Unknown and I4
//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
//IL_01ca: Invalid comparison between Unknown and I4
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
//IL_032d: Unknown result type (might be due to invalid IL or missing references)
//IL_0333: Invalid comparison between Unknown and I4
//IL_0341: Unknown result type (might be due to invalid IL or missing references)
//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
//IL_03c2: Invalid comparison between Unknown and I4
//IL_0428: Unknown result type (might be due to invalid IL or missing references)
//IL_042e: Invalid comparison between Unknown and I4
//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
if (keyName.StartsWith("sampleR", StringComparison.OrdinalIgnoreCase) && (int)token.Type == 1)
{
SampleREntry sampleREntry = new SampleREntry();
Match match = Regex.Match(keyName, "\\d+");
sampleREntry.RequiredGroupCount = (match.Success ? int.Parse(match.Value) : 2);
foreach (JProperty item4 in ((JObject)token).Properties())
{
string name = item4.Name;
string text = ((object)item4.Value).ToString();
if (name.StartsWith("request:", StringComparison.OrdinalIgnoreCase))
{
string exactKey = name.Substring(8).GetExactKey();
sampleREntry.MandatoryRules.Add(CreateSampleEntry(exactKey, text));
continue;
}
Match match2 = Regex.Match(name, "^request(\\d+):(.*)", RegexOptions.IgnoreCase);
if (match2.Success)
{
int key = int.Parse(match2.Groups[1].Value);
string exactKey2 = match2.Groups[2].Value.GetExactKey();
SampleTemplateEntry sampleTemplateEntry = CreateSampleEntry(exactKey2, text);
if (!sampleREntry.IndexedRules.ContainsKey(key))
{
sampleREntry.IndexedRules[key] = new List<SampleTemplateEntry>();
}
sampleREntry.IndexedRules[key].Add(sampleTemplateEntry);
if (!string.IsNullOrWhiteSpace(text))
{
_allKeys.Add(sampleTemplateEntry.OriginalKey);
}
}
}
_conditionalTemplates.Add(sampleREntry);
return;
}
if (keyName.StartsWith("sampleG:", StringComparison.OrdinalIgnoreCase) && (int)token.Type == 1)
{
SampleGroupEntry sampleGroupEntry = new SampleGroupEntry();
foreach (JProperty item5 in ((JObject)token).Properties())
{
if (item5.Name.StartsWith("header:", StringComparison.OrdinalIgnoreCase))
{
string exactKey3 = item5.Name.Substring(7).GetExactKey();
string item = (exactKey3.StartsWith("tag:", StringComparison.OrdinalIgnoreCase) ? exactKey3.Substring(4) : exactKey3);
sampleGroupEntry.Headers.Add(item);
if (!string.IsNullOrEmpty(((object)item5.Value).ToString()))
{
SampleTemplateEntry sampleTemplateEntry2 = CreateSampleEntry(exactKey3, ((object)item5.Value).ToString());
sampleGroupEntry.Rules.Add(sampleTemplateEntry2);
_allKeys.Add(sampleTemplateEntry2.OriginalKey);
}
}
else
{
SampleTemplateEntry sampleTemplateEntry3 = CreateSampleEntry(item5.Name, ((object)item5.Value).ToString());
sampleGroupEntry.Rules.Add(sampleTemplateEntry3);
_allKeys.Add(sampleTemplateEntry3.OriginalKey);
}
}
_groupTemplates.Add(sampleGroupEntry);
return;
}
if (keyName.StartsWith("sample:", StringComparison.OrdinalIgnoreCase) && (int)token.Type == 1)
{
foreach (JProperty item6 in ((JObject)token).Properties())
{
SampleTemplateEntry item2 = CreateSampleEntry(item6.Name, ((object)item6.Value).ToString());
_sampleTemplates.Add(item2);
}
return;
}
string exactKey4 = keyName.GetExactKey();
if (string.IsNullOrEmpty(exactKey4))
{
return;
}
if ((int)token.Type == 1)
{
_allKeys.Add(exactKey4);
{
foreach (JProperty item7 in ((JObject)token).Properties())
{
ProcessToken(item7.Value, item7.Name);
}
return;
}
}
if ((int)token.Type != 8)
{
return;
}
string text2 = ((object)token).ToString().Trim();
if (string.IsNullOrEmpty(text2))
{
return;
}
if (text2.StartsWith("sample:", StringComparison.OrdinalIgnoreCase))
{
SampleTemplateEntry item3 = CreateSampleEntry(keyName, text2.Substring(7).Trim());
_sampleTemplates.Add(item3);
return;
}
if (text2.StartsWith("fit:", StringComparison.OrdinalIgnoreCase))
{
text2 = text2.Substring(4).Trim();
_fitKeys.Add(exactKey4);
}
_allKeys.Add(exactKey4);
_allValues.Add(text2.GetExactKey());
if (Regex.IsMatch(exactKey4, "\\{#?\\d+\\}"))
{
AddTemplate(keyName, text2);
}
else
{
_exact[exactKey4] = text2;
}
}
private static SampleTemplateEntry CreateSampleEntry(string key, string val)
{
string text = key.GetExactKey();
bool flag = false;
if (text.StartsWith("tag:", StringComparison.OrdinalIgnoreCase))
{
flag = true;
text = text.Substring(4);
}
List<string> list = new List<string>();
foreach (Match item in Regex.Matches(text, "\\{(\\d+)\\}"))
{
list.Add(item.Groups[1].Value);
}
bool flag2 = list.Count == 0;
string input = Regex.Escape(text);
input = Regex.Replace(input, "\\\\\\{\\d+\\}", "(.+?)");
if (flag2 && !flag)
{
string text2 = (Regex.IsMatch(text, "^\\w") ? "(?<=^|\\W|\\\\n|\\\\r)" : "");
string text3 = (Regex.IsMatch(text, "\\w$") ? "(?=\\W|$)" : "");
input = text2 + input + text3;
}
string longestStaticChunk = GetLongestStaticChunk(text);
return new SampleTemplateEntry
{
OriginalKey = text,
CompiledRegex = new Regex(input, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant),
TranslationTemplate = val,
Placeholders = list,
IsAtomic = flag2,
IsLiteral = flag,
AnchorAnchorText = longestStaticChunk
};
}
private static void AddTemplate(string key, string val)
{
try
{
string text = key.Trim();
List<string> list = new List<string>();
foreach (Match item in Regex.Matches(text, "\\{(#?\\d+)\\}"))
{
list.Add(item.Groups[1].Value);
}
string input = text;
input = Regex.Replace(input, "\\{\\#\\d+\\}", "__KEYBINDGROUP__");
input = Regex.Replace(input, "\\{\\d+\\}", "__DIGITGROUP__");
string text2 = Regex.Escape(input);
text2 = text2.Replace("\\\"", "[\"']?").Replace("\"", "[\"']?");
text2 = text2.Replace("\\'", "[\"']?").Replace("'", "[\"']?");
text2 = text2.Replace("__DIGITGROUP__", "([+-]?\\d+(?:[.,]\\d+)?)");
text2 = text2.Replace("__KEYBINDGROUP__", "([^\\n<>]+?)");
text2 = text2.Replace("\\n", "\\n").Replace("\\\\n", "(?:\\r?\\n|\\\\n)");
text2 = "^\\s*" + text2 + "\\s*$";
string longestStaticChunk = GetLongestStaticChunk(text);
_templates.Add(new TemplateEntry
{
CompiledRegex = new Regex(text2, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.CultureInvariant),
TranslationTemplate = val,
OriginalPattern = key.GetExactKey(),
GroupPlaceholders = list,
AnchorAnchorText = longestStaticChunk
});
}
catch (Exception ex)
{
Debug.LogError((object)("[TranslationEngine] Error key: " + key + ": " + ex.Message));
}
}
public static string GetTranslation(string currentText)
{
if (string.IsNullOrEmpty(currentText) || currentText.Length <= 1)
{
return currentText;
}
if (_cache.TryGetValue(currentText, out string value))
{
return value;
}
string exactKey = currentText.GetExactKey();
if (_exact.TryGetValue(exactKey, out string value2))
{
return _cache[currentText] = value2.Replace("\\n", "\n");
}
string text2 = exactKey.Replace("\\n", "\n");
foreach (TemplateEntry template in _templates)
{
if (!string.IsNullOrEmpty(template.AnchorAnchorText) && text2.IndexOf(template.AnchorAnchorText, StringComparison.OrdinalIgnoreCase) == -1)
{
continue;
}
Match match = template.CompiledRegex.Match(text2);
if (!match.Success)
{
continue;
}
bool flag = false;
for (int i = 1; i < match.Groups.Count; i++)
{
if (match.Groups[i].Value.Contains("{") || match.Groups[i].Value.Contains("}"))
{
flag = true;
break;
}
}
if (flag)
{
continue;
}
string text3 = template.TranslationTemplate;
for (int j = 1; j < match.Groups.Count; j++)
{
text3 = text3.Replace("{" + template.GroupPlaceholders[j - 1] + "}", match.Groups[j].Value);
}
if (_fitKeys.Contains(template.OriginalPattern))
{
_fitKeys.Add(exactKey);
}
return _cache[currentText] = text3.Replace("\\n", "\n");
}
string workingText = exactKey;
bool anyTranslated = false;
foreach (SampleREntry conditionalTemplate in _conditionalTemplates)
{
bool flag2 = true;
foreach (SampleTemplateEntry mandatoryRule in conditionalTemplate.MandatoryRules)
{
if (!(mandatoryRule.IsLiteral ? (workingText.IndexOf(mandatoryRule.OriginalKey, StringComparison.OrdinalIgnoreCase) != -1) : mandatoryRule.CompiledRegex.IsMatch(workingText)))
{
flag2 = false;
break;
}
}
if (!flag2)
{
continue;
}
int num = 0;
List<SampleTemplateEntry> list = new List<SampleTemplateEntry>();
foreach (KeyValuePair<int, List<SampleTemplateEntry>> indexedRule in conditionalTemplate.IndexedRules)
{
bool flag3 = false;
foreach (SampleTemplateEntry item in indexedRule.Value)
{
if (item.IsLiteral ? (workingText.IndexOf(item.OriginalKey, StringComparison.OrdinalIgnoreCase) != -1) : item.CompiledRegex.IsMatch(workingText))
{
flag3 = true;
list.Add(item);
}
}
if (flag3)
{
num++;
}
}
if (num < conditionalTemplate.RequiredGroupCount)
{
continue;
}
foreach (SampleTemplateEntry mandatoryRule2 in conditionalTemplate.MandatoryRules)
{
workingText = ApplySampleReplacement(workingText, mandatoryRule2, ref anyTranslated);
}
list.Sort((SampleTemplateEntry a, SampleTemplateEntry b) => b.OriginalKey.Length.CompareTo(a.OriginalKey.Length));
foreach (SampleTemplateEntry item2 in list)
{
workingText = ApplySampleReplacement(workingText, item2, ref anyTranslated);
}
}
foreach (SampleGroupEntry groupTemplate in _groupTemplates)
{
if (groupTemplate.Headers.Count <= 0 || !groupTemplate.Headers.Exists((string h) => workingText.IndexOf(h, StringComparison.OrdinalIgnoreCase) != -1))
{
continue;
}
foreach (SampleTemplateEntry rule in groupTemplate.Rules)
{
workingText = ApplySampleReplacement(workingText, rule, ref anyTranslated);
}
}
foreach (SampleTemplateEntry sampleTemplate in _sampleTemplates)
{
if (string.IsNullOrEmpty(sampleTemplate.AnchorAnchorText) || workingText.IndexOf(sampleTemplate.AnchorAnchorText, StringComparison.OrdinalIgnoreCase) != -1)
{
workingText = ApplySampleReplacement(workingText, sampleTemplate, ref anyTranslated);
}
}
if (anyTranslated)
{
return _cache[currentText] = workingText.Replace("\\n", "\n");
}
return _cache[currentText] = currentText;
}
public static void SetAssignedTranslation(object ui, string translatedText)
{
if (ui != null)
{
_assignedTranslations.Remove(ui);
if (!string.IsNullOrEmpty(translatedText))
{
_assignedTranslations.Add(ui, translatedText);
}
}
}
private static string ApplySampleReplacement(string input, SampleTemplateEntry sample, ref bool anyTranslated)
{
if (sample.IsLiteral)
{
if (input.IndexOf(sample.OriginalKey, StringComparison.OrdinalIgnoreCase) != -1)
{
string text = Regex.Replace(input, Regex.Escape(sample.OriginalKey), sample.TranslationTemplate.Replace("$", "$$"), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
if (text != input)
{
anyTranslated = true;
return text;
}
}
return input;
}
if (sample.IsAtomic)
{
if (input.IndexOf(sample.OriginalKey, StringComparison.OrdinalIgnoreCase) != -1)
{
string text2 = sample.CompiledRegex.Replace(input, delegate(Match m)
{
int num = m.Index - 1;
if (num >= 0 && num < input.Length)
{
int num2 = input.LastIndexOf('<', num);
int num3 = input.LastIndexOf('>', num);
if (num2 > num3)
{
return m.Value;
}
int num4 = input.LastIndexOf('{', num);
int num5 = input.LastIndexOf('}', num);
if (num4 > num5)
{
return m.Value;
}
}
return sample.TranslationTemplate;
});
if (text2 != input)
{
anyTranslated = true;
return text2;
}
}
}
else if (sample.CompiledRegex.IsMatch(input))
{
string result = sample.CompiledRegex.Replace(input, delegate(Match match)
{
string text3 = sample.TranslationTemplate;
for (int i = 1; i < match.Groups.Count; i++)
{
string text4 = sample.Placeholders[i - 1];
string newValue = match.Groups[i].Value.Trim();
text3 = text3.Replace("{" + text4 + "}", newValue);
}
return text3;
});
anyTranslated = true;
return result;
}
return input;
}
private static string GetLongestStaticChunk(string input)
{
if (string.IsNullOrEmpty(input))
{
return string.Empty;
}
string input2 = Regex.Replace(input, "<[^>]+>", " ");
input2 = Regex.Replace(input2, "\\{\\#?\\d+\\}", " ");
input2 = input2.Replace("\\n", " ").Replace("<noparse>", "").Replace("</noparse>", "");
string[] array = input2.Split(new char[6] { ' ', '\t', '.', ',', '!', '?' }, StringSplitOptions.RemoveEmptyEntries);
string text = string.Empty;
string[] array2 = array;
foreach (string text2 in array2)
{
if (text2.Length > text.Length)
{
text = text2;
}
}
return (text.Length > 3) ? text : string.Empty;
}
public static bool IsTranslated(string text)
{
if (string.IsNullOrEmpty(text))
{
return false;
}
string exactKey = text.GetExactKey();
return _allKeys.Contains(exactKey) || _exact.ContainsKey(exactKey) || _allValues.Contains(exactKey);
}
public static bool IsTranslatedDeep(string text)
{
if (IsTranslated(text))
{
return true;
}
string exactKey = text.GetExactKey();
foreach (TemplateEntry template in _templates)
{
if (template.CompiledRegex.IsMatch(text) || template.OriginalPattern == exactKey)
{
return true;
}
}
return false;
}
public static bool IsCyrillic(string text)
{
if (string.IsNullOrEmpty(text))
{
return false;
}
return Regex.IsMatch(text, "[а-яА-ЯёЁ]");
}
public static bool IsAssignedTranslation(object ui, string text)
{
if (ui == null || string.IsNullOrEmpty(text))
{
return false;
}
if (_assignedTranslations.TryGetValue(ui, out string value))
{
return value == text || value.GetExactKey() == text.GetExactKey();
}
return false;
}
public static bool RegisterOriginal(object ui, string text)
{
if (ui == null || string.IsNullOrEmpty(text))
{
return true;
}
string exactKey = text.GetExactKey();
if (_assignedTranslations.TryGetValue(ui, out string value) && value.GetExactKey() == exactKey)
{
return false;
}
if (_originals.TryGetValue(ui, out string value2) && value2.GetExactKey() == exactKey)
{
return true;
}
if (_allValues.Contains(exactKey) && !_allKeys.Contains(exactKey))
{
return false;
}
_originals.Remove(ui);
_originals.Add(ui, text);
return true;
}
public static string GetOriginal(object ui, string current)
{
string value;
return (ui != null && _originals.TryGetValue(ui, out value)) ? value : current;
}
public static bool IsFitRequired(string key)
{
return _fitKeys.Contains(key.GetExactKey());
}
}
}