31

我正在使用i18n_patterns在 Django 应用程序中创建语言前缀。

我的网址如下所示:

/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”链接指向法语版的“联系”页面,而不是“主页”页面。

4

13 回答 13

17

我没有使用语言前缀,而是使用翻译后的网址。但是,此模板标签也应该可以帮助您:

# 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 %}

欢迎提出改进意见和建议。

于 2013-06-27T19:41:45.330 回答
7

这个片段应该这样做:

https://djangosnippets.org/snippets/2875/

将其添加为自定义模板标签后,您可以执行以下操作:

<a href='{% change_lang 'fr' %}'>View this page in French</a>

于 2014-02-05T09:52:16.587 回答
7

我认为值得一提的是,有一个名为translate_url.

from django.urls import translate_url
translate_url(url, lang_code)
于 2017-07-12T15:01:35.577 回答
4

使用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>
于 2017-12-29T03:05:55.887 回答
3

我认为你给这个问题增加了不必要的复杂性。您正在寻找的是一个简单的语言选择器。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 */
}
于 2012-08-13T11:29:58.590 回答
3

我使用文档中的标准语言形式

<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));

页面准备好时运行。

于 2014-03-11T06:51:40.643 回答
3

一个简单的解决方案是使用带有模板标签的 Djangotranslate_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 %}

希望这可以帮助。

于 2018-08-22T19:40:27.970 回答
2

对于 Django 2.0(基于 Philipp Zedler 的回答

自定义模板:

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>
于 2018-02-11T12:01:58.083 回答
1

我使用自定义模板标签遇到的问题是该函数根据当前 url 计算其他语言等效项,因为我使用的是modeltranslation 包,那么 slug 在 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-添加一个上下文变量,它将在您的views.py中保存urls字典

from .utils import getAlternateUrls
...
def MyView(DetailView):
    def get_context_data(self, **kwargs):
        context['alt_urls'] = getAlternateUrls(self.object)

4- 在模板的头部生成备用网址元标记

<!-- 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 中测试

于 2015-12-18T23:43:36.577 回答
1

我试图让它尽可能简单 - 使用reverse()任意数量的动态kwargs,以便语言切换(或任何其他类似的东西)将重定向到当前视图。

在 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 %}

很适合我。

于 2016-08-05T10:03:02.000 回答
1

我宁愿评论接受的答案,但不能,所以我发布自己的。我正在使用基于以下内容的非常相似的解决方案: https ://djangosnippets.org/snippets/2875/

resolvereverse方法都可能崩溃的问题:

  • 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
于 2016-10-04T11:06:38.820 回答
1

在 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>
于 2019-08-20T16:54:36.243 回答
1

Django 3 解决方案,基于Jonhatan 的回答

文件:App/templatetags.pyApp/templatetags/change_lang.py

from django.template.defaultfilters import register
from django.urls import translate_url


@register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs):
    path = context['request'].path
    return translate_url(path, lang)

模板:

{% load trans change_lang %}
{% trans 'View page in other languages:' %}
<a href="{% change_lang 'en' %}">English</a>
| <a href="{% change_lang 'de' %}">Deutsch</a>
于 2020-05-18T17:37:47.270 回答