Say we are writing an SVG UI, and we want to display the score. So we create some SVG boxes, and label them with:
<text x="0" y="0" id="score">0</text> <text x="0" y="10">Victory Points</text>
The first of these is fine; digits are readable by everybody. (We give the element an id so that your UI script code can change the text as the score changes.)
The second is not so great -- it's hardwired to English. We would like to set up the UI so that it can easily be extended for other languages.
To do this, make sure you have a locale
directory in your UI package. This directory should have a subdirectory for each language you want to support: locale/en
for English, locale/de
for German, and so on. You can add these one at a time. For now, we'll start with English.
Create a file locale/en/message.def
.
(In fact, this can have any name, as long as it's inside the locale/en
directory. We will use message.def
throughout this example.)
This file can contain any number of XML entity definitions. A definition would look like this:
<!ENTITY vpoints "Victory Points">
You should create one message.def
file for each language you want to support. They must all define the same entities. The German one, then, would look like:
<!ENTITY vpoints "Siegpunkt">
In order to use these entities, your SVG file must undertake the proper ritual. That is to say, it must have define and invoke a magic URL in its DOCTYPE header.
We shall not go into the arcanities of how the ritual works. Just copy this:
<?xml version="1.0"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ <!ENTITY % localedef SYSTEM "vollocp://locale/message.def?en,de#lang"> %localedef; %lang; ]>
The two magical lines go inside square brackets at the end of the <!DOCTYPE>
tag.
Ok, we'll go into some arcanities. You shall recognize the message.def
part of the header; this is the name shared by the files you created in each locale
subdirectory.
The ?en,de
part is the list of languages you support. This list must match the list of locale
subdirectories which contain message.def
files. In this case, we're declaring that locale/en/message.def
and locale/de/message.def
exist.
(By the way, the order of languages in your list is significant. If a player's client is set to some language you have not defined, it will default to the first language on your list.)
Now that your files are in place and your header is set up, you can use the entities you've defined.
<text x="0" y="0" id="score">0</text> <text x="0" y="10">&vpoints;</text>
The &vpoints; entity works just like the HTML entities you're familiar with -- & and so on. When it appears in the SVG file, its equivalent text is substituted automatically. But because of the magic header, the client substitutes the text according to the player's language preference. If the player has set his Volity client to English, he'll see "Victory Points". If he's chosen German, he'll see "Siegpunkt" instead.
(If he's chosen any other language, he'll get "Victory Points". You've only defined two languages, and any other preference defaults to the first language on your list: English.)
Create a new message.def
file -- say, locale/fr/message.def
.
Add the language code to the header line:
<!ENTITY % localedef SYSTEM "vollocp://locale/message.def?en,de,fr#lang">
Presto, you have added support for a new language.
Instead of defining XML entities, you can translate an entire SVG file, and then use this system to load SVG elements from it.
You do not translate the main.svg
file. Instead, create a secondary file in locale/en
-- say, locale/en/objects.svg
.
Define appropriate elements in this file:
<text x="0" y="10" id="scorelabel">Victory Points</text>
Then, for each other language you wish to support, create an appropriate translation. In locale/de/objects.svg
, you would have:
<text x="0" y="10" id="scorelabel">Siegpunkt</text>
...and so on. Again, each of these files must contain the same elements.
Once again, your main.svg
UI file must contain the magic header. However, the various objects.svg
files must not contain the magic header lines. Trust me on this.
Your main.svg
can then import elements from the appropriate objects.svg
, by doing this:
<use xlink:href="locale/⟨/objects.svg#scorelabel" />
This works because the ⟨ entity is defined to be the appropriate string -- en
, de
, etc -- according to the player's language preference.
(Again, if he has chosen a language you do not support, he'll get the first language on your list. This is why it's critical that the ?en,de
part of the header list the languages that you actually support. If you leave one out, the player won't be able to see it, even if you have a locale
subdirectory set up.)