-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
598fed1
commit 6a06989
Showing
4 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
<Version>0.9.0</Version> | ||
</PropertyGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using System.Xml; | ||
|
||
namespace App | ||
{ | ||
class Program | ||
{ | ||
static int _errorCount = 0; | ||
static int _warningCount = 0; | ||
static void Main(string[] args) | ||
{ | ||
try | ||
{ | ||
if (args.Length < 1) | ||
{ | ||
Console.WriteLine($"##vso[task.complete result=Failed;] usage: XliffCheck <xliff directory>"); | ||
return; | ||
} | ||
var xliffDocuments = new Dictionary<string, XmlDocument>(); | ||
XmlDocument xliffBaseFile = null; | ||
foreach (var file in Directory.EnumerateFiles(args[0])) | ||
{ | ||
var xmlDoc = new XmlDocument(); | ||
xmlDoc.Load(file); | ||
if (file.EndsWith(".g.xlf")) | ||
{ | ||
xliffBaseFile = xmlDoc; | ||
continue; | ||
} | ||
var name = Path.GetFileNameWithoutExtension(file); | ||
var key = name.Substring(name.Length - 5); | ||
xliffDocuments.Add(key, xmlDoc); | ||
} | ||
var translations = new Dictionary<string, string>(); | ||
if (xliffBaseFile != null) | ||
AddTranslation(translations, xliffBaseFile); | ||
|
||
foreach (var xliffDoc in xliffDocuments) | ||
{ | ||
var nsmgr = new XmlNamespaceManager(xliffDoc.Value.NameTable); | ||
nsmgr.AddNamespace("my", "urn:oasis:names:tc:xliff:document:1.2"); | ||
//Check aganst Project.g.xlf | ||
if (xliffBaseFile != null) | ||
{ | ||
for (int i = 0; i < translations.Count; i++) | ||
{ | ||
var element = translations.ElementAt(i); | ||
var node = xliffDoc.Value.SelectSingleNode($"//*[@id='{element.Key}']"); | ||
if (node == null) | ||
{ | ||
Console.WriteLine($"##vso[task.logissue type=error] {xliffDoc.Key} Translation for '{element.Value}' is missing ({element.Key})"); | ||
_errorCount++; | ||
} | ||
else | ||
{ | ||
var source = node.SelectSingleNode("my:source", nsmgr).InnerText; | ||
if (!source.Equals(element.Value)) | ||
{ | ||
Console.WriteLine($"##vso[task.logissue type=warning] Source '{element.Value}' (*.g.xlf) and '{source}' (*.{xliffDoc.Key}.xlf) are not the same ({element.Key})"); | ||
_errorCount++; | ||
} | ||
} | ||
} | ||
} | ||
//Check inside each xlf-File | ||
foreach (XmlNode node in xliffDoc.Value.GetElementsByTagName("trans-unit")) | ||
{ | ||
var targetElement = node.SelectSingleNode("my:target", nsmgr); | ||
if (targetElement == null) | ||
continue; | ||
var sourceElement = node.SelectSingleNode("my:source", nsmgr); | ||
if (CheckEntry("warning", targetElement.InnerText, "[NAB: REVIEW]", xliffDoc.Key, sourceElement.InnerText, node.Attributes["id"].Value, "needs review")) | ||
continue; | ||
if (CheckEntry("error", targetElement.InnerText, "[NAB: NOT TRANSLATED]", xliffDoc.Key, sourceElement.InnerText, node.Attributes["id"].Value, "is missing")) | ||
continue; | ||
if (CheckEntry("error", targetElement.InnerText, "", xliffDoc.Key, sourceElement.InnerText, node.Attributes["id"].Value, "is missing")) | ||
continue; | ||
if (targetElement.Attributes["state"] == null) | ||
continue; | ||
if (CheckEntry("warning", targetElement.Attributes["state"].Value, "needs-l10n", xliffDoc.Key, sourceElement.InnerText, node.Attributes["id"].Value, "needs adaptation")) | ||
continue; | ||
if (CheckEntry("warning", targetElement.Attributes["state"].Value, "needs-adaptation", xliffDoc.Key, sourceElement.InnerText, node.Attributes["id"].Value, "needs adaptation")) | ||
continue; | ||
if (CheckEntry("warning", targetElement.Attributes["state"].Value, "needs-review-translation", xliffDoc.Key, sourceElement.InnerText, node.Attributes["id"].Value, "needs review")) | ||
continue; | ||
if (CheckEntry("error", targetElement.Attributes["state"].Value, "new", xliffDoc.Key, sourceElement.InnerText, node.Attributes["id"].Value, "is missing")) | ||
continue; | ||
} | ||
} | ||
if (_errorCount == 0 && _warningCount == 0) | ||
{ | ||
Console.WriteLine($"##vso[task.complete result=Succeeded;]DONE"); | ||
} | ||
else if (_errorCount == 0) | ||
{ | ||
Console.WriteLine($"##vso[task.complete result=SucceededWithIssues;]DONE"); | ||
} | ||
else | ||
{ | ||
Console.WriteLine($"##vso[task.complete result=Failed;]DONE"); | ||
} | ||
} | ||
catch (Exception ex) | ||
{ | ||
Console.WriteLine($"##vso[task.logissue type=error]{ex.Message}"); | ||
Console.WriteLine($"##vso[task.complete result=Failed;]DONE"); | ||
return; | ||
} | ||
} | ||
|
||
private static bool CheckEntry(string logIssueType, string value, string valueToCheck, string lang, string sourceId, string sourceValue, string whatIsToDo) | ||
{ | ||
if (value == valueToCheck || (valueToCheck == "[NAB: REVIEW]" && value.StartsWith(valueToCheck))) | ||
{ | ||
Console.WriteLine($"##vso[task.logissue type={logIssueType}] {lang} Translation for '{sourceId}' {whatIsToDo} ({sourceValue})"); | ||
switch(logIssueType) | ||
{ | ||
case "warning": _warningCount++; break; | ||
case "error": _errorCount++; break; | ||
} | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
static void AddTranslation(Dictionary<string, string> translations, XmlDocument xmlDoc) | ||
{ | ||
foreach (XmlNode node in xmlDoc.ChildNodes[1].ChildNodes[0].ChildNodes[0].ChildNodes[0].ChildNodes) | ||
{ | ||
|
||
var translate = node.Attributes["translate"].Value; | ||
var id = node.Attributes["id"].Value; | ||
if (translate == "yes") | ||
translations.Add(id, node.ChildNodes[1].InnerText); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"profiles": { | ||
"App": { | ||
"commandName": "Project" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 16 | ||
VisualStudioVersion = 16.0.30611.23 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App", "App\App.csproj", "{A7605AFA-B9DF-4C88-9673-5CE51A9DA27E}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{A7605AFA-B9DF-4C88-9673-5CE51A9DA27E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{A7605AFA-B9DF-4C88-9673-5CE51A9DA27E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{A7605AFA-B9DF-4C88-9673-5CE51A9DA27E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{A7605AFA-B9DF-4C88-9673-5CE51A9DA27E}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {73337756-CD73-4C6B-AAC7-B3FF09E86F25} | ||
EndGlobalSection | ||
EndGlobal |