Translating the Zope backend application

By Maarten Kling | On Jul 05, 2012
There is no spoon.

Translating Plone modules or applications is not that hard, but you need to know the tricks and not get any unexpected errors on your way. I will show you my experiences and errors on the way to translate a litte widget built in plain Zope.

My situation: Zope, python 2.6, a widget sending mails using TAL templates needed in 3 languages, My freshly installed mac.

Virtualenv and i18ndude

First up, how do we translate templates or python files?  To my knowledge, we need locales and po files. After some googling I'm going to use i18ndude to generate the files for me. It sounds pretty nice because it will scan all templates for i18n tags and create the multiple po files for me.

Virtualenv and my path

As written at: I should not simply install i18ndude without creating some kind of virtual environment.

Important! The reason: You cannot install i18ndude globally, because it will install newer versions of various zope libraries including zope.tal, and zope will break (see this bug:

Luckily there is also a nice howto, lets follow it. Because I know I don't have virtualenv yet, I'm installing this first.

easy_install-2.6 virtualenv

The installation is succesful; Continue;

cd ~
mkdir bin
cd bin
mkdir i18ndude-virtualenv
virtualenv i18ndude-virtualenv

ARG! The first error, and it sounded so easy.

Kabz-MacBook:bin maarten$ virtualenv i18ndude-virtualenv
-bash: virtualenv: command not found
Kabz-MacBook:bin maarten$ 

My mac is freshly installed so chances are that there is not even a pyhon path defined in my settings, let's have a look;

cd ~
vi .profile
export PATH=/opt/local/bin:/opt/local/sbin:$PATH:/Users/maarten/bin

As expected, there is no python path here. Let's find it and add it. The command which python2.6 will show me the symlink. This is not the path where the easy_installed packages are going, that's why I need the real path.

Kabz-MacBook:~ maarten$ which python2.6

Kabz-MacBook:~ maarten$ ls -ahl /opt/local/bin | grep python2.6 python2.6 -> /opt/local/Library/Frameworks/Python.framework/Versions/2.6/bin/python2.6 cd ~
vi .profile
export PATH=/opt/local/Library/Frameworks/Python.framework/Versions/2.6/bin/python2.6:/opt/local/bin:/opt/local/sbin:$PATH:/Users/maarten/bin

Save the .profile and close the terminal, otherwise our new PATH isn't used. Let's try it again;

cd ~/bin/
virtualenv i18ndude-virtualenv

This works better now! Continue following the command list!

. i18ndude-virtualenv/bin/activate
easy_install-2.6 i18ndude
ln -s i18ndude-virtualenv/bin/i18ndude .

Everything is done, and we are now able to do ~/bin/i18ndude, whatever that may be :)

Generate PO files

So ( many thanks again! )

There is a script called

#! /bin/sh


# Synchronise the templates and scripts with the .pot.
# All on one line normally:
i18ndude rebuild-pot --pot locales/${I18NDOMAIN}.pot \
    --merge locales/manual.pot \
    --create ${I18NDOMAIN} \

# Synchronise the resulting .pot with all .po files
for po in locales/*/LC_MESSAGES/${I18NDOMAIN}.po; do
    i18ndude sync --pot locales/${I18NDOMAIN}.pot $po

We have to put this file in the package to translate;
In my case: /opt/widgetbackend/src/mypackage.widget/mypackage/widget/

We can run the script; As always, it never works the first time! Error: files missing;

Kabz-MacBook:widget maarten$ ./ 
Warning: locales/*/LC_MESSAGES/mypackage.widget.po is not a file or is ignored.
Kabz-MacBook:widget maarten$ 

First we need to create the files and all languages that we require; To create the Dutch language file, execute the following commands, which includes creating an empty po file.

cd locales
mkdir nl
cd nl
touch mypackage.widget.po 

Finally run the script and get the po files ( this is the outcome when one line is found. )

Kabz-MacBook:widget maarten$ ./ 
locales/nl/LC_MESSAGES/mypackage.widget.po: 1 added, 0 removed
locales/de/LC_MESSAGES/mypackage.widget.po: 1 added, 0 removed

We've now got ourselves some nice po files.

PO files explained

Let's have a look at the generated .po files from i18ndude. They start with information about the author, the package name and the language. We change all this to match our situation. This one I changed a little so it's for the Dutch translation.

msgid ""
msgstr ""
"Project-Id-Version: mypackage.widget\n"
"POT-Creation-Date: 2011-01-27 12:26+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0\n"
"Language-Code: nl\n"
"Language-Name: Dutch\n"
"Preferred-Encodings: utf-8 latin1\n"
"Domain: mypackage.widget\n"

#: ./browser/templates/
msgid "Widget forgot my password"
msgstr ""

To translate the line found by i18ndude, we enter the Dutch string at the msgstr;