Decompiled source of ShiftAtMidnightLocalizationAPI v1.0.0

BepInEx/plugins/ShiftAtMidnightLocalizationAPI/ShiftAtMidnightLocalizationAPI.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using ShiftAtMidnightLocalizationAPI.Api;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ShiftAtMidnightLocalizationAPI")]
[assembly: AssemblyDescription("Localization API for Shift At Midnight mods")]
[assembly: AssemblyProduct("ShiftAtMidnightLocalizationAPI")]
[assembly: ComVisible(false)]
[assembly: Guid("79870812-2aca-43d5-b058-5844d23fb3b4")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ShiftAtMidnightLocalizationAPI
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "IceBoxStudio.ShiftAtMidnight.LocalizationAPI";

		public const string PLUGIN_NAME = "ShiftAtMidnightLocalizationAPI";

		public const string PLUGIN_VERSION = "1.0.0";
	}
	[BepInPlugin("IceBoxStudio.ShiftAtMidnight.LocalizationAPI", "ShiftAtMidnightLocalizationAPI", "1.0.0")]
	public sealed class ShiftAtMidnightLocalizationAPI : BasePlugin
	{
		internal static ManualLogSource Logger { get; private set; }

		public override void Load()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			Logger = ((BasePlugin)this).Log;
			bool flag = default(bool);
			try
			{
				new Harmony("IceBoxStudio.ShiftAtMidnight.LocalizationAPI").PatchAll(Assembly.GetExecutingAssembly());
				ManualLogSource logger = Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(14, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("ShiftAtMidnightLocalizationAPI");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" initialized.");
				}
				logger.LogInfo(val);
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(43, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to initialize the localization API: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				logger2.LogError(val2);
			}
		}
	}
}
namespace ShiftAtMidnightLocalizationAPI.Patches
{
	[HarmonyPatch(typeof(LanguageManager), "OnLanguageLoaded")]
	public static class LanguageManagerOnLanguageLoadedPatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			LocalizationApi.NotifyLanguageChanged();
		}
	}
}
namespace ShiftAtMidnightLocalizationAPI.Api
{
	public static class LocalizationApi
	{
		private sealed class LocalizedConfigDescription
		{
			public ModLocalizer Localizer;

			public string Key;

			public object[] Arguments;
		}

		public const string DefaultLanguage = "ENGLISH";

		private const string LanguagePreferenceKey = "Language";

		private static readonly Dictionary<string, ModLocalizer> Localizers = new Dictionary<string, ModLocalizer>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<ConfigEntryBase, LocalizedConfigDescription> ConfigDescriptions = new Dictionary<ConfigEntryBase, LocalizedConfigDescription>();

		public static string CurrentLanguage
		{
			get
			{
				TryGetCurrentGameLanguage(out var language);
				return language;
			}
		}

		public static event Action<string> LanguageChanged;

		public static ModLocalizer For(string pluginGuid)
		{
			if (string.IsNullOrWhiteSpace(pluginGuid))
			{
				throw new ArgumentException("Plugin GUID cannot be empty.", "pluginGuid");
			}
			if (!Localizers.TryGetValue(pluginGuid, out var value))
			{
				value = new ModLocalizer(pluginGuid);
				Localizers.Add(pluginGuid, value);
			}
			return value;
		}

		public static bool TryGetCurrentGameLanguage(out string language)
		{
			try
			{
				string text = (PlayerPrefs.HasKey("Language") ? PlayerPrefs.GetString("Language", "ENGLISH") : "ENGLISH");
				language = (string.IsNullOrWhiteSpace(text) ? "ENGLISH" : text);
				return true;
			}
			catch
			{
				language = "ENGLISH";
				return false;
			}
		}

		public static string GetConfigDescription(ConfigEntryBase entry)
		{
			if (entry != null && ConfigDescriptions.TryGetValue(entry, out var value))
			{
				return value.Localizer.GetLocalizedText(value.Key, value.Arguments);
			}
			if (entry == null)
			{
				return null;
			}
			ConfigDescription description = entry.Description;
			if (description == null)
			{
				return null;
			}
			return description.Description;
		}

