La création d'un commutateur de langue qui revient à la page d'accueil dans la langue souhaitée est relativement facile. Le faire revenir à la même page dans la langue souhaitée nécessite un peu plus de travail.
Django possède de nombreux utilitaires liés aux langues. Dans ce tutoriel, on va utiliser certains d'entre eux pour créer un commutateur de langue qu'on peut activer via un lien dans notre menu de navigation et qui renverra la page sur laquelle on était dans la langue choisie. Définir une vue dans notre views.py
qui renvoie la page d'accueil dans la langue choisie est relativement simple:
from django.http import HttpResponseRedirect
from django.utils import translation
def set_language_from_url(request, language_code):
if not language_code in [lang[0] for lang in settings.LANGUAGES]:
return HttpResponseRedirect('/')
next_url = '/' + language_code +'/'
translation.activate(language_code)
response = HttpResponseRedirect(next_url)
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language_code)
return response
Cela suppose qu'on utilise des préfixes de langue pour nos URL. On vérifie d'abord si le language_code
souhaité est dans les LANGUAGES
de nos paramètres. Ensuite, on définit l'URL de la page d'accueil, la langue et définit un cookie de langue.
Si on veut revenir à la page où on était, mais dans une langue différente, la première chose qu'on doit faire est de récupérer la page où on était:
try:
# get the full path of the referring page; go back if requested language equals current language
previous = request.META['HTTP_REFERER']
if language_code == translation.get_language():
return HttpResponseRedirect(previous)
CODE FOLLOWS
except KeyError:
# if for some reason the previous page cannot be found, go to the home page
next_url = '/' + language_code +'/'
Si on ne peut pas trouver une page précédente, on revient par défaut à la page d'accueil. S'il y a une page précédente et la langue actuelle est déjà la langue demandée, alors on revient immédiatement. On récupère la langue courante avec la fonction get_language
de Django.
Maintenant, il y a deux options: soit previous
appartient à une page qui fait partie de l'arbre Wagtail, soit elle n'appartient pas. Pour trouver previous
dans l'arbre Wagtail, il faut un peu d'ingénierie d'URL. Commencez par séparer le chemin de l'URL avec la fonction urlparse
de Python:
from urllib.parse import urlparse
prev_path = urlparse(previous).path
Maintenant, on peut rechercher cela dans l'arbre Wagtail, en utilisant le champ url_path
. Cependant, il y a une petite complication: dans les sites multilingues, wagtailtrans a préfixé le chemin racine traduisible à url_path
. On peut trouver le site actuel en utilisant la méthode find_for_request
du modèle de site de Wagtail. Donc notre recherche devient (les deux chemins ont un début et une fin /
, on en supprime un avec le slice [1:]
):
from wagtail.core.models import Site
prev_url_path = Site.find_for_request(request).root_page.url_path + prev_path[1:]
prev_page = TranslatablePage.objects.get(url_path=prev_url_path)
Maintenant, on peut récupérer la version traduite de cette page en utilisant les champs canonical_page
et language
du modèle TranslatablePage
,
comme on l'a fait dans notre menu de navigation.
can_page = prev_page.canonical_page if prev_page.canonical_page else prev_page
language = Language.objects.get(code=language_code)
next_url = can_page.url if language_code == settings.LANGUAGE_CODE else TranslatablePage.objects.get(language=language, canonical_page=can_page).url
Cela termine le cas où la page précédente fait partie de l'arbre Wagtail. Les pages multilingues de notre projet en dehors de l'arbre doivent être construites avec des modèles i18n. Django fournit une fonction pour traduire leurs URL:
from django import urls
next_url = urls.translate_url(previous, language_code)
Cette fonction est également utilisée dans l'implémentation de set_language
de Django. Si translate_url
ne trouve pas de traduction, il renvoie l'url d'origine. On a déjà pris soin du cas où language_code
est égal à la langue actuelle, donc si cela se produit alors apparemment il n'y a pas de traduction. Dans ce cas, on redirige vers la page d'accueil:
if next_url == previous:
next_url = '/' + language_code + '/'
La combinaison de ces deux cas et la gestion des exceptions nous donne le code complet qu'on met dans le fichier views.py
de notre application:
from django import urls
from django.conf import settings
from django.http import HttpResponseRedirect
from django.utils import translation
from urllib.parse import urlparse
from wagtail.core.models import Site
from wagtailtrans.models import TranslatablePage, Language
def set_language_from_url(request, language_code):
if not language_code in [lang[0] for lang in settings.LANGUAGES]:
return HttpResponseRedirect('/')
try:
# get the full path of the referring page; go back if requested language equals current language
previous = request.META['HTTP_REFERER']
if language_code == translation.get_language():
return HttpResponseRedirect(previous)
try:
# split off the path of the previous page
prev_path = urlparse(previous).path
# wagtailtrans prefixes the translatable root's url_path, so we need to do that as well
prev_url_path = Site.find_for_request(request).root_page.url_path + prev_path[1:]
prev_page = TranslatablePage.objects.get(url_path=prev_url_path)
# if the current page is not canonical, get the canonical page
can_page = prev_page if prev_page.is_canonical else prev_page.canonical_page
# if the requested language is the canonical (default) language, use the canonical page, else find the translated page
language = Language.objects.get(code=language_code)
next_url = can_page.url if language_code == settings.LANGUAGE_CODE else TranslatablePage.objects.get(language=language, canonical_page=can_page).url
except (TranslatablePage.DoesNotExist, Language.DoesNotExist):
# previous page is not a TranslatablePage, try if previous path can be translated by changing the language code
next_url = urls.translate_url(previous, language_code)
# if no translation is found, translate_url will return the original url
# in that case, go to the home page in the requested language
if next_url == previous:
next_url = '/' + language_code + '/'
except KeyError:
# if for some reason the previous page cannot be found, go to the home page
next_url = '/' + language_code +'/'
translation.activate(language_code)
response = HttpResponseRedirect(next_url)
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language_code)
return response
Dans l'urls.py
de notre application, on crée un chemin vers cette fonction:
from django.urls import path
from .views import set_language_from_url
urlpatterns = [
path('<str:language_code>/', set_language_from_url, name='set_language_from_url'),
]
On peut inclure ces modèles d'URL dans notre urls.py
du project en ajoutant:
urlpatterns += i18n_patterns(
path('language/', include('cms.urls')),
)
Si on aurait plus d'entrées dans notre urls.py
de l'application, on ferait probablement cela différemment, peut-être créer une application distincte, mais pour l'instant cela suffira. On peut maintenant activer la fonction en créant des liens vers /language/en/
, /language/fr/
etc. où on veut le commutateur de langue. Dans un didacticiel précédent, on a créé un générateur de menus; on peut créer un menu language
, définir les liens de langue pour chaque élément de menu, y ajouter des icônes avec des drapeaux des différentes langues et ajouter ce menu comme entrée à notre menu principal. Ajouter une nouvelle langue à l'avenir est alors juste une question de l'ajouter au menu. Regardez la vidéo pour voir cela en action.
Lisez plus si vous souhaitez autoriser les utilisateurs à ajouter des commentaires aux articles de votre site.
Commentez cet article (connectez-vous d'abord ou confirmez par nom et email ci-dessous)