Skip to content

Instantly share code, notes, and snippets.

@dotMorten
Created June 20, 2020 01:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dotMorten/2808950a5fa4474961ac768c71fbd780 to your computer and use it in GitHub Desktop.
Save dotMorten/2808950a5fa4474961ac768c71fbd780 to your computer and use it in GitHub Desktop.
Converting xliff to resx/resw as a build task
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="UpdateRuntimeResources">
<ItemGroup>
<XLiffResources Include="$(MSBuildThisFileDirectory)\xliff_resources\**\*.xliff" />
</ItemGroup>
<ImportResourceFiles XliffFiles="@(XLiffResources)" OutputDirectory="$(MSBuildThisFileDirectory)\LocalizedStrings" IsUWP="False" />
</Target>
<UsingTask TaskName="ImportResourceFiles" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<XliffFiles ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<OutputDirectory ParameterType="System.String" Required="true" />
<IsUWP ParameterType="System.Boolean" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.IO.Packaging" />
<Using Namespace="System.Linq" />
<Using Namespace="System.Net" />
<Using Namespace="System.Xml" />
<Using Namespace="Microsoft.Build.Framework" />
<Using Namespace="Microsoft.Build.Utilities" />
<Code Type="Fragment" Language="cs">
<![CDATA[
string zipTempPath = null;
string outfileDir = OutputDirectory;
Log.LogMessage("Output directory: " + OutputDirectory, MessageImportance.High);
try {
var inFiles = XliffFiles.Select(f => f.GetMetadata("FullPath"));
string outputFilename = "Resources";
var files = new Dictionary<string, List<string>>();
foreach (var infile in inFiles)
{
var file = new System.IO.FileInfo(infile);
string languageId = file.Directory.Parent.Name;
if (!files.ContainsKey(languageId))
files[languageId] = new List<string>();
files[languageId].Add(infile);
}
foreach(var filelist in files)
{
string languageId = filelist.Key;
string outfile = outfileDir;
if (languageId == "en")
languageId = "en-US";
else if (languageId == "nb")
languageId = "nb-NO";
if (IsUWP)
{
outfile = System.IO.Path.Combine(outfile, languageId, outputFilename);
}
else
{
if (languageId == "en-US")
outfile = System.IO.Path.Combine(outfile, outputFilename);
else
outfile = System.IO.Path.Combine(outfile, outputFilename + "." + languageId);
}
outfile += IsUWP ? ".resw" : ".resx";
string message = "Generating resource for language '" + languageId + "'...";
Console.WriteLine(message);
var d = new FileInfo(outfile).Directory;
if (!d.Exists)
d.Create();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
using (XmlWriter writer = XmlWriter.Create(outfile, settings))
{
Dictionary<string, object> idChecker = new Dictionary<string, object>();
writer.WriteStartDocument();
writer.WriteStartElement("root");
writer.WriteStartElement("resheader");
writer.WriteAttributeString("name", "resmimetype");
writer.WriteElementString("value", "text/microsoft-resx");
writer.WriteEndElement(); //resheader
writer.WriteStartElement("resheader");
writer.WriteAttributeString("name", "version");
writer.WriteElementString("value", "2.0");
writer.WriteEndElement(); //resheader
writer.WriteStartElement("resheader");
writer.WriteAttributeString("name", "reader");
writer.WriteElementString("value", "System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
writer.WriteEndElement(); //resheader
writer.WriteStartElement("resheader");
writer.WriteAttributeString("name", "writer");
writer.WriteElementString("value", "System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
writer.WriteEndElement(); //resheader
writer.WriteStartElement("data");
writer.WriteAttributeString("name", "Resources_Language");
writer.WriteAttributeString("xml", "space", "", "preserve");
writer.WriteElementString("value", languageId);
writer.WriteEndElement(); //data
foreach (var infile in filelist.Value)
{
var file = new System.IO.FileInfo(infile);
string filename = file.Name.Substring(0, file.Name.LastIndexOf('.'));
Console.WriteLine("\tProcessing ' " + infile + "'...");
var fileExt = file.Extension.ToLowerInvariant();
if (fileExt == ".xliff")
{
using (XmlReader reader = XmlReader.Create(infile))
{
while (reader.ReadToFollowing("trans-unit"))
{
string id = reader.GetAttribute("id");
if (idChecker.ContainsKey(id))
throw new InvalidOperationException("Duplicate resource ids detected");
idChecker[id] = null;
string resourceString = null;
while (reader.Read() && reader.Name != "trans-unit")
{
if (reader.Name == "target")
{
resourceString = reader.ReadElementContentAsString();
break; //target takes precedence over source
}
if (reader.Name == "source")
{
resourceString = reader.ReadElementContentAsString();
}
}
if (resourceString != null)
{
writer.WriteStartElement("data");
writer.WriteAttributeString("name", id);
writer.WriteAttributeString("xml", "space", "", "preserve");
int index = -1;
for (int i = 1; i < 10; i++)
{
while ((index = resourceString.IndexOf("%" + i.ToString() + "$s")) > -1)
{
resourceString = resourceString.Replace("%" + i.ToString() + "$s", "{" + (i-1).ToString() + "}");
}
}
if (resourceString.Contains("%"))
{
throw new InvalidOperationException("String parameter placeholder not supported");
}
writer.WriteElementString("value", resourceString);
writer.WriteEndElement(); //data
}
}
}
}
else if (fileExt == ".json")
{
// Example: "output\resources\navigation\abbreviations\<LANG>.json" becomes "abbreviations__json" key
var id = file.Directory.Name + "_json";
if (idChecker.ContainsKey(id))
throw new InvalidOperationException("Duplicate resource ID detected: " + id);
idChecker[id] = null;
var jsonText = File.ReadAllText(infile);
writer.WriteStartElement("data");
writer.WriteAttributeString("name", id);
writer.WriteElementString("value", jsonText);
writer.WriteEndElement(); //data
}
else
{
throw new ArgumentException("Found a resource file of unknown file: " + infile);
}
}
writer.WriteEndElement(); //root
writer.WriteEndDocument();
writer.Flush();
writer.Close();
}
}
return true;
}
catch (Exception ex)
{
Log.LogErrorFromException(ex);
return false;
}
]]>
</Code>
</Task>
</UsingTask>
</Project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment