Difference between revisions of "Internationalization"

From The DarkMod Wiki
Jump to navigationJump to search
(use template)
(update)
Line 11: Line 11:
Changing the language will change the language of the HUD, as well as the inventory immidiately. It can also be done during a mission.  
Changing the language will change the language of the HUD, as well as the inventory immidiately. It can also be done during a mission.  


{{infobox|'''Note:''' Not all FMs are yet multi-lingual, and for these certain inventory items, the objectives, or readables might appear in English.}}
 
{{infobox|'''Note:''' Not all FMs are yet multi-lingual, and for these certain inventory items, the objectives, or readables might appear in English.<br> See the '''[[I18N Status|list of already internationalized FMs]]''' and their status.}}




Line 97: Line 98:


The main translation object is of the class CI18N (which is short for "Class Internationalization") and lives in ''Darkmod/I18N.cpp'' and ''Darkmod/I18N.h''.
The main translation object is of the class CI18N (which is short for "Class Internationalization") and lives in ''Darkmod/I18N.cpp'' and ''Darkmod/I18N.h''.
=== GUI ===
To work around the '''choiceDef''' bug, two new main menu commands have been added, called "initChoice" and "stepChoice". These two take 3 arguments each:
# the CVAR name
# the labels for each choice ('''should be''' in the form '#str_01234" to make it translatable)
# the values for each choice (usually a hard-coded list like '0;1')
In addition to these, a few GUI #defines where added that make it easier to add a new choice def. Here is how it looked before:
<pre>
choiceDef PostProcessing
{
    rect            SETTINGS_X_OFFSET, 54, 80, 14
    choices        "#str_07300" // disabled, enabled
    values          "1;0"
    cvar            "r_postprocess"
    choiceType      0
    font            SETTINGS_FONT
    textscale      SETTINGS_FONT_SCALE_CHOICE
    textalign      1
    textaligny      0
    forecolor      SETTINGS_FONT_COLOUR
    onAction
    {
        set "cmd" "play sound/meta/menu/mnu_select" ;
        resetTime "UpdateBloomSliderVisibility" 0;
    }
}
</pre>
And here is how it has to look now:
<pre>
windowDef PostProcessing
{
    rect            SETTINGS_X_OFFSET, 54, 80, 14
    text            "gui::r_postprocess_text"
    CHOICE_INIT    "initChoice 'r_postprocess' '#str_07300' '1;0'" }
    CHOICE_STEP    "stepChoice 'r_postprocess' '#str_07300' '1;0'"; resetTime "UpdateBloomSliderVisibility" 0; }
}
</pre>
'''Notes:'''
* use '''windowDef''', not '''choiceDef''', or the GUI will crash upon load.
* the text variable has to be in the format "gui::cvarname_text" (e.g. the CVAR with "_text" appended)
* The lines for "CHOICE_INIT" and "CHOICE_STEP" '''must''' end with a "}".
* The secondary action in CHOICE_STEP (resetTime in the example above) is optional.


== Known bugs ==
== Known bugs ==


Sadly, there are quite a lot of limitations in the D3 SDK that prevent a few things from fully working. Once D3 goes open source, these things will be fixed, in the meantime we hope that you can live with the quirks.
Sadly, there are quite a lot of limitations in the D3 SDK that prevent a few things from fully working. Once D3 goes open source, these things will be fixed, in the meantime we hope that you can live with the quirks:


{{red|TODO}}
* Doom3 does not support the character 0xFF in fonts rendered, but this character is used f.i. in Russian. To work around this, the character 0xFF is moved to 0xB& during loading of dictionaries. The russion font then simply contains a character 0xB6 with the proper image in place.
* choiceDefs do not properly display choices with high-bit characters. There exist two new menu commands and a few #defines to work around this, see the [[#GUI|GUI section]] above.


{{i18n}} {{editing}} {{sdk}}
{{i18n}} {{editing}} {{sdk}}

Revision as of 14:21, 24 September 2011

This article deals with the localisation/translation of both TDM itself, as well as Fan Missions.

The I18N support in TDM will only work with v1.07 or newer.

For Users

You can switch the language of TDM in the Settings menu under Video, General. The language is stored in the CVAR tdm_lang. Ignore sys_lang.

Switching the language does not require a newstart, except for some languages like Russian. There the game will inform you that you need to restart it manually, or the display will not look correct.

Changing the language will change the language of the HUD, as well as the inventory immidiately. It can also be done during a mission.


Note: Not all FMs are yet multi-lingual, and for these certain inventory items, the objectives, or readables might appear in English.
See the list of already internationalized FMs and their status.


For Mappers

As a mapper, you want to reach an audience as wide as possible with your FM. One way is to provide alternative language versions of your map. There are two ways that can be achieved:

  1. You can ignore the issue, and hope that somebody else modifies your FM and provides a translation. The past shows that the changes that someone does this are slim, tho. Only a handful of FMs were every translated, most of them only into one other languages. That is because modifying and translating an FM are quite a lot of work, and translators would rather just translate things than to muck around with your PK4 file.
  2. You can (from v1.07 on) build in support for translation from the beginning, and make the work for translators easier.

The second point can achieved in two ways:

  1. You build the FM with hard-coded strings like 'Silver Key', and then use I18N.pl to transform the FM into a package that can have external dictionaries. That might be easier to work with in DR (as DR itself has no support for dictionaries yet), but the script might not be 100% correct and you need to manually help it out.
  2. You build your FM with string templates like "#str_12345" instead of hard-coded names, and supply an external dictionary with these strings.

FM specific dictionaries

