This is an in-progress draft, enjoy.

Localizing your app with translations

As a native English speaker in a predominantly English speaking country, I think its fair to say that most native English speakers in English speaking countries give little thought to how their software will be used by people who speak other languages or by those in other countries. This works against your benefit since the cost to you to make the software available in other languages is actually pretty low, and you make it far more available.

How translation works

Conceptually, translation is very simple.

Have you ever used a two-language dictionary, like a Spanish-English dictionary? You look up a word in one language, for instance, "dog" in English, and find the Spanish counterpart to it, "perro". Translation for most software - like Django web apps - is pretty similar. The key difference is the level of token you use.

In a dual langage dictionary, the token is typically a word or perhaps a phrase. In our apps, the tokens are strings. This means they could be single words or much longer text. So instead of translating:

The quick brown fox jumps over the lazy dog.

By looking up each individual word, we'd provide a translation for the entire string.

El zorro marrón rápido salta sobre el perro perezoso.

This might sound inefficient, adding an entire translated string, but there's really no sound way of translating individual words as tokens in a way that would make sense.

String translations work by a lookup of a base string against a dictionary for a specific language. The key here is that you need to provide that dictionary! This may seem confusing at first, but the system software called gettext only provides the machinery to retrieve translations. It isn't feasible to for this software to keep dictionaries for other languages and it wouldn't even work well. Aside form linguistic choices based on context, how it would it ever know to transate "Speedo" from US English to "budgie smuggler" in Australian English?

Let's walk through the mechancis of how all of this works.

Translatable strings

The first step in making your app localizable is ensuring that all of your user-facing strings in your app are translatable. If this is all you do you'll make many people live's and Django sites better.

Let's break this down to define what we mean by "user-facing strings" and "translatable".

User-facing strings are anything that an end user might see. It does not include exception messages or logs. It does include text that will be rendered for end-users though, like form validation errors, messages sent via contrib.messages, and to a lesser degree, templates (we'll explain "lesser degree" part shortly).

Translatable means you've wrapped the string with one of the gettext functions from Django's django.utils.translation. Now this means that if someone uses your app - and provides translation files as described below - they can have their translations provided instead of your original text, regardless of what language your wrote it in.

  1. Model field help text
  2. Model field verbose names
  3. Form validation messages
  4. Admin descriptions
  5. Template copy
  6. Request messages

As a short example, instead of:

messages.info(request, "You are logged in now.")

You'd write it like this:

messages.info(request, gettext("You are logged in now."))

The Django documentation does a thorough job of explaining the gettext different functions and how to use them.

A note on templates

Templates are an obvious source of user-facing text, however it's not always critical to include translations in app-provided templates. The root reason is that templates can be overridden and extended anyhow, so in simple cases this can be left up to whoever implements the site using your app. This applies mainly to situations where templates are used for things like text email content or trivial starter templates where developers are expected to use their own templates.

Of course, if your templates are non-trivial, then it makes sense to include translations to save other people from having to copy-and-paste or recreate document structures.

Adding translations

Once you have translation strings in your app you can create message files. Message files are text files with a .po extension and straightforward format that makes for easy, human readable lookups.

Here's a short excerpt from Django's es-MX message file.

msgid "String (up to %(max_length)s)"
msgstr "Cadena (máximo %(max_length)s)"

msgid "Comma-separated integers"
msgstr "Enteros separados por comas"

The .po message files are really just intermediary files for generating compiled .mo files, which are both compiled by and later read by the gettext utility. These are what allow for translations to actually show up for end-users.

The Django documentation details the how so we're not going to do that here. Rather, when should you include these files in your own standalone app?

Django itself includes localization files for dozens of languages, which is possible because of support from volunteer translators. The degree to which you should consider adding translations to your app will need to be based on the degree to which either you are actively interested in supporting said languages or you have available support in the form of users with the need to include translations and the knowledge to provide translated text to your app.

The upshot is, if you're not actively working with different languages yourself, it both suffices to make your app amenable to translation and is a proper stopping point.