doc/book/en/devweb/internationalization.rst
branchstable
changeset 5394 105011657405
parent 5222 ed6905d98a5e
child 8032 bcb87336c7d2
equal deleted inserted replaced
5393:875bdc0fe8ce 5394:105011657405
       
     1 .. -*- coding: utf-8 -*-
       
     2 
       
     3 .. _internationalization:
       
     4 
       
     5 Internationalization
       
     6 ---------------------
       
     7 
       
     8 Cubicweb fully supports the internalization of its content and interface.
       
     9 
       
    10 Cubicweb's interface internationalization is based on the translation project `GNU gettext`_.
       
    11 
       
    12 .. _`GNU gettext`: http://www.gnu.org/software/gettext/
       
    13 
       
    14 Cubicweb' internalization involves two steps:
       
    15 
       
    16 * in your Python code and cubicweb-tal templates : mark translatable strings
       
    17 
       
    18 * in your instance : handle the translation catalog, edit translations
       
    19 
       
    20 String internationalization
       
    21 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
    22 
       
    23 User defined string
       
    24 ```````````````````
       
    25 
       
    26 In the Python code and cubicweb-tal templates translatable strings can be
       
    27 marked in one of the following ways :
       
    28 
       
    29  * by using the *built-in* function `_` ::
       
    30 
       
    31      class PrimaryView(EntityView):
       
    32          """the full view of an non final entity"""
       
    33          __regid__ = 'primary'
       
    34          title = _('primary')
       
    35 
       
    36   OR
       
    37 
       
    38  * by using the equivalent request's method ::
       
    39 
       
    40      class NoResultView(View):
       
    41          """default view when no result has been found"""
       
    42          __regid__ = 'noresult'
       
    43 
       
    44          def call(self, **kwargs):
       
    45              self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n'
       
    46                  % self._cw._('No result matching query'))
       
    47 
       
    48 The goal of the *built-in* function `_` is only **to mark the
       
    49 translatable strings**, it will only return the string to translate
       
    50 itself, but not its translation (it's actually another name for the
       
    51 `unicode` builtin).
       
    52 
       
    53 In the other hand the request's method `self._cw._` is also meant to
       
    54 retrieve the proper translation of translation strings in the
       
    55 requested language.
       
    56 
       
    57 Finally you can also use the `__` attribute of request object to get a
       
    58 translation for a string *which should not itself added to the catalog*,
       
    59 usually in case where the actual msgid is created by string interpolation ::
       
    60 
       
    61   self._cw.__('This %s' % etype)
       
    62 
       
    63 In this example ._cw.__` is used instead of ._cw._` so we don't have 'This %s' in
       
    64 messages catalogs.
       
    65 
       
    66 Translations in cubicweb-tal template can also be done with TAL tags
       
    67 `i18n:content` and `i18n:replace`.
       
    68 
       
    69 If you need to add messages on top of those that can be found in the source,
       
    70 you can create a file named `i18n/static-messages.pot`.
       
    71 
       
    72 You could put there messages not found in the python sources or
       
    73 overrides for some messages of used cubes.
       
    74 
       
    75 Generated string
       
    76 ````````````````
       
    77 
       
    78 We do not need to mark the translation strings of entities/relations used by a
       
    79 particular instance's schema as they are generated automatically. String for
       
    80 various actions are also generated.
       
    81 
       
    82 For exemple the following schema ::
       
    83 
       
    84   Class EntityA(EntityType):
       
    85       relation_a2b = SubjectRelation('EntityB')
       
    86 
       
    87   class EntityB(EntityType):
       
    88       pass
       
    89 
       
    90 May generate the following message ::
       
    91 
       
    92   add EntityA relation_a2b EntityB subject
       
    93 
       
    94 This message will be used in views of ``EntityA`` for creation of a new
       
    95 ``EntityB`` with a preset relation ``relation_a2b`` between the current
       
    96 ``EntityA`` and the new ``EntityB``. The opposite message ::
       
    97 
       
    98   add EntityA relation_a2b EntityB object
       
    99 
       
   100 Is used for similar creation of an ``EntityA`` from a view of ``EntityB``. The
       
   101 title of they respective creation form will be ::
       
   102 
       
   103   creating EntityB (EntityA %(linkto)s relation_a2b EntityB)
       
   104 
       
   105   creating EntityA (EntityA relation_a2b %(linkto)s EntityA)
       
   106 
       
   107 In the translated string you can use ``%(linkto)s`` for reference to the source
       
   108 ``entity``.
       
   109 
       
   110 Handling the translation catalog
       
   111 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
   112 
       
   113 Once the internationalization is done in your code, you need to populate and
       
   114 update the translation catalog. Cubicweb provides the following commands for this
       
   115 purpose:
       
   116 
       
   117 
       
   118 * `i18ncubicweb` updates Cubicweb framework's translation
       
   119   catalogs. Unless you actually work on the framework itself, you
       
   120   don't need to use this command.
       
   121 
       
   122 * `i18ncube` updates the translation catalogs of *one particular cube*
       
   123   (or of all cubes). After this command is executed you must update
       
   124   the translation files *.po* in the "i18n" directory of your
       
   125   cube. This command will of course not remove existing translations
       
   126   still in use. It will mark unused translation but not remove them.
       
   127 
       
   128 * `i18ninstance` recompiles the translation catalogs of *one particular
       
   129   instance* (or of all instances) after the translation catalogs of
       
   130   its cubes have been updated. This command is automatically
       
   131   called every time you create or update your instance. The compiled
       
   132   catalogs (*.mo*) are stored in the i18n/<lang>/LC_MESSAGES of
       
   133   instance where `lang` is the language identifier ('en' or 'fr'
       
   134   for exemple).
       
   135 
       
   136 
       
   137 Example
       
   138 ```````
       
   139 
       
   140 You have added and/or modified some translation strings in your cube
       
   141 (after creating a new view or modifying the cube's schema for exemple).
       
   142 To update the translation catalogs you need to do:
       
   143 
       
   144 1. `cubicweb-ctl i18ncube <cube>`
       
   145 2. Edit the <cube>/i18n/xxx.po  files and add missing translations (empty `msgstr`)
       
   146 3. `hg ci -m "updated i18n catalogs"`
       
   147 4. `cubicweb-ctl i18ninstance <myinstance>`
       
   148 
       
   149 Editing po files
       
   150 ~~~~~~~~~~~~~~~~
       
   151 
       
   152 Using a PO aware editor
       
   153 ````````````````````````
       
   154 
       
   155 Many tools exist to help maintain .po (PO) files. Common editors or
       
   156 development environment provides modes for these. One can also find
       
   157 dedicated PO files editor, such as `poedit`_.
       
   158 
       
   159 .. _`poedit`:  http://www.poedit.net/
       
   160 
       
   161 While usage of such a tool is commendable, PO files are perfectly
       
   162 editable with a (unicode aware) plain text editor. It is also useful
       
   163 to know their structure for troubleshooting purposes.
       
   164 
       
   165 Structure of a PO file
       
   166 ``````````````````````
       
   167 
       
   168 In this section, we selectively quote passages of the `GNU gettext`_
       
   169 manual chapter on PO files, available there::
       
   170 
       
   171  http://www.gnu.org/software/hello/manual/gettext/PO-Files.html
       
   172 
       
   173 One PO file entry has the following schematic structure::
       
   174 
       
   175      white-space
       
   176      #  translator-comments
       
   177      #. extracted-comments
       
   178      #: reference...
       
   179      #, flag...
       
   180      #| msgid previous-untranslated-string
       
   181      msgid untranslated-string
       
   182      msgstr translated-string
       
   183 
       
   184 
       
   185 A simple entry can look like this::
       
   186 
       
   187      #: lib/error.c:116
       
   188      msgid "Unknown system error"
       
   189      msgstr "Error desconegut del sistema"
       
   190 
       
   191 It is also possible to have entries with a context specifier. They
       
   192 look like this::
       
   193 
       
   194      white-space
       
   195      #  translator-comments
       
   196      #. extracted-comments
       
   197      #: reference...
       
   198      #, flag...
       
   199      #| msgctxt previous-context
       
   200      #| msgid previous-untranslated-string
       
   201      msgctxt context
       
   202      msgid untranslated-string
       
   203      msgstr translated-string
       
   204 
       
   205 
       
   206 The context serves to disambiguate messages with the same
       
   207 untranslated-string. It is possible to have several entries with the
       
   208 same untranslated-string in a PO file, provided that they each have a
       
   209 different context. Note that an empty context string and an absent
       
   210 msgctxt line do not mean the same thing.
       
   211 
       
   212 Contexts and CubicWeb
       
   213 `````````````````````
       
   214 
       
   215 CubicWeb PO files have both non-contextual and contextual msgids.
       
   216 
       
   217 Contextual entries are automatically used in some cases. For instance,
       
   218 entity.dc_type(), eschema.display_name(req) or display_name(etype,
       
   219 req, form, context) methods/function calls will use them.
       
   220 
       
   221 It is also possible to explicitly use the with _cw.pgettext(context,
       
   222 msgid).