From bf87500e35fc11aec707a24d69b8798f2febe19d Mon Sep 17 00:00:00 2001 From: qianlifeng Date: Fri, 2 Jan 2015 16:16:09 +0800 Subject: [PATCH] Add multiple language. [WIP] --- .../UserSettings/UserSettingStorage.cs | 8 ++ Wox/App.xaml | 4 + Wox/Helper/LanguageManager.cs | 121 ++++++++++++++++++ Wox/Helper/ResourceMerger.cs | 21 +++ Wox/{ => Helper}/ThemeManager.cs | 27 +++- Wox/Languages/English.xaml | 59 +++++++++ Wox/Languages/中文.xaml | 51 ++++++++ Wox/MainWindow.xaml.cs | 2 +- Wox/SettingWindow.xaml | 84 ++++++------ Wox/SettingWindow.xaml.cs | 58 +++++---- Wox/Themes/{Default.xaml => Base.xaml} | 0 Wox/Themes/Dark.xaml | 2 +- Wox/Themes/Light.xaml | 2 +- Wox/Themes/Metro Server.xaml | 2 +- Wox/Themes/Pink.xaml | 2 +- Wox/Wox.csproj | 23 +++- 16 files changed, 391 insertions(+), 75 deletions(-) create mode 100644 Wox/Helper/LanguageManager.cs create mode 100644 Wox/Helper/ResourceMerger.cs rename Wox/{ => Helper}/ThemeManager.cs (83%) create mode 100644 Wox/Languages/English.xaml create mode 100644 Wox/Languages/中文.xaml rename Wox/Themes/{Default.xaml => Base.xaml} (100%) diff --git a/Wox.Infrastructure/Storage/UserSettings/UserSettingStorage.cs b/Wox.Infrastructure/Storage/UserSettings/UserSettingStorage.cs index beb156a4fd..f7bf665525 100644 --- a/Wox.Infrastructure/Storage/UserSettings/UserSettingStorage.cs +++ b/Wox.Infrastructure/Storage/UserSettings/UserSettingStorage.cs @@ -14,6 +14,9 @@ namespace Wox.Infrastructure.Storage.UserSettings [JsonProperty] public string Hotkey { get; set; } + [JsonProperty] + public string Language { get; set; } + [JsonProperty] public string Theme { get; set; } @@ -150,6 +153,7 @@ namespace Wox.Infrastructure.Storage.UserSettings { DontPromptUpdateMsg = false; Theme = "Dark"; + Language = "English"; ReplaceWinR = true; WebSearches = LoadDefaultWebSearches(); ProgramSources = new List(); @@ -183,6 +187,10 @@ namespace Wox.Infrastructure.Storage.UserSettings { storage.ResultItemFont = FontFamily.GenericSansSerif.Name; } + if (storage.Language == null) + { + storage.Language = "English"; + } } } diff --git a/Wox/App.xaml b/Wox/App.xaml index f02f489f06..3021178455 100644 --- a/Wox/App.xaml +++ b/Wox/App.xaml @@ -4,6 +4,10 @@ > + + + + diff --git a/Wox/Helper/LanguageManager.cs b/Wox/Helper/LanguageManager.cs new file mode 100644 index 0000000000..eb46559c5f --- /dev/null +++ b/Wox/Helper/LanguageManager.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using Wox.Helper; +using Wox.Infrastructure.Logger; +using Wox.Infrastructure.Storage.UserSettings; + +namespace Wox +{ + public class LanguageManager + { + private static List languageDirectories = new List(); + + static LanguageManager() + { + languageDirectories.Add(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Languages")); + + string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE"); + if (userProfilePath != null) + { + languageDirectories.Add(Path.Combine(Path.Combine(userProfilePath, ".Wox"), "Languages")); + } + + MakesureThemeDirectoriesExist(); + } + + private static void MakesureThemeDirectoriesExist() + { + foreach (string pluginDirectory in languageDirectories) + { + if (!Directory.Exists(pluginDirectory)) + { + try + { + Directory.CreateDirectory(pluginDirectory); + } + catch (Exception e) + { + Log.Error(e.Message); + } + } + } + } + + public static void ChangeLanguage(string name) + { + string path = GetLanguagePath(name); + if (string.IsNullOrEmpty(path)) + { + path = GetLanguagePath("English"); + if (string.IsNullOrEmpty(path)) + { + throw new Exception("Change Language failed"); + } + } + + UserSettingStorage.Instance.Language = name; + UserSettingStorage.Instance.Save(); + ResourceMerger.ApplyResources(); + } + + internal static ResourceDictionary GetResourceDictionary() + { + return new ResourceDictionary + { + Source = new Uri(GetLanguagePath(UserSettingStorage.Instance.Language), UriKind.Absolute) + }; + } + + public static List LoadAvailableLanguages() + { + List themes = new List(); + foreach (var directory in languageDirectories) + { + themes.AddRange( + Directory.GetFiles(directory) + .Where(filePath => filePath.EndsWith(".xaml")) + .Select(Path.GetFileNameWithoutExtension) + .ToList()); + } + return themes; + } + + public static string GetTranslation(string key) + { + try + { + object translation = Application.Current.FindResource(key); + if (translation == null) + { + return "NoTranslation"; + } + return translation.ToString(); + } + catch + { + return "NoTranslation"; + } + + } + + private static string GetLanguagePath(string name) + { + foreach (string directory in languageDirectories) + { + string path = Path.Combine(directory, name + ".xaml"); + if (File.Exists(path)) + { + return path; + } + } + + return string.Empty; + } + } +} \ No newline at end of file diff --git a/Wox/Helper/ResourceMerger.cs b/Wox/Helper/ResourceMerger.cs new file mode 100644 index 0000000000..f57cbb4e92 --- /dev/null +++ b/Wox/Helper/ResourceMerger.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; + +namespace Wox.Helper +{ + public class ResourceMerger + { + public static void ApplyResources() + { + var languageResource = LanguageManager.GetResourceDictionary(); + var themeResource = ThemeManager.GetResourceDictionary(); + + Application.Current.Resources.MergedDictionaries.Clear(); + Application.Current.Resources.MergedDictionaries.Add(languageResource); + Application.Current.Resources.MergedDictionaries.Add(themeResource); + } + } +} diff --git a/Wox/ThemeManager.cs b/Wox/Helper/ThemeManager.cs similarity index 83% rename from Wox/ThemeManager.cs rename to Wox/Helper/ThemeManager.cs index 270bb4aeeb..43260a2743 100644 --- a/Wox/ThemeManager.cs +++ b/Wox/Helper/ThemeManager.cs @@ -40,7 +40,7 @@ namespace Wox { Directory.CreateDirectory(pluginDirectory); } - catch(Exception e) + catch (Exception e) { Log.Error(e.Message); } @@ -60,9 +60,17 @@ namespace Wox } } + UserSettingStorage.Instance.Theme = themeName; + UserSettingStorage.Instance.Save(); + + ResourceMerger.ApplyResources(); + } + + internal static ResourceDictionary GetResourceDictionary() + { var dict = new ResourceDictionary { - Source = new Uri(themePath, UriKind.Absolute) + Source = new Uri(GetThemePath(UserSettingStorage.Instance.Theme), UriKind.Absolute) }; Style queryBoxStyle = dict["QueryBoxStyle"] as Style; @@ -89,9 +97,20 @@ namespace Wox Array.ForEach(new Style[] { resultItemStyle, resultSubItemStyle, resultItemSelectedStyle, resultSubItemSelectedStyle }, o => Array.ForEach(setters, p => o.Setters.Add(p))); } - Application.Current.Resources.MergedDictionaries.Clear(); - Application.Current.Resources.MergedDictionaries.Add(dict); + return dict; + } + public static List LoadAvailableThemes() + { + List themes = new List(); + foreach (var themeDirectory in themeDirectories) + { + themes.AddRange( + Directory.GetFiles(themeDirectory) + .Where(filePath => filePath.EndsWith(".xaml") && !filePath.EndsWith("Default.xaml")) + .ToList()); + } + return themes; } private static string GetThemePath(string themeName) diff --git a/Wox/Languages/English.xaml b/Wox/Languages/English.xaml new file mode 100644 index 0000000000..a91e3a2d9b --- /dev/null +++ b/Wox/Languages/English.xaml @@ -0,0 +1,59 @@ + + + General + Start Wox on system startup + Hide Wox when loses focus + Don't show upgrade msg if new version available + Language + + + Plugin + Browse more plugins + Disable + Action keyword + Plugin Directory + Author + + + Theme + Browse more themes + Hello Wox + Query Box Font + Result Item Font + Window Mode + Opacity + + + Hotkey + Wox Hotkey + Custom Query Hotkey + Delete + Edit + Add + Please select an item + Are your sure to delete {0} plugin hotkey? + + + Proxy + Enable Proxy + Server + Port + User Name + Password + Test Proxy + Save + Server can't be empty + Server port can't be empty + Invalid port format + Save proxy successfully + Proxy is correct + + + + About + Website + Version + + \ No newline at end of file diff --git a/Wox/Languages/中文.xaml b/Wox/Languages/中文.xaml new file mode 100644 index 0000000000..243352f307 --- /dev/null +++ b/Wox/Languages/中文.xaml @@ -0,0 +1,51 @@ + + + 通用 + 开机启动 + 失去焦点时自动隐藏Wox + 不显示新版本提示 + 语言 + + + 插件 + 浏览更多插件 + 禁用 + 触发关键字 + 插件目录 + 作者 + + + 主题 + 浏览更多主题 + 你好,Wox + 查询框字体 + 结果项字体 + 窗口模式 + 透明度 + + + 热键 + Wox激活热键 + 自定义查询热键 + 删除 + 编辑 + 增加 + + + 代理 + 启用代理 + 服务器 + 端口 + 用户名 + 密码 + 测试代理 + 保存 + + + 关于 + 网站 + 版本 + + \ No newline at end of file diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 20f6daca39..261a549253 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -174,7 +174,7 @@ namespace Wox ThreadPool.SetMaxThreads(30, 10); ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme); - + LanguageManager.ChangeLanguage(UserSettingStorage.Instance.Language); SetHotkey(UserSettingStorage.Instance.Hotkey, OnHotkey); SetCustomPluginHotkey(); diff --git a/Wox/SettingWindow.xaml b/Wox/SettingWindow.xaml index 1ab4866c0f..8e213dbbd6 100644 --- a/Wox/SettingWindow.xaml +++ b/Wox/SettingWindow.xaml @@ -20,27 +20,31 @@ - + - - Start Wox on system startup + + - Hide Wox when loses focus + - Don't show upgrade msg if new version available + + + + + - + - + @@ -102,14 +106,18 @@ - + - Disable - ActionKeyword: + + + + + + - + @@ -121,14 +129,14 @@ - + - + @@ -150,7 +158,7 @@ - + @@ -159,7 +167,7 @@ - + - + - + Normal LayeredWindow @@ -209,7 +217,7 @@ - + @@ -218,7 +226,7 @@ - + @@ -226,7 +234,7 @@ - + @@ -234,18 +242,18 @@ - + - + - + @@ -258,15 +266,17 @@ - - + + - + @@ -320,10 +330,10 @@ - Website: + - Version: + diff --git a/Wox/SettingWindow.xaml.cs b/Wox/SettingWindow.xaml.cs index a8107ce46e..c25849c461 100644 --- a/Wox/SettingWindow.xaml.cs +++ b/Wox/SettingWindow.xaml.cs @@ -70,6 +70,8 @@ namespace Wox cbHideWhenDeactive.IsChecked = UserSettingStorage.Instance.HideWhenDeactive; cbDontPromptUpdateMsg.IsChecked = UserSettingStorage.Instance.DontPromptUpdateMsg; + LoadLanguages(); + #endregion #region Theme @@ -148,7 +150,7 @@ namespace Wox } }); - foreach (string theme in LoadAvailableThemes()) + foreach (string theme in ThemeManager.LoadAvailableThemes()) { string themeName = System.IO.Path.GetFileNameWithoutExtension(theme); themeComboBox.Items.Add(themeName); @@ -240,6 +242,19 @@ namespace Wox settingsLoaded = true; } + private void LoadLanguages() + { + cbLanguages.ItemsSource = LanguageManager.LoadAvailableLanguages(); + cbLanguages.SelectedValue = UserSettingStorage.Instance.Language; + cbLanguages.SelectionChanged += cbLanguages_SelectionChanged; + } + + void cbLanguages_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + string language = cbLanguages.SelectedValue.ToString(); + LanguageManager.ChangeLanguage(language); + } + private void EnableProxy() { tbProxyPassword.IsEnabled = true; @@ -256,12 +271,6 @@ namespace Wox tbProxyPort.IsEnabled = false; } - private List LoadAvailableThemes() - { - string themePath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "Themes"); - return Directory.GetFiles(themePath).Where(filePath => filePath.EndsWith(".xaml") && !filePath.EndsWith("Default.xaml")).ToList(); - } - private void CbStartWithWindows_OnChecked(object sender, RoutedEventArgs e) { CreateStartupFolderShortcut(); @@ -319,19 +328,20 @@ namespace Wox private void BtnDeleteCustomHotkey_OnClick(object sender, RoutedEventArgs e) { CustomPluginHotkey item = lvCustomHotkey.SelectedItem as CustomPluginHotkey; - if (item != null && - MessageBox.Show("Are your sure to delete " + item.Hotkey + " plugin hotkey?", "Delete Custom Plugin Hotkey", - MessageBoxButton.YesNo) == MessageBoxResult.Yes) + if (item == null) + { + MessageBox.Show(LanguageManager.GetTranslation("pleaseSelectAnItem")); + return; + } + + string deleteWarning = string.Format(LanguageManager.GetTranslation("deleteCustomHotkeyWarning"), item.Hotkey); + if (MessageBox.Show(deleteWarning, LanguageManager.GetTranslation("delete"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) { UserSettingStorage.Instance.CustomPluginHotkeys.Remove(item); lvCustomHotkey.Items.Refresh(); UserSettingStorage.Instance.Save(); MainWindow.RemoveHotkey(item.Hotkey); } - else - { - MessageBox.Show("Please select an item"); - } } private void BtnEditCustomHotkey_OnClick(object sender, RoutedEventArgs e) @@ -345,7 +355,7 @@ namespace Wox } else { - MessageBox.Show("Please select an item"); + MessageBox.Show(LanguageManager.GetTranslation("pleaseSelectAnItem")); } } @@ -640,17 +650,17 @@ namespace Wox { if (string.IsNullOrEmpty(tbProxyServer.Text)) { - MessageBox.Show("Server can't be empty"); + MessageBox.Show(LanguageManager.GetTranslation("serverCantBeEmpty")); return; } if (string.IsNullOrEmpty(tbProxyPort.Text)) { - MessageBox.Show("Server port can't be empty"); + MessageBox.Show(LanguageManager.GetTranslation("portCantBeEmpty")); return; } if (!int.TryParse(tbProxyPort.Text, out port)) { - MessageBox.Show("Invalid port format"); + MessageBox.Show(LanguageManager.GetTranslation("invalidPortFormat")); return; } } @@ -661,25 +671,25 @@ namespace Wox UserSettingStorage.Instance.ProxyPassword = tbProxyPassword.Password; UserSettingStorage.Instance.Save(); - MessageBox.Show("Save Proxy Successfully"); + MessageBox.Show(LanguageManager.GetTranslation("saveProxySuccessfully")); } private void btnTestProxy_Click(object sender, RoutedEventArgs e) { if (string.IsNullOrEmpty(tbProxyServer.Text)) { - MessageBox.Show("Server can't be empty"); + MessageBox.Show(LanguageManager.GetTranslation("serverCantBeEmpty")); return; } if (string.IsNullOrEmpty(tbProxyPort.Text)) { - MessageBox.Show("Server port can't be empty"); + MessageBox.Show(LanguageManager.GetTranslation("portCantBeEmpty")); return; } int port; if (!int.TryParse(tbProxyPort.Text, out port)) { - MessageBox.Show("Invalid port format"); + MessageBox.Show(LanguageManager.GetTranslation("invalidPortFormat")); return; } @@ -697,10 +707,10 @@ namespace Wox } try { - HttpWebResponse response = (HttpWebResponse) request.GetResponse(); + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); if (response.StatusCode == HttpStatusCode.OK) { - MessageBox.Show("Proxy is ok"); + MessageBox.Show(LanguageManager.GetTranslation("proxyIsCorrect")); } else { diff --git a/Wox/Themes/Default.xaml b/Wox/Themes/Base.xaml similarity index 100% rename from Wox/Themes/Default.xaml rename to Wox/Themes/Base.xaml diff --git a/Wox/Themes/Dark.xaml b/Wox/Themes/Dark.xaml index 4becca7ffa..e2d1679787 100644 --- a/Wox/Themes/Dark.xaml +++ b/Wox/Themes/Dark.xaml @@ -2,7 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib"> - +