One important issue was intentionally not covered in the "Template Design" document: the usage of different texts, labels or phrases chosen according to the languages understood by users of an application. The XSLForms toolkit provides two mechanisms for the use of translations and translated phrases:
template:i18n
attribute, as described in the "Template Attribute Reference" document.template:i18n
extension function, as described in the extension function API documentation.Each
of the above mechanisms has its own specific purpose in template
documents, and these purposes are described below, along with the
necessary procedures for initialising and invoking the translation
mechanisms in an XSLForms application.
Consider the following document fragment:
<h1>System Configurator</h1>
In order to translate this to a different language, according to that preferred by the user, we must annotate the element containing the text as follows:
<h1 template:i18n="-">System Configurator</h1>
Here, we state that the contents on the h1
element (the exact text System Configurator
)
will be used to find a suitable translation in a translation dictionary
(as described below). The anticipated result of applying the annotation
would resemble the following output document fragment:
<h1>Systemkonfigurasjon</h1>
Consequently, a translation has been inserted in place of the original text. In cases where no translation could be found, the original contents of the element would be preserved.
It is also possible to employ a specific translation as opposed to the text which just happen to reside inside an element; for example:
<h1 template:i18n="sysconfig">System Configurator</h1>
Here, instead of taking the exact text System Configurator
as the "token" to be used to find a translation, we instead use the token with the name sysconfig
. The effect, providing that the translation of sysconfig
is Systemkonfigurasjon
, would be the same as the result given above.
See the template:i18n
section of the "Template Attribute Reference" document for details of this annotation.
Consider the following document fragment:
<input type="submit" name="update" value="Update!"/>
In order to translate the label of this particular form control to another language, we must modify the value
attribute as follows:
<input type="submit" name="update" value="{template:i18n('Update!')}"/>
Here,
we insert an expression inside the attribute whose result will be
inserted in place of the expression. Note that for non-template
attributes, the expression must reside between {
and }
characters for the evaluation to take place. The anticipated result might resemble something like the following:
<input type="submit" name="update" value="Oppdatér"/>
Where no suitable translation can be found for the text passed to the function, the submitted text is returned as a result, producing something resembling the original, non-translated document fragment.
See the template:i18n
extension function description in the extension function API documentation for more details.
To permit the translation of text to occur, we must first prepare the translations themselves; then, we must change our application to make use of the translations.
Translations
are typically stored in an XML file alongside other resources such as
templates and documents containing data which are also used to prepare
the final user-viewable output from an application. For example, one
can define a file with the name translations.xml
and then insert the following contents into it:
<?xml version="1.0" encoding="iso-8859-1"?>
<translations>
<locale>
<code value="en_GB"/>
<code value="en"/>
</locale>
<locale>
<code value="nb_NO"/>
<code value="nb"/>
<translation value="System Configurator">Systemkonfigurasjon</translation>
<translation value="Update!">Oppdatér!</translation>
<translation value="Export!">Eksportér!</translation>
</locale>
</translations>
The structure of any such translations file must resemble the above:
translations
element containing...locale
sections, each containing...code
elements identifying the locale, together with...translation
elements, each providing a translation for each token.In the above example, the locale for en
and en_GB
have no translations defined; as a result, for any requests for translations in this locale the
text already found in the document will be preserved, and this
behaviour is therefore equivalent to requests for translations
in locales which are not defined or mentioned in the above
document.
Conversely, in the above example, the locale for en
and en_GB
has some translations defined; as a result, requests for translations
in this locale will result in the specified translations being
returned, provided the token is defined in a value
attribute of a translation
element; otherwise, the text already found in the document will be preserved.
To make use of such a translation file, the file must first be registered in an application. As described in the "Creating Applications: Write a Web Resource" and "Using the XSLFormsResource API" documents, we may add the above example to a resource in the document_resources
attribute:
document_resources = {
"translations" : "translations.xml"
# Other resources are defined here.
}
When producing output for a template which uses internationalisation features, we must first obtain a reference to the above document:
# In the respond_to_form method of an XSLFormsResource...
translations_xml = self.prepare_document("translations")
Then, we must decide which language or locale the output will employ. One way of making that decision is to use the WebStack API to find out which languages a user's Web browser is configured to receive:
# In the respond_to_form method of an XSLFormsResource...
languages = trans.get_content_languages()
# Get the first one...
try:
language = languages[0]
except IndexError:
language = "" # Or choose an acceptable default.
Finally,
with the above information in hand, we may now modify the output
production by adding a document reference (thus permitting the output
stylesheet to access the translations document) and by specifying the
chosen locale with the locale
stylesheet parameter:
# Use the transaction, output stylesheet, form data document, stylesheet parameters
# as well as the document reference.
self.send_output(trans, [output_xsl], doc, {"locale" : language},
references={"translations" : translations_xml})
This
should produce an output document which uses the registered
translations as much as is possible for the selected language.
Obviously, a more complicated approach could be used to choose the most
appropriate language in the languages
list, but such algorithms are not covered here.