Cubicweb fully supports the internalization of its content and interface.
Cubicweb’s interface internationalization is based on the translation project GNU gettext.
Cubicweb’ internalization involves two steps:
In the Python code and cubicweb-tal templates translatable strings can be marked in one of the following ways :
by using the built-in function _:
class PrimaryView(EntityView): """the full view of an non final entity""" __regid__ = 'primary' title = _('primary')OR
by using the equivalent request’s method:
class NoResultView(View): """default view when no result has been found""" __regid__ = 'noresult' def call(self, **kwargs): self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n' % self._cw._('No result matching query'))
The goal of the built-in function _ is only to mark the translatable strings, it will only return the string to translate itself, but not its translation (it’s actually another name for the unicode builtin).
In the other hand the request’s method self._cw._ is also meant to retrieve the proper translation of translation strings in the requested language.
Finally you can also use the __ attribute of request object to get a translation for a string which should not itself added to the catalog, usually in case where the actual msgid is created by string interpolation
self._cw.__('This %s' % etype)
In this example ._cw.__` is used instead of ._cw._` so we don’t have ‘This %s’ in messages catalogs.
Translations in cubicweb-tal template can also be done with TAL tags i18n:content and i18n:replace.
If you need to add messages on top of those that can be found in the source, you can create a file named i18n/static-messages.pot.
You could put there messages not found in the python sources or overrides for some messages of used cubes.
We do not need to mark the translation strings of entities/relations used by a particular instance’s schema as they are generated automatically. String for various actions are also generated.
For exemple the following schema:
class EntityA(EntityType):
relation_a2b = SubjectRelation('EntityB')
class EntityB(EntityType):
pass
May generate the following message
add EntityA relation_a2b EntityB subject
This message will be used in views of EntityA for creation of a new EntityB with a preset relation relation_a2b between the current EntityA and the new EntityB. The opposite message
add EntityA relation_a2b EntityB object
Is used for similar creation of an EntityA from a view of EntityB. The title of they respective creation form will be
creating EntityB (EntityA %(linkto)s relation_a2b EntityB)
creating EntityA (EntityA relation_a2b %(linkto)s EntityA)
In the translated string you can use %(linkto)s for reference to the source entity.
Once the internationalization is done in your code, you need to populate and update the translation catalog. Cubicweb provides the following commands for this purpose:
You have added and/or modified some translation strings in your cube (after creating a new view or modifying the cube’s schema for exemple). To update the translation catalogs you need to do:
Many tools exist to help maintain .po (PO) files. Common editors or development environment provides modes for these. One can also find dedicated PO files editor, such as poedit.
While usage of such a tool is commendable, PO files are perfectly editable with a (unicode aware) plain text editor. It is also useful to know their structure for troubleshooting purposes.
In this section, we selectively quote passages of the GNU gettext manual chapter on PO files, available there:
http://www.gnu.org/software/hello/manual/gettext/PO-Files.html
One PO file entry has the following schematic structure:
white-space
# translator-comments
#. extracted-comments
#: reference...
#, flag...
#| msgid previous-untranslated-string
msgid untranslated-string
msgstr translated-string
A simple entry can look like this:
#: lib/error.c:116
msgid "Unknown system error"
msgstr "Error desconegut del sistema"
It is also possible to have entries with a context specifier. They look like this:
white-space
# translator-comments
#. extracted-comments
#: reference...
#, flag...
#| msgctxt previous-context
#| msgid previous-untranslated-string
msgctxt context
msgid untranslated-string
msgstr translated-string
The context serves to disambiguate messages with the same untranslated-string. It is possible to have several entries with the same untranslated-string in a PO file, provided that they each have a different context. Note that an empty context string and an absent msgctxt line do not mean the same thing.
CubicWeb PO files have both non-contextual and contextual msgids.
Contextual entries are automatically used in some cases. For instance, entity.dc_type(), eschema.display_name(req) or display_name(etype, req, form, context) methods/function calls will use them.
It is also possible to explicitly use the with _cw.pgettext(context, msgid).