These dictionaries live in the directory strings/fm/ and must follow a specific format, explained below. The name for such a dictionary is always LANGUAGE.lang, f.i. "english.lang".

The string IDs for FMs are 20000 .. 89999, using these ensures that they do not conflict with strings from the TDM core. Note that if you have a string that matches one of the other core strings (like "Silver Key", "#str_10000"), then you should use just the core string ID. This saves the translators to translate the string again.

You MUST also separate them from the rest of your FM into their own package called "YOURFM_i18n.pk4" where YOURFM is the name of your original PK4 file. This ensures that TDM can install/update the I18N package properly.

Let's see how this looks for the FM named Outpost, which provides two translations (English and French):

 outpost.pk4:

  xdata/outpost.xd
  maps/outpost.map
  maps/outpost.cm
  maps/outpost.proc
  maps/outpost.script
  maps/outpost.aas32

 outpost_i18n.pk4:

  strings/fm/english.lang
  strings/fm/french.lang

Note that all files names should be in lowercase, otherwise there can be problems under Linux.

Example dictionary, note the entire content is wrapped in "{ }"

// String table english (iso-8859-1) for: The Outpost

// This file was generated automatically on 2011-08-20 13:56 UTC by i18n.pl v0.02
{
  "#str_20000"  "The Outpost"
  "#str_20001"  "Break into a builder outpost to retrieve a gold ingot."
  "#str_20002"  "Gold Ingot"
  "#str_20003"  "Leave the outpost after your main objectives are done and get back to the front gates."
  "#str_20004"  "You won't find bags full of money in a builder outpost, but take away any valuables you can get hold of. Find valuables worth at least 600."
  "#str_20005"  "You won't find bags full of money in a builder outpost, but take away any valuables you can get hold of. Find valuables worth at least 700."
  "#str_20006"  "No knock outs too."
  "#str_20007"  "Killing is not your style. No corpses tonight."
  "#str_20008"  "You won't find bags full of money in a builder outpost, but take away any valuables you can get hold of. Find valuables worth at least 800."
  "#str_20009"  "The massive gold ingot should be worth a fair amount of money. Find out where the ingot is kept and change its ownership."
}

This setup makes it easier to translate the FM, because an translator needs only to copy english.lang to german.lang, change the strings, repackage the outpost_i18n.pk4 file, and it works!


Inventory Item Names with multiple lines

If you have an inventor item name which is very long, you can insert \n to split it up into two (but not more!) lines:

"#str_20000" "This is a very very\nlong item name."

You should try in the game tosee how it looks, so that both lines are roughly the same length.


For Developers

CVAR tdm_lang

The D3 CVAR sys_lang is restricted to a few hard-coded values, and is thus not usable. We have added a new CVAR tdm_lang, which contains the current language as English lower-case string, e.g. "english", "german", "portuguese" etc. This variable is controlled by the GUI via a call back into the SDK code, which switches the language underneath, and also reloads the GUI.

If you change the CVAR manually (via the console f.i.), you need to restart TDM so it works!

Code

The main translation object is of the class CI18N (which is short for "Class Internationalization") and lives in Darkmod/I18N.cpp and Darkmod/I18N.h.

GUI

To work around the choiceDef bug, two new main menu commands have been added, called "initChoice" and "stepChoice". These two take 3 arguments each:

  1. the CVAR name
  2. the labels for each choice (should be in the form '#str_01234" to make it translatable)
  3. the values for each choice (usually a hard-coded list like '0;1')

In addition to these, a few GUI #defines where added that make it easier to add a new choice def. Here is how it looked before:

choiceDef PostProcessing
{
    rect            SETTINGS_X_OFFSET, 54, 80, 14
    choices         "#str_07300" // disabled, enabled
    values          "1;0"
    cvar            "r_postprocess"
    choiceType      0
    font            SETTINGS_FONT
    textscale       SETTINGS_FONT_SCALE_CHOICE
    textalign       1
    textaligny      0
    forecolor       SETTINGS_FONT_COLOUR

    onAction
    {
        set "cmd" "play sound/meta/menu/mnu_select" ;
        resetTime "UpdateBloomSliderVisibility" 0;
    }
}

And here is how it has to look now:

windowDef PostProcessing
{
    rect            SETTINGS_X_OFFSET, 54, 80, 14
    text            "gui::r_postprocess_text"
    CHOICE_INIT     "initChoice 'r_postprocess' '#str_07300' '1;0'" }
    CHOICE_STEP     "stepChoice 'r_postprocess' '#str_07300' '1;0'"; resetTime "UpdateBloomSliderVisibility" 0; }
}

Notes:

  • use windowDef, not choiceDef, or the GUI will crash upon load.
  • the text variable has to be in the format "gui::cvarname_text" (e.g. the CVAR with "_text" appended)
  • The lines for "CHOICE_INIT" and "CHOICE_STEP" must end with a "}".
  • The secondary action in CHOICE_STEP (resetTime in the example above) is optional.


Known bugs

Sadly, there are quite a lot of limitations in the D3 SDK that prevent a few things from fully working. Once D3 goes open source, these things will be fixed, in the meantime we hope that you can live with the quirks:

  • Doom3 does not support the character 0xFF in fonts rendered, but this character is used f.i. in Russian. To work around this, the character 0xFF is moved to 0xB& during loading of dictionaries. The russion font then simply contains a character 0xB6 with the proper image in place.
  • choiceDefs do not properly display choices with high-bit characters. There exist two new menu commands and a few #defines to work around this, see the GUI section above.


See Also

Translation resources

Overview of translations

Translation discussions