Skip to content

Commit c02ef0e

Browse files
authored
Merge pull request #3850 from Flow-Launcher/fast_load_language
Initialize language before portable clean up and plugin initialization
2 parents 6044fb4 + 545d12c commit c02ef0e

File tree

3 files changed

+125
-78
lines changed

3 files changed

+125
-78
lines changed

Flow.Launcher.Core/Plugin/PluginManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public static class PluginManager
4747
/// <summary>
4848
/// Directories that will hold Flow Launcher plugin directory
4949
/// </summary>
50-
private static readonly string[] Directories =
50+
public static readonly string[] Directories =
5151
{
5252
Constant.PreinstalledDirectory, DataLocation.PluginsDirectory
5353
};

Flow.Launcher.Core/Resource/Internationalization.cs

Lines changed: 119 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Globalization;
44
using System.IO;
55
using System.Linq;
6-
using System.Reflection;
76
using System.Threading;
87
using System.Threading.Tasks;
98
using System.Windows;
@@ -28,22 +27,20 @@ public class Internationalization
2827
private const string DefaultFile = "en.xaml";
2928
private const string Extension = ".xaml";
3029
private readonly Settings _settings;
31-
private readonly List<string> _languageDirectories = new();
32-
private readonly List<ResourceDictionary> _oldResources = new();
30+
private readonly List<string> _languageDirectories = [];
31+
private readonly List<ResourceDictionary> _oldResources = [];
3332
private static string SystemLanguageCode;
3433

3534
public Internationalization(Settings settings)
3635
{
3736
_settings = settings;
38-
AddFlowLauncherLanguageDirectory();
3937
}
4038

41-
private void AddFlowLauncherLanguageDirectory()
42-
{
43-
var directory = Path.Combine(Constant.ProgramDirectory, Folder);
44-
_languageDirectories.Add(directory);
45-
}
39+
#region Initialization
4640

41+
/// <summary>
42+
/// Initialize the system language code based on the current culture.
43+
/// </summary>
4744
public static void InitSystemLanguageCode()
4845
{
4946
var availableLanguages = AvailableLanguages.GetAvailableLanguages();
@@ -72,35 +69,6 @@ public static void InitSystemLanguageCode()
7269
SystemLanguageCode = DefaultLanguageCode;
7370
}
7471

75-
private void AddPluginLanguageDirectories()
76-
{
77-
foreach (var plugin in PluginManager.GetTranslationPlugins())
78-
{
79-
var location = Assembly.GetAssembly(plugin.Plugin.GetType()).Location;
80-
var dir = Path.GetDirectoryName(location);
81-
if (dir != null)
82-
{
83-
var pluginThemeDirectory = Path.Combine(dir, Folder);
84-
_languageDirectories.Add(pluginThemeDirectory);
85-
}
86-
else
87-
{
88-
API.LogError(ClassName, $"Can't find plugin path <{location}> for <{plugin.Metadata.Name}>");
89-
}
90-
}
91-
92-
LoadDefaultLanguage();
93-
}
94-
95-
private void LoadDefaultLanguage()
96-
{
97-
// Removes language files loaded before any plugins were loaded.
98-
// Prevents the language Flow started in from overwriting English if the user switches back to English
99-
RemoveOldLanguageFiles();
100-
LoadLanguage(AvailableLanguages.English);
101-
_oldResources.Clear();
102-
}
103-
10472
/// <summary>
10573
/// Initialize language. Will change app language and plugin language based on settings.
10674
/// </summary>
@@ -116,13 +84,64 @@ public async Task InitializeLanguageAsync()
11684
// Get language by language code and change language
11785
var language = GetLanguageByLanguageCode(languageCode);
11886

87+
// Add Flow Launcher language directory
88+
AddFlowLauncherLanguageDirectory();
89+
11990
// Add plugin language directories first so that we can load language files from plugins
12091
AddPluginLanguageDirectories();
12192

93+
// Load default language resources
94+
LoadDefaultLanguage();
95+
12296
// Change language
123-
await ChangeLanguageAsync(language);
97+
await ChangeLanguageAsync(language, false);
12498
}
12599

