Download pulse

babelfish.xsl - a concept for template localisation in XSL

The idea behind the babelfish concept is to separate the layout generated by the XSL-templates from the localisation of the templates. This results in layout-templates which will be locale/language-independant and therefore highly re-usable, while localisation of the templates will be provided in a standardised way through the babelfish.xsl-templates. This also makes it easier to implement further localisations.

The babelfish in the pulse demo layout

Throughout the pulse demo layout we use the babelfish concept to provide the localisation for the layout-templates. The babelfish.xsl files are located in the ".../i18n/..."-folders within the ".../xsl.../"-folders for the layout-templates.

The babelfish concept makes use of two seperate types of XSL-templates:

  • the main babelfish template used for choosing the right locale to be used for the translation
  • a locale-specific template which holds the actual translations

The main babelfish.xsl - choose the right language

The main babelfish template provides a switch which determines the locale-specific template to be called for the translation. It imports the locale-specific templates for translation. The <xsl:choose>...</xsl:choose>-block within the template uses an XSL-variable (here: $locale - as provided by the globals.xsl within the demo layout) to determine the right locale for the translation.

Below an examplary babelfish.xsl (as it can be found in the ".../i18n/..."-folders within the pulse demo layout):

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
    the main babelfish.xsl which chooses the right locale for translation       
    according to the request-locale 
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml" version="2.0">
    
    <!-- NOTE: at some point the current locale has to be provided -->
    <!--       as global XSL-variable $locale for choosing the     -->
    <!--       right language...                                   -->
    <!--       for the :pulse demo-templates this is being done    -->
    <!--       via the globals.xsl - as being imported below       -->

    <!-- imports -->
    <!-- globals.xsl: provides the current request-locale "$locale" -->
    <xsl:import href="[some path to the root-folder of the web-app]/WEB-INF/xsl/globals.xsl"/>

    <!-- includes -->
    <!-- the locale-specific translations -->
    <xsl:include href="babelfish.en.xsl"/>
    <xsl:include href="babelfish.de.xsl"/>
    <!-- include further locale-specific translations -->
    ...

    <!-- choose locale -->
    <xsl:template name="babelfish">

        <xsl:choose>
        
            <!-- locale: de, de_DE -->
            <xsl:when test="$locale='de' or $locale='de_DE'">
                <xsl:call-template name="babelfish.de"/>
            </xsl:when>
            
            <!-- further locales -->
            ...
            
            <!-- default locale -->
            <xsl:otherwise>
                <xsl:call-template name="babelfish.en"/>
            </xsl:otherwise>
            
        </xsl:choose>

    </xsl:template>

</xsl:stylesheet>

In the examplary babelfish.xsl above the xsl-import of the globals.xsl provides the global $locale XSL-variable while the xsl-includes provide the translation templates for the various locales.

The locale/language specific babelfish - the actual translations

The localisation babelfish templates provide the locale/language-specific translations template to be used within the layout-templates. It evealuates a given XSL-tunnel-parameter (here: $id, as defined at the start of the xsl:template) to determine the right translation.

!
We recommend strict alphabetical ordering by $id for the translations.

Below an examplary locale-specific (here: babelfish.en.xsl)  - as it can be found in the ".../i18n/..."-folders within the pulse demo layout:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
    this babelfish contains the english (default) translations 
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml" version="2.0">

    <xsl:template name="babelfish.en">

        <!-- the id-parameter which identifies the requested translation -->
        <xsl:param name="id" tunnel="yes"/>

	<!-- chosse the right translation according to id-parameter -->
        <xsl:choose>
        
            <!-- A -->
            <xsl:when test="$id='a.name.which.identifies.the.translation'">
                <xsl:text>The requested translation as identified by: '</xsl:text>
		<xsl:value-of select="$id"/>
                <xsl:text>'</xsl:text>
            </xsl:when>
            <!-- B -->
            <!-- C -->
            <!-- D -->
            <!-- E -->
            <!-- F -->
            <!-- G -->
            <!-- H -->
            <!-- I -->
            <!-- J -->
            <!-- K -->
            <!-- L -->
            <!-- M -->
            <!-- N -->
            <!-- O -->
            <!-- P -->
            <!-- Q -->
            <!-- R -->
            <!-- S -->
            <!-- T -->
            <!-- U -->
            <!-- V -->
            <!-- W -->
            <!-- X -->
            <!-- Y -->
            <!-- Z -->

            <!-- default: shows missing translation -->
            <xsl:otherwise>
                <strong>[missing.babelfish.en: !<xsl:value-of select="$id"/>!]</strong>
            </xsl:otherwise>
            
        </xsl:choose>

    </xsl:template>

</xsl:stylesheet>

Within the above template the <xsl:choose>...</xsl:choose>-block evaluates the given $id XSL-tunnel-parameter in order to determine the right translation. The xsl:otherwise will make sure that there will always be a default output for non-matching $ids - to ease template localisation.

Localising the templates - combine layout & translation

The below example shows how to make use of the babelfish concept within the layout XSL-templates. The call of the babelfish-template will include the right translation according to the parameter(s) passed along. This is being done throughout the templates of the demo layout.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml" version="2.0">

    <!-- imports -->
    <!-- imports the localisations -->
    <xsl:import href="i18n/babelfish.xsl"/>
    
    <!-- the current locale as global variable -->
    <!-- for choosing the language in the main babelfish.xsl -->
    <!-- (usually determined by request) -->
    <xsl:variable name="locale" select="'en'"/>    
    
    <!-- preferably the current locale will be provided by the result -->
    <!-- which is currently being transformed i.e: -->
    <!-- <xsl:variable name="locale" select="/result/current-locale/text()"/> -->

    <!-- some layout template which requires localisation -->
    <xsl:template match="...">
                        
        ...
        <!-- layout-specific stuff -->
        ...
	
        <!-- some paragraph -->
        <p>
        
            <!-- examplary babelfish-call: retrieve the localisation -->
            <xsl:call-template name="babelfish">
                <xsl:with-param name="id"  
                    select="'a.name.which.identifies.the.translation'" 
                    tunnel="yes"/>
            </xsl:call-template>

        </p>

        ...
        <!-- more layout specific stuff -->
        ...

    </xsl:template>

</xsl:stylesheet>

The examplary layout XSL-template imports the babelfish.xsl which provides the locale-specific translations. The examplary babelfish template-call in passes along the XSL-tunnel-parameter id which is being used to determine the translation.

In the example as described by the templates above this would result in the following HTML-output:

<p>The requested translation as identified by: 'a.name.which.identifies.the.translation'.</p>