Some tips for developers using PlacelessTranslationService to do i18n (Internationalization).
PTS can be used to translate Page Templates, DTML, and python code. Current docs only address the first. Here are quick notes on the others:
Translating python product code
Here's how to translate python product code with PTS:
from Products.PlacelessTranslationService.MessageID import MessageIDFactory
_ = MessageIDFactory('youri18ndomain')
print _("string to be translated")
Translating python scripts
In ZODB-based Python Scripts(s) and ControllerPythonScript?(s), it's just the same as above.
We think. I actually can only see it working with some po's. Last attempt with a breakpoint showed PTS not knowing the target language.
In CMF/Plone, you could also try _ = context.translate.
For extraction, you can copy the scripts to the filesystem, add a .py suffix, then extract the messages in the usual way, at least if using i18nextract.py.
Translating DTML
Basic DTML translation works out of the box, like this:
<dtml-translate domain=yourdomain>some message</dtml-translate> <dtml-translate domain=yourdomain msgid=some_message>some long message..</dtml-translate>
Here's a hack for extracting DTML messages:
dtmlextract:
echo '<div i18n:domain="yourdomain">' >skins/dtmlmessages.pt
find skins content -name "*dtml" | xargs perl -n -e '/<dtml-translate domain="?yourdomain"?>(.*?)<\/dtml-translate>/ and print "<span i18n:translate=\"\">$$1<\/span>\n";' >>skins/dtmlmessages.pt
echo '</div>' >>skins/dtmlmessages.pt
Then run i18nextract or i18ndude as normal, so that they pick up the messages from dtmlmessages.pt. This expects the entire dtml-translate to be on one line, and no more than one dtml-translate per line.
Fixing the character encoding
As of Zope 2.7, you must also set a Content-type HTTP header so that content is published with the appropriate character encoding, otherwise accented characters will tend to be displayed as junk. Here's how - note these examples hard-code utf-8 everywhere.
In page templates (note the double semicolon):
<head tal:define="dummy python:
request.RESPONSE.setHeader('Content-Type','text/html;; charset=utf-8')
In dtml (nb if you are rendering dtml within a page template for some reason, you'll need both of these):
<dtml-call "RESPONSE.setHeader('Content-Type','text/html; charset=utf-8')">
In python code:
self.REQUEST.RESPONSE.setHeader('Content-Type','text/html; charset=utf-8')
Here's a hack to put in your product if you have a lot of i18n'd python code:
from Products.PlacelessTranslationService.MessageID import MessageIDFactory
from Products.PlacelessTranslationService.PatchStringIO import get_request
class MessageIDFactoryWithUtf8Fix(MessageIDFactory):
"""
A hacky wrapper to ensure utf-8 encoding whenever _ is used.
"""
def __call__(self, ustr, default=None):
get_request().RESPONSE.setHeader('Content-Type','text/html; charset=utf-8')
return MessageIDFactory.__call__(self,ustr,default)
_ = MessageIDFactoryWithUtf8Fix('yourdomain') etc..
If you are internationalising a mail message - a password reminder, registration confirmation or whatever - add a mail header like this, as a hint to mail clients which otherwise tend to display messages as iso8859-1:
Content-Type: text/plain; charset="utf-8"
More extraction examples
See the pot, po and mo rules in the Zwiki ZopeProductMakefile for some examples of i18n command-lines.