I18N: tool for managing XSL variables in different languages?

  • Thread starter Sebastian Kerekes
  • Start date
S

Sebastian Kerekes

Greetings,

I'm developing an application that supports multiple languages. In my
XSL I use variables to place the text where it belongs to. At the top of
the document I include those variables - the included file depends on
the language.

Atm I'm editing those file manually. Luckily atm it's only two languages
I have to work with, but even in this case I forget to add a variable
that I added in the other file, forget to use entities .. and so on.

It would be fine to have a tool, that manages the variables, ensures
that I enter text for every defined language, and maybe even saves those
variables in a file for every language.

Do you know of some tool I could use for that?

Thx for you answers,

Sebastian
 
B

Berislav Lopac

Sebastian said:
Greetings,

I'm developing an application that supports multiple languages. In my
XSL I use variables to place the text where it belongs to. At the top
of the document I include those variables - the included file depends
on the language.

Atm I'm editing those file manually. Luckily atm it's only two
languages I have to work with, but even in this case I forget to add
a variable that I added in the other file, forget to use entities ..
and so on.

It would be fine to have a tool, that manages the variables, ensures
that I enter text for every defined language, and maybe even saves
those variables in a file for every language.

Do you know of some tool I could use for that?

Define all the variables in an external XSLT file and then include it. You
will need a separate file for each language; you include only the one you
need.

Berislav
 
S

Sebastian Kerekes

Berislav said:
Define all the variables in an external XSLT file and then include it. You
will need a separate file for each language; you include only the one you
need.

Berislav

Thx for your answer, but maybe I didn't make myself clear: I'm already
doing it as you suggested. What I'm looking for is a tool which can help
me editing these files and keep the consistency. Editing the files
manually for every language causes errors ..

Angus
 
M

Marrow

Hi,

Using variables and including them? That seems a long way to do things?

Show a short example of what you are doing - perhaps there's a better way of
achieving your goal. ;)

To your original question...
You could use XSLT itself to perform the checks to ensure that a word is
defined in each language.

Cheers
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator
 
G

Gerald Aichholzer

I'm developing an application that supports multiple languages. In my
XSL I use variables to place the text where it belongs to. At the top of
the document I include those variables - the included file depends on
the language.

Atm I'm editing those file manually. Luckily atm it's only two languages
I have to work with, but even in this case I forget to add a variable
that I added in the other file, forget to use entities .. and so on.

It would be fine to have a tool, that manages the variables, ensures
that I enter text for every defined language, and maybe even saves those
variables in a file for every language.

Do you know of some tool I could use for that?

Thx for you answers,

Hi Sebastian,

by accident I stumbled yesterday across the following site:
http://www-106.ibm.com/developerworks/xml/library/x-localis/

There they talk about XML Localisation Interchange File Format
(XLIFF). There's also a screenshot of an XLIFF-editor. Maybe
you could use this standard in your application.

HTH,
Gerald
 
S

Sebastian Kerekes

Marrow said:
Hi,

Using variables and including them? That seems a long way to do things?

Show a short example of what you are doing - perhaps there's a better way of
achieving your goal. ;)

Ok, here's a very simple and short example:

Somewhere at the top of the document i have my variables. The variables
need to have different content depending on the language I want to use.
So my XSL is a JSP file that gets a "language" parameter and includes
the file with the right language.

When the JSP finishes processing, the result is a XSL with for the
specific language passed with "language". For "en" the result is:


<xsl:variable name="text.greetings" select="'Username'" />
<b><xsl:value-of select="$text.greetings" /></b>

for "de" it's:

<xsl:variable name="text.greetings" select="'Benutzername'" />
<b><xsl:value-of select="$text.greetings" /></b>

and so on.

I found this approach in a book, and it seems ok to me, but if you have
any other (more common, more elegant) solutions, feel free to post them ;)
To your original question...
You could use XSLT itself to perform the checks to ensure that a word is
defined in each language.

Uuuhm .. how? How would you solve this?

Greetings, Sebastian
 
D

David Carlisle

for "de" it's:

<xsl:variable name="text.greetings" select="'Benutzername'" />
<b><xsl:value-of select="$text.greetings" /></b>

that means you have to modify the XSL for each language, and can't
easily be extended to support more than one language at a time (eg the
current language from an xml:lang attribute in the source file)

If instead your language config file was more like

<text name="greetings">
<x lang="en">Greetings</x>
<x lang="de">Benutzername</x>
</text>
....

then instead of going
<xsl:value-of select="$text.greetings" />
you'd go

<xsl:value-of select="$lang-config/text[@name='greetings']/x[@lang='de']" />

