Plone i18n: a brief tutorial

The following tutorial details the steps I took to internationalize (starting with a Spanish translation) the interface of Plone Translation Hub, a Plone Archetypes-based product.

Basic Plone i18n with i18ndude

First, processing your UML model via ArchGenXML (assuming you have i18ndude installed) will produce a file called generated.pot and place it in your product’s i18n directory, which is where all translations must go. Plone makes somewhat customized use of a the GNU gettext architecture for i18n of applications. So generated.pot is a template that contains the labels and text for your Archetypes objects.

Before you can begin translating, though, you’ll need to ensure that the elements in your your page templates that expose text to the user are tagged for translation by the Plone translation architecture. First you want to make sure that you specify the domain element in the template’s root (html) element to correspond to your product:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
    lang="en"
    metal:use-macro="here/main_template/macros/master"
    i18n:domain="PRODUCT_NAME">

Next, for field labels, help indicators, etc.–any text that’s visible to your user–you’ll need to apply the i18n:translate attribute:

<label for="my_field" i18n:translate="PRODUCT_NAME_label_my_field">Enter your name</label>

Once you’ve finished applying this attribute in your page templates, if your product is fairly simple, you’re nearly finished. All you need to do is merge the original PO file from your Archetypes product with your new translatable items from your page templates. Assuming i18ndude is in your path, from your product’s root directory, execute it like so:

i18ndude rebuild-pot --pot i18n/PRODUCT_NAME.pot --create PRODUCT_NAME --merge i18n/generated.pot skins/PRODUCT_NAME/*.pt

Then create an empty PO file for the language(s) you want to create. E.g., for Spanish, you’d want:

touch i18n/PRODUCT_NAME-es.po

Finally, to populate the PO file with the text from the original template so that you can translate it:

i18ndude sync --pot i18n/PRODUCT_NAME.pot i18n/PRODUCT_NAME-es.po

You can now perform your translations with a tool like POEdit.

Advanced Plone i18n

Translating workflow states and transitions

Now, if your product has its own workflow states and transitions, you’ll want to translate those as well. Enabling those translations is not included in the above process. You’ll need to create a separate file with a name reflecting the "plone" domain:

touch i18n/plone-PRODUCT_NAME-es.po

(Note also that the PO file header includes a "Domain" key to which you’ll want to assign the value "plone".)

Essentially you’ll need to edit this file by hand, assigning the msgid key with the original text and the msgstr with your translation:

msgid "Open"
msgstr "Abierto"

msgid "Closed"
msgstr "Cerrado"

Accessing the Plone translation machinery directly

You may have some text in your application that appears neither in your page templates nor in your workflow (obviously a situation that you want to avoid if possible). If so, you may need to access the Plone translation machinery directly, which is best illustrated with an example taken from an External Method used by my product:

from Products.CMFCore.utils import getToolByName
...
translation_service = getToolByName(self, 'translation_service')
msg = translation_service.utranslate(domain='PloneXL8',
                                     msgid='You have taken ownership of this translation.',
                                     default='You have taken ownership of this translation.',
                                     context=self)
msg = msg.encode('utf-8')

Note that you’ll need to add the msgid and msgstr for such into your PRODUCT_NAME.pot and/or PRODUCT_NAME-xx.po file by hand.

Leave a Reply