La documentation sur l'internationalisation d'une application Django m'ayant laissé perplexe tant en anglais qu'en français, voici un petit résumé de ce qu'il faut faire.

Dans settings.py, il vous faut :

  • Avoir un language code correctement configuré
  • Que USE_I18N soit bien activé - c'est le cas par défaut
  • Ajouter 'django.middleware.locale.LocaleMiddleware', à la liste de vos middleware. Attention l'ordre compte - cf documentation

Exemple :

[...]
 
LANGUAGE_CODE = 'fr'
 
USE_I18N = True
 
[...]
 
MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.doc.XViewMiddleware',
)
 
[...]

Dans app/models.py :

  • Importer gettext_lazy fourni par django. gettext_lazy() s'utlise pour traduire les champs des modèles
  • Pour éviter d'écrire gettext_lazy('Single'), on peut utiliser le système d'alias pour n'écrire que : _('Single') .
  • Si vous êtes en unicode, c'est ugettext_lazy() et non gettext_lazy() bien sûr,

Exemple :

# -*- coding: utf-8 -*-
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
 
"""
Profile
 
This object is used to provide some common information regarding the profile of a user.
"""
 
class Profile(models.Model):
    CIVILITY_CHOICES = (
         ('single', _('Single')),
         ('taken', _('Taken')),
    )
    who = models.ForeignKey(User, unique=True, verbose_name=_('Person'),)
    photo = models.ImageField(height_field="80", width_field="80", upload_to="photos", blank=True)
    street = models.CharField(_('Address 1'), maxlength=100)
    street_bis = models.CharField(_('Address 2'), maxlength=100, blank=True)
    zipcode = models.IntegerField(_('Zip code'), maxlength=5)
    city = models.CharField(_('City'), maxlength=100)
    phone = models.CharField(_('Phone'), maxlength=20)
    mobile = models.CharField(_('Mobile'), maxlength=20, blank=True)
    civility = models.CharField(_('Status'), maxlength=20, choices=CIVILITY_CHOICES)
    birthdate = models.DateField(_('Birth date'))
    children = models.IntegerField(_('Children'), blank=True, null=True)

Dans le répertoire de votre application, créer un répertoire "locale" :

mkdir -p /chemin/de/votre/projet/django/app/locale

Ensuite il vous faut générer votre fichier de langue .po correspondant à votre langue (ici : fr):

/usr/lib/python2.5/site-packages/django/bin/make-messages -l fr

Saisissez alors la traduction dans app/locale/<langue>/LC_MESSAGES/django.po

Exemple :

#: models.py:14
msgid "Single"
msgstr "Célibataire"

Compiler ensuite votre fichier de langue :

/usr/lib/python2.5/site-packages/django/bin/compile-messages

Vous obtenez alors un fichier app/locale/<langue>/LC_MESSAGES/django.mo

Dans votre template :

  • ajouter {% load i18n %} en tête de template

Ex :

{% extends "base.html" %}
{% load markup %}
{% load i18n %}

Si vous utilisez le serveur de développement, il faut le redémarrer pour qu'il prenne en compte les fichiers de langue compilés (idem lors d'une mise à jour des fichiers de langue).

Et voilà, savourez le travail...

Merci à benoitc et anhj de #django-fr pour m'avoir aidé à trouver mon erreur (ie avoir créer dans le répertoire de mon application une structure conf/locale au lieu de locale. La première ne s'utilise que pour l'ensemble d'un projet django).