In django I want to allow a query string of the form ?...&lang=&... to set the current url. Ideally the lang= would be removed from the query string, and the session language key set to the new language.
The eventual resulting url would be the url the browser lands on. This should happen for every url on the site, in addition to the other language selection methods that i18n makes available (so I guess this would be a middleware).
I rather dislike the POST to view approach that appears to be the standard for django-i18n.
Does anything like this exist already?
Django Middleware language change query string ?hl=langcode
https://gist.github.com/teury/5d2213181ed0abe06c316c19431f355e
import django
from django.utils import translation
from django.shortcuts import redirect, reverse
def is_django_greater_than_1_10():
main_version = django.VERSION[0]
if main_version > 1:
return True
sub_version = django.VERSION[1]
if main_version == 1 and sub_version >= 10:
return True
return False
if is_django_greater_than_1_10():
from django.utils.deprecation import MiddlewareMixin
superclass = MiddlewareMixin
else:
superclass = object
class LanguageMiddleware(superclass):
def process_response(self, request, response):
if request.resolver_match.view_name is "home":
lang_url = request.GET.get('hl')
if not lang_url:
return response
current_language = translation.get_language()
if lang_url == current_language:
return response
translation.activate(lang_url)
request.session[translation.LANGUAGE_SESSION_KEY] = lang_url
return redirect(reverse('home') + '?hl=' + lang_url)
else:
return response
I have implemented this system in a single "home" url
change the language according to the key value
Traslate by Google. Idioma nativo = Español
After reading the Django documentations, and realising that the Django devs appear to also be in the business of enforcing their own coding standards (and here I am thinking specifically at this comment in the source code:
Since this view changes how the user will see the rest of the site, it must
only be accessed as a POST request. If called as a GET request, it will
redirect to the page in the request (the 'next' parameter) without changing
any state.
) I decided to go with the solution outlined in this post, which I am pasting below (almost) verbatim (hence the non semantic table layout):
<div id="languages">
<table >
<tr>
{% get_available_languages as languages %}
{% for key, item in languages %}
<td>
<form action="/i18n/setlang/" method="post">
{% csrf_token %}
<input type="hidden" name="language" value="{{key}}"/>
<input id="lang_select_{{key}}" type = "image" src="/media/img/{{ key }}.gif" alt="{{ item }}"/>
</form>
</td>
{% endfor %}
</tr>
</table>
</div>
I also came up with my own JS solution which is a little more flexible and vastly more complicated, so it's not really worth it (though it gives links: but since they need an onClick attribute, or moral equivalent, they are useless for SEO purposes).
Of course yanking the code and removing the dumbass GET limitation is also an option - though a higher maintainence one.
P.S: Those who find my comment above adversarial (and also, no doubt, my quest misguided) should consider how the stance that requires POST to switch language flies in the face of SE traversal, while forcing jumps through this kind of hoops to honor the established design convention of allowing the user to switch language by clicking on flag icons.