Merge pull request #3849 from Flow-Launcher/translations

Add Translations for All Messages and Message Boxes
This commit is contained in:
Jeremy Wu 2025-07-20 15:12:01 +10:00 committed by GitHub
commit ff2d5e89f9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 96 additions and 68 deletions

View file

@ -45,8 +45,7 @@ namespace Flow.Launcher.Core.Configuration
#endif
IndicateDeletion(DataLocation.PortableDataPath);
API.ShowMsgBox("Flow Launcher needs to restart to finish disabling portable mode, " +
"after the restart your portable data profile will be deleted and roaming data profile kept");
API.ShowMsgBox(API.GetTranslation("restartToDisablePortableMode"));
UpdateManager.RestartApp(Constant.ApplicationFileName);
}
@ -69,8 +68,7 @@ namespace Flow.Launcher.Core.Configuration
#endif
IndicateDeletion(DataLocation.RoamingDataPath);
API.ShowMsgBox("Flow Launcher needs to restart to finish enabling portable mode, " +
"after the restart your roaming data profile will be deleted and portable data profile kept");
API.ShowMsgBox(API.GetTranslation("restartToEnablePortableMode"));
UpdateManager.RestartApp(Constant.ApplicationFileName);
}
@ -154,9 +152,8 @@ namespace Flow.Launcher.Core.Configuration
{
FilesFolders.RemoveFolderIfExists(roamingDataDir, (s) => API.ShowMsgBox(s));
if (API.ShowMsgBox("Flow Launcher has detected you enabled portable mode, " +
"would you like to move it to a different location?", string.Empty,
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
if (API.ShowMsgBox(API.GetTranslation("moveToDifferentLocation"),
string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
FilesFolders.OpenPath(Constant.RootDirectory, (s) => API.ShowMsgBox(s));
@ -169,8 +166,7 @@ namespace Flow.Launcher.Core.Configuration
{
FilesFolders.RemoveFolderIfExists(portableDataDir, (s) => API.ShowMsgBox(s));
API.ShowMsgBox("Flow Launcher has detected you disabled portable mode, " +
"the relevant shortcuts and uninstaller entry have been created");
API.ShowMsgBox(API.GetTranslation("shortcutsUninstallerCreated"));
}
}
@ -181,9 +177,8 @@ namespace Flow.Launcher.Core.Configuration
if (roamingLocationExists && portableLocationExists)
{
API.ShowMsgBox(string.Format("Flow Launcher detected your user data exists both in {0} and " +
"{1}. {2}{2}Please delete {1} in order to proceed. No changes have occurred.",
DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine));
API.ShowMsgBox(string.Format(API.GetTranslation("userDataDuplicated"),
DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine));
return false;
}

View file

@ -22,6 +22,10 @@ namespace Flow.Launcher.Core.ExternalPlugins
private static DateTime lastFetchedAt = DateTime.MinValue;
private static readonly TimeSpan fetchTimeout = TimeSpan.FromMinutes(2);
// We should not initialize API in static constructor because it will create another API instance
private static IPublicAPI api = null;
private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService<IPublicAPI>();
public static List<UserPlugin> UserPlugins { get; private set; }
public static async Task<bool> UpdateManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default)
@ -46,7 +50,7 @@ namespace Flow.Launcher.Core.ExternalPlugins
}
catch (Exception e)
{
Ioc.Default.GetRequiredService<IPublicAPI>().LogException(ClassName, "Http request failed", e);
API.LogException(ClassName, "Http request failed", e);
}
finally
{

View file

@ -719,7 +719,7 @@ namespace Flow.Launcher.Core.Plugin
catch (Exception e)
{
API.LogException(ClassName, $"Failed to delete plugin settings folder for {plugin.Name}", e);
API.ShowMsg(API.GetTranslation("failedToRemovePluginSettingsTitle"),
API.ShowMsgError(API.GetTranslation("failedToRemovePluginSettingsTitle"),
string.Format(API.GetTranslation("failedToRemovePluginSettingsMessage"), plugin.Name));
}
}
@ -735,7 +735,7 @@ namespace Flow.Launcher.Core.Plugin
catch (Exception e)
{
API.LogException(ClassName, $"Failed to delete plugin cache folder for {plugin.Name}", e);
API.ShowMsg(API.GetTranslation("failedToRemovePluginCacheTitle"),
API.ShowMsgError(API.GetTranslation("failedToRemovePluginCacheTitle"),
string.Format(API.GetTranslation("failedToRemovePluginCacheMessage"), plugin.Name));
}
Settings.RemovePluginSettings(plugin.ID);

View file

@ -120,15 +120,15 @@ namespace Flow.Launcher.Core.Plugin
{
var errorPluginString = string.Join(Environment.NewLine, erroredPlugins);
var errorMessage = "The following "
+ (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ")
+ "errored and cannot be loaded:";
var errorMessage = erroredPlugins.Count > 1 ?
API.GetTranslation("pluginsHaveErrored") :
API.GetTranslation("pluginHasErrored");
_ = Task.Run(() =>
{
Ioc.Default.GetRequiredService<IPublicAPI>().ShowMsgBox($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
API.ShowMsgBox($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
$"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
$"Please refer to the logs for more information", "",
API.GetTranslation("referToLogs"), string.Empty,
MessageBoxButton.OK, MessageBoxImage.Warning);
});
}

View file

@ -214,7 +214,7 @@ namespace Flow.Launcher.Core.Resource
// "Do you want to search with pinyin?"
string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?" ;
if (Ioc.Default.GetRequiredService<IPublicAPI>().ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No)
if (API.ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No)
return false;
return true;

View file

@ -111,7 +111,7 @@ namespace Flow.Launcher.Core
}
if (!silentUpdate)
_api.ShowMsg(_api.GetTranslation("update_flowlauncher_fail"),
_api.ShowMsgError(_api.GetTranslation("update_flowlauncher_fail"),
_api.GetTranslation("update_flowlauncher_check_connection"));
}
finally

View file

@ -20,6 +20,10 @@ namespace Flow.Launcher.Infrastructure.Http
private static readonly HttpClient client = new();
// We should not initialize API in static constructor because it will create another API instance
private static IPublicAPI api = null;
private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService<IPublicAPI>();
static Http()
{
// need to be added so it would work on a win10 machine
@ -78,7 +82,7 @@ namespace Flow.Launcher.Infrastructure.Http
}
catch (UriFormatException e)
{
Ioc.Default.GetRequiredService<IPublicAPI>().ShowMsg("Please try again", "Unable to parse Http Proxy");
API.ShowMsgError(API.GetTranslation("pleaseTryAgain"), API.GetTranslation("parseProxyFailed"));
Log.Exception(ClassName, "Unable to parse Uri", e);
}
}

View file

@ -267,7 +267,7 @@ namespace Flow.Launcher
// but if it fails (permissions, etc) then don't keep retrying
// this also gives the user a visual indication in the Settings widget
_settings.StartFlowLauncherOnSystemStartup = false;
API.ShowMsg(API.GetTranslation("setAutoStartFailed"), e.Message);
API.ShowMsgError(API.GetTranslation("setAutoStartFailed"), e.Message);
}
}
}

View file

@ -18,6 +18,22 @@
<system:String x:Key="failedToInitializePluginsTitle">Fail to Init Plugins</system:String>
<system:String x:Key="failedToInitializePluginsMessage">Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help</system:String>
<!-- Portable -->
<system:String x:Key="restartToDisablePortableMode">Flow Launcher needs to restart to finish disabling portable mode, after the restart your portable data profile will be deleted and roaming data profile kept</system:String>
<system:String x:Key="restartToEnablePortableMode">Flow Launcher needs to restart to finish enabling portable mode, after the restart your roaming data profile will be deleted and portable data profile kept</system:String>
<system:String x:Key="moveToDifferentLocation">Flow Launcher has detected you enabled portable mode, would you like to move it to a different location?</system:String>
<system:String x:Key="shortcutsUninstallerCreated">Flow Launcher has detected you disabled portable mode, the relevant shortcuts and uninstaller entry have been created</system:String>
<system:String x:Key="userDataDuplicated">Flow Launcher detected your user data exists both in {0} and {1}. {2}{2}Please delete {1} in order to proceed. No changes have occurred.</system:String>
<!-- Plugin Loader -->
<system:String x:Key="pluginHasErrored">The following plugin has errored and cannot be loaded:</system:String>
<system:String x:Key="pluginsHaveErrored">The following plugins have errored and cannot be loaded:</system:String>
<system:String x:Key="referToLogs">Please refer to the logs for more information</system:String>
<!-- Http -->
<system:String x:Key="pleaseTryAgain">Please try again</system:String>
<system:String x:Key="parseProxyFailed">Unable to parse Http Proxy</system:String>
<!-- MainWindow -->
<system:String x:Key="registerHotkeyFailed">Failed to register hotkey "{0}". The hotkey may be in use by another program. Change to a different hotkey, or exit another program.</system:String>
<system:String x:Key="unregisterHotkeyFailed">Failed to unregister hotkey "{0}". Please try again or see log for details</system:String>
@ -140,6 +156,8 @@
<system:String x:Key="KoreanImeOpenLinkButton">Open</system:String>
<system:String x:Key="KoreanImeRegistry">Use Previous Korean IME</system:String>
<system:String x:Key="KoreanImeRegistryTooltip">You can change the Previous Korean IME settings directly from here</system:String>
<system:String x:Key="KoreanImeSettingChangeFailTitle">Failed to change Korean IME setting</system:String>
<system:String x:Key="KoreanImeSettingChangeFailSubTitle">Please check your system registry access or contact support.</system:String>
<system:String x:Key="homePage">Home Page</system:String>
<system:String x:Key="homePageToolTip">Show home page results when query text is empty.</system:String>
<system:String x:Key="historyResultsForHomePage">Show History Results in Home Page</system:String>

View file

@ -59,7 +59,7 @@ namespace Flow.Launcher.Resources.Pages
}
catch (Exception e)
{
App.API.ShowMsg(App.API.GetTranslation("setAutoStartFailed"), e.Message);
App.API.ShowMsgError(App.API.GetTranslation("setAutoStartFailed"), e.Message);
}
}

