Issue trying to change language from Django template

前端 未结 7 2128
悲&欢浪女
悲&欢浪女 2020-12-01 06:46

I need to include two buttons or links to allow users change language between English and Spanish. I\'ve read the docs and tried this:

相关标签:
7条回答
  • 2020-12-01 07:32

    Besides adding form that was suggested here:

    <form action="{% url 'set_language' %}" method="post">
      {% csrf_token %}
      {{ request.get_full_path_info|slice:'3:'}}
      <input name="next" type="hidden" value="{{ languageless_url }}" />
      <ul class="nav navbar-nav navbar-right language menu">
        {% get_current_language as LANGUAGE_CODE %}
        {% get_available_languages as LANGUAGES %}
        {% get_language_info_list for LANGUAGES as languages %}
        {% for language in languages %}
        <li>
          <button type="submit" name="language" value="{{ language.code }}"
            class="{% if language.code == LANGUAGE_CODE %}selected{% endif %}">
            {{ language.code }}
          </button>
        </li>
        {% endfor %}
      </ul>
    </form>
    

    I would suggest adding a context processor (app.context_processors.py):

    def language_processor(request):
    """
    This is needed for language picker to work
    """
    return {
        'languageless_url':
        '/' + '/'.join(request.get_full_path().split('/')[2:])
    }
    

    This allows to leave the logic out of template. Also don't forget to add your processor in template settings:

                'context_processors': [
                'app.context_processors.language_processor',
    
    0 讨论(0)
  • 2020-12-01 07:38

    If in your current system you have only 2 languages then simply use like below:

    {% ifequal LANGUAGE_CODE "en" %}
           <a href="/es{{ request.get_full_path }}">Spanish</a>
    {% else %}
           <a href="/en{{ request.get_full_path }}">English</a>
    {% endifequal %}
    

    No need of a form, url and submit etc. It worked for me.

    0 讨论(0)
  • 2020-12-01 07:42
    {% load i18n %}
    
    {% get_current_language as LANGUAGE_CODE %}
    {% get_available_languages as LANGUAGES %}
    {% get_language_info_list for LANGUAGES as languages %}
    
     <div class="btn-header">
        <form action="{% url 'set_language' %}" method="post">
          {% csrf_token %}
          <input name="next" type="hidden" value="{{ redirect_to }}" />
            {% for language in languages %}
                {% if language.code != LANGUAGE_CODE %}
                    <button type="submit" name="language" value="{{ language.code }}">{{ language.name }}</button>
                {% endif %}
            {% endfor %}
        </form>
      </div>
    

    if you have two languages. It will only show you the one that's off.

    https://www.loom.com/share/9319c0e9204f417a8eec897965ce3a96

    0 讨论(0)
  • 2020-12-01 07:46

    A sum-up of possible options:

    Change the user's session language with a select

    There is an excellent extensive description with example on Django docs.

    Change the user's session language with buttons

    There is no need to repeat a form for each button as @Caumons suggested, instead you can simply include as many buttons in the form as the languages.

    <form action="{% url 'set_language' %}" method="post">
        {% csrf_token %}
        <input name="next" type="hidden" value="{{ request.get_full_path|slice:'3:' }}" />
        <ul class="nav navbar-nav navbar-right language menu">
            {% get_current_language as LANGUAGE_CODE %}
            {% get_available_languages as LANGUAGES %}
            {% get_language_info_list for LANGUAGES as languages %}
            {% for language in languages %}
                <li>
                    <button type="submit"
                            name="language"
                            value="{{ language.code }}"
                            class="{% if language.code == LANGUAGE_CODE %}selected{% endif %}">
                        {{ language.name_local }}
                    </button>
                </li>
            {% endfor %}
        </ul>
    </form>
    

    You can certainly style up the buttons to look like links or whatever.

    Change the language displayed with links

    If it is not required that the default user session language is changed, then simple links can be used to change the content:

    <ul class="nav navbar-nav navbar-right language menu">
        {% get_current_language as LANGUAGE_CODE %}
        {% get_available_languages as LANGUAGES %}
        {% get_language_info_list for LANGUAGES as languages %}
        {% for language in languages %}
            <li>
                <a href="/{{ language.code }}{{ request.get_full_path|slice:'3:' }}"
                   class="{% if language.code == LANGUAGE_CODE %}selected{% endif %}"
                   lang="{{ language.code }}">
                    {{ language.name_local }}
                </a>
            </li>
        {% endfor %}
    </ul>
    

    SEO

    I am not entirely sure that the content is seo friendly if a form is used to change the session language, as Django recommends. Therefore it is possible that the link <a> markup is added as hidden below the <button> element.

    0 讨论(0)
  • 2020-12-01 07:46

    Django 3.02

    <div class="uk-flex">
    
        {% get_current_language as LANGUAGE_CODE %}
        {% get_available_languages as LANGUAGES %}
        {% get_language_info_list for LANGUAGES as languages %}
        <div class="languages">
            <p>{% trans "Language" %}:</p>
            <ul class="languages">
            {% for language in languages %}
                <li>
                    <a href="/{{ language.code }}/{{ request.get_full_path |slice:'4:'}}" {% if language.code == LANGUAGE_CODE %} class="selected"{% endif %}>
                    {{ language.name_local }}
                    </a>
                </li>
            {% endfor %}
            </ul>
        </div>
    </div>
    
    0 讨论(0)
  • 2020-12-01 07:50

    After more testing and thanks to the related question linked by @AronYsidoro I've finally found the issue and a very simple solution that actually solves this.

    First, let me explain the problem: When working with i18_patterns in your urls.py to prepend the language code, if you call the URL set_language to change the language without specifying next, it defaults to the current one, but with the prepended old language code! So, the language gets back to the original! And, if you explicitly specify next, you must be sure to do not include the language code at the begining.

    If you use {{ request.path }} or {{ request.get_full_path }} to specify the next as the current page this won't work as it returns the language code too.

    So, how do we remove this undesired language code to reload the current page with the language changed when using i18n_patterns? Easy, we just have to slice the 3 first chars (the slash and the two chars language code)!

    Here you have two examples. The first one in form of a select (with the languages as choices) and the other one in form of a button (per language).

    I really hope this helps someone else. You can just copy and paste the code and it should work. However, if using the "button form", you just have to set the language to your desired!

    Change language from list:

    <form action="{% url 'set_language' %}" method="post">
      {% csrf_token %}
      <input name="next" type="hidden" value="{{ request.get_full_path|slice:'3:' }}" />
      <select name="language">
        {% get_language_info_list for LANGUAGES as languages %}
          {% for language in languages %}
            <option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}>
              {{ language.name_local }} ({{ language.code }})
            </option>
          {% endfor %}
      </select>
      <input type="submit" value="Change" />
    </form>
    

    Change language as button:

    <form action="{% url 'set_language' %}" method="post">
      {% csrf_token %}
      <input name="next" type="hidden" value="{{ request.get_full_path|slice:'3:' }}" />
      <input name="language" type="hidden" value="es" />
      <input type="submit" value="ES" />
    </form>
    
    0 讨论(0)
提交回复
热议问题