2014-01-02 3 views
2

Моя ситуация следующая:Django: изменение языка приложение программно (без/i18n/setlang/зрения)

Я занимаюсь разработкой многоязычного сайта в настоящее время, и я использую представление Django /i18n/setlang/, чтобы позволить пользователю переключать язык из выпадающего меню, и все работает отлично ... но теперь я хочу установить язык программно, в частности, у меня есть форма с рядом настроек, и среди них есть голос «любимого языка» , как только пользователь отправит форму, мое представление сохраняет модель User и теоретически после этого, она должна установить язык приложения с сохраненным предпочтением, но он не работает. То, что я попытался это:

from django.utils.translation import activate 

activate(lang) 

но результат странно: пользовательский интерфейс после редиректа еще в старом языке, но сообщение об успешном обновлении (Джанго сообщений каркасных) отображаются обратно в ожидаемом языке!

Я также проверил исходный код зрения Django: https://github.com/django/django/blob/master/django/views/i18n.py

И я увидел, что они сохранить выбранный язык в сессии, если таковой имеется (я активировал сеанс), так что я пробовал:

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

... но не работает, что делать?

Я использую Django 1.6 и Джанго промежуточное программное обеспечение я установить следующие:

'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', 

пс: в обеих моих попыток, {{request.LANGUAGE_CODE}} в шаблоне печатает старый код языка: (

+1

Вы пытались установить новый язык явно: request.LANGUAGE_CODE = translation.get_language()? –

+0

Да, это бесполезно ... и в любом случае мне нужно постоянно устанавливать язык не только для текущего вида:/ – daveoncode

+0

Вы используете ** i18n_patterns **? –

ответ

2

активировать самостоятельно не сделать трюк

Отъезд django.views.i18n.set_language:.

def set_language(request): 
    """ 
    Redirect to a given url while setting the chosen language in the 
    session or cookie. The url and the language code need to be 
    specified in the request parameters. 

    Since this view changes how the user will see the rest of the site, it must 
    only be accessed as a POST request. If called as a GET request, it will 
    redirect to the page in the request (the 'next' parameter) without changing 
    any state. 
    """ 
    next = request.REQUEST.get('next') 
    if not is_safe_url(url=next, host=request.get_host()): 
     next = request.META.get('HTTP_REFERER') 
     if not is_safe_url(url=next, host=request.get_host()): 
      next = '/' 
    response = http.HttpResponseRedirect(next) 
    if request.method == 'POST': 
     lang_code = request.POST.get('language', None) 
     if lang_code and check_for_language(lang_code): 
      if hasattr(request, 'session'): 
       request.session['django_language'] = lang_code 
      else: 
       response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code) 
    return response 

У этого есть все, что вам нужно, чтобы установить язык в поле зрения программно. поскольку у вас уже есть localemiddleware, тогда это представление - это все, что вам нужно. Но не копируйте его просто так. Держите его в этом режиме. Я думаю, вам может понадобиться этот, хотя :)

+0

Честно говоря, я не понимаю вашего ответа, я видел этот код, как я писал в своем вопросе ... вы говорите мне использовать этот код и добавить вызов для активации() в моем собственном представлении? Если это так, я попробовал это, но не работает – daveoncode

+0

Нет, я не говорю вам об этом. Я говорю вам, что вам нужно сделать то, что этот взгляд делает в дополнение к вызову activ (language). Вам также нужно выполнить request.session ['django_language'] = язык, и вам нужно выполнить response.set_cookie (settings.LANGUAGE_COOKIE_NAME, язык). –

2

Решенный !!! Благодаря Дмитрию Волошину, который сообщил мне о волшебстве i18n_patterns (я не знал их: P).

Для того, чтобы получить то, что я хочу, это те шаги, которые я сделал:

[1] Настройка i18n_patterns в моих базовых адресов.ру:

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] Используйте этот класс на мой взгляд, после того, как пользовательские предпочтения формируют представление:

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 в o rder читать пользовательские предпочтения:

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 будет расти исключение!).

удовлетворение ++ (опс ... в Python: удовлетворение + = 1)

UPDATE:

Я упростил свой подход, чтобы полагаться только на обычае LocaleMiddleware, это обновленный класс:

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) 
Смежные вопросы