Ticket #10260: 10260-i18n_docs_refactor-r11173.diff

File 10260-i18n_docs_refactor-r11173.diff, 94.4 KB (added by Ramiro Morales, 15 years ago)

Patch updated to include changes from r11103 and r11164 plus further modifications

  • 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===============================================
     6Using internationalization in your own projects
     7===============================================
     8
     9At 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
     19This way, you can write applications that include their own translations, and
     20you can override base translations in your project path. Or, you can just build
     21a big project out of several apps and put all translations into one big project
     22message 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
     33All 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
     41To create message files, you use the ``django-admin.py makemessages`` tool. You
     42only need to be in the same directory where the ``locale/`` directory is
     43located. 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
     47You can also run ``django-admin.py compilemessages --settings=path.to.settings``
     48to make the compiler process all the directories in your ``LOCALE_PATHS``
     49setting.
     50
     51Application message files are a bit complicated to discover -- they need the
     52``LocaleMiddleware``. If you don't use the middleware, only the Django message
     53files and project message files will be installed and available at runtime.
     54
     55Finally, you should give some thought to the structure of your translation
     56files. If your applications need to be delivered to other users and will
     57be used in other projects, you might want to use app-specific translations.
     58But using app-specific translations and project translations could produce
     59weird problems with ``makemessages``: ``makemessages`` will traverse all
     60directories below the current path and so might put message IDs into the
     61project message file that are already in application message files.
     62
     63The 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
     66strings that are connected to your explicit project and not strings that are
     67distributed independently.
  • docs/howto/index.txt

    diff --git a/docs/howto/index.txt b/docs/howto/index.txt
    a b  
    2020   deployment/index
    2121   error-reporting
    2222   initial-data
     23   i18n
    2324   jython
    2425   legacy-databases
    2526   outputting-csv
  • docs/internals/contributing.txt

    diff --git a/docs/internals/contributing.txt b/docs/internals/contributing.txt
    a b  
    402402
    403403    * Join the `Django i18n mailing list`_ and introduce yourself.
    404404
     405    * Make sure you read the notes about :ref:`specialties-of-django-i18n`.
     406
    405407    * 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.
    409412
    410413      The script runs over the entire Django source tree and pulls out all
    411414      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 be
    413       ``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``).
    414417
    415418    * Make sure that ``django-admin.py compilemessages -l <lang>`` runs without
    416419      producing any warnings.
  • docs/ref/settings.txt

    diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
    a b  
    667667Default: ``()`` (Empty tuple)
    668668
    669669A tuple of directories where Django looks for translation files.
    670 See :ref:`translations-in-your-own-projects`.
     670See :ref:`using-translations-in-your-own-projects`.
    671671
    672672.. setting:: LOGIN_REDIRECT_URL
    673673
  • 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 Internationalization
    5 ====================
    6 
    7 Django has full support for internationalization of text in code and templates.
    8 Here's how it works.
    9 
    10 Overview
    11 ========
    12 
    13 The goal of internationalization is to allow a single Web application to offer
    14 its content and functionality in multiple languages.
    15 
    16 You, the Django developer, can accomplish this goal by adding a minimal amount
    17 of hooks to your Python code and templates. These hooks are called
    18 **translation strings**. They tell Django: "This text should be translated into
    19 the end user's language, if a translation for this text is available in that
    20 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 apps
    28       should be translatable.
    29     * It uses these hooks to translate Web apps for particular users according
    30       to their language preferences.
    31 
    32 If you don't need internationalization in your app
    33 ==================================================
    34 
    35 Django's internationalization hooks are on by default, and that means there's a
    36 bit of i18n-related overhead in certain places of the framework. If you don't
    37 use internationalization, you should take the two seconds to set
    38 :setting:`USE_I18N = False <USE_I18N>` in your settings file. If
    39 :setting:`USE_I18N` is set to ``False``, then Django will make some
    40 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 steps
    46 ================================================
    47 
    48     1. Embed translation strings in your Python code and templates.
    49     2. Get translations for those strings, in whichever languages you want to
    50        support.
    51     3. Activate the locale middleware in your Django settings.
    52 
    53 .. admonition:: Behind the scenes
    54 
    55     Django's translation machinery uses the standard ``gettext`` module that
    56     comes with Python.
    57 
    58 1. How to specify translation strings
    59 =====================================
    60 
    61 Translation strings specify "This text should be translated." These strings can
    62 appear in your Python code and templates. It's your responsibility to mark
    63 translatable strings; the system can only translate strings it knows about.
    64 
    65 In Python code
    66 --------------
    67 
    68 Standard translation
    69 ~~~~~~~~~~~~~~~~~~~~
    70 
    71 Specify a translation string by using the function ``ugettext()``. It's
    72 convention to import this as a shorter alias, ``_``, to save typing.
    73 
    74 .. note::
    75     Python's standard library ``gettext`` module installs ``_()`` into the
    76     global namespace, as an alias for ``gettext()``. In Django, we have chosen
    77     not to follow this practice, for a couple of reasons:
    78 
    79       1. For international character set (Unicode) support, ``ugettext()`` is
    80          more useful than ``gettext()``. Sometimes, you should be using
    81          ``ugettext_lazy()`` as the default translation method for a particular
    82          file. Without ``_()`` in the global namespace, the developer has to
    83          think about which is the most appropriate translation function.
    84 
    85       2. The underscore character (``_``) is used to represent "the previous
    86          result" in Python's interactive shell and doctest tests. Installing a
    87          global ``_()`` function causes interference. Explicitly importing
    88          ``ugettext()`` as ``_()`` avoids this problem.
    89 
    90 .. highlightlang:: python
    91 
    92 In this example, the text ``"Welcome to my site."`` is marked as a translation
    93 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 is
    102 identical to the previous one::
    103 
    104     from django.utils.translation import ugettext
    105 
    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 previous
    111 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 two
    126 examples, is that Django's translation-string-detecting utility,
    127 ``django-admin.py makemessages``, won't be able to find these strings. More on
    128 ``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 placeholder
    138 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 the
    140 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 you
    144 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-op
    148 ~~~~~~~~~~~~~~~~~~~~~~~~
    149 
    150 Use the function ``django.utils.translation.ugettext_noop()`` to mark a string
    151 as a translation string without translating it. The string is later translated
    152 from a variable.
    153 
    154 Use this if you have constant strings that should be stored in the source
    155 language because they are exchanged over systems or users -- such as strings in
    156 a database -- but should be translated at the last possible point in time, such
    157 as when the string is presented to the user.
    158 
    159 .. _lazy-translations:
    160 
    161 Lazy translation
    162 ~~~~~~~~~~~~~~~~
    163 
    164 Use the function ``django.utils.translation.ugettext_lazy()`` to translate
    165 strings lazily -- when the value is accessed rather than when the
    166 ``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_lazy
    171 
    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 string
    177 is used in a string context, such as template rendering on the Django admin
    178 site.
    179 
    180 The result of a ``ugettext_lazy()`` call can be used wherever you would use a
    181 unicode string (an object with type ``unicode``) in Python. If you try to use
    182 it where a bytestring (a ``str`` object) is expected, things will not work as
    183 expected, since a ``ugettext_lazy()`` object doesn't know how to convert
    184 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 object
    191     # 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 ``"hello
    195 <django.utils.functional...>"``, you have tried to insert the result of
    196 ``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 as
    199 ``_`` (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, they
    208 won't be translated in the admin interface). This means writing explicit
    209 ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class,
    210 though, rather than relying on Django's default determination of
    211 ``verbose_name`` and ``verbose_name_plural`` by looking at the model's class
    212 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 Pluralization
    223 ~~~~~~~~~~~~~
    224 
    225 Use the function ``django.utils.translation.ungettext()`` to specify pluralized
    226 messages.
    227 
    228 ``ungettext`` takes three arguments: the singular translation string, the plural
    229 translation string and the number of objects.
    230 
    231 This function is useful when your need you Django application to be localizable
    232 to languages where the number and complexity of `plural forms
    233 <http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is
    234 greater than the two forms used in English ('object' for the singular and
    235 'objects' for all the cases where ``count`` is different from zero, irrespective
    236 of its value.)
    237 
    238 For example::
    239 
    240     from django.utils.translation import ungettext
    241     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 as
    248 the ``count`` variable.
    249 
    250 Lets see a slightly more complex usage example::
    251 
    252     from django.utils.translation import ungettext
    253 
    254     count = Report.objects.count()
    255     if count == 1:
    256         name = Report._meta.verbose_name
    257     else:
    258         name = Report._meta.verbose_name_plural
    259 
    260     text = ungettext(
    261             'There is %(count)d %(name)s available.',
    262             'There are %(count)d %(name)s available.',
    263             count
    264     ) % {
    265         'count': count,
    266         'name': name
    267     }
    268 
    269 Here we reuse localizable, hopefully already translated literals (contained in
    270 the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for
    271 other parts of the sentence so all of it is consistently based on the
    272 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 every
    279     extrapolated variable included in the literal. In the example above note how
    280     we used the ``name`` Python variable in both translation strings. This
    281     example would fail::
    282 
    283         from django.utils.translation import ungettext
    284         from myapp.models import Report
    285 
    286         count = Report.objects.count()
    287         d = {
    288             'count': count,
    289             'name': Report._meta.verbose_name
    290             'plural_name': Report._meta.verbose_name_plural
    291         }
    292         text = ungettext(
    293                 'There is %(count)d %(name)s available.',
    294                 'There are %(count)d %(plural_name)s available.',
    295                 count
    296         ) % d
    297 
    298     You would get a ``a format specification for argument 'name', as in
    299     'msgstr[0]', doesn't exist in 'msgid'`` error when running
    300     ``django-admin.py compilemessages`` or a ``KeyError`` Python exception at
    301     runtime.
    302 
    303 In template code
    304 ----------------
    305 
    306 .. highlightlang:: html+django
    307 
    308 Translations in :ref:`Django templates <topics-templates>` uses two template
    309 tags and a slightly different syntax than in Python code. To give your template
    310 access to these tags, put ``{% load i18n %}`` toward the top of your template.
    311 
    312 The ``{% trans %}`` template tag translates either a constant string
    313 (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 the
    319 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 ``{% trans
    327 %}``. If your translations require strings with variables (placeholders), use
    328 ``{% blocktrans %}``::
    329 
    330     {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
    331 
    332 To translate a template expression -- say, using template filters -- you need
    333 to bind the expression to a local variable for use within the translation
    334 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 the
    348 ``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and
    349 ``{% 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 local
    358 variables apart from the counter value that selects the translated literal to be
    359 used, have in mind that the ``blocktrans`` construct is internally converted
    360 to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext
    361 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 the
    366       language code and the second is the language name (translated into the
    367       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 a
    374       right-to-left language, e.g.: Hebrew, Arabic. If False it's a
    375       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 with
    379 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 accepts
    388 constant strings. In those cases, just use ``_()`` syntax to specify a
    389 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-translated
    394 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 string
    398     ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The
    399     translated string will need to contain the comma so that the filter
    400     parsing code knows how to split up the arguments. For example, a German
    401     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 objects
    407 -------------------------------------
    408 
    409 .. highlightlang:: python
    410 
    411 Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models
    412 and utility functions is a common operation. When you're working with these
    413 objects elsewhere in your code, you should ensure that you don't accidentally
    414 convert them to strings, because they should be converted as late as possible
    415 (so that the correct locale is in effect). This necessitates the use of a
    416 couple of helper functions.
    417 
    418 Joining strings: string_concat()
    419 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    420 
    421 Standard Python string joins (``''.join([...])``) will not work on lists
    422 containing lazy translation objects. Instead, you can use
    423 ``django.utils.translation.string_concat()``, which creates a lazy object that
    424 concatenates its contents *and* converts them to strings only when the result
    425 is included in a string. For example::
    426 
    427     from django.utils.translation import string_concat
    428     ...
    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 to
    434 strings when ``result`` itself is used in a string (usually at template
    435 rendering time).
    436 
    437 The allow_lazy() decorator
    438 ~~~~~~~~~~~~~~~~~~~~~~~~~~
    439 
    440 Django offers many utility functions (particularly in ``django.utils``) that
    441 take a string as their first argument and do something to that string. These
    442 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'll
    445 face the problem of what to do when the first argument is a lazy translation
    446 object. You don't want to convert it to a string immediately, because you might
    447 be using this function outside of a view (and hence the current thread's locale
    448 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 lazy
    452 translation as the first argument, the function evaluation is delayed until it
    453 needs to be converted to a string.
    454 
    455 For example::
    456 
    457     from django.utils.functional import allow_lazy
    458 
    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 the
    466 original function can return. Usually, it's enough to include ``unicode`` here
    467 and ensure that your function returns only Unicode strings.
    468 
    469 Using this decorator means you can write your function and assume that the
    470 input is a proper string, then add support for lazy translation objects at the
    471 end.
    472 
    473 .. _how-to-create-language-files:
    474 
    475 2. How to create language files
    476 ===============================
    477 
    478 Once you've tagged your strings for later translation, you need to write (or
    479 obtain) the language translations themselves. Here's how that works.
    480 
    481 .. admonition:: Locale restrictions
    482 
    483     Django does not support localizing your application into a locale for
    484     which Django itself has not been translated. In this case, it will ignore
    485     your translation files. If you were to try this and Django supported it,
    486     you would inevitably see a mixture of translated strings (from your
    487     application) and English strings (from Django itself). If you want to
    488     support a locale for your application that is not already part of
    489     Django, you'll need to make at least a minimal translation of the Django
    490     core. See the relevant :ref:`LocaleMiddleware note<locale-middleware-notes>`
    491     for more details.
    492 
    493 Message files
    494 -------------
    495 
    496 The first step is to create a **message file** for a new language. A message
    497 file is a plain-text file, representing a single language, that contains all
    498 available translation strings and how they should be represented in the given
    499 language. Message files have a ``.po`` file extension.
    500 
    501 Django comes with a tool, ``django-admin.py makemessages``, that automates the
    502 creation and upkeep of these files.
    503 
    504 .. admonition:: A note to Django veterans
    505 
    506     The old tool ``bin/make-messages.py`` has been moved to the command
    507     ``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 de
    512 
    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's
    515 ``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 one
    522       that is linked-to via ``$PYTHONPATH`` or is located somewhere on that
    523       path). This is only relevant when you are creating a translation for
    524       Django itself, see :ref:`contributing-translations`.
    525 
    526 The script runs over your project source tree or your application source tree
    527 and pulls out all strings marked for translation. It creates (or updates) a
    528 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 the
    532 ``.html`` file extension. In case you want to override that default, use the
    533 ``--extension`` or ``-e`` option to specify the file extensions to examine::
    534 
    535     django-admin.py makemessages -l de -e txt
    536 
    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 xml
    541 
    542 When `creating JavaScript translation catalogs`_ you need to use the special
    543 '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.py
    550     makemessages`` will create empty files. If that's the case, either install
    551     the ``gettext`` utilities or just copy the English message file
    552     (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting
    553     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 so
    558    ``django-admin makemessages`` works see `gettext on Windows`_ for more
    559    information.
    560 
    561 The format of ``.po`` files is straightforward. Each ``.po`` file contains a
    562 small bit of metadata, such as the translation maintainer's contact
    563 information, but the bulk of the file is a list of **messages** -- simple
    564 mappings between translation strings and the actual translated text for the
    565 particular language.
    566 
    567 For example, if your Django app contained a translation string for the text
    568 ``"Welcome to my site."``, like so::
    569 
    570     _("Welcome to my site.")
    571 
    572 ...then ``django-admin.py makemessages`` will have created a ``.po`` file
    573 containing the following snippet -- a message::
    574 
    575     #: path/to/python/module.py:23
    576     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't
    582       change it.
    583     * ``msgstr`` is where you put the language-specific translation. It starts
    584       out empty, so it's your responsibility to change it. Make sure you keep
    585       the quotes around your translation.
    586     * As a convenience, each message includes, in the form of a comment line
    587       prefixed with ``#`` and located above the ``msgid`` line, the filename and
    588       line number from which the translation string was gleaned.
    589 
    590 Long messages are a special case. There, the first string directly after the
    591 ``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be
    592 written over the next few lines as one string per line. Those strings are
    593 directly concatenated. Don't forget trailing spaces within the strings;
    594 otherwise, they'll be tacked together without whitespace!
    595 
    596 .. admonition:: Mind your charset
    597 
    598     When creating a PO file with your favorite text editor, first edit
    599     the charset line (search for ``"CHARSET"``) and set it to the charset
    600     you'll be using to edit the content. Due to the way the ``gettext`` tools
    601     work internally and because we want to allow non-ASCII source strings in
    602     Django's core and your applications, you **must** use UTF-8 as the encoding
    603     for your PO file. This means that everybody will be using the same
    604     encoding, which is important when Django processes the PO files.
    605 
    606 To reexamine all source code and templates for new translation strings and
    607 update all message files for **all** languages, run this::
    608 
    609     django-admin.py makemessages -a
    610 
    611 Compiling message files
    612 -----------------------
    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, which
    619 are binary files optimized for use by ``gettext``. In the same directory from
    620 which you ran ``django-admin.py makemessages``, run ``django-admin.py
    621 compilemessages`` like this::
    622 
    623    django-admin.py compilemessages
    624 
    625 That's it. Your translations are ready for use.
    626 
    627 .. admonition:: A note to Django veterans
    628 
    629     The old tool ``bin/compile-messages.py`` has been moved to the command
    630     ``django-admin.py compilemessages`` to provide consistency throughout
    631     Django.
    632 
    633 .. admonition:: Working on Windows?
    634 
    635    If you're using Windows and need to install the GNU gettext utilities so
    636    ``django-admin compilemessages`` works see `gettext on Windows`_ for more
    637    information.
    638 
    639 .. _how-django-discovers-language-preference:
    640 
    641 3. How Django discovers language preference
    642 ===========================================
    643 
    644 Once you've prepared your translations -- or, if you just want to use the
    645 translations that come with Django -- you'll just need to activate translation
    646 for your app.
    647 
    648 Behind the scenes, Django has a very flexible model of deciding which language
    649 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 no
    653 other translator finds a translation.
    654 
    655 If all you want to do is run Django with your native language, and a language
    656 file is available for your language, all you need to do is set
    657 ``LANGUAGE_CODE``.
    658 
    659 If you want to let each individual user specify which language he or she
    660 prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language
    661 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, you
    665 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 documentation
    681 <topics-http-middleware>`.)
    682 
    683 ``LocaleMiddleware`` tries to determine the user's language preference by
    684 following this algorithm:
    685 
    686     * First, it looks for a ``django_language`` key in the current user's
    687       session.
    688 
    689     * Failing that, it looks for a cookie.
    690 
    691       .. versionchanged:: 1.0
    692 
    693       In Django version 0.96 and before, the cookie's name is hard-coded to
    694       ``django_language``. In Django 1,0, The cookie name is set by the
    695       ``LANGUAGE_COOKIE_NAME`` setting. (The default name is
    696       ``django_language``.)
    697 
    698     * Failing that, it looks at the ``Accept-Language`` HTTP header. This
    699       header is sent by your browser and tells the server which language(s) you
    700       prefer, in order by priority. Django tries each language in the header
    701       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 the
    710       standard language format, as a string. For example, Brazilian Portuguese
    711       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 uses
    716       ``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 provided
    720       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 automatic
    729       selection to German and English (and any sublanguage, like de-ch or
    730       en-us).
    731 
    732       .. _LANGUAGES setting: ../settings/#languages
    733 
    734     * If you define a custom ``LANGUAGES`` setting, as explained in the
    735       previous bullet, it's OK to mark the languages as translation strings
    736       -- but use a "dummy" ``ugettext()`` function, not the one in
    737       ``django.utils.translation``. You should *never* import
    738       ``django.utils.translation`` from within your settings file, because that
    739       module in itself depends on the settings, and that would cause a circular
    740       import.
    741 
    742       The solution is to use a "dummy" ``ugettext()`` function. Here's a sample
    743       settings file::
    744 
    745           ugettext = lambda s: s
    746 
    747           LANGUAGES = (
    748               ('de', ugettext('German')),
    749               ('en', ugettext('English')),
    750           )
    751 
    752       With this arrangement, ``django-admin.py makemessages`` will still find
    753       and mark these strings for translation, but the translation won't happen
    754       at runtime -- so you'll have to remember to wrap the languages in the
    755       *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime.
    756 
    757     * The ``LocaleMiddleware`` can only select languages for which there is a
    758       Django-provided base translation. If you want to provide translations
    759       for your application that aren't already in the set of translations
    760       in Django's source tree, you'll want to provide at least basic
    761       translations for that language. For example, Django uses technical
    762       message IDs to translate date formats and time formats -- so you will
    763       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 to
    766       translate at least the technical messages -- maybe the validation
    767       messages, too.
    768 
    769       Technical message IDs are easily recognized; they're all upper case. You
    770       don't translate the message ID as with other messages, you provide the
    771       correct local variant on the provided English value. For example, with
    772       ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), this would
    773       be the format string that you want to use in your language. The format
    774       is identical to the format strings used by the ``now`` template tag.
    775 
    776 Once ``LocaleMiddleware`` determines the user's preference, it makes this
    777 preference available as ``request.LANGUAGE_CODE`` for each
    778 :class:`~django.http.HttpRequest`. Feel free to read this value in your view
    779 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 in
    788 ``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's
    789 in ``request.LANGUAGE_CODE``.
    790 
    791 .. _settings file: ../settings/
    792 .. _middleware documentation: ../middleware/
    793 .. _session: ../sessions/
    794 .. _request object: ../request_response/#httprequest-objects
    795 
    796 .. _translations-in-your-own-projects:
    797 
    798 Using translations in your own projects
    799 =======================================
    800 
    801 Django looks for translations by following this algorithm:
    802 
    803     * First, it looks for a ``locale`` directory in the application directory
    804       of the view that's being called. If it finds a translation for the
    805       selected language, the translation will be installed.
    806     * Next, it looks for a ``locale`` directory in the project directory. If it
    807       finds a translation, the translation will be installed.
    808     * Finally, it checks the Django-provided base translation in
    809       ``django/conf/locale``.
    810 
    811 This way, you can write applications that include their own translations, and
    812 you can override base translations in your project path. Or, you can just build
    813 a big project out of several apps and put all translations into one big project
    814 message file. The choice is yours.
    815 
    816 .. note::
    817 
    818     If you're using manually configured settings, as described
    819     :ref:`settings-without-django-settings-module`, the ``locale`` directory in
    820     the project directory will not be examined, since Django loses the ability
    821     to work out the location of the project directory. (Django normally uses the
    822     location of the settings file to determine this, and a settings file doesn't
    823     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 are
    830       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 place
    835 -- in the directory where either the ``conf/locale`` (in case of the source
    836 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 the
    845 ``LocaleMiddleware``. If you don't use the middleware, only the Django message
    846 files and project message files will be processed.
    847 
    848 Finally, you should give some thought to the structure of your translation
    849 files. If your applications need to be delivered to other users and will
    850 be used in other projects, you might want to use app-specific translations.
    851 But using app-specific translations and project translations could produce
    852 weird problems with ``makemessages``: ``makemessages`` will traverse all
    853 directories below the current path and so might put message IDs into the
    854 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 project
    857 (and so carry their own translations) outside the project tree. That way,
    858 ``django-admin.py makemessages`` on the project level will only translate
    859 strings that are connected to your explicit project and not strings that are
    860 distributed independently.
    861 
    862 The ``set_language`` redirect view
    863 ==================================
    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 view
    876 saves the language choice in the user's session. Otherwise, it saves the
    877 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 this
    881 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 the
    885       ``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+django
    892 
    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 JavaScript
    904 ===========================
    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 be
    911       delivered by the server.
    912 
    913     * The translation catalogs for JavaScript should be kept as small as
    914       possible.
    915 
    916 Django provides an integrated solution for these problems: It passes the
    917 translations into JavaScript, so you can call ``gettext``, etc., from within
    918 JavaScript.
    919 
    920 The ``javascript_catalog`` view
    921 -------------------------------
    922 
    923 The main solution to these problems is the ``javascript_catalog`` view, which
    924 sends out a JavaScript code library with functions that mimic the ``gettext``
    925 interface, plus an array of translation strings. Those translation strings are
    926 taken from the application, project or Django core, according to what you
    927 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 (the
    940 same format as the strings in ``INSTALLED_APPS``) and should refer to a package
    941 that contains a ``locale`` directory. If you specify multiple packages, all
    942 those catalogs are merged into one catalog. This is useful if you have
    943 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 from
    953 different apps and this changes often and you don't want to pull in one big
    954 catalog file. As a security measure, these values can only be either
    955 ``django.conf`` or any package from the ``INSTALLED_APPS`` setting.
    956 
    957 Using the JavaScript translation catalog
    958 ----------------------------------------
    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 the
    965 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 object
    984       whose elements values are then sequentially interpolated in their
    985       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 optional
    994       boolean ``named`` parameter as true. ``obj`` contains a JavaScript
    995       object or associative array. For example::
    996 
    997         d = {
    998             count: 10
    999             total: 50
    1000         };
    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 still
    1007 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 those
    1009 cases where you really need it (for example, in conjunction with ``ngettext``
    1010 to produce proper pluralizations).
    1011 
    1012 Creating JavaScript translation catalogs
    1013 ----------------------------------------
    1014 
    1015 You create and update the translation catalogs the same way as the other
    1016 
    1017 Django translation catalogs -- with the django-admin.py makemessages tool. The
    1018 only difference is you need to provide a ``-d djangojs`` parameter, like this::
    1019 
    1020     django-admin.py makemessages -d djangojs -l de
    1021 
    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 translation
    1027 ==================================
    1028 
    1029 If you know ``gettext``, you might note these specialties in the way Django
    1030 does translation:
    1031 
    1032     * The string domain is ``django`` or ``djangojs``. This string domain is
    1033       used to differentiate between different programs that store their data
    1034       in a common message-file library (usually ``/usr/share/locale/``). The
    1035       ``django`` domain is used for python and template translation strings
    1036       and is loaded into the global translation catalogs. The ``djangojs``
    1037       domain is only used for JavaScript translation catalogs to make sure
    1038       that those are as small as possible.
    1039     * Django doesn't use ``xgettext`` alone. It uses Python wrappers around
    1040       ``xgettext`` and ``msgfmt``. This is mostly for convenience.
    1041 
    1042 ``gettext`` on Windows
    1043 ======================
    1044 
    1045 This is only needed for people who either want to extract message IDs or compile
    1046 message files (``.po``). Translation work itself just involves editing existing
    1047 files of this type, but if you want to create your own message files, or want to
    1048 test or compile a changed message file, you will need the ``gettext`` utilities:
    1049 
    1050     * Download the following zip files from the GNOME servers
    1051       http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one
    1052       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 the
    1060       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 the
    1067         ``Variable value`` field
    1068 
    1069 .. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS
    1070 
    1071 You may also use ``gettext`` binaries you have obtained elsewhere, so long as
    1072 the ``xgettext --version`` command works properly. Some version 0.14.4 binaries
    1073 have been found to not support this command. Do not attempt to use Django
    1074 translation utilities with a ``gettext`` package if the command ``xgettext
    1075 --version`` entered at a Windows command prompt causes a popup window saying
    1076 "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=============================================
     4Deployment of Django application translations
     5=============================================
     6
     7If you don't need internationalization in your app
     8==================================================
     9
     10Django's internationalization hooks are on by default, and that means there's a
     11bit of i18n-related overhead in certain places of the framework. If you don't
     12use 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
     15optimizations so as not to load the internationalization machinery.
     16
     17You'll probably also want to remove ``'django.core.context_processors.i18n'``
     18from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting.
     19
     20If you do need internationalization
     21===================================
     22
     23.. _how-django-discovers-language-preference:
     24
     25How Django discovers language preference
     26----------------------------------------
     27
     28Once you've prepared your translations -- or, if you just want to use the
     29translations that come with Django -- you'll just need to activate translation
     30for your app.
     31
     32Behind the scenes, Django has a very flexible model of deciding which language
     33should be used -- installation-wide, for a particular user, or both.
     34
     35To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`.
     36Django uses this language as the default translation -- the final attempt if no
     37other translator finds a translation.
     38
     39If all you want to do is run Django with your native language, and a language
     40file is available for it, all you need to do is set ``LANGUAGE_CODE``.
     41
     42If you want to let each individual user specify which language he or she
     43prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language
     44selection based on data from the request. It customizes content for each user.
     45
     46To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'``
     47to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you
     48should 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
     55For 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
     67following 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
     90Notes:
     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
     147Once ``LocaleMiddleware`` determines the user's preference, it makes this
     148preference available as ``request.LANGUAGE_CODE`` for each
     149:class:`~django.http.HttpRequest`. Feel free to read this value in your view
     150code. 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
     158Note that, with static (middleware-less) translation, the language is in
     159``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's
     160in ``request.LANGUAGE_CODE``.
     161
     162.. _settings file: ../settings/
     163.. _middleware documentation: ../middleware/
     164.. _session: ../sessions/
     165.. _request object: ../request_response/#httprequest-objects
     166
     167How Django discovers translations
     168---------------------------------
     169
     170As described in :ref:`using-translations-in-your-own-projects`,
     171at 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=====================================
     4Internationalization and localization
     5=====================================
     6
     7Overview
     8========
     9
     10Django has full support for internationalization of text in code and templates.
     11
     12Essentially, 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
     19The complete process can be seen as divided in three stages. It is also possible
     20to identify an identical number of roles with very well defined responsabilities
     21associated with each of these tasks (although it's perfectly normal if you
     22find 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
     39For more general information about the topic, see the `GNU gettext documentation`_
     40and 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
     47Specialties of Django translation
     48==================================
     49
     50Django's translation machinery uses the standard ``gettext`` module that comes
     51with Python. If you know ``gettext``, you might note these specialties in the
     52way 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
     66Django technical message IDs
     67----------------------------
     68
     69Django uses **technical message IDs** to translate date formats and time
     70formats. Technical message IDs are message strings and can be easily recognized;
     71they're all upper case. You don't translate the message ID as with other message
     72strings, you provide the correct local variant on the provided English value.
     73The format is identical to the format strings used by the ``now`` template tag.
     74
     75For example, with ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``),
     76this would be the format string that you want to use in your language. A Django
     77contributor 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====================
     4Internationalization
     5====================
     6
     7Overview
     8========
     9
     10The goal of internationalization is to allow a single Web application to offer
     11its content and functionality in multiple languages.
     12
     13You, the Django developer, can accomplish this goal by adding a minimal amount
     14of hooks to your Python (and JavaScript) code and templates. These hooks are
     15called **translation strings**. They tell Django: "This text should be
     16translated into the end user's language, if a translation for this text is
     17available in that language." . It's your responsibility to mark translatable
     18strings; the system can only translate strings it knows about.
     19
     20Django takes care of using these hooks to translate Web apps, on the fly,
     21according to users' language preferences.
     22
     23Specifying translation strings: In Python code
     24==============================================
     25
     26Standard translation
     27--------------------
     28
     29Specify a translation string by using the function ``ugettext()``. It's
     30convention 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
     50In this example, the text ``"Welcome to my site."`` is marked as a translation
     51string::
     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
     59Obviously, you could code this without using the alias. This example is
     60identical 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
     68Translation works on computed values. This example is identical to the previous
     69two::
     70
     71    def my_view(request):
     72        words = ['Welcome', 'to', 'my', 'site.']
     73        output = _(' '.join(words))
     74        return HttpResponse(output)
     75
     76Translation 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
     84examples, 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
     88The strings you pass to ``_()`` or ``ugettext()`` can take placeholders,
     89specified 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
     95This technique lets language-specific translations reorder the placeholder
     96text. For example, an English translation may be ``"Today is November, 26."``,
     97while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the
     98placeholders (the month and the day) with their positions swapped.
     99
     100For this reason, you should use named-string interpolation (e.g., ``%(day)s``)
     101instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you
     102have more than a single parameter. If you used positional interpolation,
     103translations wouldn't be able to reorder placeholder text.
     104
     105Marking strings as no-op
     106------------------------
     107
     108Use the function ``django.utils.translation.ugettext_noop()`` to mark a string
     109as a translation string without translating it. The string is later translated
     110from a variable.
     111
     112Use this if you have constant strings that should be stored in the source
     113language because they are exchanged over systems or users -- such as strings in
     114a database -- but should be translated at the last possible point in time, such
     115as when the string is presented to the user.
     116
     117Pluralization
     118-------------
     119
     120Use the function ``django.utils.translation.ungettext()`` to specify pluralized
     121messages.
     122
     123``ungettext`` takes three arguments: the singular translation string, the plural
     124translation string and the number of objects.
     125
     126This function is useful when your need your Django application to be localizable
     127to languages where the number and complexity of `plural forms
     128<http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is
     129greater 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
     131of its value.)
     132
     133For 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
     142In this example the number of objects is passed to the translation languages as
     143the ``count`` variable.
     144
     145Lets 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
     164Here we reuse localizable, hopefully already translated literals (contained in
     165the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for
     166other parts of the sentence so all of it is consistently based on the
     167cardinality 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
     200Lazy translation
     201----------------
     202
     203Use the function ``django.utils.translation.ugettext_lazy()`` to translate
     204strings lazily -- when the value is accessed rather than when the
     205``ugettext_lazy()`` function is called.
     206
     207For 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
     214In this example, ``ugettext_lazy()`` stores a lazy reference to the string --
     215not the actual translation. The translation itself will be done when the string
     216is used in a string context, such as template rendering on the Django admin
     217site.
     218
     219The result of a ``ugettext_lazy()`` call can be used wherever you would use a
     220unicode string (an object with type ``unicode``) in Python. If you try to use
     221it where a bytestring (a ``str`` object) is expected, things will not work as
     222expected, since a ``ugettext_lazy()`` object doesn't know how to convert
     223itself to a bytestring.  You can't use a unicode string inside a bytestring,
     224either, 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
     233If 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
     237If 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
     245Always use lazy translations in :ref:`Django models <topics-db-models>`.
     246Field names and table names should be marked for translation (otherwise, they
     247won't be translated in the admin interface). This means writing explicit
     248``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class,
     249though, rather than relying on Django's default determination of
     250``verbose_name`` and ``verbose_name_plural`` by looking at the model's class
     251name::
     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
     261Working with lazy translation objects
     262-------------------------------------
     263
     264.. highlightlang:: python
     265
     266Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models
     267and utility functions is a common operation. When you're working with these
     268objects elsewhere in your code, you should ensure that you don't accidentally
     269convert 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
     271couple of helper functions.
     272
     273Joining strings: string_concat()
     274~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     275
     276Standard Python string joins (``''.join([...])``) will not work on lists
     277containing lazy translation objects. Instead, you can use
     278``django.utils.translation.string_concat()``, which creates a lazy object that
     279concatenates its contents *and* converts them to strings only when the result
     280is 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
     288In this case, the lazy translations in ``result`` will only be converted to
     289strings when ``result`` itself is used in a string (usually at template
     290rendering time).
     291
     292The allow_lazy() decorator
     293~~~~~~~~~~~~~~~~~~~~~~~~~~
     294
     295Django offers many utility functions (particularly in ``django.utils``) that
     296take a string as their first argument and do something to that string. These
     297functions are used by template filters as well as directly in other code.
     298
     299If you write your own similar functions and deal with translations, you'll
     300face the problem of what to do when the first argument is a lazy translation
     301object. You don't want to convert it to a string immediately, because you might
     302be using this function outside of a view (and hence the current thread's locale
     303setting will not be correct).
     304
     305For cases like this, use the ``django.utils.functional.allow_lazy()``
     306decorator. It modifies the function so that *if* it's called with a lazy
     307translation as the first argument, the function evaluation is delayed until it
     308needs to be converted to a string.
     309
     310For 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
     319The ``allow_lazy()`` decorator takes, in addition to the function to decorate,
     320a number of extra arguments (``*args``) specifying the type(s) that the
     321original function can return. Usually, it's enough to include ``unicode`` here
     322and ensure that your function returns only Unicode strings.
     323
     324Using this decorator means you can write your function and assume that the
     325input is a proper string, then add support for lazy translation objects at the
     326end.
     327
     328Specifying translation strings: In template code
     329================================================
     330
     331.. highlightlang:: html+django
     332
     333Translations in :ref:`Django templates <topics-templates>` uses two template
     334tags and a slightly different syntax than in Python code. To give your template
     335access to these tags, put ``{% load i18n %}`` toward the top of your template.
     336
     337The ``{% 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
     343If the ``noop`` option is present, variable lookup still takes place but the
     344translation is skipped. This is useful when "stubbing out" content that will
     345require translation in the future::
     346
     347    <title>{% trans "myvar" noop %}</title>
     348
     349Internally, inline translations use an ``ugettext`` call.
     350
     351It'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
     357To translate a template expression -- say, using template filters -- you need
     358to bind the expression to a local variable for use within the translation
     359block::
     360
     361    {% blocktrans with value|filter as myvar %}
     362    This will have {{ myvar }} inside.
     363    {% endblocktrans %}
     364
     365If you need to bind more than one expression inside a ``blocktrans`` tag,
     366separate 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
     372To 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
     382When you use the pluralization feature and bind additional values to local
     383variables apart from the counter value that selects the translated literal to be
     384used, have in mind that the ``blocktrans`` construct is internally converted
     385to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext
     386variables <pluralization-var-notes>` apply.
     387
     388Each ``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
     403If you don't use the ``RequestContext`` extension, you can get those values with
     404three tags::
     405
     406    {% get_current_language as LANGUAGE_CODE %}
     407    {% get_available_languages as LANGUAGES %}
     408    {% get_current_language_bidi as LANGUAGE_BIDI %}
     409
     410These tags also require a ``{% load i18n %}``.
     411
     412Translation hooks are also available within any template block tag that accepts
     413constant strings. In those cases, just use ``_()`` syntax to specify a
     414translation string::
     415
     416    {% some_special_tag _("Page not found") value|yesno:_("yes,no") %}
     417
     418In this case, both the tag and the filter will see the already-translated
     419string, 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
     431Specifying translation strings: In JavaScript code
     432==================================================
     433
     434Adding 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
     444Django provides an integrated solution for these problems: It passes the
     445translations into JavaScript, so you can call ``gettext``, etc., from within
     446JavaScript.
     447
     448The ``javascript_catalog`` view
     449-------------------------------
     450
     451The main solution to these problems is the ``javascript_catalog`` view, which
     452sends out a JavaScript code library with functions that mimic the ``gettext``
     453interface, plus an array of translation strings. Those translation strings are
     454taken from the application, project or Django core, according to what you
     455specify in either the info_dict or the URL.
     456
     457You 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
     467Each string in ``packages`` should be in Python dotted-package syntax (the
     468same format as the strings in ``INSTALLED_APPS``) and should refer to a package
     469that contains a ``locale`` directory. If you specify multiple packages, all
     470those catalogs are merged into one catalog. This is useful if you have
     471JavaScript that uses strings from different applications.
     472
     473You 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
     479With this, you specify the packages as a list of package names delimited by '+'
     480signs in the URL. This is especially useful if your pages use code from
     481different apps and this changes often and you don't want to pull in one big
     482catalog file. As a security measure, these values can only be either
     483``django.conf`` or any package from the ``INSTALLED_APPS`` setting.
     484
     485Using the JavaScript translation catalog
     486----------------------------------------
     487
     488To use the catalog, just pull in the dynamically generated script like this::
     489
     490    <script type="text/javascript" src="/path/to/jsi18n/"></script>
     491
     492This is how the admin fetches the translation catalog from the server. When the
     493catalog is loaded, your JavaScript code can use the standard ``gettext``
     494interface to access it::
     495
     496    document.write(gettext('this is to be translated'));
     497
     498There 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
     504and even a string interpolation function::
     505
     506    function interpolate(fmt, obj, named);
     507
     508The interpolation syntax is borrowed from Python, so the ``interpolate``
     509function 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
     534You shouldn't go over the top with string interpolation, though: this is still
     535JavaScript, so the code has to make repeated regular-expression substitutions.
     536This isn't as fast as string interpolation in Python, so keep it to those
     537cases where you really need it (for example, in conjunction with ``ngettext``
     538to produce proper pluralizations).
     539
     540The ``set_language`` redirect view
     541==================================
     542
     543As a convenience, Django comes with a view, ``django.views.i18n.set_language``,
     544that sets a user's language preference and redirects back to the previous page.
     545
     546Activate 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
     552The view expects to be called via the ``POST`` method, with a ``language``
     553parameter set in request. If session support is enabled, the view
     554saves the language choice in the user's session. Otherwise, it saves the
     555language choice in a cookie that is by default named ``django_language``.
     556(The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.)
     557
     558After setting the language choice, Django redirects the user, following this
     559algorithm:
     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
     567Here'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============
     4Localization
     5============
     6
     7.. _how-to-create-language-files:
     8
     9How to create language files
     10============================
     11
     12Once the string literals of an application have been tagged for later
     13translation, the translation themselves need to be written (or obtained). Here's
     14how 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
     32Message files
     33-------------
     34
     35The first step is to create a **message file** for a new language. A message
     36file is a plain-text file, representing a single language, that contains all
     37available translation strings and how they should be represented in the given
     38language. Message files have a ``.po`` file extension.
     39
     40Django comes with a tool, ``django-admin.py makemessages``, that automates the
     41creation 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
     48To 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.
     53The 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
     56The 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
     61Th script runs over your project source tree or your application source tree and
     62pulls out all strings marked for translation. It creates (or updates) a message
     63file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de`` example, the
     64file will be ``locale/de/LC_MESSAGES/django.po``.
     65
     66By 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
     72Separate multiple extensions with commas and/or use ``-e`` or ``--extension``
     73multiple times::
     74
     75    django-admin.py makemessages -l=de -e=html,txt -e xml
     76
     77When :ref:`creating message files from JavaScript source code
     78<creating-message-files-from-js-code>` you need to use the special 'djangojs'
     79domain, **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
     95The format of ``.po`` files is straightforward. Each ``.po`` file contains a
     96small bit of metadata, such as the translation maintainer's contact
     97information, but the bulk of the file is a list of **messages** -- simple
     98mappings between translation strings and the actual translated text for the
     99particular language.
     100
     101For 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
     107containing the following snippet -- a message::
     108
     109    #: path/to/python/module.py:23
     110    msgid "Welcome to my site."
     111    msgstr ""
     112
     113A 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
     124Long 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
     126written over the next few lines as one string per line. Those strings are
     127directly concatenated. Don't forget trailing spaces within the strings;
     128otherwise, 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
     140To reexamine all source code and templates for new translation strings and
     141update all message files for **all** languages, run this::
     142
     143    django-admin.py makemessages -a
     144
     145Compiling message files
     146-----------------------
     147
     148After you create your message file -- and each time you make changes to it --
     149you'll need to compile it into a more efficient form, for use by ``gettext``.
     150Do this with the ``django-admin.py compilemessages`` utility.
     151
     152This tool runs over all available ``.po`` files and creates ``.mo`` files, which
     153are binary files optimized for use by ``gettext``. In the same directory from
     154which you ran ``django-admin.py makemessages``, run ``django-admin.py
     155compilemessages`` like this::
     156
     157   django-admin.py compilemessages
     158
     159That'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
     175Creating message files from JavaScript source code
     176==================================================
     177
     178You create and update the message files the same way as the other Django message
     179files -- with the ``django-admin.py makemessages`` tool. The only difference is
     180you need to provide a ``-d djangojs`` parameter, like this::
     181
     182    django-admin.py makemessages -d djangojs -l de
     183
     184This would create or update the message file for JavaScript for German.
     185After updating message files, just run ``django-admin.py compilemessages``
     186the same way as you do with normal Django message files.
     187
     188.. _gettext_on_windows:
     189
     190``gettext`` on Windows
     191======================
     192
     193This is only needed for people who either want to extract message IDs or compile
     194message files (``.po``). Translation work itself just involves editing existing
     195files of this type, but if you want to create your own message files, or want to
     196test 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
     219You may also use ``gettext`` binaries you have obtained elsewhere, so long as
     220the ``xgettext --version`` command works properly. Some version 0.14.4 binaries
     221have been found to not support this command. Do not attempt to use Django
     222translation 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  
    2121   cache
    2222   conditional-view-processing
    2323   email
    24    i18n
     24   i18n/index
    2525   pagination
    2626   serialization
    2727   settings
Back to Top