Recrute développeur PHP

September 24, 2010 on 4:30 pm | In actu informatique, developpement, emploi, web | No Comments

Nous recherchons pour l’un de nos clients, société spécialisée en développement d’applications web de nouvelle génération (interfaces riches), deux développeurs PHP expérimentés.

Vous intégrerez une équipe d’une quinzaine de développeurs dans le quartier de l’Opéra à Paris.

Salaire à négocier + Primes.

Nous envoyer votre CV et quelques mots sur vos compétences et motivations sur contact@revolunet.com

Django internationalisation made easy with i18n

September 8, 2010 on 9:12 pm | In General, Javascript, Python, django | No Comments

Ok 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

  1. 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.

  2. 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)
  3. 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

Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds. Valid XHTML and CSS. ^Top^