Dec 16, 2007

Django internationalisation

Multilingual web site with django

I have been recently working on a web application that needs to support several languages, English and French among others. This web application is built on top of Django which has a nice built in support for internationalisation, also known as i18n. However along the road of building this web application I have noticed some gaps between what was existing and what I was trying to achieve.

Here it is the list whithout any particular order:
- a multilingual flatpages
- a way to explicitely use display the language code (ie fr for French and en for English) directly in the URL. I do prefer instead of and rely on the browser settings to direct my user the right page. In addition I have the feeling that this would result in a much better indexation by search engine like Google or Yahoo, ...
- a simple UI to set the language.

The good news is that after some time, search and chat on IRC I have found a way to close all of them.

Multilingual flatpages
This has been amazingly simple thanks to django-multilingual, a library kindly developped by ???. In a matter of one or two hours I have forked "django.contrib.flatpages" and adapted it to support my specific needs. The new django application is name django multilingual and is available there . This might be integrated as battery inside django-multilingual library in the future. This application is fairly simple and intuitive to use once it is installed you can start adding you multilingual flatpages directly in "admin". For each multilingual flatpage you will be able to write a title and a content per language in my case french and english. You can see this application live there :

Language code explicit in the URL

I found a nice post there presenting a solution closing that gap, unfortunately I am unable to find the link again. The proposal is to add a middleware that intercept the request and proceed to the following operations:
* detect the language code in the URL
* Force the language to the one specified in the URL
* remove the language code from the URL this allows you to use your unchanged

[code] --- with the indentation

from django.utils.cache import patch_vary_headers
from django.utils import translation

class MultilingualURLMiddleware:
def get_language_from_request (self,request):
from django.conf import settings
import re
supported = dict(settings.LANGUAGES)
lang = settings.LANGUAGE_CODE[:2]
check = re.match(r"/(\w\w)/.*", request.path)
changed = False
if check is not None:
request.path = request.path[3:]
t =
if t in supported:
lang = t
if hasattr(request, "session"):
request.session["django_language"] = lang
response.set_cookie("django_language", lang)
changed = True
if not changed:
if hasattr(request, "session"):
lang = request.session.get("django_language", None)
if lang in supported and lang is not None:
return lang
lang = request.COOKIES.get("django_language", None)
if lang in supported and lang is not None:
return lang
return lang
def process_request(self, request):
from django.conf import settings
language = self.get_language_from_request(request)
if language is None:
language = settings.LANGUAGE_CODE[:2]
request.LANGUAGE_CODE = translation.get_language()
def process_response(self, request, response):
patch_vary_headers(response, ("Accept-Language",))
return response


A simple UI to select the language

As of today I am using a set of dynamicaly generated URLs but I might change this in the future to use a form instead. This is fairly simple as soon as you know all the pieces. :-)


{%trans "Set your language" %}

{% for language in LANGUAGES %}
{% ifequal LANGUAGE_CODE language.0 %}
{% else %}
{{ language.1 }}|
{% endifequal %}
{% endfor %}


As you have seen most of bricks I had to use to implement my multilingual web application were available out there on the internet. After all multilingual web application is not something new, but I was a bit surprised not to find any ready to use library suiting my requirements. Several reasons could explain this:
* I had some very unique requirements
* What I did was so simple that my expectation was to high
* I missed something important
* I should not have done it that way

I would be glad hear your opinion if you have one. I am sure that the solution presented there can be enhanced do not hesitate to post a comment on that blog to let me know how. :-)

PS1: You are free to copy, modify the code posted on this blog.
PS2: Does someone know how to fix the code indentation on