Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Flow.Launcher.Core.Resource;

namespace Flow.Launcher.Core.ExternalPlugins.Environments
{
Expand Down Expand Up @@ -50,14 +51,15 @@ internal IEnumerable<PluginPair> Setup()
return SetPathForPluginPairs(PluginsSettingsFilePath, Language);
}

if (MessageBox.Show($"Flow detected you have installed {Language} plugins, which " +
$"will require {EnvName} to run. Would you like to download {EnvName}? " +
Environment.NewLine + Environment.NewLine +
"Click no if it's already installed, " +
$"and you will be prompted to select the folder that contains the {EnvName} executable",
string.Empty, MessageBoxButtons.YesNo) == DialogResult.No)
var noRuntimeMessage = string.Format(
InternationalizationManager.Instance.GetTranslation("runtimePluginInstalledChooseRuntimePrompt"),
Language,
EnvName,
Environment.NewLine
);
if (MessageBox.Show(noRuntimeMessage, string.Empty, MessageBoxButtons.YesNo) == DialogResult.No)
{
var msg = $"Please select the {EnvName} executable";
var msg = string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginChooseRuntimeExecutable"), EnvName);
string selectedFile;

selectedFile = GetFileFromDialog(msg, FileDialogFilter);
Expand All @@ -80,8 +82,7 @@ internal IEnumerable<PluginPair> Setup()
}
else
{
MessageBox.Show(
$"Unable to set {Language} executable path, please try from Flow's settings (scroll down to the bottom).");
MessageBox.Show(string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering we've implemented MessageboxEx so maybe it's better to use it here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's implemented in Flow.Launcher project while this file is in Flow.Launcher.Core. I don't know of a way to do that (besides moving MessageBoxEx to a different project) without introducing a circular dependency, and moving MessageBoxEx to a different project would be beyond the scope of this PR.

Log.Error("PluginsLoader",
$"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.",
$"{Language}Environment");
Expand Down
30 changes: 20 additions & 10 deletions Flow.Launcher.Core/Plugin/PluginManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using ISavable = Flow.Launcher.Plugin.ISavable;
using Flow.Launcher.Plugin.SharedCommands;
using System.Text.Json;
using Flow.Launcher.Core.Resource;

namespace Flow.Launcher.Core.Plugin
{
Expand Down Expand Up @@ -51,7 +52,7 @@ private static void DeletePythonBinding()
}

/// <summary>
/// Save json and ISavable
/// Save json and ISavable
/// </summary>
public static void Save()
{
Expand Down Expand Up @@ -202,24 +203,33 @@ public static async Task InitializePluginsAsync(IPublicAPI api)
}
}

InternationalizationManager.Instance.AddPluginLanguageDirectories(GetPluginsForInterface<IPluginI18n>());
InternationalizationManager.Instance.ChangeLanguage(InternationalizationManager.Instance.Settings.Language);

if (failedPlugins.Any())
{
var failed = string.Join(",", failedPlugins.Select(x => x.Metadata.Name));
API.ShowMsg($"Fail to Init Plugins",
$"Plugins: {failed} - fail to load and would be disabled, please contact plugin creator for help",
"", false);
API.ShowMsg(
InternationalizationManager.Instance.GetTranslation("failedToInitializePluginsTitle"),
string.Format(
InternationalizationManager.Instance.GetTranslation("failedToInitializePluginsMessage"),
failed
),
"",
false
);
}
}

