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.");
}
}
}
}