here you can eaily replace 'de' by for example
ancestor-or-self::*[@xml:lang][1]/@xml:lang
which gets the in scope xml:lang attribute, or have some xsl code to
provide a fall back or warning message if the language specific text is
absent.

David
 
M

Marrow

Hi Sebastian,

First off, there are a few features in XML and XSLT that can assist you with
localization, e.g...

In XML there is a pre-defined attribute of xml:lang which can contain
language (and optionally, national dialect) values. The useful thing about
utilising the xml:lang rather than defining your own 'lang' attribute is
that the xml:lang is decended down the tree for you until it is overridden.
In XSLT you have the lang() function - which can be used to query/test XML
based upon it's xml:lang attribute. The lang() function also gives you a
certain amount of fallback functionality (see below) and also is one of the
few parts of XML that is not case-sensitive.

So given those features there are several ways in which you can go about
providing a localization system for use in XSLT.

As an example...

Say you had a single vocabulary XML document that defined all of your
'tokenized' words, e.g. something like...

== Vocabulary.xml ===============================
<?xml version="1.0"?>
<vocab xml:lang="EN-GB"> <!-- this lang gives the default/fallback
language -->
<language name="English (GB)">
<token name="bin">Dustbin</token>
<token name="trousers">Trousers</token>
<token name="errtest">Something</token>
</language>
<language name="English (US)" xml:lang="en-us">
<token name="bin">Trash can</token>
<token name="trousers">Pants</token>
</language>
<language name="Deutsch" xml:lang="de">
<token name="bin">Mülleimer</token>
<token name="trousers">Hose</token>
</language>
</vocab>
== end of Vocabulary.xml ========================

using the lang() function in XSLT if you did used the XPath selection...
/vocab/language/token[@name = 'bin'][lang('en')]
it would give you the nodes...
<token name="bin">Dustbin</token>
<token name="bin">Trash can</token>
because both are defined under an element whose xml:lang is "en" (i.e.
"en-gb" and "en-us").
So if you do a more specific selection of...
/vocab/language/token[@name = 'bin'][lang('en-gb')]
this would give just the node...
<token name="bin">Dustbin</token>

So utilising that in XSLT could look something like...


== TestVocab.xsl ===============================
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="lang-select" select="'en'"/>

<xsl:eek:utput method="text"/>
<!-- get the vocabulary document -->
<xsl:variable name="vocab-doc" select="document('Vocabulary.xml')/*"/>
<!-- pick the token words from the vocab document according to the selected
language -->
<!-- also providing fallback when the selected language does not exist -->
<xsl:variable name="vocab"
select="$vocab-doc/language[lang($lang-select)]/token |

$vocab-doc/language[lang(/vocab/@default-lang)][not(/vocab/language[lang($la
ng-select)])][1]/token"/>

<xsl:template match="/">
<xsl:value-of select="$vocab[@name = 'bin']"/>
</xsl:template>
</xsl:stylesheet>
== end of TestVocab.xsl ========================

NB. Selecting the approriate tokens into the $vocab variable once saves you
keep specifying the language in later XPath expressions.

Also, some people like to keep each language in a seperate XML document - in
which case you could use system entities to accomplish this and still only
refer to one document() in your XSLT, e.g.

== Vocabulary.xml ===============================
<?xml version="1.0"?>
<!DOCTYPE includes [
<!ENTITY en-gb SYSTEM "VocabEN-GB.xml">
<!ENTITY en-us SYSTEM "VocabEN-US.xml">
<!ENTITY de SYSTEM "VocabDE.xml">
]>
<vocab xml:lang="EN-GB"> <!-- this lang gives the default/fallback
language -->
&en-gb;
&en-us;
&de;
</vocab>
== end of Vocabulary.xml ========================

and the the individual language XML documents...

== VocabEN-GB.xml ===============================
<language name="English (GB)" xml:lang="en-gb">
<token name="bin">Dustbin</token>
<token name="trousers">Trousers</token>
<token name="errtest">Something</token>
</language>
== end of VocabEN-GB.xml ========================

== VocabEN-US.xml ===============================
<language name="English (US)" xml:lang="en-us">
<token name="bin">Trash can</token>
<token name="trousers">Pants</token>
</language>
== end of VocabEN-US.xml ========================

== VocabDE.xml ===============================
<language name="Deutsch" xml:lang="de">
<token name="bin">Mülleimer</token>
<token name="trousers">Hose</token>
</language>
== end of VocabDE.xml ========================


Using such a system it would then be fairly 'easy' to write a stylesheet
that
checked the existence of each token in the languages, e.g.

== CheckVocab.xsl ===============================
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="html" indent="yes"/>