View file

@ -64,7 +64,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
}
catch (Exception e)
{
App.API.ShowMsg(App.API.GetTranslation("setAutoStartFailed"), e.Message);
App.API.ShowMsgError(App.API.GetTranslation("setAutoStartFailed"), e.Message);
}
}
}
@ -91,7 +91,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
}
catch (Exception e)
{
App.API.ShowMsg(App.API.GetTranslation("setAutoStartFailed"), e.Message);
App.API.ShowMsgError(App.API.GetTranslation("setAutoStartFailed"), e.Message);
}
}
}
@ -216,8 +216,8 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
}
else
{
//Since this is rarely seen text, language support is not provided.
App.API.ShowMsg("Failed to change Korean IME setting", "Please check your system registry access or contact support.");
// Since this is rarely seen text, language support is not provided.
App.API.ShowMsgError(App.API.GetTranslation("KoreanImeSettingChangeFailTitle"), App.API.GetTranslation("KoreanImeSettingChangeFailSubTitle"));
}
}
}

View file

@ -7,6 +7,9 @@
<system:String x:Key="flowlauncher_plugin_browserbookmark_plugin_name">Browser Bookmarks</system:String>
<system:String x:Key="flowlauncher_plugin_browserbookmark_plugin_description">Search your browser bookmarks</system:String>
<!-- Main -->
<system:String x:Key="flowlauncher_plugin_browserbookmark_copy_failed">Failed to set url in clipboard</system:String>
<!-- Settings -->
<system:String x:Key="flowlauncher_plugin_browserbookmark_bookmarkDataSetting">Bookmark Data</system:String>
<system:String x:Key="flowlauncher_plugin_browserbookmark_settings_openBookmarks">Open bookmarks in:</system:String>

