Skip to content
This repository has been archived by the owner on Sep 11, 2023. It is now read-only.

Commit

Permalink
Translations rework (#118)
Browse files Browse the repository at this point in the history
* initial rework of translations

* implemented new repo files checking for translation files

* finished modifying language parsing and loading

* shortened translation method

* removed old language file from scripts

* made english item in initial language selection window appear first

* fixed first boot not setting language properly

* documented and ordered a bit

* added failsafe for deleted translation files that were in use

* small optimization for last change
  • Loading branch information
maxijabase authored Feb 6, 2022
1 parent be36c06 commit 6906237
Show file tree
Hide file tree
Showing 43 changed files with 588 additions and 3,072 deletions.
1 change: 0 additions & 1 deletion Deploy/Compress_Beta.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ LiteralPath=
"sourcepawn/",
"lysis/",
"SPCode.exe",
"lang_0_spcode.xml",
"GPLv3.txt",
"License.txt"
DestinationPath = "SPCode.Beta.Portable.zip"
Expand Down
1 change: 0 additions & 1 deletion Deploy/Compress_Stable.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ LiteralPath=
"sourcepawn/",
"lysis/",
"SPCode.exe",
"lang_0_spcode.xml",
"GPLv3.txt",
"License.txt"
DestinationPath = "SPCode.Portable.zip"
Expand Down
1 change: 0 additions & 1 deletion Deploy/SPCode_Beta.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ SetOutPath $INSTDIR

File SPCode.exe

File lang_0_spcode.xml
File License.txt
File GPLv3.txt

Expand Down
1 change: 0 additions & 1 deletion Deploy/SPCode_Stable.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ SetOutPath $INSTDIR

File SPCode.exe

File lang_0_spcode.xml
File License.txt
File GPLv3.txt

Expand Down
1 change: 0 additions & 1 deletion Deploy/SpcodeUpdater/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
Expand Down
1 change: 0 additions & 1 deletion Interop/HotkeyControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using SPCode.Utils;
Expand Down
11 changes: 9 additions & 2 deletions Interop/OptionsControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace SPCode
[Serializable]
public class OptionsControl
{
public static int SVersion = 14;
public static int SVersion = 15;
public bool Editor_AgressiveIndentation = true;
public bool Editor_AutoCloseBrackets = true;
public bool Editor_AutoCloseStringChars = true;
Expand Down Expand Up @@ -87,6 +87,9 @@ public class OptionsControl
// Version 14
public ActionOnClose ActionOnClose;

// Version 15
public int TranslationsVersion;

public int Version = 11;

public void FillNullToDefaults()
Expand Down Expand Up @@ -174,9 +177,13 @@ public void FillNullToDefaults()
SearchOptions.MultilineRegex = false;
SearchOptions.ReplaceType = 0;
}
if (Version < 14)
{
TranslationsVersion = 0;
}

//new Optionsversion - reset new fields to default
Version = SVersion; //then Update Version afterwars
Version = SVersion; //then Update Version afterwards
}
}

Expand Down
207 changes: 154 additions & 53 deletions Interop/TranslationProvider.cs
Original file line number Diff line number Diff line change
@@ -1,98 +1,199 @@
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;
using static SPCode.Utils.DefaultTranslations;

