Django

Code

Changeset 1057

Show
Ignore:
Timestamp:
11/03/05 00:52:53 (3 years ago)
Author:
adrian
Message:

Preliminary clean-up of docs/translation.txt in i18n branch

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/i18n/docs/translation.txt

    r1049 r1057  
    44 
    55Django has support for internationalization of program strings and template 
    6 content. Translations use the gettext library to produce strings in several 
    7 languages. Here is an overview how translation works with django. 
    8  
    9 The goal of this howto is to give programmers the needed informations on how 
    10 to use translations in their own projects, on how to add translations to 
    11 django patches and on how to update and create translation files. 
    12  
    13 Using Translations in Python 
     6content. Translations use the ``gettext`` library to produce strings in several 
     7languages. Here's an overview of how translation works with Django. 
     8 
     9The goal of this document is to explain how to use translations in projects, 
     10how to add translations to Django patches and how to update and create 
     11translation files. 
     12 
     13Using translations in Python 
    1414============================ 
    1515 
    16 The translation machinery in django uses the standard gettext module that 
    17 comes as part of your Python installation. It does wrap it in it's own 
    18 functions and classes to accomplish all of it's goals, but essentially it's 
    19 just standard gettext machinery. 
    20  
    21 So to translate strings in your source you have to make use of one of the 
    22 gettext helper functions. There are essentially two ways to make use of them: 
    23  
    24 - you can use the _() function that is available globally. This function will 
    25   translate any string value it get's as parameter. 
    26 - you can use django.utils.translation and import gettext or gettext_noop 
    27   from there. gettext is identical to _() 
    28  
    29 There is one important thing to know about translations: the system can only 
    30 translate strings it knows about. So to know about those strings you have to 
    31 mark them for translation. That is done by either calling _(), gettext() or 
    32 gettext_noop() on those string constants. You can translate variable values 
    33 or computed values, but the system needs to know those strings beforehand. 
    34  
    35 The usual way is to build your strings by standard string interpolation and 
    36 to use the gettext functions to do the actual translation of the string 
    37 itself, like so:: 
    38  
    39    def hello_world(request, name, site): 
    40        page = _('Hello %(name)s, welcome to %(site)s!') % { 
    41            'name': name, 
    42            'site': site, 
    43        } 
    44        return page 
    45  
    46 This short snippet shows one important thing: you shouldn't use the positional 
    47 string interpolation (the one that uses %s and %d) but use the named string 
    48 interpolation (the one that uses %(name)s), instead. The reason is that other 
    49 languages might require a reordering of text. 
    50  
    51 The other two helper functions are similar in use:: 
    52  
    53    def hello_world(request, name, site): 
    54        from django.utils.translation import gettext 
    55        page = gettext('Hello %(name)s, welcome to %(site)s!') % { 
    56            'name': name, 
    57            'site': site, 
    58        } 
    59        return page 
    60  
    61 The difference is, you explicitly import them. There are two important 
    62 helpers: gettext and gettext_noop. gettext is just like _() - it will 
    63 translate it's argument. gettext_noop is different in that it does only 
    64 mark a string for inclusion into the message file but doesn't do translation. 
    65 Instead the string is later translated from a variable. This comes up if you 
    66 have constant strings that should be stored in the source language because 
    67 they are exchanged over systems or users - like strings in a database - but 
    68 should be translated at the last possible point in time, when the string 
    69 is presented to the user. 
    70  
    71 One special case that isn't available in other gettext usages are lazily 
    72 translated strings. This is needed for stuff that you set up in your django 
    73 model files - those messages are stored internally and translated on access, but 
    74 not translated on storage (as that would only take the default language into account). 
    75 To translate a model helptext, do the following:: 
     16The translation machinery in Django uses the standard ``gettext`` module that 
     17comes with Python. Django uses in its own functions and classes, but it uses 
     18standard ``gettext`` machinery under the hood. 
     19 
     20To translate strings in your code, use one of the ``gettext`` helper functions. 
     21There are essentially two ways to use them: 
     22 
     23    * Use the ``_()`` function, which is available globally. This function 
     24      translates any string value. 
     25    * Use ``django.utils.translation`` and import ``gettext`` or 
     26      ``gettext_noop`` from there. ``gettext`` is identical to ``_()``. 
     27 
     28Note one important thing about translations: The system can only translate 
     29strings it knows about. That means you have to mark strings for translation. 
     30This is done either by calling ``_()``, ``gettext()`` or ``gettext_noop()`` on 
     31string constants. You can translate variable values or computed values, but the 
     32system needs to know those strings beforehand. 
     33 
     34The usual method is to build your strings using string interpolation and using 
     35the ``gettext`` functions to do the actual translation. Example:: 
     36 
     37    def hello_world(request, name, site): 
     38        page = _('Hello %(name)s, welcome to %(site)s!') % { 
     39            'name': name, 
     40            'site': site, 
     41        } 
     42        return HttpResponse(page) 
     43 
     44This short snippet shows one important thing: You shouldn't use positional 
     45string interpolation (e.g., ``%s`` or ``%d``). Use the named string 
     46interpolation (e.g., ``%(name)s``), instead. Do this because other languages 
     47might require reordering of text. 
     48 
     49The other two helper functions are similar:: 
     50 
     51    from django.utils.translation import gettext 
     52    def hello_world(request, name, site): 
     53        page = gettext('Hello %(name)s, welcome to %(site)s!') % { 
     54            'name': name, 
     55            'site': site, 
     56        } 
     57        return HttpResponse(page) 
     58 
     59The difference here is that ``gettext`` is explicitly imported. 
     60 
     61Two important helper functions are available: ``gettext`` and ``gettext_noop``. 
     62 
     63    * ``gettext`` is just like ``_()`` -- it translates its argument. 
     64    * ``gettext_noop`` is different. It marks a string for inclusion into the 
     65      message file but doesn't do translation. Instead, the string is later 
     66      translated from a variable. Use this if you have constant strings that 
     67      should be stored in the source language because they are exchanged over 
     68      systems or users -- such as strings in a database -- but should be 
     69      translated at the last possible point in time, such as when the string is 
     70      presented to the user. 
     71 
     72One function, ``django.utils.translation.gettext_lazy()``, isn't available in 
     73the standard ``gettext`` module. Use it for lazily translated strings, such as 
     74messages in Django models that are stored internally and translated on access 
     75-- but not translated on storage, as that would only take the default language 
     76into account. 
     77 
     78For example, to translate a model's ``help_text``, do the following:: 
    7679 
    7780    from django.utils.translation import gettext_lazy 
    7881 
    79     class Mything(meta.Model): 
    80  
    81         name = meta.CharField('Name', help_text=gettext_lazy('This is the help text')) 
    82         ... 
    83  
    84 This way only a lazy reference is stored for the string, not the actual translation. 
    85 The translation itself will be done when the string is used in a string context, like 
    86 template rendering in the admin. 
    87  
    88 If you don't like the verbose name gettext_lazy, you can just alias it as _ - in the model 
    89 file you will allways use lazy translations anyway. And it's a good idea to add translations 
    90 for the field names and table names, too. This means writing explicit verbose_name and 
    91 verbose_names options in the META subclass, though:: 
     82    class MyThing(meta.Model): 
     83        name = meta.CharField(help_text=gettext_lazy('This is the help text')) 
     84 
     85In this example, ``gettext_lazy()`` stores a lazy reference to the string -- 
     86not the actual translation. The translation itself will be done when the string 
     87is used in a string context, such as template rendering on the Django admin site. 
     88 
     89If you don't like the verbose name ``gettext_lazy``, you can just alias it as 
     90``_``, like so:: 
    9291 
    9392    from django.utils.translation import gettext_lazy as _ 
    9493 
    95     class Mything(meta.Model): 
    96      
    97         name = meta.CharField(_('Name'), help_text=_('This is the help text')) 
    98  
     94    class MyThing(meta.Model): 
     95        name = meta.CharField(help_text=_('This is the help text')) 
     96 
     97Always use lazy translations in Django models. And it's a good idea to add 
     98translations for the field names and table names, too. This means writing 
     99explicit verbose_name and verbose_names options in the ``META`` class, 
     100though:: 
     101 
     102    from django.utils.translation import gettext_lazy as _ 
     103 
     104    class MyThing(meta.Model): 
     105        name = meta.CharField(_('name'), help_text=_('This is the help text')) 
    99106        class META: 
    100  
    101             verbose_name = _('Mything') 
    102             verbose_name_plural = _('Mythings') 
    103  
    104 There is another standard problem with translations, that is pluralization of 
    105 strings. This is done by the standard helper ngettext like so:: 
     107            verbose_name = _('my thing') 
     108            verbose_name_plural = _('mythings') 
     109 
     110A standard problem with translations is pluralization of strings. Use 
     111``ngettext`` to solve this problem. Example:: 
    106112 
    107113    def hello_world(request, count): 
     
    110116            'count': count, 
    111117        } 
    112        return page 
    113  
    114 Using Translations in Templates 
     118        return HttpResponse(page) 
     119 
     120Using translations in templates 
    115121=============================== 
    116122 
    117 Using translations in the templates is much like in python code. There is 
    118 just a template tag that will allow you to use the same _() helper function 
    119 as with your source:: 
    120  
    121    <html> 
    122    <title>{% i18n _('This is the title.') %}</title> 
    123    <body> 
    124    <p>{% i18n _('Hello %(name)s, welcome at %(site)s!') %}</p> 
    125    <p>{% i18n ngettext('There is %(count)d file', 'There are %(count)d files', files|count) %}</p> 
    126    </body> 
    127    </html> 
    128  
    129 This short snippet shows you how to do translations. You can just translate 
    130 strings, but there is one speciality: the strings can contain interpolation 
    131 parts. Those parts are automatically resolved from the template context, just 
    132 as they would be if you had used them in {{ ... }}. But this can only resolve 
    133 variables, not more complex expressions. 
    134  
    135 To translate a variable value, you can just do {% i18n _(variable) %}. This 
    136 can even include filters like {% i18n _(variable|lower} %}. 
    137  
    138 There is additional support for i18n string constants for other situations 
    139 as well. All template tags that do variable resolving (with or without filters) 
    140 will accept string constants, too. Those string constants can now be i18n 
    141 strings like this:: 
    142  
    143    <html> 
    144    <title>{{ _('This is the title') }}</title> 
    145    <body> 
    146    <p>{{ _('Hello World!') }}</p> 
    147    </body> 
    148    </html> 
    149  
    150 This is much shorter, but won't allow you to use gettext_noop or ngettext. 
    151  
    152 Sometimes you might want to give the user a selection of languages. This 
    153 can be done by accessing the LANGUAGES variable of a DjangoContext. This 
    154 is a list of tuples where the first element is the language code and the 
    155 second element is the language name (in that language). The code might 
    156 look like this:: 
     123Using translations in Django templates works much like translations in Python 
     124code. The ``{% i18n %}`` template tag lets you use the same ``_()`` helper 
     125function as in your Python code:: 
     126 
     127    <html> 
     128    <title>{% i18n _('This is the title.') %}</title> 
     129    <body> 
     130    <p>{% i18n _('Hello %(name)s, welcome at %(site)s!') %}</p> 
     131    <p>{% i18n ngettext('There is %(count)d file', 'There are %(count)d files', files|count) %}</p> 
     132    </body> 
     133    </html> 
     134 
     135It's not only possible to translate hard-coded strings, but the strings can 
     136contain interpolated parts, e.g. ``%(name)s``. Those parts are automatically 
     137resolved from the template context, just as they would be if you had used them 
     138in ``{{ ... }}``. But this can only resolve variables, not more complex 
     139expressions. 
     140 
     141To translate a variable value, do this:: 
     142 
     143    {% i18n _(variable) %} 
     144 
     145Filters are allowed, too:: 
     146 
     147    {% i18n _(variable|lower) %} 
     148 
     149Any template tag that resolves variables accepts i18n-string constants, too. 
     150 
     151Also, note you can use ``_()`` around variable names, like so:: 
     152 
     153    <html> 
     154    <title>{{ _('This is the title') }}</title> 
     155    <body> 
     156    <p>{{ _('Hello, world!') }}</p> 
     157    </body> 
     158    </html> 
     159 
     160This syntax is much shorter, but it doesn't allow you to use ``gettext_noop`` 
     161or ``ngettext``. 
     162 
     163Each ``DjangoContext`` has access to two translation-specific variables: 
     164 
     165    * ``LANGUAGES`` is a list of tuples in which the first element is the 
     166      language code and the second is the language name (in that language). 
     167    * ``LANGUAGE_CODE`` is the current user's preferred language, as a string. 
     168      Example: ``en-us``. (See "How language preference is discovered", below.) 
     169 
     170The ``setlang`` redirect view 
     171----------------------------- 
     172 
     173Django comes with a view, ``django.views.i18n.set_language`` that sets a user's 
     174language preference and redirects back to the previous page. For example, put 
     175this HTML code in your template:: 
    157176 
    158177    <form action="/i18n/setlang/" method="POST"> 
    159     <input name="next" type="hidden" value="http://server.doma.in/path/to/go/to/after/switch/"/> 
     178    <input name="next" type="hidden" value="/next/page/" /> 
    160179    <select name="language"> 
    161180    {% for lang in LANGUAGES %} 
     
    163182    {% endfor %} 
    164183    </select> 
     184    <input type="submit" value="Go" /> 
    165185    </form> 
    166186 
    167 This would jump to a language switcher and then be redirected back to the 
    168 page it came from. The switcher page will just store the language in either 
    169 the users session or a special cookie for use in the language discovery. 
    170  
    171 You can leave out the "next" field. In that case the /i18n/setlang/ view 
    172 will redirect to the URL that is in the "Referer" header. Please keep in mind 
    173 that people might suppress that header, so in those cases there won't be a 
    174 URL to redirect to - in those cases the view function will redirect to "/" 
    175 as a fallback. 
    176  
    177 The /i18n/setlang/ url can be set up by including the following in your 
    178 ROOT_URLCONF:: 
    179  
    180     urlpatterns = patterns('', 
    181         (r'^i18n/', include('django.conf.urls.i18n'), 
    182     ) 
    183  
    184 This adds the setlang handler to your urlspace and hooks up a standard view 
    185 function to it. 
    186  
    187 How the Language is Discovered 
    188 ============================== 
    189  
    190 Django has a very flexible model of deciding what language is to be used. 
    191 The first line in choice is the LANGUAGE_CODE setting in your config file. 
    192 This is used as the default translation - the last try if none of the other 
    193 translattors find a translation. Actually if youre requirement is just to 
    194 run django with your native language, you only need to set LANGUAGE_CODE 
    195 and that's it - if there is a language file for django for your language. 
    196  
    197 But with web applications, users come from all over the world. So you don't 
    198 want to have a single translation active, you want to decide what language to 
    199 present to each and every user. This is where the LocaleMiddleware comes 
    200 into the picture. You need to add it to your middleware setting. It should 
    201 be one of the first middlewares installed, but it should come after the 
    202 session middleware - that's because it makes uses of the session data. And 
    203 it must be installed before the AdminUserRequired middleware, as that will 
    204 do redirects based on not-logged-in state and so the LocaleMiddleware won't 
    205 ever see the login page (and so not initialize the language correctly)
    206  
    207 So your middleware settings might look like this:: 
     187When a user submits the form, his chosen language will be saved in a cookie, 
     188and he'll be redirected either to the URL specified in the ``next`` field, or, 
     189if ``next`` is empty, to the URL in the ``Referer`` header. If the ``Referer`` 
     190is blank -- say, if a user's browser suppresses that header -- then the user 
     191will be redirected to ``/`` (the site root) as a fallback. 
     192 
     193Activate the ``setlang`` redirect view by adding the following line to your 
     194URLconf:: 
     195 
     196    (r'^i18n/', include('django.conf.urls.i18n'), 
     197 
     198Note that this example makes the view available at ``/i18n/setlang/``. 
     199 
     200How language preference is discovered 
     201===================================== 
     202 
     203Django has a very flexible model of deciding which language should be used -- 
     204installation-wide, for a particular user, or both. 
     205 
     206To set an installation-wide language preference, set ``LANGUAGE_CODE`` in your 
     207settings file. Django uses this language as the default translation -- the 
     208final attempt if no other translator finds a translation. 
     209 
     210If all you want to do is run Django with your native language, and a language 
     211file is available for your language, all you need to do is set 
     212``LANGUAGE_CODE``. 
     213 
     214If you want to let each individual user specify which language he or she 
     215prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language 
     216selection based on data from the request. It lets each user have his or her own 
     217setting. 
     218 
     219To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'`` 
     220to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you 
     221should follow these guidelines: 
     222 
     223    * Make sure it's one of the first middlewares installed. 
     224    * It should come after ``SessionMiddleware``, because ``LocaleMiddleware`` 
     225      makes use of session data
     226 
     227For example, your ``MIDDLEWARE_CLASSES`` might look like this:: 
    208228 
    209229    MIDDLEWARE_CLASSES = ( 
    210230       'django.middleware.sessions.SessionMiddleware', 
    211231       'django.middleware.locale.LocaleMiddleware', 
    212        'django.middleware.admin.AdminUserRequired', 
    213232       'django.middleware.common.CommonMiddleware', 
    214233    ) 
    215234 
    216 This activates the LocalMiddlware in your server (in this case it was taken 
    217 from the admin.py settings file). 
    218  
    219 The LocaleMiddleware allows a selection of the language based on data from 
    220 the request - every user can have her own settings
    221  
    222 The first thing the LocaleMiddleware does, it looks at the session data for the 
    223 user. If that carries a key django_language, it's contents will be used as the 
    224 language code. If the session doesn't contain a language setting, the 
    225 middleware will look at the cookies for a django_language cookie.  If that is 
    226 found, it gives the language code
    227  
    228 The format for the explicit django_language parameters is allways the 
    229 language to use - for example it's pt-br for Brazilian. If a base language 
    230 is available, but the sublanguage specified is not, the base language is used. 
    231 For example if you specify de-at (Austrian German), but there is only a 
    232 language de available, that language is used
    233  
    234 If neither the session nor the cookie carry a language code, the middleware 
    235 will look at the HTTP header Accept-Language. This header is sent by your 
    236 browser and tells the server what languages you prefer. Languages are ordered 
    237 by some choice value - the higher, the more you prefer the language. 
    238  
    239 So the middleware will iterate over that header, ordered by the preference 
    240 value. The language with the highest preference that is in the django base 
    241 message file directory will be used as the language to present to the user. 
    242  
    243 Since the middlware discovers the language based on the request, your app 
    244 might need to know what language is selected (if only to show the flag of 
    245 that language). The selected language is stored by the middleware in the 
    246 request as the LANGUAGE_CODE attribute. So with static translation (when 
    247 you don't use the middlware) the language is in settings.LANGUAGE_CODE, while 
    248 with dynamic translations (when you do use the middleware) it's in 
    249 request.LANGUAGE_CODE. And if your application builds on DjangoContext 
    250 instances for template rendering, it will be automatically be available 
    251 as LANGUAGE_CODE in your template (with automatic determination where to 
    252 pull it from). 
    253  
    254 Creating Language Files 
     235``LocaleMiddleware`` tries to determine the user's language preference by 
     236following this algorithm: 
     237 
     238    * First, it looks for a ``django_language`` key in the the current user's 
     239      session
     240    * Failing that, it looks for a cookie called ``django_language``. 
     241    * Failing that, it looks at the ``Accept-Language`` HTTP header. This 
     242      header is sent by your browser and tells the server which language(s) you 
     243      prefer, in order by priority. Django tries each language in the header 
     244      until it finds one with available translations. 
     245    * Failing that, it uses the global ``LANGUAGE_CODE`` setting
     246 
     247Notes: 
     248 
     249    * In each of these places, the language preference is expected to be in the 
     250      standard language format, as a string. For example, Brazilian is 
     251      ``pt-br``
     252    * If a base language is available but the sublanguage specified is not, 
     253      Django uses the base language. For example, if a user specifies ``de-at`` 
     254      (Austrian German) but Django only has ``de`` available, Django uses 
     255      ``de``. 
     256 
     257Once ``LocaleMiddleware`` determines the user's preference, it makes this 
     258preference available as ``request.LANGUAGE_CODE`` for each `request object`_. 
     259Feel free to read this value in your view code. Here's a simple example:: 
     260 
     261    def hello_world(request, count): 
     262        if request.LANGUAGE_CODE == 'de-at': 
     263            return HttpResponse("You prefer to read Austrian German.") 
     264        else: 
     265            return HttpResponse("You prefer to read another language.") 
     266 
     267Note that, with static (middleware-less) translation, the language is in 
     268``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's 
     269in ``request.LANGUAGE_CODE``. 
     270 
     271.. _request object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects 
     272 
     273Creating language files 
    255274======================= 
    256275 
    257 So now you have tagged all your strings for later translation. But you need 
    258 to write the translations themselves. They need to be in a format grokable 
    259 by gettext. You need to update them. You may need to create new ones for new 
    260 languages. This will show you how to do it. 
    261  
    262 The first step is to create a message file for a new language. This can 
    263 be created with a tool delivered with django. To run it on the django 
    264 source tree (best from a subversion checkout), just go to the django-Directory 
    265 itself. Not the one you checked out, but the one you linked to your 
    266 $PYTHONPATH or the one that's localted somewhere on that path. 
    267  
    268 That directory includes a subdirectory conf, and that a directory locale. The 
    269 tools to do translations are in the django/bin directory. The first tool 
    270 to use is make-messages.py - this tool will run over the whole source tree 
    271 and pull out all strings marked for translation. 
    272  
    273 To run it, just do the following:: 
    274  
    275    bin/make-messages.py -l de 
    276  
    277 This will create or update the german message file. This file is located 
    278 at conf/locale/de/LC_MESSAGES/django.po - this file can be directly edited 
    279 with your favorite editor. You need to first edit the charset line - search 
    280 for CHARSET and set it to the charset you will use to edit the content. It 
    281 might be that it is utf-8 - if you prefer another encoding, you can use some 
    282 tools like recode or iconv to change the charset of the file and then change 
    283 the charset definition in the file (it's in the Content-Type: line). 
    284  
    285 The language code for storage is in locale format - so it is pt_BR for 
    286 Brazilian or de_AT for Austrian German. 
    287  
    288 If you don't have the gettext utilities installed, make-messages.py will create 
    289 empty files. If that is the case, either install the gettext utilities, or 
    290 just copy the conf/locale/en/LC_MESSAGES/django.po and start with that - it's just 
    291 an empty translation file. 
    292  
    293 Every message in the message file is of the same format. One line is the msgid. 
    294 This is the actual string in the source - you don't change it. The other line 
    295 is msgstr - this is the translation. It starts out empty. You change it. 
    296  
    297 There is one speciality for long messages: there the first string directly 
    298 after the msgstr (or msgid) is an emtpy string. Then the content itself will 
    299 be written over the next few lines as one string per line. Those strings 
    300 are directly concatenated - don't forget trailing spaces within the strings, 
    301 otherwise they will be tacked together without whitespace! 
    302  
    303 After you created your message file you need to transform it into some more 
    304 efficient form to read by gettext. This is done with the second tool, that's 
    305 compile-messages.py. This tool just runs over all available .po files and 
    306 turns them into .mo files. Run it as follows:: 
     276So, you've tagged all of your strings for later translation. But you need to 
     277write the translations themselves. 
     278 
     279They need to be in a format grokable by ``gettext``. You need to update them. 
     280You may need to create new ones for new languages. This section shows you how 
     281to do it. 
     282 
     283Creating message files 
     284---------------------- 
     285 
     286The first step is to create a message file for a new language. Django comes 
     287with a tool, ``make-messages.py``, that automates this. 
     288 
     289To run it on the Django source tree, navigate to the ``django`` directory 
     290itself -- not a Subversion check out, but the one linked to via ``$PYTHONPATH`` 
     291or located somewhere on that path. 
     292 
     293Then run this command:: 
     294 
     295    bin/make-messages.py -l de 
     296 
     297...where ``de`` is the language code for the message file you want to create. 
     298 
     299This script runs over the entire Django source tree and pulls out all strings 
     300marked for translation, creating or updating the language's message file. 
     301 
     302When it's done, it will have created (or updated) a message file under the 
     303directory ``conf/locale``. In this example, the file will be 
     304``conf/locale/de/LC_MESSAGES/django.po``. 
     305 
     306If you don't have the ``gettext`` utilities installed, ``make-messages.py`` 
     307will create empty files. If that's the case, either install the ``gettext`` 
     308utilities or just copy the English message file 
     309(``conf/locale/en/LC_MESSAGES/django.po``) and use it as a starting point; it's 
     310just an empty translation file. 
     311 
     312Once you've created the ``.po`` file, edit the file with your favorite text 
     313editor. First, edit the charset line (search for ``"CHARSET"``) and set it to 
     314the charset you'll be using to edit the content. Then, proceed to write your 
     315translations. 
     316 
     317The language code for storage is in locale format -- so it's ``pt_BR`` for 
     318Brazilian and ``de_AT`` for Austrian German. 
     319 
     320Every message in the message file is in the same format: 
     321 
     322    * One line is the msgid. This is the actual string in the source. Don't 
     323      change it. 
     324    * The other line is msgstr. This is the translation. It starts out empty. 
     325      You change it. 
     326 
     327Long messages are a special case. There, the first string directly after the 
     328msgstr (or msgid) is an empty string. Then the content itself will be written 
     329over the next few lines as one string per line. Those strings are directly 
     330concatenated. Don't forget trailing spaces within the strings; otherwise, 
     331they'll be tacked together without whitespace! 
     332 
     333Compiling message files 
     334----------------------- 
     335 
     336After you create your message file, you'll need to transform it into a more 
     337efficient form to be read by ``gettext``. Do this with the 
     338``compile-messages.py`` utility. This tool runs over all available ``.po`` 
     339files and creates ``.mo`` files. Run it like this:: 
    307340 
    308341   bin/compile-messages.py 
    309342 
    310 That's it. You made your first translation. If you now configure your browser 
    311 to request your language, it show up in the admin for example. 
    312  
    313 Another thing: please give us the name of your newly created language in that 
    314 native language - so we can add it to the global list of available languages 
    315 that is mirrored in settings.LANGUAGES (and the DjangoContext variabl
    316 LANGUAGES in templates). 
    317  
    318 Using Translations in Your Own Projects 
     343That's it. You made your first translation. Now, if you configure your browser 
     344to request your language, Django apps will use your language preference. 
     345 
     346Another thing: Please submit the name of your newly-created language in that 
     347native language, so we can add it to the global list of available languages 
     348that is mirrored in ``settings.LANGUAGES`` (and the ``LANGUAGES`` templat
     349variable). 
     350 
     351Using translations in your own projects 
    319352======================================= 
    320353 
    321 Of course you want to make use of the translations in your own projects, too. 
    322 This is very simple with django, as django looks in several locations for 
    323 message files. The base path in your django distribution is only the last 
    324 place to look for translations. Before that, django looks first into your 
    325 application directory (actually in the application directory of the view 
    326 function that is about to be called!) for message files. If there is one for 
    327 the selected language, it will be installed. After that django looks into the 
    328 project directory for message files. If there is one for the selected language, 
    329 it will be installed after the app-specific one. And only then comes the 
    330 base translation. 
    331  
    332 That way you can write applications that bring their own translations with 
    333 them and you can override base translations in your project path if you 
    334 want to do that. Or you can just build a big project out of several apps 
    335 and put all translations into one big project message file. The choice is 
    336 yours. All message file repositories are structured the same. They are: 
    337  
    338 - $APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo) 
    339 - $PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo) 
    340 - all paths listed in LOCALE_PATHS in your settings file are 
    341   searched in that order for <language>/LC_MESSAGES/django.(po|mo) 
    342 - $PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo) 
    343  
    344 Actually the appliaction doesn't need to be stored below the project path - 
    345 django uses module introspection to find the right place where your application 
    346 is stored. It only needs to be listed in your INSTALLED_APPS setting. 
    347  
    348 To create message files, you use the same make-messages.py tool as with the 
    349 django message files. You only need to be in the right place - in the directory 
    350 where either the conf/locale (in case of the source tree) or the locale/ 
     354Of course, your own projects should make use of translations. Django makes this 
     355simple, because it looks for message files in several locations. 
     356 
     357Django looks for translations by following this algorithm: 
     358 
     359    * First, it looks for a ``locale`` directory in the application directory 
     360      of the view that's being called. If it finds a translation for the 
     361      selected language, the translation will be installed. 
     362    * Next, it looks for a ``locale`` directory in the project directory. If it 
     363      finds a translation, the translation will be installed. 
     364    * Finally, it checks the base translation in ``django/conf/locale``. 
     365 
     366This way, you can write applications that include their own translations, and 
     367you can override base translations in your project path if you want to do that. 
     368Or, you can just build a big project out of several apps and put all 
     369translations into one big project message file. The choice is yours. 
     370 
     371All message file repositories are structured the same way. They are: 
     372 
     373    * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` 
     374    * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` 
     375    * all paths listed in ``LOCALE_PATHS`` in your settings file are 
     376      searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)`` 
     377    * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)`` 
     378 
     379To create message files, you use the same ``make-messages.py`` tool as with the 
     380Django message files. You only need to be in the right place -- in the directory 
     381where either the ``conf/locale`` (in case of the source tree) or the ``locale/`` 
    351382(in case of app messages or project messages) directory are located. And you 
    352 use the same compile-messages.py to produce the binary django.mo files that 
    353 are used by gettext
    354  
    355 Application message files are a bit complicated to discover - they need the 
    356 i18n middleware to be found. If you don't use the middleware, only th
    357 django message files and project message files will be processed. 
    358  
    359 Additionally you should think about how to structure your translation 
    360 files. If your applications should be delivered to other users and should 
     383use the same ``compile-messages.py`` to produce the binary ``django.mo`` files that 
     384are used by ``gettext``
     385 
     386Application message files are a bit complicated to discover -- they need the 
     387``LocaleMiddleware``. If you don't use the middleware, only the Django messag
     388files and project message files will be processed. 
     389 
     390Finally, you should give some thought to the structure of your translation 
     391files. If your applications need to be delivered to other users and will 
    361392be used in other projects, you might want to use app-specific translations. 
    362393But using app-specific translations and project translations could produce 
    363 weird problems with make-messages: make-messages will traverse all directories 
     394weird problems with ``make-messages``: ``make-messages`` will traverse all directories 
    364395below the current path and so might put message IDs into the project 
    365 message file that are already in application message files. Easiest way 
    366 out is to store applications that are not part of the project (and so carry 
    367 their own translations) outside the project tree. That way make-messages 
    368 on the project level will only translate stuff that is connected to your 
    369 explicit project and not stuff that is distributed independently. 
    370  
    371 Specialities of Django Translation 
     396message file that are already in application message files. 
     397 
     398The easiest way out is to store applications that are not part of the project 
     399(and so carry their own translations) outside the project tree. That way, 
     400``make-messages`` on the project level will only translate strings that are 
     401connected to your explicit project and not strings that are distributed 
     402independently. 
     403 
     404Specialities of Django translation 
    372405================================== 
    373406 
    374 If you know gettext, you might see some specialities with the way django does 
    375 translations. For one, the string domain is allways django. The string domain 
    376 is used to differentiate between different programs that store their stuff 
    377 in a common messagefile library (usually /usr/share/locale/). In our case there 
    378 are django-specific locale libraries and so the domain itself isn't used. We 
    379 could store app message files with different names and put them for example 
    380 in the project library, but decided against this: with message files in the 
    381 application tree, they can more easily be distributed. 
    382  
    383 Another speciality is that we only use gettext and gettext_noop - that's 
    384 because django uses allways DEFAULT_CHARSET strings internally. There isn't 
    385 much use in using ugettext or something like that, as you allways will need t
    386 produce utf-8 anyway. 
    387  
    388 And last we don't use xgettext alone and some makefiles but use python 
    389 wrappers around xgettext and msgfmt. That's mostly for convenience. 
    390  
     407If you know ``gettext``, you might note these specialities in the way Django 
     408does translation: 
     409 
     410    * The string domain is always ``django``. The string domain is used to 
     411      differentiate between different programs that store their data in a 
     412      common messagefile library (usually ``/usr/share/locale/``). In Django's 
     413      case, there are Django-specific locale libraries, so the domain itself 
     414      isn't used. We could store app message files with different names and put 
     415      them, say, in the project library, but we decided against this. With 
     416      message files in the application tree, apps can be distributed more 
     417      easily. 
     418    * Django only uses ``gettext`` and ``gettext_noop``. That's because Djang
     419      always uses ``DEFAULT_CHARSET`` strings internally. There isn't much use 
     420      in using ``ugettext``, because you'll always need to produce utf-8 
     421      anyway. 
     422    * Django doesn't use ``xgettext`` alone. It uses Python wrappers around 
     423      ``xgettext`` and ``msgfmt``. That's mostly for convenience.