public static ICollection<PluginPair> ValidPluginsForQuery(Query query)
{
if (query is null)
return Array.Empty<PluginPair>();

if (!NonGlobalPlugins.ContainsKey(query.ActionKeyword))
return GlobalPlugins;


var plugin = NonGlobalPlugins[query.ActionKeyword];
return new List<PluginPair>
{
Expand Down Expand Up @@ -279,8 +289,8 @@ public static void UpdatePluginMetadata(List<Result> results, PluginMetadata met
r.PluginID = metadata.ID;
r.OriginQuery = query;

// ActionKeywordAssigned is used for constructing MainViewModel's query text auto-complete suggestions
// Plugins may have multi-actionkeywords eg. WebSearches. In this scenario it needs to be overriden on the plugin level
// ActionKeywordAssigned is used for constructing MainViewModel's query text auto-complete suggestions
// Plugins may have multi-actionkeywords eg. WebSearches. In this scenario it needs to be overriden on the plugin level
if (metadata.ActionKeywords.Count == 1)
r.ActionKeywordAssigned = query.ActionKeyword;
}
Expand Down Expand Up @@ -463,7 +473,7 @@ internal static void InstallPlugin(UserPlugin plugin, string zipFilePath, bool c
// Unzip plugin files to temp folder
var tempFolderPluginPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
System.IO.Compression.ZipFile.ExtractToDirectory(zipFilePath, tempFolderPluginPath);

if(!plugin.IsFromLocalInstallPath)
File.Delete(zipFilePath);

Expand Down
15 changes: 8 additions & 7 deletions Flow.Launcher.Core/Resource/Internationalization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ public class Internationalization

public Internationalization()
{
AddPluginLanguageDirectories();
LoadDefaultLanguage();
// we don't want to load /Languages/en.xaml twice
// so add flowlauncher language directory after load plugin language files
AddFlowLauncherLanguageDirectory();
}

Expand All @@ -40,9 +36,9 @@ private void AddFlowLauncherLanguageDirectory()
}


private void AddPluginLanguageDirectories()
internal void AddPluginLanguageDirectories(IEnumerable<PluginPair> plugins)
{
foreach (var plugin in PluginManager.GetPluginsForInterface<IPluginI18n>())
foreach (var plugin in plugins)
{
var location = Assembly.GetAssembly(plugin.Plugin.GetType()).Location;
var dir = Path.GetDirectoryName(location);
Expand All @@ -56,6 +52,8 @@ private void AddPluginLanguageDirectories()
Log.Error($"|Internationalization.AddPluginLanguageDirectories|Can't find plugin path <{location}> for <{plugin.Metadata.Name}>");
}
}

LoadDefaultLanguage();
}

private void LoadDefaultLanguage()
Expand Down Expand Up @@ -140,11 +138,14 @@ private void RemoveOldLanguageFiles()

private void LoadLanguage(Language language)
{
var flowEnglishFile = Path.Combine(Constant.ProgramDirectory, Folder, DefaultFile);
var dicts = Application.Current.Resources.MergedDictionaries;
var filename = $"{language.LanguageCode}{Extension}";
var files = _languageDirectories
.Select(d => LanguageFile(d, filename))
.Where(f => !string.IsNullOrEmpty(f))
// Exclude Flow's English language file since it's built into the binary, and there's no need to load
// it again from the file system.
.Where(f => !string.IsNullOrEmpty(f) && f != flowEnglishFile)
.ToArray();

if (files.Length > 0)
Expand Down
8 changes: 3 additions & 5 deletions Flow.Launcher/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
StringMatcher.Instance = _stringMatcher;
_stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;

InternationalizationManager.Instance.Settings = _settings;
InternationalizationManager.Instance.ChangeLanguage(_settings.Language);

PluginManager.LoadPlugins(_settings.PluginSettings);
_mainVM = new MainViewModel(_settings);

Expand All @@ -89,11 +92,6 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
Current.MainWindow = window;
Current.MainWindow.Title = Constant.FlowLauncher;

// todo temp fix for instance code logic
// load plugin before change language, because plugin language also needs be changed
InternationalizationManager.Instance.Settings = _settings;
InternationalizationManager.Instance.ChangeLanguage(_settings.Language);

HotKeyMapper.Initialize(_mainVM);

// main windows needs initialized before theme change because of blur settings
Expand Down
11 changes: 11 additions & 0 deletions Flow.Launcher/Languages/en.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@
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">
<!-- Startup -->
<system:String x:Key="runtimePluginInstalledChooseRuntimePrompt">
Flow detected you have installed {0} plugins, which will require {1} to run. Would you like to download {1}?
{2}{2}
Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable
</system:String>
<system:String x:Key="runtimePluginChooseRuntimeExecutable">Please select the {0} executable</system:String>
<system:String x:Key="runtimePluginUnableToSetExecutablePath">Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom).</system:String>
<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>

<!-- 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="MessageBoxTitle">Flow Launcher</system:String>
Expand Down
8 changes: 8 additions & 0 deletions Flow.Launcher/Languages/ru.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
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">
<!-- Startup -->
<system:String x:Key="runtimePluginInstalledChooseRuntimePrompt">
Flow определил, что вы установили {0} плагины, которым требуется {1} для работы. Скачать {1}?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just fyi, if this language update hasn't been added to Crowdin, pretty sure they will get reverted back to English or overridden with updates coming from Crowdin.

{2}{2}
Кликните нет, если он уже установлен, и вам будет предложено выбрать папку, где находится исполняемый файл {1}
</system:String>
<system:String x:Key="runtimePluginChooseRuntimeExecutable">Пожалуйста, выберите исполняемый файл {0}</system:String>
<system:String x:Key="runtimePluginUnableToSetExecutablePath">Не удалось установить путь к исполняемому файлу {0}, пожалуйста, попробуйте через настройки Flow (прокрутите вниз).</system:String>
<!-- MainWindow -->
<system:String x:Key="registerHotkeyFailed">Не удалось зарегистрировать сочетание клавиш &quot;{0}&quot;. Возможно, оно используется другой программой. Измените сочетание клавиш или закройте другую программу.</system:String>
<system:String x:Key="MessageBoxTitle">Flow Launcher</system:String>
Expand Down