100+
private void AddFlowLauncherLanguageDirectory()
101+
{
102+
// Check if Flow Launcher language directory exists
103+
var directory = Path.Combine(Constant.ProgramDirectory, Folder);
104+
if (!Directory.Exists(directory))
105+
{
106+
API.LogError(ClassName, $"Flow Launcher language directory can't be found <{directory}>");
107+
return;
108+
}
109+
110+
_languageDirectories.Add(directory);
111+
}
112+
113+
private void AddPluginLanguageDirectories()
114+
{
115+
foreach (var pluginsDir in PluginManager.Directories)
116+
{
117+
if (!Directory.Exists(pluginsDir)) continue;
118+
119+
// Enumerate all top directories in the plugin directory
120+
foreach (var dir in Directory.GetDirectories(pluginsDir))
121+
{
122+
// Check if the directory contains a language folder
123+
var pluginLanguageDir = Path.Combine(dir, Folder);
124+
if (!Directory.Exists(pluginLanguageDir)) continue;
125+
126+
// Check if the language directory contains default language file since it will be checked later
127+
_languageDirectories.Add(pluginLanguageDir);
128+
}
129+
}
130+
}
131+
132+
private void LoadDefaultLanguage()
133+
{
134+
// Removes language files loaded before any plugins were loaded.
135+
// Prevents the language Flow started in from overwriting English if the user switches back to English
136+
RemoveOldLanguageFiles();
137+
LoadLanguage(AvailableLanguages.English);
138+
_oldResources.Clear();
139+
}
140+
141+
#endregion
142+
143+
#region Change Language
144+
126145
/// <summary>
127146
/// Change language during runtime. Will change app language and plugin language & save settings.
128147
/// </summary>
@@ -151,8 +170,8 @@ public void ChangeLanguage(string languageCode)
151170

152171
private static Language GetLanguageByLanguageCode(string languageCode)
153172
{
154-
var lowercase = languageCode.ToLower();
155-
var language = AvailableLanguages.GetAvailableLanguages().FirstOrDefault(o => o.LanguageCode.ToLower() == lowercase);
173+
var language = AvailableLanguages.GetAvailableLanguages().
174+
FirstOrDefault(o => o.LanguageCode.Equals(languageCode, StringComparison.OrdinalIgnoreCase));
156175
if (language == null)
157176
{
158177
API.LogError(ClassName, $"Language code can't be found <{languageCode}>");
@@ -164,7 +183,7 @@ private static Language GetLanguageByLanguageCode(string languageCode)
164183
}
165184
}
166185

167-
private async Task ChangeLanguageAsync(Language language)
186+
private async Task ChangeLanguageAsync(Language language, bool updateMetadata = true)
168187
{
169188
// Remove old language files and load language
170189
RemoveOldLanguageFiles();
@@ -176,8 +195,11 @@ private async Task ChangeLanguageAsync(Language language)
176195
// Change culture info
177196
ChangeCultureInfo(language.LanguageCode);
178197

179-
// Raise event for plugins after culture is set
180-
await Task.Run(UpdatePluginMetadataTranslations);
198+
if (updateMetadata)
199+
{
200+
// Raise event for plugins after culture is set
201+
await Task.Run(UpdatePluginMetadataTranslations);
202+
}
181203
}
182204

183205
public static void ChangeCultureInfo(string languageCode)
@@ -200,6 +222,10 @@ public static void ChangeCultureInfo(string languageCode)
200222
thread.CurrentUICulture = currentCulture;
201223
}
202224

225+
#endregion
226+
227+
#region Prompt Pinyin
228+
203229
public bool PromptShouldUsePinyin(string languageCodeToSet)
204230
{
205231
var languageToSet = GetLanguageByLanguageCode(languageCodeToSet);
@@ -212,14 +238,18 @@ public bool PromptShouldUsePinyin(string languageCodeToSet)
212238

213239
// No other languages should show the following text so just make it hard-coded
214240
// "Do you want to search with pinyin?"
215-
string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?" ;
241+
string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?";
216242

217243
if (API.ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No)
218244
return false;
219245

220246
return true;
221247
}
222248

