Jinja
Internationalization
Jinja includes support for internationalized templates. Because usually the application includes i18n/l10n code too there is no script to collect translatable strings and no default translation interface. A simple implementation wouldn't fit into every application so there are a few things you have to do.
Writing A Translator
The most important thing is writing a translator and subclassing the Environment so that Jinja knows about the translator. Then you have to think of how to resolve the current language. You probably use Jinja in a multithreaded environment where each thread (request) might want to have a different language. The best way is putting the current language into the context, this can work automatically if you create a helper function for template rendering. But that's up to you.
However. For many web applications this might be a way:
from jinja import Environment from myapplication import get_translator class ApplicationTranslator(object): def __init__(self, language): self.language = language self.translator = get_translator(language) def gettext(self, string): return self.translator.ugettext(string) def ngettext(self, singular, plural, n): return self.translator.ungettext(singuarl, plural, n) class ApplicationEnvironment(Environment): def get_translator(self, context): return ApplicationTranslator(context['LANGUAGE']) env = ApplicationEnvironment() tmpl = env.get_template('index.html') tmpl.render(LANGUAGE='de_DE')
This example assumes that you use gettext and have a gettext Translations object which is returned by the get_translator function. But you don't have to use gettext. The only thing Jinja requires is an object with to functions/methods on it that return and accept unicode strings: gettext(string) that takes a string, translates and returns it, a ngettext(singular, plural, count) function that returns the correct plural form for count items. Because some languages have no or multiple plural forms this is necessary.
Translator Factory
With Jinja 1.2 onwards it's possible to use a translator factory instead of an enviornment subclass to create a translator for a context. A translator factory is passed a context and has to return a translator. Because of the way classes work you can also assign a translator class that takes a context object as only argument as factory.
Example:
from jinja import Environment from myapplication import get_translator def translator_factory(context): return get_translator(context['LANGUAGE']) env = ApplicationEnvironment(translator_factory=translator_factory) tmpl = env.get_template('index.html') tmpl.render(LANGUAGE='de_DE')
This example assumes that the translator returned by get_translator already has a gettext and ngettext function that returns unicode strings.
Collecting Translations
The next step is to collect the translations. Every Jinja environment provides a function called get_translations which collects all translatable strings from an template.
Example:
>>> env.get_translations('index.html') [(1, u'foo', None), (2, u'Foo', None), (3, u'%(count)s Foo', u'%(count)s Foos')]
The first item in the tuple is the linenumer, the second one is the singular form and the third is the plural form if given.
Because Jinja is not bound to gettext you can now use these strings to create translation files for any translation system.
New in Jinja 1.1 You can now extract translations from strings according to the current envrionment settings too by using the environment method get_translations_for_string which takes a string containing a template as only argument. The return value is the same as for get_translations.