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.