/ / Changer de langue dans le modèle jinja - django, modèles, internationalisation, jinja2, babel

Changer de langue dans le modèle jinja - django, modèles, internationalisation, jinja2, babel

Je migre une application multilingue Django du moteur de modèle de Django vers Jinja2. Dans les modèles, je change actuellement de langue active pour chaque objet en utilisant Django "s language balise de modèle c'est à dire.:

{% load i18n %}
<h1>{% trans "Page title" %}</h1>
<ul>
{% for obj in object_list %}
{% language obj.language_code %}
<li><a href="{{ obj.get_absolute_url }}">{% trans "view" %}: {{ obj.title }}</a>
{% endlanguage %}
{% endfor %}
</ul>

Nous utilisons aussi i18n_patterns les URL de chaque objet sont donc également spécifiques à la langue.

Je ne sais pas comment convertir cela en Jinja. Je ne peux pas utiliser les balises de template i18n de Django et je ne trouve pas d’équivalent pour Jinja.

Je regardais aussi Babel pour aider à extraire des messages à partir des modèles. Une solution compatible avec Babel et Django serait donc préférable.

Réponses:

2 pour la réponse № 1

J'ai cet extrait de code pour basculer entre les langues dans jinja2.

def change_lang(request, lang=None, *args, **kwargs):
"""
Get active page"s url by a specified language, it activates
Usage: {{ change_lang(request, "en") }}
"""

path = request.path
url_parts = resolve(path)

url = path
cur_language = get_language()
try:
activate(lang)
url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
finally:
activate(cur_language)

return "%s" % url

dans settings.py

TEMPLATES = [
{
"BACKEND": "django_jinja.backend.Jinja2",
"DIRS": [
os.path.join(BASE_DIR, "templates/jinja"),
],
"OPTIONS": {
# Match the template names ending in .html but not the ones in the admin folder.
"match_extension": ".html",
"match_regex": r"^(?!admin/).*",
"newstyle_gettext": True,
"extensions": [
"jinja2.ext.do",
"jinja2.ext.loopcontrols",
"jinja2.ext.with_",
"jinja2.ext.i18n",
"jinja2.ext.autoescape",
"django_jinja.builtins.extensions.CsrfExtension",
"django_jinja.builtins.extensions.CacheExtension",
"django_jinja.builtins.extensions.TimezoneExtension",
"django_jinja.builtins.extensions.UrlsExtension",
"django_jinja.builtins.extensions.StaticFilesExtension",
"django_jinja.builtins.extensions.DjangoFiltersExtension",
],
"globals": {
"change_lang": "drug.utils.change_lang"
},
"bytecode_cache": {
"name": "default",
"backend": "django_jinja.cache.BytecodeCache",
"enabled": False,
},
"autoescape": True,
"auto_reload": DEBUG,
"translation_engine": "django.utils.translation",
"context_processors": [
"dashboard.context_processors.auth",
# "django.template.context_processors.debug",
"django.template.context_processors.i18n",
# "django.template.context_processors.media",
# "django.template.context_processors.static",
# "django.template.context_processors.tz",
"django.contrib.messages.context_processors.messages",
]
}
},
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
os.path.join(BASE_DIR, "templates"),
],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
]
},
},]

et alors vous pouvez l'utiliser n'importe où dans vos modèles {{ _("Hello World") }}


2 pour la réponse № 2

Il s’avère que c’est assez simple de faire cela en écrivant une extension jinja2 personnalisée (j’ai basé cela sur la exemple dans la documentation jinja2):

from django.utils import translation
from jinja2.ext import Extension, nodes

class LanguageExtension(Extension):
tags = {"language"}

def parse(self, parser):
lineno = next(parser.stream).lineno
# Parse the language code argument
args = [parser.parse_expression()]
# Parse everything between the start and end tag:
body = parser.parse_statements(["name:endlanguage"], drop_needle=True)
# Call the _switch_language method with the given language code and body
return nodes.CallBlock(self.call_method("_switch_language", args), [], [], body).set_lineno(lineno)

def _switch_language(self, language_code, caller):
with translation.override(language_code):
# Temporarily override the active language and render the body
output = caller()
return output

# Add jinja2"s i18n extension
env.add_extension("jinja2.ext.i18n")
# Install Django"s translation module as the gettext provider
env.install_gettext_translations(translation, newstyle=True)
# Add the language extension to the jinja2 environment
environment.add_extension(LanguageExtension)

Avec cette extension en place, changer de langue de traduction active est à peu près exactement comme vous le feriez dans Django:

{% language "en" %}{{ _("Hello World"){% endlanguage %}

Le seul inconvénient est que lorsqu’on utilise Django en tant que fournisseur gettext et Babel en tant qu’extracteur de messages, il est important de demander à Babel de définir le domaine de messages sur django en cours d'exécution init/update/compile_catalog.