| 1 | | ====================== |
|---|
| 2 | | How to do translations |
|---|
| 3 | | ====================== |
|---|
| 4 | | |
|---|
| 5 | | Django has support for internationalization of program strings and template |
|---|
| 6 | | content. Translations use the ``gettext`` library to produce strings in several |
|---|
| 7 | | languages. Here's an overview of how translation works with Django. |
|---|
| 8 | | |
|---|
| 9 | | The goal of this document is to explain how to use translations in projects, |
|---|
| 10 | | how to add translations to Django patches and how to update and create |
|---|
| 11 | | translation files. |
|---|
| 12 | | |
|---|
| 13 | | Using translations in Python |
|---|
| 14 | | ============================ |
|---|
| 15 | | |
|---|
| 16 | | The translation machinery in Django uses the standard ``gettext`` module that |
|---|
| 17 | | comes with Python. Django uses in its own functions and classes, but it uses |
|---|
| 18 | | standard ``gettext`` machinery under the hood. |
|---|
| 19 | | |
|---|
| 20 | | To translate strings in your code, use one of the ``gettext`` helper functions. |
|---|
| 21 | | There are essentially two ways to use them: |
|---|
| 22 | | |
|---|
| 23 | | * Use the ``_()`` function, which is available globally. This function |
|---|
| 24 | | translates any string value. |
|---|
| 25 | | * Use ``django.utils.translation`` and import ``gettext`` or |
|---|
| 26 | | ``gettext_noop`` from there. ``gettext`` is identical to ``_()``. |
|---|
| 27 | | |
|---|
| 28 | | Note one important thing about translations: The system can only translate |
|---|
| 29 | | strings it knows about. That means you have to mark strings for translation. |
|---|
| 30 | | This is done either by calling ``_()``, ``gettext()`` or ``gettext_noop()`` on |
|---|
| 31 | | string constants. You can translate variable values or computed values, but the |
|---|
| 32 | | system needs to know those strings beforehand. |
|---|
| 33 | | |
|---|
| 34 | | The usual method is to build your strings using string interpolation and using |
|---|
| 35 | | the ``gettext`` functions to do the actual translation. Example:: |
|---|
| 36 | | |
|---|
| 37 | | def hello_world(request, name, site): |
|---|
| 38 | | page = _('Hello %(name)s, welcome to %(site)s!') % { |
|---|
| 39 | | 'name': name, |
|---|
| 40 | | 'site': site, |
|---|
| 41 | | } |
|---|
| 42 | | return HttpResponse(page) |
|---|
| 43 | | |
|---|
| 44 | | This short snippet shows one important thing: You shouldn't use positional |
|---|
| 45 | | string interpolation (e.g., ``%s`` or ``%d``). Use the named string |
|---|
| 46 | | interpolation (e.g., ``%(name)s``), instead. Do this because other languages |
|---|
| 47 | | might require reordering of text. |
|---|
| 48 | | |
|---|
| 49 | | The other two helper functions are similar:: |
|---|
| | 1 | ==================== |
|---|
| | 2 | Internationalization |
|---|
| | 3 | ==================== |
|---|
| | 4 | |
|---|
| | 5 | Django has full support for internationalization of text in code and templates. |
|---|
| | 6 | Here's an overview of how translation works in Django. |
|---|
| | 7 | |
|---|
| | 8 | .. admonition:: Behind the scenes |
|---|
| | 9 | |
|---|
| | 10 | Django's translation machinery uses the standard ``gettext`` module that |
|---|
| | 11 | comes with Python. |
|---|
| | 12 | |
|---|
| | 13 | Overview |
|---|
| | 14 | ======== |
|---|
| | 15 | |
|---|
| | 16 | The goal of internationalization is to allow a single Web application to offer |
|---|
| | 17 | its content and functionality in multiple languages. |
|---|
| | 18 | |
|---|
| | 19 | You, the Django developer, can accomplish this goal by adding a minimal amount |
|---|
| | 20 | of hooks to your Python code and templates. These hooks are called |
|---|
| | 21 | **translation strings**. They tell Django: "This text should be translated into |
|---|
| | 22 | the end user's language, if a translation for this text is available in that |
|---|
| | 23 | language." |
|---|
| | 24 | |
|---|
| | 25 | Django takes care of using these hooks to translate Web apps, on the fly, |
|---|
| | 26 | according to users' language preferences. |
|---|
| | 27 | |
|---|
| | 28 | Essentially, Django does two things: |
|---|
| | 29 | |
|---|
| | 30 | * It lets developers and template authors specify which parts of their apps |
|---|
| | 31 | should be translatable. |
|---|
| | 32 | * It uses these hooks to translate Web apps for particular users according |
|---|
| | 33 | to their language preferences. |
|---|
| | 34 | |
|---|
| | 35 | How to internationalize your app: in three steps |
|---|
| | 36 | ------------------------------------------------ |
|---|
| | 37 | |
|---|
| | 38 | 1. Embed translation strings in your Python code and templates. |
|---|
| | 39 | 2. Get translations for those strings, in whichever languages you want to |
|---|
| | 40 | support. |
|---|
| | 41 | 2. Activate the locale middleware in your Django settings. |
|---|
| | 42 | |
|---|
| | 43 | How to specify translation strings |
|---|
| | 44 | ================================== |
|---|
| | 45 | |
|---|
| | 46 | Translation strings specify "This text should be translated." These strings can |
|---|
| | 47 | appear in your Python code and templates. It's your responsibility to mark |
|---|
| | 48 | translatable strings; the system can only translate strings it knows about. |
|---|
| | 49 | |
|---|
| | 50 | In Python code |
|---|
| | 51 | -------------- |
|---|
| | 52 | |
|---|
| | 53 | Standard translation |
|---|
| | 54 | ~~~~~~~~~~~~~~~~~~~~ |
|---|
| | 55 | |
|---|
| | 56 | Specify a translation string by using the function ``_()``. (Yes, the name of |
|---|
| | 57 | the function is the "underscore" character.) This function is available |
|---|
| | 58 | globally in any Python module; you don't have to import it. |
|---|
| | 59 | |
|---|
| | 60 | In this example, the text ``"Welcome to my site."`` is marked as a translation |
|---|
| | 61 | string:: |
|---|
| | 62 | |
|---|
| | 63 | def my_view(request): |
|---|
| | 64 | output = _("Welcome to my site.") |
|---|
| | 65 | return HttpResponse(output) |
|---|
| | 66 | |
|---|
| | 67 | The function ``django.utils.translation.gettext()`` is identical to ``_()``. |
|---|
| | 68 | This example is identical to the previous one:: |
|---|
| 52 | | def hello_world(request, name, site): |
|---|
| 53 | | page = gettext('Hello %(name)s, welcome to %(site)s!') % { |
|---|
| 54 | | 'name': name, |
|---|
| 55 | | 'site': site, |
|---|
| 56 | | } |
|---|
| 57 | | return HttpResponse(page) |
|---|
| 58 | | |
|---|
| 59 | | The difference here is that ``gettext`` is explicitly imported. |
|---|
| 60 | | |
|---|
| 61 | | Two important helper functions are available: ``gettext`` and ``gettext_noop``. |
|---|
| 62 | | |
|---|
| 63 | | * ``gettext`` is just like ``_()`` -- it translates its argument. |
|---|
| 64 | | * ``gettext_noop`` is different. It marks a string for inclusion into the |
|---|
| 65 | | message file but doesn't do translation. Instead, the string is later |
|---|
| 66 | | translated from a variable. Use this if you have constant strings that |
|---|
| 67 | | should be stored in the source language because they are exchanged over |
|---|
| 68 | | systems or users -- such as strings in a database -- but should be |
|---|
| 69 | | translated at the last possible point in time, such as when the string is |
|---|
| 70 | | presented to the user. |
|---|
| 71 | | |
|---|
| 72 | | One function, ``django.utils.translation.gettext_lazy()``, isn't available in |
|---|
| 73 | | the standard ``gettext`` module. Use it for lazily translated strings, such as |
|---|
| 74 | | messages in Django models that are stored internally and translated on access |
|---|
| 75 | | -- but not translated on storage, as that would only take the default language |
|---|
| 76 | | into account. |
|---|
| | 71 | def my_view(request): |
|---|
| | 72 | output = gettext("Welcome to my site.") |
|---|
| | 73 | return HttpResponse(output) |
|---|
| | 74 | |
|---|
| | 75 | Translation works on computed values. This example is identical to the previous |
|---|
| | 76 | two:: |
|---|
| | 77 | |
|---|
| | 78 | def my_view(request): |
|---|
| | 79 | words = ['Welcome', 'to', 'my', 'site.'] |
|---|
| | 80 | output = _(' '.join(words)) |
|---|
| | 81 | return HttpResponse(output) |
|---|
| | 82 | |
|---|
| | 83 | Translation works on variables. Again, here's an identical example:: |
|---|
| | 84 | |
|---|
| | 85 | def my_view(request): |
|---|
| | 86 | sentence = 'Welcome to my site.' |
|---|
| | 87 | output = _(sentence) |
|---|
| | 88 | return HttpResponse(output) |
|---|
| | 89 | |
|---|
| | 90 | The strings you pass to ``_()`` or ``gettext()`` can take placeholders, |
|---|
| | 91 | specified with Python's standard named-string interpolation syntax. Example:: |
|---|
| | 92 | |
|---|
| | 93 | def my_view(request, n): |
|---|
| | 94 | output = _('%(name)s is my name.') % {'name': n} |
|---|
| | 95 | return HttpResponse(output) |
|---|
| | 96 | |
|---|
| | 97 | This technique lets language-specific translations reorder the placeholder |
|---|
| | 98 | text. For example, an English translation may be ``"Adrian is my name."``, |
|---|
| | 99 | while a Spanish translation may be ``"Me llamo Adrian."`` -- with the |
|---|
| | 100 | placeholder (the name) placed after the translated text instead of before it. |
|---|
| | 101 | |
|---|
| | 102 | For this reason, you should use named-string interpolation (e.g., ``%(name)s``) |
|---|
| | 103 | instead of positional interpolation (e.g., ``%s`` or ``%d``). If you used |
|---|
| | 104 | positional interpolation, translations wouldn't be able to reorder placeholder |
|---|
| | 105 | text. |
|---|
| | 106 | |
|---|
| | 107 | Marking strings as no-op |
|---|
| | 108 | ~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| | 109 | |
|---|
| | 110 | Use the function ``django.utils.translation.gettext_noop()`` to mark a string |
|---|
| | 111 | as a translate string without translating it. The string is later translated |
|---|
| | 112 | from a variable. |
|---|
| | 113 | |
|---|
| | 114 | Use this if you have constant strings that should be stored in the source |
|---|
| | 115 | language because they are exchanged over systems or users -- such as strings in |
|---|
| | 116 | a database -- but should be translated at the last possible point in time, such |
|---|
| | 117 | as when the string is presented to the user. |
|---|
| | 118 | |
|---|
| | 119 | Lazy translation |
|---|
| | 120 | ~~~~~~~~~~~~~~~~ |
|---|
| | 121 | |
|---|
| | 122 | Use the function ``django.utils.translation.gettext_lazy()`` to translate |
|---|
| | 123 | strings lazily -- when the value is accessed rather than when the |
|---|
| | 124 | ``gettext_lazy()`` function is called. |
|---|
| 181 | | In this case both the filter and the tag will see the already translated string, so they |
|---|
| 182 | | don't need to be aware of translations. And both strings will be pulled out of the templates |
|---|
| 183 | | for translation and stored in the .po files. |
|---|
| 184 | | |
|---|
| 185 | | The ``setlang`` redirect view |
|---|
| 186 | | ----------------------------- |
|---|
| 187 | | |
|---|
| 188 | | Django comes with a view, ``django.views.i18n.set_language`` that sets a user's |
|---|
| 189 | | language preference and redirects back to the previous page. For example, put |
|---|
| 190 | | this HTML code in your template:: |
|---|
| 191 | | |
|---|
| 192 | | <form action="/i18n/setlang/" method="POST"> |
|---|
| | 240 | In this case, both the tag and the filter will see the already-translated |
|---|
| | 241 | string, so they don't need to be aware of translations. |
|---|
| | 242 | |
|---|
| | 243 | How to create language files |
|---|
| | 244 | ============================ |
|---|
| | 245 | |
|---|
| | 246 | Once you've tagged your strings for later translation, you need to write (or |
|---|
| | 247 | obtain) the language translations themselves. Here's how that works. |
|---|
| | 248 | |
|---|
| | 249 | Message files |
|---|
| | 250 | ------------- |
|---|
| | 251 | |
|---|
| | 252 | The first step is to create a **message file** for a new language. A message |
|---|
| | 253 | file is a plain-text file, representing a single language, that contains all |
|---|
| | 254 | available translation strings and how they should be represented in the given |
|---|
| | 255 | language. Message files have a ``.po`` file extension. |
|---|
| | 256 | |
|---|
| | 257 | Django comes with a tool, ``bin/make-messages.py``, that automates the creation |
|---|
| | 258 | and upkeep of these files. |
|---|
| | 259 | |
|---|
| | 260 | To create or update a message file, run this command:: |
|---|
| | 261 | |
|---|
| | 262 | bin/make-messages.py -l de |
|---|
| | 263 | |
|---|
| | 264 | ...where ``de`` is the language code for the message file you want to create. |
|---|
| | 265 | (The language code, in this case, is in locale format. So, for example, it's |
|---|
| | 266 | ``pt_BR`` for Brazilian and ``de_AT`` for Austrian German.) |
|---|
| | 267 | |
|---|
| | 268 | The script should be run from one of three places:: |
|---|
| | 269 | |
|---|
| | 270 | * The root ``django`` directory (not a Subversion checkout, but the one |
|---|
| | 271 | that is linked-to via ``$PYTHONPATH`` or is located somewhere on that |
|---|
| | 272 | path). |
|---|
| | 273 | * The root directory of your Django project. |
|---|
| | 274 | * The root directory of your Django app. |
|---|
| | 275 | |
|---|
| | 276 | The script runs over the entire Django source tree and pulls out all strings |
|---|
| | 277 | marked for translation. It creates (or updates) a message file in the directory |
|---|
| | 278 | ``conf/locale``. In the ``de`` example, the file will be |
|---|
| | 279 | ``conf/locale/de/LC_MESSAGES/django.po``. |
|---|
| | 280 | |
|---|
| | 281 | .. admonition:: No gettext? |
|---|
| | 282 | |
|---|
| | 283 | If you don't have the ``gettext`` utilities installed, ``make-messages.py`` |
|---|
| | 284 | will create empty files. If that's the case, either install the ``gettext`` |
|---|
| | 285 | utilities or just copy the English message file |
|---|
| | 286 | (``conf/locale/en/LC_MESSAGES/django.po``) and use it as a starting point; |
|---|
| | 287 | it's just an empty translation file. |
|---|
| | 288 | |
|---|
| | 289 | The format of ``.po`` files is straightforward. Each ``.po`` file contains a |
|---|
| | 290 | small bit of metadata, such as the translation maintainer's contact |
|---|
| | 291 | information, but the bulk of the file is a list of **messages** -- simple |
|---|
| | 292 | mappings between translation strings and the actual translated text for the |
|---|
| | 293 | particular language. |
|---|
| | 294 | |
|---|
| | 295 | For example, if your Django app contained a translation string for the text |
|---|
| | 296 | ``"Welcome to my site.", like so:: |
|---|
| | 297 | |
|---|
| | 298 | _("Welcome to my site.") |
|---|
| | 299 | |
|---|
| | 300 | ...then ``make-messages.py`` will have created a ``.po`` file containing the |
|---|
| | 301 | following snippet -- a message:: |
|---|
| | 302 | |
|---|
| | 303 | #: path/to/python/module.py:23 |
|---|
| | 304 | msgid "Welcome to my site." |
|---|
| | 305 | msgstr "" |
|---|
| | 306 | |
|---|
| | 307 | A quick explanation: |
|---|
| | 308 | |
|---|
| | 309 | * ``msgid`` is the translation string, which appears in the source. Don't |
|---|
| | 310 | change it. |
|---|
| | 311 | * ``msgstr`` is where you put the language-specific translation. It starts |
|---|
| | 312 | out empty, so it's your responsibility to change it. Make sure you keep |
|---|
| | 313 | the quotes around your translation. |
|---|
| | 314 | * As a convenience, each message includes the filename and line number |
|---|
| | 315 | from which the translation string was gleaned. |
|---|
| | 316 | |
|---|
| | 317 | Long messages are a special case. There, the first string directly after the |
|---|
| | 318 | ``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be |
|---|
| | 319 | written over the next few lines as one string per line. Those strings are |
|---|
| | 320 | directlyconcatenated. Don't forget trailing spaces within the strings; |
|---|
| | 321 | otherwise, they'll be tacked together without whitespace! |
|---|
| | 322 | |
|---|
| | 323 | .. admonition:: Mind your charset |
|---|
| | 324 | |
|---|
| | 325 | When creating a ``.po`` file with your favorite text editor, first edit |
|---|
| | 326 | the charset line (search for ``"CHARSET"``) and set it to the charset |
|---|
| | 327 | you'll be using to edit the content. Generally, utf-8 should work for most |
|---|
| | 328 | languages, but ``gettext`` can handle any charset you throw at it. |
|---|
| | 329 | |
|---|
| | 330 | To reexamine all source code and templates for new translation strings and |
|---|
| | 331 | update all message files for **all** languages, run ``make-messages.py -a``. |
|---|
| | 332 | |
|---|
| | 333 | Compiling message files |
|---|
| | 334 | ----------------------- |
|---|
| | 335 | |
|---|
| | 336 | After you create your message file -- and each time you make changes to it -- |
|---|
| | 337 | you'll need to compile it into a more efficient form, for use by ``gettext``. |
|---|
| | 338 | Do this with the ``bin/compile-messages.py`` utility. |
|---|
| | 339 | |
|---|
| | 340 | This tool runs over all available ``.po`` files and creates ``.mo`` files, |
|---|
| | 341 | which are binary files optimized for use by ``gettext``. In the same directory |
|---|
| | 342 | from which you ran ``make-messages.py``, run ``compile-messages.py`` like |
|---|
| | 343 | this:: |
|---|
| | 344 | |
|---|
| | 345 | bin/compile-messages.py |
|---|
| | 346 | |
|---|
| | 347 | That's it. Your translations are ready for use. |
|---|
| | 348 | |
|---|
| | 349 | .. admonition:: A note to translators |
|---|
| | 350 | |
|---|
| | 351 | If you've created a translation in a language Django doesn't yet support, |
|---|
| | 352 | please let us know! We'll add it to the global list of available languages |
|---|
| | 353 | in the global Django settings (``settings.LANGUAGES``). |
|---|
| | 354 | |
|---|
| | 355 | How Django discovers language preference |
|---|
| | 356 | ======================================== |
|---|
| | 357 | |
|---|
| | 358 | Once you've prepared your translations -- or, if you just want to use the |
|---|
| | 359 | translations that come with Django -- you'll just need to activate translation |
|---|
| | 360 | for your app. |
|---|
| | 361 | |
|---|
| | 362 | Behind the scenes, Django has a very flexible model of deciding which language |
|---|
| | 363 | should be used -- installation-wide, for a particular user, or both. |
|---|
| | 364 | |
|---|
| | 365 | To set an installation-wide language preference, set ``LANGUAGE_CODE`` in your |
|---|
| | 366 | `settings file`_. Django uses this language as the default translation -- the |
|---|
| | 367 | final attempt if no other translator finds a translation. |
|---|
| | 368 | |
|---|
| | 369 | If all you want to do is run Django with your native language, and a language |
|---|
| | 370 | file is available for your language, all you need to do is set |
|---|
| | 371 | ``LANGUAGE_CODE``. |
|---|
| | 372 | |
|---|
| | 373 | If you want to let each individual user specify which language he or she |
|---|
| | 374 | prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language |
|---|
| | 375 | selection based on data from the request. It customizes content for each user. |
|---|
| | 376 | |
|---|
| | 377 | To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'`` |
|---|
| | 378 | to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you |
|---|
| | 379 | should follow these guidelines: |
|---|
| | 380 | |
|---|
| | 381 | * Make sure it's one of the first middlewares installed. |
|---|
| | 382 | * It should come after ``SessionMiddleware``, because ``LocaleMiddleware`` |
|---|
| | 383 | makes use of session data. |
|---|
| | 384 | |
|---|
| | 385 | For example, your ``MIDDLEWARE_CLASSES`` might look like this:: |
|---|
| | 386 | |
|---|
| | 387 | MIDDLEWARE_CLASSES = ( |
|---|
| | 388 | 'django.middleware.sessions.SessionMiddleware', |
|---|
| | 389 | 'django.middleware.locale.LocaleMiddleware', |
|---|
| | 390 | 'django.middleware.common.CommonMiddleware', |
|---|
| | 391 | ) |
|---|
| | 392 | |
|---|
| | 393 | (For more on middleware, see the `middleware documentation`_.) |
|---|
| | 394 | |
|---|
| | 395 | ``LocaleMiddleware`` tries to determine the user's language preference by |
|---|
| | 396 | following this algorithm: |
|---|
| | 397 | |
|---|
| | 398 | * First, it looks for a ``django_language`` key in the the current user's |
|---|
| | 399 | `session`_. |
|---|
| | 400 | * Failing that, it looks for a cookie called ``django_language``. |
|---|
| | 401 | * Failing that, it looks at the ``Accept-Language`` HTTP header. This |
|---|
| | 402 | header is sent by your browser and tells the server which language(s) you |
|---|
| | 403 | prefer, in order by priority. Django tries each language in the header |
|---|
| | 404 | until it finds one with available translations. |
|---|
| | 405 | * Failing that, it uses the global ``LANGUAGE_CODE`` setting. |
|---|
| | 406 | |
|---|
| | 407 | Notes: |
|---|
| | 408 | |
|---|
| | 409 | * In each of these places, the language preference is expected to be in the |
|---|
| | 410 | standard language format, as a string. For example, Brazilian is |
|---|
| | 411 | ``pt-br``. |
|---|
| | 412 | * If a base language is available but the sublanguage specified is not, |
|---|
| | 413 | Django uses the base language. For example, if a user specifies ``de-at`` |
|---|
| | 414 | (Austrian German) but Django only has ``de`` available, Django uses |
|---|
| | 415 | ``de``. |
|---|
| | 416 | |
|---|
| | 417 | Once ``LocaleMiddleware`` determines the user's preference, it makes this |
|---|
| | 418 | preference available as ``request.LANGUAGE_CODE`` for each `request object`_. |
|---|
| | 419 | Feel free to read this value in your view code. Here's a simple example:: |
|---|
| | 420 | |
|---|
| | 421 | def hello_world(request, count): |
|---|
| | 422 | if request.LANGUAGE_CODE == 'de-at': |
|---|
| | 423 | return HttpResponse("You prefer to read Austrian German.") |
|---|
| | 424 | else: |
|---|
| | 425 | return HttpResponse("You prefer to read another language.") |
|---|
| | 426 | |
|---|
| | 427 | Note that, with static (middleware-less) translation, the language is in |
|---|
| | 428 | ``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's |
|---|
| | 429 | in ``request.LANGUAGE_CODE``. |
|---|
| | 430 | |
|---|
| | 431 | .. _settings file: http://www.djangoproject.com/documentation/settings/ |
|---|
| | 432 | .. _middleware documentation: http://www.djangoproject.com/documentation/middleware/ |
|---|
| | 433 | .. _session: http://www.djangoproject.com/documentation/sessions/ |
|---|
| | 434 | .. _request object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects |
|---|
| | 435 | |
|---|
| | 436 | The ``set_language`` redirect view |
|---|
| | 437 | ================================== |
|---|
| | 438 | |
|---|
| | 439 | As a convenience, Django comes with a view, ``django.views.i18n.set_language``, |
|---|
| | 440 | that sets a user's language preference and redirects back to the previous page. |
|---|
| | 441 | |
|---|
| | 442 | Activate this view by adding the following line to your URLconf:: |
|---|
| | 443 | |
|---|
| | 444 | (r'^i18n/', include('django.conf.urls.i18n'), |
|---|
| | 445 | |
|---|
| | 446 | (Note that this example makes the view available at ``/i18n/setlang/``.) |
|---|
| | 447 | |
|---|
| | 448 | The view expects to be called via the ``GET`` method, with a ``language`` |
|---|
| | 449 | parameter set in the query string. If session support is enabled, the view |
|---|
| | 450 | saves the language choice in the user's session. Otherwise, it saves the |
|---|
| | 451 | language choice in a ``django_language`` cookie. |
|---|
| | 452 | |
|---|
| | 453 | After setting the language choice, Django redirects the user, following this |
|---|
| | 454 | algorithm: |
|---|
| | 455 | |
|---|
| | 456 | * Django looks for a ``next`` parameter in the query string. |
|---|
| | 457 | * If that doesn't exist, or is empty, Django tries the URL in the |
|---|
| | 458 | ``Referer`` header. |
|---|
| | 459 | * If that's empty -- say, if a user's browser suppresses that header -- |
|---|
| | 460 | then the user will be redirected to ``/`` (the site root) as a fallback. |
|---|
| | 461 | |
|---|
| | 462 | Here's example HTML template code:: |
|---|
| | 463 | |
|---|
| | 464 | <form action="/i18n/setlang/" method="get"> |
|---|
| 202 | | When a user submits the form, his chosen language will be saved in a cookie, |
|---|
| 203 | | and he'll be redirected either to the URL specified in the ``next`` field, or, |
|---|
| 204 | | if ``next`` is empty, to the URL in the ``Referer`` header. If the ``Referer`` |
|---|
| 205 | | is blank -- say, if a user's browser suppresses that header -- then the user |
|---|
| 206 | | will be redirected to ``/`` (the site root) as a fallback. |
|---|
| 207 | | |
|---|
| 208 | | Activate the ``setlang`` redirect view by adding the following line to your |
|---|
| 209 | | URLconf:: |
|---|
| 210 | | |
|---|
| 211 | | (r'^i18n/', include('django.conf.urls.i18n'), |
|---|
| 212 | | |
|---|
| 213 | | Note that this example makes the view available at ``/i18n/setlang/``. |
|---|
| 214 | | |
|---|
| 215 | | How language preference is discovered |
|---|
| 216 | | ===================================== |
|---|
| 217 | | |
|---|
| 218 | | Django has a very flexible model of deciding which language should be used -- |
|---|
| 219 | | installation-wide, for a particular user, or both. |
|---|
| 220 | | |
|---|
| 221 | | To set an installation-wide language preference, set ``LANGUAGE_CODE`` in your |
|---|
| 222 | | settings file. Django uses this language as the default translation -- the |
|---|
| 223 | | final attempt if no other translator finds a translation. |
|---|
| 224 | | |
|---|
| 225 | | If all you want to do is run Django with your native language, and a language |
|---|
| 226 | | file is available for your language, all you need to do is set |
|---|
| 227 | | ``LANGUAGE_CODE``. |
|---|
| 228 | | |
|---|
| 229 | | If you want to let each individual user specify which language he or she |
|---|
| 230 | | prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language |
|---|
| 231 | | selection based on data from the request. It lets each user have his or her own |
|---|
| 232 | | setting. |
|---|
| 233 | | |
|---|
| 234 | | To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'`` |
|---|
| 235 | | to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you |
|---|
| 236 | | should follow these guidelines: |
|---|
| 237 | | |
|---|
| 238 | | * Make sure it's one of the first middlewares installed. |
|---|
| 239 | | * It should come after ``SessionMiddleware``, because ``LocaleMiddleware`` |
|---|
| 240 | | makes use of session data. |
|---|
| 241 | | |
|---|
| 242 | | For example, your ``MIDDLEWARE_CLASSES`` might look like this:: |
|---|
| 243 | | |
|---|
| 244 | | MIDDLEWARE_CLASSES = ( |
|---|
| 245 | | 'django.middleware.sessions.SessionMiddleware', |
|---|
| 246 | | 'django.middleware.locale.LocaleMiddleware', |
|---|
| 247 | | 'django.middleware.common.CommonMiddleware', |
|---|
| 248 | | ) |
|---|
| 249 | | |
|---|
| 250 | | ``LocaleMiddleware`` tries to determine the user's language preference by |
|---|
| 251 | | following this algorithm: |
|---|
| 252 | | |
|---|
| 253 | | * First, it looks for a ``django_language`` key in the the current user's |
|---|
| 254 | | session. |
|---|
| 255 | | * Failing that, it looks for a cookie called ``django_language``. |
|---|
| 256 | | * Failing that, it looks at the ``Accept-Language`` HTTP header. This |
|---|
| 257 | | header is sent by your browser and tells the server which language(s) you |
|---|
| 258 | | prefer, in order by priority. Django tries each language in the header |
|---|
| 259 | | until it finds one with available translations. |
|---|
| 260 | | * Failing that, it uses the global ``LANGUAGE_CODE`` setting. |
|---|
| 261 | | |
|---|
| 262 | | Notes: |
|---|
| 263 | | |
|---|
| 264 | | * In each of these places, the language preference is expected to be in the |
|---|
| 265 | | standard language format, as a string. For example, Brazilian is |
|---|
| 266 | | ``pt-br``. |
|---|
| 267 | | * If a base language is available but the sublanguage specified is not, |
|---|
| 268 | | Django uses the base language. For example, if a user specifies ``de-at`` |
|---|
| 269 | | (Austrian German) but Django only has ``de`` available, Django uses |
|---|
| 270 | | ``de``. |
|---|
| 271 | | |
|---|
| 272 | | Once ``LocaleMiddleware`` determines the user's preference, it makes this |
|---|
| 273 | | preference available as ``request.LANGUAGE_CODE`` for each `request object`_. |
|---|
| 274 | | Feel free to read this value in your view code. Here's a simple example:: |
|---|
| 275 | | |
|---|
| 276 | | def hello_world(request, count): |
|---|
| 277 | | if request.LANGUAGE_CODE == 'de-at': |
|---|
| 278 | | return HttpResponse("You prefer to read Austrian German.") |
|---|
| 279 | | else: |
|---|
| 280 | | return HttpResponse("You prefer to read another language.") |
|---|
| 281 | | |
|---|
| 282 | | Note that, with static (middleware-less) translation, the language is in |
|---|
| 283 | | ``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's |
|---|
| 284 | | in ``request.LANGUAGE_CODE``. |
|---|
| 285 | | |
|---|
| 286 | | .. _request object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects |
|---|
| 287 | | |
|---|
| 288 | | Creating language files |
|---|
| 289 | | ======================= |
|---|
| 290 | | |
|---|
| 291 | | So, you've tagged all of your strings for later translation. But you need to |
|---|
| 292 | | write the translations themselves. |
|---|
| 293 | | |
|---|
| 294 | | They need to be in a format grokable by ``gettext``. You need to update them. |
|---|
| 295 | | You may need to create new ones for new languages. This section shows you how |
|---|
| 296 | | to do it. |
|---|
| 297 | | |
|---|
| 298 | | Creating message files |
|---|
| 299 | | ---------------------- |
|---|
| 300 | | |
|---|
| 301 | | The first step is to create a message file for a new language. Django comes |
|---|
| 302 | | with a tool, ``make-messages.py``, that automates this. |
|---|
| 303 | | |
|---|
| 304 | | To run it on the Django source tree, navigate to the ``django`` directory |
|---|
| 305 | | itself -- not a Subversion check out, but the one linked to via ``$PYTHONPATH`` |
|---|
| 306 | | or located somewhere on that path. |
|---|
| 307 | | |
|---|
| 308 | | Then run this command:: |
|---|
| 309 | | |
|---|
| 310 | | bin/make-messages.py -l de |
|---|
| 311 | | |
|---|
| 312 | | ...where ``de`` is the language code for the message file you want to create. |
|---|
| 313 | | |
|---|
| 314 | | This script runs over the entire Django source tree and pulls out all strings |
|---|
| 315 | | marked for translation, creating or updating the language's message file. |
|---|
| 316 | | |
|---|
| 317 | | When it's done, it will have created (or updated) a message file under the |
|---|
| 318 | | directory ``conf/locale``. In this example, the file will be |
|---|
| 319 | | ``conf/locale/de/LC_MESSAGES/django.po``. |
|---|
| 320 | | |
|---|
| 321 | | If you don't have the ``gettext`` utilities installed, ``make-messages.py`` |
|---|
| 322 | | will create empty files. If that's the case, either install the ``gettext`` |
|---|
| 323 | | utilities or just copy the English message file |
|---|
| 324 | | (``conf/locale/en/LC_MESSAGES/django.po``) and use it as a starting point; it's |
|---|
| 325 | | just an empty translation file. |
|---|
| 326 | | |
|---|
| 327 | | Once you've created the ``.po`` file, edit the file with your favorite text |
|---|
| 328 | | editor. First, edit the charset line (search for ``"CHARSET"``) and set it to |
|---|
| 329 | | the charset you'll be using to edit the content. Then, proceed to write your |
|---|
| 330 | | translations. |
|---|
| 331 | | |
|---|
| 332 | | The language code for storage is in locale format -- so it's ``pt_BR`` for |
|---|
| 333 | | Brazilian and ``de_AT`` for Austrian German. |
|---|
| 334 | | |
|---|
| 335 | | Every message in the message file is in the same format: |
|---|
| 336 | | |
|---|
| 337 | | * One line is the msgid. This is the actual string in the source. Don't |
|---|
| 338 | | change it. |
|---|
| 339 | | * The other line is msgstr. This is the translation. It starts out empty. |
|---|
| 340 | | You change it. |
|---|
| 341 | | |
|---|
| 342 | | Long messages are a special case. There, the first string directly after the |
|---|
| 343 | | msgstr (or msgid) is an empty string. Then the content itself will be written |
|---|
| 344 | | over the next few lines as one string per line. Those strings are directly |
|---|
| 345 | | concatenated. Don't forget trailing spaces within the strings; otherwise, |
|---|
| 346 | | they'll be tacked together without whitespace! |
|---|
| 347 | | |
|---|
| 348 | | Compiling message files |
|---|
| 349 | | ----------------------- |
|---|
| 350 | | |
|---|
| 351 | | After you create your message file, you'll need to transform it into a more |
|---|
| 352 | | efficient form to be read by ``gettext``. Do this with the |
|---|
| 353 | | ``compile-messages.py`` utility. This tool runs over all available ``.po`` |
|---|
| 354 | | files and creates ``.mo`` files. Run it like this:: |
|---|
| 355 | | |
|---|
| 356 | | bin/compile-messages.py |
|---|
| 357 | | |
|---|
| 358 | | That's it. You made your first translation. Now, if you configure your browser |
|---|
| 359 | | to request your language, Django apps will use your language preference. |
|---|
| 360 | | |
|---|
| 361 | | Another thing: Please submit the name of your newly-created language in that |
|---|
| 362 | | native language, so we can add it to the global list of available languages |
|---|
| 363 | | that is mirrored in ``settings.LANGUAGES`` (and the ``LANGUAGES`` template |
|---|
| 364 | | variable). |
|---|
| 365 | | |
|---|