Ticket #10260: 10260-i18n_docs_refactor-r11173.diff
File 10260-i18n_docs_refactor-r11173.diff, 94.4 KB (added by , 15 years ago) |
---|
-
new file docs/howto/i18n.txt
diff --git a/docs/howto/i18n.txt b/docs/howto/i18n.txt new file mode 100644
- + 1 .. _howto-i18n: 2 3 .. _using-translations-in-your-own-projects: 4 5 =============================================== 6 Using internationalization in your own projects 7 =============================================== 8 9 At runtime, Django looks for translations by following this algorithm: 10 11 * First, it looks for a ``locale`` directory in the application directory 12 of the view that's being called. If it finds a translation for the 13 selected language, the translation will be installed. 14 * Next, it looks for a ``locale`` directory in the project directory. If it 15 finds a translation, the translation will be installed. 16 * Finally, it checks the Django-provided base translation in 17 ``django/conf/locale``. 18 19 This way, you can write applications that include their own translations, and 20 you can override base translations in your project path. Or, you can just build 21 a big project out of several apps and put all translations into one big project 22 message file. The choice is yours. 23 24 .. note:: 25 26 If you're using manually configured settings, as described in 27 :ref:`settings-without-django-settings-module`, the ``locale`` directory in 28 the project directory will not be examined, since Django loses the ability 29 to work out the location of the project directory. (Django normally uses the 30 location of the settings file to determine this, and a settings file doesn't 31 exist if you're manually configuring your settings.) 32 33 All message file repositories are structured the same way. They are: 34 35 * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` 36 * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` 37 * All paths listed in ``LOCALE_PATHS`` in your settings file are 38 searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)`` 39 * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)`` 40 41 To create message files, you use the ``django-admin.py makemessages`` tool. You 42 only need to be in the same directory where the ``locale/`` directory is 43 located. And you use ``django-admin.py compilemessages`` to produce the binary 44 ``.mo`` files that are used by ``gettext``. Read the 45 :ref:`topics-i18n-localization` document for more details. 46 47 You can also run ``django-admin.py compilemessages --settings=path.to.settings`` 48 to make the compiler process all the directories in your ``LOCALE_PATHS`` 49 setting. 50 51 Application message files are a bit complicated to discover -- they need the 52 ``LocaleMiddleware``. If you don't use the middleware, only the Django message 53 files and project message files will be installed and available at runtime. 54 55 Finally, you should give some thought to the structure of your translation 56 files. If your applications need to be delivered to other users and will 57 be used in other projects, you might want to use app-specific translations. 58 But using app-specific translations and project translations could produce 59 weird problems with ``makemessages``: ``makemessages`` will traverse all 60 directories below the current path and so might put message IDs into the 61 project message file that are already in application message files. 62 63 The easiest way out is to store applications that are not part of the project 64 (and so carry their own translations) outside the project tree. That way, 65 ``django-admin.py makemessages`` on the project level will only translate 66 strings that are connected to your explicit project and not strings that are 67 distributed independently. -
docs/howto/index.txt
diff --git a/docs/howto/index.txt b/docs/howto/index.txt
a b 20 20 deployment/index 21 21 error-reporting 22 22 initial-data 23 i18n 23 24 jython 24 25 legacy-databases 25 26 outputting-csv -
docs/internals/contributing.txt
diff --git a/docs/internals/contributing.txt b/docs/internals/contributing.txt
a b 402 402 403 403 * Join the `Django i18n mailing list`_ and introduce yourself. 404 404 405 * Make sure you read the notes about :ref:`specialties-of-django-i18n`. 406 405 407 * Create translations using the methods described in the 406 :ref:`i18n documentation <topics-i18n>`. For this you will use the 407 ``django-admin.py makemessages`` tool. In this particular case it should 408 be run from the top-level ``django`` directory of the Django source tree. 408 :ref:`localization documentation <topics-i18n-localization>`. For this 409 you will use the ``django-admin.py makemessages`` tool. In this 410 particular case it should be run from the top-level ``django`` directory 411 of the Django source tree. 409 412 410 413 The script runs over the entire Django source tree and pulls out all 411 414 strings marked for translation. It creates (or updates) a message file in 412 the directory ``conf/locale`` (for example for ``pt -BR``, the file will be413 ``conf/locale/pt -br/LC_MESSAGES/django.po``).415 the directory ``conf/locale`` (for example for ``pt_BR``, the file will be 416 ``conf/locale/pt_BR/LC_MESSAGES/django.po``). 414 417 415 418 * Make sure that ``django-admin.py compilemessages -l <lang>`` runs without 416 419 producing any warnings. -
docs/ref/settings.txt
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
a b 667 667 Default: ``()`` (Empty tuple) 668 668 669 669 A tuple of directories where Django looks for translation files. 670 See :ref:` translations-in-your-own-projects`.670 See :ref:`using-translations-in-your-own-projects`. 671 671 672 672 .. setting:: LOGIN_REDIRECT_URL 673 673 -
deleted file docs/topics/i18n.txt
diff --git a/docs/topics/i18n.txt b/docs/topics/i18n.txt deleted file mode 100644
+ - 1 .. _topics-i18n:2 3 ====================4 Internationalization5 ====================6 7 Django has full support for internationalization of text in code and templates.8 Here's how it works.9 10 Overview11 ========12 13 The goal of internationalization is to allow a single Web application to offer14 its content and functionality in multiple languages.15 16 You, the Django developer, can accomplish this goal by adding a minimal amount17 of hooks to your Python code and templates. These hooks are called18 **translation strings**. They tell Django: "This text should be translated into19 the end user's language, if a translation for this text is available in that20 language."21 22 Django takes care of using these hooks to translate Web apps, on the fly,23 according to users' language preferences.24 25 Essentially, Django does two things:26 27 * It lets developers and template authors specify which parts of their apps28 should be translatable.29 * It uses these hooks to translate Web apps for particular users according30 to their language preferences.31 32 If you don't need internationalization in your app33 ==================================================34 35 Django's internationalization hooks are on by default, and that means there's a36 bit of i18n-related overhead in certain places of the framework. If you don't37 use internationalization, you should take the two seconds to set38 :setting:`USE_I18N = False <USE_I18N>` in your settings file. If39 :setting:`USE_I18N` is set to ``False``, then Django will make some40 optimizations so as not to load the internationalization machinery.41 42 You'll probably also want to remove ``'django.core.context_processors.i18n'``43 from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting.44 45 If you do need internationalization: three steps46 ================================================47 48 1. Embed translation strings in your Python code and templates.49 2. Get translations for those strings, in whichever languages you want to50 support.51 3. Activate the locale middleware in your Django settings.52 53 .. admonition:: Behind the scenes54 55 Django's translation machinery uses the standard ``gettext`` module that56 comes with Python.57 58 1. How to specify translation strings59 =====================================60 61 Translation strings specify "This text should be translated." These strings can62 appear in your Python code and templates. It's your responsibility to mark63 translatable strings; the system can only translate strings it knows about.64 65 In Python code66 --------------67 68 Standard translation69 ~~~~~~~~~~~~~~~~~~~~70 71 Specify a translation string by using the function ``ugettext()``. It's72 convention to import this as a shorter alias, ``_``, to save typing.73 74 .. note::75 Python's standard library ``gettext`` module installs ``_()`` into the76 global namespace, as an alias for ``gettext()``. In Django, we have chosen77 not to follow this practice, for a couple of reasons:78 79 1. For international character set (Unicode) support, ``ugettext()`` is80 more useful than ``gettext()``. Sometimes, you should be using81 ``ugettext_lazy()`` as the default translation method for a particular82 file. Without ``_()`` in the global namespace, the developer has to83 think about which is the most appropriate translation function.84 85 2. The underscore character (``_``) is used to represent "the previous86 result" in Python's interactive shell and doctest tests. Installing a87 global ``_()`` function causes interference. Explicitly importing88 ``ugettext()`` as ``_()`` avoids this problem.89 90 .. highlightlang:: python91 92 In this example, the text ``"Welcome to my site."`` is marked as a translation93 string::94 95 from django.utils.translation import ugettext as _96 97 def my_view(request):98 output = _("Welcome to my site.")99 return HttpResponse(output)100 101 Obviously, you could code this without using the alias. This example is102 identical to the previous one::103 104 from django.utils.translation import ugettext105 106 def my_view(request):107 output = ugettext("Welcome to my site.")108 return HttpResponse(output)109 110 Translation works on computed values. This example is identical to the previous111 two::112 113 def my_view(request):114 words = ['Welcome', 'to', 'my', 'site.']115 output = _(' '.join(words))116 return HttpResponse(output)117 118 Translation works on variables. Again, here's an identical example::119 120 def my_view(request):121 sentence = 'Welcome to my site.'122 output = _(sentence)123 return HttpResponse(output)124 125 (The caveat with using variables or computed values, as in the previous two126 examples, is that Django's translation-string-detecting utility,127 ``django-admin.py makemessages``, won't be able to find these strings. More on128 ``makemessages`` later.)129 130 The strings you pass to ``_()`` or ``ugettext()`` can take placeholders,131 specified with Python's standard named-string interpolation syntax. Example::132 133 def my_view(request, m, d):134 output = _('Today is %(month)s, %(day)s.') % {'month': m, 'day': d}135 return HttpResponse(output)136 137 This technique lets language-specific translations reorder the placeholder138 text. For example, an English translation may be ``"Today is November, 26."``,139 while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the140 placeholders (the month and the day) with their positions swapped.141 142 For this reason, you should use named-string interpolation (e.g., ``%(day)s``)143 instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you144 have more than a single parameter. If you used positional interpolation,145 translations wouldn't be able to reorder placeholder text.146 147 Marking strings as no-op148 ~~~~~~~~~~~~~~~~~~~~~~~~149 150 Use the function ``django.utils.translation.ugettext_noop()`` to mark a string151 as a translation string without translating it. The string is later translated152 from a variable.153 154 Use this if you have constant strings that should be stored in the source155 language because they are exchanged over systems or users -- such as strings in156 a database -- but should be translated at the last possible point in time, such157 as when the string is presented to the user.158 159 .. _lazy-translations:160 161 Lazy translation162 ~~~~~~~~~~~~~~~~163 164 Use the function ``django.utils.translation.ugettext_lazy()`` to translate165 strings lazily -- when the value is accessed rather than when the166 ``ugettext_lazy()`` function is called.167 168 For example, to translate a model's ``help_text``, do the following::169 170 from django.utils.translation import ugettext_lazy171 172 class MyThing(models.Model):173 name = models.CharField(help_text=ugettext_lazy('This is the help text'))174 175 In this example, ``ugettext_lazy()`` stores a lazy reference to the string --176 not the actual translation. The translation itself will be done when the string177 is used in a string context, such as template rendering on the Django admin178 site.179 180 The result of a ``ugettext_lazy()`` call can be used wherever you would use a181 unicode string (an object with type ``unicode``) in Python. If you try to use182 it where a bytestring (a ``str`` object) is expected, things will not work as183 expected, since a ``ugettext_lazy()`` object doesn't know how to convert184 itself to a bytestring. You can't use a unicode string inside a bytestring,185 either, so this is consistent with normal Python behavior. For example::186 187 # This is fine: putting a unicode proxy into a unicode string.188 u"Hello %s" % ugettext_lazy("people")189 190 # This will not work, since you cannot insert a unicode object191 # into a bytestring (nor can you insert our unicode proxy there)192 "Hello %s" % ugettext_lazy("people")193 194 If you ever see output that looks like ``"hello195 <django.utils.functional...>"``, you have tried to insert the result of196 ``ugettext_lazy()`` into a bytestring. That's a bug in your code.197 198 If you don't like the verbose name ``ugettext_lazy``, you can just alias it as199 ``_`` (underscore), like so::200 201 from django.utils.translation import ugettext_lazy as _202 203 class MyThing(models.Model):204 name = models.CharField(help_text=_('This is the help text'))205 206 Always use lazy translations in :ref:`Django models <topics-db-models>`.207 Field names and table names should be marked for translation (otherwise, they208 won't be translated in the admin interface). This means writing explicit209 ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class,210 though, rather than relying on Django's default determination of211 ``verbose_name`` and ``verbose_name_plural`` by looking at the model's class212 name::213 214 from django.utils.translation import ugettext_lazy as _215 216 class MyThing(models.Model):217 name = models.CharField(_('name'), help_text=_('This is the help text'))218 class Meta:219 verbose_name = _('my thing')220 verbose_name_plural = _('mythings')221 222 Pluralization223 ~~~~~~~~~~~~~224 225 Use the function ``django.utils.translation.ungettext()`` to specify pluralized226 messages.227 228 ``ungettext`` takes three arguments: the singular translation string, the plural229 translation string and the number of objects.230 231 This function is useful when your need you Django application to be localizable232 to languages where the number and complexity of `plural forms233 <http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is234 greater than the two forms used in English ('object' for the singular and235 'objects' for all the cases where ``count`` is different from zero, irrespective236 of its value.)237 238 For example::239 240 from django.utils.translation import ungettext241 def hello_world(request, count):242 page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % {243 'count': count,244 }245 return HttpResponse(page)246 247 In this example the number of objects is passed to the translation languages as248 the ``count`` variable.249 250 Lets see a slightly more complex usage example::251 252 from django.utils.translation import ungettext253 254 count = Report.objects.count()255 if count == 1:256 name = Report._meta.verbose_name257 else:258 name = Report._meta.verbose_name_plural259 260 text = ungettext(261 'There is %(count)d %(name)s available.',262 'There are %(count)d %(name)s available.',263 count264 ) % {265 'count': count,266 'name': name267 }268 269 Here we reuse localizable, hopefully already translated literals (contained in270 the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for271 other parts of the sentence so all of it is consistently based on the272 cardinality of the elements at play.273 274 .. _pluralization-var-notes:275 276 .. note::277 278 When using this technique, make sure you use a single name for every279 extrapolated variable included in the literal. In the example above note how280 we used the ``name`` Python variable in both translation strings. This281 example would fail::282 283 from django.utils.translation import ungettext284 from myapp.models import Report285 286 count = Report.objects.count()287 d = {288 'count': count,289 'name': Report._meta.verbose_name290 'plural_name': Report._meta.verbose_name_plural291 }292 text = ungettext(293 'There is %(count)d %(name)s available.',294 'There are %(count)d %(plural_name)s available.',295 count296 ) % d297 298 You would get a ``a format specification for argument 'name', as in299 'msgstr[0]', doesn't exist in 'msgid'`` error when running300 ``django-admin.py compilemessages`` or a ``KeyError`` Python exception at301 runtime.302 303 In template code304 ----------------305 306 .. highlightlang:: html+django307 308 Translations in :ref:`Django templates <topics-templates>` uses two template309 tags and a slightly different syntax than in Python code. To give your template310 access to these tags, put ``{% load i18n %}`` toward the top of your template.311 312 The ``{% trans %}`` template tag translates either a constant string313 (enclosed in single or double quotes) or variable content::314 315 <title>{% trans "This is the title." %}</title>316 <title>{% trans myvar %}</title>317 318 If the ``noop`` option is present, variable lookup still takes place, but the319 original text will be returned unchanged. This is useful when "stubbing out"320 content that will require translation in the future::321 322 <title>{% trans "myvar" noop %}</title>323 324 Internally, inline translations use an ``ugettext`` call.325 326 It's not possible to mix a template variable inside a string within ``{% trans327 %}``. If your translations require strings with variables (placeholders), use328 ``{% blocktrans %}``::329 330 {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}331 332 To translate a template expression -- say, using template filters -- you need333 to bind the expression to a local variable for use within the translation334 block::335 336 {% blocktrans with value|filter as myvar %}337 This will have {{ myvar }} inside.338 {% endblocktrans %}339 340 If you need to bind more than one expression inside a ``blocktrans`` tag,341 separate the pieces with ``and``::342 343 {% blocktrans with book|title as book_t and author|title as author_t %}344 This is {{ book_t }} by {{ author_t }}345 {% endblocktrans %}346 347 To pluralize, specify both the singular and plural forms with the348 ``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and349 ``{% endblocktrans %}``. Example::350 351 {% blocktrans count list|length as counter %}352 There is only one {{ name }} object.353 {% plural %}354 There are {{ counter }} {{ name }} objects.355 {% endblocktrans %}356 357 When you use the pluralization feature and bind additional values to local358 variables apart from the counter value that selects the translated literal to be359 used, have in mind that the ``blocktrans`` construct is internally converted360 to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext361 variables <pluralization-var-notes>` apply.362 363 Each ``RequestContext`` has access to three translation-specific variables:364 365 * ``LANGUAGES`` is a list of tuples in which the first element is the366 language code and the second is the language name (translated into the367 currently active locale).368 369 * ``LANGUAGE_CODE`` is the current user's preferred language, as a string.370 Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`,371 below.)372 373 * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a374 right-to-left language, e.g.: Hebrew, Arabic. If False it's a375 left-to-right language, e.g.: English, French, German etc.376 377 378 If you don't use the ``RequestContext`` extension, you can get those values with379 three tags::380 381 {% get_current_language as LANGUAGE_CODE %}382 {% get_available_languages as LANGUAGES %}383 {% get_current_language_bidi as LANGUAGE_BIDI %}384 385 These tags also require a ``{% load i18n %}``.386 387 Translation hooks are also available within any template block tag that accepts388 constant strings. In those cases, just use ``_()`` syntax to specify a389 translation string::390 391 {% some_special_tag _("Page not found") value|yesno:_("yes,no") %}392 393 In this case, both the tag and the filter will see the already-translated394 string, so they don't need to be aware of translations.395 396 .. note::397 In this example, the translation infrastructure will be passed the string398 ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The399 translated string will need to contain the comma so that the filter400 parsing code knows how to split up the arguments. For example, a German401 translator might translate the string ``"yes,no"`` as ``"ja,nein"``402 (keeping the comma intact).403 404 .. _Django templates: ../templates_python/405 406 Working with lazy translation objects407 -------------------------------------408 409 .. highlightlang:: python410 411 Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models412 and utility functions is a common operation. When you're working with these413 objects elsewhere in your code, you should ensure that you don't accidentally414 convert them to strings, because they should be converted as late as possible415 (so that the correct locale is in effect). This necessitates the use of a416 couple of helper functions.417 418 Joining strings: string_concat()419 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~420 421 Standard Python string joins (``''.join([...])``) will not work on lists422 containing lazy translation objects. Instead, you can use423 ``django.utils.translation.string_concat()``, which creates a lazy object that424 concatenates its contents *and* converts them to strings only when the result425 is included in a string. For example::426 427 from django.utils.translation import string_concat428 ...429 name = ugettext_lazy(u'John Lennon')430 instrument = ugettext_lazy(u'guitar')431 result = string_concat([name, ': ', instrument])432 433 In this case, the lazy translations in ``result`` will only be converted to434 strings when ``result`` itself is used in a string (usually at template435 rendering time).436 437 The allow_lazy() decorator438 ~~~~~~~~~~~~~~~~~~~~~~~~~~439 440 Django offers many utility functions (particularly in ``django.utils``) that441 take a string as their first argument and do something to that string. These442 functions are used by template filters as well as directly in other code.443 444 If you write your own similar functions and deal with translations, you'll445 face the problem of what to do when the first argument is a lazy translation446 object. You don't want to convert it to a string immediately, because you might447 be using this function outside of a view (and hence the current thread's locale448 setting will not be correct).449 450 For cases like this, use the ``django.utils.functional.allow_lazy()``451 decorator. It modifies the function so that *if* it's called with a lazy452 translation as the first argument, the function evaluation is delayed until it453 needs to be converted to a string.454 455 For example::456 457 from django.utils.functional import allow_lazy458 459 def fancy_utility_function(s, ...):460 # Do some conversion on string 's'461 ...462 fancy_utility_function = allow_lazy(fancy_utility_function, unicode)463 464 The ``allow_lazy()`` decorator takes, in addition to the function to decorate,465 a number of extra arguments (``*args``) specifying the type(s) that the466 original function can return. Usually, it's enough to include ``unicode`` here467 and ensure that your function returns only Unicode strings.468 469 Using this decorator means you can write your function and assume that the470 input is a proper string, then add support for lazy translation objects at the471 end.472 473 .. _how-to-create-language-files:474 475 2. How to create language files476 ===============================477 478 Once you've tagged your strings for later translation, you need to write (or479 obtain) the language translations themselves. Here's how that works.480 481 .. admonition:: Locale restrictions482 483 Django does not support localizing your application into a locale for484 which Django itself has not been translated. In this case, it will ignore485 your translation files. If you were to try this and Django supported it,486 you would inevitably see a mixture of translated strings (from your487 application) and English strings (from Django itself). If you want to488 support a locale for your application that is not already part of489 Django, you'll need to make at least a minimal translation of the Django490 core. See the relevant :ref:`LocaleMiddleware note<locale-middleware-notes>`491 for more details.492 493 Message files494 -------------495 496 The first step is to create a **message file** for a new language. A message497 file is a plain-text file, representing a single language, that contains all498 available translation strings and how they should be represented in the given499 language. Message files have a ``.po`` file extension.500 501 Django comes with a tool, ``django-admin.py makemessages``, that automates the502 creation and upkeep of these files.503 504 .. admonition:: A note to Django veterans505 506 The old tool ``bin/make-messages.py`` has been moved to the command507 ``django-admin.py makemessages`` to provide consistency throughout Django.508 509 To create or update a message file, run this command::510 511 django-admin.py makemessages -l de512 513 ...where ``de`` is the language code for the message file you want to create.514 The language code, in this case, is in locale format. For example, it's515 ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian German.516 517 The script should be run from one of three places:518 519 * The root directory of your Django project.520 * The root directory of your Django app.521 * The root ``django`` directory (not a Subversion checkout, but the one522 that is linked-to via ``$PYTHONPATH`` or is located somewhere on that523 path). This is only relevant when you are creating a translation for524 Django itself, see :ref:`contributing-translations`.525 526 The script runs over your project source tree or your application source tree527 and pulls out all strings marked for translation. It creates (or updates) a528 message file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de``529 example, the file will be ``locale/de/LC_MESSAGES/django.po``.530 531 By default ``django-admin.py makemessages`` examines every file that has the532 ``.html`` file extension. In case you want to override that default, use the533 ``--extension`` or ``-e`` option to specify the file extensions to examine::534 535 django-admin.py makemessages -l de -e txt536 537 Separate multiple extensions with commas and/or use ``-e`` or ``--extension``538 multiple times::539 540 django-admin.py makemessages -l=de -e=html,txt -e xml541 542 When `creating JavaScript translation catalogs`_ you need to use the special543 'djangojs' domain, **not** ``-e js``.544 545 .. _create a JavaScript translation catalog: `Creating JavaScript translation catalogs`_546 547 .. admonition:: No gettext?548 549 If you don't have the ``gettext`` utilities installed, ``django-admin.py550 makemessages`` will create empty files. If that's the case, either install551 the ``gettext`` utilities or just copy the English message file552 (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting553 point; it's just an empty translation file.554 555 .. admonition:: Working on Windows?556 557 If you're using Windows and need to install the GNU gettext utilities so558 ``django-admin makemessages`` works see `gettext on Windows`_ for more559 information.560 561 The format of ``.po`` files is straightforward. Each ``.po`` file contains a562 small bit of metadata, such as the translation maintainer's contact563 information, but the bulk of the file is a list of **messages** -- simple564 mappings between translation strings and the actual translated text for the565 particular language.566 567 For example, if your Django app contained a translation string for the text568 ``"Welcome to my site."``, like so::569 570 _("Welcome to my site.")571 572 ...then ``django-admin.py makemessages`` will have created a ``.po`` file573 containing the following snippet -- a message::574 575 #: path/to/python/module.py:23576 msgid "Welcome to my site."577 msgstr ""578 579 A quick explanation:580 581 * ``msgid`` is the translation string, which appears in the source. Don't582 change it.583 * ``msgstr`` is where you put the language-specific translation. It starts584 out empty, so it's your responsibility to change it. Make sure you keep585 the quotes around your translation.586 * As a convenience, each message includes, in the form of a comment line587 prefixed with ``#`` and located above the ``msgid`` line, the filename and588 line number from which the translation string was gleaned.589 590 Long messages are a special case. There, the first string directly after the591 ``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be592 written over the next few lines as one string per line. Those strings are593 directly concatenated. Don't forget trailing spaces within the strings;594 otherwise, they'll be tacked together without whitespace!595 596 .. admonition:: Mind your charset597 598 When creating a PO file with your favorite text editor, first edit599 the charset line (search for ``"CHARSET"``) and set it to the charset600 you'll be using to edit the content. Due to the way the ``gettext`` tools601 work internally and because we want to allow non-ASCII source strings in602 Django's core and your applications, you **must** use UTF-8 as the encoding603 for your PO file. This means that everybody will be using the same604 encoding, which is important when Django processes the PO files.605 606 To reexamine all source code and templates for new translation strings and607 update all message files for **all** languages, run this::608 609 django-admin.py makemessages -a610 611 Compiling message files612 -----------------------613 614 After you create your message file -- and each time you make changes to it --615 you'll need to compile it into a more efficient form, for use by ``gettext``.616 Do this with the ``django-admin.py compilemessages`` utility.617 618 This tool runs over all available ``.po`` files and creates ``.mo`` files, which619 are binary files optimized for use by ``gettext``. In the same directory from620 which you ran ``django-admin.py makemessages``, run ``django-admin.py621 compilemessages`` like this::622 623 django-admin.py compilemessages624 625 That's it. Your translations are ready for use.626 627 .. admonition:: A note to Django veterans628 629 The old tool ``bin/compile-messages.py`` has been moved to the command630 ``django-admin.py compilemessages`` to provide consistency throughout631 Django.632 633 .. admonition:: Working on Windows?634 635 If you're using Windows and need to install the GNU gettext utilities so636 ``django-admin compilemessages`` works see `gettext on Windows`_ for more637 information.638 639 .. _how-django-discovers-language-preference:640 641 3. How Django discovers language preference642 ===========================================643 644 Once you've prepared your translations -- or, if you just want to use the645 translations that come with Django -- you'll just need to activate translation646 for your app.647 648 Behind the scenes, Django has a very flexible model of deciding which language649 should be used -- installation-wide, for a particular user, or both.650 651 To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`.652 Django uses this language as the default translation -- the final attempt if no653 other translator finds a translation.654 655 If all you want to do is run Django with your native language, and a language656 file is available for your language, all you need to do is set657 ``LANGUAGE_CODE``.658 659 If you want to let each individual user specify which language he or she660 prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language661 selection based on data from the request. It customizes content for each user.662 663 To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'``664 to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you665 should follow these guidelines:666 667 * Make sure it's one of the first middlewares installed.668 * It should come after ``SessionMiddleware``, because ``LocaleMiddleware``669 makes use of session data.670 * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it.671 672 For example, your ``MIDDLEWARE_CLASSES`` might look like this::673 674 MIDDLEWARE_CLASSES = (675 'django.contrib.sessions.middleware.SessionMiddleware',676 'django.middleware.locale.LocaleMiddleware',677 'django.middleware.common.CommonMiddleware',678 )679 680 (For more on middleware, see the :ref:`middleware documentation681 <topics-http-middleware>`.)682 683 ``LocaleMiddleware`` tries to determine the user's language preference by684 following this algorithm:685 686 * First, it looks for a ``django_language`` key in the current user's687 session.688 689 * Failing that, it looks for a cookie.690 691 .. versionchanged:: 1.0692 693 In Django version 0.96 and before, the cookie's name is hard-coded to694 ``django_language``. In Django 1,0, The cookie name is set by the695 ``LANGUAGE_COOKIE_NAME`` setting. (The default name is696 ``django_language``.)697 698 * Failing that, it looks at the ``Accept-Language`` HTTP header. This699 header is sent by your browser and tells the server which language(s) you700 prefer, in order by priority. Django tries each language in the header701 until it finds one with available translations.702 703 * Failing that, it uses the global ``LANGUAGE_CODE`` setting.704 705 .. _locale-middleware-notes:706 707 Notes:708 709 * In each of these places, the language preference is expected to be in the710 standard language format, as a string. For example, Brazilian Portuguese711 is ``pt-br``.712 713 * If a base language is available but the sublanguage specified is not,714 Django uses the base language. For example, if a user specifies ``de-at``715 (Austrian German) but Django only has ``de`` available, Django uses716 ``de``.717 718 * Only languages listed in the :setting:`LANGUAGES` setting can be selected.719 If you want to restrict the language selection to a subset of provided720 languages (because your application doesn't provide all those languages),721 set ``LANGUAGES`` to a list of languages. For example::722 723 LANGUAGES = (724 ('de', _('German')),725 ('en', _('English')),726 )727 728 This example restricts languages that are available for automatic729 selection to German and English (and any sublanguage, like de-ch or730 en-us).731 732 .. _LANGUAGES setting: ../settings/#languages733 734 * If you define a custom ``LANGUAGES`` setting, as explained in the735 previous bullet, it's OK to mark the languages as translation strings736 -- but use a "dummy" ``ugettext()`` function, not the one in737 ``django.utils.translation``. You should *never* import738 ``django.utils.translation`` from within your settings file, because that739 module in itself depends on the settings, and that would cause a circular740 import.741 742 The solution is to use a "dummy" ``ugettext()`` function. Here's a sample743 settings file::744 745 ugettext = lambda s: s746 747 LANGUAGES = (748 ('de', ugettext('German')),749 ('en', ugettext('English')),750 )751 752 With this arrangement, ``django-admin.py makemessages`` will still find753 and mark these strings for translation, but the translation won't happen754 at runtime -- so you'll have to remember to wrap the languages in the755 *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime.756 757 * The ``LocaleMiddleware`` can only select languages for which there is a758 Django-provided base translation. If you want to provide translations759 for your application that aren't already in the set of translations760 in Django's source tree, you'll want to provide at least basic761 translations for that language. For example, Django uses technical762 message IDs to translate date formats and time formats -- so you will763 need at least those translations for the system to work correctly.764 765 A good starting point is to copy the English ``.po`` file and to766 translate at least the technical messages -- maybe the validation767 messages, too.768 769 Technical message IDs are easily recognized; they're all upper case. You770 don't translate the message ID as with other messages, you provide the771 correct local variant on the provided English value. For example, with772 ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), this would773 be the format string that you want to use in your language. The format774 is identical to the format strings used by the ``now`` template tag.775 776 Once ``LocaleMiddleware`` determines the user's preference, it makes this777 preference available as ``request.LANGUAGE_CODE`` for each778 :class:`~django.http.HttpRequest`. Feel free to read this value in your view779 code. Here's a simple example::780 781 def hello_world(request, count):782 if request.LANGUAGE_CODE == 'de-at':783 return HttpResponse("You prefer to read Austrian German.")784 else:785 return HttpResponse("You prefer to read another language.")786 787 Note that, with static (middleware-less) translation, the language is in788 ``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's789 in ``request.LANGUAGE_CODE``.790 791 .. _settings file: ../settings/792 .. _middleware documentation: ../middleware/793 .. _session: ../sessions/794 .. _request object: ../request_response/#httprequest-objects795 796 .. _translations-in-your-own-projects:797 798 Using translations in your own projects799 =======================================800 801 Django looks for translations by following this algorithm:802 803 * First, it looks for a ``locale`` directory in the application directory804 of the view that's being called. If it finds a translation for the805 selected language, the translation will be installed.806 * Next, it looks for a ``locale`` directory in the project directory. If it807 finds a translation, the translation will be installed.808 * Finally, it checks the Django-provided base translation in809 ``django/conf/locale``.810 811 This way, you can write applications that include their own translations, and812 you can override base translations in your project path. Or, you can just build813 a big project out of several apps and put all translations into one big project814 message file. The choice is yours.815 816 .. note::817 818 If you're using manually configured settings, as described819 :ref:`settings-without-django-settings-module`, the ``locale`` directory in820 the project directory will not be examined, since Django loses the ability821 to work out the location of the project directory. (Django normally uses the822 location of the settings file to determine this, and a settings file doesn't823 exist if you're manually configuring your settings.)824 825 All message file repositories are structured the same way. They are:826 827 * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``828 * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``829 * All paths listed in ``LOCALE_PATHS`` in your settings file are830 searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)``831 * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``832 833 To create message files, you use the same ``django-admin.py makemessages``834 tool as with the Django message files. You only need to be in the right place835 -- in the directory where either the ``conf/locale`` (in case of the source836 tree) or the ``locale/`` (in case of app messages or project messages)837 directory are located. And you use the same ``django-admin.py compilemessages``838 to produce the binary ``django.mo`` files that are used by ``gettext``.839 840 You can also run ``django-admin.py compilemessages --settings=path.to.settings``841 to make the compiler process all the directories in your ``LOCALE_PATHS``842 setting.843 844 Application message files are a bit complicated to discover -- they need the845 ``LocaleMiddleware``. If you don't use the middleware, only the Django message846 files and project message files will be processed.847 848 Finally, you should give some thought to the structure of your translation849 files. If your applications need to be delivered to other users and will850 be used in other projects, you might want to use app-specific translations.851 But using app-specific translations and project translations could produce852 weird problems with ``makemessages``: ``makemessages`` will traverse all853 directories below the current path and so might put message IDs into the854 project message file that are already in application message files.855 856 The easiest way out is to store applications that are not part of the project857 (and so carry their own translations) outside the project tree. That way,858 ``django-admin.py makemessages`` on the project level will only translate859 strings that are connected to your explicit project and not strings that are860 distributed independently.861 862 The ``set_language`` redirect view863 ==================================864 865 As a convenience, Django comes with a view, ``django.views.i18n.set_language``,866 that sets a user's language preference and redirects back to the previous page.867 868 Activate this view by adding the following line to your URLconf::869 870 (r'^i18n/', include('django.conf.urls.i18n')),871 872 (Note that this example makes the view available at ``/i18n/setlang/``.)873 874 The view expects to be called via the ``POST`` method, with a ``language``875 parameter set in request. If session support is enabled, the view876 saves the language choice in the user's session. Otherwise, it saves the877 language choice in a cookie that is by default named ``django_language``.878 (The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.)879 880 After setting the language choice, Django redirects the user, following this881 algorithm:882 883 * Django looks for a ``next`` parameter in the ``POST`` data.884 * If that doesn't exist, or is empty, Django tries the URL in the885 ``Referrer`` header.886 * If that's empty -- say, if a user's browser suppresses that header --887 then the user will be redirected to ``/`` (the site root) as a fallback.888 889 Here's example HTML template code:890 891 .. code-block:: html+django892 893 <form action="/i18n/setlang/" method="post">894 <input name="next" type="hidden" value="/next/page/" />895 <select name="language">896 {% for lang in LANGUAGES %}897 <option value="{{ lang.0 }}">{{ lang.1 }}</option>898 {% endfor %}899 </select>900 <input type="submit" value="Go" />901 </form>902 903 Translations and JavaScript904 ===========================905 906 Adding translations to JavaScript poses some problems:907 908 * JavaScript code doesn't have access to a ``gettext`` implementation.909 910 * JavaScript code doesn't have access to .po or .mo files; they need to be911 delivered by the server.912 913 * The translation catalogs for JavaScript should be kept as small as914 possible.915 916 Django provides an integrated solution for these problems: It passes the917 translations into JavaScript, so you can call ``gettext``, etc., from within918 JavaScript.919 920 The ``javascript_catalog`` view921 -------------------------------922 923 The main solution to these problems is the ``javascript_catalog`` view, which924 sends out a JavaScript code library with functions that mimic the ``gettext``925 interface, plus an array of translation strings. Those translation strings are926 taken from the application, project or Django core, according to what you927 specify in either the info_dict or the URL.928 929 You hook it up like this::930 931 js_info_dict = {932 'packages': ('your.app.package',),933 }934 935 urlpatterns = patterns('',936 (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),937 )938 939 Each string in ``packages`` should be in Python dotted-package syntax (the940 same format as the strings in ``INSTALLED_APPS``) and should refer to a package941 that contains a ``locale`` directory. If you specify multiple packages, all942 those catalogs are merged into one catalog. This is useful if you have943 JavaScript that uses strings from different applications.944 945 You can make the view dynamic by putting the packages into the URL pattern::946 947 urlpatterns = patterns('',948 (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),949 )950 951 With this, you specify the packages as a list of package names delimited by '+'952 signs in the URL. This is especially useful if your pages use code from953 different apps and this changes often and you don't want to pull in one big954 catalog file. As a security measure, these values can only be either955 ``django.conf`` or any package from the ``INSTALLED_APPS`` setting.956 957 Using the JavaScript translation catalog958 ----------------------------------------959 960 To use the catalog, just pull in the dynamically generated script like this::961 962 <script type="text/javascript" src="/path/to/jsi18n/"></script>963 964 This is how the admin fetches the translation catalog from the server. When the965 catalog is loaded, your JavaScript code can use the standard ``gettext``966 interface to access it::967 968 document.write(gettext('this is to be translated'));969 970 There is also an ``ngettext`` interface::971 972 var object_cnt = 1 // or 0, or 2, or 3, ...973 s = ngettext('literal for the singular case',974 'literal for the plural case', object_cnt);975 976 and even a string interpolation function::977 978 function interpolate(fmt, obj, named);979 980 The interpolation syntax is borrowed from Python, so the ``interpolate``981 function supports both positional and named interpolation:982 983 * Positional interpolation: ``obj`` contains a JavaScript Array object984 whose elements values are then sequentially interpolated in their985 corresponding ``fmt`` placeholders in the same order they appear.986 For example::987 988 fmts = ngettext('There is %s object. Remaining: %s',989 'There are %s objects. Remaining: %s', 11);990 s = interpolate(fmts, [11, 20]);991 // s is 'There are 11 objects. Remaining: 20'992 993 * Named interpolation: This mode is selected by passing the optional994 boolean ``named`` parameter as true. ``obj`` contains a JavaScript995 object or associative array. For example::996 997 d = {998 count: 10999 total: 501000 };1001 1002 fmts = ngettext('Total: %(total)s, there is %(count)s object',1003 'there are %(count)s of a total of %(total)s objects', d.count);1004 s = interpolate(fmts, d, true);1005 1006 You shouldn't go over the top with string interpolation, though: this is still1007 JavaScript, so the code has to make repeated regular-expression substitutions.1008 This isn't as fast as string interpolation in Python, so keep it to those1009 cases where you really need it (for example, in conjunction with ``ngettext``1010 to produce proper pluralizations).1011 1012 Creating JavaScript translation catalogs1013 ----------------------------------------1014 1015 You create and update the translation catalogs the same way as the other1016 1017 Django translation catalogs -- with the django-admin.py makemessages tool. The1018 only difference is you need to provide a ``-d djangojs`` parameter, like this::1019 1020 django-admin.py makemessages -d djangojs -l de1021 1022 This would create or update the translation catalog for JavaScript for German.1023 After updating translation catalogs, just run ``django-admin.py compilemessages``1024 the same way as you do with normal Django translation catalogs.1025 1026 Specialties of Django translation1027 ==================================1028 1029 If you know ``gettext``, you might note these specialties in the way Django1030 does translation:1031 1032 * The string domain is ``django`` or ``djangojs``. This string domain is1033 used to differentiate between different programs that store their data1034 in a common message-file library (usually ``/usr/share/locale/``). The1035 ``django`` domain is used for python and template translation strings1036 and is loaded into the global translation catalogs. The ``djangojs``1037 domain is only used for JavaScript translation catalogs to make sure1038 that those are as small as possible.1039 * Django doesn't use ``xgettext`` alone. It uses Python wrappers around1040 ``xgettext`` and ``msgfmt``. This is mostly for convenience.1041 1042 ``gettext`` on Windows1043 ======================1044 1045 This is only needed for people who either want to extract message IDs or compile1046 message files (``.po``). Translation work itself just involves editing existing1047 files of this type, but if you want to create your own message files, or want to1048 test or compile a changed message file, you will need the ``gettext`` utilities:1049 1050 * Download the following zip files from the GNOME servers1051 http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one1052 of its mirrors_1053 1054 * ``gettext-runtime-X.zip``1055 * ``gettext-tools-X.zip``1056 1057 ``X`` is the version number, we recomend using ``0.15`` or higher.1058 1059 * Extract the contents of the ``bin\`` directories in both files to the1060 same folder on your system (i.e. ``C:\Program Files\gettext-utils``)1061 1062 * Update the system PATH:1063 1064 * ``Control Panel > System > Advanced > Environment Variables``1065 * In the ``System variables`` list, click ``Path``, click ``Edit``1066 * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the1067 ``Variable value`` field1068 1069 .. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS1070 1071 You may also use ``gettext`` binaries you have obtained elsewhere, so long as1072 the ``xgettext --version`` command works properly. Some version 0.14.4 binaries1073 have been found to not support this command. Do not attempt to use Django1074 translation utilities with a ``gettext`` package if the command ``xgettext1075 --version`` entered at a Windows command prompt causes a popup window saying1076 "xgettext.exe has generated errors and will be closed by Windows". -
new file docs/topics/i18n/deployment.txt
diff --git a/docs/topics/i18n/deployment.txt b/docs/topics/i18n/deployment.txt new file mode 100644
- + 1 .. _topics-i18n-deployment: 2 3 ============================================= 4 Deployment of Django application translations 5 ============================================= 6 7 If you don't need internationalization in your app 8 ================================================== 9 10 Django's internationalization hooks are on by default, and that means there's a 11 bit of i18n-related overhead in certain places of the framework. If you don't 12 use internationalization, you should take the two seconds to set 13 :setting:`USE_I18N = False <USE_I18N>` in your settings file. If 14 :setting:`USE_I18N` is set to ``False``, then Django will make some 15 optimizations so as not to load the internationalization machinery. 16 17 You'll probably also want to remove ``'django.core.context_processors.i18n'`` 18 from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting. 19 20 If you do need internationalization 21 =================================== 22 23 .. _how-django-discovers-language-preference: 24 25 How Django discovers language preference 26 ---------------------------------------- 27 28 Once you've prepared your translations -- or, if you just want to use the 29 translations that come with Django -- you'll just need to activate translation 30 for your app. 31 32 Behind the scenes, Django has a very flexible model of deciding which language 33 should be used -- installation-wide, for a particular user, or both. 34 35 To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`. 36 Django uses this language as the default translation -- the final attempt if no 37 other translator finds a translation. 38 39 If all you want to do is run Django with your native language, and a language 40 file is available for it, all you need to do is set ``LANGUAGE_CODE``. 41 42 If you want to let each individual user specify which language he or she 43 prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language 44 selection based on data from the request. It customizes content for each user. 45 46 To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'`` 47 to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you 48 should follow these guidelines: 49 50 * Make sure it's one of the first middlewares installed. 51 * It should come after ``SessionMiddleware``, because ``LocaleMiddleware`` 52 makes use of session data. 53 * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it. 54 55 For example, your ``MIDDLEWARE_CLASSES`` might look like this:: 56 57 MIDDLEWARE_CLASSES = ( 58 'django.contrib.sessions.middleware.SessionMiddleware', 59 'django.middleware.locale.LocaleMiddleware', 60 'django.middleware.common.CommonMiddleware', 61 ) 62 63 (For more on middleware, see the :ref:`middleware documentation 64 <topics-http-middleware>`.) 65 66 ``LocaleMiddleware`` tries to determine the user's language preference by 67 following this algorithm: 68 69 * First, it looks for a ``django_language`` key in the current user's 70 session. 71 72 * Failing that, it looks for a cookie. 73 74 .. versionchanged:: 1.0 75 76 In Django version 0.96 and before, the cookie's name is hard-coded to 77 ``django_language``. In Django 1,0, The cookie name is set by the 78 ``LANGUAGE_COOKIE_NAME`` setting. (The default name is 79 ``django_language``.) 80 81 * Failing that, it looks at the ``Accept-Language`` HTTP header. This 82 header is sent by your browser and tells the server which language(s) you 83 prefer, in order by priority. Django tries each language in the header 84 until it finds one with available translations. 85 86 * Failing that, it uses the global ``LANGUAGE_CODE`` setting. 87 88 .. _locale-middleware-notes: 89 90 Notes: 91 92 * In each of these places, the language preference is expected to be in the 93 standard language format, as a string. For example, Brazilian Portuguese 94 is ``pt-br``. 95 96 * If a base language is available but the sublanguage specified is not, 97 Django uses the base language. For example, if a user specifies ``de-at`` 98 (Austrian German) but Django only has ``de`` available, Django uses 99 ``de``. 100 101 * Only languages listed in the :setting:`LANGUAGES` setting can be selected. 102 If you want to restrict the language selection to a subset of provided 103 languages (because your application doesn't provide all those languages), 104 set ``LANGUAGES`` to a list of languages. For example:: 105 106 LANGUAGES = ( 107 ('de', _('German')), 108 ('en', _('English')), 109 ) 110 111 This example restricts languages that are available for automatic 112 selection to German and English (and any sublanguage, like de-ch or 113 en-us). 114 115 .. _LANGUAGES setting: ../settings/#languages 116 117 * If you define a custom ``LANGUAGES`` setting, as explained in the 118 previous bullet, it's OK to mark the languages as translation strings 119 -- but use a "dummy" ``ugettext()`` function, not the one in 120 ``django.utils.translation``. You should *never* import 121 ``django.utils.translation`` from within your settings file, because that 122 module in itself depends on the settings, and that would cause a circular 123 import. 124 125 The solution is to use a "dummy" ``ugettext()`` function. Here's a sample 126 settings file:: 127 128 ugettext = lambda s: s 129 130 LANGUAGES = ( 131 ('de', ugettext('German')), 132 ('en', ugettext('English')), 133 ) 134 135 With this arrangement, ``django-admin.py makemessages`` will still find 136 and mark these strings for translation, but the translation won't happen 137 at runtime -- so you'll have to remember to wrap the languages in the 138 *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime. 139 140 * The ``LocaleMiddleware`` can only select languages for which there is a 141 Django-provided base translation. If you want to provide translations 142 for your application that aren't already in the set of translations 143 in Django's source tree, you'll want to provide at least a basic 144 one as described in the :ref:`Locale restrictions<locale-restrictions>` 145 note. 146 147 Once ``LocaleMiddleware`` determines the user's preference, it makes this 148 preference available as ``request.LANGUAGE_CODE`` for each 149 :class:`~django.http.HttpRequest`. Feel free to read this value in your view 150 code. Here's a simple example:: 151 152 def hello_world(request, count): 153 if request.LANGUAGE_CODE == 'de-at': 154 return HttpResponse("You prefer to read Austrian German.") 155 else: 156 return HttpResponse("You prefer to read another language.") 157 158 Note that, with static (middleware-less) translation, the language is in 159 ``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's 160 in ``request.LANGUAGE_CODE``. 161 162 .. _settings file: ../settings/ 163 .. _middleware documentation: ../middleware/ 164 .. _session: ../sessions/ 165 .. _request object: ../request_response/#httprequest-objects 166 167 How Django discovers translations 168 --------------------------------- 169 170 As described in :ref:`using-translations-in-your-own-projects`, 171 at runtime, Django looks for translations by following this algorithm: 172 173 * First, it looks for a ``locale`` directory in the application directory 174 of the view that's being called. If it finds a translation for the 175 selected language, the translation will be installed. 176 * Next, it looks for a ``locale`` directory in the project directory. If it 177 finds a translation, the translation will be installed. 178 * Finally, it checks the Django-provided base translation in 179 ``django/conf/locale``. -
new file docs/topics/i18n/index.txt
diff --git a/docs/topics/i18n/index.txt b/docs/topics/i18n/index.txt new file mode 100644
- + 1 .. _topics-i18n: 2 3 ===================================== 4 Internationalization and localization 5 ===================================== 6 7 Overview 8 ======== 9 10 Django has full support for internationalization of text in code and templates. 11 12 Essentially, Django does two things: 13 14 * It lets developers and template authors specify which parts of their apps 15 should be translatable. 16 * It uses these hooks to translate Web apps for particular users according 17 to their language preferences. 18 19 The complete process can be seen as divided in three stages. It is also possible 20 to identify an identical number of roles with very well defined responsabilities 21 associated with each of these tasks (although it's perfectly normal if you 22 find yourself performing more than one of these roles): 23 24 * For applicacion authors wishing to make sure their Django apps can be 25 used in different locales: Internationalization. 26 * For translators wanting to translate Django apps: Localization. 27 * For system administrators/final users setting up internationalized apps or 28 developers integrating third party apps: Deployment. 29 30 .. toctree:: 31 :maxdepth: 1 32 33 internationalization 34 localization 35 deployment 36 37 .. _ seealso:: 38 39 For more general information about the topic, see the `GNU gettext documentation`_ 40 and the `Wikipedia article`_ 41 42 .. _GNU gettext documentation: http://www.gnu.org/software/gettext/manual/gettext.html#Concepts 43 .. _Wikipedia article: http://en.wikipedia.org/wiki/Internationalization_and_localization 44 45 .. _specialties-of-django-i18n: 46 47 Specialties of Django translation 48 ================================== 49 50 Django's translation machinery uses the standard ``gettext`` module that comes 51 with Python. If you know ``gettext``, you might note these specialties in the 52 way Django does translation: 53 54 * The string domain is ``django`` or ``djangojs``. This string domain is 55 used to differentiate between different programs that store their data 56 in a common message-file library (usually ``/usr/share/locale/``). The 57 ``django`` domain is used for python and template translation strings 58 and is loaded into the global translation catalogs. The ``djangojs`` 59 domain is only used for JavaScript translation catalogs to make sure 60 that those are as small as possible. 61 * Django doesn't use ``xgettext`` alone. It uses Python wrappers around 62 ``xgettext`` and ``msgfmt``. This is mostly for convenience. 63 64 .. _technical-messages: 65 66 Django technical message IDs 67 ---------------------------- 68 69 Django uses **technical message IDs** to translate date formats and time 70 formats. Technical message IDs are message strings and can be easily recognized; 71 they're all upper case. You don't translate the message ID as with other message 72 strings, you provide the correct local variant on the provided English value. 73 The format is identical to the format strings used by the ``now`` template tag. 74 75 For example, with ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), 76 this would be the format string that you want to use in your language. A Django 77 contributor localizing it to Spanish probably would provide a ``"j N Y P"`` 78 "translation" for it in the relevant ``django.po`` file:: 79 80 msgid "DATETIME_FORMAT" 81 msgstr "j N Y P" -
new file docs/topics/i18n/internationalization.txt
diff --git a/docs/topics/i18n/internationalization.txt b/docs/topics/i18n/internationalization.txt new file mode 100644
- + 1 .. _topics-i18n-internationalization: 2 3 ==================== 4 Internationalization 5 ==================== 6 7 Overview 8 ======== 9 10 The goal of internationalization is to allow a single Web application to offer 11 its content and functionality in multiple languages. 12 13 You, the Django developer, can accomplish this goal by adding a minimal amount 14 of hooks to your Python (and JavaScript) code and templates. These hooks are 15 called **translation strings**. They tell Django: "This text should be 16 translated into the end user's language, if a translation for this text is 17 available in that language." . It's your responsibility to mark translatable 18 strings; the system can only translate strings it knows about. 19 20 Django takes care of using these hooks to translate Web apps, on the fly, 21 according to users' language preferences. 22 23 Specifying translation strings: In Python code 24 ============================================== 25 26 Standard translation 27 -------------------- 28 29 Specify a translation string by using the function ``ugettext()``. It's 30 convention to import this as a shorter alias, ``_``, to save typing. 31 32 .. note:: 33 Python's standard library ``gettext`` module installs ``_()`` into the 34 global namespace, as an alias for ``gettext()``. In Django, we have chosen 35 not to follow this practice, for a couple of reasons: 36 37 1. For international character set (Unicode) support, ``ugettext()`` is 38 more useful than ``gettext()``. Sometimes, you should be using 39 ``ugettext_lazy()`` as the default translation method for a particular 40 file. Without ``_()`` in the global namespace, the developer has to 41 think about which is the most appropriate translation function. 42 43 2. The underscore character (``_``) is used to represent "the previous 44 result" in Python's interactive shell and doctest tests. Installing a 45 global ``_()`` function causes interference. Explicitly importing 46 ``ugettext()`` as ``_()`` avoids this problem. 47 48 .. highlightlang:: python 49 50 In this example, the text ``"Welcome to my site."`` is marked as a translation 51 string:: 52 53 from django.utils.translation import ugettext as _ 54 55 def my_view(request): 56 output = _("Welcome to my site.") 57 return HttpResponse(output) 58 59 Obviously, you could code this without using the alias. This example is 60 identical to the previous one:: 61 62 from django.utils.translation import ugettext 63 64 def my_view(request): 65 output = ugettext("Welcome to my site.") 66 return HttpResponse(output) 67 68 Translation works on computed values. This example is identical to the previous 69 two:: 70 71 def my_view(request): 72 words = ['Welcome', 'to', 'my', 'site.'] 73 output = _(' '.join(words)) 74 return HttpResponse(output) 75 76 Translation works on variables. Again, here's an identical example:: 77 78 def my_view(request): 79 sentence = 'Welcome to my site.' 80 output = _(sentence) 81 return HttpResponse(output) 82 83 (The caveat with using variables or computed values, as in the previous two 84 examples, is that Django's translation-string-detecting utility, 85 ``django-admin.py makemessages``, won't be able to find these strings. More on 86 ``makemessages`` later.) 87 88 The strings you pass to ``_()`` or ``ugettext()`` can take placeholders, 89 specified with Python's standard named-string interpolation syntax. Example:: 90 91 def my_view(request, m, d): 92 output = _('Today is %(month)s, %(day)s.') % {'month': m, 'day': d} 93 return HttpResponse(output) 94 95 This technique lets language-specific translations reorder the placeholder 96 text. For example, an English translation may be ``"Today is November, 26."``, 97 while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the 98 placeholders (the month and the day) with their positions swapped. 99 100 For this reason, you should use named-string interpolation (e.g., ``%(day)s``) 101 instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you 102 have more than a single parameter. If you used positional interpolation, 103 translations wouldn't be able to reorder placeholder text. 104 105 Marking strings as no-op 106 ------------------------ 107 108 Use the function ``django.utils.translation.ugettext_noop()`` to mark a string 109 as a translation string without translating it. The string is later translated 110 from a variable. 111 112 Use this if you have constant strings that should be stored in the source 113 language because they are exchanged over systems or users -- such as strings in 114 a database -- but should be translated at the last possible point in time, such 115 as when the string is presented to the user. 116 117 Pluralization 118 ------------- 119 120 Use the function ``django.utils.translation.ungettext()`` to specify pluralized 121 messages. 122 123 ``ungettext`` takes three arguments: the singular translation string, the plural 124 translation string and the number of objects. 125 126 This function is useful when your need your Django application to be localizable 127 to languages where the number and complexity of `plural forms 128 <http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is 129 greater than the two forms used in English ('object' for the singular and 130 'objects' for all the cases where ``count`` is different from zero, irrespective 131 of its value.) 132 133 For example:: 134 135 from django.utils.translation import ungettext 136 def hello_world(request, count): 137 page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % { 138 'count': count, 139 } 140 return HttpResponse(page) 141 142 In this example the number of objects is passed to the translation languages as 143 the ``count`` variable. 144 145 Lets see a slightly more complex usage example:: 146 147 from django.utils.translation import ungettext 148 149 count = Report.objects.count() 150 if count == 1: 151 name = Report._meta.verbose_name 152 else: 153 name = Report._meta.verbose_name_plural 154 155 text = ungettext( 156 'There is %(count)d %(name)s available.', 157 'There are %(count)d %(name)s available.', 158 count 159 ) % { 160 'count': count, 161 'name': name 162 } 163 164 Here we reuse localizable, hopefully already translated literals (contained in 165 the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for 166 other parts of the sentence so all of it is consistently based on the 167 cardinality of the elements at play. 168 169 .. _pluralization-var-notes: 170 171 .. note:: 172 173 When using this technique, make sure you use a single name for every 174 extrapolated variable included in the literal. In the example above note how 175 we used the ``name`` Python variable in both translation strings. This 176 example would fail:: 177 178 from django.utils.translation import ungettext 179 from myapp.models import Report 180 181 count = Report.objects.count() 182 d = { 183 'count': count, 184 'name': Report._meta.verbose_name 185 'plural_name': Report._meta.verbose_name_plural 186 } 187 text = ungettext( 188 'There is %(count)d %(name)s available.', 189 'There are %(count)d %(plural_name)s available.', 190 count 191 ) % d 192 193 You would get a ``a format specification for argument 'name', as in 194 'msgstr[0]', doesn't exist in 'msgid'`` error when running 195 ``django-admin.py compilemessages`` or a ``KeyError`` Python exception at 196 runtime. 197 198 .. _lazy-translations: 199 200 Lazy translation 201 ---------------- 202 203 Use the function ``django.utils.translation.ugettext_lazy()`` to translate 204 strings lazily -- when the value is accessed rather than when the 205 ``ugettext_lazy()`` function is called. 206 207 For example, to translate a model's ``help_text``, do the following:: 208 209 from django.utils.translation import ugettext_lazy 210 211 class MyThing(models.Model): 212 name = models.CharField(help_text=ugettext_lazy('This is the help text')) 213 214 In this example, ``ugettext_lazy()`` stores a lazy reference to the string -- 215 not the actual translation. The translation itself will be done when the string 216 is used in a string context, such as template rendering on the Django admin 217 site. 218 219 The result of a ``ugettext_lazy()`` call can be used wherever you would use a 220 unicode string (an object with type ``unicode``) in Python. If you try to use 221 it where a bytestring (a ``str`` object) is expected, things will not work as 222 expected, since a ``ugettext_lazy()`` object doesn't know how to convert 223 itself to a bytestring. You can't use a unicode string inside a bytestring, 224 either, so this is consistent with normal Python behavior. For example:: 225 226 # This is fine: putting a unicode proxy into a unicode string. 227 u"Hello %s" % ugettext_lazy("people") 228 229 # This will not work, since you cannot insert a unicode object 230 # into a bytestring (nor can you insert our unicode proxy there) 231 "Hello %s" % ugettext_lazy("people") 232 233 If you ever see output that looks like ``"hello 234 <django.utils.functional...>"``, you have tried to insert the result of 235 ``ugettext_lazy()`` into a bytestring. That's a bug in your code. 236 237 If you don't like the verbose name ``ugettext_lazy``, you can just alias it as 238 ``_`` (underscore), like so:: 239 240 from django.utils.translation import ugettext_lazy as _ 241 242 class MyThing(models.Model): 243 name = models.CharField(help_text=_('This is the help text')) 244 245 Always use lazy translations in :ref:`Django models <topics-db-models>`. 246 Field names and table names should be marked for translation (otherwise, they 247 won't be translated in the admin interface). This means writing explicit 248 ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class, 249 though, rather than relying on Django's default determination of 250 ``verbose_name`` and ``verbose_name_plural`` by looking at the model's class 251 name:: 252 253 from django.utils.translation import ugettext_lazy as _ 254 255 class MyThing(models.Model): 256 name = models.CharField(_('name'), help_text=_('This is the help text')) 257 class Meta: 258 verbose_name = _('my thing') 259 verbose_name_plural = _('mythings') 260 261 Working with lazy translation objects 262 ------------------------------------- 263 264 .. highlightlang:: python 265 266 Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models 267 and utility functions is a common operation. When you're working with these 268 objects elsewhere in your code, you should ensure that you don't accidentally 269 convert them to strings, because they should be converted as late as possible 270 (so that the correct locale is in effect). This necessitates the use of a 271 couple of helper functions. 272 273 Joining strings: string_concat() 274 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 275 276 Standard Python string joins (``''.join([...])``) will not work on lists 277 containing lazy translation objects. Instead, you can use 278 ``django.utils.translation.string_concat()``, which creates a lazy object that 279 concatenates its contents *and* converts them to strings only when the result 280 is included in a string. For example:: 281 282 from django.utils.translation import string_concat 283 ... 284 name = ugettext_lazy(u'John Lennon') 285 instrument = ugettext_lazy(u'guitar') 286 result = string_concat([name, ': ', instrument]) 287 288 In this case, the lazy translations in ``result`` will only be converted to 289 strings when ``result`` itself is used in a string (usually at template 290 rendering time). 291 292 The allow_lazy() decorator 293 ~~~~~~~~~~~~~~~~~~~~~~~~~~ 294 295 Django offers many utility functions (particularly in ``django.utils``) that 296 take a string as their first argument and do something to that string. These 297 functions are used by template filters as well as directly in other code. 298 299 If you write your own similar functions and deal with translations, you'll 300 face the problem of what to do when the first argument is a lazy translation 301 object. You don't want to convert it to a string immediately, because you might 302 be using this function outside of a view (and hence the current thread's locale 303 setting will not be correct). 304 305 For cases like this, use the ``django.utils.functional.allow_lazy()`` 306 decorator. It modifies the function so that *if* it's called with a lazy 307 translation as the first argument, the function evaluation is delayed until it 308 needs to be converted to a string. 309 310 For example:: 311 312 from django.utils.functional import allow_lazy 313 314 def fancy_utility_function(s, ...): 315 # Do some conversion on string 's' 316 ... 317 fancy_utility_function = allow_lazy(fancy_utility_function, unicode) 318 319 The ``allow_lazy()`` decorator takes, in addition to the function to decorate, 320 a number of extra arguments (``*args``) specifying the type(s) that the 321 original function can return. Usually, it's enough to include ``unicode`` here 322 and ensure that your function returns only Unicode strings. 323 324 Using this decorator means you can write your function and assume that the 325 input is a proper string, then add support for lazy translation objects at the 326 end. 327 328 Specifying translation strings: In template code 329 ================================================ 330 331 .. highlightlang:: html+django 332 333 Translations in :ref:`Django templates <topics-templates>` uses two template 334 tags and a slightly different syntax than in Python code. To give your template 335 access to these tags, put ``{% load i18n %}`` toward the top of your template. 336 337 The ``{% trans %}`` template tag translates either a constant string 338 (enclosed in single or double quotes) or variable content:: 339 340 <title>{% trans "This is the title." %}</title> 341 <title>{% trans myvar %}</title> 342 343 If the ``noop`` option is present, variable lookup still takes place but the 344 translation is skipped. This is useful when "stubbing out" content that will 345 require translation in the future:: 346 347 <title>{% trans "myvar" noop %}</title> 348 349 Internally, inline translations use an ``ugettext`` call. 350 351 It's not possible to mix a template variable inside a string within ``{% trans 352 %}``. If your translations require strings with variables (placeholders), use 353 ``{% blocktrans %}``:: 354 355 {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %} 356 357 To translate a template expression -- say, using template filters -- you need 358 to bind the expression to a local variable for use within the translation 359 block:: 360 361 {% blocktrans with value|filter as myvar %} 362 This will have {{ myvar }} inside. 363 {% endblocktrans %} 364 365 If you need to bind more than one expression inside a ``blocktrans`` tag, 366 separate the pieces with ``and``:: 367 368 {% blocktrans with book|title as book_t and author|title as author_t %} 369 This is {{ book_t }} by {{ author_t }} 370 {% endblocktrans %} 371 372 To pluralize, specify both the singular and plural forms with the 373 ``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and 374 ``{% endblocktrans %}``. Example:: 375 376 {% blocktrans count list|length as counter %} 377 There is only one {{ name }} object. 378 {% plural %} 379 There are {{ counter }} {{ name }} objects. 380 {% endblocktrans %} 381 382 When you use the pluralization feature and bind additional values to local 383 variables apart from the counter value that selects the translated literal to be 384 used, have in mind that the ``blocktrans`` construct is internally converted 385 to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext 386 variables <pluralization-var-notes>` apply. 387 388 Each ``RequestContext`` has access to three translation-specific variables: 389 390 * ``LANGUAGES`` is a list of tuples in which the first element is the 391 language code and the second is the language name (translated into the 392 currently active locale). 393 394 * ``LANGUAGE_CODE`` is the current user's preferred language, as a string. 395 Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`, 396 below.) 397 398 * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a 399 right-to-left language, e.g.: Hebrew, Arabic. If False it's a 400 left-to-right language, e.g.: English, French, German etc. 401 402 403 If you don't use the ``RequestContext`` extension, you can get those values with 404 three tags:: 405 406 {% get_current_language as LANGUAGE_CODE %} 407 {% get_available_languages as LANGUAGES %} 408 {% get_current_language_bidi as LANGUAGE_BIDI %} 409 410 These tags also require a ``{% load i18n %}``. 411 412 Translation hooks are also available within any template block tag that accepts 413 constant strings. In those cases, just use ``_()`` syntax to specify a 414 translation string:: 415 416 {% some_special_tag _("Page not found") value|yesno:_("yes,no") %} 417 418 In this case, both the tag and the filter will see the already-translated 419 string, so they don't need to be aware of translations. 420 421 .. note:: 422 In this example, the translation infrastructure will be passed the string 423 ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The 424 translated string will need to contain the comma so that the filter 425 parsing code knows how to split up the arguments. For example, a German 426 translator might translate the string ``"yes,no"`` as ``"ja,nein"`` 427 (keeping the comma intact). 428 429 .. _Django templates: ../templates_python/ 430 431 Specifying translation strings: In JavaScript code 432 ================================================== 433 434 Adding translations to JavaScript poses some problems: 435 436 * JavaScript code doesn't have access to a ``gettext`` implementation. 437 438 * JavaScript code doesn't have access to .po or .mo files; they need to be 439 delivered by the server. 440 441 * The translation catalogs for JavaScript should be kept as small as 442 possible. 443 444 Django provides an integrated solution for these problems: It passes the 445 translations into JavaScript, so you can call ``gettext``, etc., from within 446 JavaScript. 447 448 The ``javascript_catalog`` view 449 ------------------------------- 450 451 The main solution to these problems is the ``javascript_catalog`` view, which 452 sends out a JavaScript code library with functions that mimic the ``gettext`` 453 interface, plus an array of translation strings. Those translation strings are 454 taken from the application, project or Django core, according to what you 455 specify in either the info_dict or the URL. 456 457 You hook it up like this:: 458 459 js_info_dict = { 460 'packages': ('your.app.package',), 461 } 462 463 urlpatterns = patterns('', 464 (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), 465 ) 466 467 Each string in ``packages`` should be in Python dotted-package syntax (the 468 same format as the strings in ``INSTALLED_APPS``) and should refer to a package 469 that contains a ``locale`` directory. If you specify multiple packages, all 470 those catalogs are merged into one catalog. This is useful if you have 471 JavaScript that uses strings from different applications. 472 473 You can make the view dynamic by putting the packages into the URL pattern:: 474 475 urlpatterns = patterns('', 476 (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'), 477 ) 478 479 With this, you specify the packages as a list of package names delimited by '+' 480 signs in the URL. This is especially useful if your pages use code from 481 different apps and this changes often and you don't want to pull in one big 482 catalog file. As a security measure, these values can only be either 483 ``django.conf`` or any package from the ``INSTALLED_APPS`` setting. 484 485 Using the JavaScript translation catalog 486 ---------------------------------------- 487 488 To use the catalog, just pull in the dynamically generated script like this:: 489 490 <script type="text/javascript" src="/path/to/jsi18n/"></script> 491 492 This is how the admin fetches the translation catalog from the server. When the 493 catalog is loaded, your JavaScript code can use the standard ``gettext`` 494 interface to access it:: 495 496 document.write(gettext('this is to be translated')); 497 498 There is also an ``ngettext`` interface:: 499 500 var object_cnt = 1 // or 0, or 2, or 3, ... 501 s = ngettext('literal for the singular case', 502 'literal for the plural case', object_cnt); 503 504 and even a string interpolation function:: 505 506 function interpolate(fmt, obj, named); 507 508 The interpolation syntax is borrowed from Python, so the ``interpolate`` 509 function supports both positional and named interpolation: 510 511 * Positional interpolation: ``obj`` contains a JavaScript Array object 512 whose elements values are then sequentially interpolated in their 513 corresponding ``fmt`` placeholders in the same order they appear. 514 For example:: 515 516 fmts = ngettext('There is %s object. Remaining: %s', 517 'There are %s objects. Remaining: %s', 11); 518 s = interpolate(fmts, [11, 20]); 519 // s is 'There are 11 objects. Remaining: 20' 520 521 * Named interpolation: This mode is selected by passing the optional 522 boolean ``named`` parameter as true. ``obj`` contains a JavaScript 523 object or associative array. For example:: 524 525 d = { 526 count: 10 527 total: 50 528 }; 529 530 fmts = ngettext('Total: %(total)s, there is %(count)s object', 531 'there are %(count)s of a total of %(total)s objects', d.count); 532 s = interpolate(fmts, d, true); 533 534 You shouldn't go over the top with string interpolation, though: this is still 535 JavaScript, so the code has to make repeated regular-expression substitutions. 536 This isn't as fast as string interpolation in Python, so keep it to those 537 cases where you really need it (for example, in conjunction with ``ngettext`` 538 to produce proper pluralizations). 539 540 The ``set_language`` redirect view 541 ================================== 542 543 As a convenience, Django comes with a view, ``django.views.i18n.set_language``, 544 that sets a user's language preference and redirects back to the previous page. 545 546 Activate this view by adding the following line to your URLconf:: 547 548 (r'^i18n/', include('django.conf.urls.i18n')), 549 550 (Note that this example makes the view available at ``/i18n/setlang/``.) 551 552 The view expects to be called via the ``POST`` method, with a ``language`` 553 parameter set in request. If session support is enabled, the view 554 saves the language choice in the user's session. Otherwise, it saves the 555 language choice in a cookie that is by default named ``django_language``. 556 (The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.) 557 558 After setting the language choice, Django redirects the user, following this 559 algorithm: 560 561 * Django looks for a ``next`` parameter in the ``POST`` data. 562 * If that doesn't exist, or is empty, Django tries the URL in the 563 ``Referrer`` header. 564 * If that's empty -- say, if a user's browser suppresses that header -- 565 then the user will be redirected to ``/`` (the site root) as a fallback. 566 567 Here's example HTML template code: 568 569 .. code-block:: html+django 570 571 <form action="/i18n/setlang/" method="post"> 572 <input name="next" type="hidden" value="/next/page/" /> 573 <select name="language"> 574 {% for lang in LANGUAGES %} 575 <option value="{{ lang.0 }}">{{ lang.1 }}</option> 576 {% endfor %} 577 </select> 578 <input type="submit" value="Go" /> 579 </form> -
new file docs/topics/i18n/localization.txt
diff --git a/docs/topics/i18n/localization.txt b/docs/topics/i18n/localization.txt new file mode 100644
- + 1 .. _topics-i18n-localization: 2 3 ============ 4 Localization 5 ============ 6 7 .. _how-to-create-language-files: 8 9 How to create language files 10 ============================ 11 12 Once the string literals of an application have been tagged for later 13 translation, the translation themselves need to be written (or obtained). Here's 14 how that works. 15 16 .. _locale-restrictions: 17 18 .. admonition:: Locale restrictions 19 20 Django does not support localizing your application into a locale for which 21 Django itself has not been translated. In this case, it will ignore your 22 translation files. If you were to try this and Django supported it, you 23 would inevitably see a mixture of translated strings (from your application) 24 and English strings (from Django itself). If you want to support a locale 25 for your application that is not already part of Django, you'll need to make 26 at least a minimal translation of the Django core. 27 28 A good starting point is to copy the Django English ``.po`` file and to 29 translate at least the :ref:`technical-messages` -- maybe the validation 30 messages, too. 31 32 Message files 33 ------------- 34 35 The first step is to create a **message file** for a new language. A message 36 file is a plain-text file, representing a single language, that contains all 37 available translation strings and how they should be represented in the given 38 language. Message files have a ``.po`` file extension. 39 40 Django comes with a tool, ``django-admin.py makemessages``, that automates the 41 creation and upkeep of these files. 42 43 .. admonition:: A note to Django veterans 44 45 The old tool ``bin/make-messages.py`` has been moved to the command 46 ``django-admin.py makemessages`` to provide consistency throughout Django. 47 48 To create or update a message file, run this command:: 49 50 django-admin.py makemessages -l de 51 52 ...where ``de`` is the language code for the message file you want to create. 53 The language code, in this case, is in locale format. For example, it's 54 ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian German. 55 56 The script should be run from one of two places: 57 58 * The root directory of your Django project. 59 * The root directory of your Django app. 60 61 Th script runs over your project source tree or your application source tree and 62 pulls out all strings marked for translation. It creates (or updates) a message 63 file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de`` example, the 64 file will be ``locale/de/LC_MESSAGES/django.po``. 65 66 By default ``django-admin.py makemessages`` examines every file that has the 67 ``.html`` file extension. In case you want to override that default, use the 68 ``--extension`` or ``-e`` option to specify the file extensions to examine:: 69 70 django-admin.py makemessages -l de -e txt 71 72 Separate multiple extensions with commas and/or use ``-e`` or ``--extension`` 73 multiple times:: 74 75 django-admin.py makemessages -l=de -e=html,txt -e xml 76 77 When :ref:`creating message files from JavaScript source code 78 <creating-message-files-from-js-code>` you need to use the special 'djangojs' 79 domain, **not** ``-e js``. 80 81 .. admonition:: No gettext? 82 83 If you don't have the ``gettext`` utilities installed, ``django-admin.py 84 makemessages`` will create empty files. If that's the case, either install 85 the ``gettext`` utilities or just copy the English message file 86 (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting 87 point; it's just an empty translation file. 88 89 .. admonition:: Working on Windows? 90 91 If you're using Windows and need to install the GNU gettext utilities so 92 ``django-admin makemessages`` works see :ref:`gettext_on_windows` for more 93 information. 94 95 The format of ``.po`` files is straightforward. Each ``.po`` file contains a 96 small bit of metadata, such as the translation maintainer's contact 97 information, but the bulk of the file is a list of **messages** -- simple 98 mappings between translation strings and the actual translated text for the 99 particular language. 100 101 For example, if your Django app contained a translation string for the text 102 ``"Welcome to my site."``, like so:: 103 104 _("Welcome to my site.") 105 106 ...then ``django-admin.py makemessages`` will have created a ``.po`` file 107 containing the following snippet -- a message:: 108 109 #: path/to/python/module.py:23 110 msgid "Welcome to my site." 111 msgstr "" 112 113 A quick explanation: 114 115 * ``msgid`` is the translation string, which appears in the source. Don't 116 change it. 117 * ``msgstr`` is where you put the language-specific translation. It starts 118 out empty, so it's your responsibility to change it. Make sure you keep 119 the quotes around your translation. 120 * As a convenience, each message includes, in the form of a comment line 121 prefixed with ``#`` and located above the ``msgid`` line, the filename and 122 line number from which the translation string was gleaned. 123 124 Long messages are a special case. There, the first string directly after the 125 ``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be 126 written over the next few lines as one string per line. Those strings are 127 directly concatenated. Don't forget trailing spaces within the strings; 128 otherwise, they'll be tacked together without whitespace! 129 130 .. admonition:: Mind your charset 131 132 When creating a PO file with your favorite text editor, first edit 133 the charset line (search for ``"CHARSET"``) and set it to the charset 134 you'll be using to edit the content. Due to the way the ``gettext`` tools 135 work internally and because we want to allow non-ASCII source strings in 136 Django's core and your applications, you **must** use UTF-8 as the encoding 137 for your PO file. This means that everybody will be using the same 138 encoding, which is important when Django processes the PO files. 139 140 To reexamine all source code and templates for new translation strings and 141 update all message files for **all** languages, run this:: 142 143 django-admin.py makemessages -a 144 145 Compiling message files 146 ----------------------- 147 148 After you create your message file -- and each time you make changes to it -- 149 you'll need to compile it into a more efficient form, for use by ``gettext``. 150 Do this with the ``django-admin.py compilemessages`` utility. 151 152 This tool runs over all available ``.po`` files and creates ``.mo`` files, which 153 are binary files optimized for use by ``gettext``. In the same directory from 154 which you ran ``django-admin.py makemessages``, run ``django-admin.py 155 compilemessages`` like this:: 156 157 django-admin.py compilemessages 158 159 That's it. Your translations are ready for use. 160 161 .. admonition:: A note to Django veterans 162 163 The old tool ``bin/compile-messages.py`` has been moved to the command 164 ``django-admin.py compilemessages`` to provide consistency throughout 165 Django. 166 167 .. admonition:: Working on Windows? 168 169 If you're using Windows and need to install the GNU gettext utilities so 170 ``django-admin compilemessages`` works see :ref:`gettext_on_windows` for more 171 information. 172 173 .. _creating-message-files-from-js-code: 174 175 Creating message files from JavaScript source code 176 ================================================== 177 178 You create and update the message files the same way as the other Django message 179 files -- with the ``django-admin.py makemessages`` tool. The only difference is 180 you need to provide a ``-d djangojs`` parameter, like this:: 181 182 django-admin.py makemessages -d djangojs -l de 183 184 This would create or update the message file for JavaScript for German. 185 After updating message files, just run ``django-admin.py compilemessages`` 186 the same way as you do with normal Django message files. 187 188 .. _gettext_on_windows: 189 190 ``gettext`` on Windows 191 ====================== 192 193 This is only needed for people who either want to extract message IDs or compile 194 message files (``.po``). Translation work itself just involves editing existing 195 files of this type, but if you want to create your own message files, or want to 196 test or compile a changed message file, you will need the ``gettext`` utilities: 197 198 * Download the following zip files from the GNOME servers 199 http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one 200 of its mirrors_ 201 202 * ``gettext-runtime-X.zip`` 203 * ``gettext-tools-X.zip`` 204 205 ``X`` is the version number, we recomend using ``0.15`` or higher. 206 207 * Extract the contents of the ``bin\`` directories in both files to the 208 same folder on your system (i.e. ``C:\Program Files\gettext-utils``) 209 210 * Update the system PATH: 211 212 * ``Control Panel > System > Advanced > Environment Variables`` 213 * In the ``System variables`` list, click ``Path``, click ``Edit`` 214 * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the 215 ``Variable value`` field 216 217 .. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS 218 219 You may also use ``gettext`` binaries you have obtained elsewhere, so long as 220 the ``xgettext --version`` command works properly. Some version 0.14.4 binaries 221 have been found to not support this command. Do not attempt to use Django 222 translation utilities with a ``gettext`` package if the command ``xgettext 223 --version`` entered at a Windows command prompt causes a popup window saying 224 "xgettext.exe has generated errors and will be closed by Windows". -
docs/topics/index.txt
diff --git a/docs/topics/index.txt b/docs/topics/index.txt
a b 21 21 cache 22 22 conditional-view-processing 23 23 email 24 i18n 24 i18n/index 25 25 pagination 26 26 serialization 27 27 settings