Hello, Does anyone have feedback about i18n with BFG? I have a working solution (see below) but wonder if it could not be improved. If someone has any suggestion, I am willing to turn this (very crude) step-by-step guide to a proper and more detailed tutorial within the BFG docs if it may be useful.
Obviously, only steps 3 and from 8 onwards are interesting. --- start --- 1. Install "zope.i18n": easy_install -i http://dist.repoze.org/bfg/current/simple zope.i18n 2. Make sure you have the latest version of zope.component (should be greater or equal to 3.8.0 to avoid unnecessary dependencies). 3. Add the attached "i18n.py" file in your package. 4. Add i18n markers in your template, e.g. (supposing this is a ZPT): <h1 i18n:domain="myapp" i18n:translate="">Welcome!</h1> 5. Create the following directory hierarchy in your package (supposing you want a translation in French): myapp/locales/fr/LC_MESSAGES/ 6. In each ".../LC_MESSAGES", add a translation file, say "myapp.po". It uses the "gettext" standard. (Looking at an <a href=existing file is usually the best way to get started: https://svn.plone.org/svn/collective/collective.facetednavigation/trunk/src/collective/facetednavigation/locales/fr/LC_MESSAGES/collective.facetednavigation.po). Add this message id: msgid "Welcome!" msgstr "Bienvenue !" Be sure to indicate the same domain in this file and in the template (cf. "i18n:domain" tag). 7. Compile this file with msgfmt: msgfmt -o "myapp.mo" -v "myapp.po" 8. In your "configure.zcml", add the following directive. It will register "*.po" files on startup. <include package="zope.i18n" file="meta.zcml" /> <i18n:registerTranslations directory="locales"/> 9. In "run.app()" function, add this after the loading of the ZCML file. from zope.component import queryUtility from zope.i18n.interfaces import ITranslationDomain from myapp.i18n import AVAILABLE_LANGUAGES util = queryUtility(ITranslationDomain, name='myapp') for lang in util._catalogs.keys(): AVAILABLE_LANGUAGES.add(lang) 10. In your views, instead of calling "repoze.bfg.chameleon_zpt.render_template_to_response()", call this method: from repoze.bfg.chameleon_zpt import render_template_to_response as base_render from myapp.i18n import getPreferredLanguage def render_template_to_response(template, request, **kwargs): kwargs.update(target_language=getPreferredLanguage(request)) return base_render(template, **kwargs) 11. Run your application, test it and rant about me having forgotten something. --- end --- -- Damien Baty
DEFAULT_LANGUAGE = 'en' AVAILABLE_LANGUAGES = set([DEFAULT_LANGUAGE]) ## will be set by 'run.app()' def getPreferredLanguage(request, available_languages=None): """Return the user's preferred language (among those that are available in this application). ``available_languages`` is for test usage only. """ if available_languages is None: available_languages = AVAILABLE_LANGUAGES ## FIXME (future): add the possibility to switch language (and ## store value in a cookie) accepts = request.headers.get('Accept-Language', None) if not accepts: return DEFAULT_LANGUAGE ## The following may not be absolutely bullet-proof, but that ## should be enough. (Otherwise, we may use 'parse_accept()' from ## 'webob.acceptparse'.) for part in accepts.split(','): lang = part.split(';')[0].strip() if lang in available_languages: return lang lang = lang.split('-')[0] if lang in available_languages: return lang return DEFAULT_LANGUAGE
_______________________________________________ Repoze-dev mailing list Repoze-dev@lists.repoze.org http://lists.repoze.org/listinfo/repoze-dev