views:

1955

answers:

3

I want to deploy a website in english & spanish and detect the user browser languaje & redirect to the correct locale site.

My site is www.elmalabarista.com

I install django-localeurl, but I discover that the languaje is not correctly detected.

This are my middlewares:

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware', 
    'django.middleware.locale.LocaleMiddleware', 
    'multilingual.middleware.DefaultLanguageMiddleware',
    'middleware.feedburner.FeedburnerMiddleware',
    'lib.threadlocals.ThreadLocalsMiddleware',
    'middleware.url.UrlMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'maintenancemode.middleware.MaintenanceModeMiddleware',
    'middleware.redirect.RedirectMiddleware',
    'openidconsumer.middleware.OpenIDMiddleware',
    'django.middleware.doc.XViewMiddleware',
    'middleware.ajax_errors.AjaxMiddleware',
    'pingback.middleware.PingbackMiddleware',
    'localeurl.middleware.LocaleURLMiddleware', 
    'multilingual.flatpages.middleware.FlatpageFallbackMiddleware',
    'django.middleware.common.CommonMiddleware',
)

But ALWAYS the site get to US despite the fact my OS & Browser setup is spanish.

LANGUAGES = (
    ('en', ugettext('English')),  
    ('es', ugettext('Spanish')),
)
DEFAULT_LANGUAGE = 1

Then, I hack the middleware of locale-url and do this:

def process_request(self, request):
    locale, path = self.split_locale_from_request(request)
    if request.META.has_key('HTTP_ACCEPT_LANGUAGE'):
        locale = utils.supported_language(request.META['HTTP_ACCEPT_LANGUAGE'].split(',')[0])
    locale_path = utils.locale_path(path, locale)

    if locale_path != request.path_info:
        if request.META.get("QUERY_STRING", ""):
            locale_path = "%s?%s" % (locale_path,
                    request.META['QUERY_STRING'])
        return HttpResponseRedirect(locale_path)
    request.path_info = path
    if not locale:
        locale = settings.LANGUAGE_CODE
    translation.activate(locale)
    request.LANGUAGE_CODE = translation.get_language()

However, this detect fine the language but redirect the "en" urls to "es". So is impossible navigate in english.

UPDATE: This is the final code (after the input from Carl Meyer) with a fix for the case of "/":

def process_request(self, request):
    locale, path = self.split_locale_from_request(request)
    if (not locale) or (locale==''):
        if request.META.has_key('HTTP_ACCEPT_LANGUAGE'):
            locale = utils.supported_language(request.META['HTTP_ACCEPT_LANGUAGE'].split(',')[0])
        else:
            locale = settings.LANGUAGE_CODE
    locale_path = utils.locale_path(path, locale)
    if locale_path != request.path_info:
        if request.META.get("QUERY_STRING", ""):
            locale_path = "%s?%s" % (locale_path, request.META['QUERY_STRING'])
        return HttpResponseRedirect(locale_path)
    request.path_info = path
    translation.activate(locale)
    request.LANGUAGE_CODE = translation.get_language()
+4  A: 

(Update: django-localeurl's LocaleURLMiddleware now directly supports HTTP Accept-Language as fallback, if LOCALEURL_USE_ACCEPT_LANGUAGE setting is True. So the OP's desired behavior is now available without writing a custom middleware).

It does not make sense to have both Django's built-in LocaleMiddleware and LocaleURLMiddleware enabled. They are intended as mutually exclusive alternatives, and have different logic for choosing a language. Locale-url does what it says on the tin: the locale is defined by a URL component (thus not by the Accept-Language header). Django's LocaleMiddleware will choose the language based on a session value or cookie or Accept-Language header. Enabling both just means that whichever one comes last wins, which is why you're seeing the LocaleURLMiddleware behavior.

It sounds like maybe you want some kind of mix of the two, where the initial language (when visiting the root URL of the site?) is chosen based on Accept-Language, and thereafter defined by the URL? It's not entirely clear what behavior you want, so clarifying that is the first step. Then you'll probably need to write your own LocaleMiddleware that implements that behavior. Your first attempt at hacking LocaleURLMiddleware always uses Accept-Language in place of what's defined in the URL. Instead, you want to check the Accept-Language header further down, in the "if not locale:" section where it defaults to settings.LANGUAGE_CODE. Something more like this (untested code):

def process_request(self, request):
    locale, path = self.split_locale_from_request(request)
    locale_path = utils.locale_path(path, locale)

    if locale_path != request.path_info:
        if request.META.get("QUERY_STRING", ""):
            locale_path = "%s?%s" % (locale_path, request.META['QUERY_STRING'])
        return HttpResponseRedirect(locale_path)
    request.path_info = path
    if not locale:
        if request.META.has_key('HTTP_ACCEPT_LANGUAGE'):
            locale = utils.supported_language(request.META['HTTP_ACCEPT_LANGUAGE'].split(',')[0])
        else:
            locale = settings.LANGUAGE_CODE
    translation.activate(locale)
    request.LANGUAGE_CODE = translation.get_language()
Carl Meyer
Yes, I want a mix of btoh: Get the defaul language form the Accept-Language the first time, but use the the URL style after that.I don't know if also is important to store it in a cookie... But the behaviour I think is better is what you describe.
mamcx
Thanks for the input. I put your code but make a fix for the case of "/"
mamcx
this is giving error for me .Which file i need to change .It is giving error regarding locale, path = self.split_locale_from_request(request)
ha22109
@ha22109 Please see the note at the top of this answer. Upgrade to the most recent django-localeurl release (1.4) and set LOCALEURL_USE_ACCEPT_LANGUAGE to True, and you do not need to write any custom middleware at all.
Carl Meyer
@Carl Meyer I changed my settings.py file as per you heading and installed the latest localeurl release(1.4).But when i m changing my browser locale my site is not changing only the login part is changing as that is defined in django-admin only.Any idea why i m not able to see my translations.Do i need to set local_path
ha22109
A: 

i would need this behaviour too. are you using only your custom middleware now to get the language or are you still using the LocaleURLMiddleware and the LocaleMiddleware in combination with the middleware in the code above?

A: 

really it should be like this:

There can be multiple languages accepted by order of preference

def process_request(self, request):
    locale, path = utils.strip_path(request.path_info)
    if (not locale) or (locale==''):
        if request.META.has_key('HTTP_ACCEPT_LANGUAGE'):
        l = [x.strip()[:2] for x in request.META['HTTP_ACCEPT_LANGUAGE'].split(',')]
        for lang_code in l:
                locale = utils.supported_language(lang_code)
                if locale:
          break
        else:
            locale = settings.LANGUAGE_CODE
    locale_path = utils.locale_path(path, locale)
    if locale_path != request.path_info:
        if request.META.get("QUERY_STRING", ""):
            locale_path = "%s?%s" % (locale_path,
                    request.META['QUERY_STRING'])
        return HttpResponseRedirect(locale_path)
    request.path_info = path
    if not locale:
        try:
            locale = request.LANGUAGE_CODE
        except AttributeError:
            locale = settings.LANGUAGE_CODE
    translation.activate(locale)
    request.LANGUAGE_CODE = translation.get_language()
Stephane Konstantaropoulos