Skip to content

Commit f7f52e2

Browse files
committed
Set culture info before creating application
1 parent b4a3e06 commit f7f52e2

File tree

3 files changed

+71
-38
lines changed

3 files changed

+71
-38
lines changed

Flow.Launcher.Core/Resource/Internationalization.cs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
34
using System.IO;
45
using System.Linq;
56
using System.Reflection;
7+
using System.Threading;
8+
using System.Threading.Tasks;
69
using System.Windows;
10+
using CommunityToolkit.Mvvm.DependencyInjection;
711
using Flow.Launcher.Core.Plugin;
812
using Flow.Launcher.Infrastructure;
913
using Flow.Launcher.Infrastructure.UserSettings;
1014
using Flow.Launcher.Plugin;
11-
using System.Globalization;
12-
using System.Threading.Tasks;
13-
using CommunityToolkit.Mvvm.DependencyInjection;
1415

1516
namespace Flow.Launcher.Core.Resource
1617
{
@@ -29,13 +30,12 @@ public class Internationalization
2930
private readonly Settings _settings;
3031
private readonly List<string> _languageDirectories = new();
3132
private readonly List<ResourceDictionary> _oldResources = new();
32-
private readonly string SystemLanguageCode;
33+
private static string SystemLanguageCode;
3334

3435
public Internationalization(Settings settings)
3536
{
3637
_settings = settings;
3738
AddFlowLauncherLanguageDirectory();
38-
SystemLanguageCode = GetSystemLanguageCodeAtStartup();
3939
}
4040

4141
private void AddFlowLauncherLanguageDirectory()
@@ -44,7 +44,7 @@ private void AddFlowLauncherLanguageDirectory()
4444
_languageDirectories.Add(directory);
4545
}
4646

47-
private static string GetSystemLanguageCodeAtStartup()
47+
public static void InitSystemLanguageCode()
4848
{
4949
var availableLanguages = AvailableLanguages.GetAvailableLanguages();
5050

@@ -65,11 +65,11 @@ private static string GetSystemLanguageCodeAtStartup()
6565
string.Equals(languageCode, threeLetterCode, StringComparison.OrdinalIgnoreCase) ||
6666
string.Equals(languageCode, fullName, StringComparison.OrdinalIgnoreCase))
6767
{
68-
return languageCode;
68+
SystemLanguageCode = languageCode;
6969
}
7070
}
7171

72-
return DefaultLanguageCode;
72+
SystemLanguageCode = DefaultLanguageCode;
7373
}
7474

7575
private void AddPluginLanguageDirectories()
@@ -173,15 +173,25 @@ private async Task ChangeLanguageAsync(Language language)
173173
LoadLanguage(language);
174174
}
175175

176-
// Culture of main thread
177-
// Use CreateSpecificCulture to preserve possible user-override settings in Windows, if Flow's language culture is the same as Windows's
178-
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(language.LanguageCode);
179-
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture;
176+
// Change culture info
177+
ChangeCultureInfo(language.LanguageCode);
180178

181179
// Raise event for plugins after culture is set
182180
await Task.Run(UpdatePluginMetadataTranslations);
183181
}
184182

183+
public static void ChangeCultureInfo(string languageCode)
184+
{
185+
// Culture of main thread
186+
// Use CreateSpecificCulture to preserve possible user-override settings in Windows, if Flow's language culture is the same as Windows's
187+
var currentCulture = CultureInfo.CreateSpecificCulture(languageCode);
188+
CultureInfo.CurrentCulture = currentCulture;
189+
CultureInfo.CurrentUICulture = currentCulture;
190+
var thread = Thread.CurrentThread;
191+
thread.CurrentCulture = currentCulture;
192+
thread.CurrentUICulture = currentCulture;
193+
}
194+
185195
public bool PromptShouldUsePinyin(string languageCodeToSet)
186196
{
187197
var languageToSet = GetLanguageByLanguageCode(languageCodeToSet);

Flow.Launcher.Infrastructure/UserSettings/Settings.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@ public void SetStorage(FlowLauncherJsonStorage<Settings> storage)
2525

2626
public void Initialize()
2727
{
28+
// Initialize dependency injection instances after Ioc.Default is created
2829
_stringMatcher = Ioc.Default.GetRequiredService<StringMatcher>();
30+
31+
// Initialize application resources after application is created
32+
var settingWindowFont = new FontFamily(SettingWindowFont);
33+
Application.Current.Resources["SettingWindowFont"] = settingWindowFont;
34+
Application.Current.Resources["ContentControlThemeFontFamily"] = settingWindowFont;
2935
}
3036

3137
public void Save()
@@ -114,8 +120,11 @@ public string SettingWindowFont
114120
{
115121
_settingWindowFont = value;
116122
OnPropertyChanged();
117-
Application.Current.Resources["SettingWindowFont"] = new FontFamily(value);
118-
Application.Current.Resources["ContentControlThemeFontFamily"] = new FontFamily(value);
123+
if (Application.Current != null)
124+
{
125+
Application.Current.Resources["SettingWindowFont"] = new FontFamily(value);
126+
Application.Current.Resources["ContentControlThemeFontFamily"] = new FontFamily(value);
127+
}
119128
}
120129
}
121130
}

