Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to localize XSLT

0.00/5 (No votes)
10 Apr 2012 1  
Text in an XSLT may be localized by reading translated strings from an XML document. Numbers may also be localized.

Introduction

Text in an XSLT may be localized by reading translated strings from an XML document. Numbers may also be localized.

The XML document may contain either one language with one XML document for each language, or alternatively, a single XML document with all languages. The XML formats in the following example follows Microsoft .NET resource (.resx) files (one file per language) or a single TMX (translation memory exchange) document with all languages. Any format, however, may be used as long as the XPath used to read the text is consistent.

Using the code

Both options use the XPath document function to read the XML with the translated strings. Define parameters for each string used in the XSLT. Using parameters rather than variables allows the values to be overridden when the XSLT is transformed. Use xsl:value-of to display the translated text. When the transform is processed, pass the language code, for example, 'fr', and the URL to the resource XML document for the desired language.

In .NET, the XSLT arguments are passed using the XsltArgumentList class.

System.Xml.Xsl.XsltArgumentList args = new System.Xml.Xsl.XsltArgumentList();
args.AddParam("lang", "", "fr");
args.AddParam("localeUrl", "", "Resources.fr.resx");

But first, consider a sample data XML to process and a sample XSLT before internationalization.

Sample XML data document

<?xml version="1.0"?>
<root>
    <Number>34567.89</Number>
</root>

Sample XSLT without internationalization

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output encoding="utf-8" omit-xml-declaration="yes"/>

<xsl:template match="/root">
    The number is: <xsl:value-of select="Number"/>
</xsl:template>

</xsl:stylesheet>

Sample result

The number is: 34567.89.

Notice the number in the result is not formatted.

Localization of XSLT

Option 1: Create an XML file for each language

In the XSLT, define a parameter to accept the URL to the resource XML document for the selected language.

XSLT localized for RESX format with one RESX file for each language:

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output encoding="utf-8" omit-xml-declaration="yes"/>

<xsl:param name="lang" select="'en'"/>

<xsl:param name="localeUrl" select="'Resources.resx'"/>
<xsl:variable name="localeXml" select="document($localeUrl)/*" />
<xsl:param name="NumberFormat" 
           select="$localeXml/data[@name='NumberFormat']/value/text()"/>
<xsl:param name="NumberCaption" 
           select="$localeXml/data[@name='NumberCaption']/value/text()"/>

<xsl:decimal-format name="en" 
  grouping-separator="," decimal-separator="." />
<xsl:decimal-format name="es" 
  grouping-separator="." decimal-separator="," />
<xsl:decimal-format name="fr" 
  grouping-separator=" " decimal-separator="," />

<xsl:template match="/root">
    <xsl:value-of select="$NumberCaption"/>
    <xsl:value-of select="' '"/>
    <xsl:value-of select="format-number(Number, $NumberFormat, $lang)"/>
</xsl:template>

</xsl:stylesheet>

Resource files in English, Spanish (es) and French (fr)

Resources.resx
<?xml version="1.0" encoding="utf-8" ?>
<root>
    <xsd:schema ...
    </xsd:schema>
    <resheader name="ResMimeType">
        <value>text/microsoft-resx</value>
    </resheader>
    <data name="NumberFormat" xml:space="preserve">
        <value>#,###.00</value>
    </data>
    <data name="NumberCaption" xml:space="preserve">
        <value>The number is:</value>
    </data>
</root>
Result

The number is: 34,567.89.

Notice that the number is formatted with a ',' as the thousands separator.

Resources.es.resx
<?xml version="1.0" encoding="utf-8" ?>
<root>
    <xsd:schema ...
    </xsd:schema>
    <resheader name="ResMimeType">
        <value>text/microsoft-resx</value>
    </resheader>
    <data name="NumberFormat" xml:space="preserve">
        <value>#.###,00</value>
    </data>
    <data name="NumberCaption" xml:space="preserve">
        <value>El número es:</value>
    </data>
</root>
Result

El número es: 34.567,89

Resources.fr.resx
<?xml version="1.0" encoding="utf-8" ?>
<root>
    <xsd:schema ...
    </xsd:schema>
    <resheader name="ResMimeType">
        <value>text/microsoft-resx</value>
    </resheader>
    <data name="NumberFormat" xml:space="preserve">
        <value># ###,00</value>
    </data>
    <data name="NumberCaption" xml:space="preserve">
        <value>Le nombre est:</value>
    </data>
</root>
Result

Le nombre est: 34 567,89

Option 2: Create a single XML file with all languages

XSLT localized for TMX format with one XML file with all languages:

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output encoding="utf-8" omit-xml-declaration="yes"/>

<xsl:param name="lang" select="'en'"/>

<xsl:variable name="tmx" select="document('tmx.xml')/tmx/body"/>
<xsl:param name="NumberFormat" 
           select="$tmx/tu[@tuid='NumberFormat']/tuv[lang($lang)]/seg"/>
<xsl:param name="NumberCaption" 
           select="$tmx/tu[@tuid='NumberCaption']/tuv[lang($lang)]/seg"/>

<xsl:decimal-format name="en" grouping-separator="," decimal-separator="." />
<xsl:decimal-format name="es" grouping-separator="." decimal-separator="," />
<xsl:decimal-format name="fr" grouping-separator=" " decimal-separator="," />

<xsl:template match="/root">
    <xsl:value-of select="$NumberCaption"/>
    <xsl:value-of select="' '"/>
    <xsl:value-of select="format-number(Number, $NumberFormat, $lang)"/>
</xsl:template>

</xsl:stylesheet>

Translated XML document

tmx.xml
<?xml version="1.0"?>
<tmx>
  <body>
    <tu tuid="NumberFormat">
      <tuv xml:lang="en"><seg>#,###.00</seg></tuv>
      <tuv xml:lang="es"><seg>#.###,00</seg></tuv>
      <tuv xml:lang="fr"><seg># ###,00</seg></tuv>
    </tu>
    <tu tuid="NumberCaption">
      <tuv xml:lang="en"><seg>The number is:</seg></tuv>
      <tuv xml:lang="es"><seg>El número es:</seg></tuv>
      <tuv xml:lang="fr"><seg>Le nombre est:</seg></tuv>
    </tu>
  </body>
</tmx>

Go global!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here