View file

@ -223,11 +223,8 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex
}
catch (Exception e)
{
var message = "Failed to set url in clipboard";
_context.API.LogException(ClassName, message, e);
_context.API.ShowMsg(message);
_context.API.LogException(ClassName, "Failed to set url in clipboard", e);
_context.API.ShowMsgError(_context.API.GetTranslation("flowlauncher_plugin_browserbookmark_copy_failed"));
return false;
}
},

View file

@ -1,6 +1,7 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calculator</system:String>
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Allows to do mathematical calculations.(Try 5*3-2 in Flow Launcher)</system:String>
@ -13,4 +14,5 @@
<system:String x:Key="flowlauncher_plugin_calculator_decimal_seperator_comma">Comma (,)</system:String>
<system:String x:Key="flowlauncher_plugin_calculator_decimal_seperator_dot">Dot (.)</system:String>
<system:String x:Key="flowlauncher_plugin_calculator_max_decimal_places">Max. decimal places</system:String>
<system:String x:Key="flowlauncher_plugin_calculator_failed_to_copy">Copy failed, please try later</system:String>
</ResourceDictionary>

View file

@ -100,7 +100,7 @@ namespace Flow.Launcher.Plugin.Calculator
}
catch (ExternalException)
{
Context.API.ShowMsgBox("Copy failed, please try later");
Context.API.ShowMsgBox(Context.API.GetTranslation("flowlauncher_plugin_calculator_failed_to_copy"));
return false;
}
}