Flow.Launcher/App.xaml.cs

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ public partial class App : IDisposable, ISingleInstanceApp
4141
private static readonly string ClassName = nameof(App);
4242

4343
private static bool _disposed;
44+
private static Settings _settings;
4445
private static MainWindow _mainWindow;
4546
private readonly MainViewModel _mainVM;
46-
private readonly Settings _settings;
4747

4848
// To prevent two disposals running at the same time.
4949
private static readonly object _disposingLock = new();
@@ -55,19 +55,7 @@ public partial class App : IDisposable, ISingleInstanceApp
5555
public App()
5656
{
5757
// Initialize settings
58-
try
59-
{
60-
var storage = new FlowLauncherJsonStorage<Settings>();
61-
_settings = storage.Load();
62-
_settings.SetStorage(storage);
63-
_settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled();
64-
}
65-
catch (Exception e)
66-
{
67-
ShowErrorMsgBoxAndFailFast("Cannot load setting storage, please check local data directory", e);
68-
return;
69-
}
70-
58+
_settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled();
7159
// Configure the dependency injection container
7260
try
7361
{
@@ -119,16 +107,6 @@ public App()
119107
ShowErrorMsgBoxAndFailFast("Cannot initialize api and settings, please open new issue in Flow.Launcher", e);
120108
return;
121109
}
122-
123-
// Local function
124-
static void ShowErrorMsgBoxAndFailFast(string message, Exception e)
125-
{
126-
// Firstly show users the message
127-
MessageBox.Show(e.ToString(), message, MessageBoxButton.OK, MessageBoxImage.Error);
128-
129-
// Flow cannot construct its App instance, so ensure Flow crashes w/ the exception info.
130-
Environment.FailFast(message, e);
131-
}
132110
}
133111

134112
#endregion
@@ -138,6 +116,29 @@ static void ShowErrorMsgBoxAndFailFast(string message, Exception e)
138116
[STAThread]
139117
public static void Main()
140118
{
119+
// Initialize settings so that we can get language code
120+
try
121+
{
122+
var storage = new FlowLauncherJsonStorage<Settings>();
123+
_settings = storage.Load();
124+
_settings.SetStorage(storage);
125+
}
126+
catch (Exception e)
127+
{
128+
ShowErrorMsgBoxAndFailFast("Cannot load setting storage, please check local data directory", e);
129+
return;
130+
}
131+
132+
// Initialize system language before changing culture info
133+
Internationalization.InitSystemLanguageCode();
134+
135+
// Change culture info before application creation to localize WinForm windows
136+
if (_settings.Language != Constant.SystemLanguageCode)
137+
{
138+
Internationalization.ChangeCultureInfo(_settings.Language);
139+
}
140+
141+
// Start the application as a single instance
141142
if (SingleInstance<App>.InitializeAsFirstInstance())
142143
{
143144
using var application = new App();
@@ -148,6 +149,19 @@ public static void Main()
148149

149150
#endregion
150151

152+
#region Fail Fast
153+
154+
private static void ShowErrorMsgBoxAndFailFast(string message, Exception e)
155+
{
156+
// Firstly show users the message
157+
MessageBox.Show(e.ToString(), message, MessageBoxButton.OK, MessageBoxImage.Error);
158+
159+
// Flow cannot construct its App instance, so ensure Flow crashes w/ the exception info.
160+
Environment.FailFast(message, e);
161+
}
162+
163+
#endregion
164+
151165
#region App Events
152166

153167
#pragma warning disable VSTHRD100 // Avoid async void methods

0 commit comments

Comments
 (0)