From ba1a8a510b05074731d383e0dc1f7c21c67ff728 Mon Sep 17 00:00:00 2001 From: Michael Elsdoerfer Date: Sat, 27 Feb 2010 06:33:42 +0100 Subject: [PATCH] Added a custom makemessages command (wrapping the original) that supports string extraction from Jinja2's {% trans %} tags. --- README.rst | 16 +++++--- coffin/management/__init__.py | 0 coffin/management/commands/__init__.py | 0 coffin/management/commands/makemessages.py | 48 ++++++++++++++++++++++ 4 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 coffin/management/__init__.py create mode 100644 coffin/management/commands/__init__.py create mode 100644 coffin/management/commands/makemessages.py diff --git a/README.rst b/README.rst index 291a8f7..ec30abc 100644 --- a/README.rst +++ b/README.rst @@ -36,11 +36,15 @@ Django filters that are ported in Coffin: - truncatewords_html The template-related functionality of the following contrib modules has -been ported in Coffin: +been ported in Coffin: - ``coffin.contrib.markup`` - ``coffin.contrib.syndication``. +Jinja 2's ``i18n`` extension is hooked up with Django, and a custom version +of makemessages supports string extraction from both Jinja2 and Django +templates. + Rendering ========= @@ -125,7 +129,7 @@ information. ``coffin.template.loader`` is a port of ``django.template.loader`` and comes with a Jinja2-enabled version of ``get_template()``. -``coffin.template.Template`` is a Jinja2-Template that supports the +``coffin.template.Template`` is a Jinja2-Template that supports the Django render interface (being passed an instance of Context), and uses Coffin's global Jinja2 environment. @@ -175,12 +179,12 @@ never will, requiring manual changes on your part: - The {% autoescape %} tag is immensily difficult to port and currently not supported. - -- Literal strings from within a template are not automatically - considered "safe" by Jinja2, different from Django. According to + +- Literal strings from within a template are not automatically + considered "safe" by Jinja2, different from Django. According to Armin Ronacher, this is a design limitation that will not be changed, due to many Python builtin functions and methods, whichyou are free - to use in Jinja2, expecting raw, untainted strings and thus not being + to use in Jinja2, expecting raw, untainted strings and thus not being able to work with Jinja2's ``Markup`` string. diff --git a/coffin/management/__init__.py b/coffin/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/coffin/management/commands/__init__.py b/coffin/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/coffin/management/commands/makemessages.py b/coffin/management/commands/makemessages.py new file mode 100644 index 0000000..cb53821 --- /dev/null +++ b/coffin/management/commands/makemessages.py @@ -0,0 +1,48 @@ +"""Jinja2's i18n functionality is not exactly the same as Django's. +In particular, the tags names and their syntax are different: + + 1. The Django ``trans`` tag is replaced by a _() global. + 2. The Django ``blocktrans`` tag is called ``trans``. + +(1) isn't an issue, since the whole ``makemessages`` process is based on +converting the template tags to ``_()`` calls. However, (2) means that +those Jinja2 ``trans`` tags will not be picked up my Django's +``makemessage`` command. + +There aren't any nice solutions here. While Jinja2's i18n extension does +come with extraction capabilities built in, the code behind ``makemessages`` +unfortunately isn't extensible, so we can: + + * Duplicate the command + code behind it. + * Offer a separate command for Jinja2 extraction. + * Try to get Django to offer hooks into makemessages(). + * Monkey-patch. + +We are currently doing that last thing. It turns out there we are lucky +for once: It's simply a matter of extending two regular expressions. +Credit for the approach goes to: +http://stackoverflow.com/questions/2090717/getting-translation-strings-for-jinja2-templates-integrated-with-django-1-x +""" + +import re +from django.core.management.commands import makemessages +from django.utils.translation import trans_real + + +class Command(makemessages.Command): + + def handle(self, *args, **options): + old_endblock_re = trans_real.endblock_re + old_block_re = trans_real.block_re + # Extend the regular expressions that are used to detect + # translation blocks with an "OR jinja-syntax" clause. + trans_real.endblock_re = re.compile( + trans_real.endblock_re.pattern + '|' + r"""^\s*endtrans$""") + trans_real.block_re = re.compile( + trans_real.block_re.pattern + '|' + r"""^\s*trans(?:\s+|$)""") + + try: + super(Command, self).handle(*args, **options) + finally: + trans_real.endblock_re = old_endblock_re + trans_real.block_re = old_block_re \ No newline at end of file