namespace SPCode.Interop
{
public class TranslationProvider
{
public string[] AvailableLanguageIDs;
public string[] AvailableLanguages;

public List<string> AvailableLanguageIDs = new();
public List<string> AvailableLanguages = new();
public bool IsDefault = true;

private readonly Dictionary<string, string> LangDict = new(StringComparer.OrdinalIgnoreCase);
private readonly string _tempDir = Paths.GetTempDirectory();
private readonly string _translationsDir = Paths.GetTranslationsDirectory();
private static readonly Dictionary<string, string> _langDictionary = 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 string Get(string phrase)
public static string Translate(string phrase)
{
return LangDict.ContainsKey(phrase) ? LangDict[phrase] : "<empty>";
return _langDictionary.ContainsKey(phrase) ? _langDictionary[phrase] : "<empty>";
}

/// <summary>
/// Loads the specified language.
/// </summary>
/// <param name="lang">The language to load</param>
/// <param name="Initial"></param>
public void LoadLanguage(string lang, bool Initial = false)
/// <param name="initial">Whether this was the startup initial method call</param>
public void LoadLanguage(string lang, bool initial = false)
{
DefaultLangDict.Keys.ToList().ForEach(x => LangDict[x] = DefaultLangDict[x]);
var languageList = new List<string>();
var languageIDList = new List<string>();
languageList.Add("English");
languageIDList.Add("");
// This is probably the first boot ever
if (lang == string.Empty)
{
lang = Constants.DefaultLanguageID;
Program.OptionsObject.Language = lang;
}
lang = lang.Trim().ToLowerInvariant();
IsDefault = (string.IsNullOrEmpty(lang) || lang.ToLowerInvariant() == "en") && Initial;
if (File.Exists(Constants.LanguagesFile))
IsDefault = (string.IsNullOrEmpty(lang) || lang.ToLowerInvariant() == Constants.DefaultLanguageID) && initial;
var doc = new XmlDocument();

try
{
try
// Fill with defaults first
if (initial)
{
var document = new XmlDocument();
document.Load(Constants.LanguagesFile);
if (document.ChildNodes.Count < 1)
doc.Load(Path.Combine(_translationsDir, Constants.DefaultTranslationsFile));
foreach (XmlNode node in doc.ChildNodes[0].ChildNodes)
{
throw new Exception("No Root-Node: \"translations\" found");
_langDictionary.Add(node.Name, node.InnerText);
}

XmlNode rootLangNode = null;
foreach (XmlNode childNode in document.ChildNodes[0].ChildNodes)
// Return if the attempted language to load is the default one
if (lang == Constants.DefaultLanguageID)
{
var lID = childNode.Name;
var lNm = lID;
if (childNode.Name.ToLowerInvariant() == lang)
{
rootLangNode = childNode;
}
if (childNode.FirstChild.Name.ToLowerInvariant() == "language")
{
lNm = childNode.FirstChild.InnerText;
}
languageList.Add(lNm);
languageIDList.Add(lID);
return;
}
if (rootLangNode != null)
}

var file = Path.Combine(_translationsDir, $"{lang}.xml");
if (!File.Exists(file))
{
UpdateTranslations();
LoadLanguage(lang);
return;
}
else
{
doc.Load(file);

// Replace existing keys with the ones available in this file
foreach (XmlNode node in doc.ChildNodes[0].ChildNodes)
{
foreach (XmlNode node in rootLangNode.ChildNodes)
{
if (node.NodeType == XmlNodeType.Comment)
{
continue;
}
var nn = node.Name.ToLowerInvariant();
var nv = node.InnerText;
LangDict[nn] = nv;
}
_langDictionary[node.Name] = node.InnerText;
}
}
catch (Exception e)
}
catch (Exception)
{
throw;
}
}

/// <summary>
/// Gets all of the translation files and adds them to the global available languages list.
/// </summary>
public void ParseTranslationFiles()
{
try
{
var filesDir = Directory.GetFiles(_translationsDir).Where(x => x.EndsWith(".xml"));
foreach (var file in filesDir)
{
// 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 updating the translations file.\n" +
$"Details: {ex.Message}");
}
}

/// <summary>
/// Downloads the latest translation files release from GitHub for SPCode to parse them.
/// </summary>
public void UpdateTranslations()
{
// Clear temp folder before beggining
DirUtils.ClearTempFolder();

// 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))
{
MessageBox.Show("An error occured while reading the language-file. Without them, the editor wont show translations." + Environment.NewLine + "Details: " + e.Message
, "Error while reading configs."
, MessageBoxButton.OK
, MessageBoxImage.Warning);
File.Delete(destination);
}
File.Move(fInfo.FullName, destination);
}
AvailableLanguages = languageList.ToArray();
AvailableLanguageIDs = languageIDList.ToArray();

// Delete all temp folder contents
DirUtils.ClearTempFolder();

// Update version to options object
Program.OptionsObject.TranslationsVersion = int.Parse(_latestVersion.Name);
}

/// <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()
{
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);
}
}
}
4 changes: 2 additions & 2 deletions Interop/Updater/UpdateCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ private static async Task<IEnumerable<Release>> GetAllReleases()
PageSize = 10
};

var client = new GitHubClient(new ProductHeaderValue("spcode-client"));
var releases = await client.Repository.Release.GetAll("SPCodeOrg", "SPCode", apiOptions);
var client = new GitHubClient(new ProductHeaderValue(Constants.ProductHeaderValueName));
var releases = await client.Repository.Release.GetAll(Constants.OrgName, Constants.MainRepoName, apiOptions);
#if BETA
var finalReleasesList = releases.Where(x => x.Prerelease);
#else
Expand Down
17 changes: 9 additions & 8 deletions Interop/Updater/UpdateWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using MahApps.Metro.Controls.Dialogs;
using MdXaml;
using SPCode.Utils;
using static SPCode.Interop.TranslationProvider;

namespace SPCode.Interop.Updater
{
Expand Down Expand Up @@ -85,11 +86,11 @@ public void PrepareUpdateWindow(bool OnlyChangelog = false)
}
else
{
Title = string.Format(Program.Translations.Get("VersionAvailable"), updateInfo.AllReleases[0].TagName);
MainLine.Text = Program.Translations.Get("WantToUpdate");
ActionYesButton.Content = Program.Translations.Get("Yes");
ActionNoButton.Content = Program.Translations.Get("No");
ActionGithubButton.Content = Program.Translations.Get("ViewGithub");
Title = string.Format(Translate("VersionAvailable"), updateInfo.AllReleases[0].TagName);
MainLine.Text = Translate("WantToUpdate");
ActionYesButton.Content = Translate("Yes");
ActionNoButton.Content = Translate("No");
ActionGithubButton.Content = Translate("ViewGithub");
}

var releasesBody = new StringBuilder();
Expand Down Expand Up @@ -131,8 +132,8 @@ private void StartUpdate()
ActionYesButton.Visibility = Visibility.Hidden;
ActionNoButton.Visibility = Visibility.Hidden;
ActionGithubButton.Visibility = Visibility.Hidden;
MainLine.Text = string.Format(Program.Translations.Get("UpdatingTo"), updateInfo.AllReleases[0].TagName);
SubLine.Text = Program.Translations.Get("DownloadingUpdater");
MainLine.Text = string.Format(Translate("UpdatingTo"), updateInfo.AllReleases[0].TagName);
SubLine.Text = Translate("DownloadingUpdater");
var t = new Thread(UpdateDownloadWorker);
t.Start();
}
Expand Down Expand Up @@ -180,7 +181,7 @@ private void UpdateDownloadWorker()
/// </summary>
private void FinalizeUpdate()
{
SubLine.Text = Program.Translations.Get("StartingUpdater");
SubLine.Text = Translate("StartingUpdater");
UpdateLayout();
try
{
Expand Down
Loading

0 comments on commit 6906237

Please sign in to comment.