开发者

How does django locale work between views

I know django picks up default language for website from browser headers first and then displays page in that language if it matches possible choises from settings.

What I am trying to do, is to change & set that language after user has logged on. I have provided form for users for their default settings. Upon logon that default language is picked from those defaultSettings models. And what I am doing is:

d = DefaultSettings.objects.filter(user = request.user)
if len(d) > 0 and d[0].has_default_language:
    from django.utils import translation 开发者_开发百科     
    translation.activate(d[0].default_language)
    request.LANGUAGE_CODE = translation.get_language()

And what I'm seeing is page in "wrong" language.

Which makes me ask -Why? I did not make that code up by myself. I got it from following examples

  • Detect the language & django locale-url
  • https://github.com/Torte/django-urli18n/blob/master/urli18n/middleware.py
  • https://github.com/divio/django-cms/blob/develop/cms/middleware/multilingual.py

Since all those examples modify request/response in middleware - do I really have to do the same? Does Django reset language between requests and tries to "guess" it again after each request?

Why does not my way of setting it once work?

Alan

Update after 1st response (from Sindri Guðmundsson):

    if form.is_valid ( ):
        if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
            redirect_to = settings.LOGIN_REDIRECT_URL
        if not form.cleaned_data [ 'remember_me' ]:
            request.session.set_expiry ( 0 )
        from django.contrib.auth import login
        login ( request, form.get_user ( ) )
        if request.session.test_cookie_worked ( ):
            request.session.delete_test_cookie ( )
        set_lang_to_user_default_language(request)
        response = HttpResponseRedirect ( redirect_to )
        d = DefaultSettings.objects.filter(user = request.user)
        if len(d) > 0 and d[0].has_default_language:                  
            from django.utils import translation
            translation.activate(d[0].default_language)
            logger.debug(translation.get_language())
            request.LANGUAGE_CODE = translation.get_language()                
            if hasattr(request, 'session'):
                logger.debug('set django_language')
                request.session['django_language'] = translation.get_language()
            else:
                logger.debug('set response cookie')
                response.set_cookie(settings.LANGUAGE_COOKIE_NAME, translation.get_language())
        return  response

When I check log, I see:

DEBUG 2011-09-01 09:08:13,379 et
DEBUG 2011-09-01 09:08:13,379 set django_language

But when I check template in next view, where I have {{ LANGUAGE_CODE }} printed out, then it shows 'en' not 'et'

Update2 :

Actually what happens after processing this view is : 1st page where this view redirects to {{ LANGUAGE_CODE }} is 'en' content is in English 2nd page where I go after 1st {{ LANGUAGE_CODE }} is 'en' but content is in Estonian 3rd page where I go after 2nd {{ LANGUAGE_CODE }} is 'en' and content is in English again and remains English from thereon.

So it looks like I have to create my own middleware to keep page in "correct" language... my question is though - WHY?

Update3 : My language settings are like that :

LANGUAGES = (
            ('et', gettext('Estonian')),
            ('en', gettext('English')),
            ('ru', gettext('Russian')),
            ('lv', gettext('Latvian')),
            ('lt', gettext('Lithuanian')),
            ('fi', gettext('Finnish')),
            )

But after further investigation I think I found a workaround. I use django-cms in this project and I turned off cms.middleware.multilingual.MultilingualURLMiddleware and experienced the issues I described above. When I turn it back on, then everything works just fine - but it works just fine because that middleware is turned on and it puts required parameters into each and every response.

What I asked initially with my question was- how it works. And I've asked question WHY later. Now, I think, the question is - does one really have to set language for each and every request/response like this middleware does and like the example middlewares do?


Suggestion/answer:

I got some weird behaviour on that also! Because I was forgetting to add the 'LocaleMiddleware', double check if it is there, for illustration this is how my 'MIDDLEWARE_CLASSES' looks like:

MIDDLEWARE_CLASSES = (
    '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',
)

That Middleware is responsible for process your request and response, and add the language!

Also keep the code from 'Sindri Guðmundsson', which is changing right the lang!

EDIT

A little bit further! If we take a look at LocaleMiddleware:

def process_request(self, request):
    language = translation.get_language_from_request(request)
    translation.activate(language)
    request.LANGUAGE_CODE = translation.get_language()

So the question is! why Django needs that?! the answer: Because if you use {{ LANGUAGE_CODE }} it is reading from the REQUEST, so LANGUAGE_CODE must be in the request! otherwise ! it is not going to return it! so thats why this middleware exist! Check it out the comment, in the actual source code of the middleware:

"""
This is a very simple middleware that parses a request
and decides what translation object to install in the current
thread context. This allows pages to be dynamically
translated to the language the user desires (if the language
is available, of course).
"""

Also check the docs: https://docs.djangoproject.com/en/1.3/topics/i18n/deployment/#how-django-discovers-language-preference


Check out set_language in django.views.i18n, line 33. You have to set the language code for the user in session:

if hasattr(request, 'session'):
    request.session['django_language'] = lang_code
else:
    response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)


Django CMS uses request.LANGUAGE_CODE to determine what language to use, if you don't specifically asks for a certain language in your GET or POST parameters.

Django CMS uses a middleware, MultilingualURLMiddleware, to set request.LANGUAGE_CODE.

That middleware first looks for a language prefix in the url, then it looks for language a session key.

This means that if you want another language you can set it in the session variable once, but MultilingualURLMiddleware will still set request.LANGUAGE_CODE on every request.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