This repository was archived by the owner on Sep 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathTranslationProvider.cs
More file actions
235 lines (208 loc) · 8.16 KB
/
TranslationProvider.cs
File metadata and controls
235 lines (208 loc) · 8.16 KB
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Windows;
using System.Xml;
using Octokit;
using SPCode.Utils;
namespace SPCode.Interop
{
public class TranslationProvider
{
public List<string> AvailableLanguageIDs = new();
public List<string> AvailableLanguages = new();
private readonly string _tempDir = PathsHelper.TempDirectory;
private readonly string _translationsDir = PathsHelper.TranslationsDirectory;
private static readonly Dictionary<string, string> _langDictionary = new(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<string, string> _defaultDictionary = new(StringComparer.OrdinalIgnoreCase);
private Release _latestVersion;
public TranslationProvider()
{
// Make sure translations dir exists
if (!Directory.Exists(_translationsDir))
{
Directory.CreateDirectory(_translationsDir);
}
if (IsUpdateAvailable())
{
UpdateTranslations();
}
ParseTranslationFiles();
}
/// <summary>
/// Gets the translation of the specified phrase.
/// </summary>
/// <param name="phrase">The phrase to return translated</param>
/// <returns></returns>
public static string Translate(string phrase)
{
if (_langDictionary.TryGetValue(phrase, out var result))
{
return result;
}
else if (_defaultDictionary.TryGetValue(phrase, out result))
{
return result;
}
else
{
return $"<{phrase}>";
}
}
/// <summary>
/// Loads the specified language.
/// </summary>
/// <param name="lang">The language to load</param>
/// <param name="initial">Whether this was the startup initial method call</param>
public void LoadLanguage(string lang, bool initial = false)
{
_langDictionary.Clear();
if (lang == string.Empty)
{
// This is probably the first boot ever
lang = Constants.DefaultLanguageID;
Program.OptionsObject.Language = lang;
}
lang = lang.Trim().ToLowerInvariant();
var doc = new XmlDocument();
try
{
// Fill with defaults on first boot
if (initial)
{
doc.Load(Path.Combine(_translationsDir, Constants.DefaultTranslationsFile));
foreach (XmlNode node in doc.ChildNodes[0].ChildNodes)
{
if (node.NodeType != XmlNodeType.Comment)
{
_defaultDictionary.Add(node.Name, node.InnerText);
}
}
}
var file = Path.Combine(_translationsDir, $"{lang}.xml");
if (!File.Exists(file))
{
UpdateTranslations();
LoadLanguage(lang);
return;
}
else
{
doc.Load(file);
Program.IsRTL = false;
// Replace existing keys with the ones available in this file
foreach (XmlNode node in doc.ChildNodes[0].ChildNodes)
{
if (node.NodeType != XmlNodeType.Comment)
{
_langDictionary.Add(node.Name, node.InnerText);
}
if (node.Name == "rtl" && node.InnerText == "true")
{
Program.IsRTL = true;
}
}
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets all of the translation files and adds them to the global available languages list.
/// </summary>
public void ParseTranslationFiles()
{
var filesDir = Directory.GetFiles(_translationsDir).Where(x => x.EndsWith(".xml"));
foreach (var file in filesDir)
{
try
{
// Create wrapper
var fInfo = new FileInfo(file);
// Parse content in an XML object
var doc = new XmlDocument();
doc.LoadXml(File.ReadAllText(fInfo.FullName));
// Get language name and ID
var langName = doc.ChildNodes[0].ChildNodes
.Cast<XmlNode>()
.Single(x => x.Name == "language")
.InnerText;
var langID = fInfo.Name.Substring(0, fInfo.Name.IndexOf('.'));
// Add file to the available languages lists
AvailableLanguages.Add(langName);
AvailableLanguageIDs.Add(langID);
}
catch (Exception ex)
{
MessageBox.Show($"There was a problem while parsing the translation file '{file}'.\n" +
$"Details: {ex.Message}");
continue;
}
}
}
/// <summary>
/// Downloads the latest translation files release from GitHub for SPCode to parse them.
/// </summary>
public void UpdateTranslations()
{
try
{
// Clear temp folder before beggining
DirHelper.ClearSPCodeTempFolder();
// Download latest release zip file
var wc = new WebClient();
var downloadedFile = Path.Combine(_tempDir, "langs.zip");
wc.Headers.Add(HttpRequestHeader.UserAgent, Constants.ProductHeaderValueName);
wc.DownloadFile(_latestVersion.ZipballUrl, downloadedFile);
// Decompress and replace all of its files
ZipFile.ExtractToDirectory(downloadedFile, _tempDir);
var filesDir = Directory.GetFiles(Directory.GetDirectories(_tempDir)[0]).Where(x => x.EndsWith(".xml"));
foreach (var file in filesDir)
{
// Create wrapper
var fInfo = new FileInfo(file);
// Replace current file with this one
var destination = Path.Combine(_translationsDir, fInfo.Name);
if (File.Exists(destination))
{
File.Delete(destination);
}
File.Move(fInfo.FullName, destination);
}
// Delete all temp folder contents
DirHelper.ClearSPCodeTempFolder();
// Update version to options object
Program.OptionsObject.TranslationsVersion = int.Parse(_latestVersion.Name);
}
catch (Exception ex)
{
MessageBox.Show($"There was a problem while downloading the new translation files.\n" +
$"Details: {ex.Message}");
}
}
/// <summary>
/// Compares the stored version of the translations release with the one from GitHub
/// </summary>
/// <returns>Whether there's an update available</returns>
public bool IsUpdateAvailable()
{
try
{
var client = new GitHubClient(new ProductHeaderValue(Constants.ProductHeaderValueName));
var versionStored = Program.OptionsObject.TranslationsVersion;
_latestVersion = client.Repository.Release.GetAll(Constants.OrgName,
Constants.TranslationsRepoName).Result[0];
return versionStored < int.Parse(_latestVersion.Name);
}
catch (Exception)
{
return false;
}
}
}
}