Localization Guide

From ADempiere ERP Wiki

Jump to: navigation, search

Contents

Localization

In order for ADempiere to be usable in any country, it needs to be adapted to the local language and accounting system. A complete translation would need some 6 man-months, but if you do not translate help files and such, you could make it in under 2 months. If you only translate what will be used from inside the application, and you could work on the Accounting in paralell, maybe it would take you 3-4 weeks.

  • The main steps to localize ADempiere to your local language are:
  1. Make a terminology glossary
  2. Translate Menus, Tabs, Help files etc
  3. Import local General Ledger Accounts

Making a glossary

The first step before starting a translation, is to make a glossary of all possible terms. This will make the translation concise, which means that no end-user will complain that " this tab refers to a 'Document' and another to a 'Voucher', while meaning the same thing". The down side is that you will have to read **ALL** of the text to be translated beforehand, and write down the terms. A glossary is usualy in the form of a text file, or even two columns in a spreadsheet.

Translating ADempiere

There are two methods for translating ADempiere. You could either translate ADempiere directly through the application, or export the .xml files and translate them using a translation memory tool(it is just a large xml file with the original entry and the translated one). The advantage of using a translation memory tool is that whenever the original text is the repeated, the tool will automatically replace it with the matching phrase (ADempiere has ~10.500 entries, of which only 6.500 are the individual ones). Besides, the tool can suggest close matches based on word-for-word comparison, so you have to type a lot less text (this works like a charm when translating new entries of an upgrade!). This is the professional method. The disadvantage is that while it is the most efficient method for large projects, it has much too overhead for small ones. This means that because you would not be able to translate only what you need in an xml file (because you would not know where this section refers to in the ERP), you would have to translate the whole of the file. The best tool for working with ADempiere's xml files is Multilizer, which, sadly, is not open source.

Translating from inside the ERP

Translating from inside the ERP is quite straightforward. You just search for the "translation" menu, and read the english phrase and type the corresponding phrase in your language. You don't need to do anything else. The downside is that after having translated a large number of entries, you probably will not translate entries the same way all-through the application. Besides, if you want to change a term while in the middle of the translation, you will have to mannualy change it everywhere (that's why a glossary is important).

Translating in Launchpad.net

Translating the exported .xml files using a translation memory

In order to use a translation memory, you will export the translation from ADempiere. The export format is a large number of XML files that have many lines of the english phrase and the coressponding one to the local language. Currently, Multilizer is the only translation software that can translate only the local language part and NOT translate the originall. On the other hand, you can use an XML editor on the exported files for translation, export the text to be translated in an .csv file, save it in OpenOffice spreadsheet format, and use OmegaT for translating it. The problem here is that it is rather difficult to import the translation back to the xml files. On the other hand, with OmegaT you will get a standards compliant translation memory in .tmx (translation memory exchange) format, which could then be used in Multilizer (evaluation version) to translate automatically the XML files in seconds. But there is a trick allowing to use OmegaT only, see below!

Translating the exported .xml files using OmegaT only

There is another approach, which allows to use the OpenSource tool OmegaT only, no need to transfer to Multilizer. You take advantage of OmegaT's ability to handle HTML files. The XML files resulting from ADempiere translation export consist of XML tags <value>. A typical one is shown here:

  • <value column="Name" original="Client">Client</value>

OmegaT does not know the XML tag <value>, but it does know the tag <p>, because it is one of HTML's block element tags. So, the trick is to replace <value> by <p>, which can be done using text edition tools like sed or nawk, see example scripts below. This way the XML tag shown above is transferred into the following HTML tag, which is recognized:

  • <p column="Name" original="Client">Client</p>

OmegaT even understands, that the original (English) term to be shown to the translator is the string after 'original=' inside the start tag, and the term to be translated is the string between start and end tag. As long as no translation is done, both strings yield Client. During translation with OmegaT, a new translated HTML target file is generated, which then contains, e.g., the following translated (German) tag:

  • <p column="Name" original="Client">Mandant</p>

What still needs to be done now is to transform the <p> tags back to <value> tags and to specify the translation language. This way we get a translated XML file, ready for import to ADempiere. Below you find two example bash scripts using the sed tool and doing the tag transformation in both directions. The XML file AD_Element_Trl_en_US.xml and the language de_DE are taken as examples.

Essential lines of example Script to perform the transformation of <value> tags to <p> tags (XML to HTML)
INPUTFILE=AD_Element_Trl_en_US.xml
OUTPUTFILE=AD_Element_Trl_de_DE.html
cat $INPUTFILE > temp
# replace language=en_US by language=de_DE
sed 's:language="en_US":language="de_DE":g' temp > temporary
cat temporary > temp
# replace XML flag <value> by HTML flag <p>, done for start and end flag in one go
sed 's:<value column="\([^"]*\)" original="\([^"]*\)">\([^<]*\)</value>:<p column="\1" original="\2">\3</p>:g' temp > temporary
cat temporary > $OUTPUTFILE
Essential lines of example Script to perform the transformation of <p> tags to <value> tags (HTML to XML)
INPUTFILE=AD_Element_Trl_de_DE.html
OUTPUTFILE=AD_Element_Trl_de_DE.xml
cat $INPUTFILE > temp
# replace HTML flag <p> by XML flag <value>, done for start and end flag in one go
sed 's:<p column="\([^"]*\)" original="\([^"]*\)">\([^<]*\)</p>:<value column="\1" original="\2">\3</value>:g' temp > temporary
cat temporary > $OUTPUTFILE