249+
#endregion
250+
251+
#region Language Resources Management
252+
223253
private void RemoveOldLanguageFiles()
224254
{
225255
var dicts = Application.Current.Resources.MergedDictionaries;
@@ -255,13 +285,51 @@ private void LoadLanguage(Language language)
255285
}
256286
}
257287

288+
private static string LanguageFile(string folder, string language)
289+
{
290+
if (Directory.Exists(folder))
291+
{
292+
var path = Path.Combine(folder, language);
293+
if (File.Exists(path))
294+
{
295+
return path;
296+
}
297+
else
298+
{
299+
API.LogError(ClassName, $"Language path can't be found <{path}>");
300+
var english = Path.Combine(folder, DefaultFile);
301+
if (File.Exists(english))
302+
{
303+
return english;
304+
}
305+
else
306+
{
307+
API.LogError(ClassName, $"Default English Language path can't be found <{path}>");
308+
return string.Empty;
309+
}
310+
}
311+
}
312+
else
313+
{
314+
return string.Empty;
315+
}
316+
}
317+
318+
#endregion
319+
320+
#region Available Languages
321+
258322
public List<Language> LoadAvailableLanguages()
259323
{
260324
var list = AvailableLanguages.GetAvailableLanguages();
261325
list.Insert(0, new Language(Constant.SystemLanguageCode, AvailableLanguages.GetSystemTranslation(SystemLanguageCode)));
262326
return list;
263327
}
264328

329+
#endregion
330+
331+
#region Get Translations
332+
265333
public static string GetTranslation(string key)
266334
{
267335
var translation = Application.Current.TryFindResource(key);
@@ -276,7 +344,11 @@ public static string GetTranslation(string key)
276344
}
277345
}
278346

279-
private void UpdatePluginMetadataTranslations()
347+
#endregion
348+
349+
#region Update Metadata
350+
351+
public static void UpdatePluginMetadataTranslations()
280352
{
281353
// Update plugin metadata name & description
282354
foreach (var p in PluginManager.GetTranslationPlugins())
@@ -295,34 +367,6 @@ private void UpdatePluginMetadataTranslations()
295367
}
296368
}
297369

298-
private static string LanguageFile(string folder, string language)
299-
{
300-
if (Directory.Exists(folder))
301-
{
302-
var path = Path.Combine(folder, language);
303-
if (File.Exists(path))
304-
{
305-
return path;
306-
}
307-
else
308-
{
309-
API.LogError(ClassName, $"Language path can't be found <{path}>");
310-
var english = Path.Combine(folder, DefaultFile);
311-
if (File.Exists(english))
312-
{
313-
return english;
314-
}
315-
else
316-
{
317-
API.LogError(ClassName, $"Default English Language path can't be found <{path}>");
318-
return string.Empty;
319-
}
320-
}
321-
}
322-
else
323-
{
324-
return string.Empty;
325-
}
326-
}
370+
#endregion
327371
}
328372
}

Flow.Launcher/App.xaml.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ await API.StopwatchLogInfoAsync(ClassName, "Startup cost", async () =>
192192
// Enable Win32 dark mode if the system is in dark mode before creating all windows
193193
Win32Helper.EnableWin32DarkMode(_settings.ColorScheme);
194194

195+
// Initialize language before portable clean up since it needs translations
196+
await Ioc.Default.GetRequiredService<Internationalization>().InitializeLanguageAsync();
197+
195198
Ioc.Default.GetRequiredService<Portable>().PreStartCleanUpAfterPortabilityUpdate();
196199

197200
API.LogInfo(ClassName, "Begin Flow Launcher startup ----------------------------------------------------");
@@ -217,8 +220,8 @@ await API.StopwatchLogInfoAsync(ClassName, "Startup cost", async () =>
217220

218221
await PluginManager.InitializePluginsAsync();
219222

220-
// Change language after all plugins are initialized because we need to update plugin title based on their api
221-
await Ioc.Default.GetRequiredService<Internationalization>().InitializeLanguageAsync();
223+
// Update plugin titles after plugins are initialized with their api instances
224+
Internationalization.UpdatePluginMetadataTranslations();
222225

223226
await imageLoadertask;
224227

0 commit comments

Comments
 (0)