PDA

View Full Version : [Tutorial] Translation engine



IzNoGoD
20th October 2014, 08:41
This post will (hopefully) cover everything you need to get my translation engine working (Note: this thing does NOT do the actual translation, which still has to be done by hand).

First off, you have to register the languages so the system can actually look for them:



add_language("EN");
add_language("HU");
add_language("CZ");
add_language("DE");
add_language("HR");

This will result in a warning if the language loaded has already been loaded (on a previous map for example), which you can ignore (will be displayed in serverconsole)

After this, you'll need to load the language-files:


load_languages(getcvar("fs_homepath") + "/" + getcvar("fs_game") + "/translations/JH_b3.txt", 1);
load_languages(getcvar("fs_homepath") + "/" + getcvar("fs_game") + "/translations/JH_lang.txt", 1);
load_languages(getcvar("fs_homepath") + "/" + getcvar("fs_game") + "/translations/JH_update_1.txt", 1);


Note the , 1 in there, which forces a reload. I haven't exactly pinpointed why not-forcing causes issues and as it works by forcing, I never might.
Furthermore note that, contrary to the localization files, the filename in which a "localized" string is found does in no way influence the localized string name (aka JH_b3.txt does not result in all strings in there being referenced by using JH_b3_somestringname)

The actual language files are closely related to the CoD2 localization files in terms of syntax, here is a small example from my jumpmod:


REFERENCE b3_language_changed
LANG_EN "Language changed to: %s"
LANG_DE "Sprache ge?ndert auf: %s"
LANG_HU "A nyelv megvaltozott erre: %s"
LANG_CZ "Jazyk zmenen na: %s"
LANG_HR "Jezik promjenjen u %s"

REFERENCE b3_help_language_1
LANG_EN "Change the global language of the mod"
LANG_DE "Wechsel die Mod-Sprache"
LANG_HU "Megvaltoztatja a teljes mod nyelvezetet"
LANG_CZ "Zmenit globalni jazyk"
LANG_HR "Mjenja jezik servera"

REFERENCE b3_language_list
LANG_EN "Available languages:"
LANG_DE "Verf?gbare Sprachen:"
LANG_HU "Elerheto nyelvek:"
LANG_CZ "Dostupne jazyky:"
LANG_HR "Dostupni jezici:"


As visible, the actual items support printf-like syntaxis (due to my sprintf addition to libcod :) ).

Actual code calling these translations:


self locprintln("b3_language_changed", data[2]);


The helper functions I use are:



locprintln(item, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10)
{
if(!isdefined(self) || (isplayer(self) && !isdefined(self.izno)))
return;
if(!isplayer(self))
{
players = getentarray("player", "classname");
for(i = 0; i < players.size; i++)
{
if(isdefined(players[i].izno["login_completed"]))
players[i] thread locprintln(item, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10);
}
}
else
{
lang = self.izno["language"];
if(!isdefined(lang))
lang = level.languages[0];
//printf("getting item %s for lang %s\n", item, lang);
str = get_language_item(lang, item);
str = sprintf(str, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10);
self iprintln(str);
}
}

locprintlnbold(item, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10)
{
if(!isdefined(self) || (isplayer(self) && !isdefined(self.izno)))
return;
if(!isplayer(self))
{
players = getentarray("player", "classname");
for(i = 0; i < players.size; i++)
{
if(isdefined(players[i].izno["login_completed"]))
players[i] thread locprintlnbold(item, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10);
}
}
else
{
lang = self.izno["language"];
if(!isdefined(lang))
lang = level.languages[0];
//printf("getting item %s for lang %s\n", item, lang);
str = get_language_item(lang, item);
str = sprintf(str, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10);
self iprintlnbold(str);
}
}

Which allow for level locprintln("some_reference"), player locprintln("some_reference") etc.


Appendix:

Please note that the system does NOT default to english when a translation is unavailable but instead defaults to the first language found in the file, example:


