Шаблоны Django: Получить текущий URL на другом языке
Я использую i18n_patterns
для создания языковых префиксов в приложении Django.
Мои URL-адреса выглядят следующим образом:
/de/contact/
/fr/contact/
/it/contact/
В моем базовом шаблоне я перебираю все доступные языки, чтобы показать ссылки на языковые ключи.
{% get_available_languages as languages %}
<nav id="language_chooser">
<ul>
{% for lang_code, lang_name in languages %}
{% language lang_code %}
<li><a href="{% url 'home' %}" alt="{{ lang_name }}" title="{{ lang_name }}">{{ lang_code }}</a></li
{% endlanguage %}
{% endfor %}
</ul>
</nav>
В этом случае я перехожу к "домашнему" URL. Есть ли способ получить переведенный URL-адрес текущей страницы?
Если я на немецкой версии моей "контактной" страницы, я хочу, чтобы ссылка "fr" указывала на французскую версию "контактной" страницы, а не на "домашнюю страницу".
Ответы
Ответ 1
Я не использую языковые префиксы, но перевел URL вместо этого. Однако этот тег шаблона также должен помочь вам:
# This Python file uses the following encoding: utf-8
from django import template
from django.core.urlresolvers import reverse # from django.urls for Django >= 2.0
from django.core.urlresolvers import resolve # from django.urls for Django >= 2.0
from django.utils import translation
register = template.Library()
class TranslatedURL(template.Node):
def __init__(self, language):
self.language = language
def render(self, context):
view = resolve(context['request'].path)
request_language = translation.get_language()
translation.activate(self.language)
url = reverse(view.url_name, args=view.args, kwargs=view.kwargs)
translation.activate(request_language)
return url
@register.tag(name='translate_url')
def do_translate_url(parser, token):
language = token.split_contents()[1]
return TranslatedURL(language)
Возвращает текущий URL на желаемом языке. Используйте это так: {% translate_url de %}
Комментарии и предложения по улучшению приветствуются.
Ответ 2
Этот фрагмент должен сделать это:
https://djangosnippets.org/snippets/2875/
После того, как вы добавили это в качестве пользовательского тега шаблона, вы можете сделать что-то вроде:
<a href='{% change_lang 'fr' %}'>View this page in French</a>
Ответ 3
Я думаю, что стоит упомянуть, что есть встроенная функция под названием translate_url
.
from django.urls import translate_url
translate_url(url, lang_code)
Ответ 4
Я думаю, что вы добавляете ненужное усложнение проблемы. То, что вы ищете, - это простой языковой селектор. Django предоставляет эту функциональность из коробки, и она всегда перенаправляется на текущую страницу (на другом языке).
Это описано здесь:
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#django.conf.urls.i18n.set_language
Единственное, что представление set_language
ожидает параметр POST, поэтому вам нужно использовать элемент <form>
; вы не можете использовать простую ссылку <a href="...">
. Однако иногда вы хотите, чтобы селектор языка выглядел как ссылка, а не как форма с выбранным виджетами. Мое предложение состоит в том, чтобы использовать форму, но создавайте ее как ссылку.
Ваш шаблон может выглядеть так:
<nav id="language_chooser">
<ul>
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}" />
<input name="language" type="hidden" value="{{ language.code }}" />
<button type="submit">{{ language.local_name }}"</button>
</form>
{% endfor %}
</ul>
</nav>
И затем вы используете CSS для стилизации форм и отправки кнопок, чтобы они выглядели как обычные ссылки:
ul#language_chooser form {
display: inline;
margin: 0;
padding: 0;
}
ul#language_chooser button {
margin: 0;
padding: 0;
border: none;
background: none;
color: blue; /* whatever you like */
text-decoration: underline; /* if you like */
}
Ответ 5
Используйте django_hreflang:
{% load hreflang %}
<ul>
<li><a href="{% translate_url 'en' %}" hreflang="en">English</a></li>
<li><a href="{% translate_url 'ru' %}" hreflang="ru">Russian</a></li>
</ul>
Ответ 6
Я использую стандартную форму языка из docs
<form action="{% url 'set_language' %}" method="post" id="lang_changer">
{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}" />
<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="Go" />
</form>
и исправление jquery для работы с префиксами url lang:
$('#lang_changer input[name="next"]').attr('value', '/'+window.location.pathname.substring(4));
запускается при готовности страницы.
Ответ 7
Проблема с пользовательским тегом шаблона заключается в том, что функция вычисляет эквивалент другого языка на основе текущего URL-адреса, поскольку я использую пакет переноса модели, тогда слизь всегда была одинаковой между URL-адресами. например:.
example.com/en/article/english-slug
example.com/es/articulo/english-slug
Чтобы исправить это, я использовал несколько иной подход, вычисляя альтернативные URL-адреса на уровне представления и предоставляя их доступным в контексте шаблона.
Чтобы это сработало:
1- Создайте файл utils.py со следующей вспомогательной функцией
from django.utils.translation import activate, get_language
from django.conf import settings
def getAlternateUrls(object):
#iterate through all translated languages and get its url for alt lang meta tag
cur_language = get_language()
altUrls = {}
for language in settings.LANGUAGES:
try:
code = language[0]
activate(code)
url = object.get_absolute_url()
altUrls[code] = url
finally:
activate(cur_language)
return altUrls;
2. Определите ли ваши модели обратный URL-адрес: get_absolute_url
3- Добавьте переменную контекста, которая будет удерживать словарь urls в ваших view.py
from .utils import getAlternateUrls
...
def MyView(DetailView):
def get_context_data(self, **kwargs):
context['alt_urls'] = getAlternateUrls(self.object)
4- Генерировать метатеги альтернативных URL-адресов в разделе заголовка шаблона
<!-- alternate lang -->
{% for key, value in alt_urls.items %}
<link rel="alternate" hreflang="{{ key }}" href="http://{{ request.get_host }}{{ value}}">
{% endfor %}
{% endblock %}
Протестировано в Django 1.8
Ответ 8
Я попытался сделать это как можно проще - использовать динамический reverse()
с любым числом kwargs
, чтобы языковой переключатель (или любой другой подобный материал) перенаправлялся на текущий вид.
Добавлен простой тег шаблона в dir файл templatetags (например, templatetags/helpers.py
):
from django.core.urlresolvers import reverse
register = template.Library()
@register.simple_tag
def get_url_with_kwargs(request):
url_name = ''.join([
request.resolver_match.app_name,
':',
request.resolver_match.url_name,
])
url_kwargs = request.resolver_match.kwargs
return reverse(url_name, None, None, url_kwargs)
Что можно использовать в шаблоне переключения языков следующим образом:
{% load helpers %}
{% get_available_languages as available_languages %}
{% get_language_info_list for available_languages as language_info_list %}
{% for language in language_info_list %}
{% language language.code %}
{% get_url_with_kwargs request as url_with_kwargs %}
<a href="{{ url_with_kwargs }}">{{ language.code }}</a>
{% endlanguage %}
{% endfor %}
Хорошо работает для меня.
Ответ 9
Я бы предпочел прокомментировать принятый ответ, но не могу, поэтому я отправляю свой собственный.
Я использую довольно похожее решение, основанное на:
https://djangosnippets.org/snippets/2875/
Существует проблема, с которой могут столкнуться как методы resolve
, так и reverse
:
-
resolve
может вызвать исключение Resolver404, особенно если вы уже показываете страницу 404 (вместо этого вызывается ошибка 500, очень раздражающая и трудная для обнаружения, особенно с DEBUG = True, не отображающая реальный 404)
-
reverse
может произойти сбой, когда вы пытаетесь получить страницу с другим языком, на самом деле не имеющим перевода.
Возможно, обратное больше зависит от того, какой метод перевода вы используете или что-то еще, но разрешить сбой на 404 странице довольно очевидно.
В случае исключения вы можете захотеть либо вернуть тот же URL-адрес, либо URL-адрес, чтобы индексировать страницу, а не поднимать исключение в шаблоне. Код может выглядеть так:
from django.core.urlresolvers import resolve, reverse
from django.utils.translation import activate, get_language
@register.simple_tag(takes_context=True, name="change_lang")
def change_lang(context, lang=None, *args, **kwargs):
url = context['request'].path
cur_language = get_language()
try:
url_parts = resolve(url)
activate(lang)
url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
except:
url = reverse("index") #or whatever page you want to link to
# or just pass if you want to return same url
finally:
activate(cur_language)
return "%s" % url
Ответ 10
Для Django 2.0 (основано на ответе Филиппа Зедлера answer)
Пользовательский шаблон:
from django import template
from django.urls import reverse
from django.urls import resolve
from django.utils import translation
register = template.Library()
@register.simple_tag(takes_context=True)
def translate_url(context, language):
view = resolve(context['request'].path)
request_language = translation.get_language()
translation.activate(language)
url = reverse(view.app_name+":"+view.url_name, args=view.args, kwargs=view.kwargs, )
translation.activate(request_language)
return url
В шаблоне:
{% get_available_languages as LANGUAGES %}
<ul>
{% for lang_code, lang_name in LANGUAGES %}
<li><a href="{% translate_url lang_code %}">{{ lang_name }}</a></li>
{% endfor %}
</ul>
Ответ 11
Простым решением было бы использование функции Django translate_url
с тегом шаблона:
# utils/templatetags/utils.py
from django.template import Library
from django.urls import translate_url as django_translate_url
register = Library()
@register.simple_tag(takes_context=True)
def translate_url(context, lang_code):
path = context.get('request').get_full_path()
return django_translate_url(path, lang_code)
Затем используйте его в своем html для выбора языка:
{% load i18n utils %}
{% get_available_languages as languages %}
<ul>
{% for lang_code, lang_name in languages %}
<li><a href="{% translate_url lang_code %}">{{ lang_code }}</a></li>
{% endfor %}
</ul>
И для hreflangs:
{% get_available_languages as languages %}
{% for lang_code, lang_name in languages %}
<link rel="alternate" hreflang="{{lang_code}}" href="{% translate_url lang_code %}" />
{% endfor %}
Надеюсь, это поможет.
Ответ 12
У меня работает в Django 2.2
Создайте собственный тег шаблона
from django import template
from django.urls import translate_url
register = template.Library()
@register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs):
path = context['request'].path
return translate_url(path, lang)
В шаблоне
{% load change_lang %}
<a href="{% change_lang 'en' %}">English</a>
<a href="{% change_lang 'es' %}">Español</a>