I have the following menu to change languages in my site:
<div class="btn-group navbar-right language menu">
<button class="btn btn-secondary btn-sm dropdown-toggle language-btn" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{% get_language_info for LANGUAGE_CODE as lang %}
{{ lang.name_local }} ({{ lang.code }})
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenu2">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<ul class="language-item">
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ request.get_full_path }}" />
<input name="language" type="hidden" value="{{ language.code }}" />
<input type="submit" value="{{ language.name_local }} ({{ language.code }})" /> <span>{% if language.code == LANGUAGE_CODE %}✓{% endif %}</span>
</form>
</ul>
{% endfor %}
</div>
</div>
Being shown like
This works the same than the form suggested by Django docs but avoiding the "Go" button to switch languages.
It usually switches languages properly, except in certain cases, as I found out after a user reported the problem.
If the user gets to my site via www.mydomain.com
, it will be redirected to www.mydomain.com/en/
(or /es/
or /de/
) and as far as I know, changing languages works as expected.
However, if the user gets to my site via www.mydomain.com/es/
, then when trying to change the language through the menu, www.mydomain.com/es/
is loaded again. The same behavior occurs with www.mydomain.com/de/
.
Strange enough, when entering my site via www.mydomain.com/en/
, changing languages works properly. Maybe because it is the default language?
I am able to replicate the issue consistently if entering the site through an incognito window. If I do it through a normal window, it is a similar behavior, but not always consistent. For instance, sometimes entering via www.mydomain.com/en/
will not let me change the language either. This makes me think it might have something to do with cookies. But this is as far as I got.
I checked for similar problems during hours and the only similar thing I found is the Django ticket In some cases i18n set_language does not change url language. Its conclusion is:
...I recreated the issue: we set a language (once) then try to reverse a URL from the old language when setting the language again.
This obviously fails.
Workarounds:
- keeping track of the old language and falling back to try that if the lookup with the current language fails.
- Signalling across browser tabs that we already changed the language and adjusting accordingly (???).
Both of these are out of scope for the in-built i18n. (The first would be possible on a project level — reimplementing e.g. set_language — if it was deemed cost effective.)
I'm going to close this on that basis.
I am not sure if it is the same case, as I don't understand why it "obviously fails". As I see it, the obvious behavior should be to change the language.
I am surprised that such a basic feature does not work, so probably I am missing something.
Why is it not working in the cases described? Any help would be appreciated.
Edit 1:
Previously I was using translated URLs instead of the form, as suggested here. However, this was taking 1 second to render due to the translation of the slug. This is why I decided to change