add_language("EN");
add_language("HU");
add_language("CZ");
add_language("DE");

with language file:


REFERENCE b3_language_list
LANG_HU "Elerheto nyelvek:"
LANG_CZ "Dostupne jazyky:"
LANG_EN "Available languages:"

will result in "Elerheto nyelvek" when trying to obtain the german translation ("DE").

Ni3ls
20th October 2014, 09:23
But where are these files located? I have installed libcod, but i dont have the files
JH_b3.txt
JH_lang.txt
JH_update_1.txt

IzNoGoD
20th October 2014, 09:43
But where are these files located? I have installed libcod, but i dont have the files
JH_b3.txt
JH_lang.txt
JH_update_1.txt

These are actually files you have to create yourself, they are named JH_b3 etc in my mod (JumpersHeaven B3 translations), an contain the reference/values for the languages you want

Ni3ls
20th October 2014, 10:14
I still dont really get it. For example I want to have English and Dutch in my mod.
ENG- Welcome to this server
NL- Welkom in deze server
ENG- Have fun!
NL- Veel plezier!

How should I set up that language.txt file? And how to load the translations properly based on the language you have chosen?

IzNoGoD
20th October 2014, 11:02
Language file would look like this:


REFERENCE mod_welcome
LANG_EN "Welcome to this server"
LANG_NL "Welkom in deze server"

REFERENCE mod_have_fun
LANG_EN "Have fun!"
LANG_NL "Veel plezier!"

and can be saved as any filename with any extension, just make sure to call load_languages(filename, 1) on that file.

The part which actually decides which one of these to show is in the helper functions posted in first post. To reiterate, here is locprintln:


locprintln(item, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10)
{
if(!isdefined(self) || (isplayer(self) && !isdefined(self.izno)))
return;
if(!isplayer(self))
{
players = getentarray("player", "classname");
for(i = 0; i < players.size; i++)
{
if(isdefined(players[i].izno["login_completed"]))
players[i] thread locprintln(item, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10);
}
}
else
{
lang = self.izno["language"];
if(!isdefined(lang))
lang = level.languages[0];
//printf("getting item %s for lang %s\n", item, lang);
str = get_language_item(lang, item);
str = sprintf(str, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10);
self iprintln(str);
}
}
As you can see, it uses level.languages as an array of available languages and check self.izno["login_completed"] before showing a global iprintln (called by level locprintln()). The language a player sees is defined by player.izno["language"], you might want to change these variables.

To show something like this on your server, you'd need something like:



init()
{
add_language("EN");
add_language("NL");
level.languages = [];
level.languages[0] = "EN";
level.languages[1] = "NL";
load_language(path_to_the_saved_language_file, 1);
}

onconnect()
{
self.izno = [];
self.izno["login_completed"] = true;
self.izno["language"] = "NL";
self locprintlnbold("mod_welcome");
self locprintlnbold("mod_have_fun");
}

Ni3ls
27th August 2015, 10:27
Is it also possible to use this in a menu, like localized strings? For example

itemDef
{
name "test"
visible 1
textstyle ITEM_TEXTSTYLE_SHADOWED
origin 471 223
textfont UI_FONT_NORMAL
text "@LANG_HELLO"
textalign ITEM_ALIGN_CENTER
textscale .25
decoration
}


REFERENCE HELLO
LANG_EN "Hi"
LANG_NL "Hoi"
LANG_FR "Salut"
LANG_GR "Hallo"


And save that file as lang.txt?

IzNoGoD
27th August 2015, 12:09
Its server-sided so you would need a shitton of setclientcvars

Ni3ls
27th August 2015, 13:07
So its only usefull for iprints?

IzNoGoD
27th August 2015, 16:06
Its just a quick server-side lookup table for phrases that have been pre-programmed.
So its pretty much useful for stuff like iprints, huds (with setinftext) and a bit of menus

Ni3ls
27th August 2015, 17:00
If this was working like the real localized strings it would be awesome :)