= Adding l10n support to Trac plugins (Trac >= 0.12) = == Motivation == [FIXME: content needed, especially address the intended audience (plugin maintainers and developers in general) here - who should read on (and who shouldn't care at all)] == i18n vs. l10n (again) == [FIXME: is this needed?, well consider this is nice to the reader allowing to focus on i18n after coming from the greater scope of l10n, but be as short as possible when] == Background and basics of i18n support == The evolution of native support for Trac plugins is documented in [comment:11:ticket:7497 ticket 7497]. The final implementation as documented there in [comment:12:ticket:7497 comment 12] was introduced to Trac trunk in [changeset: changeset r7705] and finally done with [changeset: changeset r7714]. Adding the needed i18n helper functions is as easy as adding {{{ from trac.util.translation import domain_functions _, tag_, N_, add_domain = domain_functions('tracmercurial', '_', 'tag_', 'N_', 'add_domain') }}} at the beginning of the main python script file of an existing or new plugin. To bring in the compiled message catalog for actually using the translated texts one will have to extend the `__init__` function of plugins main class too. For a fictional plugin Foo this would be done like this: {{{ def __init__(self): self._version = None self.ui = None # bind the 'foo' catalog to the specified locale directory locale_dir = pkg_resources.resource_filename(__name__, 'locale') add_domain(self.env.path, locale_dir) }}} assuming that folder `locale` will reside in `./foo/locale/` within the directory structure (of the Python egg). [FIXME: explain what _version and ui are used for or leave them out, if unnecessary here] == Required minimal workflow == a walk-through General advice from [wiki:TracL10N TracL10N] on making good translation for Trac in general applies here too. === Preparing the plugin code === ==== Provide translation configuration ==== add lines to `setup.cfg`, or if it doesn't exist, create it This will tell the translation helper programs where to look and store message catalog files. Since this is a per plugin translation, you need to customize the code to the plugins name wherever it reads `foo` in the example. ==== Mark text for extraction ==== In python scripts you'll have to wrap text with the translation function `_()` to get it handled by translation helper programs. Some code, that was {{{ msg = 'This is a msg text.' }}} before, will read like {{{ msg = _('This is a msg text.') }}} afterwards. This is a somewhat time consuming task depending on the size of the plugin's code. If you initially fail to find all desired texts you may notice this by missing them from the message catalog later and come back to this step again. If the plugin maintainer is unaware of your l10n work or unwilling to support it and he adds more message without the translation function call, remember that you have to do the wrapping of these new texts too. Message extraction for Genshi templates should be done auto-magically. However there is a markup available, to ensure extraction even from less common tags. [FIXME: add details about msg extraction from templates and other files] ==== Register new files for packaging ==== To include the translated messages into the packaged plugin you need to add the path to the catalog files to `package_data` in `setup.py`. ==== New plugin version ==== The plugin will not work with any Trac version before 0.12dev, since import of the translation helper functions introduced for 0.12 will fail. It is possible to wrap the import with a `try:` and define dummy functions in a corresponding `except ImportError:` to allow the plugin to work with older versions of Trac, but there might already be a different version for 0.11 and 0.12, so this is not required in most cases. All the work you did by now will go unnoticed, at least with regard to package naming. To help with identification of the new revision you should bump the plugin's version. This is done by changing the version/revision, typically in `setup.cfg` or `setup.py`. === Translation work === === Compilation and testing === Compile the `messages.po` catalog file with your translations into a machine readable `messages.mo` file. Now go for the plugin packaging, make the python egg. === Advanced stuff === ==== Finally l10n ==== == Related resources ==