-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathLanguage.cs
164 lines (151 loc) · 7.13 KB
/
Language.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
namespace DocumentTranslationService.Core
{
public partial class DocumentTranslationService
{
/// <summary>
/// Holds the set of languages. If list is empty, call GetLanguagesAsync first.
/// </summary>
public Dictionary<string, Language> Languages { get; private set; } = new();
/// <summary>
/// Fires when the 'Languages' list finished updating.
/// </summary>
public event EventHandler OnLanguagesUpdate;
public bool ShowExperimental { get; set; }
private bool? lastShowExperimental = null;
private string lastLanguage;
/// <summary>
/// Read the set of languages from the service and store in the Languages list.
/// This function can run before any authentication is set up, because the server side does not need authentication for this call.
/// </summary>
/// <param name="acceptLanguage">The language you want the language list in. Default is the thread locale</param>
/// <returns>Task</returns>
public async Task GetLanguagesAsync(string acceptLanguage = null)
{
await GetLanguagesAsyncInternal(acceptLanguage, false);
if (ShowExperimental)
{
Dictionary<string, Language> nonExpLangs = new(Languages);
await GetLanguagesAsyncInternal(acceptLanguage, true);
foreach (var lang in Languages)
if (nonExpLangs.ContainsKey(lang.Key)) lang.Value.Experimental = false;
else lang.Value.Experimental = true;
}
OnLanguagesUpdate?.Invoke(this, EventArgs.Empty);
return;
}
/// <summary>
/// Read the set of languages from the service and store in the Languages list.
/// This function can run before any authentication is set up, because the server side does not need authentication for this call.
/// </summary>
/// <param name="acceptLanguage">The language you want the language list in. Default is the thread locale</param>
/// <param name="showExperimental">Whether to show the experimental languages</param>
/// <returns>Task</returns>
private async Task GetLanguagesAsyncInternal(string acceptLanguage = null, bool showExperimental = false)
{
if (string.IsNullOrEmpty(acceptLanguage)) acceptLanguage = System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
//Cut this call short if we have everything and no change in language of the language names, or in the experimental state.
if ((acceptLanguage == lastLanguage) && (showExperimental == lastShowExperimental) && (Languages.Count > 10)) return;
lastLanguage = acceptLanguage;
lastShowExperimental = showExperimental;
string textTransUri = TextTransUri;
for (int i = 0; i < 3; i++) //retry loop
{
HttpRequestMessage request = new()
{
Method = HttpMethod.Get
};
request.Headers.AcceptLanguage.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue(acceptLanguage));
request.RequestUri = showExperimental
? new Uri($"{textTransUri}/languages?api-version=3.0&scope=translation&flight=experimental")
: new Uri($"{textTransUri}/languages?api-version=3.0&scope=translation");
HttpClient client = HttpClientFactory.GetHttpClient();
HttpResponseMessage response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
Languages.Clear();
string resultJson = await response.Content.ReadAsStringAsync();
using JsonDocument doc = JsonDocument.Parse(resultJson);
var langprop = doc.RootElement.GetProperty("translation");
foreach (var item in langprop.EnumerateObject())
{
Language langEntry = new(null, null);
var langCode = item.Name;
langEntry.LangCode = langCode;
foreach (var prop in item.Value.EnumerateObject())
{
string n = prop.Name;
string v = prop.Value.GetString();
switch (n)
{
case "name":
langEntry.Name = v;
break;
case "nativeName":
langEntry.NativeName = v;
break;
case "dir":
{ if (v == "rtl") langEntry.Bidi = true; else langEntry.Bidi = false; }
break;
default:
break;
}
}
if (!Languages.TryAdd(langCode, langEntry))
Debug.WriteLine($"Duplicate language entry: {langCode}");
}
Debug.WriteLine($"Languages received: {Languages.Count}, Experimental: {showExperimental}");
return;
}
else if (response.StatusCode is System.Net.HttpStatusCode.NotFound or System.Net.HttpStatusCode.Unauthorized)
textTransUri = "https://api.cognitive.microsofttranslator.us/"; //try Azure Gov in case Azure public is blocked.
else await Task.Delay(1000); //wait one seconds before retry
}
return;
}
}
/// <summary>
/// Holds information about a language
/// </summary>
public class Language : ICloneable
{
public Language(string langCode, string name)
{
LangCode = langCode;
Name = name;
}
/// <summary>
/// ISO639 language code
/// </summary>
public string LangCode { get; set; }
/// <summary>
/// Friendly name of the language in the language of the Accept-Language setting
/// </summary>
public string Name { get; set; }
/// <summary>
/// Name of the language in its own language
/// </summary>
public string NativeName { get; set; }
/// <summary>
/// Is this a bidirectional language?
/// </summary>
public bool Bidi { get; set; }
/// <summary>
/// Indicates whether this language has been selected, for multi-language operations
/// </summary>
public bool IsChecked { get; set; }
/// <summary>
/// Is this an experimental language?
/// </summary>
public bool Experimental;
public object Clone()
{
return (Language)MemberwiseClone();
}
}
}