mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge pull request #3566 from Flow-Launcher/winform_language_issue
Fix plugin culture info issue for those that use WinForm
This commit is contained in:
commit
5e026c0c20
4 changed files with 94 additions and 40 deletions
|
|
@ -1,16 +1,17 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||||
using Flow.Launcher.Core.Plugin;
|
using Flow.Launcher.Core.Plugin;
|
||||||
using Flow.Launcher.Infrastructure;
|
using Flow.Launcher.Infrastructure;
|
||||||
using Flow.Launcher.Infrastructure.UserSettings;
|
using Flow.Launcher.Infrastructure.UserSettings;
|
||||||
using Flow.Launcher.Plugin;
|
using Flow.Launcher.Plugin;
|
||||||
using System.Globalization;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
|
||||||
|
|
||||||
namespace Flow.Launcher.Core.Resource
|
namespace Flow.Launcher.Core.Resource
|
||||||
{
|
{
|
||||||
|
|
@ -29,13 +30,12 @@ namespace Flow.Launcher.Core.Resource
|
||||||
private readonly Settings _settings;
|
private readonly Settings _settings;
|
||||||
private readonly List<string> _languageDirectories = new();
|
private readonly List<string> _languageDirectories = new();
|
||||||
private readonly List<ResourceDictionary> _oldResources = new();
|
private readonly List<ResourceDictionary> _oldResources = new();
|
||||||
private readonly string SystemLanguageCode;
|
private static string SystemLanguageCode;
|
||||||
|
|
||||||
public Internationalization(Settings settings)
|
public Internationalization(Settings settings)
|
||||||
{
|
{
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
AddFlowLauncherLanguageDirectory();
|
AddFlowLauncherLanguageDirectory();
|
||||||
SystemLanguageCode = GetSystemLanguageCodeAtStartup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddFlowLauncherLanguageDirectory()
|
private void AddFlowLauncherLanguageDirectory()
|
||||||
|
|
@ -44,7 +44,7 @@ namespace Flow.Launcher.Core.Resource
|
||||||
_languageDirectories.Add(directory);
|
_languageDirectories.Add(directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetSystemLanguageCodeAtStartup()
|
public static void InitSystemLanguageCode()
|
||||||
{
|
{
|
||||||
var availableLanguages = AvailableLanguages.GetAvailableLanguages();
|
var availableLanguages = AvailableLanguages.GetAvailableLanguages();
|
||||||
|
|
||||||
|
|
@ -65,11 +65,11 @@ namespace Flow.Launcher.Core.Resource
|
||||||
string.Equals(languageCode, threeLetterCode, StringComparison.OrdinalIgnoreCase) ||
|
string.Equals(languageCode, threeLetterCode, StringComparison.OrdinalIgnoreCase) ||
|
||||||
string.Equals(languageCode, fullName, StringComparison.OrdinalIgnoreCase))
|
string.Equals(languageCode, fullName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return languageCode;
|
SystemLanguageCode = languageCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefaultLanguageCode;
|
SystemLanguageCode = DefaultLanguageCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddPluginLanguageDirectories()
|
private void AddPluginLanguageDirectories()
|
||||||
|
|
@ -173,15 +173,33 @@ namespace Flow.Launcher.Core.Resource
|
||||||
LoadLanguage(language);
|
LoadLanguage(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Culture of main thread
|
// Change culture info
|
||||||
// Use CreateSpecificCulture to preserve possible user-override settings in Windows, if Flow's language culture is the same as Windows's
|
ChangeCultureInfo(language.LanguageCode);
|
||||||
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(language.LanguageCode);
|
|
||||||
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture;
|
|
||||||
|
|
||||||
// Raise event for plugins after culture is set
|
// Raise event for plugins after culture is set
|
||||||
await Task.Run(UpdatePluginMetadataTranslations);
|
await Task.Run(UpdatePluginMetadataTranslations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ChangeCultureInfo(string languageCode)
|
||||||
|
{
|
||||||
|
// Culture of main thread
|
||||||
|
// Use CreateSpecificCulture to preserve possible user-override settings in Windows, if Flow's language culture is the same as Windows's
|
||||||
|
CultureInfo currentCulture;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
currentCulture = CultureInfo.CreateSpecificCulture(languageCode);
|
||||||
|
}
|
||||||
|
catch (CultureNotFoundException)
|
||||||
|
{
|
||||||
|
currentCulture = CultureInfo.CreateSpecificCulture(SystemLanguageCode);
|
||||||
|
}
|
||||||
|
CultureInfo.CurrentCulture = currentCulture;
|
||||||
|
CultureInfo.CurrentUICulture = currentCulture;
|
||||||
|
var thread = Thread.CurrentThread;
|
||||||
|
thread.CurrentCulture = currentCulture;
|
||||||
|
thread.CurrentUICulture = currentCulture;
|
||||||
|
}
|
||||||
|
|
||||||
public bool PromptShouldUsePinyin(string languageCodeToSet)
|
public bool PromptShouldUsePinyin(string languageCodeToSet)
|
||||||
{
|
{
|
||||||
var languageToSet = GetLanguageByLanguageCode(languageCodeToSet);
|
var languageToSet = GetLanguageByLanguageCode(languageCodeToSet);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,13 @@ namespace Flow.Launcher.Infrastructure.UserSettings
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
|
// Initialize dependency injection instances after Ioc.Default is created
|
||||||
_stringMatcher = Ioc.Default.GetRequiredService<StringMatcher>();
|
_stringMatcher = Ioc.Default.GetRequiredService<StringMatcher>();
|
||||||
|
|
||||||
|
// Initialize application resources after application is created
|
||||||
|
var settingWindowFont = new FontFamily(SettingWindowFont);
|
||||||
|
Application.Current.Resources["SettingWindowFont"] = settingWindowFont;
|
||||||
|
Application.Current.Resources["ContentControlThemeFontFamily"] = settingWindowFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
|
|
@ -119,8 +125,11 @@ namespace Flow.Launcher.Infrastructure.UserSettings
|
||||||
{
|
{
|
||||||
_settingWindowFont = value;
|
_settingWindowFont = value;
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
Application.Current.Resources["SettingWindowFont"] = new FontFamily(value);
|
if (Application.Current != null)
|
||||||
Application.Current.Resources["ContentControlThemeFontFamily"] = new FontFamily(value);
|
{
|
||||||
|
Application.Current.Resources["SettingWindowFont"] = new FontFamily(value);
|
||||||
|
Application.Current.Resources["ContentControlThemeFontFamily"] = new FontFamily(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,9 @@ namespace Flow.Launcher
|
||||||
private static readonly string ClassName = nameof(App);
|
private static readonly string ClassName = nameof(App);
|
||||||
|
|
||||||
private static bool _disposed;
|
private static bool _disposed;
|
||||||
|
private static Settings _settings;
|
||||||
private static MainWindow _mainWindow;
|
private static MainWindow _mainWindow;
|
||||||
private readonly MainViewModel _mainVM;
|
private readonly MainViewModel _mainVM;
|
||||||
private readonly Settings _settings;
|
|
||||||
|
|
||||||
// To prevent two disposals running at the same time.
|
// To prevent two disposals running at the same time.
|
||||||
private static readonly object _disposingLock = new();
|
private static readonly object _disposingLock = new();
|
||||||
|
|
@ -55,18 +55,7 @@ namespace Flow.Launcher
|
||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
// Initialize settings
|
// Initialize settings
|
||||||
try
|
_settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled();
|
||||||
{
|
|
||||||
var storage = new FlowLauncherJsonStorage<Settings>();
|
|
||||||
_settings = storage.Load();
|
|
||||||
_settings.SetStorage(storage);
|
|
||||||
_settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ShowErrorMsgBoxAndFailFast("Cannot load setting storage, please check local data directory", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the dependency injection container
|
// Configure the dependency injection container
|
||||||
try
|
try
|
||||||
|
|
@ -123,16 +112,6 @@ namespace Flow.Launcher
|
||||||
ShowErrorMsgBoxAndFailFast("Cannot initialize api and settings, please open new issue in Flow.Launcher", e);
|
ShowErrorMsgBoxAndFailFast("Cannot initialize api and settings, please open new issue in Flow.Launcher", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Local function
|
|
||||||
static void ShowErrorMsgBoxAndFailFast(string message, Exception e)
|
|
||||||
{
|
|
||||||
// Firstly show users the message
|
|
||||||
MessageBox.Show(e.ToString(), message, MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
|
|
||||||
// Flow cannot construct its App instance, so ensure Flow crashes w/ the exception info.
|
|
||||||
Environment.FailFast(message, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
@ -142,6 +121,29 @@ namespace Flow.Launcher
|
||||||
[STAThread]
|
[STAThread]
|
||||||
public static void Main()
|
public static void Main()
|
||||||
{
|
{
|
||||||
|
// Initialize settings so that we can get language code
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var storage = new FlowLauncherJsonStorage<Settings>();
|
||||||
|
_settings = storage.Load();
|
||||||
|
_settings.SetStorage(storage);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ShowErrorMsgBoxAndFailFast("Cannot load setting storage, please check local data directory", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize system language before changing culture info
|
||||||
|
Internationalization.InitSystemLanguageCode();
|
||||||
|
|
||||||
|
// Change culture info before application creation to localize WinForm windows
|
||||||
|
if (_settings.Language != Constant.SystemLanguageCode)
|
||||||
|
{
|
||||||
|
Internationalization.ChangeCultureInfo(_settings.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the application as a single instance
|
||||||
if (SingleInstance<App>.InitializeAsFirstInstance())
|
if (SingleInstance<App>.InitializeAsFirstInstance())
|
||||||
{
|
{
|
||||||
using var application = new App();
|
using var application = new App();
|
||||||
|
|
@ -152,6 +154,19 @@ namespace Flow.Launcher
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Fail Fast
|
||||||
|
|
||||||
|
private static void ShowErrorMsgBoxAndFailFast(string message, Exception e)
|
||||||
|
{
|
||||||
|
// Firstly show users the message
|
||||||
|
MessageBox.Show(e.ToString(), message, MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
|
||||||
|
// Flow cannot construct its App instance, so ensure Flow crashes w/ the exception info.
|
||||||
|
Environment.FailFast(message, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region App Events
|
#region App Events
|
||||||
|
|
||||||
#pragma warning disable VSTHRD100 // Avoid async void methods
|
#pragma warning disable VSTHRD100 // Avoid async void methods
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,23 @@
|
||||||
using Microsoft.Win32;
|
using System;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
namespace Flow.Launcher.Helper;
|
namespace Flow.Launcher.Helper;
|
||||||
|
|
||||||
internal static class WindowsMediaPlayerHelper
|
internal static class WindowsMediaPlayerHelper
|
||||||
{
|
{
|
||||||
|
private static readonly string ClassName = nameof(WindowsMediaPlayerHelper);
|
||||||
|
|
||||||
internal static bool IsWindowsMediaPlayerInstalled()
|
internal static bool IsWindowsMediaPlayerInstalled()
|
||||||
{
|
{
|
||||||
using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\MediaPlayer");
|
try
|
||||||
return key?.GetValue("Installation Directory") != null;
|
{
|
||||||
|
using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\MediaPlayer");
|
||||||
|
return key?.GetValue("Installation Directory") != null;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
App.API.LogException(ClassName, "Failed to check if Windows Media Player is installed", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue