Message translation
Mosel supports a message translation mechanism that makes it possible to display messages in the current language of the operating environment. This system requires that all messages are originally written in English and identified as messages to be translated (it is usually not desirable to translate all text strings of a model). The Mosel compiler can then collect all messages to be translated for building message catalogs. Each message catalog file contains the translations of the messages for a given language: Mosel will select the appropriate file for the current language during its execution to use the right set of translations. The system is designed such that it will not fail if a translation or an entire language is missing: in such a case the original English text is used.
Preparing the model source
Most often, not all text strings occurring in a program are to be translated to native language. This is why it is necessary to tag each message to be translated such that the automatic message translation system can process only the relevant texts. The tagging is achieved by using the operators _c(), _() or the modified procedures write_(), writeln_(), fwrite_() and fwriteln_().
The operator _c() is used to identify constant strings that should be collected for translation but the string will not be translated at the place where it is used. This operator can be applied to a list of string constants. A similar effect can be obtained with the annotation mc.msgid.
The function _() applies to both constant strings and variables: it replaces its argument by the translated string. As with the operator _c() constant strings are collected for the message catalogs, but they will also be replaced by their translation at the place where the operator is applied to the string.
The write_ and writeln_ procedures are equivalent to their normal versions except that they process the constant strings they have to display for translation.
All translations of a model (or package) are grouped under a domain: this identifier is used to name the message catalog files. The default domain name is the model (or package) name after having replaced spaces and non-ascii characters by underscores (for instance the domain name of the model "my mod" is "my_mod"). The domain name can also be specified using the mc.msgdom annotation.
The following model example shows the use of the various markers:
model translate ! The message domain is 'trs' (default name would be the model name 'translate') !@mc.msgdom trs declarations ! The elements of 'nums' are kept in English, but collected for translation nums=[_c("one","two","three")] ! Add 'four' to the message catalogs (although it is not used here) !@mc.msgid:four end-declarations ! Translate the message text, without translating 'nums' writeln_("all numbers (in English): ", nums) n:=getfirst(nums) ! Translate the message text and the first occurrence of 'n', but not ! its second occurrence writeln_("the first number is: ", _(n), " (in English:", n, ")") end-model
Building the message catalogs
Once the model source has been prepared, the list of messages to be translated can be extracted. This operation is performed by the Mosel compiler when executed with the option -x:
>mosel comp -x mymod.mos -o trs.pot
The output of this command is a Portable Object Template (POT): this is a text file consisting of a list of pairs msgid (message to translate), msgstr (translation) for which only the first entry is populated.
With the example model from the previous section the generated POT file results in the following:
# Created by Mosel v4.0.0 from 'translate.mos' # Domain name: trs msgid "all numbers (in English): %L\n" msgstr "" msgid "four" msgstr "" msgid "one" msgstr "" msgid "the first number is: %s (in English:%s)\n" msgstr "" msgid "three" msgstr "" msgid "two" msgstr ""
For each of the supported languages a separate PO (Portable Object) file that will contain the corresponding translations has to be created from this template. The command xprnls is used for this task (for further details please refer to the XPRNLS Reference Manual). For instance the following command will create the file for the Italian translations of the messages:
>xprnls init -o trs.it.po trs.pot
Here we name the file domain.language.po in order to ease the management of these translation files (where language stands for the ISO639 language code).
The generated file is a copy of the template with an additional header that should be completed by the translator (it is pre-populated with information obtained from the system), in particular the language (property "Language") and the encoding (property "Content-Type"). For each of the msgid records the translation in the language associated to the file has to be provided in the msgstr record. Note that some messages include escape sequences (like "\n") and format markers (e.g. "%s"): the corresponding translation must include the same format markers as the original text and they must appear in the same order (otherwise the translation will be ignored).
The beginning of the translation file of our example for French (named "trs.fr.po") should be similar to the following (the extract below shows only the header and the translation of the first message):
msgid "" msgstr "" "Project-Id-Version: My translation example\n" "POT-Creation-Date: 2015-12-04 18:16+0100\n" "PO-Revision-Date: 2015-12-04 18:16+0100\n" "Last-Translator: Jules Verne\n" "Language: fr\n" "Content-Type: text/plain; charset=ISO8859-15\n" msgid "all numbers (in English): %L\n" msgstr "tous les nombres (en anglais): %L\n"
The message catalogs for the PO files are obtained by running once more the xprnls command, this time using the option mogen:
>xprnls mogen -d locale trs.*.po
This command will compile each of the PO files into a Machine Object (MO) file named trs.mo that will be saved under the directory locale/lang/LC_MESSAGES. This directory tree must be distributed along with the model file for the automatic translation to work.
Model execution
During the execution of the model the message catalogs for the current language (as indicated by the operating system) are loaded automatically from the 'locale' directory. This location is defined by the "localedir" control parameter (by default this is "./locale"). If no message catalog can be found for the requested language then the original English text is used. This will also be the case if a translation is missing (e.g. if the message catalog has not been updated after some model source change).
When run on a computer configured for French our example displays:
tous les nombres (en anglais): [`one',`two',`three'] le premier nombre est: un (en anglais:one)
© 2001-2019 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.