Ticket #10260: 10260-i18n-docs-rf-1.1.x-r12229.diff
File 10260-i18n-docs-rf-1.1.x-r12229.diff, 97.4 KB (added by , 15 years ago) |
---|
-
new file docs/howto/i18n.txt
diff -r 4755c937c02f 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 In all cases the name of the directory containing the translation is expected to 20 be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``, 21 etc. 22 23 This way, you can write applications that include their own translations, and 24 you can override base translations in your project path. Or, you can just build 25 a big project out of several apps and put all translations into one big project 26 message file. The choice is yours. 27 28 .. note:: 29 30 If you're using manually configured settings, as described in 31 :ref:`settings-without-django-settings-module`, the ``locale`` directory in 32 the project directory will not be examined, since Django loses the ability 33 to work out the location of the project directory. (Django normally uses the 34 location of the settings file to determine this, and a settings file doesn't 35 exist if you're manually configuring your settings.) 36 37 All message file repositories are structured the same way. They are: 38 39 * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` 40 * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` 41 * All paths listed in ``LOCALE_PATHS`` in your settings file are 42 searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)`` 43 * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)`` 44 45 To create message files, you use the :djadmin:`django-admin.py makemessages <makemessages>` 46 tool. You only need to be in the same directory where the ``locale/`` directory 47 is located. And you use :djadmin:`django-admin.py compilemessages <compilemessages>` 48 to produce the binary ``.mo`` files that are used by ``gettext``. Read the 49 :ref:`topics-i18n-localization` document for more details. 50 51 You can also run ``django-admin.py compilemessages --settings=path.to.settings`` 52 to make the compiler process all the directories in your :setting:`LOCALE_PATHS` 53 setting. 54 55 Application message files are a bit complicated to discover -- they need the 56 :class:`~django.middleware.locale.LocaleMiddleware`. If you don't use the 57 middleware, only the Django message files and project message files will be 58 installed and available at runtime. 59 60 Finally, you should give some thought to the structure of your translation 61 files. If your applications need to be delivered to other users and will 62 be used in other projects, you might want to use app-specific translations. 63 But using app-specific translations and project translations could produce 64 weird problems with ``makemessages``: It will traverse all directories below 65 the current path and so might put message IDs into the project message file 66 that are already in application message files. 67 68 The easiest way out is to store applications that are not part of the project 69 (and so carry their own translations) outside the project tree. That way, 70 ``django-admin.py makemessages`` on the project level will only translate 71 strings that are connected to your explicit project and not strings that are 72 distributed independently. -
docs/howto/index.txt
diff -r 4755c937c02f 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 4755c937c02f docs/internals/contributing.txt
a b 402 402 403 403 * Join the `Django i18n mailing list`_ and introduce yourself. 404 404 405 * Make sure you read the notes about :ref:`specialties-of-django-i18n`. 406 405 407 * Create translations using the methods described in the 406 :ref:`i18n documentation <topics-i18n>`. For this you will use the 407 ``django-admin.py makemessages`` tool. In this particular case it should 408 be run from the top-level ``django`` directory of the Django source tree. 408 :ref:`localization documentation <topics-i18n-localization>`. For this 409 you will use the ``django-admin.py makemessages`` tool. In this 410 particular case it should be run from the top-level ``django`` directory 411 of the Django source tree. 409 412 410 413 The script runs over the entire Django source tree and pulls out all 411 414 strings marked for translation. It creates (or updates) a message file in 412 the directory ``conf/locale`` (for example for ``pt -BR``, the file will be413 ``conf/locale/pt -br/LC_MESSAGES/django.po``).415 the directory ``conf/locale`` (for example for ``pt_BR``, the file will be 416 ``conf/locale/pt_BR/LC_MESSAGES/django.po``). 414 417 415 418 * Make sure that ``django-admin.py compilemessages -l <lang>`` runs without 416 419 producing any warnings. -
docs/ref/settings.txt
diff -r 4755c937c02f docs/ref/settings.txt
a b 610 610 Default: ``'en-us'`` 611 611 612 612 A string representing the language code for this installation. This should be in 613 standard language format. For example, U.S. English is ``"en-us"``. See614 :ref:`topics-i18n`.613 standard :term:`language format<language code>`. For example, U.S. English is 614 ``"en-us"``. See :ref:`topics-i18n`. 615 615 616 616 .. setting:: LANGUAGE_COOKIE_NAME 617 617 … … 638 638 639 639 .. _online source: http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py 640 640 641 The list is a tuple of two-tuples in the format (language code, language 642 name) -- for example, ``('ja', 'Japanese')``. This specifies which languages 643 are available for language selection. See :ref:`topics-i18n`. 641 The list is a tuple of two-tuples in the format ``(language code, language 642 name)``, the ``language code`` part should be a 643 :term:`language name<language code>` -- for example, ``('ja', 'Japanese')``. 644 This specifies which languages are available for language selection. See 645 :ref:`topics-i18n`. 644 646 645 647 Generally, the default value should suffice. Only set this setting if you want 646 648 to restrict language selection to a subset of the Django-provided languages. … … 675 677 Default: ``()`` (Empty tuple) 676 678 677 679 A tuple of directories where Django looks for translation files. 678 See :ref:` translations-in-your-own-projects`.680 See :ref:`using-translations-in-your-own-projects`. 679 681 680 682 .. setting:: LOGIN_REDIRECT_URL 681 683 -
deleted file docs/topics/i18n.txt
diff -r 4755c937c02f docs/topics/i18n.txt
+ - 1 .. _topics-i18n:2 3 ====================4 Internationalization5 ====================6 7 Django has full support for internationalization of text in code and templates.8 Here's how it works.9 10 Overview11 ========12 13 The goal of internationalization is to allow a single Web application to offer14 its content and functionality in multiple languages.15 16 You, the Django developer, can accomplish this goal by adding a minimal amount17 of hooks to your Python code and templates. These hooks are called18 **translation strings**. They tell Django: "This text should be translated into19 the end user's language, if a translation for this text is available in that20 language."21 22 Django takes care of using these hooks to translate Web apps, on the fly,23 according to users' language preferences.24 25 Essentially, Django does two things:26 27 * It lets developers and template authors specify which parts of their apps28 should be translatable.29 * It uses these hooks to translate Web apps for particular users according30 to their language preferences.31 32 If you don't need internationalization in your app33 ==================================================34 35 Django's internationalization hooks are on by default, and that means there's a36 bit of i18n-related overhead in certain places of the framework. If you don't37 use internationalization, you should take the two seconds to set38 :setting:`USE_I18N = False <USE_I18N>` in your settings file. If39 :setting:`USE_I18N` is set to ``False``, then Django will make some40 optimizations so as not to load the internationalization machinery.41 42 You'll probably also want to remove ``'django.core.context_processors.i18n'``43 from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting.44 45 If you do need internationalization: three steps46 ================================================47 48 1. Embed translation strings in your Python code and templates.49 2. Get translations for those strings, in whichever languages you want to50 support.51 3. Activate the locale middleware in your Django settings.52 53 .. admonition:: Behind the scenes54 55 Django's translation machinery uses the standard ``gettext`` module that56 comes with Python.57 58 1. How to specify translation strings59 =====================================60 61 Translation strings specify "This text should be translated." These strings can62 appear in your Python code and templates. It's your responsibility to mark63 translatable strings; the system can only translate strings it knows about.64 65 In Python code66 --------------67 68 Standard translation69 ~~~~~~~~~~~~~~~~~~~~70 71 Specify a translation string by using the function ``ugettext()``. It's72 convention to import this as a shorter alias, ``_``, to save typing.73 74 .. note::75 Python's standard library ``gettext`` module installs ``_()`` into the76 global namespace, as an alias for ``gettext()``. In Django, we have chosen77 not to follow this practice, for a couple of reasons:78 79 1. For international character set (Unicode) support, ``ugettext()`` is80 more useful than ``gettext()``. Sometimes, you should be using81 ``ugettext_lazy()`` as the default translation method for a particular82 file. Without ``_()`` in the global namespace, the developer has to83 think about which is the most appropriate translation function.84 85 2. The underscore character (``_``) is used to represent "the previous86 result" in Python's interactive shell and doctest tests. Installing a87 global ``_()`` function causes interference. Explicitly importing88 ``ugettext()`` as ``_()`` avoids this problem.89 90 .. highlightlang:: python91 92 In this example, the text ``"Welcome to my site."`` is marked as a translation93 string::94 95 from django.utils.translation import ugettext as _96 97 def my_view(request):98 output = _("Welcome to my site.")99 return HttpResponse(output)100 101 Obviously, you could code this without using the alias. This example is102 identical to the previous one::103 104 from django.utils.translation import ugettext105 106 def my_view(request):107 output = ugettext("Welcome to my site.")108 return HttpResponse(output)109 110 Translation works on computed values. This example is identical to the previous111 two::112 113 def my_view(request):114 words = ['Welcome', 'to', 'my', 'site.']115 output = _(' '.join(words))116 return HttpResponse(output)117 118 Translation works on variables. Again, here's an identical example::119 120 def my_view(request):121 sentence = 'Welcome to my site.'122 output = _(sentence)123 return HttpResponse(output)124 125 (The caveat with using variables or computed values, as in the previous two126 examples, is that Django's translation-string-detecting utility,127 ``django-admin.py makemessages``, won't be able to find these strings. More on128 ``makemessages`` later.)129 130 The strings you pass to ``_()`` or ``ugettext()`` can take placeholders,131 specified with Python's standard named-string interpolation syntax. Example::132 133 def my_view(request, m, d):134 output = _('Today is %(month)s, %(day)s.') % {'month': m, 'day': d}135 return HttpResponse(output)136 137 This technique lets language-specific translations reorder the placeholder138 text. For example, an English translation may be ``"Today is November, 26."``,139 while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the140 placeholders (the month and the day) with their positions swapped.141 142 For this reason, you should use named-string interpolation (e.g., ``%(day)s``)143 instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you144 have more than a single parameter. If you used positional interpolation,145 translations wouldn't be able to reorder placeholder text.146 147 Marking strings as no-op148 ~~~~~~~~~~~~~~~~~~~~~~~~149 150 Use the function ``django.utils.translation.ugettext_noop()`` to mark a string151 as a translation string without translating it. The string is later translated152 from a variable.153 154 Use this if you have constant strings that should be stored in the source155 language because they are exchanged over systems or users -- such as strings in156 a database -- but should be translated at the last possible point in time, such157 as when the string is presented to the user.158 159 .. _lazy-translations:160 161 Lazy translation162 ~~~~~~~~~~~~~~~~163 164 Use the function ``django.utils.translation.ugettext_lazy()`` to translate165 strings lazily -- when the value is accessed rather than when the166 ``ugettext_lazy()`` function is called.167 168 For example, to translate a model's ``help_text``, do the following::169 170 from django.utils.translation import ugettext_lazy171 172 class MyThing(models.Model):173 name = models.CharField(help_text=ugettext_lazy('This is the help text'))174 175 In this example, ``ugettext_lazy()`` stores a lazy reference to the string --176 not the actual translation. The translation itself will be done when the string177 is used in a string context, such as template rendering on the Django admin178 site.179 180 The result of a ``ugettext_lazy()`` call can be used wherever you would use a181 unicode string (an object with type ``unicode``) in Python. If you try to use182 it where a bytestring (a ``str`` object) is expected, things will not work as183 expected, since a ``ugettext_lazy()`` object doesn't know how to convert184 itself to a bytestring. You can't use a unicode string inside a bytestring,185 either, so this is consistent with normal Python behavior. For example::186 187 # This is fine: putting a unicode proxy into a unicode string.188 u"Hello %s" % ugettext_lazy("people")189 190 # This will not work, since you cannot insert a unicode object191 # into a bytestring (nor can you insert our unicode proxy there)192 "Hello %s" % ugettext_lazy("people")193 194 If you ever see output that looks like ``"hello195 <django.utils.functional...>"``, you have tried to insert the result of196 ``ugettext_lazy()`` into a bytestring. That's a bug in your code.197 198 If you don't like the verbose name ``ugettext_lazy``, you can just alias it as199 ``_`` (underscore), like so::200 201 from django.utils.translation import ugettext_lazy as _202 203 class MyThing(models.Model):204 name = models.CharField(help_text=_('This is the help text'))205 206 Always use lazy translations in :ref:`Django models <topics-db-models>`.207 Field names and table names should be marked for translation (otherwise, they208 won't be translated in the admin interface). This means writing explicit209 ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class,210 though, rather than relying on Django's default determination of211 ``verbose_name`` and ``verbose_name_plural`` by looking at the model's class212 name::213 214 from django.utils.translation import ugettext_lazy as _215 216 class MyThing(models.Model):217 name = models.CharField(_('name'), help_text=_('This is the help text'))218 class Meta:219 verbose_name = _('my thing')220 verbose_name_plural = _('mythings')221 222 Pluralization223 ~~~~~~~~~~~~~224 225 Use the function ``django.utils.translation.ungettext()`` to specify pluralized226 messages.227 228 ``ungettext`` takes three arguments: the singular translation string, the229 plural translation string and the number of objects.230 231 This function is useful when you need your Django application to be localizable232 to languages where the number and complexity of `plural forms233 <http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is234 greater than the two forms used in English ('object' for the singular and235 'objects' for all the cases where ``count`` is different from zero,236 irrespective of its value).237 238 For example::239 240 from django.utils.translation import ungettext241 def hello_world(request, count):242 page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % {243 'count': count,244 }245 return HttpResponse(page)246 247 In this example the number of objects is passed to the translation languages as248 the ``count`` variable.249 250 Lets see a slightly more complex usage example::251 252 from django.utils.translation import ungettext253 254 count = Report.objects.count()255 if count == 1:256 name = Report._meta.verbose_name257 else:258 name = Report._meta.verbose_name_plural259 260 text = ungettext(261 'There is %(count)d %(name)s available.',262 'There are %(count)d %(name)s available.',263 count264 ) % {265 'count': count,266 'name': name267 }268 269 Here we reuse localizable, hopefully already translated literals (contained in270 the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for271 other parts of the sentence so all of it is consistently based on the272 cardinality of the elements at play.273 274 .. _pluralization-var-notes:275 276 .. note::277 278 When using this technique, make sure you use a single name for every279 extrapolated variable included in the literal. In the example above note280 how we used the ``name`` Python variable in both translation strings. This281 example would fail::282 283 from django.utils.translation import ungettext284 from myapp.models import Report285 286 count = Report.objects.count()287 d = {288 'count': count,289 'name': Report._meta.verbose_name290 'plural_name': Report._meta.verbose_name_plural291 }292 text = ungettext(293 'There is %(count)d %(name)s available.',294 'There are %(count)d %(plural_name)s available.',295 count296 ) % d297 298 You would get a ``a format specification for argument 'name', as in299 'msgstr[0]', doesn't exist in 'msgid'`` error when running300 ``django-admin.py compilemessages`` or a ``KeyError`` Python exception at301 runtime.302 303 In template code304 ----------------305 306 .. highlightlang:: html+django307 308 Translations in :ref:`Django templates <topics-templates>` uses two template309 tags and a slightly different syntax than in Python code. To give your template310 access to these tags, put ``{% load i18n %}`` toward the top of your template.311 312 The ``{% trans %}`` template tag translates either a constant string313 (enclosed in single or double quotes) or variable content::314 315 <title>{% trans "This is the title." %}</title>316 <title>{% trans myvar %}</title>317 318 If the ``noop`` option is present, variable lookup still takes place, but the319 original text will be returned unchanged. This is useful when "stubbing out"320 content that will require translation in the future::321 322 <title>{% trans "myvar" noop %}</title>323 324 Internally, inline translations use an ``ugettext`` call.325 326 It's not possible to mix a template variable inside a string within ``{% trans327 %}``. If your translations require strings with variables (placeholders), use328 ``{% blocktrans %}``::329 330 {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}331 332 To translate a template expression -- say, using template filters -- you need333 to bind the expression to a local variable for use within the translation334 block::335 336 {% blocktrans with value|filter as myvar %}337 This will have {{ myvar }} inside.338 {% endblocktrans %}339 340 If you need to bind more than one expression inside a ``blocktrans`` tag,341 separate the pieces with ``and``::342 343 {% blocktrans with book|title as book_t and author|title as author_t %}344 This is {{ book_t }} by {{ author_t }}345 {% endblocktrans %}346 347 To pluralize, specify both the singular and plural forms with the348 ``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and349 ``{% endblocktrans %}``. Example::350 351 {% blocktrans count list|length as counter %}352 There is only one {{ name }} object.353 {% plural %}354 There are {{ counter }} {{ name }} objects.355 {% endblocktrans %}356 357 When you use the pluralization feature and bind additional values to local358 variables apart from the counter value that selects the translated literal to359 be used, have in mind that the ``blocktrans`` construct is internally converted360 to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext361 variables <pluralization-var-notes>` apply.362 363 Each ``RequestContext`` has access to three translation-specific variables:364 365 * ``LANGUAGES`` is a list of tuples in which the first element is the366 language code and the second is the language name (translated into the367 currently active locale).368 369 * ``LANGUAGE_CODE`` is the current user's preferred language, as a string.370 Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`,371 below.)372 373 * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a374 right-to-left language, e.g.: Hebrew, Arabic. If False it's a375 left-to-right language, e.g.: English, French, German etc.376 377 378 If you don't use the ``RequestContext`` extension, you can get those values379 with three tags::380 381 {% get_current_language as LANGUAGE_CODE %}382 {% get_available_languages as LANGUAGES %}383 {% get_current_language_bidi as LANGUAGE_BIDI %}384 385 These tags also require a ``{% load i18n %}``.386 387 Translation hooks are also available within any template block tag that accepts388 constant strings. In those cases, just use ``_()`` syntax to specify a389 translation string::390 391 {% some_special_tag _("Page not found") value|yesno:_("yes,no") %}392 393 In this case, both the tag and the filter will see the already-translated394 string, so they don't need to be aware of translations.395 396 .. note::397 In this example, the translation infrastructure will be passed the string398 ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The399 translated string will need to contain the comma so that the filter400 parsing code knows how to split up the arguments. For example, a German401 translator might translate the string ``"yes,no"`` as ``"ja,nein"``402 (keeping the comma intact).403 404 .. _Django templates: ../templates_python/405 406 Working with lazy translation objects407 -------------------------------------408 409 .. highlightlang:: python410 411 Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models412 and utility functions is a common operation. When you're working with these413 objects elsewhere in your code, you should ensure that you don't accidentally414 convert them to strings, because they should be converted as late as possible415 (so that the correct locale is in effect). This necessitates the use of a416 couple of helper functions.417 418 Joining strings: string_concat()419 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~420 421 Standard Python string joins (``''.join([...])``) will not work on lists422 containing lazy translation objects. Instead, you can use423 ``django.utils.translation.string_concat()``, which creates a lazy object that424 concatenates its contents *and* converts them to strings only when the result425 is included in a string. For example::426 427 from django.utils.translation import string_concat428 ...429 name = ugettext_lazy(u'John Lennon')430 instrument = ugettext_lazy(u'guitar')431 result = string_concat([name, ': ', instrument])432 433 In this case, the lazy translations in ``result`` will only be converted to434 strings when ``result`` itself is used in a string (usually at template435 rendering time).436 437 The allow_lazy() decorator438 ~~~~~~~~~~~~~~~~~~~~~~~~~~439 440 Django offers many utility functions (particularly in ``django.utils``) that441 take a string as their first argument and do something to that string. These442 functions are used by template filters as well as directly in other code.443 444 If you write your own similar functions and deal with translations, you'll445 face the problem of what to do when the first argument is a lazy translation446 object. You don't want to convert it to a string immediately, because you might447 be using this function outside of a view (and hence the current thread's locale448 setting will not be correct).449 450 For cases like this, use the ``django.utils.functional.allow_lazy()``451 decorator. It modifies the function so that *if* it's called with a lazy452 translation as the first argument, the function evaluation is delayed until it453 needs to be converted to a string.454 455 For example::456 457 from django.utils.functional import allow_lazy458 459 def fancy_utility_function(s, ...):460 # Do some conversion on string 's'461 ...462 fancy_utility_function = allow_lazy(fancy_utility_function, unicode)463 464 The ``allow_lazy()`` decorator takes, in addition to the function to decorate,465 a number of extra arguments (``*args``) specifying the type(s) that the466 original function can return. Usually, it's enough to include ``unicode`` here467 and ensure that your function returns only Unicode strings.468 469 Using this decorator means you can write your function and assume that the470 input is a proper string, then add support for lazy translation objects at the471 end.472 473 .. _how-to-create-language-files:474 475 2. How to create language files476 ===============================477 478 Once you've tagged your strings for later translation, you need to write (or479 obtain) the language translations themselves. Here's how that works.480 481 .. admonition:: Locale restrictions482 483 Django does not support localizing your application into a locale for484 which Django itself has not been translated. In this case, it will ignore485 your translation files. If you were to try this and Django supported it,486 you would inevitably see a mixture of translated strings (from your487 application) and English strings (from Django itself). If you want to488 support a locale for your application that is not already part of489 Django, you'll need to make at least a minimal translation of the Django490 core. See the relevant :ref:`LocaleMiddleware note<locale-middleware-notes>`491 for more details.492 493 Message files494 -------------495 496 The first step is to create a **message file** for a new language. A message497 file is a plain-text file, representing a single language, that contains all498 available translation strings and how they should be represented in the given499 language. Message files have a ``.po`` file extension.500 501 Django comes with a tool, ``django-admin.py makemessages``, that automates the502 creation and upkeep of these files.503 504 .. admonition:: A note to Django veterans505 506 The old tool ``bin/make-messages.py`` has been moved to the command507 ``django-admin.py makemessages`` to provide consistency throughout Django.508 509 To create or update a message file, run this command::510 511 django-admin.py makemessages -l de512 513 ...where ``de`` is the language code for the message file you want to create.514 The language code, in this case, is in locale format. For example, it's515 ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian German.516 517 The script should be run from one of three places:518 519 * The root directory of your Django project.520 * The root directory of your Django app.521 * The root ``django`` directory (not a Subversion checkout, but the one522 that is linked-to via ``$PYTHONPATH`` or is located somewhere on that523 path). This is only relevant when you are creating a translation for524 Django itself, see :ref:`contributing-translations`.525 526 The script runs over your project source tree or your application source tree527 and pulls out all strings marked for translation. It creates (or updates) a528 message file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de``529 example, the file will be ``locale/de/LC_MESSAGES/django.po``.530 531 By default ``django-admin.py makemessages`` examines every file that has the532 ``.html`` file extension. In case you want to override that default, use the533 ``--extension`` or ``-e`` option to specify the file extensions to examine::534 535 django-admin.py makemessages -l de -e txt536 537 Separate multiple extensions with commas and/or use ``-e`` or ``--extension``538 multiple times::539 540 django-admin.py makemessages -l=de -e=html,txt -e xml541 542 When `creating JavaScript translation catalogs`_ you need to use the special543 'djangojs' domain, **not** ``-e js``.544 545 .. admonition:: No gettext?546 547 If you don't have the ``gettext`` utilities installed, ``django-admin.py548 makemessages`` will create empty files. If that's the case, either install549 the ``gettext`` utilities or just copy the English message file550 (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting551 point; it's just an empty translation file.552 553 .. admonition:: Working on Windows?554 555 If you're using Windows and need to install the GNU gettext utilities so556 ``django-admin makemessages`` works see `gettext on Windows`_ for more557 information.558 559 The format of ``.po`` files is straightforward. Each ``.po`` file contains a560 small bit of metadata, such as the translation maintainer's contact561 information, but the bulk of the file is a list of **messages** -- simple562 mappings between translation strings and the actual translated text for the563 particular language.564 565 For example, if your Django app contained a translation string for the text566 ``"Welcome to my site."``, like so::567 568 _("Welcome to my site.")569 570 ...then ``django-admin.py makemessages`` will have created a ``.po`` file571 containing the following snippet -- a message::572 573 #: path/to/python/module.py:23574 msgid "Welcome to my site."575 msgstr ""576 577 A quick explanation:578 579 * ``msgid`` is the translation string, which appears in the source. Don't580 change it.581 * ``msgstr`` is where you put the language-specific translation. It starts582 out empty, so it's your responsibility to change it. Make sure you keep583 the quotes around your translation.584 * As a convenience, each message includes, in the form of a comment line585 prefixed with ``#`` and located above the ``msgid`` line, the filename586 and line number from which the translation string was gleaned.587 588 Long messages are a special case. There, the first string directly after the589 ``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be590 written over the next few lines as one string per line. Those strings are591 directly concatenated. Don't forget trailing spaces within the strings;592 otherwise, they'll be tacked together without whitespace!593 594 .. admonition:: Mind your charset595 596 When creating a PO file with your favorite text editor, first edit597 the charset line (search for ``"CHARSET"``) and set it to the charset598 you'll be using to edit the content. Due to the way the ``gettext`` tools599 work internally and because we want to allow non-ASCII source strings in600 Django's core and your applications, you **must** use UTF-8 as the encoding601 for your PO file. This means that everybody will be using the same602 encoding, which is important when Django processes the PO files.603 604 To reexamine all source code and templates for new translation strings and605 update all message files for **all** languages, run this::606 607 django-admin.py makemessages -a608 609 Compiling message files610 -----------------------611 612 After you create your message file -- and each time you make changes to it --613 you'll need to compile it into a more efficient form, for use by ``gettext``.614 Do this with the ``django-admin.py compilemessages`` utility.615 616 This tool runs over all available ``.po`` files and creates ``.mo`` files,617 which are binary files optimized for use by ``gettext``. In the same directory618 from which you ran ``django-admin.py makemessages``, run ``django-admin.py619 compilemessages`` like this::620 621 django-admin.py compilemessages622 623 That's it. Your translations are ready for use.624 625 .. admonition:: A note to Django veterans626 627 The old tool ``bin/compile-messages.py`` has been moved to the command628 ``django-admin.py compilemessages`` to provide consistency throughout629 Django.630 631 .. admonition:: Working on Windows?632 633 If you're using Windows and need to install the GNU gettext utilities so634 ``django-admin compilemessages`` works see `gettext on Windows`_ for more635 information.636 637 .. _how-django-discovers-language-preference:638 639 3. How Django discovers language preference640 ===========================================641 642 Once you've prepared your translations -- or, if you just want to use the643 translations that come with Django -- you'll just need to activate translation644 for your app.645 646 Behind the scenes, Django has a very flexible model of deciding which language647 should be used -- installation-wide, for a particular user, or both.648 649 To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`.650 Django uses this language as the default translation -- the final attempt if no651 other translator finds a translation.652 653 If all you want to do is run Django with your native language, and a language654 file is available for your language, all you need to do is set655 ``LANGUAGE_CODE``.656 657 If you want to let each individual user specify which language he or she658 prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language659 selection based on data from the request. It customizes content for each user.660 661 To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'``662 to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you663 should follow these guidelines:664 665 * Make sure it's one of the first middlewares installed.666 * It should come after ``SessionMiddleware``, because ``LocaleMiddleware``667 makes use of session data.668 * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it.669 670 For example, your ``MIDDLEWARE_CLASSES`` might look like this::671 672 MIDDLEWARE_CLASSES = (673 'django.contrib.sessions.middleware.SessionMiddleware',674 'django.middleware.locale.LocaleMiddleware',675 'django.middleware.common.CommonMiddleware',676 )677 678 (For more on middleware, see the :ref:`middleware documentation679 <topics-http-middleware>`.)680 681 ``LocaleMiddleware`` tries to determine the user's language preference by682 following this algorithm:683 684 * First, it looks for a ``django_language`` key in the current user's685 session.686 687 * Failing that, it looks for a cookie.688 689 .. versionchanged:: 1.0690 691 In Django version 0.96 and before, the cookie's name is hard-coded to692 ``django_language``. In Django 1,0, The cookie name is set by the693 ``LANGUAGE_COOKIE_NAME`` setting. (The default name is694 ``django_language``.)695 696 * Failing that, it looks at the ``Accept-Language`` HTTP header. This697 header is sent by your browser and tells the server which language(s) you698 prefer, in order by priority. Django tries each language in the header699 until it finds one with available translations.700 701 * Failing that, it uses the global ``LANGUAGE_CODE`` setting.702 703 .. _locale-middleware-notes:704 705 Notes:706 707 * In each of these places, the language preference is expected to be in the708 standard language format, as a string. For example, Brazilian Portuguese709 is ``pt-br``.710 711 * If a base language is available but the sublanguage specified is not,712 Django uses the base language. For example, if a user specifies ``de-at``713 (Austrian German) but Django only has ``de`` available, Django uses714 ``de``.715 716 * Only languages listed in the :setting:`LANGUAGES` setting can be selected.717 If you want to restrict the language selection to a subset of provided718 languages (because your application doesn't provide all those languages),719 set ``LANGUAGES`` to a list of languages. For example::720 721 LANGUAGES = (722 ('de', _('German')),723 ('en', _('English')),724 )725 726 This example restricts languages that are available for automatic727 selection to German and English (and any sublanguage, like de-ch or728 en-us).729 730 .. _LANGUAGES setting: ../settings/#languages731 732 * If you define a custom ``LANGUAGES`` setting, as explained in the733 previous bullet, it's OK to mark the languages as translation strings734 -- but use a "dummy" ``ugettext()`` function, not the one in735 ``django.utils.translation``. You should *never* import736 ``django.utils.translation`` from within your settings file, because that737 module in itself depends on the settings, and that would cause a circular738 import.739 740 The solution is to use a "dummy" ``ugettext()`` function. Here's a sample741 settings file::742 743 ugettext = lambda s: s744 745 LANGUAGES = (746 ('de', ugettext('German')),747 ('en', ugettext('English')),748 )749 750 With this arrangement, ``django-admin.py makemessages`` will still find751 and mark these strings for translation, but the translation won't happen752 at runtime -- so you'll have to remember to wrap the languages in the753 *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime.754 755 * The ``LocaleMiddleware`` can only select languages for which there is a756 Django-provided base translation. If you want to provide translations757 for your application that aren't already in the set of translations758 in Django's source tree, you'll want to provide at least basic759 translations for that language. For example, Django uses technical760 message IDs to translate date formats and time formats -- so you will761 need at least those translations for the system to work correctly.762 763 A good starting point is to copy the English ``.po`` file and to764 translate at least the technical messages -- maybe the validation765 messages, too.766 767 Technical message IDs are easily recognized; they're all upper case. You768 don't translate the message ID as with other messages, you provide the769 correct local variant on the provided English value. For example, with770 ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), this would771 be the format string that you want to use in your language. The format772 is identical to the format strings used by the ``now`` template tag.773 774 Once ``LocaleMiddleware`` determines the user's preference, it makes this775 preference available as ``request.LANGUAGE_CODE`` for each776 :class:`~django.http.HttpRequest`. Feel free to read this value in your view777 code. Here's a simple example::778 779 def hello_world(request, count):780 if request.LANGUAGE_CODE == 'de-at':781 return HttpResponse("You prefer to read Austrian German.")782 else:783 return HttpResponse("You prefer to read another language.")784 785 Note that, with static (middleware-less) translation, the language is in786 ``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's787 in ``request.LANGUAGE_CODE``.788 789 .. _settings file: ../settings/790 .. _middleware documentation: ../middleware/791 .. _session: ../sessions/792 .. _request object: ../request_response/#httprequest-objects793 794 .. _translations-in-your-own-projects:795 796 Using translations in your own projects797 =======================================798 799 Django looks for translations by following this algorithm:800 801 * First, it looks for a ``locale`` directory in the application directory802 of the view that's being called. If it finds a translation for the803 selected language, the translation will be installed.804 * Next, it looks for a ``locale`` directory in the project directory. If it805 finds a translation, the translation will be installed.806 * Finally, it checks the Django-provided base translation in807 ``django/conf/locale``.808 809 This way, you can write applications that include their own translations, and810 you can override base translations in your project path. Or, you can just build811 a big project out of several apps and put all translations into one big project812 message file. The choice is yours.813 814 .. note::815 816 If you're using manually configured settings, as described817 :ref:`settings-without-django-settings-module`, the ``locale`` directory in818 the project directory will not be examined, since Django loses the ability819 to work out the location of the project directory. (Django normally uses820 the location of the settings file to determine this, and a settings file821 doesn't exist if you're manually configuring your settings.)822 823 All message file repositories are structured the same way. They are:824 825 * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``826 * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``827 * All paths listed in ``LOCALE_PATHS`` in your settings file are828 searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)``829 * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``830 831 To create message files, you use the same ``django-admin.py makemessages``832 tool as with the Django message files. You only need to be in the right place833 -- in the directory where either the ``conf/locale`` (in case of the source834 tree) or the ``locale/`` (in case of app messages or project messages)835 directory are located. And you use the same ``django-admin.py836 compilemessages`` to produce the binary ``django.mo`` files that are used by837 ``gettext``.838 839 You can also run ``django-admin.py compilemessages840 --settings=path.to.settings`` to make the compiler process all the directories841 in your ``LOCALE_PATHS`` setting.842 843 Application message files are a bit complicated to discover -- they need the844 ``LocaleMiddleware``. If you don't use the middleware, only the Django message845 files and project message files will be processed.846 847 Finally, you should give some thought to the structure of your translation848 files. If your applications need to be delivered to other users and will849 be used in other projects, you might want to use app-specific translations.850 But using app-specific translations and project translations could produce851 weird problems with ``makemessages``: ``makemessages`` will traverse all852 directories below the current path and so might put message IDs into the853 project message file that are already in application message files.854 855 The easiest way out is to store applications that are not part of the project856 (and so carry their own translations) outside the project tree. That way,857 ``django-admin.py makemessages`` on the project level will only translate858 strings that are connected to your explicit project and not strings that are859 distributed independently.860 861 The ``set_language`` redirect view862 ==================================863 864 As a convenience, Django comes with a view, ``django.views.i18n.set_language``,865 that sets a user's language preference and redirects back to the previous page.866 867 Activate this view by adding the following line to your URLconf::868 869 (r'^i18n/', include('django.conf.urls.i18n')),870 871 (Note that this example makes the view available at ``/i18n/setlang/``.)872 873 The view expects to be called via the ``POST`` method, with a ``language``874 parameter set in request. If session support is enabled, the view875 saves the language choice in the user's session. Otherwise, it saves the876 language choice in a cookie that is by default named ``django_language``.877 (The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.)878 879 After setting the language choice, Django redirects the user, following this880 algorithm:881 882 * Django looks for a ``next`` parameter in the ``POST`` data.883 * If that doesn't exist, or is empty, Django tries the URL in the884 ``Referrer`` header.885 * If that's empty -- say, if a user's browser suppresses that header --886 then the user will be redirected to ``/`` (the site root) as a fallback.887 888 Here's example HTML template code:889 890 .. code-block:: html+django891 892 <form action="/i18n/setlang/" method="post">893 <input name="next" type="hidden" value="/next/page/" />894 <select name="language">895 {% for lang in LANGUAGES %}896 <option value="{{ lang.0 }}">{{ lang.1 }}</option>897 {% endfor %}898 </select>899 <input type="submit" value="Go" />900 </form>901 902 Translations and JavaScript903 ===========================904 905 Adding translations to JavaScript poses some problems:906 907 * JavaScript code doesn't have access to a ``gettext`` implementation.908 909 * JavaScript code doesn't have access to .po or .mo files; they need to be910 delivered by the server.911 912 * The translation catalogs for JavaScript should be kept as small as913 possible.914 915 Django provides an integrated solution for these problems: It passes the916 translations into JavaScript, so you can call ``gettext``, etc., from within917 JavaScript.918 919 The ``javascript_catalog`` view920 -------------------------------921 922 The main solution to these problems is the ``javascript_catalog`` view, which923 sends out a JavaScript code library with functions that mimic the ``gettext``924 interface, plus an array of translation strings. Those translation strings are925 taken from the application, project or Django core, according to what you926 specify in either the info_dict or the URL.927 928 You hook it up like this::929 930 js_info_dict = {931 'packages': ('your.app.package',),932 }933 934 urlpatterns = patterns('',935 (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),936 )937 938 Each string in ``packages`` should be in Python dotted-package syntax (the939 same format as the strings in ``INSTALLED_APPS``) and should refer to a package940 that contains a ``locale`` directory. If you specify multiple packages, all941 those catalogs are merged into one catalog. This is useful if you have942 JavaScript that uses strings from different applications.943 944 You can make the view dynamic by putting the packages into the URL pattern::945 946 urlpatterns = patterns('',947 (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),948 )949 950 With this, you specify the packages as a list of package names delimited by '+'951 signs in the URL. This is especially useful if your pages use code from952 different apps and this changes often and you don't want to pull in one big953 catalog file. As a security measure, these values can only be either954 ``django.conf`` or any package from the ``INSTALLED_APPS`` setting.955 956 Using the JavaScript translation catalog957 ----------------------------------------958 959 To use the catalog, just pull in the dynamically generated script like this::960 961 <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script>962 963 This uses reverse URL lookup to find the URL of the JavaScript catalog view.964 When the catalog is loaded, your JavaScript code can use the standard965 ``gettext`` interface to access it::966 967 document.write(gettext('this is to be translated'));968 969 There is also an ``ngettext`` interface::970 971 var object_cnt = 1 // or 0, or 2, or 3, ...972 s = ngettext('literal for the singular case',973 'literal for the plural case', object_cnt);974 975 and even a string interpolation function::976 977 function interpolate(fmt, obj, named);978 979 The interpolation syntax is borrowed from Python, so the ``interpolate``980 function supports both positional and named interpolation:981 982 * Positional interpolation: ``obj`` contains a JavaScript Array object983 whose elements values are then sequentially interpolated in their984 corresponding ``fmt`` placeholders in the same order they appear.985 For example::986 987 fmts = ngettext('There is %s object. Remaining: %s',988 'There are %s objects. Remaining: %s', 11);989 s = interpolate(fmts, [11, 20]);990 // s is 'There are 11 objects. Remaining: 20'991 992 * Named interpolation: This mode is selected by passing the optional993 boolean ``named`` parameter as true. ``obj`` contains a JavaScript994 object or associative array. For example::995 996 d = {997 count: 10998 total: 50999 };1000 1001 fmts = ngettext('Total: %(total)s, there is %(count)s object',1002 'there are %(count)s of a total of %(total)s objects', d.count);1003 s = interpolate(fmts, d, true);1004 1005 You shouldn't go over the top with string interpolation, though: this is still1006 JavaScript, so the code has to make repeated regular-expression substitutions.1007 This isn't as fast as string interpolation in Python, so keep it to those1008 cases where you really need it (for example, in conjunction with ``ngettext``1009 to produce proper pluralizations).1010 1011 Creating JavaScript translation catalogs1012 ----------------------------------------1013 1014 You create and update the translation catalogs the same way as the other1015 1016 Django translation catalogs -- with the ``django-admin.py makemessages`` tool.1017 The only difference is you need to provide a ``-d djangojs`` parameter, like1018 this::1019 1020 django-admin.py makemessages -d djangojs -l de1021 1022 This would create or update the translation catalog for JavaScript for German.1023 After updating translation catalogs, just run ``django-admin.py1024 compilemessages`` the same way as you do with normal Django translation1025 catalogs.1026 1027 Specialties of Django translation1028 ==================================1029 1030 If you know ``gettext``, you might note these specialties in the way Django1031 does translation:1032 1033 * The string domain is ``django`` or ``djangojs``. This string domain is1034 used to differentiate between different programs that store their data1035 in a common message-file library (usually ``/usr/share/locale/``). The1036 ``django`` domain is used for python and template translation strings1037 and is loaded into the global translation catalogs. The ``djangojs``1038 domain is only used for JavaScript translation catalogs to make sure1039 that those are as small as possible.1040 * Django doesn't use ``xgettext`` alone. It uses Python wrappers around1041 ``xgettext`` and ``msgfmt``. This is mostly for convenience.1042 1043 ``gettext`` on Windows1044 ======================1045 1046 This is only needed for people who either want to extract message IDs or1047 compile message files (``.po``). Translation work itself just involves editing1048 existing files of this type, but if you want to create your own message files,1049 or want to test or compile a changed message file, you will need the1050 ``gettext`` utilities:1051 1052 * Download the following zip files from the GNOME servers1053 http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one1054 of its mirrors_1055 1056 * ``gettext-runtime-X.zip``1057 * ``gettext-tools-X.zip``1058 1059 ``X`` is the version number, we recomend using ``0.15`` or higher.1060 1061 * Extract the contents of the ``bin\`` directories in both files to the1062 same folder on your system (i.e. ``C:\Program Files\gettext-utils``)1063 1064 * Update the system PATH:1065 1066 * ``Control Panel > System > Advanced > Environment Variables``1067 * In the ``System variables`` list, click ``Path``, click ``Edit``1068 * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the1069 ``Variable value`` field1070 1071 .. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS1072 1073 You may also use ``gettext`` binaries you have obtained elsewhere, so long as1074 the ``xgettext --version`` command works properly. Some version 0.14.4 binaries1075 have been found to not support this command. Do not attempt to use Django1076 translation utilities with a ``gettext`` package if the command ``xgettext1077 --version`` entered at a Windows command prompt causes a popup window saying1078 "xgettext.exe has generated errors and will be closed by Windows". -
new file docs/topics/i18n/deployment.txt
diff -r 4755c937c02f 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 If you do need internationalization 21 =================================== 22 23 .. _how-django-discovers-language-preference: 24 25 How Django discovers language preference 26 ---------------------------------------- 27 28 Once you've prepared your translations -- or, if you just want to use the 29 translations that come with Django -- you'll just need to activate translation 30 for your app. 31 32 Behind the scenes, Django has a very flexible model of deciding which language 33 should be used -- installation-wide, for a particular user, or both. 34 35 To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`. 36 Django uses this language as the default translation -- the final attempt if no 37 other translator finds a translation. 38 39 If all you want to do is run Django with your native language, and a language 40 file is available for it, all you need to do is set ``LANGUAGE_CODE``. 41 42 If you want to let each individual user specify which language he or she 43 prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language 44 selection based on data from the request. It customizes content for each user. 45 46 To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'`` 47 to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you 48 should follow these guidelines: 49 50 * Make sure it's one of the first middlewares installed. 51 * It should come after ``SessionMiddleware``, because ``LocaleMiddleware`` 52 makes use of session data. 53 * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it. 54 55 For example, your ``MIDDLEWARE_CLASSES`` might look like this:: 56 57 MIDDLEWARE_CLASSES = ( 58 'django.contrib.sessions.middleware.SessionMiddleware', 59 'django.middleware.locale.LocaleMiddleware', 60 'django.middleware.common.CommonMiddleware', 61 ) 62 63 (For more on middleware, see the :ref:`middleware documentation 64 <topics-http-middleware>`.) 65 66 ``LocaleMiddleware`` tries to determine the user's language preference by 67 following this algorithm: 68 69 * First, it looks for a ``django_language`` key in the current user's 70 session. 71 72 * Failing that, it looks for a cookie. 73 74 .. versionchanged:: 1.0 75 76 In Django version 0.96 and before, the cookie's name is hard-coded to 77 ``django_language``. In Django 1,0, The cookie name is set by the 78 ``LANGUAGE_COOKIE_NAME`` setting. (The default name is 79 ``django_language``.) 80 81 * Failing that, it looks at the ``Accept-Language`` HTTP header. This 82 header is sent by your browser and tells the server which language(s) you 83 prefer, in order by priority. Django tries each language in the header 84 until it finds one with available translations. 85 86 * Failing that, it uses the global ``LANGUAGE_CODE`` setting. 87 88 .. _locale-middleware-notes: 89 90 Notes: 91 92 * In each of these places, the language preference is expected to be in the 93 standard :term:`language format<language code>`, as a string. For example, 94 Brazilian Portuguese is ``pt-br``. 95 96 * If a base language is available but the sublanguage specified is not, 97 Django uses the base language. For example, if a user specifies ``de-at`` 98 (Austrian German) but Django only has ``de`` available, Django uses 99 ``de``. 100 101 * Only languages listed in the :setting:`LANGUAGES` setting can be selected. 102 If you want to restrict the language selection to a subset of provided 103 languages (because your application doesn't provide all those languages), 104 set ``LANGUAGES`` to a list of languages. For example:: 105 106 LANGUAGES = ( 107 ('de', _('German')), 108 ('en', _('English')), 109 ) 110 111 This example restricts languages that are available for automatic 112 selection to German and English (and any sublanguage, like de-ch or 113 en-us). 114 115 .. _LANGUAGES setting: ../settings/#languages 116 117 * If you define a custom ``LANGUAGES`` setting, as explained in the 118 previous bullet, it's OK to mark the languages as translation strings 119 -- but use a "dummy" ``ugettext()`` function, not the one in 120 ``django.utils.translation``. You should *never* import 121 ``django.utils.translation`` from within your settings file, because that 122 module in itself depends on the settings, and that would cause a circular 123 import. 124 125 The solution is to use a "dummy" ``ugettext()`` function. Here's a sample 126 settings file:: 127 128 ugettext = lambda s: s 129 130 LANGUAGES = ( 131 ('de', ugettext('German')), 132 ('en', ugettext('English')), 133 ) 134 135 With this arrangement, ``django-admin.py makemessages`` will still find 136 and mark these strings for translation, but the translation won't happen 137 at runtime -- so you'll have to remember to wrap the languages in the 138 *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime. 139 140 * The ``LocaleMiddleware`` can only select languages for which there is a 141 Django-provided base translation. If you want to provide translations 142 for your application that aren't already in the set of translations 143 in Django's source tree, you'll want to provide at least a basic 144 one as described in the :ref:`Locale restrictions<locale-restrictions>` 145 note. 146 147 Once ``LocaleMiddleware`` determines the user's preference, it makes this 148 preference available as ``request.LANGUAGE_CODE`` for each 149 :class:`~django.http.HttpRequest`. Feel free to read this value in your view 150 code. Here's a simple example:: 151 152 def hello_world(request, count): 153 if request.LANGUAGE_CODE == 'de-at': 154 return HttpResponse("You prefer to read Austrian German.") 155 else: 156 return HttpResponse("You prefer to read another language.") 157 158 Note that, with static (middleware-less) translation, the language is in 159 ``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's 160 in ``request.LANGUAGE_CODE``. 161 162 .. _settings file: ../settings/ 163 .. _middleware documentation: ../middleware/ 164 .. _session: ../sessions/ 165 .. _request object: ../request_response/#httprequest-objects 166 167 How Django discovers translations 168 --------------------------------- 169 170 As described in :ref:`using-translations-in-your-own-projects`, 171 at runtime, Django looks for translations by following this algorithm: 172 173 * First, it looks for a ``locale`` directory in the application directory 174 of the view that's being called. If it finds a translation for the 175 selected language, the translation will be installed. 176 * Next, it looks for a ``locale`` directory in the project directory. If it 177 finds a translation, the translation will be installed. 178 * Finally, it checks the Django-provided base translation in 179 ``django/conf/locale``. 180 181 In all cases the name of the directory containing the translation is expected to 182 be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``, 183 etc. -
new file docs/topics/i18n/index.txt
diff -r 4755c937c02f 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 templates. 11 12 Essentially, Django does two things: 13 14 * It lets developers and template authors specify which parts of their apps 15 should be translatable. 16 * It uses these hooks to translate Web apps for particular users according 17 to their language preferences. 18 19 The complete process can be seen as divided in three stages. It is also possible 20 to identify an identical number of roles with very well defined responsabilities 21 associated with each of these tasks (although it's perfectly normal if you 22 find yourself performing more than one of these roles): 23 24 * For applicacion authors wishing to make sure their Django apps can be 25 used in different locales: Internationalization. 26 * For translators wanting to translate Django apps: Localization. 27 * For system administrators/final users setting up internationalized apps or 28 developers integrating third party apps: Deployment. 29 30 .. toctree:: 31 :maxdepth: 1 32 33 internationalization 34 localization 35 deployment 36 37 .. _ seealso:: 38 39 For more general information about the topic, see the `GNU gettext documentation`_ 40 and the `Wikipedia article`_ 41 42 .. _GNU gettext documentation: http://www.gnu.org/software/gettext/manual/gettext.html#Concepts 43 .. _Wikipedia article: http://en.wikipedia.org/wiki/Internationalization_and_localization 44 45 Glossary 46 ======== 47 48 First lets define some terms that will help us to handle a common language: 49 50 .. glossary:: 51 52 locale name 53 A locale name, either a language specification of the form ``ll`` or a 54 combined language and country specification of the form ``ll_CC``. 55 Examples: ``it``, ``de_AT``, ``es``, ``pt_BR``. Note the underscore in 56 some of them and the case of the part located to its right. 57 58 language code 59 Represents the name of a language. Browsers send the names of the 60 languages they accept in the ``Accept-Language`` HTTP header using this 61 format. Examples: ``it``, ``de-at``, ``es``, ``pt-br``. Note the ``-`` 62 separator. 63 64 message file 65 A message file is a plain-text file, representing a single language, that 66 contains all available :term:`translation string`\s and how they should be 67 represented in the given language. Message files have a ``.po`` file 68 extension. 69 70 translation string 71 A literal that can be translated. 72 73 .. _specialties-of-django-i18n: 74 75 Specialties of Django translation 76 ================================== 77 78 Django's translation machinery uses the standard ``gettext`` module that comes 79 with Python. If you know ``gettext``, you might note these specialties in the 80 way Django does translation: 81 82 * The string domain is ``django`` or ``djangojs``. This string domain is 83 used to differentiate between different programs that store their data 84 in a common message-file library (usually ``/usr/share/locale/``). The 85 ``django`` domain is used for python and template translation strings 86 and is loaded into the global translation catalogs. The ``djangojs`` 87 domain is only used for JavaScript translation catalogs to make sure 88 that those are as small as possible. 89 * Django doesn't use ``xgettext`` alone. It uses Python wrappers around 90 ``xgettext`` and ``msgfmt``. This is mostly for convenience. 91 92 .. _technical-messages: 93 94 Django technical message IDs 95 ---------------------------- 96 97 Django uses technical message IDs to translate date formats and time formats. 98 Technical message IDs are :term:`translation string`\s and can be easily 99 recognized; they're all upper case. You don't translate the message ID as with 100 other translation strings, you provide the correct local variant on the provided 101 English value. The format is identical to the format strings used by the 102 ``now`` template tag. 103 104 For example, with ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), 105 this would be the format string that you want to use in your language. A Django 106 contributor localizing it to Spanish probably would provide a ``"j N Y P"`` 107 "translation" for it in the relevant ``django.po`` file:: 108 109 msgid "DATETIME_FORMAT" 110 msgstr "j N Y P" -
new file docs/topics/i18n/internationalization.txt
diff -r 4755c937c02f 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. 12 13 You, the Django developer, can accomplish this goal by adding a minimal amount 14 xof hooks to your Python (and JavaScript) code and templates. These hooks are 15 called **translation strings**. They tell Django: "This text should be 16 translated into the end user's language, if a translation for this text is 17 available in that language." It's your responsibility to mark translatable 18 strings; the system can only translate strings it knows about. 19 20 Django takes care of using these hooks to translate Web apps, on the fly, 21 according to users' language preferences. 22 23 Specifying translation strings: In Python code 24 ============================================== 25 26 Standard translation 27 -------------------- 28 29 Specify a translation string by using the function ``ugettext()``. It's 30 convention to import this as a shorter alias, ``_``, to save typing. 31 32 .. note:: 33 Python's standard library ``gettext`` module installs ``_()`` into the 34 global namespace, as an alias for ``gettext()``. In Django, we have chosen 35 not to follow this practice, for a couple of reasons: 36 37 1. For international character set (Unicode) support, ``ugettext()`` is 38 more useful than ``gettext()``. Sometimes, you should be using 39 ``ugettext_lazy()`` as the default translation method for a particular 40 file. Without ``_()`` in the global namespace, the developer has to 41 think about which is the most appropriate translation function. 42 43 2. The underscore character (``_``) is used to represent "the previous 44 result" in Python's interactive shell and doctest tests. Installing a 45 global ``_()`` function causes interference. Explicitly importing 46 ``ugettext()`` as ``_()`` avoids this problem. 47 48 .. highlightlang:: python 49 50 In this example, the text ``"Welcome to my site."`` is marked as a translation 51 string:: 52 53 from django.utils.translation import ugettext as _ 54 55 def my_view(request): 56 output = _("Welcome to my site.") 57 return HttpResponse(output) 58 59 Obviously, you could code this without using the alias. This example is 60 identical to the previous one:: 61 62 from django.utils.translation import ugettext 63 64 def my_view(request): 65 output = ugettext("Welcome to my site.") 66 return HttpResponse(output) 67 68 Translation works on computed values. This example is identical to the previous 69 two:: 70 71 def my_view(request): 72 words = ['Welcome', 'to', 'my', 'site.'] 73 output = _(' '.join(words)) 74 return HttpResponse(output) 75 76 Translation works on variables. Again, here's an identical example:: 77 78 def my_view(request): 79 sentence = 'Welcome to my site.' 80 output = _(sentence) 81 return HttpResponse(output) 82 83 (The caveat with using variables or computed values, as in the previous two 84 examples, is that Django's translation-string-detecting utility, 85 ``django-admin.py makemessages``, won't be able to find these strings. More on 86 ``makemessages`` later.) 87 88 The strings you pass to ``_()`` or ``ugettext()`` can take placeholders, 89 specified with Python's standard named-string interpolation syntax. Example:: 90 91 def my_view(request, m, d): 92 output = _('Today is %(month)s, %(day)s.') % {'month': m, 'day': d} 93 return HttpResponse(output) 94 95 This technique lets language-specific translations reorder the placeholder 96 text. For example, an English translation may be ``"Today is November, 26."``, 97 while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the 98 placeholders (the month and the day) with their positions swapped. 99 100 For this reason, you should use named-string interpolation (e.g., ``%(day)s``) 101 instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you 102 have more than a single parameter. If you used positional interpolation, 103 translations wouldn't be able to reorder placeholder text. 104 105 Marking strings as no-op 106 ------------------------ 107 108 Use the function ``django.utils.translation.ugettext_noop()`` to mark a string 109 as a translation string without translating it. The string is later translated 110 from a variable. 111 112 Use this if you have constant strings that should be stored in the source 113 language because they are exchanged over systems or users -- such as strings in 114 a database -- but should be translated at the last possible point in time, such 115 as when the string is presented to the user. 116 117 Pluralization 118 ------------- 119 120 Use the function ``django.utils.translation.ungettext()`` to specify pluralized 121 messages. 122 123 ``ungettext`` takes three arguments: the singular translation string, the plural 124 translation string and the number of objects. 125 126 This function is useful when you need your Django application to be localizable 127 to languages where the number and complexity of `plural forms 128 <http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is 129 greater than the two forms used in English ('object' for the singular and 130 'objects' for all the cases where ``count`` is different from zero, irrespective 131 of its value.) 132 133 For example:: 134 135 from django.utils.translation import ungettext 136 def hello_world(request, count): 137 page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % { 138 'count': count, 139 } 140 return HttpResponse(page) 141 142 In this example the number of objects is passed to the translation languages as 143 the ``count`` variable. 144 145 Lets see a slightly more complex usage example:: 146 147 from django.utils.translation import ungettext 148 149 count = Report.objects.count() 150 if count == 1: 151 name = Report._meta.verbose_name 152 else: 153 name = Report._meta.verbose_name_plural 154 155 text = ungettext( 156 'There is %(count)d %(name)s available.', 157 'There are %(count)d %(name)s available.', 158 count 159 ) % { 160 'count': count, 161 'name': name 162 } 163 164 Here we reuse localizable, hopefully already translated literals (contained in 165 the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for 166 other parts of the sentence so all of it is consistently based on the 167 cardinality of the elements at play. 168 169 .. _pluralization-var-notes: 170 171 .. note:: 172 173 When using this technique, make sure you use a single name for every 174 extrapolated variable included in the literal. In the example above note how 175 we used the ``name`` Python variable in both translation strings. This 176 example would fail:: 177 178 from django.utils.translation import ungettext 179 from myapp.models import Report 180 181 count = Report.objects.count() 182 d = { 183 'count': count, 184 'name': Report._meta.verbose_name 185 'plural_name': Report._meta.verbose_name_plural 186 } 187 text = ungettext( 188 'There is %(count)d %(name)s available.', 189 'There are %(count)d %(plural_name)s available.', 190 count 191 ) % d 192 193 You would get a ``a format specification for argument 'name', as in 194 'msgstr[0]', doesn't exist in 'msgid'`` error when running 195 ``django-admin.py compilemessages`` or a ``KeyError`` Python exception at 196 runtime. 197 198 .. _lazy-translations: 199 200 Lazy translation 201 ---------------- 202 203 Use the function ``django.utils.translation.ugettext_lazy()`` to translate 204 strings lazily -- when the value is accessed rather than when the 205 ``ugettext_lazy()`` function is called. 206 207 For example, to translate a model's ``help_text``, do the following:: 208 209 from django.utils.translation import ugettext_lazy 210 211 class MyThing(models.Model): 212 name = models.CharField(help_text=ugettext_lazy('This is the help text')) 213 214 In this example, ``ugettext_lazy()`` stores a lazy reference to the string -- 215 not the actual translation. The translation itself will be done when the string 216 is used in a string context, such as template rendering on the Django admin 217 site. 218 219 The result of a ``ugettext_lazy()`` call can be used wherever you would use a 220 unicode string (an object with type ``unicode``) in Python. If you try to use 221 it where a bytestring (a ``str`` object) is expected, things will not work as 222 expected, since a ``ugettext_lazy()`` object doesn't know how to convert 223 itself to a bytestring. You can't use a unicode string inside a bytestring, 224 either, so this is consistent with normal Python behavior. For example:: 225 226 # This is fine: putting a unicode proxy into a unicode string. 227 u"Hello %s" % ugettext_lazy("people") 228 229 # This will not work, since you cannot insert a unicode object 230 # into a bytestring (nor can you insert our unicode proxy there) 231 "Hello %s" % ugettext_lazy("people") 232 233 If you ever see output that looks like ``"hello 234 <django.utils.functional...>"``, you have tried to insert the result of 235 ``ugettext_lazy()`` into a bytestring. That's a bug in your code. 236 237 If you don't like the verbose name ``ugettext_lazy``, you can just alias it as 238 ``_`` (underscore), like so:: 239 240 from django.utils.translation import ugettext_lazy as _ 241 242 class MyThing(models.Model): 243 name = models.CharField(help_text=_('This is the help text')) 244 245 Always use lazy translations in :ref:`Django models <topics-db-models>`. 246 Field names and table names should be marked for translation (otherwise, they 247 won't be translated in the admin interface). This means writing explicit 248 ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class, 249 though, rather than relying on Django's default determination of 250 ``verbose_name`` and ``verbose_name_plural`` by looking at the model's class 251 name:: 252 253 from django.utils.translation import ugettext_lazy as _ 254 255 class MyThing(models.Model): 256 name = models.CharField(_('name'), help_text=_('This is the help text')) 257 class Meta: 258 verbose_name = _('my thing') 259 verbose_name_plural = _('mythings') 260 261 Working with lazy translation objects 262 ------------------------------------- 263 264 .. highlightlang:: python 265 266 Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models 267 and utility functions is a common operation. When you're working with these 268 objects elsewhere in your code, you should ensure that you don't accidentally 269 convert them to strings, because they should be converted as late as possible 270 (so that the correct locale is in effect). This necessitates the use of a 271 couple of helper functions. 272 273 Joining strings: string_concat() 274 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 275 276 Standard Python string joins (``''.join([...])``) will not work on lists 277 containing lazy translation objects. Instead, you can use 278 ``django.utils.translation.string_concat()``, which creates a lazy object that 279 concatenates its contents *and* converts them to strings only when the result 280 is included in a string. For example:: 281 282 from django.utils.translation import string_concat 283 ... 284 name = ugettext_lazy(u'John Lennon') 285 instrument = ugettext_lazy(u'guitar') 286 result = string_concat([name, ': ', instrument]) 287 288 In this case, the lazy translations in ``result`` will only be converted to 289 strings when ``result`` itself is used in a string (usually at template 290 rendering time). 291 292 The allow_lazy() decorator 293 ~~~~~~~~~~~~~~~~~~~~~~~~~~ 294 295 Django offers many utility functions (particularly in ``django.utils``) that 296 take a string as their first argument and do something to that string. These 297 functions are used by template filters as well as directly in other code. 298 299 If you write your own similar functions and deal with translations, you'll 300 face the problem of what to do when the first argument is a lazy translation 301 object. You don't want to convert it to a string immediately, because you might 302 be using this function outside of a view (and hence the current thread's locale 303 setting will not be correct). 304 305 For cases like this, use the ``django.utils.functional.allow_lazy()`` 306 decorator. It modifies the function so that *if* it's called with a lazy 307 translation as the first argument, the function evaluation is delayed until it 308 needs to be converted to a string. 309 310 For example:: 311 312 from django.utils.functional import allow_lazy 313 314 def fancy_utility_function(s, ...): 315 # Do some conversion on string 's' 316 ... 317 fancy_utility_function = allow_lazy(fancy_utility_function, unicode) 318 319 The ``allow_lazy()`` decorator takes, in addition to the function to decorate, 320 a number of extra arguments (``*args``) specifying the type(s) that the 321 original function can return. Usually, it's enough to include ``unicode`` here 322 and ensure that your function returns only Unicode strings. 323 324 Using this decorator means you can write your function and assume that the 325 input is a proper string, then add support for lazy translation objects at the 326 end. 327 328 Specifying translation strings: In template code 329 ================================================ 330 331 .. highlightlang:: html+django 332 333 Translations in :ref:`Django templates <topics-templates>` uses two template 334 tags and a slightly different syntax than in Python code. To give your template 335 access to these tags, put ``{% load i18n %}`` toward the top of your template. 336 337 The ``{% trans %}`` template tag translates either a constant string 338 (enclosed in single or double quotes) or variable content:: 339 340 <title>{% trans "This is the title." %}</title> 341 <title>{% trans myvar %}</title> 342 343 If the ``noop`` option is present, variable lookup still takes place but the 344 translation is skipped. This is useful when "stubbing out" content that will 345 require translation in the future:: 346 347 <title>{% trans "myvar" noop %}</title> 348 349 Internally, inline translations use an ``ugettext`` call. 350 351 It's not possible to mix a template variable inside a string within ``{% trans 352 %}``. If your translations require strings with variables (placeholders), use 353 ``{% blocktrans %}``:: 354 355 {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %} 356 357 To translate a template expression -- say, using template filters -- you need 358 to bind the expression to a local variable for use within the translation 359 block:: 360 361 {% blocktrans with value|filter as myvar %} 362 This will have {{ myvar }} inside. 363 {% endblocktrans %} 364 365 If you need to bind more than one expression inside a ``blocktrans`` tag, 366 separate the pieces with ``and``:: 367 368 {% blocktrans with book|title as book_t and author|title as author_t %} 369 This is {{ book_t }} by {{ author_t }} 370 {% endblocktrans %} 371 372 To pluralize, specify both the singular and plural forms with the 373 ``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and 374 ``{% endblocktrans %}``. Example:: 375 376 {% blocktrans count list|length as counter %} 377 There is only one {{ name }} object. 378 {% plural %} 379 There are {{ counter }} {{ name }} objects. 380 {% endblocktrans %} 381 382 When you use the pluralization feature and bind additional values to local 383 variables apart from the counter value that selects the translated literal to be 384 used, have in mind that the ``blocktrans`` construct is internally converted 385 to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext 386 variables <pluralization-var-notes>` apply. 387 388 Each ``RequestContext`` has access to three translation-specific variables: 389 390 * ``LANGUAGES`` is a list of tuples in which the first element is the 391 :term:`language code` and the second is the language name (translated into 392 the currently active locale). 393 394 * ``LANGUAGE_CODE`` is the current user's preferred language, as a string. 395 Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`.) 396 397 * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a 398 right-to-left language, e.g.: Hebrew, Arabic. If False it's a 399 left-to-right language, e.g.: English, French, German etc. 400 401 402 If you don't use the ``RequestContext`` extension, you can get those values with 403 three tags:: 404 405 {% get_current_language as LANGUAGE_CODE %} 406 {% get_available_languages as LANGUAGES %} 407 {% get_current_language_bidi as LANGUAGE_BIDI %} 408 409 These tags also require a ``{% load i18n %}``. 410 411 Translation hooks are also available within any template block tag that accepts 412 constant strings. In those cases, just use ``_()`` syntax to specify a 413 translation string:: 414 415 {% some_special_tag _("Page not found") value|yesno:_("yes,no") %} 416 417 In this case, both the tag and the filter will see the already-translated 418 string, so they don't need to be aware of translations. 419 420 .. note:: 421 In this example, the translation infrastructure will be passed the string 422 ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The 423 translated string will need to contain the comma so that the filter 424 parsing code knows how to split up the arguments. For example, a German 425 translator might translate the string ``"yes,no"`` as ``"ja,nein"`` 426 (keeping the comma intact). 427 428 .. _Django templates: ../templates_python/ 429 430 Specifying translation strings: In JavaScript code 431 ================================================== 432 433 Adding translations to JavaScript poses some problems: 434 435 * JavaScript code doesn't have access to a ``gettext`` implementation. 436 437 * JavaScript code doesn't have access to .po or .mo files; they need to be 438 delivered by the server. 439 440 * The translation catalogs for JavaScript should be kept as small as 441 possible. 442 443 Django provides an integrated solution for these problems: It passes the 444 translations into JavaScript, so you can call ``gettext``, etc., from within 445 JavaScript. 446 447 The ``javascript_catalog`` view 448 ------------------------------- 449 450 The main solution to these problems is the ``javascript_catalog`` view, which 451 sends out a JavaScript code library with functions that mimic the ``gettext`` 452 interface, plus an array of translation strings. Those translation strings are 453 taken from the application, project or Django core, according to what you 454 specify in either the info_dict or the URL. 455 456 You hook it up like this:: 457 458 js_info_dict = { 459 'packages': ('your.app.package',), 460 } 461 462 urlpatterns = patterns('', 463 (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), 464 ) 465 466 Each string in ``packages`` should be in Python dotted-package syntax (the 467 same format as the strings in ``INSTALLED_APPS``) and should refer to a package 468 that contains a ``locale`` directory. If you specify multiple packages, all 469 those catalogs are merged into one catalog. This is useful if you have 470 JavaScript that uses strings from different applications. 471 472 You can make the view dynamic by putting the packages into the URL pattern:: 473 474 urlpatterns = patterns('', 475 (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'), 476 ) 477 478 With this, you specify the packages as a list of package names delimited by '+' 479 signs in the URL. This is especially useful if your pages use code from 480 different apps and this changes often and you don't want to pull in one big 481 catalog file. As a security measure, these values can only be either 482 ``django.conf`` or any package from the ``INSTALLED_APPS`` setting. 483 484 Using the JavaScript translation catalog 485 ---------------------------------------- 486 487 To use the catalog, just pull in the dynamically generated script like this:: 488 489 <script type="text/javascript" src={% url django.views.i18n.javascript_catalog %}"></script> 490 491 This uses reverse URL lookup to find the URL of the JavaScript catalog view. 492 When the catalog is loaded, your JavaScript code can use the standard 493 ``gettext`` interface to access it:: 494 495 document.write(gettext('this is to be translated')); 496 497 There is also an ``ngettext`` interface:: 498 499 var object_cnt = 1 // or 0, or 2, or 3, ... 500 s = ngettext('literal for the singular case', 501 'literal for the plural case', object_cnt); 502 503 and even a string interpolation function:: 504 505 function interpolate(fmt, obj, named); 506 507 The interpolation syntax is borrowed from Python, so the ``interpolate`` 508 function supports both positional and named interpolation: 509 510 * Positional interpolation: ``obj`` contains a JavaScript Array object 511 whose elements values are then sequentially interpolated in their 512 corresponding ``fmt`` placeholders in the same order they appear. 513 For example:: 514 515 fmts = ngettext('There is %s object. Remaining: %s', 516 'There are %s objects. Remaining: %s', 11); 517 s = interpolate(fmts, [11, 20]); 518 // s is 'There are 11 objects. Remaining: 20' 519 520 * Named interpolation: This mode is selected by passing the optional 521 boolean ``named`` parameter as true. ``obj`` contains a JavaScript 522 object or associative array. For example:: 523 524 d = { 525 count: 10 526 total: 50 527 }; 528 529 fmts = ngettext('Total: %(total)s, there is %(count)s object', 530 'there are %(count)s of a total of %(total)s objects', d.count); 531 s = interpolate(fmts, d, true); 532 533 You shouldn't go over the top with string interpolation, though: this is still 534 JavaScript, so the code has to make repeated regular-expression substitutions. 535 This isn't as fast as string interpolation in Python, so keep it to those 536 cases where you really need it (for example, in conjunction with ``ngettext`` 537 to produce proper pluralizations). 538 539 The ``set_language`` redirect view 540 ================================== 541 542 As a convenience, Django comes with a view, ``django.views.i18n.set_language``, 543 that sets a user's language preference and redirects back to the previous page. 544 545 Activate this view by adding the following line to your URLconf:: 546 547 (r'^i18n/', include('django.conf.urls.i18n')), 548 549 (Note that this example makes the view available at ``/i18n/setlang/``.) 550 551 The view expects to be called via the ``POST`` method, with a ``language`` 552 parameter set in request. If session support is enabled, the view 553 saves the language choice in the user's session. Otherwise, it saves the 554 language choice in a cookie that is by default named ``django_language``. 555 (The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.) 556 557 After setting the language choice, Django redirects the user, following this 558 algorithm: 559 560 * Django looks for a ``next`` parameter in the ``POST`` data. 561 * If that doesn't exist, or is empty, Django tries the URL in the 562 ``Referrer`` header. 563 * If that's empty -- say, if a user's browser suppresses that header -- 564 then the user will be redirected to ``/`` (the site root) as a fallback. 565 566 Here's example HTML template code: 567 568 .. code-block:: html+django 569 570 <form action="/i18n/setlang/" method="post"> 571 <input name="next" type="hidden" value="/next/page/" /> 572 <select name="language"> 573 {% for lang in LANGUAGES %} 574 <option value="{{ lang.0 }}">{{ lang.1 }}</option> 575 {% endfor %} 576 </select> 577 <input type="submit" value="Go" /> 578 </form> -
new file docs/topics/i18n/localization.txt
diff -r 4755c937c02f docs/topics/i18n/localization.txt
- + 1 .. _topics-i18n-localization: 2 3 ============ 4 Localization 5 ============ 6 7 .. seealso:: 8 9 The :ref:`howto-i18n` document included with the Django HOW-TO documents collection. 10 11 .. _how-to-create-language-files: 12 13 How to create language files 14 ============================ 15 16 Once the string literals of an application have been tagged for later 17 translation, the translation themselves need to be written (or obtained). Here's 18 how that works. 19 20 .. _locale-restrictions: 21 22 .. admonition:: Locale restrictions 23 24 Django does not support localizing your application into a locale for which 25 Django itself has not been translated. In this case, it will ignore your 26 translation files. If you were to try this and Django supported it, you 27 would inevitably see a mixture of translated strings (from your application) 28 and English strings (from Django itself). If you want to support a locale 29 for your application that is not already part of Django, you'll need to make 30 at least a minimal translation of the Django core. 31 32 A good starting point is to copy the Django English ``.po`` file and to 33 translate at least the :ref:`technical-messages` -- maybe the validation 34 messages, too. 35 36 Message files 37 ------------- 38 39 The first step is to create a :term:`message file` for a new language. A message 40 file is a plain-text file, representing a single language, that contains all 41 available translation strings and how they should be represented in the given 42 language. Message files have a ``.po`` file extension. 43 44 Django comes with a tool, ``django-admin.py makemessages``, that automates the 45 creation and upkeep of these files. 46 47 .. admonition:: A note to Django veterans 48 49 The old tool ``bin/make-messages.py`` has been moved to the command 50 ``django-admin.py makemessages`` to provide consistency throughout Django. 51 52 To create or update a message file, run this command:: 53 54 django-admin.py makemessages -l de 55 56 ...where ``de`` is the language code for the message file you want to create. 57 The language code, in this case, is in :term:`locale format<locale name>`. For 58 example, it's ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian 59 German. 60 61 The script should be run from one of two places: 62 63 * The root directory of your Django project. 64 * The root directory of your Django app. 65 66 Th script runs over your project source tree or your application source tree and 67 pulls out all strings marked for translation. It creates (or updates) a message 68 file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de`` example, the 69 file will be ``locale/de/LC_MESSAGES/django.po``. 70 71 By default ``django-admin.py makemessages`` examines every file that has the 72 ``.html`` file extension. In case you want to override that default, use the 73 ``--extension`` or ``-e`` option to specify the file extensions to examine:: 74 75 django-admin.py makemessages -l de -e txt 76 77 Separate multiple extensions with commas and/or use ``-e`` or ``--extension`` 78 multiple times:: 79 80 django-admin.py makemessages -l=de -e=html,txt -e xml 81 82 When :ref:`creating message files from JavaScript source code 83 <creating-message-files-from-js-code>` you need to use the special 'djangojs' 84 domain, **not** ``-e js``. 85 86 .. admonition:: No gettext? 87 88 If you don't have the ``gettext`` utilities installed, ``django-admin.py 89 makemessages`` will create empty files. If that's the case, either install 90 the ``gettext`` utilities or just copy the English message file 91 (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting 92 point; it's just an empty translation file. 93 94 .. admonition:: Working on Windows? 95 96 If you're using Windows and need to install the GNU gettext utilities so 97 ``django-admin makemessages`` works see :ref:`gettext_on_windows` for more 98 information. 99 100 The format of ``.po`` files is straightforward. Each ``.po`` file contains a 101 small bit of metadata, such as the translation maintainer's contact 102 information, but the bulk of the file is a list of **messages** -- simple 103 mappings between translation strings and the actual translated text for the 104 particular language. 105 106 For example, if your Django app contained a translation string for the text 107 ``"Welcome to my site."``, like so:: 108 109 _("Welcome to my site.") 110 111 ...then ``django-admin.py makemessages`` will have created a ``.po`` file 112 containing the following snippet -- a message:: 113 114 #: path/to/python/module.py:23 115 msgid "Welcome to my site." 116 msgstr "" 117 118 A quick explanation: 119 120 * ``msgid`` is the translation string, which appears in the source. Don't 121 change it. 122 * ``msgstr`` is where you put the language-specific translation. It starts 123 out empty, so it's your responsibility to change it. Make sure you keep 124 the quotes around your translation. 125 * As a convenience, each message includes, in the form of a comment line 126 prefixed with ``#`` and located above the ``msgid`` line, the filename and 127 line number from which the translation string was gleaned. 128 129 Long messages are a special case. There, the first string directly after the 130 ``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be 131 written over the next few lines as one string per line. Those strings are 132 directly concatenated. Don't forget trailing spaces within the strings; 133 otherwise, they'll be tacked together without whitespace! 134 135 .. admonition:: Mind your charset 136 137 When creating a PO file with your favorite text editor, first edit 138 the charset line (search for ``"CHARSET"``) and set it to the charset 139 you'll be using to edit the content. Due to the way the ``gettext`` tools 140 work internally and because we want to allow non-ASCII source strings in 141 Django's core and your applications, you **must** use UTF-8 as the encoding 142 for your PO file. This means that everybody will be using the same 143 encoding, which is important when Django processes the PO files. 144 145 To reexamine all source code and templates for new translation strings and 146 update all message files for **all** languages, run this:: 147 148 django-admin.py makemessages -a 149 150 Compiling message files 151 ----------------------- 152 153 After you create your message file -- and each time you make changes to it -- 154 you'll need to compile it into a more efficient form, for use by ``gettext``. 155 Do this with the ``django-admin.py compilemessages`` utility. 156 157 This tool runs over all available ``.po`` files and creates ``.mo`` files, which 158 are binary files optimized for use by ``gettext``. In the same directory from 159 which you ran ``django-admin.py makemessages``, run ``django-admin.py 160 compilemessages`` like this:: 161 162 django-admin.py compilemessages 163 164 That's it. Your translations are ready for use. 165 166 .. admonition:: A note to Django veterans 167 168 The old tool ``bin/compile-messages.py`` has been moved to the command 169 ``django-admin.py compilemessages`` to provide consistency throughout 170 Django. 171 172 .. admonition:: Working on Windows? 173 174 If you're using Windows and need to install the GNU gettext utilities so 175 ``django-admin compilemessages`` works see :ref:`gettext_on_windows` for more 176 information. 177 178 .. _creating-message-files-from-js-code: 179 180 Creating message files from JavaScript source code 181 ================================================== 182 183 You create and update the message files the same way as the other Django message 184 files -- with the ``django-admin.py makemessages`` tool. The only difference is 185 you need to provide a ``-d djangojs`` parameter, like this:: 186 187 django-admin.py makemessages -d djangojs -l de 188 189 This would create or update the message file for JavaScript for German. 190 After updating message files, just run ``django-admin.py compilemessages`` 191 the same way as you do with normal Django message files. 192 193 .. _gettext_on_windows: 194 195 ``gettext`` on Windows 196 ====================== 197 198 This is only needed for people who either want to extract message IDs or compile 199 message files (``.po``). Translation work itself just involves editing existing 200 files of this type, but if you want to create your own message files, or want to 201 test or compile a changed message file, you will need the ``gettext`` utilities: 202 203 * Download the following zip files from the GNOME servers 204 http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one 205 of its mirrors_ 206 207 * ``gettext-runtime-X.zip`` 208 * ``gettext-tools-X.zip`` 209 210 ``X`` is the version number, we recomend using ``0.15`` or higher. 211 212 * Extract the contents of the ``bin\`` directories in both files to the 213 same folder on your system (i.e. ``C:\Program Files\gettext-utils``) 214 215 * Update the system PATH: 216 217 * ``Control Panel > System > Advanced > Environment Variables``. 218 * In the ``System variables`` list, click ``Path``, click ``Edit``. 219 * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the 220 ``Variable value`` field. 221 222 .. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS 223 224 You may also use ``gettext`` binaries you have obtained elsewhere, so long as 225 the ``xgettext --version`` command works properly. Some version 0.14.4 binaries 226 have been found to not support this command. Do not attempt to use Django 227 translation utilities with a ``gettext`` package if the command ``xgettext 228 --version`` entered at a Windows command prompt causes a popup window saying 229 "xgettext.exe has generated errors and will be closed by Windows". -
docs/topics/index.txt
diff -r 4755c937c02f 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