		internal static void RegisterConfigDescription(ConfigEntryBase entry, ModLocalizer localizer, string key, object[] arguments)
		{
			if (entry == null)
			{
				throw new ArgumentNullException("entry");
			}
			if (localizer == null)
			{
				throw new ArgumentNullException("localizer");
			}
			if (string.IsNullOrWhiteSpace(key))
			{
				throw new ArgumentException("Localization key cannot be empty.", "key");
			}
			ConfigDescriptions[entry] = new LocalizedConfigDescription
			{
				Localizer = localizer,
				Key = key,
				Arguments = arguments
			};
		}

		internal static void NotifyLanguageChanged()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			Action<string> languageChanged = LocalizationApi.LanguageChanged;
			if (languageChanged == null)
			{
				return;
			}
			string currentLanguage = CurrentLanguage;
			Delegate[] invocationList = languageChanged.GetInvocationList();
			bool flag = default(bool);
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((Action<string>)obj)(currentLanguage);
				}
				catch (Exception ex)
				{
					ManualLogSource logger = ShiftAtMidnightLocalizationAPI.Logger;
					if (logger != null)
					{
						BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Language change callback failed: ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
						}
						logger.LogError(val);
					}
				}
			}
		}
	}
	public sealed class ModLocalizer
	{
		private readonly Dictionary<string, Dictionary<string, string>> _localizations = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);

		public string PluginGuid { get; }

		internal ModLocalizer(string pluginGuid)
		{
			PluginGuid = pluginGuid;
		}

		public void RegisterJson(string jsonPath)
		{
			if (string.IsNullOrWhiteSpace(jsonPath))
			{
				throw new ArgumentException("Localization file path cannot be empty.", "jsonPath");
			}
			if (!File.Exists(jsonPath))
			{
				throw new FileNotFoundException("Localization file not found.", jsonPath);
			}
			Dictionary<string, Dictionary<string, string>> dictionary = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
			using (JsonDocument jsonDocument = JsonDocument.Parse(File.ReadAllText(jsonPath)))
			{
				if (jsonDocument.RootElement.ValueKind != JsonValueKind.Object)
				{
					throw new InvalidDataException("Localization file root must be a JSON object.");
				}
				foreach (JsonProperty item in jsonDocument.RootElement.EnumerateObject())
				{
					if (item.Value.ValueKind != JsonValueKind.Object)
					{
						continue;
					}
					Dictionary<string, string> dictionary2 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
					foreach (JsonProperty item2 in item.Value.EnumerateObject())
					{
						if (item2.Value.ValueKind == JsonValueKind.String)
						{
							dictionary2[item2.Name] = item2.Value.GetString() ?? string.Empty;
						}
					}
					if (dictionary2.Count > 0)
					{
						dictionary[item.Name] = dictionary2;
					}
				}
			}
			if (!dictionary.ContainsKey("ENGLISH"))
			{
				throw new InvalidDataException("Localization file must contain a ENGLISH section.");
			}
			_localizations.Clear();
			foreach (KeyValuePair<string, Dictionary<string, string>> item3 in dictionary)
			{
				_localizations.Add(item3.Key, item3.Value);
			}
		}

		public string GetLocalizedText(string key, params object[] args)
		{
			if (string.IsNullOrEmpty(key))
			{
				return string.Empty;
			}
			string currentLanguage = LocalizationApi.CurrentLanguage;
			if (TryGetText(currentLanguage, key, out var text))
			{
				return Format(text, args);
			}
			if (!string.Equals(currentLanguage, "ENGLISH", StringComparison.OrdinalIgnoreCase) && TryGetText("ENGLISH", key, out var text2))
			{
				return Format(text2, args);
			}
			return key;
		}

		public void RegisterConfigDescription(ConfigEntryBase entry, string key, params object[] args)
		{
			LocalizationApi.RegisterConfigDescription(entry, this, key, args);
		}

		private bool TryGetText(string language, string key, out string text)
		{
			text = null;
			if (_localizations.TryGetValue(language, out var value))
			{
				return value.TryGetValue(key, out text);
			}
			return false;
		}

		private static string Format(string text, object[] args)
		{
			if (args == null || args.Length == 0)
			{
				return text;
			}
			try
			{
				return string.Format(text, args);
			}
			catch (FormatException)
			{
				return text;
			}
		}
	}
}