Django 1.8 set_language视图不会重定向到指定的语言 [英] Django 1.8 set_language view does not redirect to specified language

查看:149
本文介绍了Django 1.8 set_language视图不会重定向到指定的语言的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在"set_language无法正常工作"类别的另一种变体中,我有这个问题.

In yet another variant of the "set_language isn't working" category of questions, I have this head scratcher.

在我的页面中,我有一个由三部分组成的语言选择器:

In my page I have a language selector made of three parts:

  1. 隐藏表格

  1. Hidden form

<form action="{% url 'set_language' %}" method="post" id="language-form" name="language-form">
    {% csrf_token %}
    <input type="hidden" name="language" id="language" value="" />
</form>

  • JavaScript表单提交功能

  • Javascript form submission function

    function set_language(code) {
        $('#language').val(code);
        $('#language-form').submit();
    }
    

  • 以及html列表(此处显示为浏览器中的呈现方式,而不是模板语言):

  • And the html list (shown here as rendered in the browser, rather than the template language):

    <li class="active"><a href="javascript:set_language('en-gb')"><img src="/static/img/locale/en-gb.png"> Great Britain (English) (en-gb)</a></li>
    <li><a href="javascript:set_language('nl-be')"><img src="/static/img/locale/nl-be.png"> Belgium (Dutch) (nl-be)</a></li>
    <li><a href="javascript:set_language('fr-be')"><img src="/static/img/locale/fr-be.png"> Belgium (French) (fr-be)</a></li>
    <li><a href="javascript:set_language('nl-nl')"><img src="/static/img/locale/nl-nl.png"> Netherlands (Dutch) (nl-nl)</a></li>
    <li><a href="javascript:set_language('fy-nl')"><img src="/static/img/locale/fy-nl.png"> Netherlands (Frisian) (fy-nl)</a></li>
    

  • 我可以确认上述功能正常运行,并提交包含以下内容的POST请求:

    I can confirm that the above functions as expected, and submits a POST request with content such as:

    csrfmiddlewaretoken=5Vcs9XdvHs7uJwPg4BHtnVPhPW3mMT0w&language=nl-nl
    

    ,并且开发服务器可以看到该帖子,如下所示:

    and that the development server sees the post, as shown by:

    [08/Jul/2015 23:58:33]"POST /i18n/setlang/ HTTP/1.1" 302 0
    [08/Jul/2015 23:58:33]"GET /en-gb/ HTTP/1.1" 200 6738
    

    我还可以确认手动输入时各种站点url都能正常工作,因此我可以转到localhost/en-gb/foolocalhost/fr-be/foo.

    I can also confirm that the various site urls do work when manually entered, so I can goto localhost/en-gb/foo and localhost/fr-be/foo just fine.

    我专门排除了表单中的下一个字段,以便重定向返回到当前页面(也可以按预期工作).

    I have specifically excluded the next field in the form so that the redirect returns to the current page (and that works as expected too).

    问题在于,尽管所有这些事情都在触发,但重定向后语言并未更改.

    The problem is that whilst all these things are triggering, the language isn't being changed after the redirect.

    我的Cookie似乎没有任何语言数据.我试图在输出中显示session._language值-如您所料,失败了,所以我尝试了:

    My cookie appears to be devoid of any language data. I've attempted to display the session._language value in the output - that failed as you would expect, so I tried:

    {% with settings.LANGUAGE_SESSION_KEY as langkey %}
    <p>Lang: {{ request.session.langkey }} {{ langkey }}</p>
    {% endwith %}
    

    它返回"Lang:",就是这样(即它看起来好像没有设置或为空).

    which returns "Lang:" and that's it (i.e. it looks like it isn't set or is empty).

    我现在很茫然.我相信set_language应该从/en-gb/foo重定向到/fr-be/foo,但这没有发生.浏览完代码调用后,我还可以从 set_language进行确认代码,当lang_code == 'fr-be'返回check_for_language(lang_code)时返回true(就像在我的设置中指定的所有其他语言一样-参见下文),对于"ff"之类的值返回false.即使值'en','fr,'nl'和'fy'也不能用作网址(它们会导致404错误),它也会返回true.

    I'm now at a loss. I believe that set_language should redirect from /en-gb/foo to /fr-be/foo, but this isn't happening. Having looked through the code calls, I can also confirm that from set_language code that check_for_language(lang_code) when lang_code == 'fr-be' returns true (as it does for all the other languages specified in my settings - see below), and returns false for values like 'ff'. It also returns true for values of 'en', 'fr, 'nl', and 'fy' too, even though they don't work as urls (they result in 404 errors).

    任何人都可以:

    1. 确认我对set_language的期望是正确的-是否应该使用语言和国家/地区代码进行重定向?
    2. 告诉我这是否是Django 1.8.2的错误吗?
    3. 是否建议我忽略其他调试方法?
    4. 建议简单解决(1)或(2)错误吗?

    谢谢

    Settings.py

    Settings.py

    MIDDLEWARE_CLASSES = (
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.locale.LocaleMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'django.middleware.security.SecurityMiddleware',
    )
    
    ROOT_URLCONF = 'wp4.urls'
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.core.context_processors.i18n',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    
    # Internationalization
    # https://docs.djangoproject.com/en/1.8/topics/i18n/
    
    LANGUAGE_CODE = 'en-gb'
    
    LANGUAGES = (
        ('en-gb', _('Great Britain (English)')),
        ('nl-be', _('Belgium (Dutch)')),
        ('fr-be', _('Belgium (French)')),
        ('nl-nl', _('Netherlands (Dutch)')),
        ('fy-nl', _('Netherlands (Frisian)')),
    )
    
    LOCALE_PATHS = (
        os.path.join(BASE_DIR, 'locale'),
    )
    
    TIME_ZONE = 'UTC'
    USE_I18N = True
    USE_L10N = True
    USE_TZ = True
    

    推荐答案

    好的,进一步的观察发现了以下答案和意见.

    Ok, few bits of further observation have resulted in the following answers and opinions.

    首先要回答我的具体问题:

    To answer my specific questions first:

    1. 我的期望基本上是正确的,set_language应该重定向到页面的新语言,但有一个警告.参见下文.
    2. 我认为这是一个逻辑错误,因此会提交给django项目.
    3. 我收到的唯一建议是检查会话变量值,我也将在下面进行报告.
    4. 关键的解决方法是将下一个"字段设置为当前网址,但不使用语言代码前缀.
    1. My expectations are mostly correct, set_language should redirect to the new language for the page, but there is a caveat. See below.
    2. I think there is a logic bug, and will submit as such to the django project.
    3. The only suggestion I received was to check the session variable values, and I'll report on that below too.
    4. The key workaround is to set 'next' field to your current url, but without the language code prefix.

    这是我在查看Django代码和路径的基础上提出意见的地方.

    This is where I venture into opinion based on reviewing the django code and paths.

    我认为set_language() 代码文档.也许这是对代码说明的期望,因为文档将next的分辨率列出为:

    I think there is a logic error in the set_language() code and documentation. This is perhaps more an expectation against what the code says it does, as the docs list the resolution of next as:

    1. Django在POST数据中寻找下一个参数.
    2. 如果该网址不存在或为空,则Django会在Referrer标头中尝试使用该网址.
    3. 如果该字段为空(例如,如果用户的浏览器禁止显示该标头),则该用户将被重定向到/(网站根目录),作为后备广告.

    我没有思考next来触发步骤2.我的期望是,如果新语言是"fr-be",它将把URL从/nl-be/foo/bar/转换为/fr-be/foo/bar/.没有.而是将next设置为/nl-be/foo/bar/,然后将session._language值设置为'fr-be'.然后,在加载页面时会忽略此会话值,因为 locale middleware (get_language_from_request())通过首先在url中查找语言代码来处理请求,并且只有在找不到语言代码时,它才会查看其他选项(例如会话,cookie,请求数据,设置).

    I left next empty thinking to trigger step 2. My expectation is that if the new language was 'fr-be', that it would translate the url from /nl-be/foo/bar/ into /fr-be/foo/bar/. It doesn't. Instead it sets next to remain as /nl-be/foo/bar/ and then sets the session._language value to 'fr-be'. This session value is then ignored as the page is loaded, because the locale middleware (get_language_from_request()) processes the request by looking for a language code in the url first, and only if it doesn't find one, does it look at the other options (such as session, cookie, request data, settings).

    这意味着'fr-be'的会话值将被忽略,而使用url中的'nl-be',然后其他东西在呈现模板之前清除了会话值(这就是为什么我发现会话值在模板中查询时为无".

    This means that the session value of 'fr-be' is ignored in favour of the 'nl-be' in the url, and then something else clears the session value before the template is rendered (which is why I find the session value to be None when I query it in the template).

    我认为这是一个逻辑错误,因为如果您想更改语言并运行i18n,那么url总是会包含您当前语言的语言代码,因此步骤2总是会导致语言更改被忽略.

    I would argue that this is a logic misstep, because if you wanted to change the language and have i18n running, then the url is always going to have the language code of your present language in it, so step 2 would always result in the language change being ignored.

    虽然我将使用变通方法(即确保每个页面都知道自己的网址语言代码前缀,并将其明确设置为next值),但我认为是应该更改的内容(或者至少是文档明确表明您不能使用确定下一个的第二种方法来更改语言).

    Whilst I'm going to use my workaround (i.e. ensuring that every page knows its own urls minus the language code prefix, and setting that as the next value explicitly), I think this is something that should be changed (or at least the docs made explicit that you can't change language using the second method of determining next).

    这篇关于Django 1.8 set_language视图不会重定向到指定的语言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