Skip to content
Snippets Groups Projects

Initial guide for application translation

Files
2
+ 117
0
.. _translating_applications_guide:
Translating Applications
========================
Applications developed using `GNOME Builder`_, or using `Meson`_ and `Ninja`_ as build tools, can be easily written with translation in mind. This document describes aspects of the development and translation process that should help you to make your application available in multiple languages.
.. contents::
:local:
We begin by looking at the tasks that need to be done when making an application ready for translation.
Overview
--------
For an application to be translatable into multiple languages, it needs three things:
#. Source code that distinguishes between user-visible, translatable text and non-translatable text. See :ref:`translating_applications_guide_visible_text` for ways to do this.
#. A way to make the text available to translators so that it can be translated. This can be part of a build system or a set of tools that are run separately.
#. A build system that takes the translations and bundles them with the application so that they can be used at run-time.
With these in place, there is a framework for a translation process.
.. _translating_applications_guide_visible_text:
Handling User-Visible Text
--------------------------
In Python applications, user-visible text in labels and other widgets is wrapped in function calls, using the ``_()`` translation function. This special underscore method is used by tools to identify the translatable text in source files.
In the following code from the :ref:`examples_Simple_Weather` example, only the user-visible text, ``Remove Place``, is passed to the translation function:
.. literalinclude:: /Apps/Examples/General/Simple_Weather/app/src/widgets.py
:language: python3
:dedent: 8
:start-at: _('Remove Place')
:end-at: 'win.remove'
The ``win.remove`` text is not translated because it defines the scope and name of an action that is only used by the code, and must remain unchanged for the application to work correctly.
Setting up the Translation Function
-----------------------------------
The ``_()`` function is provided by the standard `Python gettext module`_ and is made available throughout the application when the application starts. We do this in the `src/simple-weather.in`_ file which becomes the executable ``simple-weather`` file at when the application is built:
.. literalinclude:: /Apps/Examples/General/Simple_Weather/app/src/simple-weather.in
:language: python3
:start-at: # Enable translation
:end-at: gettext.install
The build system replaces the ``@project_name@`` placeholder with ``simple_weather`` when the application is built. The resulting calls to the functions in ``gettext`` and ``locale`` ensure that the application can use the translation files installed with it.
The translation files contain translations of the original user-visible text strings into other languages. These are generated from a single file that contains all the user-visible text for the application.
Generating a POT File
---------------------
If you want to generate a POT file without updating the existing translation files, you can run the ``simple_weather-pot`` rule that is generated by `Meson`_ when an application's build is configured. This can be done using the `Ninja`_ build tool on the command line from the repository root. For example, this is how the :ref:`examples_Simple_Weather` example's initial POT file was generated:
.. code-block:: bash
meson . _build
ninja -C _build simple_weather-pot
In this case, running these commands causes the `po/simple_weather.pot`_ file to be created if it does not already exist. Otherwise, the existing file is updated with any new strings that are found in the translatable files.
Handling Translation Files
--------------------------
In order to provide a translation of the application, a Portable Object Template (POT) file needs to be generated from all the files that contain user-visible text, including both source code and metadata files. The list of translatable files is the kept in the ``POTFILES`` file in the application's ``po`` directory:
.. literalinclude:: /Apps/Examples/General/Simple_Weather/app/po/POTFILES
These files are searched for translatable text strings, which are extracted from the arguments of the ``_()`` function, when the ``simple_weather-update-po`` rule is run. This can be performed as part of the process of generating and updating Portable Object (PO) files for each of the languages that the application is translated into. You can run this rule on the command line from the repository root:
.. code-block:: bash
meson . _build
ninja -C _build simple_weather-update-po
This is something you should do after adding new user-visible strings to any of the translatable files in the application. The newly created or updated PO files can then be completed by translators before the application is built.
The `LINGUAS`_ file contains a list of the languages that the application aims to support. PO files will be generated for each of these languages. In this example, the list is very small, but other applications may contain extensive lists of languages for which translations are available.
The `po/meson.build`_ file contains the declaration that causes the necessary build rules to be generated:
.. literalinclude:: /Apps/Examples/General/Simple_Weather/app/po/meson.build
:language: python3
:start-at: i18n.gettext
When the application is built, any PO files are compiled to Machine Object (MO) files that will be installed with the application. These files are loaded at run-time when the application calls ``gettext.install`` to install the translation function, as described above.
Testing Translations
--------------------
Different translations for the application can be tested easily if it is started from the command line. Use the ``LANGUAGE`` environment variable to specify the language shown in the user interface, as in these examples:
.. code-block:: bash
# Try the British English translation
LANGUAGE=en_GB simple-weather
# Try the Norwegian Bokmål translation
LANGUAGE=nb simple-weather
By default, the application will run in the current locale, so this approach can help developers to discover issues with translations without having to change their working environments.
Further Reading
---------------
The `GNU gettext utilities`_ manual contains detailed information about working with translations. The `Python gettext module`_ documentation also contains good background information specific to the Python language.
.. include:: /links.txt
.. _`src/simple-weather.in`: https://source.puri.sm/Librem5/example-apps/simple-weather-app/blob/master/src/simple-weather.in
.. _`po/simple_weather.pot`: https://source.puri.sm/Librem5/example-apps/simple-weather-app/blob/master/po/simple_weather.pot
.. _`po/meson.build`: https://source.puri.sm/Librem5/example-apps/simple-weather-app/blob/master/po/meson.build
.. _`LINGUAS`: https://source.puri.sm/Librem5/example-apps/simple-weather-app/blob/master/po/LINGUAS
Loading