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).
...
The translation as stored in the translation system.
The phrase in the base language as stored in the translation system.
The phrase as typed directly in Microbizz.
Translateable objects
The following types of objects may be translated:
type | objectcode | objectid | subid | subsubid |
---|---|---|---|---|
Question form name | “question_form_name” | ID of the q.form | not used | not used |
Question form question | “question_form” | ID of the q.form | The 'hardid' of the question | 0 for the actual question |
Question form question option (A) | “question_form” | ID of the q.form | The 'hardid' of the question | 1..N : The index of the option |
Custom field name | “customfields” | ID of the field | 0 for the field name | not used |
Custom field option (B) | “customfields” | ID of the field | 1..N for the index of the option | |
“Types” (C) | <tablename> | ID of the type | not used | |
Headline of infoboxes (on startpage) | “infobox_name” | ID of the box | not used | not used |
Help text for infoboxes | “infobox_helptext” | ID of the box | not used | not 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”.
...
(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:
modcode | Module in which the base phrase occurs. |
---|---|
objectcode | A unique string naming the object where the base phrase occurs, ie. “customfield”. |
objectid | A unique ID identifying the specific object where the base phrase occurs ie. “49”. |
subid | An optional sub-ID identifying a subpart of the specific object where the base phrase occurs. |
subsubid | Used in case each sub-ID may refer to multiple phrases. |
basephrase | The base phrase in the base language. |
translations | The translations of the base phrase. |
translation_statuses | The status of each translation. See later. |
changedate | The date of last editing |
changetime | The 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:
modcode | objectcode | objectid | subid | basephrase | translations | translation_statuses |
---|---|---|---|---|---|---|
todo | customfields | 49 | 0 | Antenna position | DA:Antenneposition SE:Antenneposition | DA:1 SE:1 |
todo | customfields | 49 | 1 | On roof | DA:På taget SE:På taket | DA:1 SE:1 |
todo | customfields | 49 | 2 | On ground | DA: På jorden SE:På marken | DA:1 SE:1 |
If the same field is editable in a question form, the translation structure for the question could look like this:
modcode | objectcode | objectid | subid | subsubid | basephrase | translations | translation_statuses |
---|---|---|---|---|---|---|---|
todo | question_form | 32 | 2 | 0 | Antenna position | DA:Antenneposition SE:Antenneposition | DA:1 SE:1 |
todo | question_form | 32 | 2 | 1 | On roof | DA:På taget SE:På taket | DA:1 SE:1 |
todo | question_form | 32 | 2 | 2 | On ground | DA: På jorden SE:På marken | DA:1 SE:1 |
Translation status
Each translation keeps a status, as follows:
0 | Missing. The translation is missing. |
---|---|
1 | OK. The translation is entered and considered correct. |
2 | Tainted. 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:
...
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.
...
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:
...
$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.
...
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.
...
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.