Django internationalisation made easy with i18n
September 8, 2010 on 9:12 pm | In General, Javascript, Python, django | No CommentsOk so now you have your new django based killer app you’d like to translate it into several languages. Here’s a quick memo to get all this running quickly.
Django provides all the tools you need to do this effectively. You can use simple string translations or create more advanced rules with various plurals forms, variable interpolations…
First, be sure to use UTF-8 encode anywhere in your project :
- Save your file as UTF-8 (check your text editor)
- Declare python files encoding with this at the top of each python file (see PEP 263) :
# -*- encoding: UTF-8 -*- - Define your strings as unicode if needed
- Be warned : mixing encodings and charsets in a project can cause hasardous/mystical issues then massive headaches
Django provides several builtin tools to help you internationalise :
- makemessages command : scan your code to extract definition and create a .po file
- compilemessages command : compile your translations in the .po files to .mo
- django.middleware.locale.LocaleMiddleWare : Autodetect user language (from browser) or use session defined language (or fallback to project default)
- django.core.context_processors.i18n: add LANGUAGE_CODE and LANGUAGES variables to your templates
- django.conf.urls.i18n : a view that accepts a language POST parameter to change session language
- django.views.i18n.javascript_catalog : provides a javascript array with the translations and helpers functions gettext…
So lets internationalise our project :
Django make it easier to work with app level localisations and not project-global files.
So you must create a ‘locale’ subfolder for each app you want to localize.
Create a ‘fr’ and ‘en’ folder inside each ‘locale’ folder. (or more if needed)
Try first to translate a first app in a second language before going on.
Activate django.middleware.locale.LocaleMiddleWare and tweak your settings.py :
# -*- encoding: UTF-8 -*-
TIME_ZONE = 'Europe/Paris'
LANGUAGE_CODE = 'fr-FR'
USE_I18N = True
# see http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py
gettext = lambda s: s
LANGUAGES = (
('fr', gettext(u'French')),
('en', gettext('English')),
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
)
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.debug",
)
Add a lang toolbar to your template and connect to the django.conf.urls.i18n view :
Add a simple lang bar to your base template :
{% load i18n %}
<div id='langbar' style='text-align:right;padding-top:5px;'>
<form name='langform' style='margin:0px;display:inline;width:200px' action='/i18n/setlang/' method='POST'>
{% for LANG in LANGUAGES %}
<img src='{{ MEDIA_URL }}img/flags/{{ LANG.0 }}.png' title="{% trans LANG.1 %}" style='margin:5px;cursor:pointer' onclick="document.langform.language.value='{{ LANG.0 }}';document.langform.submit();">
{% endfor %}
<input name='language' type=hidden value="{{ LANGUAGE_CODE }}">
current LANG : {{ LANGUAGE_CODE }}
</form>
</div>
As you can see, when you enable i18n context processor, your templates can acces new variables like LANGUAGE_CODE or LANGUAGES
Now add the /i18n/setlang/ view in your urls.py.
This view accepts language POST parameter then redirect user to REFERER page (or one designed with ?next GET parameter). Selected language is then kept in session.
urlpatterns += patterns('',
(r'^i18n/', include('django.conf.urls.i18n')),
)
Now, check if when you submit the form, the selected language is kept in session. If not check your database (need the session table), restart your dev server or enable settings.DEBUG
If you can submit your lang and LANGUAGE_CODE is kept in session, bravo, your django is multilingual ready.
Internationalise your code
In your templates : just load i18n then replace every string with a trans tag
{% load i18n %}
<div class="main">{% trans "Welcome to our new website" %}></div>
{% block contents %}<img src="/img/intro-{{ LANGUAGE_CODE }}"/>{% trans "This is the intro" %}{% block %}
In your views : just import django.utils.translation.gettext then replace every string with gettext(thestring)
from django.utils.translation import gettext as _ # just a shortcut
def view(request):
hello = _('Hello, World')
return HttpResponse('<b>%s</b>' % hello)
Now each time you run the makemessages command for this app, it will detect these string and update this app django.po files accordingly.
Generate the .po, traduct then compile to .mo
- From this app folder, run
python ../manage.py makemessages --all
This will scan this app .py and .html files for gettext/trans calls and generate or update a django.po file for each lang.
- Now you can edit (manually) this old-fashionned-style .po file with your favorite text editor.
If your site default is English, edit app/locale/fr/LC_MESSAGES/django.po (and djangojs.po if needed) - Once all your strings are translated, run
python ../manage.py compilemessages
from the app root. This will generate .mo files from the .po
Now your templates and views should be automagically translated.
run makemessages/compilemessages commands to update the .po and .mo when you change some code. restart the web server.
Javascript internationalisation
Now your templates and views are correctly translated, you may also need to internationalise jour javascript files.
Django provide a simple solution that you can use in your projects
- the makemessages command takes a -d djangojs parameter to parse .js files and create a djangojs.po
- The django.views.i18n.javascript_catalog provides a way to acces the .po files from javascript
- This view serves a javascript file containing a ‘catalog’ array with translations and utilities functions such as gettext
Activate the view in your urls.py :
I tweaked the official rule a bit.
# urls.py
def jsi18n(request, packages = None, domain = None):
if not domain:
domain = 'djangojs'
from django.views.i18n import javascript_catalog
return javascript_catalog(request, domain, packages)
urlpatterns += patterns('',
(r'^jsi18n/?(?P<packages>[^/]+)?/?(?P<domain>[^/]+)?/?$', jsi18n ), # serves the javascript data
)
Add a javascript include in your template ( be sure to include it before any other javascript localised file) :
<script type="text/javascript" src="/jsi18n/main/djangojs"></script>
This url will serves you a javascript file from project/main/locale/fr/LC_MESSAGES/djangojs.po (if user lang is fr)
By default, this language definition returns the user LANGUAGE_CODE but you can override using ?language GET parameter
Now you just need to replace each string in your javascript files with a call to gettext.
alert( gettext("Ready to start ?") );
Maintain
When you add new code, always use calls to gettext instead of strings.
run makemessages to update the .po definitions
translate new strings in the .po files
run compilemessages to update
Voila Now your app can speak any UTF-8 lang, which is more than 600 languages
These are just the basics, check out for the full story http://docs.djangoproject.com/en/dev/topics/i18n/internationalization/
Notes/Gotchas :
- Using builtin dev server, you need to restart after a compilemessages
- Use famfamfam flag icons
- You must add your app to settings.INSTALLED_APPS if you want to use jsi18n view for this app
- Double check middlewares order, and session tables
Astuces Django
December 11, 2009 on 1:46 am | In Python, developpement, django, web | 1 Comment
Suite à mon quickstart Django, me revoici avec quelques astuces pour continuer.
Pour tester/développer avec Django, je rappelle qu’il vaut mieux utiliser le serveur de dev intégré, puis passer à Apache, nginx ou autre pour la production par la suite.
Il est important de lire pour commencer les principes de la philosophie Django ainsi que le ‘django coding style’
Ne hardcodez pas vos paths
- dans votre settings.py :
-
BASE_DIR = os.path.dirname(__file__)
- utilisez ensuite os.path.join avec settings.BASE_DIR ailleurs si besoin
- Pour importer les settings de votre projet, utilisez toujours
from django.conf import settings
Utilisez un fichier local_settings.py
- Créez un fichier local_settings.py qui contiendra uniquement les settings relatifs au déploiment de votre application : settings de base de données, smtp, debug… Vous n’aurez plus que celui la à modifier pour un nouveau déploiement.
Mettre en production avec Apache
- Pour une installation classique avec Apache, utilisez de préférence mod_wsgi. N’utilisez pas le serveur de dev intégré en production!
Debug AJAX plus pratique
- Si vous faites de l’Ajax, utilisez Firebug et le middleware AJAXSimpleExceptionResponse
Queysets : filters et excludes dynamiques
- Utilisez les dictionnaires pour filtrer dynamiquement vos querysets :
filtres['date__gte'] = datetime.datetime.today() – datetime.timedelta(dasy=7)
filtres['titre__icontains'] = ‘python’
excludes={}
excludes['epuise'] = True
qs = model.Livres.objects.exclude(**excludes).filter(**filtres)
Créez des applications modulaires
- Placez vos app dans un sous dossier ‘apps’
- Utiliser des objets génériques : le ContentType framework
Utilisez un script pour mettre à jour vos modèles
- Django ne gérant pas nativement les ALTER sur votre base de données, vous devez sauvegarder (manage.py dumpdata), reset votre base (manage.py reset) puis recréer votre base (manage.py syncdb) et recharger les données (manage.py loaddata).
- Utilisez plutot un script qui automatisera cette tache
Utilisez des décorateurs dans vos vues
- @login_required pour restreindre la vue aux utilisateurs loggés
- @user_passes_test(lambda u: u.has_perm(’polls.can_vote’)) pour restreindre la vue selon un test particulier
- créez vos propres décorateurs
Ne définissez qu’une fois vos urls
- Utilisez les named-urls pour ne plus harcoder vos urls
- Dans urls.py :
(r’^articles/list/(\d)+’, apps.main.list, name=”list-view”)
- Dans une vue :
return HttpResponseRedirect(reverse(’list-view’, args=[2007]))
- Dans un template :
<a href=”{% url list-view 2007 %}”>ma vue</a>
- Dans urls.py :
- Utilisez get_absolute_url() sur vos modèles pour affecter une url à chacun de vos objets
Des questions que vous vous posez surement :
- La différence entre null et blank dans vos modèles
- Comment toujours passer des variables à mes templates : les template contexts
De bons examples de coding-styles :
Différents cas de figures sur les formulaires Django : http://uswaretech.com/blog/2010/01/doing-things-with-django-forms/
Bien démarrer avec django
December 2, 2009 on 12:21 pm | In General, Python, developpement, django | 1 CommentCela fait maintenant presque deux ans que j’utilise intensivement le framework Django pour toutes mes applications web, et j’ai enfin réuni assez d’éléments pour pouvoir vous livrer un petit ‘QuickStart’ qui vous permettra de démarrer rapidement.
Contrairement à d’autres frameworks web, Django n’est pas orienté CMS ou HTML. Vous pouvez tout autant créer un site HTML/Ajax, une API RESTFUL http ou une application en ligne de commande.
Django permet de coder toute la partie serveur de votre application, mais pour la partie ‘client’, c.a.d. le HTML par exemple, vous devrez vous débrouiller tout seul ou utiliser un autre framework, jQuery par exemple, ou ExtJs.