<xsl:variable name="vocab" select="/vocab/language[lang('invalid')]/token |

/vocab/language[lang(/vocab/@xml:lang)][not(/vocab/language[lang('invalid')]
)][1]/token"/>

<xsl:key name="kXMLLangAtts" match="@xml:lang" use="'x'"/>
<xsl:key name="kDistinctLanguages" match="@xml:lang"
use="translate(substring(.,1,2),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmn
opqrstuvwxyz')"/>
<xsl:key name="kDistinctLangDialect" match="@xml:lang"
use="translate(.,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')"
/>
<xsl:key name="kDistinctTokens" match="token" use="@name"/>
<xsl:variable name="ucase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="lcase" select="'abcdefghijklmnopqrstuvwxyz'"/>

<xsl:variable name="vDistinctLanguages"
select="key('kXMLLangAtts','x')[generate-id() =
generate-id(key('kDistinctLanguages',translate(substring(.,1,2),$ucase,$lcas
e)))]"/>
<xsl:variable name="vDistinctTokens"
select="/vocab/language/token[generate-id() =
generate-id(key('kDistinctTokens',@name))]"/>

<xsl:template match="/">
<html>
<head>
<title>
<xsl:text>My Vocabulary Checks</xsl:text>
</title>
</head>
<body>
<h2>
<xsl:text>Vocabulary Checks</xsl:text>
</h2>
<hr/>
<table border="1">
<tr>
<th rowspan="2" align="center" valign="bottom">
<xsl:text>Token</xsl:text>
</th>
<th rowspan="2" align="center" valign="bottom">
<xsl:text>Default</xsl:text>
<br/>
<xsl:text>Value</xsl:text>
</th>
<xsl:for-each select="$vDistinctLanguages">
<xsl:variable name="this-lang"
select="translate(substring(.,1,2),$ucase,$lcase)"/>
<xsl:variable name="no-dialects"
select="count(key('kDistinctLanguages',$this-lang)[contains(.,'-')][generate
-id() =
generate-id(key('kDistinctLangDialect',translate(.,$ucase,$lcase)))])+1"/>
<th align="center" colspan="{$no-dialects}">
<xsl:text>Language: </xsl:text>
<xsl:value-of select="$this-lang"/>
</th>
</xsl:for-each>
</tr>
<tr>
<xsl:for-each select="$vDistinctLanguages">
<xsl:variable name="this-lang"
select="translate(substring(.,1,2),$ucase,$lcase)"/>
<th>
<xsl:value-of select="$this-lang"/>
</th>
<xsl:variable name="dialects"
select="key('kDistinctLanguages',$this-lang)[contains(.,'-')][generate-id()
= generate-id(key('kDistinctLangDialect',translate(.,$ucase,$lcase)))]"/>
<xsl:for-each select="$dialects">
<th>
<xsl:value-of select="translate(.,$ucase,$lcase)"/>
</th>
</xsl:for-each>
</xsl:for-each>
</tr>
<xsl:for-each select="$vDistinctTokens">
<xsl:sort/>
<tr>
<th align="left">
<xsl:value-of select="@name"/>
</th>
<td>
<xsl:value-of select="$vocab[@name = current()/@name]"/>
</td>
<xsl:variable name="this-name" select="@name"/>
<xsl:for-each select="$vDistinctLanguages">
<xsl:variable name="this-lang"
select="translate(substring(.,1,2),$ucase,$lcase)"/>
<xsl:variable name="dialects"
select="key('kDistinctLanguages',$this-lang)[contains(.,'-')][generate-id()
= generate-id(key('kDistinctLangDialect',translate(.,$ucase,$lcase)))]"/>
<td>
<xsl:variable name="this-token"
select="/vocab/language[lang($this-lang)]/token[@name = $this-name]"/>
<xsl:choose>
<xsl:when test="$this-token">
<xsl:value-of select="$this-token"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:attribute name="bgcolor">
<xsl:text>Red</xsl:text>
</xsl:attribute>
<xsl:text>(undefined)</xsl:text>
</xsl:eek:therwise>
</xsl:choose>
</td>
<xsl:for-each select="$dialects">
<td>
<xsl:variable name="this-token"
select="/vocab/language[lang(current())]/token[@name = $this-name]"/>
<xsl:choose>
<xsl:when test="$this-token">
<xsl:value-of select="$this-token"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:attribute name="bgcolor">
<xsl:text>Red</xsl:text>
</xsl:attribute>
<xsl:text>(undefined)</xsl:text>
</xsl:eek:therwise>
</xsl:choose>
</td>
</xsl:for-each>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
== end of CheckVocab.xsl ========================


HTH
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top