set_language не меняет язык в некоторых случаях (django)
У меня есть следующее меню для смены языков на моем сайте:
<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>
Показывается как
Это работает так же, как форма, предложенная Django docs, но избегая кнопки "Перейти" для переключения языков.
Обычно он переключает языки должным образом, за исключением некоторых случаев, как я узнал после того, как пользователь сообщил о проблеме.
Если пользователь попадает на мой сайт через www.mydomain.com
, он будет перенаправлен на www.mydomain.com/en/
(или же /es/
или же /de/
) и, насколько я знаю, смена языков работает, как ожидалось.
Однако, если пользователь попадает на мой сайт через www.mydomain.com/es/
затем при попытке изменить язык через меню, www.mydomain.com/es/
загружается снова. Такое же поведение происходит с www.mydomain.com/de/
,
Как ни странно, при входе на мой сайт через www.mydomain.com/en/
, изменение языков работает правильно. Может потому что это язык по умолчанию?
Я могу постоянно повторять проблему, если захожу на сайт через окно инкогнито. Если я делаю это через обычное окно, это аналогичное поведение, но не всегда последовательное. Например, иногда входя через www.mydomain.com/en/
не позволит мне изменить язык либо. Это заставляет меня думать, что это может иметь отношение к куки. Но это насколько я понял.
Я проверял наличие подобных проблем в течение нескольких часов, и единственное, что я нашел, это билет Django. В некоторых случаях i18n set_language не меняет язык URL. Его вывод таков:
... Я воссоздал проблему: мы устанавливаем язык (один раз), а затем пытаемся изменить URL-адрес со старого языка при повторной установке языка.
Это явно не удается.
обходные:
- отслеживание старого языка и отступление, чтобы попробовать это, если поиск с текущим языком не удался.
- Сигнализация через вкладки браузера, что мы уже поменяли язык и соответственно настроили (???).
Оба из них выходят за рамки встроенного i18n. (Первое будет возможно на уровне проекта - переопределение, например, set_language - если это будет сочтено экономически эффективным.)
Я собираюсь закрыть это на этом основании.
Я не уверен, что это тот же случай, так как я не понимаю, почему это "явно не удается". На мой взгляд, очевидным поведением должно быть изменение языка.
Я удивлен, что такая базовая функция не работает, поэтому, вероятно, я что-то упустил.
Почему это не работает в описанных случаях? Любая помощь будет оценена.
Изменить 1:
Ранее я использовал переведенные URL-адреса вместо формы, как предложено здесь. Тем не менее, это заняло 1 секунду, чтобы сделать из-за перевода слаг. Вот почему я решил изменить
3 ответа
У меня возникла та же проблема. Это все еще существующая проблема, когда django, по-видимому, не переводит заголовок HTTP-реферера.
См. Исходный код set_language на Django
Способ обойти это - отправить скрытое поле ввода с именем next
который вы установили на тот же URL-адрес, на котором находитесь (request.get_full_path
), но замените текущую языковую часть языком, на который вы собираетесь переключиться.
Вот фрагмент переключателя языка, решающего эту проблему:
<li {% if current_language|slice:":2" == 'en' %} class="active"{% endif %}>
<form method="POST" action="{% url 'set_language' %}" autocomplete="off">
{% csrf_token %}
<span class="language-code">en</span>
<input type="submit" name="language" value="en">
<input type="hidden" name="next" value="{{ request.get_full_path|replace_language:"en" }}">
</form>
</li>
<li{% if current_language|slice:":2" == 'da' %} class="active"{% endif %}>
<form method="POST" action="{% url 'set_language' %}" autocomplete="off">
{% csrf_token %}
<span class="language-code">dk</span>
<input type="submit" name="language" value="da">
<input type="hidden" name="next" value="{{ request.get_full_path|replace_language:"da" }}">
</form>
</li>
Затем вы можете реализовать настраиваемый тег шаблона с именем replace_language, который проходит через настроенные вами языки и заменяет его аргументом.
Надеюсь это поможет:-)
Решил проблему, удалив код языка из «следующего» ввода (вырежьте текущий код языка из URL-адреса)
Следующий ввод:
<input name="next" type="hidden" value="{{ request.get_full_path|slice:"3:" }}">
Весь выпадающий список:
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<div class="row g-2">
<div class="col col-sm-12 col-lg-3 col-md-4">
<div class="form-floating">
<input name="next" type="hidden" value="{{ request.get_full_path|slice:"3:" }}">
<select class="form-select" name="language" onchange="this.form.submit()" id="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<label for="language">Language</label>
</div>
</div>
</div>
</form>
Для дальнейшего использования я просто вернулся к использованию переведенных URL-адресов, как предлагается здесь, вместо формы.
Я узнал, что делает это так медленно. Оказалось, что это можно оптимизировать, поэтому теперь переведенные URL-адреса загружаются очень быстро.