View file

@ -132,9 +132,8 @@ namespace Flow.Launcher.Plugin.Explorer
}
catch (Exception e)
{
var message = "Fail to set text in clipboard";
LogException(message, e);
Context.API.ShowMsg(message);
LogException("Fail to set text in clipboard", e);
Context.API.ShowMsgError(Context.API.GetTranslation("plugin_explorer_fail_to_set_text"));
return false;
}
},
@ -155,9 +154,8 @@ namespace Flow.Launcher.Plugin.Explorer
}
catch (Exception e)
{
var message = "Fail to set text in clipboard";
LogException(message, e);
Context.API.ShowMsg(message);
LogException("Fail to set text in clipboard", e);
Context.API.ShowMsgError(Context.API.GetTranslation("plugin_explorer_fail_to_set_text"));
return false;
}
},
@ -178,9 +176,8 @@ namespace Flow.Launcher.Plugin.Explorer
}
catch (Exception e)
{
var message = $"Fail to set file/folder in clipboard";
LogException(message, e);
Context.API.ShowMsg(message);
LogException($"Fail to set file/folder in clipboard", e);
Context.API.ShowMsgError(Context.API.GetTranslation("plugin_explorer_fail_to_set_files"));
return false;
}
@ -221,9 +218,8 @@ namespace Flow.Launcher.Plugin.Explorer
}
catch (Exception e)
{
var message = $"Fail to delete {record.FullPath}";
LogException(message, e);
Context.API.ShowMsgError(message);
LogException($"Fail to delete {record.FullPath}", e);
Context.API.ShowMsgError(string.Format(Context.API.GetTranslation("plugin_explorer_fail_to_delete"), record.FullPath));
return false;
}
@ -265,9 +261,9 @@ namespace Flow.Launcher.Plugin.Explorer
}
catch (FileNotFoundException e)
{
var name = "Plugin: Folder";
var message = $"File not found: {e.Message}";
Context.API.ShowMsgError(name, message);
Context.API.ShowMsgError(
Context.API.GetTranslation("plugin_explorer_plugin_name"),
string.Format(Context.API.GetTranslation("plugin_explorer_file_not_found"), e.Message));
return false;
}
@ -334,9 +330,8 @@ namespace Flow.Launcher.Plugin.Explorer
}
catch (Exception e)
{
var message = $"Fail to open file at {record.FullPath}";
LogException(message, e);
Context.API.ShowMsgError(message);
LogException($"Fail to open file at {record.FullPath}", e);
Context.API.ShowMsgError(string.Format(Context.API.GetTranslation("plugin_explorer_fail_to_open"), record.FullPath));
return false;
}