Pourquoi Django ?
Open Source
Portable
Langage Python
Prototypage rapide
Evolutivité
Abstration ORM
Supporté par Google AppEngine (avec restrictions)
Excellente documentation
Fonctionnalités principales :
- ORM : permet une abstraction de la base de données et du SQL, ce qui fait que vos applications peuvent tourner sur : SQLlite, MySQL, SQLserver, Oracle, PostGres…
- Admin automatique : une fois vos modèles définis, ils sont de suite accessible dans l’interface d’admin automatique, et vous pouvez toute de suite créer objets
- Templates : une gestion des templates très poussée, avec gestion des héritages, des filtres et ‘customs tags’.
- Shell intégré : Tout votre code est également accessible directement depuis un shell intégré
- Gestion des utilisateurs : Toute la partie utilisateurs, comptes, login, sécurité et permissions est déjà disponible sans efforts
Inconvénients :
- Peu d’hébergeurs mais cela évolue : http://code.djangoproject.com/wiki/DjangoFriendlyWebHosts
- C’est surtout un avantage, mais le projet évoluant très vite, vous devrez coder avec et pour une version spécifique de Django. Et vous ne mettrez à jour django pour tel projet seulement après avoir consulté cette page : http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges
A noter que Django est une librairie python, vous pouvez n’utiliser que les fonctions dont vous avez besoin, même en ’standalone’ (hors du web). Et vous pouvez tout modifier, étendre et améliorer à souhait.
La première chose à faire avant de se lancer dans Django est déjà de connaitre un minimum le langage python et sa ‘magie’. Le livre ‘Think like a computer scientist‘ est à lire, Instant Python pour les préssés, et “A byte of python” (en francais).
C’est parti
Installez python (2.5 ou 2.6) sur votre machine, et récupérez la dernière version de Django. Le repertoire ‘django’ de cette archive doit se trouver dans le dossier ‘lib/site-packages’ de votre installation de Python. Si vous souhaitez utiliser MySQL comme serveur, installez python-mysqldb. Sinon, SQLlite fera très bien l’affaire pour démarrer !
Pour tester si votre installation de python/django est correcte :
Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.
>>>import django
>>>print django.VERSION
(1, 0, 2, ‘final’, 0)
>>>
Si vous avez une erreur lors de l’import, alors votre dossier ‘django’ n’est pas dans votre dossier python\lib\site-packages, vérifiez.
Si l’install est correcte, alors vous pouvez créer votre premier projet django.
Exemple sur windows :
Ouvrez un shell, et placez vous dans votre dossier de travail, puis lancez la commande django-admin.py startproject
c:\dev\django>c:\Python25\lib\site-packages\django\bin\django-admin.py startproject projet1
Un dossier ‘projet1′ a été crée et contient les fichier de base :
- settings.py : configuration du projt, base de données, emails…
- urls.py : la configuration des urls de votre projet
- manage.py : la commande qui permet de lancer le serveur, mettre a jour les bases et effectuer des opérations de maintenance.
- __init__.py : ce fichier permet simplement à Python d’interpréter le dossier en tant que ‘module’
Pour développer un projet Django, utilisez le ’serveur de dev’ intégré (commande manage.py runserver), mais pour la production, vous devrez mettre en place Apache+WSGI, Nginx ou un autre serveur.
Lancez le serveur pour vérifier que votre projet est bien crée :
c:\dev\django>manage.py runserver
Validating models…
0 errors found
Django version 1.0-alpha-SVN-8225, using settings ‘projet1.settings’
Development server is running at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Maintenant vous pouvez ouvrir votre browser à cette adresse : http://127.0.0.1:8000/
Modifiez le fichier settings.py, puis suivez le premier tutorial pour commencer à faire joujou.
Je reviens prochainement pour la suite.
Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds.
Valid XHTML and CSS. ^Top^