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 |
|
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(EmptyRsetView): |
|
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 meant to retrieve the |
|
54 proper translation of translation strings in the requested language. |
|
55 |
|
56 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 usually in case where the actual msgid is created by string interpolation :: |
|
59 |
|
60 self._cw.__('This %s' % etype) |
|
61 |
|
62 In this example ._cw.__` is used instead of ._cw._` so we don't have 'This %s' in |
|
63 messages catalogs. |
|
64 |
|
65 |
|
66 Translations in cubicweb-tal template can also be done with TAL tags |
|
67 `i18n:content` and `i18n:replace`. |
|
68 |
|
69 |
|
70 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`. |
|
72 |
|
73 Generated string |
|
74 ```````````````` |
|
75 |
|
76 We do not need to mark the translation strings of entities/relations used by a |
|
77 particular instance's schema as they are generated automatically. String for |
|
78 various actions are also generated. |
|
79 |
|
80 For exemple the following schema :: |
|
81 |
|
82 Class EntityA(EntityType): |
|
83 relationa2b = SubjectRelation('EntityB') |
|
84 |
|
85 class EntityB(EntityType): |
|
86 pass |
|
87 |
|
88 May generate the following message :: |
|
89 |
|
90 add Execution has_export File subject |
|
91 |
|
92 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 |
|
94 ``EntityA`` and the new ``EntityB``. The opposite message :: |
|
95 |
|
96 add Execution has_export File object |
|
97 |
|
98 Is used for similar creation of an ``EntityA`` from a view of ``EntityB``. The |
|
99 title of they respective creation form will be :: |
|
100 |
|
101 creating EntityB (EntityA %(linkto)s relation_a2b EntityB) |
|
102 |
|
103 creating EntityA (EntityA relation_a2b %(linkto)s EntityA) |
|
104 |
|
105 In the translated string you can use ``%(linkto)s`` for reference to the source |
|
106 ``entity``. |
|
107 |
|
108 Handle the translation catalog |
|
109 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
110 |
|
111 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 |
|
113 purpose: |
|
114 |
|
115 |
|
116 * `i18ncubicweb` updates Cubicweb framework's translation |
|
117 catalogs. Unless you actually work on the framework itself, you |
|
118 don't need to use this command. |
|
119 |
|
120 * `i18ncube` updates the translation catalogs of *one particular |
|
121 cube* (or of all cubes). After this command is |
|
122 executed you must update the translation files *.po* in the "i18n" |
|
123 directory of your template. This command will of course not remove |
|
124 existing translations still in use. |
|
125 |
|
126 * `i18ninstance` recompiles the translation catalogs of *one particular |
|
127 instance* (or of all instances) after the translation catalogs of |
|
128 its cubes have been updated. This command is automatically |
|
129 called every time you create or update your instance. The compiled |
|
130 catalogs (*.mo*) are stored in the i18n/<lang>/LC_MESSAGES of |
|
131 instance where `lang` is the language identifier ('en' or 'fr' |
|
132 for exemple). |
|
133 |
|
134 |
|
135 Example |
|
136 ``````` |
|
137 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). |
|
139 To update the translation catalogs you need to do: |
|
140 |
|
141 1. `cubicweb-ctl i18ncube <cube>` |
|
142 2. Edit the <cube>/i18n/xxx.po files and add missing translations (empty `msgstr`) |
|
143 3. `hg ci -m "updated i18n catalogs"` |
|
144 4. `cubicweb-ctl i18ninstance <myinstance>` |
|
145 |
|