View file

@ -132,6 +132,11 @@
<system:String x:Key="plugin_explorer_show_contextmenu_title">Show Windows Context Menu</system:String>
<system:String x:Key="plugin_explorer_openwith">Open With</system:String>
<system:String x:Key="plugin_explorer_openwith_subtitle">Select a program to open with</system:String>
<system:String x:Key="plugin_explorer_fail_to_delete">Fail to delete {0}</system:String>
<system:String x:Key="plugin_explorer_file_not_found">File not found: {0}</system:String>
<system:String x:Key="plugin_explorer_fail_to_open">Fail to open {0}</system:String>
<system:String x:Key="plugin_explorer_fail_to_set_text">Fail to set text in clipboard</system:String>
<system:String x:Key="plugin_explorer_fail_to_set_files">Fail to set files/folders in clipboard</system:String>
<!-- Special Results -->
<system:String x:Key="plugin_explorer_diskfreespace">{0} free of {1}</system:String>

View file

@ -446,7 +446,7 @@ namespace Flow.Launcher.Plugin.Program
var title = Context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_error");
var message = string.Format(Context.API.GetTranslation("flowlauncher_plugin_program_run_failed"),
info.FileName);
Context.API.ShowMsg(title, string.Format(message, info.FileName), string.Empty);
Context.API.ShowMsgError(title, message);
}
}

View file

@ -462,7 +462,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
var message =
api.GetTranslation(
"flowlauncher_plugin_program_run_as_administrator_not_supported_message");
api.ShowMsg(title, message, string.Empty);
api.ShowMsgError(title, message);
}
return true;

View file

@ -1,6 +1,7 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_cmd_relace_winr">Replace Win+R</system:String>
<system:String x:Key="flowlauncher_plugin_cmd_close_cmd_after_press">Close Command Prompt after pressing any key</system:String>
@ -16,4 +17,6 @@
<system:String x:Key="flowlauncher_plugin_cmd_run_as_administrator">Run As Administrator</system:String>
<system:String x:Key="flowlauncher_plugin_cmd_copy">Copy the command</system:String>
<system:String x:Key="flowlauncher_plugin_cmd_history">Only show number of most used commands:</system:String>
<system:String x:Key="flowlauncher_plugin_cmd_command_not_found">Command not found: {0}</system:String>
<system:String x:Key="flowlauncher_plugin_cmd_error_running_command">Error running the command: {0}</system:String>
</ResourceDictionary>

View file

@ -335,15 +335,17 @@ namespace Flow.Launcher.Plugin.Shell
}
catch (FileNotFoundException e)
{
var name = "Plugin: Shell";
var message = $"Command not found: {e.Message}";
Context.API.ShowMsg(name, message);
Context.API.ShowMsgError(GetTranslatedPluginTitle(),
string.Format(Context.API.GetTranslation("flowlauncher_plugin_cmd_command_not_found"), e.Message));
}
catch (Win32Exception e)
{
var name = "Plugin: Shell";
var message = $"Error running the command: {e.Message}";
Context.API.ShowMsg(name, message);
Context.API.ShowMsgError(GetTranslatedPluginTitle(),
string.Format(Context.API.GetTranslation("flowlauncher_plugin_cmd_error_running_command"), e.Message));
}
catch (Exception e)
{
Context.API.LogException(ClassName, $"Error executing command: {info.FileName} {string.Join(" ", info.ArgumentList)}", e);
}
}

View file

@ -70,7 +70,7 @@ namespace Flow.Launcher.Plugin.Url
}
catch(Exception)
{
context.API.ShowMsg(string.Format(context.API.GetTranslation("flowlauncher_plugin_url_cannot_open_url"), raw));
context.API.ShowMsgError(string.Format(context.API.GetTranslation("flowlauncher_plugin_url_cannot_open_url"), raw));
return false;
}
}