Home > Uncategorized > Synchronizing #Resx files within a .NET project

Synchronizing #Resx files within a .NET project

resx

If you are developing a multi-lingual website or application in .NET, then you undoubtedly use resx files. Over time, it’s likely that these files go out of sync, when you add text to the english version, and forget to send the french version for translation.

Here’s some code in C# that can compare a master resx file (english) with a candidate file (french), and determine what keys are missing, and what keys are present, but not translated.

To start off with, lets create an XSD model for the resx xml;

<?xml version=”1.0″ encoding=”UTF-8″?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema&#8221; elementFormDefault=”qualified”>
<xs:import namespace=”http://www.w3.org/XML/1998/namespace&#8221; schemaLocation=”xml.xsd”/>
<xs:element name=”root”>
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs=”unbounded” ref=”resheader”/>
<xs:element maxOccurs=”unbounded” ref=”data”/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name=”resheader”>
<xs:complexType>
<xs:complexContent>
<xs:extension base=”value”>
<xs:attribute name=”name” use=”required” type=”xs:NCName”/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name=”data”>
<xs:complexType>
<xs:complexContent>
<xs:extension base=”value”>
<xs:sequence>
<xs:element minOccurs=”0″ ref=”comment”/>
</xs:sequence>
<xs:attribute name=”name” use=”required”/>
<xs:attribute ref=”xml:space”/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name=”comment” type=”xs:string”/>
<xs:complexType name=”value”>
<xs:sequence>
<xs:element ref=”value”/>
</xs:sequence>
</xs:complexType>
<xs:element name=”value” type=”xs:string”/>
</xs:schema>

From this, I create resx.cs by running xsd.exe, and include it in my project

Two helper functions I’m going to need is some code to serialise and deserialise the XML into objects as follows;

public static T ParseXmlData<T>(string xml)
{
var xsT = new XmlSerializer(typeof(T));
var srT = new StringReader(xml);
return (T)xsT.Deserialize(srT);
}
public static string Serialize<T>(T o)
{
var swOutput = new StringWriter();
var xs = new XmlSerializer(typeof(T));
xs.Serialize(swOutput, o);
return swOutput.ToString();
}

Now, lets create the main function

private static void CompareResx(string masterFile, string testFile, string outputFile)
{
var strMasterXml = File.ReadAllText(masterFile);
var strTestXml = File.ReadAllText(testFile);
var rootMaster = ParseXmlData<root>(strMasterXml);
var rootTest = ParseXmlData<root>(strTestXml);
if (rootTest.data == null) return;
var lMissingNodes = new List<data>();
foreach (var entry in rootMaster.data)
{
var testEntry = rootTest.data.FirstOrDefault(e => e.name == entry.name);
if (testEntry != null)
{
if (testEntry.value1 == entry.value1)
{
Console.WriteLine(“English?” + entry.name);
lMissingNodes.Add(entry);
}
else if (string.IsNullOrEmpty(testEntry.value1))
{
Console.WriteLine(“Blank entry:” + entry.name);
lMissingNodes.Add(entry);
}
}
else
{
Console.WriteLine(“Missing entry:” + entry.name);
lMissingNodes.Add(entry);
}
}
var output = new root();
output.data = lMissingNodes.ToArray();
var strOutputXml = Serialize(output);
File.WriteAllText(outputFile, strOutputXml);
}

Pass in the location of the master resx, the candidate resx, and an output file, and then run this code.

Categories: Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: