aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/doc/tutorials/basictutorial/translations.rst
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/doc/tutorials/basictutorial/translations.rst')
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/translations.rst168
1 files changed, 93 insertions, 75 deletions
diff --git a/sources/pyside6/doc/tutorials/basictutorial/translations.rst b/sources/pyside6/doc/tutorials/basictutorial/translations.rst
index 31cd004a3..21c16cdcd 100644
--- a/sources/pyside6/doc/tutorials/basictutorial/translations.rst
+++ b/sources/pyside6/doc/tutorials/basictutorial/translations.rst
@@ -9,10 +9,10 @@ Translating Applications
Qt Linguist
-----------
-`Qt Linguist <https://doc.qt.io/qt-6/qtlinguist-index.html>`_ and
+`Qt Linguist`_ and
its related tools can be used to provide translations for applications.
-The ``examples/widgets/linguist`` example illustrates this. The example is
+The :ref:`qt-linguist-example` example illustrates this. The example is
very simple, it has a menu and shows a list of programming languages with
multiselection.
@@ -28,18 +28,18 @@ The linguist example has a number of messages enclosed in ``self.tr()``.
The status bar message shown in response to a selection change uses
a plural form depending on a count:
- .. code-block:: python
+.. code-block:: python
- count = len(self._list_widget.selectionModel().selectedRows())
- message = self.tr("%n language(s) selected", "", count)
+ count = len(self._list_widget.selectionModel().selectedRows())
+ message = self.tr("%n language(s) selected", "", count)
The translation workflow for the example is as follows:
The translated messages are extracted using the ``lupdate`` tool,
producing XML-based ``.ts`` files:
- .. code-block:: bash
+.. code-block:: bash
- pyside6-lupdate main.py -ts example_de.ts
+ pyside6-lupdate main.py -ts example_de.ts
If ``example_de.ts`` already exists, it will be updated with the new
messages added to the code in-between.
@@ -52,15 +52,29 @@ they should be passed to the ``pyside6-lupdate`` tool as well:
pyside6-lupdate main.py main.qml form.ui -ts example_de.ts
The source files generated by ``pyside6-uic`` from the form files
-should `not` be passed.
+should **not** be passed.
+
+The ``lupdate`` mode of ``pyside6-project`` can also be used for this. It
+collects all source files and runs ``pyside6-lupdate`` when ``.ts`` file(s)
+are given in the ``.pyproject`` file:
+
+.. code-block:: bash
+
+ pyside6-project lupdate .
``.ts`` files are translated using *Qt Linguist*. Once this is complete,
the files are converted to a binary form (``.qm`` files):
- .. code-block:: bash
+.. code-block:: bash
+
+ pyside6-lrelease example_de.ts -qm example_de.qm
+
+``pyside6-project`` will build the ``.qm`` file automatically when
+``.ts`` file(s) are given in the ``.pyproject`` file:
- mkdir translations
- pyside6-lrelease example_de.ts -qm translations/example_de.qm
+.. code-block:: bash
+
+ pyside6-project build .
To avoid having to ship the ``.qm`` files, it is recommend
to put them into a Qt resource file along with icons and other
@@ -68,43 +82,45 @@ applications resources (see :ref:`using_qrc_files`).
The resource file ``linguist.qrc`` provides the ``example_de.qm``
under ``:/translations``:
- .. code-block:: xml
+.. code-block:: xml
- <!DOCTYPE RCC><RCC version="1.0">
- <qresource>
- <file>translations/example_de.qm</file>
- </qresource>
- </RCC>
+ <!DOCTYPE RCC><RCC version="1.0">
+ <qresource prefix="translations">
+ <file>example_de.qm</file>
+ </qresource>
+ </RCC>
At runtime, the translations need to be loaded using the ``QTranslator`` class:
- .. code-block:: python
+.. code-block:: python
- path = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
- translator = QTranslator(app)
- if translator.load(QLocale.system(), 'qtbase', '_', path):
- app.installTranslator(translator)
- translator = QTranslator(app)
- path = ':/translations'
- if translator.load(QLocale.system(), 'example', '_', path):
- app.installTranslator(translator)
+ path = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
+ translator = QTranslator(app)
+ if translator.load(QLocale.system(), 'qtbase', '_', path):
+ app.installTranslator(translator)
+ translator = QTranslator(app)
+ path = ':/translations'
+ if translator.load(QLocale.system(), 'example', '_', path):
+ app.installTranslator(translator)
The code first loads the translations shipped for Qt and then
the translations of the applications loaded from resources.
The example can then be run in German:
- .. code-block:: bash
+.. code-block:: bash
+
+ LANG=de python main.py
- LANG=de python main.py
+.. _Qt Linguist: https://doc.qt.io/qt-6/qtlinguist-index.html
GNU gettext
-----------
-The `GNU gettext <https://docs.python.org/3/library/gettext.html>`_ module
+The `GNU gettext`_ module
can be used to provide translations for applications.
-The ``examples/widgets/gettext`` example illustrates this. The example is
+The :ref:`gettext-example` example illustrates this. The example is
very simple, it has a menu and shows a list of programming languages with
multiselection.
@@ -116,29 +132,29 @@ aliased to ``ngettext``.
Those functions are defined at the top:
- .. code-block:: python
+.. code-block:: python
- import gettext
- ...
- _ = None
- ngettext = None
+ import gettext
+ # ...
+ _ = None
+ ngettext = None
and later assigned as follows:
- .. code-block:: python
-
- src_dir = Path(__file__).resolve().parent
- try:
- translation = gettext.translation('example', localedir=src_dir / 'locales')
- if translation:
- translation.install()
- _ = translation.gettext
- ngettext = translation.ngettext
- except FileNotFoundError:
- pass
- if not _:
- _ = gettext.gettext
- ngettext = gettext.ngettext
+.. code-block:: python
+
+ src_dir = Path(__file__).resolve().parent
+ try:
+ translation = gettext.translation('example', localedir=src_dir / 'locales')
+ if translation:
+ translation.install()
+ _ = translation.gettext
+ ngettext = translation.ngettext
+ except FileNotFoundError:
+ pass
+ if not _:
+ _ = gettext.gettext
+ ngettext = gettext.ngettext
This specifies that our translation file has the base name ``example`` and
will be found in the source tree under ``locales``. The code will try
@@ -146,18 +162,18 @@ to load a translation matching the current language.
Messages to be translated look like:
- .. code-block:: python
+.. code-block:: python
- file_menu = self.menuBar().addMenu(_("&File"))
+ file_menu = self.menuBar().addMenu(_("&File"))
The status bar message shown in response to a selection change uses
a plural form depending on a count:
- .. code-block:: python
+.. code-block:: python
- count = len(self._list_widget.selectionModel().selectedRows())
- message = ngettext("{0} language selected",
- "{0} languages selected", count).format(count)
+ count = len(self._list_widget.selectionModel().selectedRows())
+ message = ngettext("{0} language selected",
+ "{0} languages selected", count).format(count)
The ``ngettext()`` function takes the singular form, plural form and the count.
The returned string still contains the formatting placeholder, so it needs
@@ -172,43 +188,45 @@ is first created:
xgettext -L Python -o locales/example.pot main.py
This file has a few generic placeholders which can be replaced by the
-appropriate values. It is then copied to the ``de_DE/LC_MESSAGES`` directory.
+appropriate values. It is then copied to the ``de_DE/LC_MESSAGES`` directory.
- .. code-block:: bash
+.. code-block:: bash
- cd locales/de_DE/LC_MESSAGES/
- cp ../../example.pot .
+ cd locales/de_DE/LC_MESSAGES/
+ cp ../../example.pot .
Further adaptions need to be made to account for the German plural
form and encoding:
- .. code-block::
+.. code-block::
- "Project-Id-Version: PySide6 gettext example\n"
- "POT-Creation-Date: 2021-07-05 14:16+0200\n"
- "Language: de_DE\n"
- "MIME-Version: 1.0\n"
- "Content-Type: text/plain; charset=UTF-8\n"
- "Content-Transfer-Encoding: 8bit\n"
- "Plural-Forms: nplurals=2; plural=n != 1;\n"
+ "Project-Id-Version: PySide6 gettext example\n"
+ "POT-Creation-Date: 2021-07-05 14:16+0200\n"
+ "Language: de_DE\n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: text/plain; charset=UTF-8\n"
+ "Content-Transfer-Encoding: 8bit\n"
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
Below, the translated messages can be given:
- .. code-block::
+.. code-block::
- #: main.py:57
- msgid "&File"
- msgstr "&Datei"
+ #: main.py:57
+ msgid "&File"
+ msgstr "&Datei"
Finally, the ``.pot`` is converted to its binary form (machine object file,
``.mo``), which needs to be deployed:
- .. code-block:: bash
+.. code-block:: bash
- msgfmt -o example.mo example.pot
+ msgfmt -o example.mo example.pot
The example can then be run in German:
- .. code-block:: bash
+.. code-block:: bash
+
+ LANG=de python main.py
- LANG=de python main.py
+.. _GNU gettext: https://docs.python.org/3/library/gettext.html