Django 1.8 set_language视图不会重定向到指定的语言

时间:2015-07-09 00:45:00

标签: django localization internationalization

在另一个版本中," set_language没有工作"问题的类别,我有这个头颅。

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

  1. 隐藏表格

    <form action="{% url 'set_language' %}" method="post" id="language-form" name="language-form">
        {% csrf_token %}
        <input type="hidden" name="language" id="language" value="" />
    </form>
    
  2. Javascript表单提交功能

    function set_language(code) {
        $('#language').val(code);
        $('#language-form').submit();
    }
    
  3. 和html列表(此处显示为在浏览器中呈现,而不是模板语言):

    <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>
    
  4. 我可以确认上述功能符合预期,并提交包含以下内容的POST请求:

    csrfmiddlewaretoken=5Vcs9XdvHs7uJwPg4BHtnVPhPW3mMT0w&language=nl-nl
    

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

    [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
    

    我还可以确认手动输入时各种网站网址是否有效,因此我可以转到localhost/en-gb/foolocalhost/fr-be/foo

    我已经明确地排除了表单中的下一个字段,以便重定向返回到当前页面(并且也按预期工作)。

    问题在于,虽然所有这些事情都在触发,但重定向后语言不会被更改。

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

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

    返回&#34;郎:&#34;那就是它(即看起来它没有设置或为空)。

    我现在不知所措。我相信set_language应该从/en-gb/foo重定向到/fr-be/foo,但这不会发生。查看了代码调用后,我还可以从set_language code确认check_for_language(lang_code)lang_code == 'fr-be'返回true时(就像我设置中指定的所有其他语言一样 - 见下文),并返回false,例如&f;&#39; ff&#39;。对于&#39; en&#39;,&#39; fr,&#39; nl&#39;和&#39; fy&#39;的值也会返回true。即使他们不作为网址工作(他们也会导致404错误)。

    任何人都可以:

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

      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
      

1 个答案:

答案 0 :(得分:5)

好的,进一步观察的几点已经产生了以下答案和意见。

首先回答我的具体问题:

  1. 我的期望大多是正确的,set_language应该重定向到页面的新语言,但有一点需要注意。见下文。
  2. 我认为存在一个逻辑错误,并将这样提交给django项目。
  3. 我收到的唯一建议是检查会话变量值,我也会在下面报告。
  4. 关键的解决方法是设置&#39; next&#39;字段到您当前的网址,但没有语言代码前缀。
  5. 这是我在审查django代码和路径时冒险的意见。

    我认为set_language() codedocumentation存在逻辑错误。这或许更像是对代码所说的内容的期望,因为文档将下一个分辨率列为:

    1. Django在POST数据中查找下一个参数。
    2. 如果它不存在或为空,Django会在Referrer标题中尝试URL。
    3. 如果这是空的 - 比方说,如果用户的浏览器禁止该标题 - 那么用户将被重定向到/(网站根目录)作为后备。
    4. 我离开next空洞思考触发第2步。我的期望是,如果新语言是&#39; fr-be&#39;,它会将网址从/nl-be/foo/bar/转换为/fr-be/foo/bar/。它没有。相反,它设置为保留为/nl-be/foo/bar/,然后将session._language值设置为&#39; fr-be&#39;。然后在加载页面时忽略此会话值,因为locale middlewareget_language_from_request())通过首先在URL中查找语言代码来处理请求,并且只有在找不到时才会处理请求一,它是否会查看其他选项(例如会话,cookie,请求数据,设置)。

      这意味着&#39; fr-be&#39;的会话值被忽略,有利于&#39; nl-be&#39;在url中,然后在渲染模板之前清除会话值(这就是为什么当我在模板中查询时会发现会话值为None)。

      我认为这是一个逻辑错误,因为如果你想改变语言并让i18n运行,那么url总是会有你当前语言的语言代码,所以第2步总会产生在语言变化中被忽略。

      虽然我将使用我的解决方法(即确保每个页面都知道自己的网址减去语言代码前缀,并明确将其设置为next值) ,我认为这是应该改变的(或者至少是明确的文档,你可以使用第二种确定下一种方法来改变语言)。