using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace PKHeX.Core { public static class LocalizationUtil { private const string TranslationSplitter = " = "; /// /// Gets the names of the properties defined in the given input /// /// Enumerable of translation definitions in the form "Property = Value". private static string[] GetProperties(IEnumerable input) { static string AfterSplit(string l) { var split = l.IndexOf(TranslationSplitter, StringComparison.Ordinal); return l[..split]; } return input.Select(AfterSplit).ToArray(); } private static IEnumerable DumpStrings(Type t) { var props = ReflectUtil.GetPropertiesStartWithPrefix(t, string.Empty); return props.Select(p => $"{p}{TranslationSplitter}{ReflectUtil.GetValue(t, p)}"); } /// /// Gets the current localization in a static class containing language-specific strings /// /// public static string[] GetLocalization(Type t) => DumpStrings(t).ToArray(); /// /// Gets the current localization in a static class containing language-specific strings /// /// /// Existing localization lines (if provided) public static string[] GetLocalization(Type t, string[] existingLines) { var currentLines = GetLocalization(t); var existing = GetProperties(existingLines); var current = GetProperties(currentLines); var result = new string[currentLines.Length]; for (int i = 0; i < current.Length; i++) { int index = Array.IndexOf(existing, current[i]); result[i] = index < 0 ? currentLines[i] : existingLines[index]; } return result; } /// /// Applies localization to a static class containing language-specific strings. /// /// Type of the static class containing the desired strings. /// Lines containing the localized strings private static void SetLocalization(Type t, IReadOnlyCollection lines) { if (lines.Count == 0) return; foreach (var line in lines) { var index = line.IndexOf(TranslationSplitter, StringComparison.Ordinal); if (index < 0) continue; var prop = line[..index]; var value = line[(index + TranslationSplitter.Length)..]; try { ReflectUtil.SetValue(t, prop, value); } #pragma warning disable CA1031 // Do not catch general exception types // Malformed translation files, log catch (Exception e) #pragma warning restore CA1031 // Do not catch general exception types { Debug.WriteLine($"Property not present: {prop} || Value written: {value}"); Debug.WriteLine(e.Message); } } } /// /// Applies localization to a static class containing language-specific strings. /// /// Type of the static class containing the desired strings. /// Prefix of the language file to use. Example: if the target is legality_en.txt, should be "legality". /// Culture information private static void SetLocalization(Type t, string languageFilePrefix, string currentCultureCode) { var lines = Util.GetStringList($"{languageFilePrefix}_{currentCultureCode}"); SetLocalization(t, lines); } /// /// Applies localization to a static class containing language-specific strings. /// /// Type of the static class containing the desired strings. /// The values used to translate the given static class are retrieved from [TypeName]_[CurrentLangCode2].txt in the resource manager of PKHeX.Core. /// Culture information public static void SetLocalization(Type t, string currentCultureCode) { SetLocalization(t, t.Name, currentCultureCode); } } }