Sprachabhängige Template-Imports

Zuerst die Erklärung, der vollständige Code folgt am Ende.

Um Internationalisierung (i18n) bzw. Übersetzung in Django-Templates zu bringen, gibt es verschiedene Möglichkeiten, allen voran die Möglichkeit, Strings mittels trans oder blocktrans zu markieren und in den entsprechenden gettext-Dateien zu übersetzen.

Das funktioniert gut und hat sich bewährt, solange es sich um Strings handelt. Möchte man eine komplette Seite übersetzen, inkl. Bildern und HTML-Code, wird es schwieriger, mal abgesehen davon, dass ich HTML in gettext-Strings einfach häßlich finde.

Eine Möglichkeit ist es, ifequal mit dem aktuellen Sprachcode des Users (LANGUAGE_CODE) zu vergleichen:

{% ifequal LANGUAGE_CODE "de" %}
    <p>Hier ganz viel deutscher Text.</p>
{% else %}
    <p>Here is a lot of english text, the default language.</p>
{% endif %}

Wird der Inhalt zu lang, kann man die Texte jeweils in eigene Templates auslagern und mittels include importieren:

{% ifequal LANGUAGE_CODE "de" %}
    {% include "vieltext_deutsch.html" %}
{% else %}
    {% include "vieltext_english.html" %}
{% endif %}

Hier setzt der unten gezeigte Templatetag an. Er arbeitet prinzipiell wie der Standard-Include-Tag aber importiert automatisch das Template mit der jeweiligen Sprache.

Der Templatename muss dabei das Format <templatename>.<languagecode> als Dateinamen besitzen. Angenommen unser User ist mit deutscher Spracheinstellung unterwegs und sein LANGUAGE_CODE wäre de, der Aufruf:

{% langinclude "meintext.html" %}

würde hier zuerst das Template meintext.html.de suchen und importierten. Schlägt dies fehl, importiert es wie gewohnt das Template meintext.html.

Hier nun der Templatetag:

from django.template import Library, Node
from django.template import TemplateSyntaxError, TemplateDoesNotExist, Variable
from django.template.loader_tags import IncludeNode
from django.template.loader import get_template
from django.conf import settings

register = Library()

class ConstantLanguageIncludeNode(Node):
    def __init__(self, template_path):
        self.template_path = template_path

    def render(self, context):
        try: 
            t = get_template('%s.%s' % (self.template_path, context['LANGUAGE_CODE']))
        except TemplateDoesNotExist, KeyError:
            t = get_template(self.template_path)
        except:
            if settings.TEMPLATE_DEBUG:
                raise
            return ''
        return t.render(context)

def do_language_include(parser, token):
    """
    Looks up for a template based on the template-name plus the current users language code.
    Loads the template and renders it with the current context.

    Example::

        {% langinclude "foo/some_include.html" %}

    Based on the users LANGUAGE_CODE, assumed we have 'de', it tries to render the
    template 'foo/some_include.html.de'. If that doesn't exists, it renders the 
    template 'foo/some_include.html'. This is the default behavior of the include-Tag.

    Basically this is a shortcut for the following code, just with a fallback for the
    default template::

        {% ifequal LANGUAGE_CODE "de" %}
            {% include "foo/some_include.html.de" %}
        {% else %}
            {% include "foo/some_include.html" %}
        {% endifequal %}
    """
    bits = token.contents.split()
    if len(bits) != 2:
        raise TemplateSyntaxError, "%r tag takes one argument: the name of the template to be included" % bits[0]
    path = bits[1]
    if path[0] in ('"', "'") and path[-1] == path[0]:
        return ConstantLanguageIncludeNode(path[1:-1])
    return IncludeNode(bits[1])

register.tag('langinclude', do_language_include)

Der Quellcode auf djangosnippets.org.



↑ to the elevators

© 2001—2012 Martin Mahner. This is an I ♥ Django Project.

Admin | Generated: Sun, 5 Feb 2012 09:34:23 +0100