View source | Discuss this page | Page history | Printable version   

How to Create and Update Translation Modules


About this document

This document describes the process of creating and updating translation modules in Openbravo, including the Core's module. It is designed as how-to document to be read from the beginning to the end, but it also provides useful information to be consulted as a reference guide.

Recommended articles

Translations are distributed using modules, that's why it is important to have a clear idea of the Modularity Concepts, specially the process of creating and packing modules. Related to that, it is interesting to read the Naming guidelines for modules.

It is also highly recommended to read the Translation Engine Concepts to clear understand the way Openbravo manages translations.

Finally, if you plan to use the openbravo2po tool to work with PO files, you can find detailed information about its installation and usage into the User documentation for openbravo2po

Estimated effort

Creating a translation module from scratch

The estimated effort for creating a translation module is directly proportional to the number of strings into the module to translate.

For example, in the Core's module, which is by far the biggest module available in the Openbravo distribution, there are more than 15800 strings to be translated. These strings can be just words, sentences with less than 10 words or larger paragraphs.

Some of the strings are very easy to translate, specially the ones belonging to messages or elements, however other strings will require a bit more effort to locate its context and provide an accurate translation.

So estimating an average of one minute per string gives us about 30-35 days (of a translator working tirelessly in the Openbravo's Core translation 8 hours/day. Apart from that we should include a few hours more to the usual tasks of creating and packaging the module, testing the installation, etc.

Besides the above, an estimation of 10 days more, should be considered as the estimated effort of translating the remaining Openbravo 3 distribution modules.

Updating a translation module

In the case of updating a translation module the effort is usually much lower, because we just need to translate the new strings that have been added to the module or the ones that have changed. As you can imagine the rest of the translation is kept.

So in this task, apart from the time invested in translating the strings, we obviously need to add a few hours to install the updated version of the module we are going to translate, and to package and test the new version of the translation.

Creating a new translation module from scratch

Create module definition

As you can imagine, the first thing we need to do is to create the translation module definition into the Application Dictionary.

Logged as System Administrator role, we select the Application Dictionary || Module window from the Application menu and we create a new record trying to follow the Naming guidelines for modules.

Translation modules are a special kind of modules. They have to be marked as Is translation module in the Module window and they must define the translation language at the Module Language field.

No other contents than translations are allowed in translation modules. A translation module can only contain the translation for one module. For example, in the screenshot below we are creating a Spanish (Spain) translation module for the User Interface Application module whose declared language is English (USA).

LocGuide HowTo Translate 10.png

Apart from checking the Is translation module and setting the Module Language, we need to add a dependency to the module and version we are translating. In the example, our User Interface Application Translation Spanish (Spain) module in version 1.0.5 depends on the User Interface Application module version 2.1.0.

Once done it don't forget to register the module!

Prepare strings to be translated

Logged as the System Administrator role, we select the General Setup || Application || Language window from the Application menu. Now find the language on which we want to create the translation module and check the System Language checkbox field. This checkbox allows this language to be selected in the user interface (Change role popup) in the next login.

LocGuide HowTo Translate 20.png

LocGuide HowTo Translate 30.png

Verify Languages

Each time we want to create a translation for a new language we need to prepare the strings to be translated. There is an automatic process, called Verify Languages (available as well at the Language window), in which the ERP creates a copy of the original strings of all the modules available in the system from their base languages to the desire translation language.

For example, in the case of creating a Spanish (Spain) translation for the core's module, whose base language is English (USA), the system will copy all the original English strings to the Spanish translation. And the same is extended to the rest of the modules installed in the system with their respective base languages.

So it is time to press the Verify Languages button. After several seconds, the application will display the number of records created. If this number is equal to 0 means that something was wrong, and the probable cause is that we have forgotten to check the System Language field.

LocGuide HowTo Translate 35.png

Export the translation

We are ready to export the translation, i.e., to get the XML files that we need to translate. This is an automatic process available at the General Setup || Application || Import/Export Translations window.

As System Administrator role, select the language in which user want to export translation files. Export Reduced Version flag can be set to Yes to have a reduced translation version. This would exclude all translation candidates that are linked directly or indirectly to the Menu having translation strategy as "Exclude From Reduced Translation". User could set this flag as No to have a full translation version by pressing the Export button. The process takes several seconds to export all the XML files so be patient.

LocGuide HowTo Translate.png

Inside the attachments folder of your Openbravo instance (which is defined at the file), you will find a new directory called lang, and inside it a new one with the lowercase two-letter ISO-639 language code and the uppercase two-letter ISO-3166 country code separatted by an underbar character ('_'). Example: /home/openbravo/attachments/lang/es_ES

LocGuide HowTo Translate 50.png

Inside this directory you will find the translation files for all the available modules into the instance. The core's translation files are stored directly into the root directory, the rest of the modules have their own folder named as their java packages. So we just need to find the folder of the original module we want to translate (not the translation module) and get its XML files.

Translate the module

The translation of the module can be directly done inside the exported XML files, which is a convinient method for modules with few strings to be translated, or using the openbravo2po tool which is the recommended way for modules with a lot of strings, like Core.

Translate directly into the XML files

If we choose this method, we just need to open each XML file that is inside the module's directory we want to translate and edit it. It is very important to open these files with a text editor (like Vim, Emacs, gEdit, notepad...), never using a word processor (like LibreOffice Writer or Microsoft Word) because they can break the XML structure.

The text we need to change for making a translation is the content of each value tag. It's not necessary to edit any attribute because they will be automatically updated when importing and exporting the files into the ERP in a next step.

LocGuide HowTo Translate 60.jpg

If you need more information about the structure of the translation files in Openbravo, you can visit the Translation concepts article.

Translate using openbravo2po

openbravo2po is a Java tool that transforms the Openbravo XML translation files into .po files (gettext catalog). PO (Portable Object) is a very popular format for storing and translating software. The great advantage of using PO files is that there are a lot of editors that help the user in the translation process.

openbravo2po is compatible with any operating system that supports Java and that has installed Apache Ant.

Installing openbravo2po

Clone the mercurial repository with the command:

hg clone

Compile the openbravo2po with the command:

ant jar

Run the openbravo2po tests to check the tool is ready with the command:

ant test

Note: To run this you may need to copy the ant-junit.jar in the lib folder of your $ANT_HOME

If you want more information about this tool, you can read the User documentation for openbravo2po

Generating PO files

openbravo2po is a command line tool based on Apache Ant. This means you will need to enter ant commands each time you want to work with it. This may sound a bit complex, but don't worry because it's very easy!

The ant command for generating PO files from the Openbravo's XML files is runXML2PO. The command accepts the following options:

So, inside the openbravo2po root directory, we should execute the command:

ant runXML2PO -DinpFold=<directory containing module's XML files> -DoutFold=<directory to save the PO files> -DmsgStr=yes


ant runXML2PO -DinpFold=/home/openbravo/attachments/lang/es_ES/org.openbravo.client.application -DoutFold=/tmp/PO_directory -DmsgStr=yes

LocGuide HowTo Translate 70.png

Important information if you are translating Core

Openbravo's Core provides an additional file called buildStructure.xml. This file contains the information related to the names of the different stages through which the Openbravo build process passes, and the error and warning messages that can be shown during a rebuild. You should also need to translate this file, however it is not compatible with the openbravo2po software. So before generating the PO files using the runXML2PO command, you must be sure the buildStructure.xml file is not inside the XML directory, otherwise the openbravo2po will fail.

Editing PO files

Now we are ready for editing the generated PO files. As we saw in the Translate directly into the XML files section, we can directly make the translation using a plain text editor. In this case we just need to translate the content of the msgid string, which represents the original text, into the msgstr entry for all the available .po files. Example:

LocGuide HowTo Translate 75.png

However editing the .po files using a text editor doesn't seem to provide an advantage compared to translating XML files. The great benefit of working with PO files is that we can use PO editors, which are specialized software with tools that facilitate the task of translating. There are a large number of cross platform PO editors to choose from, and most of them distributed under a free software license: PoEdit, gted (Eclipse plugin), PO Mode for Emacs, Lokalize (part of KDE), OmegaT, etc. I recommend you to try some of them to find the perfect for you.

PoEdit is an editor that has a large number of features and a very intuitive user interface. It provides a project manager that is very useful when we work on several modules at the same time. For creating a new project we just need to specify the folder where the PO files are stored:

LocGuide HowTo Translate 80.png

PoEdit inspects all the .po files inside the selected directory and provides useful statistics about the status of each file, i.e., the number of total strings, the ones that are pending to be translated, etc.

LocGuide HowTo Translate 90.png

So we just need to open the files with untranslated strings by doble clicking on them and start translating. By default the untranslated strings are always displayed at the top of the editor. In the lower right corner it's shown the comments window that can give interesting information to provide an accurate translation.

LocGuide HowTo Translate 100.png

Generating the Openbravo XML files from PO files

Once we have completed the translation of all the strings in the PO files for the module, it is time to transform them back to XML files. As you can imagine this process is driven again by the openbravo2po tool.

In this case the ant command we must use is runPO2XML. The available options are quite similar to the runXML2PO command:

So, inside the openbravo2po root directory, we should execute the command:

ant runPO2XML -DinpFold=<directory containing PO files> -DoutFold=<directory to save the XML files>


ant runPO2XML -DinpFold= /tmp/PO_directory -DoutFold=/home/openbravo/attachments/lang/es_ES/org.openbravo.client.application

Import and Export the translation

After the translation is completed, or even in the middle of a translation process, is a good practice to import the XML files into the ERP to review the translation in context.

Finally, once we feel the translation is OK, we should export it again. Doing that we ensure the XML files have the final structure, with all the attributes properly set.

Moreover, if we are working with a Source Code Management (highly recommended), the process of importing/exporting the XML files will help us a lot when updating translations. The diff will show us only the translation differences between the old version and the new one, but not changes in the structure of the XML file.

For importing/exporting the translation you can use the General Setup || Application || Import/Export Translations window as we previously saw in the Export the Translation section.

As you can imagine, all the XML files to be imported must be inside their correspondent module's folder of your attachments directory, overwriting the original XML files exported at the beginning of this process.

Now, at the Import/Export Translations window, we can select the language used for the translations and press the Import button. We wait a few seconds to complete the process and we press now the Export button, that will export the XML files again.

LocGuide HowTo Translate 40.png

Note: During this process it is highly recommended to keep a backup of your translated XML files.

Specific information if you are translating Core

buildstructure.xml file

Openbravo's Core provides an additional file called buildStructure.xml. This file contains the information related to the names of the different stages through which the Openbravo build process passes, and the error and warning messages that can be shown during a rebuild. You should also need to translate this file, however it is not compatible with the openbravo2po software, so you will need to manually edit it using a text editor (not a word processor)

The structure of this file is a bit different compared to the standard Openbravo XML translation files, but it is also very easy to understand. You just need to translate the content of all the attributes that start with translated, like translatedName, translatedErrorMessage, etc. This is an example of the buildstructure.xml file translated into Spanish.

<?xml version='1.0' ?>
    <mainStepTranslation code="RB11" originalName="Initial Build Validation" translatedName="Validación de la construcción del sistema" translatedErrorMessage="La validación ha fallado. El sistema no se ha modificado y continua estable, pero los problemas descritos en la parte inferior de la ventana deberían resolverse (ya sea desinstalando los módulos afectados, o resolviendo los problemas de la forma descrita), y una nueva construcción del sistema debería iniciarse.">
    <mainStepTranslation code="RB20" originalName="Build" translatedName="Construcción del sistema" translatedSuccessMessage="La construcción del sistema se ha completado con éxito." translatedWarningMessage="Se produjeron alertas durante la compilación. La aplicación se ejecutará, pero debería comprobarlas para ver si son importantes. Ir a &lt;a href=&quot;; target=&quot;_blank&quot; class=&quot;MessageBox_TextLink&quot;&gt; este enlace &lt;/a&gt; para más información. &lt;b&gt;Ahora debe reiniciar el contenedor de servlets&lt;/b&gt; para que los cambios tengan efecto." translatedErrorMessage="Ha ocurrido un error durante la construcción del sistema. Para saber qué pasos realizar a continuación, vaya a &lt;a href=&quot;; target=&quot;_blank&quot; class=&quot;MessageBox_TextLink&quot;&gt;este enlace&lt;/a&gt;">
        <stepTranslation code="RB12" originalName="Database update" translatedName="Actualización de la base de datos"/>
        <stepTranslation code="RB31" originalName="Reference data" translatedName="Datos de referencia"/>
        <stepTranslation code="RB43" originalName="Compilation" translatedName="Compilación"/>

If you are using openbravo2po remember that, before generating the PO files using the runXML2PO command, you must be sure the buildStructure.xml file is not inside the XML directory, otherwise the openbravo2po will fail.

Masterdata dataset

All the XML files exported through the Import/Export window and the buildstructure.xml represents all the available user interface strings in the ERP. If we translate all these files we will have a fully translated application. However, the ERP includes some other strings not related to the UI that can be also translated. Inside this group, called Masterdata, we include: country names, currencies, units of measure and month names. All this data is not exported into the XML files, however this does not mean we can't not translated it.

The way for translating masterdata is creating a system level dataset that only contains the translated strings for countries, currencies, units of measure and months. We will now explain the specific details for the masterdata translation dataset, but if you need general information about creating datasets you can read the How to create a Dataset article.

As System Administrator we create a new record inside the Dataset window for our core's translation module. It is important to define this dataset at System only level to ensure it will be automatically applied when we install the module.

As you can see in the screenshot, the tables to be included are: AD_Month_Trl, C_Country_Trl, C_Currency_Trl and C_UOM_Trl. All of them have a filter clause that uses the language column, in the example es_ES.

LocGuide HowTo Translate 110.png

Now our Core's translation module has a dataset, so we must remember to check the Has reference data flag into the module's definition

LocGuide HowTo Translate 120.png

The dataset definition is ready, but it's pending the translation itself. For translating this dataset we have two possibilities:

Translation pack

As you probably know, Openbravo is a distribution of modules, including Core. That means that for having a fully translated application, you must translate all the modules that are part of the distribution. At the time this document has been written, the list contain the following modules: Query/List Widget, JSON Datasource, User Interface Application, Widget Collection, User Interface Client Kernel, Advanced Payables and Receivables, HTML Widget, Orders Awaiting Delivery, Smartclient, User Interface Selector, Workspace & Widgets, Payment Report, Integration with Google APIs, OpenID Service Integration and Core.

It is a good idea to create a translation pack that covers all these modules. Later on we can include this pack into our Localization Pack.

Packaging the translation module

The process of packaging a translation module is similar to the standard packaging process with just one important consideration: we need to copy the translated XML files to the correspondent module's referencedata/translation folder within your module folder.

The summarized process is:

ant export.database 
<translation module java package name>
├── referencedata
│ ├── standard
│ │ └── Masterdata.xml (only for core)
│ └── translation
│     └── es_ES
│         ├── AD_ELEMENT_TRL_es_ES.xml
│         ├── AD_FIELDGROUP_TRL_es_ES.xml
│         ├── AD_FIELD_TRL_es_ES.xml
│         ├── AD_FORM_TRL_es_ES.xml
│         ├── AD_MENU_TRL_es_ES.xml
│         ├── AD_MESSAGE_TRL_es_ES.xml
│         ├── AD_MODULE_TRL_es_ES.xml
│         ├── AD_PROCESS_PARA_TRL_es_ES.xml
│         ├── AD_PROCESS_TRL_es_ES.xml
│         ├── AD_REFERENCE_TRL_es_ES.xml
│         ├── AD_REF_LIST_TRL_es_ES.xml
│         ├── AD_TAB_TRL_es_ES.xml
│         ├── AD_TEXTINTERFACES_TRL_es_ES.xml
│         ├── AD_WF_NODE_TRL_es_ES.xml
│         ├── AD_WINDOW_TRL_es_ES.xml
│         ├── AD_WORKFLOW_TRL_es_ES.xml
│         ├── buildStructureTrl.xml
│         ├── C_DOCTYPE_TRL_es_ES.xml
│         ├── CONTRIBUTORS_es_ES.xml
│         ├── OBKMO_WIDGET_CLASS_TRL_es_ES.xml
│         ├── OBUIAPP_PARAMETER_TRL_es_ES.xml
│         ├── OBUISEL_SELECTOR_FIELD_TRL_es_ES.xml
│         └── OBUISEL_SELECTOR_TRL_es_ES.xml
└── src-db
    └── database
        ├── model
        │ ├── functions
        │ ├── sequences
        │ ├── tables
        │ ├── triggers
        │ └── views
        └── sourcedata
            ├── AD_DATASET_TABLE.xml (only for core)
            ├── AD_DATASET.xml (only for core)
            ├── AD_MODULE_DEPENDENCY.xml
            └── AD_MODULE.xml
ant package.module -Dmodule=<java package name>

Updating translation modules

First of all let's comment the obvious considerations for updating a translation module:

The main steps for updating a translation module are almost the same as when Creating a new translation module from scratch. The only difference is that we don't need to declare the System Language and to run the Verify Languages process. The rest of the process is exactly the same, starting by the Export the translation section.

Tips and Tricks

This section tries to provide a set of useful translation tips and tricks. Take into account that some of this tricks may require development knownledges.

Translation Memory

Po editors like PoEdit have interesting features that helps translators. For example, one of its interesting features is the Translation Memory, that tries to automatically translate new strings based on the previous translations found in the project. When we are editing a PO file using PO edit, we can use the Automatically translate using TM option at the Catalog menu. This process will translate for us the pending strings looking at its translation database. The automatically translated strings have the fuzzy status to help you review them.

In the screenshot bellow PoEdit has automatically translated to Spanish the Amount string:

LocGuide HowTo Translate 140.png

If you are translating directly into the XML files you can also have a manual translation memory using the Grep tool. grep command can search for matching strings (or regular expresions) into a set of files.

The following example finds all the ocurrences of the string “Exempt Amount” in all .xml files in the directory

openbravo@por0828:~/XML_files$ fgrep -i "Exempt Amount" *.xml 
AD_ELEMENT_TRL_es_ES.xml:    <value column="Name" isTrl="Y" original="Exempt Amount">Importe exento</value> 
AD_TEXTINTERFACES_TRL_es_ES.xml:    <value column="Text" isTrl="Y" original="Exempt Amount">Importe exento</value>

Finding the context

Making a good translation requires to know the exact context where the string we are translating appears. Unfortunatelly the context in the XML file is not clear at all, and sometimes we will need to dive into the application to get the exact context. Here you have a list of tips for finding it:

With this information I can use the grep command to find the places in the module's source code where the message is used:

$ fgrep -r NoBPLocation src* 
src/org/openbravo/erpCommon/ad_callouts/      message.append(Utility.messageBD(this, "NoBPLocation", vars.getLanguage())); 

Now I know it is used in a callout, so I just need to find in the Application Dictionary the places where this callout is used using the Linked Items feature commented before.

Retrieved from ""

This page has been accessed 31,427 times. This page was last modified on 9 December 2020, at 07:25. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.