LenovoLegionToolkit
177 строк · 5.1 Кб
1using System;2using System.Globalization;3using System.IO;4using System.Linq;5using System.Runtime.InteropServices;6using System.Threading;7using System.Threading.Tasks;8using System.Windows;9using Humanizer;10using LenovoLegionToolkit.Lib.Utils;11using LenovoLegionToolkit.WPF.Resources;12using LenovoLegionToolkit.WPF.Windows.Utils;13using Windows.Win32;14using Windows.Win32.Foundation;15
16namespace LenovoLegionToolkit.WPF.Utils;17
18public static class LocalizationHelper19{
20private static readonly string LanguagePath = Path.Combine(Folders.AppData, "lang");21
22private static readonly CultureInfo DefaultLanguage = new("en");23
24public static readonly CultureInfo[] Languages = {25DefaultLanguage,26new("ar"),27new("bg"),28new("cs"),29new("de"),30new("el"),31new("es"),32new("fr"),33new("it"),34new("lv"),35new("nl-nl"),36new("pt"),37new("pt-br"),38new("ro"),39new("ru"),40new("sk"),41new("tr"),42new("uk"),43new("vi"),44new("zh-hans"),45new("zh-hant"),46// HACK: Karakalpak is not a recognized culture by msbuild, so we use this one as workaround instead.47new("uz-latn-uz")48};49
50public static FlowDirection Direction => Resource.Culture?.TextInfo.IsRightToLeft ?? false51? FlowDirection.RightToLeft52: FlowDirection.LeftToRight;53
54private static string? _dateFormat;55
56public static string ShortDateFormat57{58get59{60if (_dateFormat is not null)61return _dateFormat;62
63_dateFormat = GetSystemShortDateFormat() ?? "dd/M/yyyy";64return _dateFormat;65}66}67
68public static string LanguageDisplayName(CultureInfo culture)69{70var name = culture.NativeName.Transform(culture, To.TitleCase);71
72if (culture.IetfLanguageTag.Equals("uz-latn-uz", StringComparison.InvariantCultureIgnoreCase))73name = "Karakalpak";74
75return ForceLeftToRight(name);76}77
78public static string ForceLeftToRight(string str)79{80if (Resource.Culture?.TextInfo.IsRightToLeft ?? false)81return "\u200e" + str + "\u200e";82return str;83}84
85public static async Task SetLanguageAsync(bool interactive = false)86{87CultureInfo? cultureInfo = null;88
89if (interactive && await GetLanguageFromFile() is null)90{91var window = new LanguageSelectorWindow(Languages, DefaultLanguage);92window.Show();93cultureInfo = await window.ShouldContinue;94if (cultureInfo is not null)95await SaveLanguageToFileAsync(cultureInfo);96}97
98cultureInfo ??= await GetLanguageAsync();99
100SetLanguageInternal(cultureInfo);101}102
103public static async Task SetLanguageAsync(CultureInfo cultureInfo)104{105await SaveLanguageToFileAsync(cultureInfo);106SetLanguageInternal(cultureInfo);107}108
109public static async Task<CultureInfo> GetLanguageAsync()110{111var cultureInfo = await GetLanguageFromFile();112if (cultureInfo is null)113{114cultureInfo = DefaultLanguage;115await SaveLanguageToFileAsync(cultureInfo);116}117return cultureInfo;118}119
120private static async Task<CultureInfo?> GetLanguageFromFile()121{122try123{124var name = await File.ReadAllTextAsync(LanguagePath);125var cultureInfo = new CultureInfo(name);126if (!Languages.Contains(cultureInfo))127throw new InvalidOperationException("Unknown language.");128return cultureInfo;129}130catch131{132return null;133}134}135
136private static Task SaveLanguageToFileAsync(CultureInfo cultureInfo) => File.WriteAllTextAsync(LanguagePath, cultureInfo.Name);137
138private static void SetLanguageInternal(CultureInfo cultureInfo)139{140Thread.CurrentThread.CurrentCulture = new CultureInfo("en");141CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en");142
143Thread.CurrentThread.CurrentUICulture = cultureInfo;144CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;145
146Resource.Culture = cultureInfo;147Lib.Resources.Resource.Culture = cultureInfo;148Lib.Automation.Resources.Resource.Culture = cultureInfo;149
150if (Log.Instance.IsTraceEnabled)151Log.Instance.Trace($"Applied culture: {cultureInfo.Name}");152}153
154private static unsafe string? GetSystemShortDateFormat()155{156var ptr = IntPtr.Zero;157try158{159var length = PInvoke.GetLocaleInfoEx((string?)null, PInvoke.LOCALE_SSHORTDATE, null, 0);160if (length == 0)161return null;162
163ptr = Marshal.AllocHGlobal(sizeof(char) * length);164var charPtr = new PWSTR((char*)ptr.ToPointer());165
166length = PInvoke.GetLocaleInfoEx((string?)null, PInvoke.LOCALE_SSHORTDATE, charPtr, length);167if (length == 0)168return null;169
170return charPtr.ToString();171}172finally173{174Marshal.FreeHGlobal(ptr);175}176}177}
178