diff --git a/.gitignore b/.gitignore index e3853f1..050a84e 100644 --- a/.gitignore +++ b/.gitignore @@ -22,10 +22,9 @@ TranslationAssistant.DocumentTranslationInterface/bin/Release/FileTranslator.vsh *.ide *.ide-shm *.ide -.vs/Microsoft.DocumentTranslator/v15/sqlite3/storage.ide *.ide-wal -.vs/Microsoft.DocumentTranslator/v15/sqlite3/storage.ide *.ide +*.sqlite /TranslationAssistant.DocumentTranslationInstaller/obj/Debug *.dtbcache /TranslationAssistant.AutomationToolkit.BasePlugin/bin/Debug/TranslationAssistant.AutomationToolkit.BasePlugin.dll @@ -43,6 +42,5 @@ TranslationAssistant.DocumentTranslationInterface/bin/Release/FileTranslator.vsh /TranslationAssistant.AutomationToolkit.TranslationPlugins/obj/Release /azure-libraries-for-net /OpenXmlPowerTools/bin/Debug -/.vs/Microsoft.DocumentTranslator/DesignTimeBuild +/.vs/ .vs/ -.vs/slnx.sqlite diff --git a/.vs/Microsoft.DocumentTranslator/config/applicationhost.config b/.vs/Microsoft.DocumentTranslator/config/applicationhost.config deleted file mode 100644 index 82fa5c7..0000000 --- a/.vs/Microsoft.DocumentTranslator/config/applicationhost.config +++ /dev/null @@ -1,974 +0,0 @@ - - - - - - -
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
- -
-
- -
-
-
- - -
-
-
-
-
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json deleted file mode 100644 index 6b61141..0000000 --- a/.vs/VSWorkspaceState.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ExpandedNodes": [ - "" - ], - "PreviewInSolutionExplorer": false -} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite deleted file mode 100644 index 86a5ed3..0000000 Binary files a/.vs/slnx.sqlite and /dev/null differ diff --git a/Microsoft.DocumentTranslator.sln b/Microsoft.DocumentTranslator.sln index 61452e7..97310f9 100644 --- a/Microsoft.DocumentTranslator.sln +++ b/Microsoft.DocumentTranslator.sln @@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29609.76 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocumentTranslator", "TranslationAssistant.DocumentTranslationInterface\DocumentTranslator.csproj", "{4007B1E0-9E4F-449A-AE61-C38F771001F6}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TranslationServices.Core", "TranslationServices.Core\TranslationServices.Core.csproj", "{9F027538-F794-4543-A510-155043A40CC6}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TranslationAssistant.Business", "TranslationAssistant.Business\TranslationAssistant.Business.csproj", "{6BF8556D-3875-4C4A-86B4-A9AA5B1F8696}" @@ -10,8 +12,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TranslationAssistant.Busine {1E89FBEE-7C28-41F8-8894-1B11D4855A26} = {1E89FBEE-7C28-41F8-8894-1B11D4855A26} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocumentTranslator", "TranslationAssistant.DocumentTranslationInterface\DocumentTranslator.csproj", "{4007B1E0-9E4F-449A-AE61-C38F771001F6}" -EndProject Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "TranslationAssistant.DocumentTranslationInstaller", "TranslationAssistant.DocumentTranslationInstaller\TranslationAssistant.DocumentTranslationInstaller.wixproj", "{CB4E5694-FB0B-4E8C-92EB-FEB5362A28E8}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TranslationAssistant.AutomationToolkit.BasePlugin", "TranslationAssistant.AutomationToolkit.BasePlugin\TranslationAssistant.AutomationToolkit.BasePlugin.csproj", "{443BE96F-82E7-4952-A078-DEBCFF6B2311}" diff --git a/TranslationAssistant.AutomationToolkit.TranslationPlugins/TranslateDocuments.cs b/TranslationAssistant.AutomationToolkit.TranslationPlugins/TranslateDocuments.cs index 3f974a3..06fb976 100644 --- a/TranslationAssistant.AutomationToolkit.TranslationPlugins/TranslateDocuments.cs +++ b/TranslationAssistant.AutomationToolkit.TranslationPlugins/TranslateDocuments.cs @@ -82,7 +82,7 @@ public TranslateDocuments(ConsoleLogger Logger) "from", false, new[] { "Auto-Detect" }, - TranslationServiceFacade.AvailableLanguages.Keys.ToArray(), + AvailableLanguages.GetLanguages().Result.Keys.ToArray(), true, "The source language. Auto-detect if no language specified."); @@ -90,7 +90,7 @@ public TranslateDocuments(ConsoleLogger Logger) "to", true, new string[] { }, - TranslationServiceFacade.AvailableLanguages.Keys.ToArray(), + AvailableLanguages.GetLanguages().Result.Keys.ToArray(), new[] { ',' }, "The target language code, or comma-separated list of language codes."); @@ -185,8 +185,7 @@ public override bool Execute() var sourceLanguageExpanded = String.IsNullOrEmpty(this.sourceLanguage.ValueString) || this.sourceLanguage.ValueString.Equals("Auto-Detect") ? "Auto-Detect" - : TranslationServiceFacade.AvailableLanguages[ - this.sourceLanguage.ValueString]; + : AvailableLanguages.GetLanguages().Result[this.sourceLanguage.ValueString]; string languagename = TranslationServiceFacade.LanguageCodeToLanguageName(language.ToString()); DocumentTranslationManager.DoTranslation( diff --git a/TranslationAssistant.AutomationToolkit.TranslationPlugins/TranslateXML.cs b/TranslationAssistant.AutomationToolkit.TranslationPlugins/TranslateXML.cs index 2092587..2818bac 100644 --- a/TranslationAssistant.AutomationToolkit.TranslationPlugins/TranslateXML.cs +++ b/TranslationAssistant.AutomationToolkit.TranslationPlugins/TranslateXML.cs @@ -70,7 +70,7 @@ public TranslateXML (ConsoleLogger Logger) "from", false, new[] { "Auto-Detect" }, - TranslationServiceFacade.AvailableLanguages.Keys.ToArray(), + AvailableLanguages.GetLanguages().Result.Keys.ToArray(), true, "The source language. Auto-detect if no language specified."); @@ -78,7 +78,7 @@ public TranslateXML (ConsoleLogger Logger) "to", true, new string[] { }, - TranslationServiceFacade.AvailableLanguages.Keys.ToArray(), + AvailableLanguages.GetLanguages().Result.Keys.ToArray(), new[] { ',' }, "The target language code, or comma-separated list of language codes."); diff --git a/TranslationAssistant.Business/AllLanguageList.cs b/TranslationAssistant.Business/AllLanguageList.cs index 5410cc8..e2832e7 100644 --- a/TranslationAssistant.Business/AllLanguageList.cs +++ b/TranslationAssistant.Business/AllLanguageList.cs @@ -14,18 +14,15 @@ public static class AllLanguageList public static async Task GetAllLanguages() { - Task GetLanguagesTask = TranslationServiceFacade.GetLanguages(); StringWriter writer = new StringWriter(); Dictionary languagelist = new Dictionary(); - await GetLanguagesTask; - languagelist = TranslationServiceFacade.AvailableLanguages; + languagelist = await AvailableLanguages.GetLanguages(); writer.WriteLine("{0}\t{1}\t{2}", "Language", "Language Code", "Display Name"); writer.WriteLine("------------------------------------------------------"); foreach (KeyValuePair language in languagelist.ToList()) { - Task t = TranslationServiceFacade.GetLanguages(language.Key); - await t; - foreach (KeyValuePair lang in TranslationServiceFacade.AvailableLanguages) + Dictionary languagesinlanguage = await AvailableLanguages.GetLanguages(language.Key); + foreach (KeyValuePair lang in languagesinlanguage) { writer.WriteLine("{0}\t{1}\t{2}", language.Key, lang.Key, lang.Value); } diff --git a/TranslationAssistant.Business/TranslateFromAll.cs b/TranslationAssistant.Business/TranslateFromAll.cs index b626edd..68dea98 100644 --- a/TranslationAssistant.Business/TranslateFromAll.cs +++ b/TranslationAssistant.Business/TranslateFromAll.cs @@ -24,7 +24,7 @@ private async Task> TranslateFromAllLanguages(s { EventHandler handler = OneTranslationDone; List>> tasklist = new List>>(); - foreach (KeyValuePair language in TranslationServiceFacade.AvailableLanguages) + foreach (KeyValuePair language in await AvailableLanguages.GetLanguages()) { Task> task = TranslateInternal(text, language.Key, to, category, contentType); tasklist.Add(task); diff --git a/TranslationAssistant.Business/TranslateToAll.cs b/TranslationAssistant.Business/TranslateToAll.cs index 197f938..ff7cb9e 100644 --- a/TranslationAssistant.Business/TranslateToAll.cs +++ b/TranslationAssistant.Business/TranslateToAll.cs @@ -23,7 +23,7 @@ private async Task> TranslateToAllLanguages(str { EventHandler handler = OneTranslationDone; List>> tasklist = new List>>(); - foreach (KeyValuePair language in TranslationServiceFacade.AvailableLanguages) + foreach (KeyValuePair language in await AvailableLanguages.GetLanguages()) { Task> task = TranslateInternal(text, from, language.Key, category, contentType); tasklist.Add(task); diff --git a/TranslationAssistant.DocumentTranslationInterface/Content/Account.xaml.cs b/TranslationAssistant.DocumentTranslationInterface/Content/Account.xaml.cs index 048ad4d..3b33cd2 100644 --- a/TranslationAssistant.DocumentTranslationInterface/Content/Account.xaml.cs +++ b/TranslationAssistant.DocumentTranslationInterface/Content/Account.xaml.cs @@ -53,7 +53,8 @@ private void PasswordBox_PasswordChanged(object sender, System.Windows.RoutedEve private void CheckBox_Click(object sender, System.Windows.RoutedEventArgs e) { - _ = TranslationServices.Core.TranslationServiceFacade.Initialize(true); + TranslationServices.Core.AvailableLanguages.ShowExperimental = ShowExperimental_CheckBox.IsChecked.Value; + _ = TranslationServices.Core.AvailableLanguages.GetLanguages(); ShowExperimental_Changed?.Invoke(this, EventArgs.Empty); } private void CloudSelector_SelectionChanged(object sender, SelectionChangedEventArgs e) diff --git a/TranslationAssistant.DocumentTranslationInterface/Pages/DocumentTranslationPage.xaml.cs b/TranslationAssistant.DocumentTranslationInterface/Pages/DocumentTranslationPage.xaml.cs index 3a45d6d..afb2777 100644 --- a/TranslationAssistant.DocumentTranslationInterface/Pages/DocumentTranslationPage.xaml.cs +++ b/TranslationAssistant.DocumentTranslationInterface/Pages/DocumentTranslationPage.xaml.cs @@ -21,12 +21,13 @@ namespace TranslationAssistant.DocumentTranslationInterface.Pages #endregion - /// + /// /// Interaction logic for ProjectCodeCommentsTranslationPage.xaml /// public partial class DocumentTranslationPage : UserControl { #region Constructors and Destructors + readonly ViewModel.DocumentTranslation documentTranslation = new ViewModel.DocumentTranslation(); /// /// Initializes a new instance of the class. @@ -62,6 +63,7 @@ private void DocumentTranslationPage_KeyDown(object sender, System.Windows.Input private void RefreshLanguageComboBoxes(bool successful) { + documentTranslation.PopulateAvailableLanguages(); cbSourceLanguages.Items.Refresh(); cbTargetLanguages.Items.Refresh(); } diff --git a/TranslationAssistant.DocumentTranslationInterface/Pages/ImmediateWindow.xaml.cs b/TranslationAssistant.DocumentTranslationInterface/Pages/ImmediateWindow.xaml.cs index 7f9e0b5..5617bf4 100644 --- a/TranslationAssistant.DocumentTranslationInterface/Pages/ImmediateWindow.xaml.cs +++ b/TranslationAssistant.DocumentTranslationInterface/Pages/ImmediateWindow.xaml.cs @@ -22,6 +22,7 @@ namespace TranslationAssistant.DocumentTranslationInterface.Pages using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; + using TranslationAssistant.DocumentTranslationInterface.Common; /// /// Interaction logic for ProjectCodeCommentsTranslationPage.xaml @@ -37,18 +38,26 @@ public partial class ImmediateWindow : UserControl /// public ImmediateWindow() { + Debug.WriteLine("ImmediateWindow entered."); this.InitializeComponent(); this.Loaded += ImmediateWindow_Loaded; - this.GotFocus += ImmediateWindow_GotFocus; + TranslationServices.Core.AvailableLanguages.OnUpdate += AvailableLanguages_OnUpdate; + SingletonEventAggregator.Instance.GetEvent().Unsubscribe(RefreshLanguageComboBoxes); + SingletonEventAggregator.Instance.GetEvent().Subscribe(RefreshLanguageComboBoxes); } - private void ImmediateWindow_GotFocus(object sender, RoutedEventArgs e) + private void RefreshLanguageComboBoxes(bool successful) + { + documentTranslation.PopulateAvailableLanguages(); + cbSourceLanguages.Items.Refresh(); + cbTargetLanguages.Items.Refresh(); + } + + private void AvailableLanguages_OnUpdate(object sender, EventArgs e) { - Debug.WriteLine("ImmediateWindow.xaml.cs: Available Languages: {0}", TranslationServices.Core.TranslationServiceFacade.AvailableLanguages.Count); documentTranslation.PopulateAvailableLanguages(); cbSourceLanguages.GetBindingExpression(ComboBox.ItemsSourceProperty).UpdateTarget(); cbTargetLanguages.GetBindingExpression(ComboBox.ItemsSourceProperty).UpdateTarget(); - } private void ImmediateWindow_Loaded(object sender, RoutedEventArgs e) @@ -181,6 +190,7 @@ private void CbSourceLanguages_SelectionChanged(object sender, SelectionChangedE private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { documentTranslation.SaveSettings(); + TranslationServices.Core.AvailableLanguages.OnUpdate -= AvailableLanguages_OnUpdate; } private void CbTranslateMode_SelectionChanged(object sender, SelectionChangedEventArgs e) diff --git a/TranslationAssistant.DocumentTranslationInterface/ViewModel/AccountViewModel.cs b/TranslationAssistant.DocumentTranslationInterface/ViewModel/AccountViewModel.cs index 68c763c..0910318 100644 --- a/TranslationAssistant.DocumentTranslationInterface/ViewModel/AccountViewModel.cs +++ b/TranslationAssistant.DocumentTranslationInterface/ViewModel/AccountViewModel.cs @@ -264,7 +264,7 @@ public AccountViewModel() this.AzureCloud = TranslationServices.Core.TranslationServiceFacade.AzureCloud; this.useCustomEndpoint = TranslationServices.Core.TranslationServiceFacade.UseCustomEndpoint; this.customEndpointUrl = TranslationServices.Core.TranslationServiceFacade.CustomEndpointUrl; - this.showExperimental = TranslationServices.Core.TranslationServiceFacade.ShowExperimental; + this.showExperimental = TranslationServices.Core.AvailableLanguages.ShowExperimental; } /// @@ -279,12 +279,12 @@ private async void SaveAccountClick() TranslationServices.Core.TranslationServiceFacade.AzureRegion = this.azureRegion; TranslationServices.Core.TranslationServiceFacade.UseCustomEndpoint = this.useCustomEndpoint; TranslationServices.Core.TranslationServiceFacade.CustomEndpointUrl = this.customEndpointUrl; - TranslationServices.Core.TranslationServiceFacade.ShowExperimental = this.showExperimental; + TranslationServices.Core.AvailableLanguages.ShowExperimental = this.showExperimental; + TranslationServices.Core.AvailableLanguages.ShowExperimental = this.showExperimental; TranslationServices.Core.TranslationServiceFacade.SaveCredentials(); _ = TranslationServices.Core.TranslationServiceFacade.Initialize(true); - bool isready = false; - + bool isready; try { isready = await TranslationServices.Core.TranslationServiceFacade.IsTranslationServiceReadyAsync(); } catch { isready = false; } diff --git a/TranslationAssistant.DocumentTranslationInterface/ViewModel/DocumentTranslation.cs b/TranslationAssistant.DocumentTranslationInterface/ViewModel/DocumentTranslation.cs index 213f42b..8825b0c 100644 --- a/TranslationAssistant.DocumentTranslationInterface/ViewModel/DocumentTranslation.cs +++ b/TranslationAssistant.DocumentTranslationInterface/ViewModel/DocumentTranslation.cs @@ -116,6 +116,7 @@ public DocumentTranslation() _ = TranslationServiceFacade.Initialize(); this.PopulateAvailableLanguages(); this.PopulateTranslateMode(); + AvailableLanguages.OnUpdate += AvailableLanguages_OnUpdate; this.ShowProgressBar = false; this.IsGoButtonEnabled = false; this.TargetFolder = string.Empty; @@ -137,6 +138,11 @@ public DocumentTranslation() SingletonEventAggregator.Instance.GetEvent().Subscribe(PopulateReadyToTranslateMessage); } + private void AvailableLanguages_OnUpdate(object sender, EventArgs e) + { + PopulateAvailableLanguages(); + } + /// /// Save the selected source and target languages for the next session; /// @@ -526,10 +532,7 @@ public void PopulateAvailableLanguages() if (!TranslationServiceFacade.UseCustomEndpoint) this.sourceLanguageList.Add(Properties.Resources.Common_AutoDetect); try { - lock (TranslationServiceFacade.AvailableLanguages) - { - this.targetLanguageList.AddRange(TranslationServiceFacade.AvailableLanguages.Values); - } + targetLanguageList.AddRange(AvailableLanguages.GetLanguages().Result.Values); } catch (Exception ex) { this.StatusText = String.Format("{0}\n{1}", Properties.Resources.Error_LanguageList, ex.Message); diff --git a/TranslationServices.Core/AvailableLanguages.cs b/TranslationServices.Core/AvailableLanguages.cs new file mode 100644 index 0000000..ee007a6 --- /dev/null +++ b/TranslationServices.Core/AvailableLanguages.cs @@ -0,0 +1,142 @@ +// // ---------------------------------------------------------------------- +// // +// // Copyright (c) Microsoft Corporation. +// // All rights reserved. +// // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY +// // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// // PARTICULAR PURPOSE. +// // +// // ---------------------------------------------------------------------- +// // TranslationServiceFacade.cs +// // ---------------------------------------------------------------------- + +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; + +namespace TranslationAssistant.TranslationServices.Core +{ + public static class AvailableLanguages + { + private static Dictionary languages = new Dictionary(); + + public static bool UseCustomEndpoint { get; set; } = false; + public static bool ShowExperimental { get; set; } = false; + private static bool LastShowExperimental = false; + private static string LastAcceptLanguage = string.Empty; + public static string EndPointAddress = "https://api.cognitive.microsofttranslator.com"; + public static event EventHandler OnUpdate; + + public static async Task> GetLanguages() + { + await GetLanguages(System.Globalization.CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); + lock (languages) + { + return languages; + } + } + + static AvailableLanguages() + { + + } + + + /// + /// Fills the AvailableLanguages dictionary + /// + /// Accept-Language + public static async Task> GetLanguages(string AcceptLanguage) + { + Debug.WriteLine("GetLanguages entered."); + if (string.IsNullOrEmpty(AcceptLanguage)) AcceptLanguage = System.Globalization.CultureInfo.CurrentUICulture.TwoLetterISOLanguageName; + if ((AcceptLanguage == LastAcceptLanguage) && (ShowExperimental == LastShowExperimental) && (languages.Count > 3)) + { + Debug.WriteLine("GetLanguages returned from cache."); + return languages; + } + LastAcceptLanguage = AcceptLanguage; + LastShowExperimental = ShowExperimental; + Debug.WriteLine("AvailableLanguages: ShowExperimental: {0}", ShowExperimental); + int retrycounter = 2; + while (retrycounter >= 0) + { + retrycounter--; + try + { + Debug.WriteLine("GetLanguages awaiting server response, retry #{0}.", retrycounter); + await GetLanguagesInternal(AcceptLanguage); + return languages; + } + catch + { + if (retrycounter <= 0) throw; + await Task.Delay(200); //wait a bit before retrying + } + } + return null; + } + + + + /// + /// Fills the AvailableLanguages dictionary + /// + /// Accept-Language + private static async Task GetLanguagesInternal(string AcceptLanguage = "en") + { + if (UseCustomEndpoint) + { + languages = await TranslationServiceFacade.ContainerGetLanguages(); + OnUpdate?.Invoke(null, EventArgs.Empty); + return; + } + string uri = EndPointAddress + "/languages?api-version=3.0&scope=translation"; + if (ShowExperimental) uri += "&flight=experimental"; + + try + { + using HttpClient client = new HttpClient(); + using HttpRequestMessage request = new HttpRequestMessage(); + client.Timeout = TimeSpan.FromSeconds(10); + request.Method = HttpMethod.Get; + request.RequestUri = new Uri(uri); + request.Headers.Add("Accept-Language", AcceptLanguage); + HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false); + string jsonResponse = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + var result = JsonConvert.DeserializeObject>>>(jsonResponse); + var langs = result["translation"]; + + string[] languagecodes = languages.Keys.ToArray(); + lock (languages) + { + languages.Clear(); + foreach (var kv in langs) + { + languages.Add(kv.Key, kv.Value["name"]); + } + } + } + OnUpdate?.Invoke(null, EventArgs.Empty); + } + catch (HttpRequestException) + { + Debug.WriteLine("ERROR: Request exception while retrieving languages."); + lock (languages) + { + languages.Clear(); + OnUpdate?.Invoke(null, EventArgs.Empty); + } + return; + } + return; + } + } +} \ No newline at end of file diff --git a/TranslationServices.Core/ContainerSpecifics.cs b/TranslationServices.Core/ContainerSpecifics.cs index 981ecfb..0276e8f 100644 --- a/TranslationServices.Core/ContainerSpecifics.cs +++ b/TranslationServices.Core/ContainerSpecifics.cs @@ -31,29 +31,31 @@ private static async Task ContainerStatus() } - private static async void ContainerGetLanguages() + public static async Task> ContainerGetLanguages() { - AvailableLanguages.Clear(); - AvailableLanguages.Add("en", "English"); - AvailableLanguages.Add("ar", "Arabic"); - AvailableLanguages.Add("de", "German"); - AvailableLanguages.Add("ru", "Russian"); - AvailableLanguages.Add("zh-Hans", "Chinese (Simplified)"); - AvailableLanguages.Add("es", "Spanish"); - AvailableLanguages.Add("fr", "French"); + Dictionary languages = new Dictionary(); + languages.Clear(); + languages.Add("en", "English"); + languages.Add("ar", "Arabic"); + languages.Add("de", "German"); + languages.Add("ru", "Russian"); + languages.Add("zh-Hans", "Chinese (Simplified)"); + languages.Add("es", "Spanish"); + languages.Add("fr", "French"); ///This container probably only contains a subset of these. ///Test all of them and delete the ones that aren't valid. List>> tasks = new List>>(); - foreach (KeyValuePair kv in AvailableLanguages) + foreach (KeyValuePair kv in languages) { Task> task = ContainerTestLanguage(kv.Key); } await Task.WhenAll(tasks).ConfigureAwait(false); foreach (var task in tasks) { - if (!task.Result.Value) AvailableLanguages.Remove(task.Result.Key); + if (!task.Result.Value) languages.Remove(task.Result.Key); } + return languages; } private static async Task> ContainerTestLanguage(string language) @@ -128,7 +130,6 @@ private static async Task ContainerTranslateTextAsyncInternal(string tex } catch { - AvailableLanguages.Clear(); return null; } } diff --git a/TranslationServices.Core/LoadSaveCredentials.cs b/TranslationServices.Core/LoadSaveCredentials.cs index 24f6450..1f2ebef 100644 --- a/TranslationServices.Core/LoadSaveCredentials.cs +++ b/TranslationServices.Core/LoadSaveCredentials.cs @@ -14,7 +14,7 @@ public static void LoadCredentials() AzureKey = Properties.Settings.Default.AzureKey; CategoryID = Properties.Settings.Default.CategoryID; AppId = Properties.Settings.Default.AppId; - ShowExperimental = Properties.Settings.Default.ShowExperimental; + AvailableLanguages.ShowExperimental = Properties.Settings.Default.ShowExperimental; UseAdvancedSettings = Properties.Settings.Default.UseAdvancedSettings; AzureCloud = Properties.Settings.Default.AzureCloud; AzureRegion = Properties.Settings.Default.SubscriptionRegion; @@ -31,7 +31,7 @@ public static void SaveCredentials() Properties.Settings.Default.AzureKey = AzureKey; Properties.Settings.Default.CategoryID = CategoryID; Properties.Settings.Default.AppId = AppId; - Properties.Settings.Default.ShowExperimental = ShowExperimental; + Properties.Settings.Default.ShowExperimental = AvailableLanguages.ShowExperimental; Properties.Settings.Default.UseAdvancedSettings = UseAdvancedSettings; Properties.Settings.Default.AzureCloud = AzureCloud; EndPointAddress = SetEndPointAddress(AzureCloud); diff --git a/TranslationServices.Core/TranslationServiceFacade.cs b/TranslationServices.Core/TranslationServiceFacade.cs index 00ad214..d3c70fb 100644 --- a/TranslationServices.Core/TranslationServiceFacade.cs +++ b/TranslationServices.Core/TranslationServiceFacade.cs @@ -52,7 +52,6 @@ public static partial class TranslationServiceFacade /// Holds the value of the custom endpoint, the container /// public static string CustomEndpointUrl { get; set; } - public static bool ShowExperimental { get; set; } /// /// Holds the Azure subscription key @@ -72,8 +71,6 @@ public static partial class TranslationServiceFacade /// End point address for the Translator API /// public static string EndPointAddress { get; set; } = "https://api.cognitive.microsofttranslator.com"; - - public static Dictionary AvailableLanguages { get; } = new Dictionary(); public static int Maxrequestsize { get => maxrequestsize; } public static int Maxelements { get => maxelements; } public static string AzureRegion { get; set; } = null; @@ -303,8 +300,8 @@ static TranslationServiceFacade() /// False if credentials failed public static async Task Initialize(bool force = false) { - await GetLanguages(Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName); - if (IsInitialized && (!force) && (AvailableLanguages.Count>2)) return true; + Dictionary availablelanguages = await AvailableLanguages.GetLanguages(Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName); + if (IsInitialized && (!force) && (availablelanguages.Count > 2)) return true; LoadCredentials(); if (String.IsNullOrEmpty(AzureKey)) { @@ -335,91 +332,11 @@ public static async Task Initialize(bool force = false) else return true; } IsInitialized = true; - Debug.WriteLine("Facade: Number of available Languages: {0}", AvailableLanguages.Count); + Debug.WriteLine("Facade: Number of available Languages: {0}", availablelanguages.Count); return true; } - /// - /// Fills the AvailableLanguages dictionary - /// - /// Accept-Language - public static async Task GetLanguages(string AcceptLanguage = "en") - { - int retrycounter = 2; - while (retrycounter >= 0) - { - retrycounter--; - try - { - await GetLanguagesInternal(AcceptLanguage); - return; - } - catch - { - if (retrycounter <= 0) throw; - await Task.Delay(1000); //wait one second - } - } - } - - - - /// - /// Fills the AvailableLanguages dictionary - /// - /// Accept-Language - private static async Task GetLanguagesInternal(string AcceptLanguage = "en") - { - lock (AvailableLanguages) - { - AvailableLanguages.Clear(); - } - if (UseCustomEndpoint) - { - ContainerGetLanguages(); - return; - } - string uri = EndPointAddress + "/languages?api-version=3.0&scope=translation"; - if (ShowExperimental) uri += "&flight=experimental"; - - try - { - using HttpClient client = new HttpClient(); - using HttpRequestMessage request = new HttpRequestMessage(); - client.Timeout = TimeSpan.FromSeconds(10); - request.Method = HttpMethod.Get; - request.RequestUri = new Uri(uri); - request.Headers.Add("Accept-Language", AcceptLanguage); - HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false); - string jsonResponse = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - lock (AvailableLanguages) - { - if (response.StatusCode == System.Net.HttpStatusCode.OK) - { - var result = JsonConvert.DeserializeObject>>>(jsonResponse); - var languages = result["translation"]; - - string[] languagecodes = languages.Keys.ToArray(); - foreach (var kv in languages) - { - AvailableLanguages.Add(kv.Key, kv.Value["name"]); - } - } - } - Debug.Assert(AvailableLanguages.Count > 0, "GetLanguagesInternal: Zero languages."); - } - catch (HttpRequestException) - { - Debug.WriteLine("ERROR: Request exception while retrieving languages."); - authMode = AuthMode.Disconnected; - AvailableLanguages.Clear(); - return; - } - return; - } - - /// /// Takes a single language name and returns the matching language code. OK to pass a language code. /// @@ -427,13 +344,14 @@ private static async Task GetLanguagesInternal(string AcceptLanguage = "en") /// public static string LanguageNameToLanguageCode(string languagename) { - if (AvailableLanguages.ContainsKey(languagename)) + Dictionary availablelanguages = AvailableLanguages.GetLanguages(CultureInfo.CurrentUICulture.TwoLetterISOLanguageName).Result; + if (availablelanguages.ContainsKey(languagename)) { return languagename; } - else if (AvailableLanguages.ContainsValue(languagename)) + else if (availablelanguages.ContainsValue(languagename)) { - return AvailableLanguages.FirstOrDefault(t => t.Value == languagename).Key; + return availablelanguages.FirstOrDefault(t => t.Value == languagename).Key; } else { @@ -443,6 +361,7 @@ public static string LanguageNameToLanguageCode(string languagename) public static string LanguageCodeToLanguageName(string languagecode) { + Dictionary availablelanguages = AvailableLanguages.GetLanguages(CultureInfo.CurrentUICulture.TwoLetterISOLanguageName).Result; switch (languagecode.ToLowerInvariant()) { case "zh-hans": @@ -459,13 +378,13 @@ public static string LanguageCodeToLanguageName(string languagecode) languagecode = "yue"; break; } - if (AvailableLanguages.ContainsValue(languagecode)) + if (availablelanguages.ContainsValue(languagecode)) { return languagecode; } - else if (AvailableLanguages.ContainsKey(languagecode)) + else if (availablelanguages.ContainsKey(languagecode)) { - return AvailableLanguages.First(t => t.Key == languagecode).Value; + return availablelanguages.First(t => t.Key == languagecode).Value; } else { @@ -511,7 +430,7 @@ public static string[] TranslateArray(string[] texts, string from, string to, Co } else { - try { fromCode = AvailableLanguages.First(t => t.Value == from).Key; } + try { fromCode = AvailableLanguages.GetLanguages(CultureInfo.CurrentUICulture.TwoLetterISOLanguageName).Result.First(t => t.Value == from).Key; } catch { fromCode = from; } } @@ -773,7 +692,7 @@ private static async Task TranslateV3AsyncInternal( else { string path = "/translate?api-version=3.0"; - if (ShowExperimental) path += "&flight=experimental"; + if (AvailableLanguages.ShowExperimental) path += "&flight=experimental"; string params_ = "&from=" + from + "&to=" + to; string thiscategory = category; if (String.IsNullOrEmpty(category)) diff --git a/TranslationServices.Core/TranslationServices.Core.csproj b/TranslationServices.Core/TranslationServices.Core.csproj index 0539fb9..1010522 100644 --- a/TranslationServices.Core/TranslationServices.Core.csproj +++ b/TranslationServices.Core/TranslationServices.Core.csproj @@ -47,6 +47,7 @@ +