Decompiled source of White Knuckle RU v3.0.1

BepInEx/plugins/WKMSTranslation/WKMSTranslation.dll

Decompiled 3 hours ago
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());
		}
	}
}