Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of REPO PTBR Contextual v1.0.1
BepInEx/plugins/RepoPTBRContextual/RepoPTBRContextual.dll
Decompiled 12 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Localization; using UnityEngine.Localization.Settings; using UnityEngine.Localization.Tables; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.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 RepoPTBRContextual { [BepInPlugin("local.repo.ptbrcontextual", "R.E.P.O. PT-BR Contextual", "1.0.1")] public sealed class RepoPTBRContextualPlugin : BaseUnityPlugin { private Harmony harmony; public void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown PTBRTranslator.Load(Paths.PluginPath); harmony = new Harmony("local.repo.ptbrcontextual"); harmony.PatchAll(typeof(RepoPTBRContextualPlugin).Assembly); OverrideTools.ApplyOverridesToActiveLocales(); ((MonoBehaviour)this).StartCoroutine(ApplyTranslationWhenReady()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"PT-BR contextual translation loaded."); } private IEnumerator ApplyTranslationWhenReady() { for (int attempt = 0; attempt < 12; attempt++) { yield return (object)new WaitForSecondsRealtime(1f); OverrideTools.ApplyOverridesToActiveLocales(); } } public void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class PTBRTranslator { private static readonly Dictionary<string, string> Exact = new Dictionary<string, string>(); private static readonly HashSet<string> Missing = new HashSet<string>(); private static readonly object MissingLock = new object(); private static string missingPath; private static string localizationPath; private static DateTime nextOverrideApplyAt = DateTime.MinValue; internal static string LocalizationPath => localizationPath; public static void Load(string pluginPath) { string path = Path.Combine(pluginPath, "RepoPTBRContextual"); string path2 = Path.Combine(path, "runtime.tsv"); localizationPath = Path.Combine(path, "Localizations"); missingPath = Path.Combine(Paths.ConfigPath, "RepoPTBRContextual.missing.tsv"); Exact.Clear(); if (!File.Exists(path2)) { LoadOfficialLocalizationPairs(); return; } string[] array = File.ReadAllLines(path2, Encoding.UTF8); foreach (string text in array) { if (!string.IsNullOrWhiteSpace(text) && !text.StartsWith("#", StringComparison.Ordinal)) { string[] array2 = text.Split(new char[1] { '\t' }, 2); if (array2.Length == 2 && !string.IsNullOrWhiteSpace(array2[0])) { Exact[array2[0].Replace("\\n", "\n")] = array2[1].Replace("\\n", "\n"); } } } LoadOfficialLocalizationPairs(); } public static bool ShouldApplyOverridesNow() { DateTime utcNow = DateTime.UtcNow; if (utcNow < nextOverrideApplyAt) { return false; } nextOverrideApplyAt = utcNow.AddSeconds(1.0); return true; } public static string Translate(string value) { if (string.IsNullOrEmpty(value)) { return value; } string translated; if (value.StartsWith("(PT-BR) ", StringComparison.OrdinalIgnoreCase)) { string text = value.Substring("(PT-BR) ".Length); if (TryTranslate(text, out translated)) { return translated; } return text; } if (TryTranslate(value, out translated)) { return translated; } LogMissing(value); return value; } private static bool TryTranslate(string value, out string translated) { if (Exact.TryGetValue(value, out translated)) { return true; } string text = value.Trim(); if (text.Length != value.Length && Exact.TryGetValue(text, out translated)) { int length = value.Length - value.TrimStart().Length; int num = value.Length - value.TrimEnd().Length; translated = value.Substring(0, length) + translated + value.Substring(value.Length - num); return true; } return false; } private static void LoadOfficialLocalizationPairs() { try { string path = Path.Combine(Path.Combine(Application.streamingAssetsPath, "Localizations"), "Default"); string[] array = new string[3] { "HUD.tsv", "Menu.tsv", "Game.tsv" }; for (int i = 0; i < array.Length; i++) { Dictionary<string, string> dictionary = ReadTsv(Path.Combine(path, array[i])); Dictionary<string, string> dictionary2 = ReadTsv(Path.Combine(localizationPath, array[i])); foreach (KeyValuePair<string, string> item in dictionary) { if (dictionary2.TryGetValue(item.Key, out var value) && !Exact.ContainsKey(item.Value)) { Exact[item.Value] = value; string key = item.Value.ToUpperInvariant(); if (!Exact.ContainsKey(key)) { Exact[key] = value; } } } } } catch { } } private static Dictionary<string, string> ReadTsv(string path) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (!File.Exists(path)) { return dictionary; } string[] array = File.ReadAllLines(path, Encoding.UTF8); foreach (string text in array) { if (!string.IsNullOrWhiteSpace(text)) { string[] array2 = text.Split(new char[1] { '\t' }, 2); if (array2.Length == 2 && !string.IsNullOrWhiteSpace(array2[0])) { dictionary[array2[0]] = array2[1].Replace("\\n", "\n"); } } } return dictionary; } private static void LogMissing(string value) { if (!LooksUserFacingEnglish(value)) { return; } lock (MissingLock) { if (Missing.Add(value)) { File.AppendAllText(missingPath, value.Replace("\r", "\\r").Replace("\n", "\\n") + "\t\r\n", Encoding.UTF8); } } } private static bool LooksUserFacingEnglish(string value) { string text = value.Trim(); if (text.Length < 2 || text.Length > 180) { return false; } if (text.Contains("/") || text.Contains("\\") || text.Contains(".dll") || text.Contains(".asset")) { return false; } bool flag = false; bool flag2 = false; foreach (char c in text) { if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { flag = true; } else if (char.IsWhiteSpace(c) || ",.!?:;()[]{}'\"-".IndexOf(c) >= 0) { flag2 = true; } } if (!flag) { return false; } if (!flag2 && text.ToUpperInvariant() == text && text.Contains(".")) { return false; } return true; } } internal static class LocaleTools { public static void ForcePtBr(object manager) { try { if (manager == null) { return; } Type type = manager.GetType(); FieldInfo fieldInfo = AccessTools.Field(type, "AvailableLocales"); MethodInfo methodInfo = AccessTools.Method(type, "SwitchLocale", (Type[])null, (Type[])null); IEnumerable enumerable = ((fieldInfo == null) ? null : (fieldInfo.GetValue(manager) as IEnumerable)); if (enumerable == null || methodInfo == null) { return; } foreach (object item in enumerable) { if (string.Equals(GetLocaleCode(item), "pt-BR", StringComparison.OrdinalIgnoreCase)) { methodInfo.Invoke(manager, new object[2] { item, true }); break; } } } catch (Exception ex) { Debug.LogError((object)("[RepoPTBRContextual] Failed to apply localization overrides: " + ex)); } } private static string GetLocaleCode(object localeAsset) { if (localeAsset == null) { return null; } FieldInfo fieldInfo = AccessTools.Field(localeAsset.GetType(), "LocaleReference"); object obj = ((fieldInfo == null) ? null : fieldInfo.GetValue(localeAsset)); if (obj == null) { return null; } object value = AccessTools.Property(obj.GetType(), "Identifier").GetValue(obj, null); if (value != null) { return (string)AccessTools.Property(value.GetType(), "Code").GetValue(value, null); } return null; } } internal static class OverrideTools { public static void ApplyOverridesToActiveLocales() { try { string localizationPath = PTBRTranslator.LocalizationPath; if (string.IsNullOrEmpty(localizationPath) || !Directory.Exists(localizationPath)) { Debug.LogWarning((object)"[RepoPTBRContextual] Bundled localization tables were not found."); return; } string[] array = new string[3] { "HUD", "Menu", "Game" }; List<Locale> targetLocales = GetTargetLocales(); int num = 0; foreach (string text in array) { string path = Path.Combine(localizationPath, text + ".tsv"); if (File.Exists(path)) { List<KeyValuePair<string, string>> entries = ReadEntries(path); for (int j = 0; j < targetLocales.Count; j++) { num += ApplyTable(text, targetLocales[j], entries); } } } Debug.Log((object)("[RepoPTBRContextual] Applied " + num + " localization override entries to " + targetLocales.Count + " locale(s).")); } catch (Exception ex) { Debug.LogWarning((object)("[RepoPTBRContextual] Localization tables are not ready yet: " + ex.Message)); } } private static List<Locale> GetTargetLocales() { List<Locale> list = new List<Locale>(); AddLocale(list, LocalizationSettings.SelectedLocale); AddLocale(list, LocalizationSettings.ProjectLocale); try { if (LocalizationSettings.AvailableLocales != null) { foreach (Locale locale in LocalizationSettings.AvailableLocales.Locales) { if (IsPtBr(locale)) { AddLocale(list, locale); } } } } catch { } return list; } private static void AddLocale(List<Locale> locales, Locale locale) { if ((Object)(object)locale == (Object)null) { return; } for (int i = 0; i < locales.Count; i++) { if ((Object)(object)locales[i] == (Object)(object)locale) { return; } } locales.Add(locale); } private static bool IsPtBr(Locale locale) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)locale == (Object)null) { return false; } LocaleIdentifier identifier = locale.Identifier; return string.Equals(((LocaleIdentifier)(ref identifier)).Code, "pt-BR", StringComparison.OrdinalIgnoreCase); } private static List<KeyValuePair<string, string>> ReadEntries(string path) { List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); string[] array = File.ReadAllLines(path, Encoding.UTF8); foreach (string text in array) { if (!string.IsNullOrWhiteSpace(text)) { string[] array2 = text.Split(new char[1] { '\t' }, 2); if (array2.Length == 2 && !string.IsNullOrWhiteSpace(array2[0])) { list.Add(new KeyValuePair<string, string>(array2[0], array2[1].Replace("\\n", "\n"))); } } } return list; } private static int ApplyTable(string tableName, Locale locale, List<KeyValuePair<string, string>> entries) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) StringTable table = ((LocalizedDatabase<StringTable, StringTableEntry>)(object)LocalizationSettings.StringDatabase).GetTable(TableReference.op_Implicit(tableName), locale); if ((Object)(object)table == (Object)null) { return 0; } int num = 0; for (int i = 0; i < entries.Count; i++) { KeyValuePair<string, string> keyValuePair = entries[i]; StringTableEntry entry = ((DetailedLocalizationTable<StringTableEntry>)(object)table).GetEntry(keyValuePair.Key); if (entry != null) { entry.Value = keyValuePair.Value; } else { ((DetailedLocalizationTable<StringTableEntry>)(object)table).AddEntry(keyValuePair.Key, keyValuePair.Value); } num++; } return num; } } [HarmonyPatch(typeof(LocalizationManager), "Start")] internal static class LocalizationManagerStartPatch { private static void Postfix(LocalizationManager __instance) { OverrideTools.ApplyOverridesToActiveLocales(); MethodInfo methodInfo = AccessTools.Method(((object)__instance).GetType(), "NotifyLocalizationChanged", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(__instance, null); } } } [HarmonyPatch(typeof(LocalizationChangedEvent), "OnLocaleChange")] internal static class LocalizationChangedEventPatch { private static void Prefix() { if (PTBRTranslator.ShouldApplyOverridesNow()) { OverrideTools.ApplyOverridesToActiveLocales(); } } } [HarmonyPatch(typeof(TMP_Text), "set_text")] internal static class TMPTextPatch { private static void Prefix(ref string value) { value = PTBRTranslator.Translate(value); } } [HarmonyPatch] internal static class TMPSetTextPatch { private static IEnumerable<MethodBase> TargetMethods() { return from method in typeof(TMP_Text).GetMethods(BindingFlags.Instance | BindingFlags.Public) where method.Name == "SetText" && method.GetParameters().Length != 0 && method.GetParameters()[0].ParameterType == typeof(string) select method; } private static void Prefix(ref string sourceText) { sourceText = PTBRTranslator.Translate(sourceText); } } [HarmonyPatch(typeof(Text), "set_text")] internal static class UITextPatch { private static void Prefix(ref string value) { value = PTBRTranslator.Translate(value); } } }