Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django1.4: Generic way to set language links in template to work with i18n_patterns?

I started to play with new i18n_patterns in Django 1.4. Basically, i want to have language links for each of my supported languages on all of my templates headers. I have implemented my header as a separate template that is being included in other templates.

Is there a way to keep my header generic and solve this without passing the current view name or current url in template context? I guess it comes to a question how do i retrieve the current view or url from inside the template in a generic way.

BTW, i discovered that my previous approach with set_lang view to change the active language using the referrer will be broken with url_patterns as after changing the language it will change it back when redirected to the referred view.

Any help figuring out the common approach to set language links in templates to be used with url_patterns in a generic way would be appreciated!

like image 438
user1039384 Avatar asked Apr 19 '12 08:04

user1039384


People also ask

Which template tag is to be included for translating strings in a template?

Internationalization in template code Translations in Django templates use one of the two template tags, {% t %} and {% ut %} . These tags are used to translate strings or variables that contain strings.

Which templating language is supported default by Django?

A Django template is a text document or a Python string marked-up using the Django template language. Some constructs are recognized and interpreted by the template engine.

What is the name of the template tag that is used to define which child blocks can be filled in by the child templates?

This template, which we'll call base. html , defines an HTML skeleton document that you might use for a two-column page. It's the job of “child” templates to fill the empty blocks with content. In this example, the block tag defines three blocks that child templates can fill in.

What does {{ NAME }} mean in Django templates?

8. What does {{ name }} this mean in Django Templates? {{ name }} will be the output. It will be displayed as name in HTML. The name will be replaced with values of Python variable.


2 Answers

Basically, there are two different approaches to setting the language. You can use i18n_patterns to auto-magically prefix your urls with a language code, or you can use the django.views.i18n.set_language view to change the value of the language code in the user's session (or a cookie, if your project doesn't have session support).

It's worth noting the algorithm LocaleMiddleware uses to determine language:

  • First, it looks for the language prefix in the requested URL. This is only performed when you are using the i18n_patterns function in your root URLconf. See Internationalization: in URL patterns for more information about the language prefix and how to internationalize URL patterns.

  • Failing that, it looks for a django_language key in the current user's session.

  • Failing that, it looks for a cookie.The name of the cookie used is set by the LANGUAGE_COOKIE_NAME setting. (The default name is django_language.)

  • Failing that, it looks at the Accept-Language HTTP header. This header is sent by your browser and tells the server which language(s) you prefer, in order by priority. Django tries each language in the header until it finds one with available translations.

  • Failing that, it uses the global LANGUAGE_CODE setting.

The problem you're likely running into is that you can't use set_language to redirect from a url that's already being served with a language prefix, unless you specifically pass a next parameter in the POST data. This is because set_language will default to redirecting to the referrer, which will include the previous language prefix, which LocaleMiddleware will then see and serve the content in the old language (because it looks for a language prefix in the url before checking the django_language session variable).

An example, for clarity:

  1. Your user is on /en/news/article/1000, and clicks on the link which will post 'language=es' to set_language.

  2. set_language sees 'language=es', checks to see if 'es' is available, and then sets the 'django_language' session variable (or cookie) to 'es'

  3. Since you haven't set 'next', it redirects to the value of reqeuest.META['HTTP_REFERRER'], which is /en/news/article/1000

  4. LocaleMiddleware (source) sees the 'en' prefix in the url, and activates the 'en' language and sets request.LANGUAGE_CODE to 'en'

I see two possible solutions:

  1. Write your own set_language view (see the original source here), which will check for a language prefix in the referrer(use django.utils.translation.get_language_from_path), and change it to the prefix for the newly selected language before redirecting back to it.

  2. Use javascript to do the same operation client-side, and set the next POST parameter. Really this is kind of silly; it would probably be simpler to just use javascript to dynamically prepend all urls with the user's preferred language code, and forget about set_language altogether.

It seems that this new set_language view should probably be Django's default behavior. There was a ticket raised, which included a proposed implementation, but didn't really describe the problem and was subsequently closed. I suggest opening a new ticket with a better description of your use case, the problem caused by the existing set_language implementation, and your proposed solution.

like image 115
Chris Lawlor Avatar answered Oct 04 '22 15:10

Chris Lawlor


Actually, there's no need to fiddle with your view. Django has a handy slice tag, so you can just use {{ request.path|slice:'3:' }} as your link URL. This lops the language code prefix off so the language is set by the set_lang function.

like image 29
Keith Avatar answered Oct 04 '22 14:10

Keith