[UP]
Reference
|
|
|
Internationalization
Internationalization (I18N) is the ability to support several languages,
character encodings, and local notation conventions. Currently,
WDialog has some support for that, but I18N is not yet done.
In particular, the following features already work:
UTF-8 support: It is possible to represent
all character data as UTF-8 strings. By default, character data are
encoded as ISO-8859-1 (Latin-1) strings. UTF-8 does not only support
many languages, but also special characters such as mathematical
symbols. In order to switch from ISO-8859-1 to UTF-8, pass the
~charset:`Enc_utf8 argument to the Wd_run_cgi.run
function (or Wd_run_jserv.run). The consequence is that all strings are now UTF-8 strings,
and that the generated HTML output is UTF-8, too. The XML file(s) that contain the UI definition can be
encoded differently, however. These files begin with
<?xml version='1.0' encoding='ENC'?> where ENC
is the name of a character encoding, for example ISO-8859-1, or
UTF-8. Many other encodings of the ISO-8859 series are possible,
too. The characters read from these files are automatically recoded
to the character set demanded by the charset option. This
means that your text editor need not to support UTF-8. As alternative to the direct inclusion of characters,
the notation &#n; (where n is a decimal
number) can be used to denote the character number n in the input
text (the Unicode character set is assumed). For the default ISO-8859-1
encoding the number n must be less than 256, but for UTF-8 all valid
Unicode character codes are allowed. The 'language' variable: Every dialog object
may contain a language variable that selects the language
of the user interface. The name of this variable must be
declared in the ui:dialog element, for example:
<ui:dialog name="foo" lang-variable="current-language">
...
<ui:variable name="current-language">
<ui:string-value>en</ui:string-value>
</ui:variable>
...
</ui:dialog>
Here, the variable is initialized with the string "en".
It is recommended to store two-letter ISO language codes
as abbreviations for the meant languages into the variable.
The language variable can be used as any other variable,
but there are some statements that access the variable
automatically. Read on for more.Language conditions: The
ui:iflang element can be used to
expand text only if the language variable has a certain
value. An application are message catalogs like:
<ui:cond>
<ui:iflang xml:lang="en">
This is English.
</ui:iflang>
<ui:iflang xml:lang="de">
Dies ist Deutsch.
</ui:iflang>
</ui:cond>
Of course, the ui:iflang conditions are evaluated
sequentially, and such "catalogs" should only be used if the
number of languages is small. Nevertheless, this construct
seems to be reasonable, and there is even an abbreviation
to avoid notation overhead:
<ui:cond>
<l:en>
This is English.
</l:en>
<l:de>
Dies ist Deutsch.
</l:de>
</ui:cond>
This means exactly the same as the example above.
Language-sensitive templates: Another way to
select UI code depending on the language are templates
that are defined differently for different languages. For instance:
<ui:template name="salutation" xml:lang="en" from-caller="user title">
Good morning, $title $user!
</ui:template>
<ui:template name="salutation" xml:lang="de" from-caller="user title">
Guten Morgen, $title $user!
</ui:template>
If you invoke the template, one of the definitions is
selected depending on the current state of the language
variable. You can also define a "fallback" version without
xml:lang attribute, it is used when no special
version for the template is defined.In reality, the above templates have the full names
salutation#en and salutation#de, i.e.
the language code is appended to the name after the
hash mark. Because of this, the language code is sometimes
also called language suffix. Of course, you can call
the template by its full name, and bypass the automatic
selection rules, e.g.
<ui:use template="salutation#de">.
And these features would be nice to have, but are not yet
available: More character sets: Currently, only
ISO-8859-1 and UTF-8 are possible. Other character sets
should be supported, too. Localized enumerations: It is not possible
to define enumerations differently depending on the
selected language.
Accepted languages: There should be a
library function to determine the languages accepted/preferred
by the browser.
What is really missing is a good example. I have not yet
enough experience to say whether we need more features or not. Last but not least some interesting code snippets. There
are already some tricks that I should mention, as they
simplify localization a lot. Localized attributes: Imagine you want to have
a button with localized labels. The string for the label
is passed as XML attribute, and the question is: how to
select attributes in a language-dependent way? The straight-forward solution simply repeats the button:
<ui:cond>
<l:en>
<ui:button name="foo" label="Press here"/>
</l:en>
<l:de>
<ui:button name="foo" label="Hier drücken"/>
</l:de>
</ui:cond>
The drawback is that you must repeat the whole button
element although only one attribute is different. Is
there a better solution?The idea is to define a template for the button, and to pass
different labels. There are several possibilities: (1)
<ui:template name="button_foo" from-caller="$label">
<ui:button name="foo" label="$label"/>
</ui:template>
...
<ui:cond>
<l:en>
<t:button_foo label="Press here"/>
</l:en>
<l:de>
<t:button_foo label="Hier drücken"/>
</l:de>
</ui:cond>
(2)
<ui:template name="button_foo" from-caller="$label">
<ui:button name="foo" label="$label"/>
</ui:template>
...
<t:button_foo>
<p:label
><ui:cond
><l:en>Press Here</l:en><l:de>Hier drücken</l:de></ui:cond></p:label>
</t:button_foo>
(3)
<ui:template name="button_foo" from-caller="$label">
<ui:default param="label"
><ui:cond
><l:en>Press Here</l:en><l:de>Hier drücken</l:de><ui:cond></ui:default>
<ui:button name="foo" label="$label"/>
</ui:template>
...
<t:button_foo/>
Unfortunately, these tricks work only for template invocations,
so we must define button_foo and cannot do the same with
ui:button directly.
Using enumerations for localization: If the
string to localize is constant, an alternative for
condition testing may be an enumeration. Continuing the
last example, another solution is:
<ui:template name="button_foo" from-caller="$label">
<ui:button name="foo" label="$label"/>
</ui:template>
...
<ui:enumeration name="label_for_foo">
<ui:enum internal="en" external="Press here"/>
<ui:enum internal="de" external="Hier drücken"/>
</ui:enumeration>
...
<t:button_foo>
<p:label
><ui:translate type="label_for_foo"
internal="$[language()]"/></p:label>
</t:button_foo>
Here, $[language()] expands to the current language
code, and the ui:translate element
finds the corresponding external string for this code.
With enumerations it is even possible to avoid the extra
template definition completely:
<ui:enumeration name="label_for_foo">
<ui:enum internal="en" external="Press here"/>
<ui:enum internal="de" external="Hier drücken"/>
</ui:enumeration>
...
<ui:button name="foo" label="$[translate(enum(label_for_foo),language())]"/>
The enum expression is a special form that returns
the declaration of the named enumeration. The translate
function does the same as ui:translate, but can be used
in a bracket expression.
|