- DataModel
- UI changes
- Ticket management
- Examples
In iTop and iTop modules, a language is identified by two things:
Localization relies on dictionary files, which names are prefixed with the language code in lowercase, like : pt_br.dictionary.itop.core.php
. Those files are part of the datamodel, so a compilation is needed after each modification (run the setup again or use the toolkit).
In iTop, the embedded dictionnaries are located in :
<itop-root>/dictionaries/
<itop-root>/datamodels/2.x/<module>/
In modules, thoses files are located in the module's root directory.
A dictionary is in fact a PHP file. It must be encoded in the utf-8 character set (this is a MUST). We recommend that the PHP closing tag be omitted as in the example given below.
<?php /** * Localized data * * @copyright Copyright (C) 2015 John Foo Ltd * @author John Foo (john@foo.com) * @license http://opensource.org/licenses/AGPL-3.0 */ Dict::Add('PT BR', 'Brazilian', 'Portuguese', array( 'Menu:ChangeManagement' => 'Gerenciamento Mudanças', 'Menu:Change:Overview' => 'Visão geral', 'Menu:NewChange' => 'New Change~~', ));
Notes:
~~
at the end of some strings. This suffix is not displayed to the end-user. It is added by Combodo when releasing a new version, revealing which new strings requires a translation.core/config.class.inc.php
) : ITOP_APPLICATION
: The complete name of the application package, for example “iTop Community” or “iTop Professional”ITOP_APPLICATION_SHORT
: Just the name of the application, for example “iTop”Class:<classname>
, Class:<classname>/Attribute:<fieldname>
. For example : Class:Ticket
, Class:Ticket/Attribute:ref
, Class:UserRequest/Attribute:status/Value:new
Class:Ticket/Attribute:ref
but not Class:Change/Attribute:ref
. If you need the later, then just add it to your iTop instance using a customization module.Class:<classname>/Attribute:friendlyname
displayed as “Full name” in english if not translated, which do not correspond to a particular class field but to the magic attribute used as the object label on external key, objects list and object details.Key syntax | Purpose | Example |
Class:<classname> | Translating the name of a class | Class:Ticket |
Class:<classname>/Attribute:<fieldname> | Translating a field label | Class:Ticket/Attribute:ref |
Class:<classname>/Attribute:<fieldname>/Value:<value> | Translating a value of a Enum attribute | Class:UserRequest/Attribute:status/Value:new |
Class:<classname>/Attribute | Formating the friendlyname value. (see example below) | 'Class:Person/Name' ⇒ '%2$s %1$s' |
Friendlyname syntax: In this example
'Class:Person/Name' => '%2$s, %1$s', /* example: "Christie, Agatha" */
first_name
name
This allow to specify a different order and even some other characters, separators.
<classes> <class id="Person"> <properties> <naming> <attributes> <attribute id="first_name"/> <!-- mapped to %1$s --> <attribute id="name"/> <!-- mapped to %2$s --> </attributes> </naming>
A new entry should be named after its domain and purpose, starting with the less specific information.
The most commonly used separator is ':' but '/' and '-' could also be found.
'Core:BulkExport:TextFormat' => 'Text fields containing some HTML markup', 'UI:CSVImport:TextQualifierCharacter' => 'Text qualifier character', 'DayOfWeek-Sunday-Min' => 'Su',
Use suffixes to define variations of the same label :
'Core:SynchroAtt:update' => 'Update ?', 'Core:SynchroAtt:update+' => 'Used to update the object', 'UI:CSVImport:AdvancedMode' => 'Advanced mode', 'UI:CSVImport:AdvancedMode+' => 'In advanced mode the "id" (primary key) of the objects can be used to update and rename objects.' .'However the column "id" (if present) can only be used as a search criteria' .' and can not be combined with any other search criteria.',
When a naming convention is established, then the identifiers should be specified as <name>:<value>, like in the following example:
'Class:Event/Attribute:date' => 'Date', 'Class:Event/Attribute:date+' => 'date and time at which the changes have been recorded',
Note that, in this case, the separator should be '/'.
If you add a new end-users portal, you might want to create a dict. entry so it has a real label, to do so follow this synthax:
// Default portal 'portal:itop-portal' => 'Standard portal', 'portal:<YOUR_PORTAIL_ID>' => 'Your new portal label',
If you create a new theme for the backoffice, you might want to create a dict. entry so it has a nice label when users will select it from the preferences page.to do so follow this synthax:
// Default theme 'theme:fullmoon' => 'Full Moon 🌕', 'theme:<YOUR_THEME_ID>' => 'Your new theme label',
You'll have to create a fork from iTop main repository or the corresponding module repository, then do your modifications and propose them using a pull request : see the CONTRIBUTING.md file in the repo you're modifying for details.
A detailed procedure on pull request model is available in the GitHub help pages : Creating a pull request from a fork.
To add translations to an existing language : look for (grep) the ~~
and translate them in place.
~~
tag:find -name "de*dict*.php" | grep -v "env-" | xargs grep "~~"
Simply change de*
in the command above by the language code you want to process (fr, it, sp…) and launch this command from the directory where you installed iTop.
To add translations for a new language : find out your language code and country code. Copy the english files (either dictionary.*.php or en.dict.*.php) into their respective directory, with the relevant prefix (like in pt_br.dict…
). Translate them.
Dict::Add
function calls. Failing to do so will overwrite (at runtime) the english texts with yours.
The pull request will then be analyzed by Combodo maintainers, and eventually merged into the original repository.