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 Valheim Ascended PTBR v1.0.0
plugins/ValheimAscended_PTBR.dll
Decompiled 11 hours agousing System; 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.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; 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: AssemblyCompany("ValheimAscended_PTBR")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ValheimAscended_PTBR")] [assembly: AssemblyTitle("ValheimAscended_PTBR")] [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 ValheimAscendedPTBR { [BepInPlugin("glitnir.valheimascended.ptbr", "Valheim Ascended PT-BR", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "glitnir.valheimascended.ptbr"; public const string ModName = "Valheim Ascended PT-BR"; public const string Version = "1.0.0"; private const string VaGuid = "com.valheimascended.mod"; internal static ManualLogSource Log; internal static Translator Tr; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> TranslateTmp; internal static ConfigEntry<bool> ColorizeKeywords; internal static ConfigEntry<string> DictionaryFile; internal static ConfigEntry<KeyboardShortcut> ReloadKey; internal static ConfigEntry<bool> DumpUntranslated; private static string _pluginDir; private static Type _terminalType; private static readonly Dictionary<int, bool> SkipCache = new Dictionary<int, bool>(); private static HashSet<string> _dumped; private static string _dumpPath; private Harmony _harmony; private static readonly Regex EnglishWord = new Regex("[A-Za-z]{3,}", RegexOptions.CultureInvariant); private static bool _loggedError; private void Awake() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; _pluginDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? Paths.PluginPath; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Geral", "Ativado", true, "Liga/desliga a tradução do Valheim Ascended."); TranslateTmp = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Geral", "TraduzirTextMeshPro", true, "Também traduz textos TextMeshPro (mensagens na tela, dicas de item, texto de hover, menu de personagens). Chat e console nunca são traduzidos."); ColorizeKeywords = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Geral", "ColorirPalavrasChave", true, "Colore palavras-chave em português nas descrições de talentos (fogo, gelo, veneno, sangramento...), igual o mod faz com as palavras em inglês."); DictionaryFile = ((BaseUnityPlugin)this).Config.Bind<string>("1 - Geral", "ArquivoDicionario", "translations/pt-BR.json", "Dicionário principal (relativo à pasta do plugin). Se existir 'translations/pt-BR.custom.json', ele é carregado por cima — use esse arquivo para as suas correções, assim elas não se perdem ao atualizar."); ReloadKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - Geral", "TeclaRecarregar", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Recarrega o dicionário sem reiniciar o jogo (útil para testar traduções)."); DumpUntranslated = ((BaseUnityPlugin)this).Config.Bind<bool>("9 - Debug", "SalvarNaoTraduzidos", false, "Salva em BepInEx/ValheimAscended_PTBR_nao_traduzidos.txt os textos de interface que continuaram em inglês. Útil para completar o dicionário quando o Valheim Ascended atualizar."); LoadDictionary(); _terminalType = AccessTools.TypeByName("Terminal"); _harmony = new Harmony("glitnir.valheimascended.ptbr"); ApplyPatches(); } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = ReloadKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { LoadDictionary(); Log.LogMessage((object)"Dicionário recarregado."); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } internal static void LoadDictionary() { Translator translator = new Translator(); Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal); string path = Path.Combine(_pluginDir, DictionaryFile.Value); if (File.Exists(path)) { LoadInto(dictionary, path); } else { LoadEmbedded(dictionary); } string path2 = Path.Combine(Path.GetDirectoryName(path) ?? _pluginDir, Path.GetFileNameWithoutExtension(path) + ".custom.json"); LoadInto(dictionary, path2); LoadInto(dictionary, Path.Combine(Paths.ConfigPath, "ValheimAscended_PTBR.custom.json")); string[] array = new string[5] { "STR", "AGI", "INT", "END", "DEX" }; foreach (string text in array) { string key = "% per " + text; if (!dictionary.ContainsKey(key)) { dictionary[key] = "% por " + text; } } translator.Load(dictionary); Tr = translator; SkipCache.Clear(); Log.LogInfo((object)$"Dicionário carregado: {translator.LiteralCount} literais, {translator.TemplateCount} modelos ({translator.SkippedCount} ignorados)."); } private static void LoadEmbedded(Dictionary<string, string> target) { try { using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("ValheimAscendedPTBR.pt-BR.json"); if (stream == null) { Log.LogError((object)"Dicionário embutido não encontrado na DLL."); return; } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); Dictionary<string, string> dictionary = MiniJson.ParseFlatObject(streamReader.ReadToEnd()); foreach (KeyValuePair<string, string> item in dictionary) { target[item.Key] = item.Value; } Log.LogInfo((object)$"Dicionário embutido: {dictionary.Count} entradas."); } catch (Exception ex) { Log.LogError((object)("Erro lendo o dicionário embutido: " + ex.Message)); } } private static void LoadInto(Dictionary<string, string> target, string path) { if (!File.Exists(path)) { return; } try { Dictionary<string, string> dictionary = MiniJson.ParseFlatObject(File.ReadAllText(path, Encoding.UTF8)); foreach (KeyValuePair<string, string> item in dictionary) { target[item.Key] = item.Value; } Log.LogInfo((object)$"{Path.GetFileName(path)}: {dictionary.Count} entradas."); } catch (Exception ex) { Log.LogError((object)("Erro lendo " + path + ": " + ex.Message)); } } private void ApplyPatches() { TryPatch(AccessTools.PropertySetter(typeof(Text), "text"), "UiTextPrefix"); TryPatch(AccessTools.PropertySetter(typeof(TMP_Text), "text"), "TmpTextPrefix"); TryPatch(AccessTools.Method(typeof(TMP_Text), "SetText", new Type[2] { typeof(string), typeof(bool) }, (Type[])null), "TmpSetTextPrefix"); Type type = AccessTools.TypeByName("ValheimAscended.UI.TalentPanel"); if (type != null) { TryPatch(AccessTools.Method(type, "ColorizeDescription", new Type[1] { typeof(string) }, (Type[])null), "ColorizePrefix", "ColorizePostfix"); } else { Log.LogWarning((object)"Valheim Ascended não encontrado — só a tradução genérica de texto está ativa."); } } private void TryPatch(MethodBase target, string prefix = null, string postfix = null) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (target == null) { Log.LogWarning((object)("Método alvo não encontrado para " + (prefix ?? postfix) + ".")); return; } try { _harmony.Patch(target, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), postfix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { Log.LogError((object)("Falha ao aplicar patch em " + target.DeclaringType?.Name + "." + target.Name + ": " + ex.Message)); } } private static void UiTextPrefix(Text __instance, ref string value) { if (!Enabled.Value || Tr == null || string.IsNullOrEmpty(value) || (Object)(object)__instance == (Object)null) { return; } try { if (!IsInputText(__instance)) { string text = Tr.Translate(value); if (DumpUntranslated.Value && text == value) { Dump(value); } value = text; } } catch (Exception e) { LogOnce(e); } } private static void TmpTextPrefix(TMP_Text __instance, ref string value) { if (!Enabled.Value || !TranslateTmp.Value || Tr == null || string.IsNullOrEmpty(value) || (Object)(object)__instance == (Object)null) { return; } try { if (!IsInputOrChat(__instance)) { value = Tr.Translate(value); } } catch (Exception e) { LogOnce(e); } } private static void TmpSetTextPrefix(TMP_Text __instance, ref string __0) { TmpTextPrefix(__instance, ref __0); } private static void ColorizePrefix(ref string __0) { if (!Enabled.Value || Tr == null || string.IsNullOrEmpty(__0)) { return; } try { __0 = Tr.Translate(__0); } catch (Exception e) { LogOnce(e); } } private static void ColorizePostfix(ref string __result) { if (!Enabled.Value || !ColorizeKeywords.Value || string.IsNullOrEmpty(__result)) { return; } try { __result = PtColorizer.Apply(__result); } catch (Exception e) { LogOnce(e); } } private static bool IsInputText(Text t) { int instanceID = ((Object)t).GetInstanceID(); if (SkipCache.TryGetValue(instanceID, out var value)) { return value; } InputField componentInParent = ((Component)t).GetComponentInParent<InputField>(true); value = (Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.textComponent == (Object)(object)t; Remember(instanceID, value); return value; } private static bool IsInputOrChat(TMP_Text t) { int instanceID = ((Object)t).GetInstanceID(); if (SkipCache.TryGetValue(instanceID, out var value)) { return value; } TMP_InputField componentInParent = ((Component)t).GetComponentInParent<TMP_InputField>(true); value = (Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.textComponent == (Object)(object)t; if (!value && _terminalType != null) { value = (Object)(object)((Component)t).GetComponentInParent(_terminalType, true) != (Object)null; } Remember(instanceID, value); return value; } private static void Remember(int id, bool skip) { if (SkipCache.Count > 20000) { SkipCache.Clear(); } SkipCache[id] = skip; } private static void Dump(string s) { if (_dumped == null) { _dumped = new HashSet<string>(StringComparer.Ordinal); _dumpPath = Path.Combine(Paths.BepInExRootPath, "ValheimAscended_PTBR_nao_traduzidos.txt"); } if (_dumped.Count > 5000 || s.Length > 2000 || !EnglishWord.IsMatch(s) || !_dumped.Add(s)) { return; } try { File.AppendAllText(_dumpPath, s.Replace("\r", "\\r").Replace("\n", "\\n") + Environment.NewLine, Encoding.UTF8); } catch { } } private static void LogOnce(Exception e) { if (!_loggedError) { _loggedError = true; Log.LogError((object)("Erro na tradução (mostrado só uma vez): " + e)); } } } internal static class PtColorizer { private static readonly Regex TagSplit = new Regex("(<[^>]+>)", RegexOptions.CultureInvariant); private static readonly KeyValuePair<Regex, string>[] Rules = new KeyValuePair<Regex, string>[20] { R("\\b(fogo|chamas)\\b", "#FF8844"), R("\\b(queima\\w*)\\b", "#FF8844"), R("\\b(gelo|geada|frio)\\b", "#66CCFF"), R("\\b(resfriad\\w*|resfriamento)\\b", "#66CCFF"), R("\\b(congelad\\w*|congelar|congelamento)\\b", "#44AAFF"), R("\\b(enregelamento)\\b", "#44AAFF"), R("\\b(raios?)\\b(?! de [\\d<])(?!:)", "#FFFF66"), R("\\b(eletrifica\\w*)\\b", "#FFFF66"), R("\\b(espírito|espiritua(?:l|is))\\b", "#CCCCFF"), R("\\b(veneno|envenenad\\w*|peçonha)\\b", "#66FF66"), R("\\b(sangramento|sangra\\w*)\\b", "#DD4444"), R("\\b(molhad[oa]s?)\\b", "#66CCFF"), R("\\b(fumaça|enfumaçad[oa]s?)\\b", "#888888"), R("\\b(atordoa\\w*)\\b", "#FFAA44"), R("\\b(desequilibr\\w*|desequilíbrio)\\b", "#FFAA44"), R("\\b(lentidão)\\b", "#66CCFF"), R("\\b(enraizad\\w*|enraíza\\w*)\\b", "#A088DD"), R("\\b(Voltagem)\\b", "#FFFF66"), R("\\b(Calor)\\b", "#FF8844"), R("\\b(Ressonância)\\b", "#CC99FF") }; private static KeyValuePair<Regex, string> R(string pattern, string color) { return new KeyValuePair<Regex, string>(new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant), color); } public static string Apply(string text) { string[] array = TagSplit.Split(text); StringBuilder stringBuilder = new StringBuilder(text.Length + 64); int num = 0; string[] array2 = array; foreach (string text2 in array2) { if (text2.Length == 0) { continue; } if (text2[0] == '<' && text2[text2.Length - 1] == '>') { if (text2.StartsWith("<color", StringComparison.OrdinalIgnoreCase)) { num++; } else if (text2.StartsWith("</color", StringComparison.OrdinalIgnoreCase) && num > 0) { num--; } stringBuilder.Append(text2); continue; } if (num > 0) { stringBuilder.Append(text2); continue; } string text3 = text2; KeyValuePair<Regex, string>[] rules = Rules; for (int j = 0; j < rules.Length; j++) { KeyValuePair<Regex, string> keyValuePair = rules[j]; string color = keyValuePair.Value; text3 = keyValuePair.Key.Replace(text3, (Match m) => "\u0001" + color + "\u0002" + m.Groups[1].Value + "\u0003"); } text3 = text3.Replace("\u0001", "<color=").Replace("\u0002", ">").Replace("\u0003", "</color>"); stringBuilder.Append(text3); } return stringBuilder.ToString(); } } internal sealed class Translator { private sealed class Part { public string Literal; public string Token; public int Group; } private sealed class Rule { public string En; public string Pt; public bool IsTemplate; public string Anchor; public bool NeedWordStart; public bool NeedWordEnd; public string Pattern; public List<object> PtParts; public string[] Prefilter; public bool Broken; private Regex _re; public Regex Re { get { if (_re == null) { _re = new Regex(Pattern, RegexOptions.CultureInvariant, TimeSpan.FromMilliseconds(40.0)); } return _re; } } } private struct Hit { public int Start; public int Length; public string Replacement; } private static readonly Regex TokenRx = new Regex("\\{[^{}]*\\}", RegexOptions.CultureInvariant); private static readonly Regex WordRx = new Regex("\\p{L}{2,}", RegexOptions.CultureInvariant); private static readonly CultureInfo PtBr = CultureInfo.GetCultureInfo("pt-BR"); private const string InnerGroup = "([^\\n]*?)"; private const string LeadGroup = "((?:<[^>]*>|[^\\s<>])*?)"; private const string TrailGroup = "((?:<[^>]*>|[^\\s<>])*)"; private readonly Dictionary<string, string> _exact = new Dictionary<string, string>(StringComparer.Ordinal); private readonly Dictionary<string, List<Rule>> _byAnchor = new Dictionary<string, List<Rule>>(StringComparer.Ordinal); private readonly Dictionary<string, string> _cache = new Dictionary<string, string>(StringComparer.Ordinal); private readonly int _cacheLimit; public int LiteralCount { get; private set; } public int TemplateCount { get; private set; } public int SkippedCount { get; private set; } public Translator(int cacheLimit = 30000) { _cacheLimit = cacheLimit; } public void Load(Dictionary<string, string> dict) { _exact.Clear(); _byAnchor.Clear(); _cache.Clear(); int num = (SkippedCount = 0); int literalCount = (TemplateCount = num); LiteralCount = literalCount; List<Rule> list = new List<Rule>(); foreach (KeyValuePair<string, string> item in dict) { if (!string.IsNullOrEmpty(item.Key) && item.Value != null && !(item.Key == item.Value)) { Rule rule = ((item.Key.IndexOf('{') >= 0 && TokenRx.IsMatch(item.Key)) ? BuildTemplate(item.Key, item.Value) : BuildLiteral(item.Key, item.Value)); if (rule == null) { SkippedCount++; } else { list.Add(rule); } } } HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); foreach (Rule item2 in list) { if (!item2.IsTemplate) { hashSet.Add(item2.En); } } List<Rule> list2 = new List<Rule>(); foreach (Rule item3 in list) { if (item3.IsTemplate || item3.En.Length > 40 || !IsSimpleWords(item3.En)) { continue; } string text = item3.En.ToUpperInvariant(); if (!(text == item3.En) && !hashSet.Contains(text)) { hashSet.Add(text); Rule rule2 = BuildLiteral(text, item3.Pt.ToUpper(PtBr)); if (rule2 != null) { list2.Add(rule2); } } } list.AddRange(list2); Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal); List<List<string>> list3 = new List<List<string>>(list.Count); foreach (Rule item4 in list) { List<string> list4 = LiteralWords(item4); list3.Add(list4); foreach (string item5 in list4) { dictionary.TryGetValue(item5, out var value); dictionary[item5] = value + 1; } } for (int i = 0; i < list.Count; i++) { Rule rule3 = list[i]; List<string> list5 = list3[i]; if (list5.Count == 0) { SkippedCount++; continue; } string text2 = null; int num4 = int.MaxValue; foreach (string item6 in list5) { int num5 = dictionary[item6]; if (num5 < num4 || (num5 == num4 && item6.Length > text2.Length)) { text2 = item6; num4 = num5; } } rule3.Anchor = text2; if (!_byAnchor.TryGetValue(text2, out var value2)) { value2 = (_byAnchor[text2] = new List<Rule>()); } value2.Add(rule3); if (rule3.IsTemplate) { TemplateCount++; continue; } LiteralCount++; if (!_exact.ContainsKey(rule3.En)) { _exact[rule3.En] = rule3.Pt; } } } private static bool IsSimpleWords(string s) { bool result = false; foreach (char c in s) { if (char.IsLetter(c)) { result = true; } else if (c != ' ' && c != '-' && c != '\'' && c != '!' && c != '&') { return false; } } return result; } private static List<string> LiteralWords(Rule r) { List<string> list = new List<string>(); string input = (r.IsTemplate ? TokenRx.Replace(r.En, " ") : r.En); input = Regex.Replace(input, "<[^>]*>", " "); foreach (Match item2 in WordRx.Matches(input)) { string item = item2.Value.ToLowerInvariant(); if (!list.Contains(item)) { list.Add(item); } } return list; } private static bool IsWordChar(char c) { return char.IsLetterOrDigit(c); } private static Rule BuildLiteral(string en, string pt) { if (en.Length == 0) { return null; } return new Rule { En = en, Pt = pt, IsTemplate = false, NeedWordStart = IsWordChar(en[0]), NeedWordEnd = IsWordChar(en[en.Length - 1]) }; } private static Rule BuildTemplate(string en, string pt) { List<Part> list = new List<Part>(); int num = 0; foreach (Match item in TokenRx.Matches(en)) { if (item.Index > num) { list.Add(new Part { Literal = en.Substring(num, item.Index - num) }); } list.Add(new Part { Token = item.Value }); num = item.Index + item.Length; } if (num < en.Length) { list.Add(new Part { Literal = en.Substring(num) }); } List<Part> list2 = new List<Part>(); for (int i = 0; i < list.Count; i++) { if (list[i].Literal != null) { list2.Add(list[i]); continue; } int j = i; StringBuilder stringBuilder = new StringBuilder(); for (; j < list.Count && list[j].Literal == null; j++) { stringBuilder.Append(list[j].Token); } if (j - i > 1 && pt.Contains(stringBuilder.ToString())) { list2.Add(new Part { Token = stringBuilder.ToString() }); } else { for (int k = i; k < j; k++) { list2.Add(new Part { Token = list[k].Token }); } } i = j - 1; } string text = pt; while (list2.Count > 0 && list2[0].Literal == null && text.StartsWith(list2[0].Token, StringComparison.Ordinal) && CountOf(text, list2[0].Token) == 1) { text = text.Substring(list2[0].Token.Length); list2.RemoveAt(0); } while (list2.Count > 0 && list2[list2.Count - 1].Literal == null && text.EndsWith(list2[list2.Count - 1].Token, StringComparison.Ordinal) && CountOf(text, list2[list2.Count - 1].Token) == 1) { text = text.Substring(0, text.Length - list2[list2.Count - 1].Token.Length); list2.RemoveAt(list2.Count - 1); } if (list2.Count == 0) { return null; } bool flag = false; foreach (Part item2 in list2) { if (item2.Literal == null) { flag = true; break; } } if (!flag) { StringBuilder stringBuilder2 = new StringBuilder(); foreach (Part item3 in list2) { stringBuilder2.Append(item3.Literal); } string text2 = stringBuilder2.ToString(); if (text2.Trim().Length < 2) { return null; } return BuildLiteral(text2, text); } int num2 = 0; foreach (Part item4 in list2) { if (item4.Literal == null) { continue; } string literal = item4.Literal; for (int l = 0; l < literal.Length; l++) { if (char.IsLetter(literal[l])) { num2++; } } } if (num2 < 2) { return null; } StringBuilder stringBuilder3 = new StringBuilder(); List<string> tokens = new List<string>(); List<string> list3 = new List<string>(); for (int m = 0; m < list2.Count; m++) { Part part = list2[m]; if (part.Literal != null) { if (m == 0 && IsWordChar(part.Literal[0])) { stringBuilder3.Append("(?<![\\p{L}\\p{N}])"); } stringBuilder3.Append(Regex.Escape(part.Literal)); if (m == list2.Count - 1 && IsWordChar(part.Literal[part.Literal.Length - 1])) { stringBuilder3.Append("(?![\\p{L}\\p{N}])"); } string text3 = part.Literal.Trim(); if (text3.Length >= 3) { list3.Add(text3); } } else { part.Group = tokens.Count; tokens.Add(part.Token); if (m == 0) { stringBuilder3.Append("((?:<[^>]*>|[^\\s<>])*?)"); } else if (m == list2.Count - 1) { stringBuilder3.Append("((?:<[^>]*>|[^\\s<>])*)"); } else { stringBuilder3.Append("([^\\n]*?)"); } } } List<object> list4 = new List<object>(); List<int> list5 = new List<int>(); for (int n = 0; n < tokens.Count; n++) { list5.Add(n); } list5.Sort((int a, int b) => tokens[b].Length.CompareTo(tokens[a].Length)); int num3 = 0; StringBuilder stringBuilder4 = new StringBuilder(); while (num3 < text.Length) { int num4 = -1; if (text[num3] == '{') { foreach (int item5 in list5) { if (string.CompareOrdinal(text, num3, tokens[item5], 0, tokens[item5].Length) == 0) { num4 = item5; break; } } } if (num4 >= 0) { if (stringBuilder4.Length > 0) { list4.Add(stringBuilder4.ToString()); stringBuilder4.Length = 0; } list4.Add(num4); num3 += tokens[num4].Length; } else { stringBuilder4.Append(text[num3]); num3++; } } if (stringBuilder4.Length > 0) { list4.Add(stringBuilder4.ToString()); } StringBuilder stringBuilder5 = new StringBuilder(); foreach (Part item6 in list2) { stringBuilder5.Append(item6.Literal ?? item6.Token); } return new Rule { En = stringBuilder5.ToString(), Pt = text, IsTemplate = true, Pattern = stringBuilder3.ToString(), PtParts = list4, Prefilter = list3.ToArray() }; } private static int CountOf(string s, string sub) { int num = 0; int startIndex = 0; while ((startIndex = s.IndexOf(sub, startIndex, StringComparison.Ordinal)) >= 0) { num++; startIndex += sub.Length; } return num; } public string Translate(string s) { return Translate(s, 0); } private string Translate(string s, int depth) { if (string.IsNullOrEmpty(s)) { return s; } if (_cache.TryGetValue(s, out var value)) { return value; } string text = TranslateCore(s, depth); if (_cache.Count >= _cacheLimit) { _cache.Clear(); } _cache[s] = text; if ((object)text != s && !_cache.ContainsKey(text)) { _cache[text] = text; } return text; } private string TranslateCore(string s, int depth) { if (_exact.TryGetValue(s, out var value)) { return value; } HashSet<string> hashSet = null; foreach (Match item in WordRx.Matches(s)) { if (hashSet == null) { hashSet = new HashSet<string>(StringComparer.Ordinal); } hashSet.Add(item.Value.ToLowerInvariant()); } if (hashSet == null) { return s; } List<Hit> hits = null; foreach (string item2 in hashSet) { if (!_byAnchor.TryGetValue(item2, out var value2)) { continue; } foreach (Rule item3 in value2) { if (item3.IsTemplate) { CollectTemplate(item3, s, depth, ref hits); } else { CollectLiteral(item3, s, ref hits); } } } if (hits == null) { return s; } hits.Sort(delegate(Hit a, Hit b) { int num2 = b.Length.CompareTo(a.Length); return (num2 == 0) ? a.Start.CompareTo(b.Start) : num2; }); List<Hit> list = new List<Hit>(); foreach (Hit item4 in hits) { bool flag = false; foreach (Hit item5 in list) { if (item4.Start < item5.Start + item5.Length && item5.Start < item4.Start + item4.Length) { flag = true; break; } } if (!flag) { list.Add(item4); } } if (list.Count == 0) { return s; } list.Sort((Hit a, Hit b) => a.Start.CompareTo(b.Start)); StringBuilder stringBuilder = new StringBuilder(s.Length + 32); int num = 0; foreach (Hit item6 in list) { stringBuilder.Append(s, num, item6.Start - num); stringBuilder.Append(item6.Replacement); num = item6.Start + item6.Length; } stringBuilder.Append(s, num, s.Length - num); return stringBuilder.ToString(); } private static void CollectLiteral(Rule r, string s, ref List<Hit> hits) { int startIndex = 0; while ((startIndex = s.IndexOf(r.En, startIndex, StringComparison.Ordinal)) >= 0) { int num = startIndex + r.En.Length; bool flag = true; if (r.NeedWordStart && startIndex > 0 && IsWordChar(s[startIndex - 1])) { flag = false; } if (flag && r.NeedWordEnd && num < s.Length && IsWordChar(s[num])) { flag = false; } if (flag) { if (hits == null) { hits = new List<Hit>(); } hits.Add(new Hit { Start = startIndex, Length = r.En.Length, Replacement = r.Pt }); startIndex = num; } else { startIndex++; } } } private void CollectTemplate(Rule r, string s, int depth, ref List<Hit> hits) { if (r.Broken) { return; } string[] prefilter = r.Prefilter; foreach (string value in prefilter) { if (s.IndexOf(value, StringComparison.Ordinal) < 0) { return; } } MatchCollection matchCollection; try { matchCollection = r.Re.Matches(s); if (matchCollection.Count == 0) { return; } } catch (RegexMatchTimeoutException) { r.Broken = true; return; } catch (ArgumentException) { r.Broken = true; return; } foreach (Match item in matchCollection) { if (item.Length == 0) { continue; } StringBuilder stringBuilder = new StringBuilder(); foreach (object ptPart in r.PtParts) { if (ptPart is string value2) { stringBuilder.Append(value2); continue; } string text = item.Groups[(int)ptPart + 1].Value; if (depth < 2 && text.Length > 1 && HasLetters(text)) { text = Translate(text, depth + 1); } stringBuilder.Append(text); } if (hits == null) { hits = new List<Hit>(); } hits.Add(new Hit { Start = item.Index, Length = item.Length, Replacement = stringBuilder.ToString() }); } } private static bool HasLetters(string s) { bool flag = false; foreach (char c in s) { switch (c) { case '<': flag = true; continue; case '>': flag = false; continue; } if (!flag && char.IsLetter(c)) { return true; } } return false; } } internal static class MiniJson { public static Dictionary<string, string> ParseFlatObject(string json) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal); int i = 0; SkipWs(json, ref i); Expect(json, ref i, '{'); SkipWs(json, ref i); if (Peek(json, i) == '}') { return dictionary; } while (true) { SkipWs(json, ref i); string key = ReadString(json, ref i); SkipWs(json, ref i); Expect(json, ref i, ':'); SkipWs(json, ref i); string value = ReadString(json, ref i); dictionary[key] = value; SkipWs(json, ref i); switch (Peek(json, i)) { case ',': break; case '}': i++; return dictionary; default: throw new FormatException("JSON inválido perto da posição " + i); } i++; } } private static char Peek(string s, int i) { if (i >= s.Length) { return '\0'; } return s[i]; } private static void SkipWs(string s, ref int i) { while (i < s.Length && char.IsWhiteSpace(s[i])) { i++; } } private static void Expect(string s, ref int i, char c) { if (Peek(s, i) != c) { throw new FormatException("Esperado '" + c + "' na posição " + i); } i++; } private static string ReadString(string s, ref int i) { Expect(s, ref i, '"'); StringBuilder stringBuilder = new StringBuilder(); while (i < s.Length) { char c = s[i++]; switch (c) { case '"': return stringBuilder.ToString(); default: stringBuilder.Append(c); continue; case '\\': break; } if (i >= s.Length) { break; } char c2 = s[i++]; switch (c2) { case 'n': stringBuilder.Append('\n'); break; case 't': stringBuilder.Append('\t'); break; case 'r': stringBuilder.Append('\r'); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case '"': stringBuilder.Append('"'); break; case '\\': stringBuilder.Append('\\'); break; case '/': stringBuilder.Append('/'); break; case 'u': if (i + 4 > s.Length) { throw new FormatException("Escape \\u incompleto"); } stringBuilder.Append((char)int.Parse(s.Substring(i, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture)); i += 4; break; default: stringBuilder.Append(c2); break; } } throw new FormatException("String JSON sem fechamento"); } } }