Decompiled source of TABS Korean Localization v1.0.0

TABSKorean.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("TABSKorean")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TABSKorean")]
[assembly: AssemblyTitle("TABSKorean")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 TABSKorean
{
	public static class KoreanLanguage
	{
		public const int LanguageIndex = 9;

		public static bool Enabled { get; private set; }

		public static void Enable()
		{
			Enabled = true;
		}

		public static void Disable()
		{
			Enabled = false;
		}
	}
	[HarmonyPatch(typeof(GlobalSettingsHandler), "GetSettingsInstance", new Type[] { typeof(string) })]
	internal static class GlobalSettingsHandler_GetSettingsInstance_Patch
	{
		private static void Postfix(string settingsKey, ref SettingsInstance __result)
		{
			if (__result != null && !(settingsKey != "VIDEO_LANGUAGE"))
			{
				AddKoreanOption(__result);
			}
		}

		private static void AddKoreanOption(SettingsInstance settings)
		{
			if (settings.options == null)
			{
				Plugin.Log.LogWarning((object)"VIDEO_LANGUAGE has no options array.");
			}
			else
			{
				if (settings.options.Length > 9 && settings.options[9] == "한국어")
				{
					return;
				}
				if (settings.options.Length > 9)
				{
					Plugin.Log.LogWarning((object)"VIDEO_LANGUAGE already has an option at index 9. Korean option was not overwritten.");
					return;
				}
				string[] array = new string[10];
				for (int i = 0; i < settings.options.Length; i++)
				{
					array[i] = settings.options[i];
				}
				array[9] = "한국어(Korean)";
				settings.options = array;
				Plugin.Log.LogInfo((object)"Added Korean language option to VIDEO_LANGUAGE.");
			}
		}
	}
	internal static class KoreanLanguageSwitchPath
	{
		public const int LanguageIndex = 9;

		public static bool Enabled { get; private set; }

		public static void Enable()
		{
			Enabled = true;
		}

		public static void Disable()
		{
			Enabled = false;
		}
	}
	[HarmonyPatch(typeof(Localizer), "SetLanguage")]
	internal static class Localizer_SetLanguage_Patch
	{
		private static readonly FieldInfo CallbacksField = typeof(Localizer).GetField("m_callbacks", BindingFlags.Static | BindingFlags.NonPublic);

		private static bool Prefix(Language lang)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Expected I4, but got Unknown
			int num = (int)lang;
			Plugin.Log.LogInfo((object)$"Localizer.SetLanguage called: {num}");
			if (num == 9)
			{
				KoreanLanguage.Enable();
				SetKoreanCulture();
				RefreshLocalization();
				Plugin.Log.LogInfo((object)"Korean language enabled.");
				return false;
			}
			KoreanLanguage.Disable();
			Plugin.Log.LogInfo((object)$"Korean language disabled. Using TABS language {num}.");
			return true;
		}

		private static void SetKoreanCulture()
		{
			try
			{
				CultureInfo cultureInfo = CultureInfo.GetCultureInfo("ko-KR");
				Thread.CurrentThread.CurrentCulture = cultureInfo;
				Thread.CurrentThread.CurrentUICulture = cultureInfo;
			}
			catch (CultureNotFoundException)
			{
				Plugin.Log.LogWarning((object)"Could not set Korean culture.");
			}
		}

		private static void RefreshLocalization()
		{
			if (CallbacksField == null)
			{
				Plugin.Log.LogWarning((object)"Could not find Localizer.m_callbacks.");
				return;
			}
			try
			{
				object value = CallbacksField.GetValue(null);
				if (value == null)
				{
					Plugin.Log.LogWarning((object)"Localizer.m_callbacks is null.");
					return;
				}
				if (!(value is IDictionary dictionary))
				{
					Plugin.Log.LogWarning((object)"Localizer.m_callbacks is not an IDictionary.");
					return;
				}
				List<Delegate> list = new List<Delegate>();
				foreach (DictionaryEntry item2 in dictionary)
				{
					if (item2.Value is Delegate item)
					{
						list.Add(item);
					}
				}
				Plugin.Log.LogInfo((object)$"Refreshing {list.Count} localization callbacks.");
				foreach (Delegate item3 in list)
				{
					try
					{
						item3.DynamicInvoke();
					}
					catch (Exception ex)
					{
						Plugin.Log.LogWarning((object)("Localization callback failed: " + ex.Message));
					}
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogError((object)("Failed to refresh localization: " + ex2));
			}
		}
	}
	internal static class KoreanLocalization
	{
		private static readonly Dictionary<string, string> Translations = new Dictionary<string, string>(StringComparer.Ordinal);

		private static string FilePath;

		public static int Count => Translations.Count;

		public static void Initialize()
		{
			try
			{
				string directoryName = Path.GetDirectoryName(typeof(KoreanLocalization).Assembly.Location);
				string path = Path.Combine(directoryName, "Localization");
				FilePath = Path.Combine(path, "tabs_ko_kr.txt");
				LoadFile(FilePath);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to initialize Korean localization: {arg}");
			}
		}

		private static void LoadFile(string path)
		{
			Translations.Clear();
			if (!File.Exists(path))
			{
				Plugin.Log.LogError((object)"Korean localization file was not found.");
				Plugin.Log.LogError((object)("Expected path: " + path));
				return;
			}
			string[] array = File.ReadAllLines(path, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			int num = 0;
			int num2 = 0;
			string[] array2 = array;
			foreach (string text in array2)
			{
				string text2 = text.Trim();
				if (string.IsNullOrEmpty(text2) || text2.StartsWith("#"))
				{
					continue;
				}
				int num3 = text2.IndexOf('=');
				if (num3 <= 0)
				{
					num2++;
					Plugin.Log.LogWarning((object)("Invalid localization line: " + text));
					continue;
				}
				string text3 = text2.Substring(0, num3).Trim();
				string value = text2.Substring(num3 + 1);
				if (string.IsNullOrEmpty(text3))
				{
					num2++;
					continue;
				}
				Translations[text3] = value;
				num++;
			}
			Plugin.Log.LogInfo((object)$"Korean localization loaded: {num} entries.");
			if (num2 > 0)
			{
				Plugin.Log.LogWarning((object)$"Skipped {num2} invalid localization lines.");
			}
		}

		public static bool TryGet(string key, out string value)
		{
			return Translations.TryGetValue(key, out value);
		}

		public static string Translate(string phraseID, string[] args)
		{
			if (string.IsNullOrEmpty(phraseID))
			{
				return phraseID;
			}
			if (!TryGet(phraseID, out var value))
			{
				return null;
			}
			value = ResolveNestedLocalization(value);
			if (args != null && args.Length != 0)
			{
				string[] array = new string[args.Length];
				for (int i = 0; i < args.Length; i++)
				{
					array[i] = args[i];
					if (!string.IsNullOrEmpty(array[i]) && array[i].Length > 1 && array[i][0] == '$')
					{
						string phraseID2 = array[i].Substring(1);
						string text = Translate(phraseID2, null);
						if (text != null)
						{
							array[i] = text;
						}
					}
				}
				try
				{
					string format = value;
					object[] args2 = array;
					value = string.Format(format, args2);
				}
				catch (FormatException)
				{
					Plugin.Log.LogWarning((object)("Invalid format string for key: " + phraseID));
				}
			}
			return value;
		}

		private static string ResolveNestedLocalization(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text;
			}
			for (int i = 0; i < 32; i++)
			{
				int num = text.IndexOf('$');
				if (num < 0)
				{
					break;
				}
				int num2 = text.IndexOf('$', num + 1);
				if (num2 < 0)
				{
					break;
				}
				string text2 = text.Substring(num + 1, num2 - num - 1);
				if (string.IsNullOrEmpty(text2) || !TryGet(text2, out var value))
				{
					break;
				}
				value = ResolveNestedLocalization(value);
				string oldValue = text.Substring(num, num2 - num + 1);
				text = text.Replace(oldValue, value);
			}
			return text;
		}
	}
	[HarmonyPatch(typeof(Localizer), "GetSinglePhrase", new Type[]
	{
		typeof(string),
		typeof(string[])
	})]
	internal static class Localizer_GetSinglePhrase_Patch
	{
		private static bool Prefix(string phraseID, string[] args, ref string __result)
		{
			if (!KoreanLanguage.Enabled)
			{
				return true;
			}
			string text = KoreanLocalization.Translate(phraseID, args);
			if (text == null)
			{
				return true;
			}
			__result = text;
			return false;
		}
	}
	[BepInPlugin("com.anhyeongseop.tabs.korean", "TABS Korean", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "com.anhyeongseop.tabs.korean";

		public const string NAME = "TABS Korean";

		public const string VERSION = "1.0.0";

		internal static ManualLogSource Log;

		internal static Harmony HarmonyInstance;

		private void Awake()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"=================================");
			Log.LogInfo((object)"TABS Korean starting...");
			Log.LogInfo((object)"=================================");
			KoreanLocalization.Initialize();
			HarmonyInstance = new Harmony("com.anhyeongseop.tabs.korean");
			HarmonyInstance.PatchAll();
			Log.LogInfo((object)"TABS Korean loaded successfully.");
			Log.LogInfo((object)$"Loaded Korean strings: {KoreanLocalization.Count}");
		}

		private void OnDestroy()
		{
			if (HarmonyInstance != null)
			{
				HarmonyInstance.UnpatchSelf();
				HarmonyInstance = null;
			}
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"TABS Korean unloaded.");
			}
		}
	}
}