Language in v5

One of the major changes between v4 and v5 is how language is dealt with. This document describes the workings in general, how to set preferred language and how to change messages.

Hardcoded language

All previous enCore versions build on the lambdamoo style of coding language into the verbs. All strings printed to the user are put directly into the programming code, like:

requestor:tell("As you requested, the housekeeper tidied ", $string_utils:nn(object), " from ", $string_utils:nn(loc), " to ", $string_utils:nn(place), ".");

which produces something like:

As you requested, the housekeeper tidied Coke bottle (#3728) from Manor (#4729) to Fountain (#3213).

This is the case for web pages as well, e.g.,

form = $list_utils:append(form, $encore_web_utils:p(), $encore_web_utils:input("submit", "Save Changes", "", "submit"));

which simply produces a submit button reading "Save Changes" underneath a web formular.

But this "simply" is not always self-explaining. If you want to use enCore for, e.g., German language learning purposes, you probably want to put German writing on the submit button. Now, you could go into the code and change the words. But even administrators/wizards often do not know what spots to change, and they wonder what their changes will do to the workings. Must I change the "submit" next to the "Save Changes"? What if I don't? If I change "Save Changes", will that affect the next step, i.e., the handling of the request? Indeed, you will find places where the form processing script searches for the exact wording "Save Changes", and only acts if that wording is encountered. So ideally, one would have to trace everything and redo everything in the desired language. This is tremendous work. And if you do it, you are stuck with a core customized to the bone, and still as hardcoded as the original. Updating code (to newer main distro versions) becomes even more complicated than it already is. Sharing code becomes so hard that if often is not worth it.

There is another problem. The sequence

The housekeeper tidied x from y to z

is written in English structure. There are many languages which do not share all of these grammatical structures. Look at the "arguments" x y z and their position in the sentence. In German, one might say (amoungst other possibilities)

Der Hausmeister hat in y x genommen und nach z gebracht.

How do you hack something like that into the original code? So translating is not merely a matter of exchanging a few words, like "tidied", "from" and "to" and keeping the structure as it is. This has given many translators a major headache.

Separating code and language

The main idea in v5 is to separate code from language. Typically, you would now find the code section above replaced with something like

1: lang = user:lang(); 2: strings = "player_strings"; 3: what = $string_utils:nn(object); 4: from = $string_utils:nn(loc); 5: to = $string_utils:nn(place); 6: replacements = {{"%what", what}, {"%from", from}, {"%to", to}}; 7: message = lang:g(strings, "housekeeper_cleaned_up", replacements); 8: requestor:tell(message);

As you see, there is no hardcoded language baked into the code. The code refers to a language object. This language object is defined on the user (lang = user:lang();). Then, a collection of strings is defined (strings = "player_strings";). This variable points to a property on the user's language object. It may contain a range of strings, like:

$eng_utils.player_strings connected => %p has connected disconnected => %p has disconnected housekeeper_remove => The housekeeper comes to remove %p. housekeeper_drop => The housekeeper comes to drop off %p. housekeeper_cleaned_up => As you requested, the housekeeper tidied %what from %from to %to.

Now, the language object (here: English) finds the property, finds the line, replaces the placeholders and returns the string to the calling verb, from where it is printed to the user.

This holds a number of advantages: One can freely tinker with the string to be produced (on the right of the =>) without breaking any code. This means as well that the string is translatable, without having to worry about the core code.

Another advantage is that messages for a whole room don't need to be in one language any more. The :announce verb (in its current, more sophisticated version) runs through the players connected in one room, finds their language object, and let each object retrieve the string, and print it out individually. Please read section 2 in Communication .

Preferences

Let's have a look at the Preferences section. You will find a TAB for Language. (Since there are many tabs to choose amoungst, I made a "brief" and a "complete" list of choices. The language TAB might be hidden under "more choices".) The first screenshot is in Norwegian.

You will find two select boxes: The first one is for the main language objects. Note that this is not a simple drop down select, but a sortable box. Mark (highlight) a language and move it up and down with the buttons to the right. The languages are now sorted according to your preferences. Whenever there is a page which holds more than one language, e.g. descriptions of rooms in multilanguage platforms, your most preferred language is returned to you. This language setting is also used for the new Help Function (forthcoming), where (upon clicking on a lightbulb) an argument string is sent to the Help database server, saying, e.g.: lang=fr,de,en, meaning that help texts should be served French, and, if not available in French, in German, and, again, if not available, in English.

The second one is the alternating language. This means that the title- and alt-attributes for links and pictures will be displayed in that other language. Take a close look at the screenshot above: Although pure and correct Norwegian, most of it would appear as gibberish to the common English speaker. Yet, the small yellow floating box displays some English text. (The yellow box appears upon hovering on an element which has an ALT or a TITLE attribute attached to it.) The idea is to help language learning students with these alt/title-boxes in a familiar language.

If we switch the main language to English and the ALT-language to Norwegian, we get something like this:

Please compare the screenshots carefully. Note the yellow floating box. Note as well that, in the Preferences, the yellow box is filled with the first sentence of the "direct help" (the small expandable text to the right of the lightbulb).

Please note that the code for producing these two pages is exactly the same. There is just one code, and no language is found within it. Wherever a string is needed, the appropriate language object (the user's) kicks in and delivers the string. The strings are retrieved from this list (just a small section of the list is shown):

$eng_utils.object_editor_strings edit_langs => Language edit_langs_expl => Choose your preferred languages for system messages and interface. Note: Objects you build will carry your language setting at the time of their creation until you change it. edit_langs_lang => Languages edit_langs_raise => raise edit_langs_lower => lower

Finding and changing strings

Say you encounter the word "Bookmarks" somewhere and you want to globally change it to, say, "Favorites". You can then go to the Program Editor, enter the search word into the search box and hit the "lgrep" (language grep) button. This will produce a list with all instances of "Bookmarks" in all string-collections.

Say we want to alter the string where it says "%n added to your personal Xpress Bookmarks". Find that string in the third column. The second column gives the key under which to find the string, and the first column gives the name of the property where the key is encountered. This list is clickable, meaning that clicking on the link in the second column will give you a new list of instances which are alling this string:

In this example, there is only one instance calling. The header of the box lists the object, the verb, the last player who changed it (and when). Many elements are clickable and will lead to further programming instances. The code itself is tagged and clickable as well; this example doesn't show this though. Note that the line number is given, for easier retrieval of the line in the verb code in the next screenshot. Clicking on the verb name on the header ($Xpress_navigator:bookmarks) will open the Program Editor's Verb page.

But since this string is not defined in the code, this isn't really of interest right now. We want to see the language pack where the string "%n added to your personal Xpress Bookmarks" is defined. Clicking on the first column brings you right to the string collection.

Here, you can alter whatever you want without breaking any (functional) code.

Entering commands

The MOO has a built-in parser which allows to type in various commands. I have used much time to add foreign languages to the parser, both verb names, prepositions and structures. However, I found that keeping hacking on the parser there means more problems than actual benefit. So the current version of v5 has NO altering to the parser nor the interactive verb names nor the prepositions. They stay English for now.

Using Right-To-left

Arabic languages, like Hebrew, are written from right to left. Since we moved the Chat from Java to HTML, we are no longer bound by the restrictions the earlier Java applet posed for right-to-left-scripts. HTML and CSS are doing the job now.

Since it would confuse most users, I put the choice "Show rtl-link" (show right-to-left toggle link) in the Preferences under Chat Settings. Setting the choice to "yes" will display link underneath the text command box. This link is toggable, switching from RTL (right-to-left) to LTR (left-to-right). Setting the choice to "no" again will not change the direction, it will just hide the link.

In the following screenshot, rtl is activated, and the link says "ltr" in order to switch to ltr again when clicked. Note that the textbox has a scrollbar on the left side; the drop down selects have their choice arrows on their left as well.

Everybody in that room will see the Arabic part as on this screenshot - right flush and rtl. The settings of the indivudual player are not touched, however.

Note, too, that it reads "...", Wizard says due to the mixing of English and Arabic, which is detected by the browser and rendered ltr (the English bit) and rtl (the Arabic bit). Ideally, it should be "..." :says Wizard or similar. Putting in the correct Arabic forms (for "XY says") into the Arabic language object strings will fix this - for those who have defined Arabic as their first language object.

Note that the use of LTR and RTL is independent of the preferred language, as seen above. Clicking on RTL does not switch the preferred language to Arabic nor Hebrew.

Changes

Since I am not an expert on Arabic, Hebrew, nor their representaions in Unicode/HTML/CSS, and since I count on valuable input from those who are, there will most likely be changes to the details in which switching to, and using, RTL languages is performed. Once we have the translations into Arabic done, I picture a feature where the whole pages, including the main frameset, may be flipped right-to-left.

(End of file)