使用已翻译的URL重定向切换Django中的语言

时间:2015-02-23 13:58:08

标签: django url internationalization

我正确安装了国际化。

它适用于以下网址:

/en/bookings/ #English
/es/reservas/ #Spanish

在主页中语言切换也可以正常工作。

- 问题是什么?

当我更改翻译页面中的语言时,例如/ en / bookings /,如果我将语言翻译成西班牙语,我会被重定向到/ en / bookings /再次,我会看到英文页面

如果我更改前缀(like this answer),重定向将转至/ es / bookings /不存在。

我不想被重定向到主页。

- 我喜欢什么?

如果我在/ en / bookings /并切换到西班牙语,我希望将所有已翻译的网址重定向到/ es / reservas /。

最好的方法是什么?

感谢。

2 个答案:

答案 0 :(得分:2)

我有类似的问题所以我发送决议以节省您的时间。

主(urls.py)

from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns

urlpatterns = [
    url(r'^i18n/', include('django.conf.urls.i18n')), 
]

urlpatterns += i18n_patterns(
    url(r'^', include('index.urls', namespace='index')),
)

(index.urls.py)

from django.conf.urls import url
from django.views.generic import TemplateView
from django.utils.translation import ugettext_lazy as _


urlpatterns = [
    url(r'^$', TemplateView.as_view(template_name='index/index.html'), name='index'),
    url(_(r'^python-programming/$'), TemplateView.as_view(template_name='index/new_page.html'),
        name='new_page'),
]

创建模板标记以返回我们支持的所有语言中当前位置的网址(index.templatetags.helper_tags.py)

from django.template import Library
from django.core.urlresolvers import resolve, reverse
from django.utils.translation import activate, get_language

register = Library()


@register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs):
    """
    Get active page's url by a specified language
    Usage: {% change_lang 'en' %}
    """

    path = context['request'].path
    url_parts = resolve(path)

    url = path
    cur_language = get_language()
    try:
        activate(lang)
        url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
    finally:
        activate(cur_language)

    return "%s" % url

当用户点击此子网站的替代链接但使用其他语言时,创建中间件以更改网站语言 (middleware.py)

from django.utils import translation
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin


class LangBasedOnUrlMiddleware(MiddlewareMixin):

    @staticmethod
    def process_request(request):

        if hasattr(request, 'session'):
            active_session_lang = request.session.get(translation.LANGUAGE_SESSION_KEY)

            if active_session_lang == request.LANGUAGE_CODE:
                return

            if any(request.LANGUAGE_CODE in language for language in settings.LANGUAGES):
                translation.activate(request.LANGUAGE_CODE)
                request.session[translation.LANGUAGE_SESSION_KEY] = request.LANGUAGE_CODE

在LocaleMiddleware

之后将其添加到(settings.py)
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'our_app.middleware.LangBasedOnUrlMiddleware',
]

模板中的示例用法:

{% load i18n %}
{% load helper_tags %}
    {% get_available_languages as languages %}
    {% for lang_code, lang_name in languages %}
        <a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{% change_lang lang_code %}">
    {% endfor %}

答案 1 :(得分:1)

当我遇到同样的问题时,我实现了一个自定义模板标记(current_url),根据上下文中的请求,重新呈现活动语言的URL:

{% load custom_tags %}
<ul>
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
    {# IMPORTANT! enclose the 'current_url' tag in a 'language' block #}
    {% language language.code %}
        <li {% if language.code == LANGUAGE_CODE %}class="active"{% endif %}>
            <a href="{% current_url %}">{{ language.name_local }}</a>
        </li>
    {% endlanguage %}
{% endfor %}
</ul>

以下是自定义标记的代码(custom_tags.py):

import six
import sys
from django.template import Node, TemplateSyntaxError, Library
from django.conf import settings

register = Library()

class CurrentURLNode(Node):

    def __init__(self, asvar=None):
        self.asvar = asvar

    def render(self, context):
        request = context['request']
        from django.core.urlresolvers import reverse, NoReverseMatch
        url = ''
        try:
            url = reverse(request.resolver_match.view_name, args=request.resolver_match.args, kwargs=request.resolver_match.kwargs, current_app=context.current_app)
        except NoReverseMatch:
            exc_info = sys.exc_info()
            if settings.SETTINGS_MODULE:
                project_name = settings.SETTINGS_MODULE.split('.')[0]
                try:
                    url = reverse(project_name + '.' + request.resolver_match.view_name,
                          args=request.resolver_match.args, kwargs=request.resolver_match.kwargs,
                          current_app=context.current_app)
                except NoReverseMatch:
                    if self.asvar is None:                      
                        six.reraise(*exc_info)
            else:
                if self.asvar is None:
                    raise

        if self.asvar:
            context[self.asvar] = url
            return ''
        else:
            return url

@register.tag
def current_url(parser, token):
    bits = token.split_contents()
    bits = bits[1:]
    asvar = None
    if len(bits) >= 2 and bits[-2] == 'as':
        asvar = bits[-1]
        bits = bits[:-2]
    if len(bits):
        raise TemplateSyntaxError("Unexpected arguments to current_url tag")
    return CurrentURLNode(asvar)

无需使用'set_language'django视图。无需发出POST请求来更改活动语言。只有html存档将所有国际化内容链接在一起,对SEO更好。