Document toolboxDocument toolbox

User translations

User translations provides the user of a Microbizz solution to provide own translations to own data, such as custom field names, task status'es, info boxes etc.

See Translation.

Type of languages

System language

The system language can be understood as the language which the system talks, and therefore must be one of the languages that Microbizz is translated into.it

Base language

The base language is the language in which the users start their texts, and will usually match the system language, except if the user uses a language which isn't available as a system language. The base language must be one of the language that Microbizz is translated into. All data entered into Microbizz such as custom field names, are considered to be entered using the base language.

Other languages

A number of other languages can be defined, which is languages that the data will be translated into, so everything is translated from the base language to one or more other languages. Other languages must be selected from the languages Microbizz is translated into.dit

Which language to display ?

When logging in a user (or person, if on xnet) should be able to select between all languages (system, base and other).

If the user selects the base language, then phrases should be chosen in the following order:

  1. The phrase in the base language as stored in the translation system.

  2. The phrase as typed directly in Microbizz.

If the user selects another language than the base language:

  1. The translation as stored in the translation system.

  2. The phrase in the base language as stored in the translation system.

  3. The phrase as typed directly in Microbizz.

Translateable objects

The following types of objects may be translated:

typeobjectcodeobjectidsubidsubsubid
Question form name“question_form_name”ID of the q.formnot usednot used
Question form question“question_form”ID of the q.formThe 'hardid' of the question0 for the actual question
Question form question option (A)“question_form”ID of the q.formThe 'hardid' of the question1..N : The index of the option
Custom field name“customfields”ID of the field0 for the field namenot used
Custom field option (B)“customfields”ID of the field1..N for the index of the option
“Types” (C)<tablename>ID of the typenot used
Headline of infoboxes (on startpage)“infobox_name”ID of the boxnot usednot used
Help text for infoboxes“infobox_helptext”ID of the boxnot usednot used
Extranet (D)“xnet_menu”ID of the xnet page

Extranet<fieldname>ID of the xnet page


(A) For the question types “dropdown”, “radio” and “select multiple”.

(B) For the field types “One of many” or “Multi check” etc

(C) Person types, work areas, customer types, equipment types, task status etc. The modcode should be set to types and the objectcode should be set to the name of the table holding the types. TODO what if each type includes multiple translateable phrases ?

(D) There are other extranet texts that should be translateable, like the login page, and the frontpage.

Translation structure

A translation is structured as follows:

modcodeModule in which the base phrase occurs.
objectcodeA unique string naming the object where the base phrase occurs, ie. “customfield”.
objectidA unique ID identifying the specific object where the base phrase occurs ie. “49”.
subidAn optional sub-ID identifying a subpart of the specific object where the base phrase occurs.
subsubidUsed in case each sub-ID may refer to multiple phrases.
basephraseThe base phrase in the base language.
translationsThe translations of the base phrase.
translation_statusesThe status of each translation. See later.
changedateThe date of last editing
changetimeThe time of last editing


The translation structures for a custom field named: “Antenna position” with the following options: “On roof”, “On ground” could look like this:

modcodeobjectcodeobjectidsubidbasephrasetranslationstranslation_statuses
todocustomfields490Antenna positionDA:Antenneposition SE:AntennepositionDA:1 SE:1
todocustomfields491On roofDA:På taget SE:På taketDA:1 SE:1
todocustomfields492On groundDA: På jorden SE:På markenDA:1 SE:1


If the same field is editable in a question form, the translation structure for the question could look like this:

modcodeobjectcodeobjectidsubidsubsubidbasephrasetranslationstranslation_statuses
todoquestion_form3220Antenna positionDA:Antenneposition SE:AntennepositionDA:1 SE:1
todoquestion_form3221On roofDA:På taget SE:På taketDA:1 SE:1
todoquestion_form3222On groundDA: På jorden SE:På markenDA:1 SE:1


Translation status

Each translation keeps a status, as follows:

