doc/book/en/development/devweb/internationalization.rst
branchstable
changeset 5137 efc280ad9898
parent 4751 1a9d2c3c7f0c
child 5222 ed6905d98a5e
equal deleted inserted replaced
5136:d795cac8ad40 5137:efc280ad9898
    13 
    13 
    14 Cubicweb' internalization involves two steps:
    14 Cubicweb' internalization involves two steps:
    15 
    15 
    16 * in your Python code and cubicweb-tal templates : mark translatable strings
    16 * in your Python code and cubicweb-tal templates : mark translatable strings
    17 
    17 
    18 * in your instance : handle the translation catalog
    18 * in your instance : handle the translation catalog, edit translations
    19 
    19 
    20 String internationalization
    20 String internationalization
    21 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    21 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    22 
    22 
    23 User defined string
    23 User defined string
    48 The goal of the *built-in* function `_` is only **to mark the
    48 The goal of the *built-in* function `_` is only **to mark the
    49 translatable strings**, it will only return the string to translate
    49 translatable strings**, it will only return the string to translate
    50 itself, but not its translation (it's actually another name for the
    50 itself, but not its translation (it's actually another name for the
    51 `unicode` builtin).
    51 `unicode` builtin).
    52 
    52 
    53 In the other hand the request's method `self._cw._` is meant to retrieve the
    53 In the other hand the request's method `self._cw._` is also meant to
    54 proper translation of translation strings in the requested language.
    54 retrieve the proper translation of translation strings in the
       
    55 requested language.
    55 
    56 
    56 Finally you can also use the `__` attribute of request object to get a
    57 Finally you can also use the `__` attribute of request object to get a
    57 translation for a string *which should not itself added to the catalog*,
    58 translation for a string *which should not itself added to the catalog*,
    58 usually in case where the actual msgid is created by string interpolation ::
    59 usually in case where the actual msgid is created by string interpolation ::
    59 
    60 
    60   self._cw.__('This %s' % etype)
    61   self._cw.__('This %s' % etype)
    61 
    62 
    62 In this example ._cw.__` is used instead of ._cw._` so we don't have 'This %s' in
    63 In this example ._cw.__` is used instead of ._cw._` so we don't have 'This %s' in
    63 messages catalogs.
    64 messages catalogs.
    64 
    65 
    65 
       
    66 Translations in cubicweb-tal template can also be done with TAL tags
    66 Translations in cubicweb-tal template can also be done with TAL tags
    67 `i18n:content` and `i18n:replace`.
    67 `i18n:content` and `i18n:replace`.
    68 
    68 
    69 
       
    70 If you need to add messages on top of those that can be found in the source,
    69 If you need to add messages on top of those that can be found in the source,
    71 you can create a file named `i18n/static-messages.pot`.
    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.
    72 
    74 
    73 Generated string
    75 Generated string
    74 ````````````````
    76 ````````````````
    75 
    77 
    76 We do not need to mark the translation strings of entities/relations used by a
    78 We do not need to mark the translation strings of entities/relations used by a
    78 various actions are also generated.
    80 various actions are also generated.
    79 
    81 
    80 For exemple the following schema ::
    82 For exemple the following schema ::
    81 
    83 
    82   Class EntityA(EntityType):
    84   Class EntityA(EntityType):
    83       relationa2b = SubjectRelation('EntityB')
    85       relation_a2b = SubjectRelation('EntityB')
    84 
    86 
    85   class EntityB(EntityType):
    87   class EntityB(EntityType):
    86       pass
    88       pass
    87 
    89 
    88 May generate the following message ::
    90 May generate the following message ::
    89 
    91 
    90   add Execution has_export File subject
    92   add EntityA relation_a2b EntityB subject
    91 
    93 
    92 This message will be used in views of ``EntityA`` for creation of a new
    94 This message will be used in views of ``EntityA`` for creation of a new
    93 ``EntityB`` with a preset relation ``relation_a2b`` between the current
    95 ``EntityB`` with a preset relation ``relation_a2b`` between the current
    94 ``EntityA`` and the new ``EntityB``. The opposite message ::
    96 ``EntityA`` and the new ``EntityB``. The opposite message ::
    95 
    97 
    96   add Execution has_export File object
    98   add EntityA relation_a2b EntityB object
    97 
    99 
    98 Is used for similar creation of an ``EntityA`` from a view of ``EntityB``. The
   100 Is used for similar creation of an ``EntityA`` from a view of ``EntityB``. The
    99 title of they respective creation form will be ::
   101 title of they respective creation form will be ::
   100 
   102 
   101   creating EntityB (EntityA %(linkto)s relation_a2b EntityB)
   103   creating EntityB (EntityA %(linkto)s relation_a2b EntityB)
   103   creating EntityA (EntityA relation_a2b %(linkto)s EntityA)
   105   creating EntityA (EntityA relation_a2b %(linkto)s EntityA)
   104 
   106 
   105 In the translated string you can use ``%(linkto)s`` for reference to the source
   107 In the translated string you can use ``%(linkto)s`` for reference to the source
   106 ``entity``.
   108 ``entity``.
   107 
   109 
   108 Handle the translation catalog
   110 Handling the translation catalog
   109 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   111 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   110 
   112 
   111 Once the internationalization is done in your code, you need to populate and
   113 Once the internationalization is done in your code, you need to populate and
   112 update the translation catalog. Cubicweb provides the following commands for this
   114 update the translation catalog. Cubicweb provides the following commands for this
   113 purpose:
   115 purpose:
   114 
   116 
   115 
   117 
   116 * `i18ncubicweb` updates Cubicweb framework's translation
   118 * `i18ncubicweb` updates Cubicweb framework's translation
   117   catalogs. Unless you actually work on the framework itself, you
   119   catalogs. Unless you actually work on the framework itself, you
   118   don't need to use this command.
   120   don't need to use this command.
   119 
   121 
   120 * `i18ncube` updates the translation catalogs of *one particular
   122 * `i18ncube` updates the translation catalogs of *one particular cube*
   121   cube* (or of all cubes). After this command is
   123   (or of all cubes). After this command is executed you must update
   122   executed you must update the translation files *.po* in the "i18n"
   124   the translation files *.po* in the "i18n" directory of your
   123   directory of your template. This command will of course not remove
   125   cube. This command will of course not remove existing translations
   124   existing translations still in use.
   126   still in use. It will mark unused translation but not remove them.
   125 
   127 
   126 * `i18ninstance` recompiles the translation catalogs of *one particular
   128 * `i18ninstance` recompiles the translation catalogs of *one particular
   127   instance* (or of all instances) after the translation catalogs of
   129   instance* (or of all instances) after the translation catalogs of
   128   its cubes have been updated. This command is automatically
   130   its cubes have been updated. This command is automatically
   129   called every time you create or update your instance. The compiled
   131   called every time you create or update your instance. The compiled
   132   for exemple).
   134   for exemple).
   133 
   135 
   134 
   136 
   135 Example
   137 Example
   136 ```````
   138 ```````
       
   139 
   137 You have added and/or modified some translation strings in your cube
   140 You have added and/or modified some translation strings in your cube
   138 (after creating a new view or modifying the cube's schema for exemple).
   141 (after creating a new view or modifying the cube's schema for exemple).
   139 To update the translation catalogs you need to do:
   142 To update the translation catalogs you need to do:
   140 
   143 
   141 1. `cubicweb-ctl i18ncube <cube>`
   144 1. `cubicweb-ctl i18ncube <cube>`
   142 2. Edit the <cube>/i18n/xxx.po  files and add missing translations (empty `msgstr`)
   145 2. Edit the <cube>/i18n/xxx.po  files and add missing translations (empty `msgstr`)
   143 3. `hg ci -m "updated i18n catalogs"`
   146 3. `hg ci -m "updated i18n catalogs"`
   144 4. `cubicweb-ctl i18ninstance <myinstance>`
   147 4. `cubicweb-ctl i18ninstance <myinstance>`
   145 
   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).