【问题标题】:Django i18n patternDjango i18n 模式
【发布时间】:2015-01-12 23:29:33
【问题描述】:
我正在使用国际化。
所以,当我访问 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/
如何做到这一点?
【问题讨论】:
标签:
python
django
internationalization
django-i18n
【解决方案1】:
为了使所描述的行为起作用,当前语言必须以session 或cookie 形式保存。当使用 Django 的 set_language 重定向视图切换语言时,它会注意这一点:
带有set_languageredirect-view 的语言切换器
此视图通过 POST 请求接收新语言,然后更新会话(或 cookie),以便保持语言偏好。
来自docs 的示例语言切换器:
要求TEMPLATE_CONTEXT_PREPROCESSORS 中的django.core.context_processors.i18n 和项目的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,尽管这必须在每个请求中完成(可能在自定义中间件中),这样才能保证在用户手动更改地址时获取可能发生的每个地址更改浏览器地址栏中的语言前缀。 (在比较普通的 Django 和 Django CMS 设置时,我注意到 Django CMS 支持开箱即用的行为,所以看看他们的repo 看看他们是怎么做到的。)
【解决方案2】:
您遇到的情况是您的语言选择没有按照应有的方式进行,因此要执行此操作需要检查一些事项。
我的猜测是您在设置中将“en”作为 LANGUAGE_CODE,因此这将始终是您的后备。很多时候,您无法坚持使用语言的原因是您的设置 MIDDLEWARE_CLASSES 中可能没有正确的中间件。
试试下面的清单,看看你是否拥有所需的一切:
在您的设置中将 SessionMiddleware 和 LocaleMiddleware 添加到您的中间件堆栈,确保 SessionMiddleware 位于 LocaleMiddleware 之前,因为它依赖于会话的使用,并且它负责通过 url/session/ 从请求中获取您想要的语言cookie/request 标头按我相信的顺序排列,然后在所有其他方法都失败时使用您的后备语言。
确保您要提供的所有语言都在设置中的 LANGUAGES 列表中
这应该可以解决问题,所以希望有所帮助。
【解决方案3】:
问题是 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')。据我了解,我无法访问请求,那该怎么办?