Django:以编程方式更改应用程序语言(不带/ i18n / setlang / view) [英] Django: change app language programmatically (without /i18n/setlang/ view)

查看:137
本文介绍了Django:以编程方式更改应用程序语言(不带/ i18n / setlang / view)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的情况如下:

我正在开发一个多语言网站,目前我使用Django视图 / i18n / setlang /强大>让用户从下拉菜单中切换语言,并且一切正常工作...但是现在,我希望以编程方式设置语言,具体来说我有一个表单与一系列的设置,其中有一个喜欢的语言语音,一旦用户提交表单,我的观点保存用户模型,理论上应该使用保存的首选项设置应用程序语言,但不起作用。我试过的是:

I'm developing a multi-language site and currently I use the Django view /i18n/setlang/ to let user switch language from a dropdown menu, and all works fine… but now, I wish to set the language programmatically, specifically I have a form with a series of settings and, among these, there is a "favorite language" voice, once the user submit the form, my view saves the User model and theoretically after that it should set the application language using the saved preference, but it does not work. What I tried is:

from django.utils.translation import activate

activate(lang)

但结果是奇怪的:重定向后的UI仍然是旧的语言,但是成功更新(django消息框架)显示回预期语言!

but the result is bizarre: the UI after the redirect is still in the old language, but the message of successful update (django messages framework) is displayed back in the expected language!

我还检查了Django视图的源代码: https://github.com/django/django/blob/master/django/views/i18n.py

I've also checked the source code of the Django view: https://github.com/django/django/blob/master/django/views/i18n.py

我看到他们在会话中保存所选语言(如果可用)(我已启用会话),所以我试过:

And I saw that they save the selected language in session if available (I have session activated), so I tried:

self.request.session['_language'] = form.cleaned_data['favouriteLanguage']

...但不行,我该怎么办?

…but is not working, what should I do?

我使用的是Django 1.6,我安装的django中间件如下:

I'm using Django 1.6 and the django middleware I did install are the following:

    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',

ps:在我的两次尝试中,{{request .LANGUAGE_CODE}}在模板中打印旧的语言代码:(

ps: in both my tries, {{ request.LANGUAGE_CODE }} in template prints the old language code :(

推荐答案

感谢Dmytriy Voloshyn告诉我关于魔术 i18n_patterns (我不知道他们:P)。

Solved!!! Thanks to Dmytriy Voloshyn which informed me about the magic i18n_patterns (I did not know them :P).

为了获得我想要的,这些是我已经完成的步骤:

In order to obtain what I want, these are the steps I've done:

[1]在我的基地设置i18n_patterns urls.py:

from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns

urlpatterns = i18n_patterns(
    '',
    url(r'^', include('mysite.core.urls')),
    url(r'^foo/', include('mysite.foo.urls')),
    # ...
)

[2]编写一个实用程序类以更改路径前缀

import re

from django.utils.encoding import force_text
from django.utils.translation import check_for_language


class PathUtils(object):
LANGUAGE_PREFIX_REGEX = re.compile('^/[a-z]{2}/')

@classmethod
def __pathHasValidPrefix(cls, path):
    matches = cls.LANGUAGE_PREFIX_REGEX.findall(path)
    if not matches:
        return False
    return check_for_language(matches[0].strip('/'))


@classmethod
def replaceLanguagePrefix(cls, path, newPrefix):
    """
    Returns the original path string with the language prefix replaced by the given one.
    Returns the unmodified path if language prefix is not found or is invalid (the language is not
    available for the application).



    :param path: (str) url path
    :param newPrefix: (str) 2 chars language code (ie: "IT", "DE", "ES"...)
    :return: (str) Path with new prefix
    """
    path, newPrefix = force_text(path), force_text(newPrefix)
    if not check_for_language(newPrefix) or not cls.__pathHasValidPrefix(path):
        return path
    return cls.LANGUAGE_PREFIX_REGEX.sub('/{0}/'.format(newPrefix), path)

[3]在用户偏好表单提交后,在我的视图中使用该类: p>

[3] Use that class in my view after user preferences form submission:

def form_valid(self, form):
     form.save()
     self.success_url = PathUtils.replaceLanguagePrefix(self.success_url, form.cleaned_data['locale'])
     return super(UserSettingsUpdateView, self).form_valid(form)

[4]覆盖默认的LocaleMiddleware以便读取用户偏好设置:

from django.middleware.locale import LocaleMiddleware as BaseLocaleMiddleware
from django.utils.translation import activate


class LocaleMiddleware(BaseLocaleMiddleware):
"""
Override Django LocaleMiddleware in order to read user preferences.
"""

def __userHasLanguagePreference(self, request):
    return request.user.is_authenticated() and request.user.locale


def __activateUserFavoriteLanguage(self, request):
    activate(request.user.locale)
    request.LANGUAGE_CODE = request.user.locale


def process_request(self, request):
    if self.__userHasLanguagePreference(request):
        self.__activateUserFavoriteLanguage(request)
    else:
        super(LocaleMiddleware, self).process_request(request)

重要的是以正确的顺序导入中间件进行此实现,AuthenticationMiddleware必须在LocaleMiddleware之前导入,否则用户将在请求中丢失(并且访问request.user将引发异常!)

It is important to import middleware in the right order for this implementation, AuthenticationMiddleware MUST be imported before LocaleMiddleware, otherwise user would be missing in request (and accessing request.user will rise an exception!).

满意++(ops ... in Python:satisfaction + = 1)

satisfaction++ (ops… in Python: satisfaction += 1)

更新:

我简化了我的做法,只能依靠cu来自django的这个更新的类:

I simplified my approach in order to rely only on the custom LocaleMiddleware, this is the updated class:

from django.middleware.locale import LocaleMiddleware as BaseLocaleMiddleware
from django.utils.translation import get_language_from_path

from myapp.PathUtils import PathUtils


class LocaleMiddleware(BaseLocaleMiddleware):
    """
    Override Django LocaleMiddleware in order to read user preferences.
    """

    def __userHasLanguagePreference(self, request):
        return request.user.is_authenticated() and request.user.locale


    def __honorUserLanguagePreference(self, request):
        preferred = request.user.locale
        language = get_language_from_path(request.path_info, supported=self._supported_languages)
        if language != preferred:
            request.path_info = PathUtils.replaceLanguagePrefix(request.path_info, preferred)


    def process_request(self, request):
        if self.__userHasLanguagePreference(request):
            self.__honorUserLanguagePreference(request)
        super(LocaleMiddleware, self).process_request(request)

这篇关于Django:以编程方式更改应用程序语言(不带/ i18n / setlang / view)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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