Skip to content

Latest commit

 

History

History
115 lines (91 loc) · 5.6 KB

i18n.md

File metadata and controls

115 lines (91 loc) · 5.6 KB

TolaActivity Internationalization Documentation

How Django discovers language preference

Django uses the LocaleMiddleware to discover language preference for individual users. The LocaleMiddleware enables language selection through the request context.

  • If we want to let each user specify their preferred language we need to use LocaleMiddleware. LocaleMiddleware determines a user's language preferences through the request context. It is activated by adding it to MIDDLEWARE in your settings (tola/settings/base.py) as one of the topmost classes, before CommonMiddleware, but after SessionMiddleware. MIDDLEWARE_CLASSES = ( ... 'django.middleware.locale.LocaleMiddleware', ... )

After first looking for a language prefix in the requested url, LocaleMiddleware will look for the LANGUAGE_SESSION_KEY in current user's session to determine language. (Failing that, it will look for a cookie, then at the Accept-Language HTTP header and finally in the global LANGUAGE_CODE setting. For further information about Django's algorithm to determine language preference see https://docs.djangoproject.com/en/1.11/topics/i18n/translation/)

  • In order for a user to select a preferred language with a button, the Django documentation recommends the LANGUAGE_SESSION_KEY option. In order for this to be successful, the LANGUAGE_SESSION_KEY has to be set in django.utils.translation. Django comes with a view, django.views.i18n.set_language(), that sets a user’s language preference and redirects to a given URL or, by default, back to the previous page. Activate this view by adding the following line to your URLconf:

url(r'^i18n/', include('django.conf.urls.i18n'))

(Source code: https://docs.djangoproject.com/en/1.11/_modules/django/conf/urls/i18n/, https://docs.djangoproject.com/en/1.11/_modules/django/views/i18n/)

Translation

In order for strings to be translated by Django, you have to add hooks, called translation strings to your templates and Python code. Django then extracts the translation strings into a message file where the translators will provide the equivalent strings in the target languages. Django looks for a locale directory listed in the LOCALE_PATH to create, compile and load message files with translation strings.

  • Create locale directory in tola project directory to save translation files. In this directory Django will create locale_code_for_each_languages/LC_MESSAGES directories for each language specified and within each a django.po file with the translation strings.

  • Specify the LOCALE_PATHS in tola/settings/base.py like so: LOCALE_PATHS = [ join(DJANGO_ROOT, 'locale'), ] This is where Django will create and look for translation files.

  • In tola/settings/base.py import ugettext_lazy function from django.utils.translation import ugettext_lazy as _ The u prefix represents unicode strings in Python 2. In Python 3 gettext() and ugettext() can be used interchangeably. The ugettext_lazy function is used here to mark the language names for translation. Different from the ugettext function which translate the string immediately, ugetttext_lazy stores a lazy reference to the string and translates the string when it is used in context, such as rendering a template.

  • Add list of languages available for selection. LANGUAGES = [ ('fr', _('French')), ('es', _('Spanish')), ('ar', _('Arabic')), ('en', _('English')), ]

  • Make sure USE_I18N is set to True.

Internationalization: in template code

Django uses two template tags for string translations in templates. The {% trans %} translates either a constant string or a variable content. The {% blocktrans %} {% endblocktrans %} tags enclose complex sentences consisting of variables and literals. In order to access these tags {% load i18n %} must be places toward the top of the template.

Internationalization: in Python code

  • In views import ugettext() as _, since they are callables which return a response every time a request is issued. (No need to store translation as a reference like it is done on models, forms and apps. Here the code is only executed once at startup.)

  • In models, forms and apps import ugettext_lazy() as _, because the code is exexuted at startup and the lazy version holds the reference to the translation string in case the user changes the languages.

Creating and compiling translation files

  • Before the creation of the messagefile make sure GNU gettext() is installed. [If deploying locally on MacOs, you either have to force link gettext() with brew link gettext --force (unlink it with brew unlink gettext after your translation is done) because it is not symlinked or, if using virtualenvwrapper, set a new PATH variable for your virtual environment. More information here: https://stackoverflow.com/questions/27220052/django-i18n-make-sure-you-have-gnu-gettext-tools/35579852]

  • To create or update a messagefile after tags have been added, run python manage.py makemessages -l fr (to make a messagefile in French). This will create a PO file. Django uses UTF-8 endcoding a default when generating these files. DO NOT CHANGE! Fill in translation strings and run python manage.py compilemessages -l fr. To reexamine all source code and templates for new translation strings and update all message files for all languages, run python manage.py makemessages -a.