Django 国际化模式

Django i18n pattern

我正在使用国际化。

所以,当我访问 http://localhost:8000/en/http://localhost:8000/de/

时,一切正常

但是当我访问 http://localhost:8000/ 时,它会将我重定向到 http://localhost:8000/en/,即使上次访问的页面是 http://localhost:8000/de/

基本上,我想根据访问的页面保存语言代码,例如如果我访问 http://localhost:8000/de/ 那么语言是德语。接下来,当我访问 http://localhost:8000 时,它应该指向 http://localhost:8000/de/,而不是默认的 http://localhost:8000/en/

如何做到这一点?

为了使描述的行为起作用,必须在 sessioncookie 中保留当前语言。当使用 Django 的 set_language 重定向视图切换语言时,它会注意:

带有 set_language 重定向视图的语言切换器

此视图通过 POST 请求接收新语言,然后更新会话(或 cookie)以便保留语言首选项。

示例语言切换器来自 docs:

需要 django.core.context_processors.i18nTEMPLATE_CONTEXT_PREPROCESSORS 和项目的 urls.py.

中的 i18n 视图
<form action="{% url 'set_language' %}" method="post">
    {% 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>

在每个请求中明确保留所请求页面的语言

另一种选择是 set it explicitly,尽管这必须在每个请求中完成(可能在自定义中间件中),以便保证在用户手动更改浏览器地址栏中的语言前缀。 (在比较普通 DjangoDjango CMS 设置时,我注意到 Django CMS 支持开箱即用的行为,所以它可能是查看他们的回购协议以了解他们是如何做到这一点的想法。)

您遇到的问题是您的语言选择没有按应有的方式坚持下去,因此要做到这一点,需要检查一些事项。

我的猜测是您在设置中将 'en' 作为 LANGUAGE_CODE,因此这将始终是您的后备。很多时候,你不能让你的语言坚持下去的原因是你的设置中可能没有正确的中间件 MIDDLEWARE_CLASSES。

尝试以下核对清单,看看您是否拥有所需的一切:

  • 在您的设置中将 SessionMiddleware 和 LocaleMiddleware 添加到您的中间件堆栈,确保 SessionMiddleware 在 LocaleMiddleware 之前出现,因为它依赖于会话的使用,并且它负责通过请求从请求中获取所需的语言url/session/cookie/request header 按照我相信的顺序,如果其他所有方法都失败,则使用您的后备语言。

  • 确保您要提供的所有语言都在设置中的语言列表中

这应该可以解决问题,希望对您有所帮助。

问题是 Django 没有添加 request.session['django_language'] = lang_code

我只是扩展语言环境中间件并使用以下代码。

def process_request(self, request):

    if self.is_language_prefix_patterns_used():
        lang_code = (get_language_from_path(request.path_info) or
                     request.session.get('django_language', settings.LANGUAGE_CODE))

        activate(lang_code)
        request.session['django_language'] = lang_code
        request.LANGUAGE_CODE = get_language()

现在,我有以下问题。 我该怎么做才能 http://localhost:8000 没有重定向(以语言代码为前缀)?

我找到了以下代码:

class NoPrefixLocaleRegexURLResolver(LocaleRegexURLResolver):

@property
def regex(self):
    language_code = get_language()
    if language_code not in self._regex_dict:
        regex_compiled = (re.compile('' % language_code, re.UNICODE)
                          if language_code == settings.LANGUAGE_CODE
                          else re.compile('^%s/' % language_code, re.UNICODE))

        self._regex_dict[language_code] = regex_compiled
    return self._regex_dict[language_code]

但是,该代码在检查 language_code == settings.LANGUAGE_CODE 时存在问题。如果我输入 http://localchost:8000,它不会重定向,但会提供一个包含来自 settings.LANGUAGE_CODE 而不是 request.session.get('django_language') 的翻译的页面。据我了解,无法访问request,请问怎么办?