Ticket #10260: 10260-post-r11964.2.diff
File 10260-post-r11964.2.diff, 101.1 KB (added by , 15 years ago) |
---|
-
django/conf/global_settings.py
diff -r 8a4e070b280a django/conf/global_settings.py
a b 297 297 # http://docs.djangoproject.com/en/dev/ref/templates/builtins/#now 298 298 MONTH_DAY_FORMAT = 'F j' 299 299 300 # Default short formatting for date objects. See all available format strings here:300 # Default short formatting for date objects. See all available format strings here: 301 301 # http://docs.djangoproject.com/en/dev/ref/templates/builtins/#now 302 302 SHORT_DATE_FORMAT = 'm/d/Y' 303 303 -
new file docs/howto/i18n.txt
diff -r 8a4e070b280a docs/howto/i18n.txt
- + 1 .. _howto-i18n: 2 3 .. _using-translations-in-your-own-projects: 4 5 =============================================== 6 Using internationalization in your own projects 7 =============================================== 8 9 At runtime, Django looks for translations by following this algorithm: 10 11 * First, it looks for a ``locale`` directory in the application directory 12 of the view that's being called. If it finds a translation for the 13 selected language, the translation will be installed. 14 * Next, it looks for a ``locale`` directory in the project directory. If it 15 finds a translation, the translation will be installed. 16 * Finally, it checks the Django-provided base translation in 17 ``django/conf/locale``. 18 19 This way, you can write applications that include their own translations, and 20 you can override base translations in your project path. Or, you can just build 21 a big project out of several apps and put all translations into one big project 22 message file. The choice is yours. 23 24 .. note:: 25 26 If you're using manually configured settings, as described in 27 :ref:`settings-without-django-settings-module`, the ``locale`` directory in 28 the project directory will not be examined, since Django loses the ability 29 to work out the location of the project directory. (Django normally uses the 30 location of the settings file to determine this, and a settings file doesn't 31 exist if you're manually configuring your settings.) 32 33 All message file repositories are structured the same way. They are: 34 35 * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` 36 * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` 37 * All paths listed in ``LOCALE_PATHS`` in your settings file are 38 searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)`` 39 * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)`` 40 41 To create message files, you use the :djadmin:`django-admin.py makemessages <makemessages>` 42 tool. You only need to be in the same directory where the ``locale/`` directory 43 is located. And you use :djadmin:`django-admin.py compilemessages <compilemessages>` 44 to produce the binary ``.mo`` files that are used by ``gettext``. Read the 45 :ref:`topics-i18n-localization` document for more details. 46 47 You can also run ``django-admin.py compilemessages --settings=path.to.settings`` 48 to make the compiler process all the directories in your :setting:`LOCALE_PATHS` 49 setting. 50 51 Application message files are a bit complicated to discover -- they need the 52 :class:`~django.middleware.locale.LocaleMiddleware`. If you don't use the 53 middleware, only the Django message files and project message files will be 54 installed and available at runtime. 55 56 Finally, you should give some thought to the structure of your translation 57 files. If your applications need to be delivered to other users and will 58 be used in other projects, you might want to use app-specific translations. 59 But using app-specific translations and project translations could produce 60 weird problems with ``makemessages``: It will traverse all directories belowthe 61 current path and so might put message IDs into the project message file that 62 are already in application message files. 63 64 The easiest way out is to store applications that are not part of the project 65 (and so carry their own translations) outside the project tree. That way, 66 ``django-admin.py makemessages`` on the project level will only translate 67 strings that are connected to your explicit project and not strings that are 68 distributed independently. -
docs/howto/index.txt
diff -r 8a4e070b280a docs/howto/index.txt
a b 20 20 deployment/index 21 21 error-reporting 22 22 initial-data 23 i18n 23 24 jython 24 25 legacy-databases 25 26 outputting-csv -
docs/internals/contributing.txt
diff -r 8a4e070b280a docs/internals/contributing.txt
a b 402 402 403 403 * Join the `Django i18n mailing list`_ and introduce yourself. 404 404 405 * Make sure you read the notes about :ref:`specialties-of-django-i18n`. 406 405 407 * Create translations using the methods described in the 406 :ref:`i18n documentation <topics-i18n>`. For this you will use the 407 ``django-admin.py makemessages`` tool. In this particular case it should 408 be run from the top-level ``django`` directory of the Django source tree. 408 :ref:`localization documentation <topics-i18n-localization>`. For this 409 you will use the ``django-admin.py makemessages`` tool. In this 410 particular case it should be run from the top-level ``django`` directory 411 of the Django source tree. 409 412 410 413 The script runs over the entire Django source tree and pulls out all 411 414 strings marked for translation. It creates (or updates) a message file in 412 the directory ``conf/locale`` (for example for ``pt -BR``, the file will be413 ``conf/locale/pt -br/LC_MESSAGES/django.po``).415 the directory ``conf/locale`` (for example for ``pt_BR``, the file will be 416 ``conf/locale/pt_BR/LC_MESSAGES/django.po``). 414 417 415 418 * Make sure that ``django-admin.py compilemessages -l <lang>`` runs without 416 419 producing any warnings. … … 419 422 ``-d djangojs`` command line option to the ``django-admin.py`` 420 423 invocations). 421 424 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. 423 430 424 431 * Open a ticket in Django's ticket system, set its ``Component`` field to 425 432 ``Translations``, and attach the patch to it. -
docs/ref/settings.txt
diff -r 8a4e070b280a docs/ref/settings.txt
a b 917 917 Default: ``()`` (Empty tuple) 918 918 919 919 A tuple of directories where Django looks for translation files. 920 See :ref:` translations-in-your-own-projects`.920 See :ref:`using-translations-in-your-own-projects`. 921 921 922 922 .. setting:: LOGIN_REDIRECT_URL 923 923 -
deleted file docs/topics/i18n.txt
diff -r 8a4e070b280a docs/topics/i18n.txt
+ - 1 .. _topics-i18n:2 3 ====================4 Internationalization5 ====================6 7 Django has full support for internationalization of text in code and8 templates, and format localization of dates and numbers. Here's how it works.9 10 Overview11 ========12 13 The goal of internationalization is to allow a single Web application to offer14 its content and functionality in multiple languages and locales.15 16 For text translation, you, the Django developer, can accomplish this goal by17 adding a minimal amount of hooks to your Python code and templates. These hooks18 are called **translation strings**. They tell Django: "This text should be19 translated into the end user's language, if a translation for this text is20 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 apps28 should be translatable.29 * It uses these hooks to translate Web apps for particular users according30 to their language preferences.31 32 For format localization, it's just necessary to set33 :setting:`USE_L10N = True <USE_L10N>` in your settings file. If34 :setting:`USE_L10N` is set to ``True``, Django will display35 numbers and dates in the format of the current locale. That includes field36 representation on templates, and allowed input formats on the admin.37 38 If you don't need internationalization in your app39 ==================================================40 41 Django's internationalization hooks are on by default, and that means there's a42 bit of i18n-related overhead in certain places of the framework. If you don't43 use internationalization, you should take the two seconds to set44 :setting:`USE_I18N = False <USE_I18N>` in your settings file. If45 :setting:`USE_I18N` is set to ``False``, then Django will make some46 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 steps52 ================================================53 54 1. Embed translation strings in your Python code and templates.55 2. Get translations for those strings, in whichever languages you want to56 support.57 3. Activate the locale middleware in your Django settings.58 59 .. admonition:: Behind the scenes60 61 Django's translation machinery uses the standard ``gettext`` module that62 comes with Python.63 64 1. How to specify translation strings65 =====================================66 67 Translation strings specify "This text should be translated." These strings can68 appear in your Python code and templates. It's your responsibility to mark69 translatable strings; the system can only translate strings it knows about.70 71 In Python code72 --------------73 74 Standard translation75 ~~~~~~~~~~~~~~~~~~~~76 77 Specify a translation string by using the function ``ugettext()``. It's78 convention to import this as a shorter alias, ``_``, to save typing.79 80 .. note::81 Python's standard library ``gettext`` module installs ``_()`` into the82 global namespace, as an alias for ``gettext()``. In Django, we have chosen83 not to follow this practice, for a couple of reasons:84 85 1. For international character set (Unicode) support, ``ugettext()`` is86 more useful than ``gettext()``. Sometimes, you should be using87 ``ugettext_lazy()`` as the default translation method for a particular88 file. Without ``_()`` in the global namespace, the developer has to89 think about which is the most appropriate translation function.90 91 2. The underscore character (``_``) is used to represent "the previous92 result" in Python's interactive shell and doctest tests. Installing a93 global ``_()`` function causes interference. Explicitly importing94 ``ugettext()`` as ``_()`` avoids this problem.95 96 .. highlightlang:: python97 98 In this example, the text ``"Welcome to my site."`` is marked as a translation99 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 is108 identical to the previous one::109 110 from django.utils.translation import ugettext111 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 previous117 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 two132 examples, is that Django's translation-string-detecting utility,133 ``django-admin.py makemessages``, won't be able to find these strings. More on134 ``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 placeholder144 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 the146 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 you150 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-op154 ~~~~~~~~~~~~~~~~~~~~~~~~155 156 Use the function ``django.utils.translation.ugettext_noop()`` to mark a string157 as a translation string without translating it. The string is later translated158 from a variable.159 160 Use this if you have constant strings that should be stored in the source161 language because they are exchanged over systems or users -- such as strings in162 a database -- but should be translated at the last possible point in time, such163 as when the string is presented to the user.164 165 .. _lazy-translations:166 167 Lazy translation168 ~~~~~~~~~~~~~~~~169 170 Use the function ``django.utils.translation.ugettext_lazy()`` to translate171 strings lazily -- when the value is accessed rather than when the172 ``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_lazy177 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 string183 is used in a string context, such as template rendering on the Django admin184 site.185 186 The result of a ``ugettext_lazy()`` call can be used wherever you would use a187 unicode string (an object with type ``unicode``) in Python. If you try to use188 it where a bytestring (a ``str`` object) is expected, things will not work as189 expected, since a ``ugettext_lazy()`` object doesn't know how to convert190 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 object197 # 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 ``"hello201 <django.utils.functional...>"``, you have tried to insert the result of202 ``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 as205 ``_`` (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, they214 won't be translated in the admin interface). This means writing explicit215 ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class,216 though, rather than relying on Django's default determination of217 ``verbose_name`` and ``verbose_name_plural`` by looking at the model's class218 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 Pluralization229 ~~~~~~~~~~~~~230 231 Use the function ``django.utils.translation.ungettext()`` to specify pluralized232 messages.233 234 ``ungettext`` takes three arguments: the singular translation string, the plural235 translation string and the number of objects.236 237 This function is useful when your need you Django application to be localizable238 to languages where the number and complexity of `plural forms239 <http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is240 greater than the two forms used in English ('object' for the singular and241 'objects' for all the cases where ``count`` is different from zero, irrespective242 of its value.)243 244 For example::245 246 from django.utils.translation import ungettext247 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 as254 the ``count`` variable.255 256 Lets see a slightly more complex usage example::257 258 from django.utils.translation import ungettext259 260 count = Report.objects.count()261 if count == 1:262 name = Report._meta.verbose_name263 else:264 name = Report._meta.verbose_name_plural265 266 text = ungettext(267 'There is %(count)d %(name)s available.',268 'There are %(count)d %(name)s available.',269 count270 ) % {271 'count': count,272 'name': name273 }274 275 Here we reuse localizable, hopefully already translated literals (contained in276 the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for277 other parts of the sentence so all of it is consistently based on the278 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 every285 extrapolated variable included in the literal. In the example above note how286 we used the ``name`` Python variable in both translation strings. This287 example would fail::288 289 from django.utils.translation import ungettext290 from myapp.models import Report291 292 count = Report.objects.count()293 d = {294 'count': count,295 'name': Report._meta.verbose_name296 'plural_name': Report._meta.verbose_name_plural297 }298 text = ungettext(299 'There is %(count)d %(name)s available.',300 'There are %(count)d %(plural_name)s available.',301 count302 ) % d303 304 You would get a ``a format specification for argument 'name', as in305 'msgstr[0]', doesn't exist in 'msgid'`` error when running306 ``django-admin.py compilemessages`` or a ``KeyError`` Python exception at307 runtime.308 309 In template code310 ----------------311 312 .. highlightlang:: html+django313 314 Translations in :ref:`Django templates <topics-templates>` uses two template315 tags and a slightly different syntax than in Python code. To give your template316 access to these tags, put ``{% load i18n %}`` toward the top of your template.317 318 The ``{% trans %}`` template tag translates either a constant string319 (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 the325 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 ``{% trans333 %}``. If your translations require strings with variables (placeholders), use334 ``{% blocktrans %}``::335 336 {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}337 338 To translate a template expression -- say, using template filters -- you need339 to bind the expression to a local variable for use within the translation340 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 the354 ``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and355 ``{% 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 local364 variables apart from the counter value that selects the translated literal to be365 used, have in mind that the ``blocktrans`` construct is internally converted366 to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext367 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 the372 language code and the second is the language name (translated into the373 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 a380 right-to-left language, e.g.: Hebrew, Arabic. If False it's a381 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 with385 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 accepts394 constant strings. In those cases, just use ``_()`` syntax to specify a395 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-translated400 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 string404 ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The405 translated string will need to contain the comma so that the filter406 parsing code knows how to split up the arguments. For example, a German407 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 objects413 -------------------------------------414 415 .. highlightlang:: python416 417 Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models418 and utility functions is a common operation. When you're working with these419 objects elsewhere in your code, you should ensure that you don't accidentally420 convert them to strings, because they should be converted as late as possible421 (so that the correct locale is in effect). This necessitates the use of a422 couple of helper functions.423 424 Joining strings: string_concat()425 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~426 427 Standard Python string joins (``''.join([...])``) will not work on lists428 containing lazy translation objects. Instead, you can use429 ``django.utils.translation.string_concat()``, which creates a lazy object that430 concatenates its contents *and* converts them to strings only when the result431 is included in a string. For example::432 433 from django.utils.translation import string_concat434 ...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 to440 strings when ``result`` itself is used in a string (usually at template441 rendering time).442 443 The allow_lazy() decorator444 ~~~~~~~~~~~~~~~~~~~~~~~~~~445 446 Django offers many utility functions (particularly in ``django.utils``) that447 take a string as their first argument and do something to that string. These448 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'll451 face the problem of what to do when the first argument is a lazy translation452 object. You don't want to convert it to a string immediately, because you might453 be using this function outside of a view (and hence the current thread's locale454 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 lazy458 translation as the first argument, the function evaluation is delayed until it459 needs to be converted to a string.460 461 For example::462 463 from django.utils.functional import allow_lazy464 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 the472 original function can return. Usually, it's enough to include ``unicode`` here473 and ensure that your function returns only Unicode strings.474 475 Using this decorator means you can write your function and assume that the476 input is a proper string, then add support for lazy translation objects at the477 end.478 479 .. _how-to-create-language-files:480 481 2. How to create language files482 ===============================483 484 Once you've tagged your strings for later translation, you need to write (or485 obtain) the language translations themselves. Here's how that works.486 487 .. admonition:: Locale restrictions488 489 Django does not support localizing your application into a locale for490 which Django itself has not been translated. In this case, it will ignore491 your translation files. If you were to try this and Django supported it,492 you would inevitably see a mixture of translated strings (from your493 application) and English strings (from Django itself). If you want to494 support a locale for your application that is not already part of495 Django, you'll need to make at least a minimal translation of the Django496 core. See the relevant :ref:`LocaleMiddleware note<locale-middleware-notes>`497 for more details.498 499 Message files500 -------------501 502 The first step is to create a **message file** for a new language. A message503 file is a plain-text file, representing a single language, that contains all504 available translation strings and how they should be represented in the given505 language. Message files have a ``.po`` file extension.506 507 Django comes with a tool, ``django-admin.py makemessages``, that automates the508 creation and upkeep of these files.509 510 .. admonition:: A note to Django veterans511 512 The old tool ``bin/make-messages.py`` has been moved to the command513 ``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 de518 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's521 ``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 one528 that is linked-to via ``$PYTHONPATH`` or is located somewhere on that529 path). This is only relevant when you are creating a translation for530 Django itself, see :ref:`contributing-translations`.531 532 The script runs over your project source tree or your application source tree533 and pulls out all strings marked for translation. It creates (or updates) a534 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 the538 ``.html`` file extension. In case you want to override that default, use the539 ``--extension`` or ``-e`` option to specify the file extensions to examine::540 541 django-admin.py makemessages -l de -e txt542 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 xml547 548 When `creating JavaScript translation catalogs`_ you need to use the special549 'djangojs' domain, **not** ``-e js``.550 551 .. _create a JavaScript translation catalog: `Creating JavaScript translation catalogs`_552 553 .. admonition:: No gettext?554 555 If you don't have the ``gettext`` utilities installed, ``django-admin.py556 makemessages`` will create empty files. If that's the case, either install557 the ``gettext`` utilities or just copy the English message file558 (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting559 point; it's just an empty translation file.560 561 .. admonition:: Working on Windows?562 563 If you're using Windows and need to install the GNU gettext utilities so564 ``django-admin makemessages`` works see `gettext on Windows`_ for more565 information.566 567 The format of ``.po`` files is straightforward. Each ``.po`` file contains a568 small bit of metadata, such as the translation maintainer's contact569 information, but the bulk of the file is a list of **messages** -- simple570 mappings between translation strings and the actual translated text for the571 particular language.572 573 For example, if your Django app contained a translation string for the text574 ``"Welcome to my site."``, like so::575 576 _("Welcome to my site.")577 578 ...then ``django-admin.py makemessages`` will have created a ``.po`` file579 containing the following snippet -- a message::580 581 #: path/to/python/module.py:23582 msgid "Welcome to my site."583 msgstr ""584 585 A quick explanation:586 587 * ``msgid`` is the translation string, which appears in the source. Don't588 change it.589 * ``msgstr`` is where you put the language-specific translation. It starts590 out empty, so it's your responsibility to change it. Make sure you keep591 the quotes around your translation.592 * As a convenience, each message includes, in the form of a comment line593 prefixed with ``#`` and located above the ``msgid`` line, the filename and594 line number from which the translation string was gleaned.595 596 Long messages are a special case. There, the first string directly after the597 ``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be598 written over the next few lines as one string per line. Those strings are599 directly concatenated. Don't forget trailing spaces within the strings;600 otherwise, they'll be tacked together without whitespace!601 602 .. admonition:: Mind your charset603 604 When creating a PO file with your favorite text editor, first edit605 the charset line (search for ``"CHARSET"``) and set it to the charset606 you'll be using to edit the content. Due to the way the ``gettext`` tools607 work internally and because we want to allow non-ASCII source strings in608 Django's core and your applications, you **must** use UTF-8 as the encoding609 for your PO file. This means that everybody will be using the same610 encoding, which is important when Django processes the PO files.611 612 To reexamine all source code and templates for new translation strings and613 update all message files for **all** languages, run this::614 615 django-admin.py makemessages -a616 617 Compiling message files618 -----------------------619 620 After you create your message file -- and each time you make changes to it --621 you'll need to compile it into a more efficient form, for use by ``gettext``.622 Do this with the ``django-admin.py compilemessages`` utility.623 624 This tool runs over all available ``.po`` files and creates ``.mo`` files, which625 are binary files optimized for use by ``gettext``. In the same directory from626 which you ran ``django-admin.py makemessages``, run ``django-admin.py627 compilemessages`` like this::628 629 django-admin.py compilemessages630 631 That's it. Your translations are ready for use.632 633 .. admonition:: A note to Django veterans634 635 The old tool ``bin/compile-messages.py`` has been moved to the command636 ``django-admin.py compilemessages`` to provide consistency throughout637 Django.638 639 .. admonition:: Working on Windows?640 641 If you're using Windows and need to install the GNU gettext utilities so642 ``django-admin compilemessages`` works see `gettext on Windows`_ for more643 information.644 645 .. _how-django-discovers-language-preference:646 647 3. How Django discovers language preference648 ===========================================649 650 Once you've prepared your translations -- or, if you just want to use the651 translations that come with Django -- you'll just need to activate translation652 for your app.653 654 Behind the scenes, Django has a very flexible model of deciding which language655 should be used -- installation-wide, for a particular user, or both.656 657 To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`.658 Django uses this language as the default translation -- the final attempt if no659 other translator finds a translation.660 661 If all you want to do is run Django with your native language, and a language662 file is available for your language, all you need to do is set663 ``LANGUAGE_CODE``.664 665 If you want to let each individual user specify which language he or she666 prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language667 selection based on data from the request. It customizes content for each user.668 669 To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'``670 to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you671 should follow these guidelines:672 673 * Make sure it's one of the first middlewares installed.674 * It should come after ``SessionMiddleware``, because ``LocaleMiddleware``675 makes use of session data.676 * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it.677 678 For example, your ``MIDDLEWARE_CLASSES`` might look like this::679 680 MIDDLEWARE_CLASSES = (681 'django.contrib.sessions.middleware.SessionMiddleware',682 'django.middleware.locale.LocaleMiddleware',683 'django.middleware.common.CommonMiddleware',684 )685 686 (For more on middleware, see the :ref:`middleware documentation687 <topics-http-middleware>`.)688 689 ``LocaleMiddleware`` tries to determine the user's language preference by690 following this algorithm:691 692 * First, it looks for a ``django_language`` key in the current user's693 session.694 695 * Failing that, it looks for a cookie.696 697 .. versionchanged:: 1.0698 699 In Django version 0.96 and before, the cookie's name is hard-coded to700 ``django_language``. In Django 1,0, The cookie name is set by the701 ``LANGUAGE_COOKIE_NAME`` setting. (The default name is702 ``django_language``.)703 704 * Failing that, it looks at the ``Accept-Language`` HTTP header. This705 header is sent by your browser and tells the server which language(s) you706 prefer, in order by priority. Django tries each language in the header707 until it finds one with available translations.708 709 * Failing that, it uses the global ``LANGUAGE_CODE`` setting.710 711 .. _locale-middleware-notes:712 713 Notes:714 715 * In each of these places, the language preference is expected to be in the716 standard language format, as a string. For example, Brazilian Portuguese717 is ``pt-br``.718 719 * If a base language is available but the sublanguage specified is not,720 Django uses the base language. For example, if a user specifies ``de-at``721 (Austrian German) but Django only has ``de`` available, Django uses722 ``de``.723 724 * Only languages listed in the :setting:`LANGUAGES` setting can be selected.725 If you want to restrict the language selection to a subset of provided726 languages (because your application doesn't provide all those languages),727 set ``LANGUAGES`` to a list of languages. For example::728 729 LANGUAGES = (730 ('de', _('German')),731 ('en', _('English')),732 )733 734 This example restricts languages that are available for automatic735 selection to German and English (and any sublanguage, like de-ch or736 en-us).737 738 .. _LANGUAGES setting: ../settings/#languages739 740 * If you define a custom ``LANGUAGES`` setting, as explained in the741 previous bullet, it's OK to mark the languages as translation strings742 -- but use a "dummy" ``ugettext()`` function, not the one in743 ``django.utils.translation``. You should *never* import744 ``django.utils.translation`` from within your settings file, because that745 module in itself depends on the settings, and that would cause a circular746 import.747 748 The solution is to use a "dummy" ``ugettext()`` function. Here's a sample749 settings file::750 751 ugettext = lambda s: s752 753 LANGUAGES = (754 ('de', ugettext('German')),755 ('en', ugettext('English')),756 )757 758 With this arrangement, ``django-admin.py makemessages`` will still find759 and mark these strings for translation, but the translation won't happen760 at runtime -- so you'll have to remember to wrap the languages in the761 *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime.762 763 * The ``LocaleMiddleware`` can only select languages for which there is a764 Django-provided base translation. If you want to provide translations765 for your application that aren't already in the set of translations766 in Django's source tree, you'll want to provide at least basic767 translations for that language. For example, Django uses technical768 message IDs to translate date formats and time formats -- so you will769 need at least those translations for the system to work correctly.770 771 A good starting point is to copy the English ``.po`` file and to772 translate at least the technical messages -- maybe the validation773 messages, too.774 775 Technical message IDs are easily recognized; they're all upper case. You776 don't translate the message ID as with other messages, you provide the777 correct local variant on the provided English value. For example, with778 ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), this would779 be the format string that you want to use in your language. The format780 is identical to the format strings used by the ``now`` template tag.781 782 Once ``LocaleMiddleware`` determines the user's preference, it makes this783 preference available as ``request.LANGUAGE_CODE`` for each784 :class:`~django.http.HttpRequest`. Feel free to read this value in your view785 code. Here's a simple example::786 787 def hello_world(request, count):788 if request.LANGUAGE_CODE == 'de-at':789 return HttpResponse("You prefer to read Austrian German.")790 else:791 return HttpResponse("You prefer to read another language.")792 793 Note that, with static (middleware-less) translation, the language is in794 ``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's795 in ``request.LANGUAGE_CODE``.796 797 .. _settings file: ../settings/798 .. _middleware documentation: ../middleware/799 .. _session: ../sessions/800 .. _request object: ../request_response/#httprequest-objects801 802 .. _translations-in-your-own-projects:803 804 Using translations in your own projects805 =======================================806 807 Django looks for translations by following this algorithm:808 809 * First, it looks for a ``locale`` directory in the application directory810 of the view that's being called. If it finds a translation for the811 selected language, the translation will be installed.812 * Next, it looks for a ``locale`` directory in the project directory. If it813 finds a translation, the translation will be installed.814 * Finally, it checks the Django-provided base translation in815 ``django/conf/locale``.816 817 This way, you can write applications that include their own translations, and818 you can override base translations in your project path. Or, you can just build819 a big project out of several apps and put all translations into one big project820 message file. The choice is yours.821 822 .. note::823 824 If you're using manually configured settings, as described825 :ref:`settings-without-django-settings-module`, the ``locale`` directory in826 the project directory will not be examined, since Django loses the ability827 to work out the location of the project directory. (Django normally uses the828 location of the settings file to determine this, and a settings file doesn't829 exist if you're manually configuring your settings.)830 831 All message file repositories are structured the same way. They are:832 833 * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``834 * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``835 * All paths listed in ``LOCALE_PATHS`` in your settings file are836 searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)``837 * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``838 839 To create message files, you use the same ``django-admin.py makemessages``840 tool as with the Django message files. You only need to be in the right place841 -- in the directory where either the ``conf/locale`` (in case of the source842 tree) or the ``locale/`` (in case of app messages or project messages)843 directory are located. And you use the same ``django-admin.py compilemessages``844 to produce the binary ``django.mo`` files that are used by ``gettext``.845 846 You can also run ``django-admin.py compilemessages --settings=path.to.settings``847 to make the compiler process all the directories in your ``LOCALE_PATHS``848 setting.849 850 Application message files are a bit complicated to discover -- they need the851 ``LocaleMiddleware``. If you don't use the middleware, only the Django message852 files and project message files will be processed.853 854 Finally, you should give some thought to the structure of your translation855 files. If your applications need to be delivered to other users and will856 be used in other projects, you might want to use app-specific translations.857 But using app-specific translations and project translations could produce858 weird problems with ``makemessages``: ``makemessages`` will traverse all859 directories below the current path and so might put message IDs into the860 project message file that are already in application message files.861 862 The easiest way out is to store applications that are not part of the project863 (and so carry their own translations) outside the project tree. That way,864 ``django-admin.py makemessages`` on the project level will only translate865 strings that are connected to your explicit project and not strings that are866 distributed independently.867 868 The ``set_language`` redirect view869 ==================================870 871 As a convenience, Django comes with a view, ``django.views.i18n.set_language``,872 that sets a user's language preference and redirects back to the previous page.873 874 Activate this view by adding the following line to your URLconf::875 876 (r'^i18n/', include('django.conf.urls.i18n')),877 878 (Note that this example makes the view available at ``/i18n/setlang/``.)879 880 The view expects to be called via the ``POST`` method, with a ``language``881 parameter set in request. If session support is enabled, the view882 saves the language choice in the user's session. Otherwise, it saves the883 language choice in a cookie that is by default named ``django_language``.884 (The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.)885 886 After setting the language choice, Django redirects the user, following this887 algorithm:888 889 * Django looks for a ``next`` parameter in the ``POST`` data.890 * If that doesn't exist, or is empty, Django tries the URL in the891 ``Referrer`` header.892 * If that's empty -- say, if a user's browser suppresses that header --893 then the user will be redirected to ``/`` (the site root) as a fallback.894 895 Here's example HTML template code:896 897 .. code-block:: html+django898 899 <form action="/i18n/setlang/" method="post">900 <input name="next" type="hidden" value="/next/page/" />901 <select name="language">902 {% for lang in LANGUAGES %}903 <option value="{{ lang.0 }}">{{ lang.1 }}</option>904 {% endfor %}905 </select>906 <input type="submit" value="Go" />907 </form>908 909 Translations and JavaScript910 ===========================911 912 Adding translations to JavaScript poses some problems:913 914 * JavaScript code doesn't have access to a ``gettext`` implementation.915 916 * JavaScript code doesn't have access to .po or .mo files; they need to be917 delivered by the server.918 919 * The translation catalogs for JavaScript should be kept as small as920 possible.921 922 Django provides an integrated solution for these problems: It passes the923 translations into JavaScript, so you can call ``gettext``, etc., from within924 JavaScript.925 926 The ``javascript_catalog`` view927 -------------------------------928 929 The main solution to these problems is the ``javascript_catalog`` view, which930 sends out a JavaScript code library with functions that mimic the ``gettext``931 interface, plus an array of translation strings. Those translation strings are932 taken from the application, project or Django core, according to what you933 specify in either the info_dict or the URL.934 935 You hook it up like this::936 937 js_info_dict = {938 'packages': ('your.app.package',),939 }940 941 urlpatterns = patterns('',942 (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),943 )944 945 Each string in ``packages`` should be in Python dotted-package syntax (the946 same format as the strings in ``INSTALLED_APPS``) and should refer to a package947 that contains a ``locale`` directory. If you specify multiple packages, all948 those catalogs are merged into one catalog. This is useful if you have949 JavaScript that uses strings from different applications.950 951 You can make the view dynamic by putting the packages into the URL pattern::952 953 urlpatterns = patterns('',954 (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),955 )956 957 With this, you specify the packages as a list of package names delimited by '+'958 signs in the URL. This is especially useful if your pages use code from959 different apps and this changes often and you don't want to pull in one big960 catalog file. As a security measure, these values can only be either961 ``django.conf`` or any package from the ``INSTALLED_APPS`` setting.962 963 Using the JavaScript translation catalog964 ----------------------------------------965 966 To use the catalog, just pull in the dynamically generated script like this::967 968 <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script>969 970 This uses reverse URL lookup to find the URL of the JavaScript catalog view.971 When the catalog is loaded, your JavaScript code can use the standard972 ``gettext`` interface to access it::973 974 document.write(gettext('this is to be translated'));975 976 There is also an ``ngettext`` interface::977 978 var object_cnt = 1 // or 0, or 2, or 3, ...979 s = ngettext('literal for the singular case',980 'literal for the plural case', object_cnt);981 982 and even a string interpolation function::983 984 function interpolate(fmt, obj, named);985 986 The interpolation syntax is borrowed from Python, so the ``interpolate``987 function supports both positional and named interpolation:988 989 * Positional interpolation: ``obj`` contains a JavaScript Array object990 whose elements values are then sequentially interpolated in their991 corresponding ``fmt`` placeholders in the same order they appear.992 For example::993 994 fmts = ngettext('There is %s object. Remaining: %s',995 'There are %s objects. Remaining: %s', 11);996 s = interpolate(fmts, [11, 20]);997 // s is 'There are 11 objects. Remaining: 20'998 999 * Named interpolation: This mode is selected by passing the optional1000 boolean ``named`` parameter as true. ``obj`` contains a JavaScript1001 object or associative array. For example::1002 1003 d = {1004 count: 101005 total: 501006 };1007 1008 fmts = ngettext('Total: %(total)s, there is %(count)s object',1009 'there are %(count)s of a total of %(total)s objects', d.count);1010 s = interpolate(fmts, d, true);1011 1012 You shouldn't go over the top with string interpolation, though: this is still1013 JavaScript, so the code has to make repeated regular-expression substitutions.1014 This isn't as fast as string interpolation in Python, so keep it to those1015 cases where you really need it (for example, in conjunction with ``ngettext``1016 to produce proper pluralizations).1017 1018 Creating JavaScript translation catalogs1019 ----------------------------------------1020 1021 You create and update the translation catalogs the same way as the other1022 1023 Django translation catalogs -- with the django-admin.py makemessages tool. The1024 only difference is you need to provide a ``-d djangojs`` parameter, like this::1025 1026 django-admin.py makemessages -d djangojs -l de1027 1028 This would create or update the translation catalog for JavaScript for German.1029 After updating translation catalogs, just run ``django-admin.py compilemessages``1030 the same way as you do with normal Django translation catalogs.1031 1032 Specialties of Django translation1033 ==================================1034 1035 If you know ``gettext``, you might note these specialties in the way Django1036 does translation:1037 1038 * The string domain is ``django`` or ``djangojs``. This string domain is1039 used to differentiate between different programs that store their data1040 in a common message-file library (usually ``/usr/share/locale/``). The1041 ``django`` domain is used for python and template translation strings1042 and is loaded into the global translation catalogs. The ``djangojs``1043 domain is only used for JavaScript translation catalogs to make sure1044 that those are as small as possible.1045 * Django doesn't use ``xgettext`` alone. It uses Python wrappers around1046 ``xgettext`` and ``msgfmt``. This is mostly for convenience.1047 1048 ``gettext`` on Windows1049 ======================1050 1051 This is only needed for people who either want to extract message IDs or compile1052 message files (``.po``). Translation work itself just involves editing existing1053 files of this type, but if you want to create your own message files, or want to1054 test or compile a changed message file, you will need the ``gettext`` utilities:1055 1056 * Download the following zip files from the GNOME servers1057 http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one1058 of its mirrors_1059 1060 * ``gettext-runtime-X.zip``1061 * ``gettext-tools-X.zip``1062 1063 ``X`` is the version number, we recomend using ``0.15`` or higher.1064 1065 * Extract the contents of the ``bin\`` directories in both files to the1066 same folder on your system (i.e. ``C:\Program Files\gettext-utils``)1067 1068 * Update the system PATH:1069 1070 * ``Control Panel > System > Advanced > Environment Variables``1071 * In the ``System variables`` list, click ``Path``, click ``Edit``1072 * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the1073 ``Variable value`` field1074 1075 .. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS1076 1077 You may also use ``gettext`` binaries you have obtained elsewhere, so long as1078 the ``xgettext --version`` command works properly. Some version 0.14.4 binaries1079 have been found to not support this command. Do not attempt to use Django1080 translation utilities with a ``gettext`` package if the command ``xgettext1081 --version`` entered at a Windows command prompt causes a popup window saying1082 "xgettext.exe has generated errors and will be closed by Windows".1083 1084 .. _format-localization:1085 1086 Format localization1087 ===================1088 1089 Django's formatting system is disabled by default. To enable it, it's necessay1090 to set :setting:`USE_L10N = True <USE_L10N>` in your settings file.1091 1092 When using Django's formatting system, dates and numbers on templates will be1093 displayed using the format specified for the current locale. Two users1094 accessing the same content, but in different language, will see date and1095 number fields formatted in different ways, depending on the format for their1096 current locale.1097 1098 Django will also use localized formats when parsing data in forms. That means1099 Django uses different formats for different locales when guessing the format1100 used by the user when inputting data on forms. Note that Django uses different1101 formats for displaying data, and for parsing it.1102 1103 Creating custom format files1104 ----------------------------1105 1106 Django provides format definitions for many locales, but sometimes you might1107 want to create your own, because a format files doesn't exist for your locale,1108 or because you want to overwrite some of the values.1109 1110 To use custom formats, first thing to do, is to specify the path where you'll1111 place format files. To do that, just set your :setting:`FORMAT_MODULE_PATH`1112 setting to the the path (in the format ``'foo.bar.baz``) where format files1113 will exists.1114 1115 Files are not placed directly in this directory, but in a directory named as1116 the locale, and must be named ``formats.py``.1117 1118 To customize the English formats, a structure like this would be needed::1119 1120 mysite/1121 formats/1122 __init__.py1123 en/1124 __init__.py1125 formats.py1126 1127 where :file:`formats.py` contains custom format definitions. For example::1128 1129 THOUSAND_SEPARATOR = ' '1130 1131 to use a space as a thousand separator, instead of the default for English,1132 a comma. -
new file docs/topics/i18n/deployment.txt
diff -r 8a4e070b280a docs/topics/i18n/deployment.txt
- + 1 .. _topics-i18n-deployment: 2 3 ============================================= 4 Deployment of Django application translations 5 ============================================= 6 7 If you don't need internationalization in your app 8 ================================================== 9 10 Django's internationalization hooks are on by default, and that means there's a 11 bit of i18n-related overhead in certain places of the framework. If you don't 12 use internationalization, you should take the two seconds to set 13 :setting:`USE_I18N = False <USE_I18N>` in your settings file. If 14 :setting:`USE_I18N` is set to ``False``, then Django will make some 15 optimizations so as not to load the internationalization machinery. 16 17 You'll probably also want to remove ``'django.core.context_processors.i18n'`` 18 from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting. 19 20 .. 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 32 If you do need internationalization 33 =================================== 34 35 .. _how-django-discovers-language-preference: 36 37 How Django discovers language preference 38 ---------------------------------------- 39 40 Once you've prepared your translations -- or, if you just want to use the 41 translations that come with Django -- you'll just need to activate translation 42 for your app. 43 44 Behind the scenes, Django has a very flexible model of deciding which language 45 should be used -- installation-wide, for a particular user, or both. 46 47 To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`. 48 Django uses this language as the default translation -- the final attempt if no 49 other translator finds a translation. 50 51 If all you want to do is run Django with your native language, and a language 52 file is available for it, all you need to do is set ``LANGUAGE_CODE``. 53 54 If you want to let each individual user specify which language he or she 55 prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language 56 selection based on data from the request. It customizes content for each user. 57 58 To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'`` 59 to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you 60 should 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 67 For 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 79 following 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 102 Notes: 103 104 * In each of these places, the language preference is expected to be in the 105 standard language format, as a string. For example, Brazilian Portuguese 106 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 159 Once ``LocaleMiddleware`` determines the user's preference, it makes this 160 preference available as ``request.LANGUAGE_CODE`` for each 161 :class:`~django.http.HttpRequest`. Feel free to read this value in your view 162 code. 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 170 Note that, with static (middleware-less) translation, the language is in 171 ``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's 172 in ``request.LANGUAGE_CODE``. 173 174 .. _settings file: ../settings/ 175 .. _middleware documentation: ../middleware/ 176 .. _session: ../sessions/ 177 .. _request object: ../request_response/#httprequest-objects 178 179 How Django discovers translations 180 --------------------------------- 181 182 As described in :ref:`using-translations-in-your-own-projects`, 183 at 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``. -
new file docs/topics/i18n/index.txt
diff -r 8a4e070b280a docs/topics/i18n/index.txt
- + 1 .. _topics-i18n: 2 3 ===================================== 4 Internationalization and localization 5 ===================================== 6 7 Overview 8 ======== 9 10 Django has full support for internationalization of text in code and 11 templates, and format localization of dates and numbers. Here's how it works. 12 13 Essentially, 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 20 The complete process can be seen as divided in three stages. It is also possible 21 to identify an identical number of roles with very well defined responsabilities 22 associated with each of these tasks (although it's perfectly normal if you 23 find 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 40 For more general information about the topic, see the `GNU gettext documentation`_ 41 and 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 46 .. _specialties-of-django-i18n: 47 48 Specialties of Django translation 49 ================================== 50 51 Django's translation machinery uses the standard ``gettext`` module that comes 52 with Python. If you know ``gettext``, you might note these specialties in the 53 way Django does translation: 54 55 * The string domain is ``django`` or ``djangojs``. This string domain is 56 used to differentiate between different programs that store their data 57 in a common message-file library (usually ``/usr/share/locale/``). The 58 ``django`` domain is used for python and template translation strings 59 and is loaded into the global translation catalogs. The ``djangojs`` 60 domain is only used for JavaScript translation catalogs to make sure 61 that those are as small as possible. 62 * Django doesn't use ``xgettext`` alone. It uses Python wrappers around 63 ``xgettext`` and ``msgfmt``. This is mostly for convenience. 64 65 .. _technical-messages: 66 67 Django technical message IDs 68 ---------------------------- 69 70 .. versionchanged:: 1.2 71 Starting with Django 1.2, technical message IDs are being replaced by :ref:`format-localization` 72 73 Django uses **technical message IDs** to translate date formats and time 74 formats. Technical message IDs are message strings and can be easily recognized; 75 they're all upper case. You don't translate the message ID as with other message 76 strings, you provide the correct local variant on the provided English value. 77 The format is identical to the format strings used by the ``now`` template tag. 78 79 For example, with ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), 80 this would be the format string that you want to use in your language. A Django 81 contributor localizing it to Spanish probably would provide a ``"j N Y P"`` 82 "translation" for it in the relevant ``django.po`` file:: 83 84 msgid "DATETIME_FORMAT" 85 msgstr "j N Y P" -
new file docs/topics/i18n/internationalization.txt
diff -r 8a4e070b280a docs/topics/i18n/internationalization.txt
- + 1 .. _topics-i18n-internationalization: 2 3 ==================== 4 Internationalization 5 ==================== 6 7 Overview 8 ======== 9 10 The goal of internationalization is to allow a single Web application to offer 11 its content and functionality in multiple languages and locales. 12 13 For text translations, you, the Django developer, can accomplish this goal by 14 adding a minimal amount of hooks to your Python and templates. These hooks 15 are called **translation strings**. They tell Django: "This text should be 16 translated into the end user's language, if a translation for this text is 17 available in that language." It's your responsibility to mark translatable 18 strings; the system can only translate strings it knows about. 19 20 Django takes care of using these hooks to translate Web apps, on the fly, 21 according to users' language preferences. 22 23 Specifying translation strings: In Python code 24 ============================================== 25 26 Standard translation 27 -------------------- 28 29 Specify a translation string by using the function ``ugettext()``. It's 30 convention to import this as a shorter alias, ``_``, to save typing. 31 32 .. note:: 33 Python's standard library ``gettext`` module installs ``_()`` into the 34 global namespace, as an alias for ``gettext()``. In Django, we have chosen 35 not to follow this practice, for a couple of reasons: 36 37 1. For international character set (Unicode) support, ``ugettext()`` is 38 more useful than ``gettext()``. Sometimes, you should be using 39 ``ugettext_lazy()`` as the default translation method for a particular 40 file. Without ``_()`` in the global namespace, the developer has to 41 think about which is the most appropriate translation function. 42 43 2. The underscore character (``_``) is used to represent "the previous 44 result" in Python's interactive shell and doctest tests. Installing a 45 global ``_()`` function causes interference. Explicitly importing 46 ``ugettext()`` as ``_()`` avoids this problem. 47 48 .. highlightlang:: python 49 50 In this example, the text ``"Welcome to my site."`` is marked as a translation 51 string:: 52 53 from django.utils.translation import ugettext as _ 54 55 def my_view(request): 56 output = _("Welcome to my site.") 57 return HttpResponse(output) 58 59 Obviously, you could code this without using the alias. This example is 60 identical to the previous one:: 61 62 from django.utils.translation import ugettext 63 64 def my_view(request): 65 output = ugettext("Welcome to my site.") 66 return HttpResponse(output) 67 68 Translation works on computed values. This example is identical to the previous 69 two:: 70 71 def my_view(request): 72 words = ['Welcome', 'to', 'my', 'site.'] 73 output = _(' '.join(words)) 74 return HttpResponse(output) 75 76 Translation works on variables. Again, here's an identical example:: 77 78 def my_view(request): 79 sentence = 'Welcome to my site.' 80 output = _(sentence) 81 return HttpResponse(output) 82 83 (The caveat with using variables or computed values, as in the previous two 84 examples, is that Django's translation-string-detecting utility, 85 ``django-admin.py makemessages``, won't be able to find these strings. More on 86 ``makemessages`` later.) 87 88 The strings you pass to ``_()`` or ``ugettext()`` can take placeholders, 89 specified with Python's standard named-string interpolation syntax. Example:: 90 91 def my_view(request, m, d): 92 output = _('Today is %(month)s, %(day)s.') % {'month': m, 'day': d} 93 return HttpResponse(output) 94 95 This technique lets language-specific translations reorder the placeholder 96 text. For example, an English translation may be ``"Today is November, 26."``, 97 while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the 98 placeholders (the month and the day) with their positions swapped. 99 100 For this reason, you should use named-string interpolation (e.g., ``%(day)s``) 101 instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you 102 have more than a single parameter. If you used positional interpolation, 103 translations wouldn't be able to reorder placeholder text. 104 105 Marking strings as no-op 106 ------------------------ 107 108 Use the function ``django.utils.translation.ugettext_noop()`` to mark a string 109 as a translation string without translating it. The string is later translated 110 from a variable. 111 112 Use this if you have constant strings that should be stored in the source 113 language because they are exchanged over systems or users -- such as strings in 114 a database -- but should be translated at the last possible point in time, such 115 as when the string is presented to the user. 116 117 Pluralization 118 ------------- 119 120 Use the function ``django.utils.translation.ungettext()`` to specify pluralized 121 messages. 122 123 ``ungettext`` takes three arguments: the singular translation string, the plural 124 translation string and the number of objects. 125 126 This function is useful when your need you Django application to be localizable 127 to languages where the number and complexity of `plural forms 128 <http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is 129 greater than the two forms used in English ('object' for the singular and 130 'objects' for all the cases where ``count`` is different from zero, irrespective 131 of its value.) 132 133 For example:: 134 135 from django.utils.translation import ungettext 136 def hello_world(request, count): 137 page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % { 138 'count': count, 139 } 140 return HttpResponse(page) 141 142 In this example the number of objects is passed to the translation languages as 143 the ``count`` variable. 144 145 Lets see a slightly more complex usage example:: 146 147 from django.utils.translation import ungettext 148 149 count = Report.objects.count() 150 if count == 1: 151 name = Report._meta.verbose_name 152 else: 153 name = Report._meta.verbose_name_plural 154 155 text = ungettext( 156 'There is %(count)d %(name)s available.', 157 'There are %(count)d %(name)s available.', 158 count 159 ) % { 160 'count': count, 161 'name': name 162 } 163 164 Here we reuse localizable, hopefully already translated literals (contained in 165 the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for 166 other parts of the sentence so all of it is consistently based on the 167 cardinality of the elements at play. 168 169 .. _pluralization-var-notes: 170 171 .. note:: 172 173 When using this technique, make sure you use a single name for every 174 extrapolated variable included in the literal. In the example above note how 175 we used the ``name`` Python variable in both translation strings. This 176 example would fail:: 177 178 from django.utils.translation import ungettext 179 from myapp.models import Report 180 181 count = Report.objects.count() 182 d = { 183 'count': count, 184 'name': Report._meta.verbose_name 185 'plural_name': Report._meta.verbose_name_plural 186 } 187 text = ungettext( 188 'There is %(count)d %(name)s available.', 189 'There are %(count)d %(plural_name)s available.', 190 count 191 ) % d 192 193 You would get a ``a format specification for argument 'name', as in 194 'msgstr[0]', doesn't exist in 'msgid'`` error when running 195 ``django-admin.py compilemessages`` or a ``KeyError`` Python exception at 196 runtime. 197 198 .. _lazy-translations: 199 200 Lazy translation 201 ---------------- 202 203 Use the function ``django.utils.translation.ugettext_lazy()`` to translate 204 strings lazily -- when the value is accessed rather than when the 205 ``ugettext_lazy()`` function is called. 206 207 For example, to translate a model's ``help_text``, do the following:: 208 209 from django.utils.translation import ugettext_lazy 210 211 class MyThing(models.Model): 212 name = models.CharField(help_text=ugettext_lazy('This is the help text')) 213 214 In this example, ``ugettext_lazy()`` stores a lazy reference to the string -- 215 not the actual translation. The translation itself will be done when the string 216 is used in a string context, such as template rendering on the Django admin 217 site. 218 219 The result of a ``ugettext_lazy()`` call can be used wherever you would use a 220 unicode string (an object with type ``unicode``) in Python. If you try to use 221 it where a bytestring (a ``str`` object) is expected, things will not work as 222 expected, since a ``ugettext_lazy()`` object doesn't know how to convert 223 itself to a bytestring. You can't use a unicode string inside a bytestring, 224 either, so this is consistent with normal Python behavior. For example:: 225 226 # This is fine: putting a unicode proxy into a unicode string. 227 u"Hello %s" % ugettext_lazy("people") 228 229 # This will not work, since you cannot insert a unicode object 230 # into a bytestring (nor can you insert our unicode proxy there) 231 "Hello %s" % ugettext_lazy("people") 232 233 If you ever see output that looks like ``"hello 234 <django.utils.functional...>"``, you have tried to insert the result of 235 ``ugettext_lazy()`` into a bytestring. That's a bug in your code. 236 237 If you don't like the verbose name ``ugettext_lazy``, you can just alias it as 238 ``_`` (underscore), like so:: 239 240 from django.utils.translation import ugettext_lazy as _ 241 242 class MyThing(models.Model): 243 name = models.CharField(help_text=_('This is the help text')) 244 245 Always use lazy translations in :ref:`Django models <topics-db-models>`. 246 Field names and table names should be marked for translation (otherwise, they 247 won't be translated in the admin interface). This means writing explicit 248 ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class, 249 though, rather than relying on Django's default determination of 250 ``verbose_name`` and ``verbose_name_plural`` by looking at the model's class 251 name:: 252 253 from django.utils.translation import ugettext_lazy as _ 254 255 class MyThing(models.Model): 256 name = models.CharField(_('name'), help_text=_('This is the help text')) 257 class Meta: 258 verbose_name = _('my thing') 259 verbose_name_plural = _('mythings') 260 261 Working with lazy translation objects 262 ------------------------------------- 263 264 .. highlightlang:: python 265 266 Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models 267 and utility functions is a common operation. When you're working with these 268 objects elsewhere in your code, you should ensure that you don't accidentally 269 convert them to strings, because they should be converted as late as possible 270 (so that the correct locale is in effect). This necessitates the use of a 271 couple of helper functions. 272 273 Joining strings: string_concat() 274 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 275 276 Standard Python string joins (``''.join([...])``) will not work on lists 277 containing lazy translation objects. Instead, you can use 278 ``django.utils.translation.string_concat()``, which creates a lazy object that 279 concatenates its contents *and* converts them to strings only when the result 280 is included in a string. For example:: 281 282 from django.utils.translation import string_concat 283 ... 284 name = ugettext_lazy(u'John Lennon') 285 instrument = ugettext_lazy(u'guitar') 286 result = string_concat([name, ': ', instrument]) 287 288 In this case, the lazy translations in ``result`` will only be converted to 289 strings when ``result`` itself is used in a string (usually at template 290 rendering time). 291 292 The allow_lazy() decorator 293 ~~~~~~~~~~~~~~~~~~~~~~~~~~ 294 295 Django offers many utility functions (particularly in ``django.utils``) that 296 take a string as their first argument and do something to that string. These 297 functions are used by template filters as well as directly in other code. 298 299 If you write your own similar functions and deal with translations, you'll 300 face the problem of what to do when the first argument is a lazy translation 301 object. You don't want to convert it to a string immediately, because you might 302 be using this function outside of a view (and hence the current thread's locale 303 setting will not be correct). 304 305 For cases like this, use the ``django.utils.functional.allow_lazy()`` 306 decorator. It modifies the function so that *if* it's called with a lazy 307 translation as the first argument, the function evaluation is delayed until it 308 needs to be converted to a string. 309 310 For example:: 311 312 from django.utils.functional import allow_lazy 313 314 def fancy_utility_function(s, ...): 315 # Do some conversion on string 's' 316 ... 317 fancy_utility_function = allow_lazy(fancy_utility_function, unicode) 318 319 The ``allow_lazy()`` decorator takes, in addition to the function to decorate, 320 a number of extra arguments (``*args``) specifying the type(s) that the 321 original function can return. Usually, it's enough to include ``unicode`` here 322 and ensure that your function returns only Unicode strings. 323 324 Using this decorator means you can write your function and assume that the 325 input is a proper string, then add support for lazy translation objects at the 326 end. 327 328 Specifying translation strings: In template code 329 ================================================ 330 331 .. highlightlang:: html+django 332 333 Translations in :ref:`Django templates <topics-templates>` uses two template 334 tags and a slightly different syntax than in Python code. To give your template 335 access to these tags, put ``{% load i18n %}`` toward the top of your template. 336 337 The ``{% trans %}`` template tag translates either a constant string 338 (enclosed in single or double quotes) or variable content:: 339 340 <title>{% trans "This is the title." %}</title> 341 <title>{% trans myvar %}</title> 342 343 If the ``noop`` option is present, variable lookup still takes place but the 344 translation is skipped. This is useful when "stubbing out" content that will 345 require translation in the future:: 346 347 <title>{% trans "myvar" noop %}</title> 348 349 Internally, inline translations use an ``ugettext`` call. 350 351 It's not possible to mix a template variable inside a string within ``{% trans 352 %}``. If your translations require strings with variables (placeholders), use 353 ``{% blocktrans %}``:: 354 355 {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %} 356 357 To translate a template expression -- say, using template filters -- you need 358 to bind the expression to a local variable for use within the translation 359 block:: 360 361 {% blocktrans with value|filter as myvar %} 362 This will have {{ myvar }} inside. 363 {% endblocktrans %} 364 365 If you need to bind more than one expression inside a ``blocktrans`` tag, 366 separate the pieces with ``and``:: 367 368 {% blocktrans with book|title as book_t and author|title as author_t %} 369 This is {{ book_t }} by {{ author_t }} 370 {% endblocktrans %} 371 372 To pluralize, specify both the singular and plural forms with the 373 ``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and 374 ``{% endblocktrans %}``. Example:: 375 376 {% blocktrans count list|length as counter %} 377 There is only one {{ name }} object. 378 {% plural %} 379 There are {{ counter }} {{ name }} objects. 380 {% endblocktrans %} 381 382 When you use the pluralization feature and bind additional values to local 383 variables apart from the counter value that selects the translated literal to be 384 used, have in mind that the ``blocktrans`` construct is internally converted 385 to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext 386 variables <pluralization-var-notes>` apply. 387 388 Each ``RequestContext`` has access to three translation-specific variables: 389 390 * ``LANGUAGES`` is a list of tuples in which the first element is the 391 language code and the second is the language name (translated into the 392 currently active locale). 393 394 * ``LANGUAGE_CODE`` is the current user's preferred language, as a string. 395 Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`, 396 below.) 397 398 * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a 399 right-to-left language, e.g.: Hebrew, Arabic. If False it's a 400 left-to-right language, e.g.: English, French, German etc. 401 402 403 If you don't use the ``RequestContext`` extension, you can get those values with 404 three tags:: 405 406 {% get_current_language as LANGUAGE_CODE %} 407 {% get_available_languages as LANGUAGES %} 408 {% get_current_language_bidi as LANGUAGE_BIDI %} 409 410 These tags also require a ``{% load i18n %}``. 411 412 Translation hooks are also available within any template block tag that accepts 413 constant strings. In those cases, just use ``_()`` syntax to specify a 414 translation string:: 415 416 {% some_special_tag _("Page not found") value|yesno:_("yes,no") %} 417 418 In this case, both the tag and the filter will see the already-translated 419 string, so they don't need to be aware of translations. 420 421 .. note:: 422 In this example, the translation infrastructure will be passed the string 423 ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The 424 translated string will need to contain the comma so that the filter 425 parsing code knows how to split up the arguments. For example, a German 426 translator might translate the string ``"yes,no"`` as ``"ja,nein"`` 427 (keeping the comma intact). 428 429 .. _Django templates: ../templates_python/ 430 431 Specifying translation strings: In JavaScript code 432 ================================================== 433 434 Adding translations to JavaScript poses some problems: 435 436 * JavaScript code doesn't have access to a ``gettext`` implementation. 437 438 * JavaScript code doesn't have access to .po or .mo files; they need to be 439 delivered by the server. 440 441 * The translation catalogs for JavaScript should be kept as small as 442 possible. 443 444 Django provides an integrated solution for these problems: It passes the 445 translations into JavaScript, so you can call ``gettext``, etc., from within 446 JavaScript. 447 448 The ``javascript_catalog`` view 449 ------------------------------- 450 451 The main solution to these problems is the ``javascript_catalog`` view, which 452 sends out a JavaScript code library with functions that mimic the ``gettext`` 453 interface, plus an array of translation strings. Those translation strings are 454 taken from the application, project or Django core, according to what you 455 specify in either the info_dict or the URL. 456 457 You hook it up like this:: 458 459 js_info_dict = { 460 'packages': ('your.app.package',), 461 } 462 463 urlpatterns = patterns('', 464 (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), 465 ) 466 467 Each string in ``packages`` should be in Python dotted-package syntax (the 468 same format as the strings in ``INSTALLED_APPS``) and should refer to a package 469 that contains a ``locale`` directory. If you specify multiple packages, all 470 those catalogs are merged into one catalog. This is useful if you have 471 JavaScript that uses strings from different applications. 472 473 You can make the view dynamic by putting the packages into the URL pattern:: 474 475 urlpatterns = patterns('', 476 (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'), 477 ) 478 479 With this, you specify the packages as a list of package names delimited by '+' 480 signs in the URL. This is especially useful if your pages use code from 481 different apps and this changes often and you don't want to pull in one big 482 catalog file. As a security measure, these values can only be either 483 ``django.conf`` or any package from the ``INSTALLED_APPS`` setting. 484 485 Using the JavaScript translation catalog 486 ---------------------------------------- 487 488 To use the catalog, just pull in the dynamically generated script like this:: 489 490 <script type="text/javascript" src={% url django.views.i18n.javascript_catalog %}"></script> 491 492 This uses reverse URL lookup to find the URL of the JavaScript catalog view. 493 When the catalog is loaded, your JavaScript code can use the standard 494 ``gettext`` interface to access it:: 495 496 document.write(gettext('this is to be translated')); 497 498 There is also an ``ngettext`` interface:: 499 500 var object_cnt = 1 // or 0, or 2, or 3, ... 501 s = ngettext('literal for the singular case', 502 'literal for the plural case', object_cnt); 503 504 and even a string interpolation function:: 505 506 function interpolate(fmt, obj, named); 507 508 The interpolation syntax is borrowed from Python, so the ``interpolate`` 509 function supports both positional and named interpolation: 510 511 * Positional interpolation: ``obj`` contains a JavaScript Array object 512 whose elements values are then sequentially interpolated in their 513 corresponding ``fmt`` placeholders in the same order they appear. 514 For example:: 515 516 fmts = ngettext('There is %s object. Remaining: %s', 517 'There are %s objects. Remaining: %s', 11); 518 s = interpolate(fmts, [11, 20]); 519 // s is 'There are 11 objects. Remaining: 20' 520 521 * Named interpolation: This mode is selected by passing the optional 522 boolean ``named`` parameter as true. ``obj`` contains a JavaScript 523 object or associative array. For example:: 524 525 d = { 526 count: 10 527 total: 50 528 }; 529 530 fmts = ngettext('Total: %(total)s, there is %(count)s object', 531 'there are %(count)s of a total of %(total)s objects', d.count); 532 s = interpolate(fmts, d, true); 533 534 You shouldn't go over the top with string interpolation, though: this is still 535 JavaScript, so the code has to make repeated regular-expression substitutions. 536 This isn't as fast as string interpolation in Python, so keep it to those 537 cases where you really need it (for example, in conjunction with ``ngettext`` 538 to produce proper pluralizations). 539 540 The ``set_language`` redirect view 541 ================================== 542 543 As a convenience, Django comes with a view, ``django.views.i18n.set_language``, 544 that sets a user's language preference and redirects back to the previous page. 545 546 Activate this view by adding the following line to your URLconf:: 547 548 (r'^i18n/', include('django.conf.urls.i18n')), 549 550 (Note that this example makes the view available at ``/i18n/setlang/``.) 551 552 The view expects to be called via the ``POST`` method, with a ``language`` 553 parameter set in request. If session support is enabled, the view 554 saves the language choice in the user's session. Otherwise, it saves the 555 language choice in a cookie that is by default named ``django_language``. 556 (The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.) 557 558 After setting the language choice, Django redirects the user, following this 559 algorithm: 560 561 * Django looks for a ``next`` parameter in the ``POST`` data. 562 * If that doesn't exist, or is empty, Django tries the URL in the 563 ``Referrer`` header. 564 * If that's empty -- say, if a user's browser suppresses that header -- 565 then the user will be redirected to ``/`` (the site root) as a fallback. 566 567 Here's example HTML template code: 568 569 .. code-block:: html+django 570 571 <form action="/i18n/setlang/" method="post"> 572 <input name="next" type="hidden" value="/next/page/" /> 573 <select name="language"> 574 {% for lang in LANGUAGES %} 575 <option value="{{ lang.0 }}">{{ lang.1 }}</option> 576 {% endfor %} 577 </select> 578 <input type="submit" value="Go" /> 579 </form> -
new file docs/topics/i18n/localization.txt
diff -r 8a4e070b280a docs/topics/i18n/localization.txt
- + 1 .. _topics-i18n-localization: 2 3 ============ 4 Localization 5 ============ 6 7 This document covers two localization-related topics: `Creating language 8 files`_ 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 19 How to create language files 20 ============================ 21 22 Once the string literals of an application have been tagged for later 23 translation, the translation themselves need to be written (or obtained). Here's 24 how 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 *translation strings*. 40 41 Message files 42 ------------- 43 44 The first step is to create a **message file** for a new language. A message 45 file is a plain-text file, representing a single language, that contains all 46 available translation strings and how they should be represented in the given 47 language. Message files have a ``.po`` file extension. 48 49 Django comes with a tool, ``django-admin.py makemessages``, that automates the 50 creation 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 57 To 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. 62 The language code, in this case, is in locale format. For example, it's 63 ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian German. 64 65 The script should be run from one of two places: 66 67 * The root directory of your Django project. 68 * The root directory of your Django app. 69 70 Th script runs over your project source tree or your application source tree and 71 pulls out all strings marked for translation. It creates (or updates) a message 72 file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de`` example, the 73 file will be ``locale/de/LC_MESSAGES/django.po``. 74 75 By default ``django-admin.py makemessages`` examines every file that has the 76 ``.html`` file extension. In case you want to override that default, use the 77 ``--extension`` or ``-e`` option to specify the file extensions to examine:: 78 79 django-admin.py makemessages -l de -e txt 80 81 Separate multiple extensions with commas and/or use ``-e`` or ``--extension`` 82 multiple times:: 83 84 django-admin.py makemessages -l=de -e=html,txt -e xml 85 86 When :ref:`creating message files from JavaScript source code 87 <creating-message-files-from-js-code>` you need to use the special 'djangojs' 88 domain, **not** ``-e js``. 89 90 .. admonition:: No gettext? 91 92 If you don't have the ``gettext`` utilities installed, ``django-admin.py 93 makemessages`` will create empty files. If that's the case, either install 94 the ``gettext`` utilities or just copy the English message file 95 (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting 96 point; it's just an empty translation file. 97 98 .. admonition:: Working on Windows? 99 100 If you're using Windows and need to install the GNU gettext utilities so 101 ``django-admin makemessages`` works see :ref:`gettext_on_windows` for more 102 information. 103 104 The format of ``.po`` files is straightforward. Each ``.po`` file contains a 105 small bit of metadata, such as the translation maintainer's contact 106 information, but the bulk of the file is a list of **messages** -- simple 107 mappings between translation strings and the actual translated text for the 108 particular language. 109 110 For example, if your Django app contained a translation string for the text 111 ``"Welcome to my site."``, like so:: 112 113 _("Welcome to my site.") 114 115 ...then ``django-admin.py makemessages`` will have created a ``.po`` file 116 containing the following snippet -- a message:: 117 118 #: path/to/python/module.py:23 119 msgid "Welcome to my site." 120 msgstr "" 121 122 A quick explanation: 123 124 * ``msgid`` is the translation string, which appears in the source. Don't 125 change it. 126 * ``msgstr`` is where you put the language-specific translation. It starts 127 out empty, so it's your responsibility to change it. Make sure you keep 128 the quotes around your translation. 129 * As a convenience, each message includes, in the form of a comment line 130 prefixed with ``#`` and located above the ``msgid`` line, the filename and 131 line number from which the translation string was gleaned. 132 133 Long messages are a special case. There, the first string directly after the 134 ``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be 135 written over the next few lines as one string per line. Those strings are 136 directly concatenated. Don't forget trailing spaces within the strings; 137 otherwise, they'll be tacked together without whitespace! 138 139 .. admonition:: Mind your charset 140 141 When creating a PO file with your favorite text editor, first edit 142 the charset line (search for ``"CHARSET"``) and set it to the charset 143 you'll be using to edit the content. Due to the way the ``gettext`` tools 144 work internally and because we want to allow non-ASCII source strings in 145 Django's core and your applications, you **must** use UTF-8 as the encoding 146 for your PO file. This means that everybody will be using the same 147 encoding, which is important when Django processes the PO files. 148 149 To reexamine all source code and templates for new translation strings and 150 update all message files for **all** languages, run this:: 151 152 django-admin.py makemessages -a 153 154 Compiling message files 155 ----------------------- 156 157 After you create your message file -- and each time you make changes to it -- 158 you'll need to compile it into a more efficient form, for use by ``gettext``. 159 Do this with the ``django-admin.py compilemessages`` utility. 160 161 This tool runs over all available ``.po`` files and creates ``.mo`` files, which 162 are binary files optimized for use by ``gettext``. In the same directory from 163 which you ran ``django-admin.py makemessages``, run ``django-admin.py 164 compilemessages`` like this:: 165 166 django-admin.py compilemessages 167 168 That's it. Your translations are ready for use. 169 170 .. admonition:: A note to Django veterans 171 172 The old tool ``bin/compile-messages.py`` has been moved to the command 173 ``django-admin.py compilemessages`` to provide consistency throughout 174 Django. 175 176 .. admonition:: Working on Windows? 177 178 If you're using Windows and need to install the GNU gettext utilities so 179 ``django-admin compilemessages`` works see :ref:`gettext_on_windows` for more 180 information. 181 182 .. _creating-message-files-from-js-code: 183 184 Creating message files from JavaScript source code 185 ================================================== 186 187 You create and update the message files the same way as the other Django message 188 files -- with the ``django-admin.py makemessages`` tool. The only difference is 189 you need to provide a ``-d djangojs`` parameter, like this:: 190 191 django-admin.py makemessages -d djangojs -l de 192 193 This would create or update the message file for JavaScript for German. 194 After updating message files, just run ``django-admin.py compilemessages`` 195 the same way as you do with normal Django message files. 196 197 .. _gettext_on_windows: 198 199 ``gettext`` on Windows 200 ====================== 201 202 This is only needed for people who either want to extract message IDs or compile 203 message files (``.po``). Translation work itself just involves editing existing 204 files of this type, but if you want to create your own message files, or want to 205 test or compile a changed message file, you will need the ``gettext`` utilities: 206 207 * Download the following zip files from the GNOME servers 208 http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one 209 of its mirrors_ 210 211 * ``gettext-runtime-X.zip`` 212 * ``gettext-tools-X.zip`` 213 214 ``X`` is the version number, we recomend using ``0.15`` or higher. 215 216 * Extract the contents of the ``bin\`` directories in both files to the 217 same folder on your system (i.e. ``C:\Program Files\gettext-utils``) 218 219 * Update the system PATH: 220 221 * ``Control Panel > System > Advanced > Environment Variables``. 222 * In the ``System variables`` list, click ``Path``, click ``Edit``. 223 * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the 224 ``Variable value`` field. 225 226 .. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS 227 228 You may also use ``gettext`` binaries you have obtained elsewhere, so long as 229 the ``xgettext --version`` command works properly. Some version 0.14.4 binaries 230 have been found to not support this command. Do not attempt to use Django 231 translation utilities with a ``gettext`` package if the command ``xgettext 232 --version`` entered at a Windows command prompt causes a popup window saying 233 "xgettext.exe has generated errors and will be closed by Windows". 234 235 .. _format-localization: 236 237 Format localization 238 =================== 239 240 Django's formatting system is disabled by default. To enable it, it's necessay 241 to set :setting:`USE_L10N = True <USE_L10N>` in your settings file. 242 243 When using Django's formatting system, dates and numbers on templates will be 244 displayed using the format specified for the current locale. Two users 245 accessing the same content, but in different language, will see date and 246 number fields formatted in different ways, depending on the format for their 247 current locale. 248 249 Django will also use localized formats when parsing data in forms. That means 250 Django uses different formats for different locales when guessing the format 251 used by the user when inputting data on forms. Note that Django uses different 252 formats for displaying data, and for parsing it. 253 254 Creating custom format files 255 ---------------------------- 256 257 Django provides format definitions for many locales, but sometimes you might 258 want to create your own, because a format files doesn't exist for your locale, 259 or because you want to overwrite some of the values. 260 261 To use custom formats, first thing to do, is to specify the path where you'll 262 place format files. To do that, just set your :setting:`FORMAT_MODULE_PATH` 263 setting to the the path (in the format ``'foo.bar.baz``) where format files 264 will exists. 265 266 Files are not placed directly in this directory, but in a directory named as 267 the locale, and must be named ``formats.py``. 268 269 To customize the English formats, a structure like this would be needed:: 270 271 mysite/ 272 formats/ 273 __init__.py 274 en/ 275 __init__.py 276 formats.py 277 278 where :file:`formats.py` contains custom format definitions. For example:: 279 280 THOUSAND_SEPARATOR = ' ' 281 282 to use a space as a thousand separator, instead of the default for English, 283 a comma. -
docs/topics/index.txt
diff -r 8a4e070b280a docs/topics/index.txt
a b 21 21 cache 22 22 conditional-view-processing 23 23 email 24 i18n 24 i18n/index 25 25 pagination 26 26 serialization 27 27 settings