0Missing. The translation is missing.
1OK. The translation is entered and considered correct.
2Tainted. The translation is entered, but is not necessarily correct.


When a base phrase is added, then all translations are considered missing, but as they are entered they will become OK. If the base phrase at some point is changed from the original all existing translations becomes tainted, to indicate that they most likely doesn't represent a valid translation anymore.

If a tainted translation is edited and saved, it is automatically considered OK again.

Adding and removing phrases

Some phrases are added and removed on the fly as data is created in the system, while other very basic phrases such as yes and no are added to the system by default.

Updating an object

Things like task state is sent to the app in text form, So if the translation of a task state changes then all tasks in that state need be marked so that they will be resend to the app.

Changing base language

If the base language is changed and translations are present, the following takes place:

The old base language becomes another language and all base phrases are copied to the appropriate translations for that language.

If the new base language earlier was another language with translations present, these translations are copied into the base language. In the case where a translation isn't available, the former text is kept (even though it is in a wrong language).

Using the translations

The various classes should register/unregister phrases as necessary, based on the fields that may be translatable, and should subsequently call Translation::getPhrase() or trt() when a translatable field is displayed, typically in gvd().

Types

“Types” classes like Workarea, PersonType, TodoState etc should use Translation::getPhrase() or trt() when gvd() is called for the object title.

The classes should also set “registertranslations” in the Record2 definition in Record2::getClasses() - this will allow Record2 to handle the registering of phrases whenever an object is saved.

When editing a “type” object the input field for the object title should be an FTextTranslate, eg. for equipment types:

$trans = new Translation('tools', 'tools_group', $obj->toolgroupid);
$form->addField(new FTextTranslate(l('Type name'), 'groupname', true, array('width' => 250, 'trans' => $trans)));

When the form is submitted, Record2 will update the base language translation and taint the other translations for the other languages.

Extranet

Each XnetPagexxx class should include a list of the fields that can be translated:

public $translation_fields = array('pagehtml', 'disclaimer');

Thanks to the way HTML editable fields are handled by Xnet you will have to specify pagehtml instead of pagetext for the pagetext field.

Retrieving the translated phrase is done using trt():

$text = trt('xnet', 'pagetext', $this->pageid, $this->pagetext);

Input fields

The field FTextTranslate can be used instead of FText for text that should be translatable.

The FTextarea field provides a function makeTranslatable() which makes it translatable. I

$trans = new Translation($modcode, $objectcode, $objectid, $subid);
$field = new FTextTranslate(l('Name'), 'name', false, array('trans' => $trans));

$field = new FTextarea(l('Description'), 'desc', false);
$field->makeTranslatable($trans);

If a <textarea> use the HTML editor (puny_mce) then it is necessary for Javascript to call

 translation_adjust_textareaHTML($('textarea'), false);

This will adjust the onscreen position of the translation icons for the <textarea>.

javascript

The javascript for editing translation should be initialized by calling translation_init() when the editing form has been loaded.

Javascript generates events when the 'globe' icon is clicked for editing, and when the translations are about to be saved.

If the page allows editing of multiple objects with different modcodes or object codes or object IDs etc then it is necessary to update the translation ID when an object is selected for editing/translation. This is done using e.g. translation_set_objectid(objid) or translation_set_subid(subid). These may only be called from the translation_xxx events.

You may use translation_set_future_objectid(objid) at any time; the next time the translation dialog is opened the object ID is then set.

Record2

The class definitions in Record2::getClasses() may include a field registertranslations which (when present) allows Record2 to automatically register translatable phrases when an object is saved, and unregister them when the object is removed.

registertranslations may either be a bool (true to enable auto.reg., false to disable), or a string (will be used as the objectcode for the translation, instead of the DB table name), or an array (in case there are multiple translatable fields in the class, see UserSkill for an example).

App / API

Some API calls include the textual name of eg. a task status. Thus the information in the app may be incorrect if the translation of the task status changed. The function Translation::changed() time-stamps the tasks (or whatever) when the translation changes, so that they will be resent to the app.