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-адреса загружаются очень быстро.

Другие вопросы по тегам