We have translated XML files - how can OmegaT reuse them for further releases?

During translation OmegaT produces a standards compliant translation memory in .tmx (translation memory exchange) format. These translation memory files are used by OmegaT to show fuzzy matches to the translator, i.e. translations, which fit more or less to the actual term to be translated. In order to take over the translation proposal, the translator has to click on it. When going over from one ADempiere release to another, this would mean, the translator would have to click thousands and thousands of times to take over existing translations to the new release. This can't be the direction to go!

But there is another trick: OmegaT uses internally a specific file also in tmx format. This file is called project_save.tmx and is an internal storage containing translations, which have already been done on the current source file. Therefore all translations saved in project_save.tmx are executed automatically by OmegaT to a related source file at the moment, the file is loaded into the program to continue translation work on it.

The idea is now to take any tranlated XML file and create a related file in tmx format out of it. Once, we have such a file, we can copy it to OmegaT's translation memory in order to get fuzzy matches displayed, or, even better, we create a tmx file with correct header and footer, thus cheating OmegaT by pretending to be its internal translation storage. OmegaT will accept the file as its project_save.tmx file, when we copy it to the right place (this is below a subdirectory called omegat) and overwrite a file, which might already exist there. OmegaT then executes automatically all applicable translations in this project_save.tmx file, removes the ones not applicable and writes a nicely formatted new project_save.tmx file at the moment the translator presses the save button. I have to admit, this is not a recommended proceeding (I didn't find any description like this in OmegaT's documentation), as OmegaT assumes project_save.tmx to be for internal use, only. Though it works, at least with OmegaT version 1.6 RC12, which I used.

Question remains how to transform the translation of English Client into German Mandant, for example, as typical part of one of the translated XML files, looking like this:

<value column="Name" original="Client">Mandant</value>

into the related tmx format, as shown below:

<tu>
  <tuv lang="EN-US">
    <seg>Client</seg>
  </tuv>
  <tuv lang="DE">
    <seg>Mandant</seg>
  </tuv>
</tu>

The bash script in next chapter does this for you. Moreover, it inserts the necessary header and footer to the project_save.tmx file. At least the header probably needs to be adapted to the OmegaT version used! Have a look to part 'Write header to tmx file' inside script below. All lines between the one ending with EOF and the line containing just EOF are copied 1 to 1 to the output file. So, in order to adapt the script to the header you need, you have to recognize the following structure:

cat > $OUTPUTFILE <<-EOF
These 3 lines
are copied as they are
to the outputfile.
EOF


Essential lines of example Script to perform the transformation of <value> tags to tmx (XML to Translation Memory)
INPUTFILE=AD_Element_Trl_de_DE.xml
OUTPUTFILE=project_save.tmx
cat $INPUTFILE > temp

# remove header
sed 's:<?xml.*table="AD_[^"]*">::g' temp > temporary
cat temporary > temp
# remove footer
sed 's:</adempiereTrl>::g' temp > temporary
cat temporary > temp
# remove row end and start tags
sed 's:</row>::g' temp > temporary
cat temporary > temp
sed 's:<row[^>]*>::g' temp > temporary
cat temporary > temp
# replace value start tag, but keep english text, i.e. text after 'original='
sed 's:<value column=[^g]*ginal="\([^"]*\)">:<tu><tuv lang="EN-US"><seg>\1</seg></tuv><tuv lang="DE"><seg>:g' temp > temporary
cat temporary > temp
# replace value end tag, translated (german) text in front of that tag is not touched
sed 's:</value>:</seg></tuv></tu>:g' temp > temporary
cat temporary > temp


# Write header to tmx file. This part needs to be adapted, if another OmegaT version is used.
cat > $OUTPUTFILE <<-EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tmx SYSTEM "tmx11.dtd">
<tmx version="1.1">
  <header
    creationtool="OmegaT"
    creationtoolversion="1.6 RC12"
    segtype="sentence"
    o-tmf="OmegaT TMX"
    adminlang="EN-US"
    srclang="EN-US"
    datatype="plaintext"
  >
  </header>
  <body>
EOF


# write all translations in tmx format to tmx file
cat temp >> $OUTPUTFILE


# write footer to tmx file
cat >> $OUTPUTFILE <<-EOF
  </body>
</tmx>
EOF

Importing local General Ledger Accounts

For Accounting, you would need the help of an experienced accountant, because ADempiere needs a basic set of ~75 accounts to be set-up to the corresponding local ones. Due to the diferences in each country's accounting systems, these will probably not be the same for each country, so you should get professional advice. You could approach your client's accountant for enlisting his help - it would be for his benefit, anyway.

Useful links

Personal tools