Coding for translation using weblate

From Gramps
Revision as of 19:03, 29 June 2021 by Nick H (talk | contribs)
Jump to: navigation, search

Coding guidelines to enable easy and correct translation of strings on the User Interface.

Introduction

Gramps has always been internationalized (see: https://gramps-project.org/introduction-WP/2006/04/looking-back-over-5-years/ ) Therefore, all strings meant for the user should always be flagged for translation.

In order to be considered for inclusion in the official Gramps release, any piece of code must support internationalization. What this means is that the Python module must support translations into different languages. Gramps provides support to make this as easy as possible for the developer.

How to allow translations

Gramps is a fully-internationalized application with translations in many languages. All code which presents text to users must provide for that text to be translated. Fortunately, Gramps provides an extension of gettext which makes this fairly painless.

Simple strings

First, alias the gettext function from the single localization instance:

from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext

This statement imports the gettext function and aliases it as _. The translation tools treat strings wrapped in _() as translatable and assemble them into catalogs for the translators to work with; by aliasing it to gettext(), we also enable python to retrieve the translation appropriate for the user's locale.

Example 1:

print("Hello world!")

In this example, the string will always be printed as specified.

Example 1 internationalized:

print _("Hello world!")

In this example, Gramps will attempt to translate the string. If a translation exists, the call to the function will return the translation. If a translation does not exist, the original string is returned.

Plurals

In some strings, it's necessary to specify different translations depending upon the number of an argument. For example,

George Smith and Annie Jones have 1 child 
George Smith and Annie Jones have 3 children

We'd code that in python as follows:

_ = glocale.translation.ngettext
_("George Smith and Annie Jones have %(num)d child", "George Smith and Annie Jones have %(num)d children", n) % {num : n}

Context

Sometimes a word in English can have different meanings, for example, "rest" can mean either "what's left" or "take a nap". In such cases, we can provide the context by passing a second optional parameter:

_("rest", "Remaining names")

We're making sure that the translators know the context of the string. The context is made available to the translators in Weblate, but is not displayed to the user.

Comments

A note can be passed to the translators by including a comment in the code on the line before the translated string. This comment must begin with the string "Translators:" and may be multi-line.

# Translators:  Keep your translation short
_("short string")

Glade files

Strings can be marked as translatable in the "Edit Text" dialog in the Glade editor. Context and comments can also be added.

Glade edit text dialog.png

These are saved as translatable, context and comments attributes on an XML element.

<property name="label" translatable="yes" context="context" comments="comment">string</property>

Addons

Third-party addons often need to provide their own message catalogs. To pull one in, use this instead of the usual.

from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.get_addon_translator(__file__).gettext

or if you need more than one retrieval function:

 _translation = glocale.get_addon_translator(__file__)
 _ = _translation.gettext

The addon translator is another instance of GrampsTranslation, so the rules for creating translatable strings and for retrieving the translated values are the same as for internal modules.

See Addons development for more details.

Workflow

Generating the template file

Strings marked for translation are automatically extracted into a template file called gramps.pot. This is used to update the .po file for each translation.

When translated strings are changed the template file should be regenerated with the following:

cd po
python update_po.py -p

Weblate will then merge each translation file with the new template and notify translators of new strings to translate.

Adding and removing files

Every python file in Gramps should be listed in either POTFILES.in if it contains translated strings or POTFILES.skip if it doesn't. These files are used when generating the template file.

If a file is added or removed from Gramps, these files should be updated accordingly.

Adding a new language

To add a new language, navigate to the "gramps" component in Weblate and click on the Tools -> Start new translation menu option. Then select a language code. You need to be a Weblate administrator to do this.

Then the language code must be added to the LINGUAS file.

An entry must also be made in the _LOCALE_NAMES dictionary in the grampslocale.py file.