Ticket #10260: 10260-i18n-docs-rf-r12229.diff

File 10260-i18n-docs-rf-r12229.diff, 104.7 KB (added by Ramiro Morales, 15 years ago)

Patch for trunk updated to r12229 (solve merge conflict with r12213).

  • django/conf/global_settings.py

    diff -r 257fac48943d django/conf/global_settings.py
    a b  
    298298# http://docs.djangoproject.com/en/dev/ref/templates/builtins/#now
    299299MONTH_DAY_FORMAT = 'F j'
    300300
    301 # Default shortformatting for date objects. See all available format strings here:
     301# Default short formatting for date objects. See all available format strings here:
    302302# http://docs.djangoproject.com/en/dev/ref/templates/builtins/#now
    303303SHORT_DATE_FORMAT = 'm/d/Y'
    304304
  • new file docs/howto/i18n.txt

    diff -r 257fac48943d docs/howto/i18n.txt
    - +  
     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
     19In all cases the name of the directory containing the translation is expected to
     20be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
     21etc.
     22
     23This way, you can write applications that include their own translations, and
     24you can override base translations in your project path. Or, you can just build
     25a big project out of several apps and put all translations into one big project
     26message file. The choice is yours.
     27
     28.. note::
     29
     30    If you're using manually configured settings, as described in
     31    :ref:`settings-without-django-settings-module`, the ``locale`` directory in
     32    the project directory will not be examined, since Django loses the ability
     33    to work out the location of the project directory. (Django normally uses the
     34    location of the settings file to determine this, and a settings file doesn't
     35    exist if you're manually configuring your settings.)
     36
     37All message file repositories are structured the same way. They are:
     38
     39    * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
     40    * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
     41    * All paths listed in ``LOCALE_PATHS`` in your settings file are
     42      searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)``
     43    * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``
     44
     45To create message files, you use the :djadmin:`django-admin.py makemessages <makemessages>`
     46tool. You only need to be in the same directory where the ``locale/`` directory
     47is located. And you use :djadmin:`django-admin.py compilemessages <compilemessages>`
     48to produce the binary ``.mo`` files that are used by ``gettext``. Read the
     49:ref:`topics-i18n-localization` document for more details.
     50
     51You can also run ``django-admin.py compilemessages --settings=path.to.settings``
     52to make the compiler process all the directories in your :setting:`LOCALE_PATHS`
     53setting.
     54
     55Application message files are a bit complicated to discover -- they need the
     56:class:`~django.middleware.locale.LocaleMiddleware`. If you don't use the
     57middleware, only the Django message files and project message files will be
     58installed and available at runtime.
     59
     60Finally, you should give some thought to the structure of your translation
     61files. If your applications need to be delivered to other users and will
     62be used in other projects, you might want to use app-specific translations.
     63But using app-specific translations and project translations could produce
     64weird problems with ``makemessages``: It will traverse all directories below
     65the current path and so might put message IDs into the project message file
     66that are already in application message files.
     67
     68The easiest way out is to store applications that are not part of the project
     69(and so carry their own translations) outside the project tree. That way,
     70``django-admin.py makemessages`` on the project level will only translate
     71strings that are connected to your explicit project and not strings that are
     72distributed independently.
  • docs/howto/index.txt

    diff -r 257fac48943d 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 -r 257fac48943d 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.
     
    419422      ``-d djangojs`` command line option to the ``django-admin.py``
    420423      invocations).
    421424
    422     * Create a diff of the ``.po`` file(s) against the current Subversion trunk.
     425    * Optionally, review and update the ``conf/locale/<locale>/formats.py``
     426      file to describe the date, time and numbers formatting particularities of
     427      your locale. See :ref:`format-localization` for details.
     428
     429    * Create a diff against the current Subversion trunk.
    423430
    424431    * Open a ticket in Django's ticket system, set its ``Component`` field to
    425432      ``Translations``, and attach the patch to it.
  • docs/ref/settings.txt

    diff -r 257fac48943d docs/ref/settings.txt
    a b  
    852852Default: ``'en-us'``
    853853
    854854A string representing the language code for this installation. This should be in
    855 standard language format. For example, U.S. English is ``"en-us"``. See
    856 :ref:`topics-i18n`.
     855standard :term:`language format<language code>`. For example, U.S. English is
     856``"en-us"``. See :ref:`topics-i18n`.
    857857
    858858.. setting:: LANGUAGE_COOKIE_NAME
    859859
     
    880880
    881881.. _online source: http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py
    882882
    883 The list is a tuple of two-tuples in the format (language code, language
    884 name) -- for example, ``('ja', 'Japanese')``. This specifies which languages
    885 are available for language selection. See :ref:`topics-i18n`.
     883The list is a tuple of two-tuples in the format ``(language code, language
     884name)``, the ``language code`` part should be a
     885:term:`language name<language code>` -- for example, ``('ja', 'Japanese')``.
     886This specifies which languages are available for language selection. See
     887:ref:`topics-i18n`.
    886888
    887889Generally, the default value should suffice. Only set this setting if you want
    888890to restrict language selection to a subset of the Django-provided languages.
     
    917919Default: ``()`` (Empty tuple)
    918920
    919921A tuple of directories where Django looks for translation files.
    920 See :ref:`translations-in-your-own-projects`.
     922See :ref:`using-translations-in-your-own-projects`.
    921923
    922924.. setting:: LOGIN_REDIRECT_URL
    923925
  • docs/releases/1.2.txt

    diff -r 257fac48943d docs/releases/1.2.txt
    a b  
    367367django.form.fields to django.core.validators. You will need to update
    368368your imports if you are using it.
    369369
     370Technical message IDs
     371---------------------
     372
     373Up to version 1.1 Django used :ref:`technical message IDs<technical-messages>`
     374to provide localizers the possibility to translate date and time formats.  They
     375were translatable :term:`translation string`\s that could be recognized because
     376they were all upper case (for example ``DATETIME_FORMAT``, ``DATE_FORMAT``,
     377``TIME_FORMAT``). They have been deprecated in favor of the new :ref:`Format
     378localization <format-localization>` infrastructure that allows localizers to
     379specify that information in a ``formats.py`` file in the corresponding
     380``django/conf/locale/<locale name>/`` directory.
     381
    370382What's new in Django 1.2
    371383========================
    372384
     
    431443     ...
    432444    {% endifnotequal %}
    433445
    434 You can now do this::
     446You can now do this:
    435447
    436448.. code-block:: html+django
    437449
  • deleted file docs/topics/i18n.txt

    diff -r 257fac48943d docs/topics/i18n.txt
    + -  
    1 .. _topics-i18n:
    2 
    3 ====================
    4 Internationalization
    5 ====================
    6 
    7 Django has full support for internationalization of text in code and
    8 templates, and format localization of dates and numbers. 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 and locales.
    15 
    16 For text translation, you, the Django developer, can accomplish this goal by
    17 adding a minimal amount of hooks to your Python code and templates. These hooks
    18 are called **translation strings**. They tell Django: "This text should be
    19 translated into the end user's language, if a translation for this text is
    20 available in that 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 For format localization, it's just necessary to set
    33 :setting:`USE_L10N = True <USE_L10N>` in your settings file. If
    34 :setting:`USE_L10N` is set to ``True``, Django will display
    35 numbers and dates in the format of the current locale. That includes field
    36 representation on templates, and allowed input formats on the admin.
    37 
    38 If you don't need internationalization in your app
    39 ==================================================
    40 
    41 Django's internationalization hooks are on by default, and that means there's a
    42 bit of i18n-related overhead in certain places of the framework. If you don't
    43 use internationalization, you should take the two seconds to set
    44 :setting:`USE_I18N = False <USE_I18N>` in your settings file. If
    45 :setting:`USE_I18N` is set to ``False``, then Django will make some
    46 optimizations so as not to load the internationalization machinery.
    47 
    48 You'll probably also want to remove ``'django.core.context_processors.i18n'``
    49 from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting.
    50 
    51 If you do need internationalization: three steps
    52 ================================================
    53 
    54     1. Embed translation strings in your Python code and templates.
    55     2. Get translations for those strings, in whichever languages you want to
    56        support.
    57     3. Activate the locale middleware in your Django settings.
    58 
    59 .. admonition:: Behind the scenes
    60 
    61     Django's translation machinery uses the standard ``gettext`` module that
    62     comes with Python.
    63 
    64 1. How to specify translation strings
    65 =====================================
    66 
    67 Translation strings specify "This text should be translated." These strings can
    68 appear in your Python code and templates. It's your responsibility to mark
    69 translatable strings; the system can only translate strings it knows about.
    70 
    71 In Python code
    72 --------------
    73 
    74 Standard translation
    75 ~~~~~~~~~~~~~~~~~~~~
    76 
    77 Specify a translation string by using the function ``ugettext()``. It's
    78 convention to import this as a shorter alias, ``_``, to save typing.
    79 
    80 .. note::
    81     Python's standard library ``gettext`` module installs ``_()`` into the
    82     global namespace, as an alias for ``gettext()``. In Django, we have chosen
    83     not to follow this practice, for a couple of reasons:
    84 
    85       1. For international character set (Unicode) support, ``ugettext()`` is
    86          more useful than ``gettext()``. Sometimes, you should be using
    87          ``ugettext_lazy()`` as the default translation method for a particular
    88          file. Without ``_()`` in the global namespace, the developer has to
    89          think about which is the most appropriate translation function.
    90 
    91       2. The underscore character (``_``) is used to represent "the previous
    92          result" in Python's interactive shell and doctest tests. Installing a
    93          global ``_()`` function causes interference. Explicitly importing
    94          ``ugettext()`` as ``_()`` avoids this problem.
    95 
    96 .. highlightlang:: python
    97 
    98 In this example, the text ``"Welcome to my site."`` is marked as a translation
    99 string::
    100 
    101     from django.utils.translation import ugettext as _
    102 
    103     def my_view(request):
    104         output = _("Welcome to my site.")
    105         return HttpResponse(output)
    106 
    107 Obviously, you could code this without using the alias. This example is
    108 identical to the previous one::
    109 
    110     from django.utils.translation import ugettext
    111 
    112     def my_view(request):
    113         output = ugettext("Welcome to my site.")
    114         return HttpResponse(output)
    115 
    116 Translation works on computed values. This example is identical to the previous
    117 two::
    118 
    119     def my_view(request):
    120         words = ['Welcome', 'to', 'my', 'site.']
    121         output = _(' '.join(words))
    122         return HttpResponse(output)
    123 
    124 Translation works on variables. Again, here's an identical example::
    125 
    126     def my_view(request):
    127         sentence = 'Welcome to my site.'
    128         output = _(sentence)
    129         return HttpResponse(output)
    130 
    131 (The caveat with using variables or computed values, as in the previous two
    132 examples, is that Django's translation-string-detecting utility,
    133 ``django-admin.py makemessages``, won't be able to find these strings. More on
    134 ``makemessages`` later.)
    135 
    136 The strings you pass to ``_()`` or ``ugettext()`` can take placeholders,
    137 specified with Python's standard named-string interpolation syntax. Example::
    138 
    139     def my_view(request, m, d):
    140         output = _('Today is %(month)s, %(day)s.') % {'month': m, 'day': d}
    141         return HttpResponse(output)
    142 
    143 This technique lets language-specific translations reorder the placeholder
    144 text. For example, an English translation may be ``"Today is November, 26."``,
    145 while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the
    146 placeholders (the month and the day) with their positions swapped.
    147 
    148 For this reason, you should use named-string interpolation (e.g., ``%(day)s``)
    149 instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you
    150 have more than a single parameter. If you used positional interpolation,
    151 translations wouldn't be able to reorder placeholder text.
    152 
    153 Marking strings as no-op
    154 ~~~~~~~~~~~~~~~~~~~~~~~~
    155 
    156 Use the function ``django.utils.translation.ugettext_noop()`` to mark a string
    157 as a translation string without translating it. The string is later translated
    158 from a variable.
    159 
    160 Use this if you have constant strings that should be stored in the source
    161 language because they are exchanged over systems or users -- such as strings in
    162 a database -- but should be translated at the last possible point in time, such
    163 as when the string is presented to the user.
    164 
    165 .. _lazy-translations:
    166 
    167 Lazy translation
    168 ~~~~~~~~~~~~~~~~
    169 
    170 Use the function ``django.utils.translation.ugettext_lazy()`` to translate
    171 strings lazily -- when the value is accessed rather than when the
    172 ``ugettext_lazy()`` function is called.
    173 
    174 For example, to translate a model's ``help_text``, do the following::
    175 
    176     from django.utils.translation import ugettext_lazy
    177 
    178     class MyThing(models.Model):
    179         name = models.CharField(help_text=ugettext_lazy('This is the help text'))
    180 
    181 In this example, ``ugettext_lazy()`` stores a lazy reference to the string --
    182 not the actual translation. The translation itself will be done when the string
    183 is used in a string context, such as template rendering on the Django admin
    184 site.
    185 
    186 The result of a ``ugettext_lazy()`` call can be used wherever you would use a
    187 unicode string (an object with type ``unicode``) in Python. If you try to use
    188 it where a bytestring (a ``str`` object) is expected, things will not work as
    189 expected, since a ``ugettext_lazy()`` object doesn't know how to convert
    190 itself to a bytestring.  You can't use a unicode string inside a bytestring,
    191 either, so this is consistent with normal Python behavior. For example::
    192 
    193     # This is fine: putting a unicode proxy into a unicode string.
    194     u"Hello %s" % ugettext_lazy("people")
    195 
    196     # This will not work, since you cannot insert a unicode object
    197     # into a bytestring (nor can you insert our unicode proxy there)
    198     "Hello %s" % ugettext_lazy("people")
    199 
    200 If you ever see output that looks like ``"hello
    201 <django.utils.functional...>"``, you have tried to insert the result of
    202 ``ugettext_lazy()`` into a bytestring. That's a bug in your code.
    203 
    204 If you don't like the verbose name ``ugettext_lazy``, you can just alias it as
    205 ``_`` (underscore), like so::
    206 
    207     from django.utils.translation import ugettext_lazy as _
    208 
    209     class MyThing(models.Model):
    210         name = models.CharField(help_text=_('This is the help text'))
    211 
    212 Always use lazy translations in :ref:`Django models <topics-db-models>`.
    213 Field names and table names should be marked for translation (otherwise, they
    214 won't be translated in the admin interface). This means writing explicit
    215 ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class,
    216 though, rather than relying on Django's default determination of
    217 ``verbose_name`` and ``verbose_name_plural`` by looking at the model's class
    218 name::
    219 
    220     from django.utils.translation import ugettext_lazy as _
    221 
    222     class MyThing(models.Model):
    223         name = models.CharField(_('name'), help_text=_('This is the help text'))
    224         class Meta:
    225             verbose_name = _('my thing')
    226             verbose_name_plural = _('mythings')
    227 
    228 Pluralization
    229 ~~~~~~~~~~~~~
    230 
    231 Use the function ``django.utils.translation.ungettext()`` to specify pluralized
    232 messages.
    233 
    234 ``ungettext`` takes three arguments: the singular translation string, the
    235 plural translation string and the number of objects.
    236 
    237 This function is useful when you need your Django application to be localizable
    238 to languages where the number and complexity of `plural forms
    239 <http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is
    240 greater than the two forms used in English ('object' for the singular and
    241 'objects' for all the cases where ``count`` is different from zero,
    242 irrespective of its value).
    243 
    244 For example::
    245 
    246     from django.utils.translation import ungettext
    247     def hello_world(request, count):
    248         page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % {
    249             'count': count,
    250         }
    251         return HttpResponse(page)
    252 
    253 In this example the number of objects is passed to the translation languages as
    254 the ``count`` variable.
    255 
    256 Lets see a slightly more complex usage example::
    257 
    258     from django.utils.translation import ungettext
    259 
    260     count = Report.objects.count()
    261     if count == 1:
    262         name = Report._meta.verbose_name
    263     else:
    264         name = Report._meta.verbose_name_plural
    265 
    266     text = ungettext(
    267             'There is %(count)d %(name)s available.',
    268             'There are %(count)d %(name)s available.',
    269             count
    270     ) % {
    271         'count': count,
    272         'name': name
    273     }
    274 
    275 Here we reuse localizable, hopefully already translated literals (contained in
    276 the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for
    277 other parts of the sentence so all of it is consistently based on the
    278 cardinality of the elements at play.
    279 
    280 .. _pluralization-var-notes:
    281 
    282 .. note::
    283 
    284     When using this technique, make sure you use a single name for every
    285     extrapolated variable included in the literal. In the example above note
    286     how we used the ``name`` Python variable in both translation strings. This
    287     example would fail::
    288 
    289         from django.utils.translation import ungettext
    290         from myapp.models import Report
    291 
    292         count = Report.objects.count()
    293         d = {
    294             'count': count,
    295             'name': Report._meta.verbose_name
    296             'plural_name': Report._meta.verbose_name_plural
    297         }
    298         text = ungettext(
    299                 'There is %(count)d %(name)s available.',
    300                 'There are %(count)d %(plural_name)s available.',
    301                 count
    302         ) % d
    303 
    304     You would get a ``a format specification for argument 'name', as in
    305     'msgstr[0]', doesn't exist in 'msgid'`` error when running
    306     ``django-admin.py compilemessages`` or a ``KeyError`` Python exception at
    307     runtime.
    308 
    309 In template code
    310 ----------------
    311 
    312 .. highlightlang:: html+django
    313 
    314 Translations in :ref:`Django templates <topics-templates>` uses two template
    315 tags and a slightly different syntax than in Python code. To give your template
    316 access to these tags, put ``{% load i18n %}`` toward the top of your template.
    317 
    318 The ``{% trans %}`` template tag translates either a constant string
    319 (enclosed in single or double quotes) or variable content::
    320 
    321     <title>{% trans "This is the title." %}</title>
    322     <title>{% trans myvar %}</title>
    323 
    324 If the ``noop`` option is present, variable lookup still takes place, but the
    325 original text will be returned unchanged. This is useful when "stubbing out"
    326 content that will require translation in the future::
    327 
    328     <title>{% trans "myvar" noop %}</title>
    329 
    330 Internally, inline translations use an ``ugettext`` call.
    331 
    332 It's not possible to mix a template variable inside a string within ``{% trans
    333 %}``. If your translations require strings with variables (placeholders), use
    334 ``{% blocktrans %}``::
    335 
    336     {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
    337 
    338 To translate a template expression -- say, using template filters -- you need
    339 to bind the expression to a local variable for use within the translation
    340 block::
    341 
    342     {% blocktrans with value|filter as myvar %}
    343     This will have {{ myvar }} inside.
    344     {% endblocktrans %}
    345 
    346 If you need to bind more than one expression inside a ``blocktrans`` tag,
    347 separate the pieces with ``and``::
    348 
    349     {% blocktrans with book|title as book_t and author|title as author_t %}
    350     This is {{ book_t }} by {{ author_t }}
    351     {% endblocktrans %}
    352 
    353 To pluralize, specify both the singular and plural forms with the
    354 ``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and
    355 ``{% endblocktrans %}``. Example::
    356 
    357     {% blocktrans count list|length as counter %}
    358     There is only one {{ name }} object.
    359     {% plural %}
    360     There are {{ counter }} {{ name }} objects.
    361     {% endblocktrans %}
    362 
    363 When you use the pluralization feature and bind additional values to local
    364 variables apart from the counter value that selects the translated literal to
    365 be used, have in mind that the ``blocktrans`` construct is internally converted
    366 to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext
    367 variables <pluralization-var-notes>` apply.
    368 
    369 Each ``RequestContext`` has access to three translation-specific variables:
    370 
    371     * ``LANGUAGES`` is a list of tuples in which the first element is the
    372       language code and the second is the language name (translated into the
    373       currently active locale).
    374 
    375     * ``LANGUAGE_CODE`` is the current user's preferred language, as a string.
    376       Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`,
    377       below.)
    378 
    379     * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a
    380       right-to-left language, e.g.: Hebrew, Arabic. If False it's a
    381       left-to-right language, e.g.: English, French, German etc.
    382 
    383 
    384 If you don't use the ``RequestContext`` extension, you can get those values
    385 with three tags::
    386 
    387     {% get_current_language as LANGUAGE_CODE %}
    388     {% get_available_languages as LANGUAGES %}
    389     {% get_current_language_bidi as LANGUAGE_BIDI %}
    390 
    391 These tags also require a ``{% load i18n %}``.
    392 
    393 Translation hooks are also available within any template block tag that accepts
    394 constant strings. In those cases, just use ``_()`` syntax to specify a
    395 translation string::
    396 
    397     {% some_special_tag _("Page not found") value|yesno:_("yes,no") %}
    398 
    399 In this case, both the tag and the filter will see the already-translated
    400 string, so they don't need to be aware of translations.
    401 
    402 .. note::
    403     In this example, the translation infrastructure will be passed the string
    404     ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The
    405     translated string will need to contain the comma so that the filter
    406     parsing code knows how to split up the arguments. For example, a German
    407     translator might translate the string ``"yes,no"`` as ``"ja,nein"``
    408     (keeping the comma intact).
    409 
    410 .. _Django templates: ../templates_python/
    411 
    412 Working with lazy translation objects
    413 -------------------------------------
    414 
    415 .. highlightlang:: python
    416 
    417 Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models
    418 and utility functions is a common operation. When you're working with these
    419 objects elsewhere in your code, you should ensure that you don't accidentally
    420 convert them to strings, because they should be converted as late as possible
    421 (so that the correct locale is in effect). This necessitates the use of a
    422 couple of helper functions.
    423 
    424 Joining strings: string_concat()
    425 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    426 
    427 Standard Python string joins (``''.join([...])``) will not work on lists
    428 containing lazy translation objects. Instead, you can use
    429 ``django.utils.translation.string_concat()``, which creates a lazy object that
    430 concatenates its contents *and* converts them to strings only when the result
    431 is included in a string. For example::
    432 
    433     from django.utils.translation import string_concat
    434     ...
    435     name = ugettext_lazy(u'John Lennon')
    436     instrument = ugettext_lazy(u'guitar')
    437     result = string_concat([name, ': ', instrument])
    438 
    439 In this case, the lazy translations in ``result`` will only be converted to
    440 strings when ``result`` itself is used in a string (usually at template
    441 rendering time).
    442 
    443 The allow_lazy() decorator
    444 ~~~~~~~~~~~~~~~~~~~~~~~~~~
    445 
    446 Django offers many utility functions (particularly in ``django.utils``) that
    447 take a string as their first argument and do something to that string. These
    448 functions are used by template filters as well as directly in other code.
    449 
    450 If you write your own similar functions and deal with translations, you'll
    451 face the problem of what to do when the first argument is a lazy translation
    452 object. You don't want to convert it to a string immediately, because you might
    453 be using this function outside of a view (and hence the current thread's locale
    454 setting will not be correct).
    455 
    456 For cases like this, use the ``django.utils.functional.allow_lazy()``
    457 decorator. It modifies the function so that *if* it's called with a lazy
    458 translation as the first argument, the function evaluation is delayed until it
    459 needs to be converted to a string.
    460 
    461 For example::
    462 
    463     from django.utils.functional import allow_lazy
    464 
    465     def fancy_utility_function(s, ...):
    466         # Do some conversion on string 's'
    467         ...
    468     fancy_utility_function = allow_lazy(fancy_utility_function, unicode)
    469 
    470 The ``allow_lazy()`` decorator takes, in addition to the function to decorate,
    471 a number of extra arguments (``*args``) specifying the type(s) that the
    472 original function can return. Usually, it's enough to include ``unicode`` here
    473 and ensure that your function returns only Unicode strings.
    474 
    475 Using this decorator means you can write your function and assume that the
    476 input is a proper string, then add support for lazy translation objects at the
    477 end.
    478 
    479 .. _how-to-create-language-files:
    480 
    481 2. How to create language files
    482 ===============================
    483 
    484 Once you've tagged your strings for later translation, you need to write (or
    485 obtain) the language translations themselves. Here's how that works.
    486 
    487 .. admonition:: Locale restrictions
    488 
    489     Django does not support localizing your application into a locale for
    490     which Django itself has not been translated. In this case, it will ignore
    491     your translation files. If you were to try this and Django supported it,
    492     you would inevitably see a mixture of translated strings (from your
    493     application) and English strings (from Django itself). If you want to
    494     support a locale for your application that is not already part of
    495     Django, you'll need to make at least a minimal translation of the Django
    496     core. See the relevant :ref:`LocaleMiddleware note<locale-middleware-notes>`
    497     for more details.
    498 
    499 Message files
    500 -------------
    501 
    502 The first step is to create a **message file** for a new language. A message
    503 file is a plain-text file, representing a single language, that contains all
    504 available translation strings and how they should be represented in the given
    505 language. Message files have a ``.po`` file extension.
    506 
    507 Django comes with a tool, ``django-admin.py makemessages``, that automates the
    508 creation and upkeep of these files.
    509 
    510 .. admonition:: A note to Django veterans
    511 
    512     The old tool ``bin/make-messages.py`` has been moved to the command
    513     ``django-admin.py makemessages`` to provide consistency throughout Django.
    514 
    515 To create or update a message file, run this command::
    516 
    517     django-admin.py makemessages -l de
    518 
    519 ...where ``de`` is the language code for the message file you want to create.
    520 The language code, in this case, is in locale format. For example, it's
    521 ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian German.
    522 
    523 The script should be run from one of three places:
    524 
    525     * The root directory of your Django project.
    526     * The root directory of your Django app.
    527     * The root ``django`` directory (not a Subversion checkout, but the one
    528       that is linked-to via ``$PYTHONPATH`` or is located somewhere on that
    529       path). This is only relevant when you are creating a translation for
    530       Django itself, see :ref:`contributing-translations`.
    531 
    532 The script runs over your project source tree or your application source tree
    533 and pulls out all strings marked for translation. It creates (or updates) a
    534 message file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de``
    535 example, the file will be ``locale/de/LC_MESSAGES/django.po``.
    536 
    537 By default ``django-admin.py makemessages`` examines every file that has the
    538 ``.html`` file extension. In case you want to override that default, use the
    539 ``--extension`` or ``-e`` option to specify the file extensions to examine::
    540 
    541     django-admin.py makemessages -l de -e txt
    542 
    543 Separate multiple extensions with commas and/or use ``-e`` or ``--extension``
    544 multiple times::
    545 
    546     django-admin.py makemessages -l=de -e=html,txt -e xml
    547 
    548 When `creating JavaScript translation catalogs`_ you need to use the special
    549 'djangojs' domain, **not** ``-e js``.
    550 
    551 .. admonition:: No gettext?
    552 
    553     If you don't have the ``gettext`` utilities installed, ``django-admin.py
    554     makemessages`` will create empty files. If that's the case, either install
    555     the ``gettext`` utilities or just copy the English message file
    556     (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting
    557     point; it's just an empty translation file.
    558 
    559 .. admonition:: Working on Windows?
    560 
    561    If you're using Windows and need to install the GNU gettext utilities so
    562    ``django-admin makemessages`` works see `gettext on Windows`_ for more
    563    information.
    564 
    565 The format of ``.po`` files is straightforward. Each ``.po`` file contains a
    566 small bit of metadata, such as the translation maintainer's contact
    567 information, but the bulk of the file is a list of **messages** -- simple
    568 mappings between translation strings and the actual translated text for the
    569 particular language.
    570 
    571 For example, if your Django app contained a translation string for the text
    572 ``"Welcome to my site."``, like so::
    573 
    574     _("Welcome to my site.")
    575 
    576 ...then ``django-admin.py makemessages`` will have created a ``.po`` file
    577 containing the following snippet -- a message::
    578 
    579     #: path/to/python/module.py:23
    580     msgid "Welcome to my site."
    581     msgstr ""
    582 
    583 A quick explanation:
    584 
    585     * ``msgid`` is the translation string, which appears in the source. Don't
    586       change it.
    587     * ``msgstr`` is where you put the language-specific translation. It starts
    588       out empty, so it's your responsibility to change it. Make sure you keep
    589       the quotes around your translation.
    590     * As a convenience, each message includes, in the form of a comment line
    591       prefixed with ``#`` and located above the ``msgid`` line, the filename
    592       and line number from which the translation string was gleaned.
    593 
    594 Long messages are a special case. There, the first string directly after the
    595 ``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be
    596 written over the next few lines as one string per line. Those strings are
    597 directly concatenated. Don't forget trailing spaces within the strings;
    598 otherwise, they'll be tacked together without whitespace!
    599 
    600 .. admonition:: Mind your charset
    601 
    602     When creating a PO file with your favorite text editor, first edit
    603     the charset line (search for ``"CHARSET"``) and set it to the charset
    604     you'll be using to edit the content. Due to the way the ``gettext`` tools
    605     work internally and because we want to allow non-ASCII source strings in
    606     Django's core and your applications, you **must** use UTF-8 as the encoding
    607     for your PO file. This means that everybody will be using the same
    608     encoding, which is important when Django processes the PO files.
    609 
    610 To reexamine all source code and templates for new translation strings and
    611 update all message files for **all** languages, run this::
    612 
    613     django-admin.py makemessages -a
    614 
    615 Compiling message files
    616 -----------------------
    617 
    618 After you create your message file -- and each time you make changes to it --
    619 you'll need to compile it into a more efficient form, for use by ``gettext``.
    620 Do this with the ``django-admin.py compilemessages`` utility.
    621 
    622 This tool runs over all available ``.po`` files and creates ``.mo`` files,
    623 which are binary files optimized for use by ``gettext``. In the same directory
    624 from which you ran ``django-admin.py makemessages``, run ``django-admin.py
    625 compilemessages`` like this::
    626 
    627    django-admin.py compilemessages
    628 
    629 That's it. Your translations are ready for use.
    630 
    631 .. admonition:: A note to Django veterans
    632 
    633     The old tool ``bin/compile-messages.py`` has been moved to the command
    634     ``django-admin.py compilemessages`` to provide consistency throughout
    635     Django.
    636 
    637 .. admonition:: Working on Windows?
    638 
    639    If you're using Windows and need to install the GNU gettext utilities so
    640    ``django-admin compilemessages`` works see `gettext on Windows`_ for more
    641    information.
    642 
    643 .. _how-django-discovers-language-preference:
    644 
    645 3. How Django discovers language preference
    646 ===========================================
    647 
    648 Once you've prepared your translations -- or, if you just want to use the
    649 translations that come with Django -- you'll just need to activate translation
    650 for your app.
    651 
    652 Behind the scenes, Django has a very flexible model of deciding which language
    653 should be used -- installation-wide, for a particular user, or both.
    654 
    655 To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`.
    656 Django uses this language as the default translation -- the final attempt if no
    657 other translator finds a translation.
    658 
    659 If all you want to do is run Django with your native language, and a language
    660 file is available for your language, all you need to do is set
    661 ``LANGUAGE_CODE``.
    662 
    663 If you want to let each individual user specify which language he or she
    664 prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language
    665 selection based on data from the request. It customizes content for each user.
    666 
    667 To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'``
    668 to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you
    669 should follow these guidelines:
    670 
    671     * Make sure it's one of the first middlewares installed.
    672     * It should come after ``SessionMiddleware``, because ``LocaleMiddleware``
    673       makes use of session data.
    674     * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it.
    675 
    676 For example, your ``MIDDLEWARE_CLASSES`` might look like this::
    677 
    678     MIDDLEWARE_CLASSES = (
    679        'django.contrib.sessions.middleware.SessionMiddleware',
    680        'django.middleware.locale.LocaleMiddleware',
    681        'django.middleware.common.CommonMiddleware',
    682     )
    683 
    684 (For more on middleware, see the :ref:`middleware documentation
    685 <topics-http-middleware>`.)
    686 
    687 ``LocaleMiddleware`` tries to determine the user's language preference by
    688 following this algorithm:
    689 
    690     * First, it looks for a ``django_language`` key in the current user's
    691       session.
    692 
    693     * Failing that, it looks for a cookie.
    694 
    695       .. versionchanged:: 1.0
    696 
    697       In Django version 0.96 and before, the cookie's name is hard-coded to
    698       ``django_language``. In Django 1,0, The cookie name is set by the
    699       ``LANGUAGE_COOKIE_NAME`` setting. (The default name is
    700       ``django_language``.)
    701 
    702     * Failing that, it looks at the ``Accept-Language`` HTTP header. This
    703       header is sent by your browser and tells the server which language(s) you
    704       prefer, in order by priority. Django tries each language in the header
    705       until it finds one with available translations.
    706 
    707     * Failing that, it uses the global ``LANGUAGE_CODE`` setting.
    708 
    709 .. _locale-middleware-notes:
    710 
    711 Notes:
    712 
    713     * In each of these places, the language preference is expected to be in the
    714       standard language format, as a string. For example, Brazilian Portuguese
    715       is ``pt-br``.
    716 
    717     * If a base language is available but the sublanguage specified is not,
    718       Django uses the base language. For example, if a user specifies ``de-at``
    719       (Austrian German) but Django only has ``de`` available, Django uses
    720       ``de``.
    721 
    722     * Only languages listed in the :setting:`LANGUAGES` setting can be selected.
    723       If you want to restrict the language selection to a subset of provided
    724       languages (because your application doesn't provide all those languages),
    725       set ``LANGUAGES`` to a list of languages. For example::
    726 
    727           LANGUAGES = (
    728             ('de', _('German')),
    729             ('en', _('English')),
    730           )
    731 
    732       This example restricts languages that are available for automatic
    733       selection to German and English (and any sublanguage, like de-ch or
    734       en-us).
    735 
    736       .. _LANGUAGES setting: ../settings/#languages
    737 
    738     * If you define a custom ``LANGUAGES`` setting, as explained in the
    739       previous bullet, it's OK to mark the languages as translation strings
    740       -- but use a "dummy" ``ugettext()`` function, not the one in
    741       ``django.utils.translation``. You should *never* import
    742       ``django.utils.translation`` from within your settings file, because that
    743       module in itself depends on the settings, and that would cause a circular
    744       import.
    745 
    746       The solution is to use a "dummy" ``ugettext()`` function. Here's a sample
    747       settings file::
    748 
    749           ugettext = lambda s: s
    750 
    751           LANGUAGES = (
    752               ('de', ugettext('German')),
    753               ('en', ugettext('English')),
    754           )
    755 
    756       With this arrangement, ``django-admin.py makemessages`` will still find
    757       and mark these strings for translation, but the translation won't happen
    758       at runtime -- so you'll have to remember to wrap the languages in the
    759       *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime.
    760 
    761     * The ``LocaleMiddleware`` can only select languages for which there is a
    762       Django-provided base translation. If you want to provide translations
    763       for your application that aren't already in the set of translations
    764       in Django's source tree, you'll want to provide at least basic
    765       translations for that language. For example, Django uses technical
    766       message IDs to translate date formats and time formats -- so you will
    767       need at least those translations for the system to work correctly.
    768 
    769       A good starting point is to copy the English ``.po`` file and to
    770       translate at least the technical messages -- maybe the validation
    771       messages, too.
    772 
    773       Technical message IDs are easily recognized; they're all upper case. You
    774       don't translate the message ID as with other messages, you provide the
    775       correct local variant on the provided English value. For example, with
    776       ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), this would
    777       be the format string that you want to use in your language. The format
    778       is identical to the format strings used by the ``now`` template tag.
    779 
    780 Once ``LocaleMiddleware`` determines the user's preference, it makes this
    781 preference available as ``request.LANGUAGE_CODE`` for each
    782 :class:`~django.http.HttpRequest`. Feel free to read this value in your view
    783 code. Here's a simple example::
    784 
    785     def hello_world(request, count):
    786         if request.LANGUAGE_CODE == 'de-at':
    787             return HttpResponse("You prefer to read Austrian German.")
    788         else:
    789             return HttpResponse("You prefer to read another language.")
    790 
    791 Note that, with static (middleware-less) translation, the language is in
    792 ``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's
    793 in ``request.LANGUAGE_CODE``.
    794 
    795 .. _settings file: ../settings/
    796 .. _middleware documentation: ../middleware/
    797 .. _session: ../sessions/
    798 .. _request object: ../request_response/#httprequest-objects
    799 
    800 .. _translations-in-your-own-projects:
    801 
    802 Using translations in your own projects
    803 =======================================
    804 
    805 Django looks for translations by following this algorithm:
    806 
    807     * First, it looks for a ``locale`` directory in the application directory
    808       of the view that's being called. If it finds a translation for the
    809       selected language, the translation will be installed.
    810     * Next, it looks for a ``locale`` directory in the project directory. If it
    811       finds a translation, the translation will be installed.
    812     * Finally, it checks the Django-provided base translation in
    813       ``django/conf/locale``.
    814 
    815 This way, you can write applications that include their own translations, and
    816 you can override base translations in your project path. Or, you can just build
    817 a big project out of several apps and put all translations into one big project
    818 message file. The choice is yours.
    819 
    820 .. note::
    821 
    822     If you're using manually configured settings, as described
    823     :ref:`settings-without-django-settings-module`, the ``locale`` directory in
    824     the project directory will not be examined, since Django loses the ability
    825     to work out the location of the project directory. (Django normally uses
    826     the location of the settings file to determine this, and a settings file
    827     doesn't exist if you're manually configuring your settings.)
    828 
    829 All message file repositories are structured the same way. They are:
    830 
    831     * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
    832     * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
    833     * All paths listed in ``LOCALE_PATHS`` in your settings file are
    834       searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)``
    835     * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``
    836 
    837 To create message files, you use the same ``django-admin.py makemessages``
    838 tool as with the Django message files. You only need to be in the right place
    839 -- in the directory where either the ``conf/locale`` (in case of the source
    840 tree) or the ``locale/`` (in case of app messages or project messages)
    841 directory are located. And you use the same ``django-admin.py
    842 compilemessages`` to produce the binary ``django.mo`` files that are used by
    843 ``gettext``.
    844 
    845 You can also run ``django-admin.py compilemessages
    846 --settings=path.to.settings`` to make the compiler process all the directories
    847 in your ``LOCALE_PATHS`` setting.
    848 
    849 Application message files are a bit complicated to discover -- they need the
    850 ``LocaleMiddleware``. If you don't use the middleware, only the Django message
    851 files and project message files will be processed.
    852 
    853 Finally, you should give some thought to the structure of your translation
    854 files. If your applications need to be delivered to other users and will
    855 be used in other projects, you might want to use app-specific translations.
    856 But using app-specific translations and project translations could produce
    857 weird problems with ``makemessages``: ``makemessages`` will traverse all
    858 directories below the current path and so might put message IDs into the
    859 project message file that are already in application message files.
    860 
    861 The easiest way out is to store applications that are not part of the project
    862 (and so carry their own translations) outside the project tree. That way,
    863 ``django-admin.py makemessages`` on the project level will only translate
    864 strings that are connected to your explicit project and not strings that are
    865 distributed independently.
    866 
    867 The ``set_language`` redirect view
    868 ==================================
    869 
    870 As a convenience, Django comes with a view, ``django.views.i18n.set_language``,
    871 that sets a user's language preference and redirects back to the previous page.
    872 
    873 Activate this view by adding the following line to your URLconf::
    874 
    875     (r'^i18n/', include('django.conf.urls.i18n')),
    876 
    877 (Note that this example makes the view available at ``/i18n/setlang/``.)
    878 
    879 The view expects to be called via the ``POST`` method, with a ``language``
    880 parameter set in request. If session support is enabled, the view
    881 saves the language choice in the user's session. Otherwise, it saves the
    882 language choice in a cookie that is by default named ``django_language``.
    883 (The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.)
    884 
    885 After setting the language choice, Django redirects the user, following this
    886 algorithm:
    887 
    888     * Django looks for a ``next`` parameter in the ``POST`` data.
    889     * If that doesn't exist, or is empty, Django tries the URL in the
    890       ``Referrer`` header.
    891     * If that's empty -- say, if a user's browser suppresses that header --
    892       then the user will be redirected to ``/`` (the site root) as a fallback.
    893 
    894 Here's example HTML template code:
    895 
    896 .. code-block:: html+django
    897 
    898     <form action="/i18n/setlang/" method="post">
    899     <input name="next" type="hidden" value="/next/page/" />
    900     <select name="language">
    901     {% for lang in LANGUAGES %}
    902     <option value="{{ lang.0 }}">{{ lang.1 }}</option>
    903     {% endfor %}
    904     </select>
    905     <input type="submit" value="Go" />
    906     </form>
    907 
    908 Translations and JavaScript
    909 ===========================
    910 
    911 Adding translations to JavaScript poses some problems:
    912 
    913     * JavaScript code doesn't have access to a ``gettext`` implementation.
    914 
    915     * JavaScript code doesn't have access to .po or .mo files; they need to be
    916       delivered by the server.
    917 
    918     * The translation catalogs for JavaScript should be kept as small as
    919       possible.
    920 
    921 Django provides an integrated solution for these problems: It passes the
    922 translations into JavaScript, so you can call ``gettext``, etc., from within
    923 JavaScript.
    924 
    925 The ``javascript_catalog`` view
    926 -------------------------------
    927 
    928 The main solution to these problems is the ``javascript_catalog`` view, which
    929 sends out a JavaScript code library with functions that mimic the ``gettext``
    930 interface, plus an array of translation strings. Those translation strings are
    931 taken from the application, project or Django core, according to what you
    932 specify in either the info_dict or the URL.
    933 
    934 You hook it up like this::
    935 
    936     js_info_dict = {
    937         'packages': ('your.app.package',),
    938     }
    939 
    940     urlpatterns = patterns('',
    941         (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
    942     )
    943 
    944 Each string in ``packages`` should be in Python dotted-package syntax (the
    945 same format as the strings in ``INSTALLED_APPS``) and should refer to a package
    946 that contains a ``locale`` directory. If you specify multiple packages, all
    947 those catalogs are merged into one catalog. This is useful if you have
    948 JavaScript that uses strings from different applications.
    949 
    950 You can make the view dynamic by putting the packages into the URL pattern::
    951 
    952     urlpatterns = patterns('',
    953         (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),
    954     )
    955 
    956 With this, you specify the packages as a list of package names delimited by '+'
    957 signs in the URL. This is especially useful if your pages use code from
    958 different apps and this changes often and you don't want to pull in one big
    959 catalog file. As a security measure, these values can only be either
    960 ``django.conf`` or any package from the ``INSTALLED_APPS`` setting.
    961 
    962 Using the JavaScript translation catalog
    963 ----------------------------------------
    964 
    965 To use the catalog, just pull in the dynamically generated script like this::
    966 
    967     <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script>
    968 
    969 This uses reverse URL lookup to find the URL of the JavaScript catalog view.
    970 When the catalog is loaded, your JavaScript code can use the standard
    971 ``gettext`` interface to access it::
    972 
    973     document.write(gettext('this is to be translated'));
    974 
    975 There is also an ``ngettext`` interface::
    976 
    977     var object_cnt = 1 // or 0, or 2, or 3, ...
    978     s = ngettext('literal for the singular case',
    979             'literal for the plural case', object_cnt);
    980 
    981 and even a string interpolation function::
    982 
    983     function interpolate(fmt, obj, named);
    984 
    985 The interpolation syntax is borrowed from Python, so the ``interpolate``
    986 function supports both positional and named interpolation:
    987 
    988     * Positional interpolation: ``obj`` contains a JavaScript Array object
    989       whose elements values are then sequentially interpolated in their
    990       corresponding ``fmt`` placeholders in the same order they appear.
    991       For example::
    992 
    993         fmts = ngettext('There is %s object. Remaining: %s',
    994                 'There are %s objects. Remaining: %s', 11);
    995         s = interpolate(fmts, [11, 20]);
    996         // s is 'There are 11 objects. Remaining: 20'
    997 
    998     * Named interpolation: This mode is selected by passing the optional
    999       boolean ``named`` parameter as true. ``obj`` contains a JavaScript
    1000       object or associative array. For example::
    1001 
    1002         d = {
    1003             count: 10
    1004             total: 50
    1005         };
    1006 
    1007         fmts = ngettext('Total: %(total)s, there is %(count)s object',
    1008         'there are %(count)s of a total of %(total)s objects', d.count);
    1009         s = interpolate(fmts, d, true);
    1010 
    1011 You shouldn't go over the top with string interpolation, though: this is still
    1012 JavaScript, so the code has to make repeated regular-expression substitutions.
    1013 This isn't as fast as string interpolation in Python, so keep it to those
    1014 cases where you really need it (for example, in conjunction with ``ngettext``
    1015 to produce proper pluralizations).
    1016 
    1017 Creating JavaScript translation catalogs
    1018 ----------------------------------------
    1019 
    1020 You create and update the translation catalogs the same way as the other
    1021 
    1022 Django translation catalogs -- with the ``django-admin.py makemessages`` tool.
    1023 The only difference is you need to provide a ``-d djangojs`` parameter, like
    1024 this::
    1025 
    1026     django-admin.py makemessages -d djangojs -l de
    1027 
    1028 This would create or update the translation catalog for JavaScript for German.
    1029 After updating translation catalogs, just run ``django-admin.py
    1030 compilemessages`` the same way as you do with normal Django translation
    1031 catalogs.
    1032 
    1033 Specialties of Django translation
    1034 ==================================
    1035 
    1036 If you know ``gettext``, you might note these specialties in the way Django
    1037 does translation:
    1038 
    1039     * The string domain is ``django`` or ``djangojs``. This string domain is
    1040       used to differentiate between different programs that store their data
    1041       in a common message-file library (usually ``/usr/share/locale/``). The
    1042       ``django`` domain is used for python and template translation strings
    1043       and is loaded into the global translation catalogs. The ``djangojs``
    1044       domain is only used for JavaScript translation catalogs to make sure
    1045       that those are as small as possible.
    1046     * Django doesn't use ``xgettext`` alone. It uses Python wrappers around
    1047       ``xgettext`` and ``msgfmt``. This is mostly for convenience.
    1048 
    1049 ``gettext`` on Windows
    1050 ======================
    1051 
    1052 This is only needed for people who either want to extract message IDs or
    1053 compile message files (``.po``). Translation work itself just involves editing
    1054 existing files of this type, but if you want to create your own message files,
    1055 or want to test or compile a changed message file, you will need the
    1056 ``gettext`` utilities:
    1057 
    1058     * Download the following zip files from the GNOME servers
    1059       http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one
    1060       of its mirrors_
    1061 
    1062       * ``gettext-runtime-X.zip``
    1063       * ``gettext-tools-X.zip``
    1064 
    1065       ``X`` is the version number, we recomend using ``0.15`` or higher.
    1066 
    1067     * Extract the contents of the ``bin\`` directories in both files to the
    1068       same folder on your system (i.e. ``C:\Program Files\gettext-utils``)
    1069 
    1070     * Update the system PATH:
    1071 
    1072       * ``Control Panel > System > Advanced > Environment Variables``
    1073       * In the ``System variables`` list, click ``Path``, click ``Edit``
    1074       * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the
    1075         ``Variable value`` field
    1076 
    1077 .. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS
    1078 
    1079 You may also use ``gettext`` binaries you have obtained elsewhere, so long as
    1080 the ``xgettext --version`` command works properly. Some version 0.14.4 binaries
    1081 have been found to not support this command. Do not attempt to use Django
    1082 translation utilities with a ``gettext`` package if the command ``xgettext
    1083 --version`` entered at a Windows command prompt causes a popup window saying
    1084 "xgettext.exe has generated errors and will be closed by Windows".
    1085 
    1086 .. _format-localization:
    1087 
    1088 Format localization
    1089 ===================
    1090 
    1091 Django's formatting system is disabled by default. To enable it, it's necessay
    1092 to set :setting:`USE_L10N = True <USE_L10N>` in your settings file.
    1093 
    1094 When using Django's formatting system, dates and numbers on templates will be
    1095 displayed using the format specified for the current locale. Two users
    1096 accessing the same content, but in different language, will see date and
    1097 number fields formatted in different ways, depending on the format for their
    1098 current locale.
    1099 
    1100 Django will also use localized formats when parsing data in forms. That means
    1101 Django uses different formats for different locales when guessing the format
    1102 used by the user when inputting data on forms. Note that Django uses different
    1103 formats for displaying data, and for parsing it.
    1104 
    1105 Creating custom format files
    1106 ----------------------------
    1107 
    1108 Django provides format definitions for many locales, but sometimes you might
    1109 want to create your own, because a format files doesn't exist for your locale,
    1110 or because you want to overwrite some of the values.
    1111 
    1112 To use custom formats, first thing to do, is to specify the path where you'll
    1113 place format files. To do that, just set your :setting:`FORMAT_MODULE_PATH`
    1114 setting to the the path (in the format ``'foo.bar.baz``) where format files
    1115 will exists.
    1116 
    1117 Files are not placed directly in this directory, but in a directory named as
    1118 the locale, and must be named ``formats.py``.
    1119 
    1120 To customize the English formats, a structure like this would be needed::
    1121 
    1122     mysite/
    1123         formats/
    1124             __init__.py
    1125             en/
    1126                 __init__.py
    1127                 formats.py
    1128 
    1129 where :file:`formats.py` contains custom format definitions. For example::
    1130 
    1131     THOUSAND_SEPARATOR = ' '
    1132 
    1133 to use a space as a thousand separator, instead of the default for English,
    1134 a comma.
  • new file docs/topics/i18n/deployment.txt

    diff -r 257fac48943d docs/topics/i18n/deployment.txt
    - +  
     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
     20.. note::
     21
     22    There is also an independent but related :setting:`USE_L10N` setting that
     23    controls if Django should implement format localization.
     24
     25    If :setting:`USE_L10N` is set to ``True``, Django will handle numbers times,
     26    and dates in the format of the current locale. That includes representation
     27    of     these field types on templates and allowed input formats for dates,
     28    times on model forms.
     29
     30    See :ref:`format-localization` for more details.
     31
     32If you do need internationalization
     33===================================
     34
     35.. _how-django-discovers-language-preference:
     36
     37How Django discovers language preference
     38----------------------------------------
     39
     40Once you've prepared your translations -- or, if you just want to use the
     41translations that come with Django -- you'll just need to activate translation
     42for your app.
     43
     44Behind the scenes, Django has a very flexible model of deciding which language
     45should be used -- installation-wide, for a particular user, or both.
     46
     47To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`.
     48Django uses this language as the default translation -- the final attempt if no
     49other translator finds a translation.
     50
     51If all you want to do is run Django with your native language, and a language
     52file is available for it, all you need to do is set ``LANGUAGE_CODE``.
     53
     54If you want to let each individual user specify which language he or she
     55prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language
     56selection based on data from the request. It customizes content for each user.
     57
     58To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'``
     59to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you
     60should follow these guidelines:
     61
     62    * Make sure it's one of the first middlewares installed.
     63    * It should come after ``SessionMiddleware``, because ``LocaleMiddleware``
     64      makes use of session data.
     65    * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it.
     66
     67For example, your ``MIDDLEWARE_CLASSES`` might look like this::
     68
     69    MIDDLEWARE_CLASSES = (
     70       'django.contrib.sessions.middleware.SessionMiddleware',
     71       'django.middleware.locale.LocaleMiddleware',
     72       'django.middleware.common.CommonMiddleware',
     73    )
     74
     75(For more on middleware, see the :ref:`middleware documentation
     76<topics-http-middleware>`.)
     77
     78``LocaleMiddleware`` tries to determine the user's language preference by
     79following this algorithm:
     80
     81    * First, it looks for a ``django_language`` key in the current user's
     82      session.
     83
     84    * Failing that, it looks for a cookie.
     85
     86      .. versionchanged:: 1.0
     87
     88      In Django version 0.96 and before, the cookie's name is hard-coded to
     89      ``django_language``. In Django 1,0, The cookie name is set by the
     90      ``LANGUAGE_COOKIE_NAME`` setting. (The default name is
     91      ``django_language``.)
     92
     93    * Failing that, it looks at the ``Accept-Language`` HTTP header. This
     94      header is sent by your browser and tells the server which language(s) you
     95      prefer, in order by priority. Django tries each language in the header
     96      until it finds one with available translations.
     97
     98    * Failing that, it uses the global ``LANGUAGE_CODE`` setting.
     99
     100.. _locale-middleware-notes:
     101
     102Notes:
     103
     104    * In each of these places, the language preference is expected to be in the
     105      standard :term:`language format<language code>`, as a string. For example,
     106      Brazilian Portuguese is ``pt-br``.
     107
     108    * If a base language is available but the sublanguage specified is not,
     109      Django uses the base language. For example, if a user specifies ``de-at``
     110      (Austrian German) but Django only has ``de`` available, Django uses
     111      ``de``.
     112
     113    * Only languages listed in the :setting:`LANGUAGES` setting can be selected.
     114      If you want to restrict the language selection to a subset of provided
     115      languages (because your application doesn't provide all those languages),
     116      set ``LANGUAGES`` to a list of languages. For example::
     117
     118          LANGUAGES = (
     119            ('de', _('German')),
     120            ('en', _('English')),
     121          )
     122
     123      This example restricts languages that are available for automatic
     124      selection to German and English (and any sublanguage, like de-ch or
     125      en-us).
     126
     127      .. _LANGUAGES setting: ../settings/#languages
     128
     129    * If you define a custom ``LANGUAGES`` setting, as explained in the
     130      previous bullet, it's OK to mark the languages as translation strings
     131      -- but use a "dummy" ``ugettext()`` function, not the one in
     132      ``django.utils.translation``. You should *never* import
     133      ``django.utils.translation`` from within your settings file, because that
     134      module in itself depends on the settings, and that would cause a circular
     135      import.
     136
     137      The solution is to use a "dummy" ``ugettext()`` function. Here's a sample
     138      settings file::
     139
     140          ugettext = lambda s: s
     141
     142          LANGUAGES = (
     143              ('de', ugettext('German')),
     144              ('en', ugettext('English')),
     145          )
     146
     147      With this arrangement, ``django-admin.py makemessages`` will still find
     148      and mark these strings for translation, but the translation won't happen
     149      at runtime -- so you'll have to remember to wrap the languages in the
     150      *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime.
     151
     152    * The ``LocaleMiddleware`` can only select languages for which there is a
     153      Django-provided base translation. If you want to provide translations
     154      for your application that aren't already in the set of translations
     155      in Django's source tree, you'll want to provide at least a basic
     156      one as described in the :ref:`Locale restrictions<locale-restrictions>`
     157      note.
     158
     159Once ``LocaleMiddleware`` determines the user's preference, it makes this
     160preference available as ``request.LANGUAGE_CODE`` for each
     161:class:`~django.http.HttpRequest`. Feel free to read this value in your view
     162code. Here's a simple example::
     163
     164    def hello_world(request, count):
     165        if request.LANGUAGE_CODE == 'de-at':
     166            return HttpResponse("You prefer to read Austrian German.")
     167        else:
     168            return HttpResponse("You prefer to read another language.")
     169
     170Note that, with static (middleware-less) translation, the language is in
     171``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's
     172in ``request.LANGUAGE_CODE``.
     173
     174.. _settings file: ../settings/
     175.. _middleware documentation: ../middleware/
     176.. _session: ../sessions/
     177.. _request object: ../request_response/#httprequest-objects
     178
     179How Django discovers translations
     180---------------------------------
     181
     182As described in :ref:`using-translations-in-your-own-projects`,
     183at runtime, Django looks for translations by following this algorithm:
     184
     185    * First, it looks for a ``locale`` directory in the application directory
     186      of the view that's being called. If it finds a translation for the
     187      selected language, the translation will be installed.
     188    * Next, it looks for a ``locale`` directory in the project directory. If it
     189      finds a translation, the translation will be installed.
     190    * Finally, it checks the Django-provided base translation in
     191      ``django/conf/locale``.
     192
     193In all cases the name of the directory containing the translation is expected to
     194be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
     195etc.
  • new file docs/topics/i18n/index.txt

    diff -r 257fac48943d docs/topics/i18n/index.txt
    - +  
     1.. _topics-i18n:
     2
     3=====================================
     4Internationalization and localization
     5=====================================
     6
     7Overview
     8========
     9
     10Django has full support for internationalization of text in code and
     11templates, and format localization of dates and numbers. Here's how it works.
     12
     13Essentially, Django does two things:
     14
     15    * It lets developers and template authors specify which parts of their apps
     16      should be translatable.
     17    * It uses these hooks to translate Web apps for particular users according
     18      to their language preferences.
     19
     20The complete process can be seen as divided in three stages. It is also possible
     21to identify an identical number of roles with very well defined responsabilities
     22associated with each of these tasks (although it's perfectly normal if you
     23find yourself performing more than one of these roles):
     24
     25    * For applicacion authors wishing to make sure their Django apps can be
     26      used in different locales: Internationalization.
     27    * For translators wanting to translate Django apps: Localization.
     28    * For system administrators/final users setting up internationalized apps or
     29      developers integrating third party apps: Deployment.
     30
     31.. toctree::
     32   :maxdepth: 1
     33
     34   internationalization
     35   localization
     36   deployment
     37
     38.. _ seealso::
     39
     40For more general information about the topic, see the `GNU gettext documentation`_
     41and the `Wikipedia article`_
     42
     43.. _GNU gettext documentation: http://www.gnu.org/software/gettext/manual/gettext.html#Concepts
     44.. _Wikipedia article: http://en.wikipedia.org/wiki/Internationalization_and_localization
     45
     46Glossary
     47========
     48
     49First lets define some terms that will help us to handle a common language:
     50
     51.. glossary::
     52
     53    locale name
     54      A locale name, either a language specification of the form ``ll`` or a
     55      combined language and country specification of the form ``ll_CC``.
     56      Examples: ``it``, ``de_AT``, ``es``, ``pt_BR``. Note the underscore in
     57      some of them and the case of the part located to its right.
     58
     59    language code
     60      Represents the name of a language. Browsers send the names of the
     61      languages they accept in the ``Accept-Language`` HTTP header using this
     62      format. Examples: ``it``, ``de-at``, ``es``, ``pt-br``. Note the ``-``
     63      separator.
     64
     65    message file
     66      A message file is a plain-text file, representing a single language, that
     67      contains all available :term:`translation string`\s and how they should be
     68      represented in the given language. Message files have a ``.po`` file
     69      extension.
     70
     71    translation string
     72      A literal that can be translated.
     73
     74.. _specialties-of-django-i18n:
     75
     76Specialties of Django translation
     77==================================
     78
     79Django's translation machinery uses the standard ``gettext`` module that comes
     80with Python. If you know ``gettext``, you might note these specialties in the
     81way Django does translation:
     82
     83    * The string domain is ``django`` or ``djangojs``. This string domain is
     84      used to differentiate between different programs that store their data
     85      in a common message-file library (usually ``/usr/share/locale/``). The
     86      ``django`` domain is used for python and template translation strings
     87      and is loaded into the global translation catalogs. The ``djangojs``
     88      domain is only used for JavaScript translation catalogs to make sure
     89      that those are as small as possible.
     90    * Django doesn't use ``xgettext`` alone. It uses Python wrappers around
     91      ``xgettext`` and ``msgfmt``. This is mostly for convenience.
     92
     93.. _technical-messages:
     94
     95Django technical message IDs
     96----------------------------
     97
     98.. versionchanged:: 1.2
     99    Starting with Django 1.2, technical message IDs are being replaced by :ref:`format-localization`
     100
     101Django uses technical message IDs to translate date formats and time formats.
     102Technical message IDs are :term:`translation string`\s and can be easily
     103recognized; they're all upper case. You don't translate the message ID as with
     104other translation strings, you provide the correct local variant on the provided
     105English value.  The format is identical to the format strings used by the
     106``now`` template tag.
     107
     108For example, with ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``),
     109this would be the format string that you want to use in your language. A Django
     110contributor localizing it to Spanish probably would provide a ``"j N Y P"``
     111"translation" for it in the relevant ``django.po`` file::
     112
     113    msgid "DATETIME_FORMAT"
     114    msgstr "j N Y P"
  • new file docs/topics/i18n/internationalization.txt

    diff -r 257fac48943d docs/topics/i18n/internationalization.txt
    - +  
     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 and locales.
     12
     13For text translations, you, the Django developer, can accomplish this goal by
     14adding a minimal amount of hooks to your Python and templates. These hooks
     15are called **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 you 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      :term:`language code` and the second is the language name (translated into
     392      the 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
     397    * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a
     398      right-to-left language, e.g.: Hebrew, Arabic. If False it's a
     399      left-to-right language, e.g.: English, French, German etc.
     400
     401
     402If you don't use the ``RequestContext`` extension, you can get those values with
     403three tags::
     404
     405    {% get_current_language as LANGUAGE_CODE %}
     406    {% get_available_languages as LANGUAGES %}
     407    {% get_current_language_bidi as LANGUAGE_BIDI %}
     408
     409These tags also require a ``{% load i18n %}``.
     410
     411Translation hooks are also available within any template block tag that accepts
     412constant strings. In those cases, just use ``_()`` syntax to specify a
     413translation string::
     414
     415    {% some_special_tag _("Page not found") value|yesno:_("yes,no") %}
     416
     417In this case, both the tag and the filter will see the already-translated
     418string, so they don't need to be aware of translations.
     419
     420.. note::
     421    In this example, the translation infrastructure will be passed the string
     422    ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The
     423    translated string will need to contain the comma so that the filter
     424    parsing code knows how to split up the arguments. For example, a German
     425    translator might translate the string ``"yes,no"`` as ``"ja,nein"``
     426    (keeping the comma intact).
     427
     428.. _Django templates: ../templates_python/
     429
     430Specifying translation strings: In JavaScript code
     431==================================================
     432
     433Adding translations to JavaScript poses some problems:
     434
     435    * JavaScript code doesn't have access to a ``gettext`` implementation.
     436
     437    * JavaScript code doesn't have access to .po or .mo files; they need to be
     438      delivered by the server.
     439
     440    * The translation catalogs for JavaScript should be kept as small as
     441      possible.
     442
     443Django provides an integrated solution for these problems: It passes the
     444translations into JavaScript, so you can call ``gettext``, etc., from within
     445JavaScript.
     446
     447The ``javascript_catalog`` view
     448-------------------------------
     449
     450The main solution to these problems is the ``javascript_catalog`` view, which
     451sends out a JavaScript code library with functions that mimic the ``gettext``
     452interface, plus an array of translation strings. Those translation strings are
     453taken from the application, project or Django core, according to what you
     454specify in either the info_dict or the URL.
     455
     456You hook it up like this::
     457
     458    js_info_dict = {
     459        'packages': ('your.app.package',),
     460    }
     461
     462    urlpatterns = patterns('',
     463        (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
     464    )
     465
     466Each string in ``packages`` should be in Python dotted-package syntax (the
     467same format as the strings in ``INSTALLED_APPS``) and should refer to a package
     468that contains a ``locale`` directory. If you specify multiple packages, all
     469those catalogs are merged into one catalog. This is useful if you have
     470JavaScript that uses strings from different applications.
     471
     472You can make the view dynamic by putting the packages into the URL pattern::
     473
     474    urlpatterns = patterns('',
     475        (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),
     476    )
     477
     478With this, you specify the packages as a list of package names delimited by '+'
     479signs in the URL. This is especially useful if your pages use code from
     480different apps and this changes often and you don't want to pull in one big
     481catalog file. As a security measure, these values can only be either
     482``django.conf`` or any package from the ``INSTALLED_APPS`` setting.
     483
     484Using the JavaScript translation catalog
     485----------------------------------------
     486
     487To use the catalog, just pull in the dynamically generated script like this::
     488
     489    <script type="text/javascript" src={% url django.views.i18n.javascript_catalog %}"></script>
     490
     491This uses reverse URL lookup to find the URL of the JavaScript catalog view.
     492When the catalog is loaded, your JavaScript code can use the standard
     493``gettext`` interface to access it::
     494
     495    document.write(gettext('this is to be translated'));
     496
     497There is also an ``ngettext`` interface::
     498
     499    var object_cnt = 1 // or 0, or 2, or 3, ...
     500    s = ngettext('literal for the singular case',
     501            'literal for the plural case', object_cnt);
     502
     503and even a string interpolation function::
     504
     505    function interpolate(fmt, obj, named);
     506
     507The interpolation syntax is borrowed from Python, so the ``interpolate``
     508function supports both positional and named interpolation:
     509
     510    * Positional interpolation: ``obj`` contains a JavaScript Array object
     511      whose elements values are then sequentially interpolated in their
     512      corresponding ``fmt`` placeholders in the same order they appear.
     513      For example::
     514
     515        fmts = ngettext('There is %s object. Remaining: %s',
     516                'There are %s objects. Remaining: %s', 11);
     517        s = interpolate(fmts, [11, 20]);
     518        // s is 'There are 11 objects. Remaining: 20'
     519
     520    * Named interpolation: This mode is selected by passing the optional
     521      boolean ``named`` parameter as true. ``obj`` contains a JavaScript
     522      object or associative array. For example::
     523
     524        d = {
     525            count: 10
     526            total: 50
     527        };
     528
     529        fmts = ngettext('Total: %(total)s, there is %(count)s object',
     530        'there are %(count)s of a total of %(total)s objects', d.count);
     531        s = interpolate(fmts, d, true);
     532
     533You shouldn't go over the top with string interpolation, though: this is still
     534JavaScript, so the code has to make repeated regular-expression substitutions.
     535This isn't as fast as string interpolation in Python, so keep it to those
     536cases where you really need it (for example, in conjunction with ``ngettext``
     537to produce proper pluralizations).
     538
     539The ``set_language`` redirect view
     540==================================
     541
     542As a convenience, Django comes with a view, ``django.views.i18n.set_language``,
     543that sets a user's language preference and redirects back to the previous page.
     544
     545Activate this view by adding the following line to your URLconf::
     546
     547    (r'^i18n/', include('django.conf.urls.i18n')),
     548
     549(Note that this example makes the view available at ``/i18n/setlang/``.)
     550
     551The view expects to be called via the ``POST`` method, with a ``language``
     552parameter set in request. If session support is enabled, the view
     553saves the language choice in the user's session. Otherwise, it saves the
     554language choice in a cookie that is by default named ``django_language``.
     555(The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.)
     556
     557After setting the language choice, Django redirects the user, following this
     558algorithm:
     559
     560    * Django looks for a ``next`` parameter in the ``POST`` data.
     561    * If that doesn't exist, or is empty, Django tries the URL in the
     562      ``Referrer`` header.
     563    * If that's empty -- say, if a user's browser suppresses that header --
     564      then the user will be redirected to ``/`` (the site root) as a fallback.
     565
     566Here's example HTML template code:
     567
     568.. code-block:: html+django
     569
     570    <form action="/i18n/setlang/" method="post">
     571    <input name="next" type="hidden" value="/next/page/" />
     572    <select name="language">
     573    {% for lang in LANGUAGES %}
     574    <option value="{{ lang.0 }}">{{ lang.1 }}</option>
     575    {% endfor %}
     576    </select>
     577    <input type="submit" value="Go" />
     578    </form>
  • new file docs/topics/i18n/localization.txt

    diff -r 257fac48943d docs/topics/i18n/localization.txt
    - +  
     1.. _topics-i18n-localization:
     2
     3============
     4Localization
     5============
     6
     7This document covers two localization-related topics: `Creating language
     8files`_ and `locale aware date, time and numbers input/output in forms`_
     9
     10.. _`Creating language files`: how-to-create-language-files_
     11.. _`locale aware date, time and numbers input/output in forms`: format-localization_
     12
     13.. seealso::
     14
     15    The :ref:`howto-i18n` document included with the Django HOW-TO documents collection.
     16
     17.. _how-to-create-language-files:
     18
     19How to create language files
     20============================
     21
     22Once the string literals of an application have been tagged for later
     23translation, the translation themselves need to be written (or obtained). Here's
     24how that works.
     25
     26.. _locale-restrictions:
     27
     28.. admonition:: Locale restrictions
     29
     30    Django does not support localizing your application into a locale for which
     31    Django itself has not been translated. In this case, it will ignore your
     32    translation files. If you were to try this and Django supported it, you
     33    would inevitably see a mixture of translated strings (from your application)
     34    and English strings (from Django itself). If you want to support a locale
     35    for your application that is not already part of Django, you'll need to make
     36    at least a minimal translation of the Django core.
     37
     38    A good starting point is to copy the Django English ``.po`` file and to
     39    translate at least some :term:`translation string`\s.
     40
     41Message files
     42-------------
     43
     44The first step is to create a :term:`message file` for a new language. A message
     45file is a plain-text file, representing a single language, that contains all
     46available translation strings and how they should be represented in the given
     47language. Message files have a ``.po`` file extension.
     48
     49Django comes with a tool, ``django-admin.py makemessages``, that automates the
     50creation and upkeep of these files.
     51
     52.. admonition:: A note to Django veterans
     53
     54    The old tool ``bin/make-messages.py`` has been moved to the command
     55    ``django-admin.py makemessages`` to provide consistency throughout Django.
     56
     57To create or update a message file, run this command::
     58
     59    django-admin.py makemessages -l de
     60
     61...where ``de`` is the language code for the message file you want to create.
     62The language code, in this case, is in :term:`locale format<locale name>`. For
     63example, it's ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian
     64German.
     65
     66The script should be run from one of two places:
     67
     68    * The root directory of your Django project.
     69    * The root directory of your Django app.
     70
     71Th script runs over your project source tree or your application source tree and
     72pulls out all strings marked for translation. It creates (or updates) a message
     73file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de`` example, the
     74file will be ``locale/de/LC_MESSAGES/django.po``.
     75
     76By default ``django-admin.py makemessages`` examines every file that has the
     77``.html`` file extension. In case you want to override that default, use the
     78``--extension`` or ``-e`` option to specify the file extensions to examine::
     79
     80    django-admin.py makemessages -l de -e txt
     81
     82Separate multiple extensions with commas and/or use ``-e`` or ``--extension``
     83multiple times::
     84
     85    django-admin.py makemessages -l=de -e=html,txt -e xml
     86
     87When :ref:`creating message files from JavaScript source code
     88<creating-message-files-from-js-code>` you need to use the special 'djangojs'
     89domain, **not** ``-e js``.
     90
     91.. admonition:: No gettext?
     92
     93    If you don't have the ``gettext`` utilities installed, ``django-admin.py
     94    makemessages`` will create empty files. If that's the case, either install
     95    the ``gettext`` utilities or just copy the English message file
     96    (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting
     97    point; it's just an empty translation file.
     98
     99.. admonition:: Working on Windows?
     100
     101   If you're using Windows and need to install the GNU gettext utilities so
     102   ``django-admin makemessages`` works see :ref:`gettext_on_windows` for more
     103   information.
     104
     105The format of ``.po`` files is straightforward. Each ``.po`` file contains a
     106small bit of metadata, such as the translation maintainer's contact
     107information, but the bulk of the file is a list of **messages** -- simple
     108mappings between translation strings and the actual translated text for the
     109particular language.
     110
     111For example, if your Django app contained a translation string for the text
     112``"Welcome to my site."``, like so::
     113
     114    _("Welcome to my site.")
     115
     116...then ``django-admin.py makemessages`` will have created a ``.po`` file
     117containing the following snippet -- a message::
     118
     119    #: path/to/python/module.py:23
     120    msgid "Welcome to my site."
     121    msgstr ""
     122
     123A quick explanation:
     124
     125    * ``msgid`` is the translation string, which appears in the source. Don't
     126      change it.
     127    * ``msgstr`` is where you put the language-specific translation. It starts
     128      out empty, so it's your responsibility to change it. Make sure you keep
     129      the quotes around your translation.
     130    * As a convenience, each message includes, in the form of a comment line
     131      prefixed with ``#`` and located above the ``msgid`` line, the filename and
     132      line number from which the translation string was gleaned.
     133
     134Long messages are a special case. There, the first string directly after the
     135``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be
     136written over the next few lines as one string per line. Those strings are
     137directly concatenated. Don't forget trailing spaces within the strings;
     138otherwise, they'll be tacked together without whitespace!
     139
     140.. admonition:: Mind your charset
     141
     142    When creating a PO file with your favorite text editor, first edit
     143    the charset line (search for ``"CHARSET"``) and set it to the charset
     144    you'll be using to edit the content. Due to the way the ``gettext`` tools
     145    work internally and because we want to allow non-ASCII source strings in
     146    Django's core and your applications, you **must** use UTF-8 as the encoding
     147    for your PO file. This means that everybody will be using the same
     148    encoding, which is important when Django processes the PO files.
     149
     150To reexamine all source code and templates for new translation strings and
     151update all message files for **all** languages, run this::
     152
     153    django-admin.py makemessages -a
     154
     155Compiling message files
     156-----------------------
     157
     158After you create your message file -- and each time you make changes to it --
     159you'll need to compile it into a more efficient form, for use by ``gettext``.
     160Do this with the ``django-admin.py compilemessages`` utility.
     161
     162This tool runs over all available ``.po`` files and creates ``.mo`` files, which
     163are binary files optimized for use by ``gettext``. In the same directory from
     164which you ran ``django-admin.py makemessages``, run ``django-admin.py
     165compilemessages`` like this::
     166
     167   django-admin.py compilemessages
     168
     169That's it. Your translations are ready for use.
     170
     171.. admonition:: A note to Django veterans
     172
     173    The old tool ``bin/compile-messages.py`` has been moved to the command
     174    ``django-admin.py compilemessages`` to provide consistency throughout
     175    Django.
     176
     177.. admonition:: Working on Windows?
     178
     179   If you're using Windows and need to install the GNU gettext utilities so
     180   ``django-admin compilemessages`` works see :ref:`gettext_on_windows` for more
     181   information.
     182
     183.. _creating-message-files-from-js-code:
     184
     185Creating message files from JavaScript source code
     186==================================================
     187
     188You create and update the message files the same way as the other Django message
     189files -- with the ``django-admin.py makemessages`` tool. The only difference is
     190you need to provide a ``-d djangojs`` parameter, like this::
     191
     192    django-admin.py makemessages -d djangojs -l de
     193
     194This would create or update the message file for JavaScript for German.
     195After updating message files, just run ``django-admin.py compilemessages``
     196the same way as you do with normal Django message files.
     197
     198.. _gettext_on_windows:
     199
     200``gettext`` on Windows
     201======================
     202
     203This is only needed for people who either want to extract message IDs or compile
     204message files (``.po``). Translation work itself just involves editing existing
     205files of this type, but if you want to create your own message files, or want to
     206test or compile a changed message file, you will need the ``gettext`` utilities:
     207
     208    * Download the following zip files from the GNOME servers
     209      http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one
     210      of its mirrors_
     211
     212      * ``gettext-runtime-X.zip``
     213      * ``gettext-tools-X.zip``
     214
     215      ``X`` is the version number, we recomend using ``0.15`` or higher.
     216
     217    * Extract the contents of the ``bin\`` directories in both files to the
     218      same folder on your system (i.e. ``C:\Program Files\gettext-utils``)
     219
     220    * Update the system PATH:
     221
     222      * ``Control Panel > System > Advanced > Environment Variables``.
     223      * In the ``System variables`` list, click ``Path``, click ``Edit``.
     224      * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the
     225        ``Variable value`` field.
     226
     227.. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS
     228
     229You may also use ``gettext`` binaries you have obtained elsewhere, so long as
     230the ``xgettext --version`` command works properly. Some version 0.14.4 binaries
     231have been found to not support this command. Do not attempt to use Django
     232translation utilities with a ``gettext`` package if the command ``xgettext
     233--version`` entered at a Windows command prompt causes a popup window saying
     234"xgettext.exe has generated errors and will be closed by Windows".
     235
     236.. _format-localization:
     237
     238Format localization
     239===================
     240
     241Django's formatting system is disabled by default. To enable it, it's necessay
     242to set :setting:`USE_L10N = True <USE_L10N>` in your settings file.
     243
     244When using Django's formatting system, dates and numbers on templates will be
     245displayed using the format specified for the current locale. Two users
     246accessing the same content, but in different language, will see date and
     247number fields formatted in different ways, depending on the format for their
     248current locale.
     249
     250Django will also use localized formats when parsing data in forms. That means
     251Django uses different formats for different locales when guessing the format
     252used by the user when inputting data on forms. Note that Django uses different
     253formats for displaying data, and for parsing it.
     254
     255Creating custom format files
     256----------------------------
     257
     258Django provides format definitions for many locales, but sometimes you might
     259want to create your own, because a format files doesn't exist for your locale,
     260or because you want to overwrite some of the values.
     261
     262To use custom formats, first thing to do, is to specify the path where you'll
     263place format files. To do that, just set your :setting:`FORMAT_MODULE_PATH`
     264setting to the the path (in the format ``'foo.bar.baz``) where format files
     265will exists.
     266
     267Files are not placed directly in this directory, but in a directory named as
     268the locale, and must be named ``formats.py``.
     269
     270To customize the English formats, a structure like this would be needed::
     271
     272    mysite/
     273        formats/
     274            __init__.py
     275            en/
     276                __init__.py
     277                formats.py
     278
     279where :file:`formats.py` contains custom format definitions. For example::
     280
     281    THOUSAND_SEPARATOR = ' '
     282
     283to use a space as a thousand separator, instead of the default for English,
     284a comma.
  • docs/topics/index.txt

    diff -r 257fac48943d 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