Zope, Formulator, Localization, and the Solution to Translating Option Values
So you set up a nice little form with Formulator on Zope? And you went ahead and provided multilingual content with Zope Page Templates (ZPT) and TranslationService, translating all the text snippets on the page and even the form element titles and texts with the i18n:translate syntax. Well done. At least until you get stuck on the "option" values in "select" fields that you have done in Formulator. How do you translate those? There is no place to put the i18n-attributes in your ZPT and you don't want to make the form manual again after setting it up with Formulator. Read on for the solution:
Older versions of Formulator seem to have had some hook for i18n-Translationservice, but according to the HISTORY.txt-file that's gone (with only an obscure remark that it can be better replaced with i18n:translate - which you are already using, except for the option values). It's really OK for this to be gone, but some more info for the solution is necessary.
What you need is the "TALES" tab in the Formulator management screens. For the field in question, you have to access the Localizer-translation with the TAL "python:" syntax. Provided you have added a MessageCatalog called "MessageCatalog" (just like you have to set it up for the TranslationService), you would use:
python:here.MessageCatalog.gettext('Name of text in MessageCatalog')
A short explanation might be needed if you don't have much experience with MessageCatalogs and translation through Localizer: What happens is not really that the text gets "translated". The idea is that the MessageCatalog holds text snippets in multiple languages for a project. The "names" of the text snippets might be the original text in one language ("Thank you for providing us with this information") or they might be an abbreviated identifier for the text ("thank you note bottom"). The "gettext" method and the ZPT/TranslationService "i18n:translate" syntax do a lookup in the MessageCatalog and return a suitable string for the "current" language. A string which you or someone else has entered into the MessageCatalog.
This TAL/python example works well for Text fields, but fails for any kind of list field. The reason is that Formulator expects a python list as a result, and what it gets is a string. So it turns each character into a list item and in your popup menu you can choose such informative items as "b" instead of "blue".
My solution was to make a python script (called "translateme"), which contains:
Parameters: snippet='default option list' import string return string.split(context.MessageCatalog.gettext(snippet),'||')
The script is called from the "TALES" tab of Formulator with:
python:here.translateme('optionlist')
As you noticed I've set up one parameter for the script. I'm using a
default value, because most option lists are the same for this project.
But you don't have to use that obviously. Then I get the translated text
snippet out of my message catalog. In the MessageCatalog, I use "||" to
separate the items of the option list. The "string.split" part in the
script is responsible for making a list out of that, just like
Formulator expects.
So, now I hope this is helpfull for someone else running into this or a similar problem. At least it will serve as a reminder for myself :-)