使用翻译后的 url 重定向在 Django 中切换语言

Ign*_*rez 4 django url internationalization

我已经正确安装了国际化。

它适用于以下网址:

/en/bookings/ #English
/es/reservas/ #Spanish
Run Code Online (Sandbox Code Playgroud)

在主页中,语言切换也能正常工作。

- 有什么问题吗?

当我更改翻译页面中的语言时,例如 /en/bookings/,如果我将语言转换为西班牙语 (es),我将再次重定向到 /en/bookings/ 并看到英文页面。

如果我更改前缀(如这个答案),重定向将转到不存在的 /es/bookings/ 。

我不想被重定向到主页。

- 我喜欢什么?

如果我在 /en/bookings/ 并切换到西班牙语,我想重定向到 /es/reservas/,所有翻译的 url。

什么是最好的方法?

谢谢。

Mar*_*iak 6

我遇到了类似的问题,所以我发送了我的决议以节省您的时间。

主要(网址.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')),
)
Run Code Online (Sandbox Code Playgroud)

(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'),
]
Run Code Online (Sandbox Code Playgroud)

创建模板标签以在我们支持的所有语言中返回当前位置的 url (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
Run Code Online (Sandbox Code Playgroud)

创建中间件以在用户单击指向此子站点的替代链接时更改站点语言但使用不同的语言 (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
Run Code Online (Sandbox Code Playgroud)

在 LocaleMiddleware 之后将它添加到 (settings.py)

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'our_app.middleware.LangBasedOnUrlMiddleware',
]
Run Code Online (Sandbox Code Playgroud)

模板中的示例用法:

{% 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 %}
Run Code Online (Sandbox Code Playgroud)


sus*_*lrd 2

当我遇到同样的问题时,我实现了一个自定义模板标记 (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>
Run Code Online (Sandbox Code Playgroud)

以下是自定义标签的代码 (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)
Run Code Online (Sandbox Code Playgroud)

无需使用“set_language”django 视图。无需发出 POST 请求即可更改活动语言。仅使用 html archors 将所有国际化内容链接在一起,这更有利于 SEO。