Python e Qt 6: Como utilizar QTranslator e translate

No texto de hoje veremos como utilizar QTranslator e translate para traduzir interfaces gráficas criadas com a linguagem de programação Python (PyQt6) e Qt 6.

O primeiro passo é criar uma interface gráfica e nela marcar com translante os textos que serão traduzidos.

Como exemplo podemos utilizar o seguinte código:

# -*- coding: utf-8 -*-
"""Python e Qt 6: PyQt6 QTranslator() e translate."""

from pathlib import Path

from PyQt6.QtCore import Qt, QTranslator, QSettings, QLocale
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QWidget,
                             QLabel, QComboBox)

# Informações do aplicativo.
APPLICATION_NAME = 'br.natorsc.Exemplo'
ORGANIZATION_NAME = APPLICATION_NAME.split('.')[1]
ORGANIZATION_DOMAIN = '.'.join(APPLICATION_NAME.split('.')[0:2])

BASE_DIR = Path(__file__).resolve().parent
ICONS_DIR = BASE_DIR.parent.parent
LANGS_DIR = BASE_DIR.joinpath('locales')

HOME_DIR = Path.home()
CONF_FILE = HOME_DIR.joinpath(
    '.config',
    ORGANIZATION_NAME,
    f'{APPLICATION_NAME}.conf',
)

window_icon = ICONS_DIR.joinpath('assets', 'icons', 'icon-256x256.png')
app_settings = QSettings(ORGANIZATION_NAME, APPLICATION_NAME)


class MainWindow(QMainWindow):

    def __init__(self, application):
        super().__init__()
        self.application = application

        # Informações do monitor principal.
        primary_screen = self.application.primaryScreen()
        primary_screen_geometry = primary_screen.geometry()
        primary_screen_height = primary_screen_geometry.height()
        primary_screen_width = primary_screen_geometry.width()

        # Configurando a janela.
        # Definindo o tamanho da janela de forma dinâmica.
        window_width = int(primary_screen_width / 2)
        window_height = int(primary_screen_height / 2)
        # Configurando a posição e tamanho.
        self.setGeometry(0, 0, window_width, window_height)
        # Tamanho minimo da janela.
        self.setMinimumSize(window_width, window_height)
        # Tamanho maximo da janela.
        self.setMaximumSize(window_width + 200, window_height + 200)
        # Titulo da janela.
        self.setWindowTitle(
            self.application.translate(
                'window_title',
                'Python e Qt 6: PyQt6 QTranslator() e translate.',
            ),
        )
        # Ícone da janela
        self.setWindowIcon(QIcon(str(window_icon)))

        # Layout do central_widget.
        vbox = QVBoxLayout()

        # Widget central.
        central_widget = QWidget()
        # Definindo o layout do widget central.
        central_widget.setLayout(vbox)
        # Adicionando o widget central.
        self.setCentralWidget(central_widget)

        # O seu código aqui:
        label = QLabel()
        label.setText(
            self.application.translate(
                'label',
                'Após trocar o idioma é necessário reiniciar o aplicativo.',
            ),
        )
        label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        vbox.addWidget(label)

        self.combobox = QComboBox()
        self.combobox.addItem(
            self.application.translate(
                'combobox',
                'Selecione um idioma.',
            ),
        )
        self.combobox.addItem('en_US')
        self.combobox.addItem('pt_BR')
        self.combobox.setCurrentText(app_settings.value('language'))
        self.combobox.currentIndexChanged.connect(self.set_translate)
        vbox.addWidget(self.combobox)

        self.show()

    def set_translate(self, index):
        combobox_text = self.combobox.currentText()
        if index != 0:
            if combobox_text == 'pt_BR':
                app_settings.setValue('language', 'default')
            else:
                app_settings.setValue('language', f'{combobox_text}')


if __name__ == "__main__":
    import sys

    # Verificando a plataforma onde o código está sendo executado.
    if sys.platform == 'win32' or sys.platform == 'win64':
        from ctypes import windll

        # Para exibir o ícone na taskbar (barra de tarefas) do windows.
        windll.shell32.SetCurrentProcessExplicitAppUserModelID(APPLICATION_NAME)
    elif sys.platform == 'linux':
        from os import environ, getenv

        # Definindo o tipo de sessão onde o código será executado.
        if getenv('XDG_SESSION_TYPE') == 'wayland':
            environ['QT_QPA_PLATFORM'] = 'wayland'
        elif getenv('XDG_SESSION_TYPE') is None:
            # Funciona bem no Chrome OS.
            environ['QT_QPA_PLATFORM'] = 'xcb'

    application = QApplication(sys.argv)
    application.setOrganizationName(ORGANIZATION_NAME)
    application.setOrganizationDomain(ORGANIZATION_DOMAIN)
    application.setApplicationName(APPLICATION_NAME)
    application.setDesktopFileName(f'{APPLICATION_NAME}.desktop')

    if CONF_FILE.exists():
        translator = QTranslator()
        translator.load(
            str(
                LANGS_DIR.joinpath(
                    f'{app_settings.value("language")}',
                    'LC_MESSAGES',
                    f'{APPLICATION_NAME}.qm',
                ),
            ),
        )
        application.installTranslator(translator)
    else:
        system_locale = QLocale()

        translator = QTranslator()
        translator.load(
            str(
                LANGS_DIR.joinpath(
                    f'{system_locale.name()}',
                    'LC_MESSAGES',
                    f'{APPLICATION_NAME}.qm',
                ),
            ),
        )
        application.installTranslator(translator)

    window = MainWindow(application=application)
    sys.exit(application.exec())

Tradução

Nota: Para esse tutorial estou armazenando os arquivos de tradução dentro de um diretório chamado locales:

.
├── locales
│   └── en_US
│       └── LC_MESSAGES
│           ├── br.natorsc.Exemplo.qm
│           └── br.natorsc.Exemplo.ts
└── MainWindow.py

No Qt os arquivos de tradução tem a extensão *.**ts, esse arquivo é do tipo XML.

Arquivos de tradução podem ser gerados ou atualizados utilizando-se o comando:

pylupdate6 MainWindow.py \
--ts locales/en_US/LC_MESSAGES/br.natorsc.Exemplo.ts

Caso esteja utilizando Qt 5 o comando será:

pylupdate5 MainWindow.py \
--ts locales/en_US/LC_MESSAGES/br.natorsc.Exemplo.ts

Nota: O comando pylupdate6 ou pylupdate5 vem junto com a instalação do PyQt6 ou PyQt5.

Também é possível gerar o arquivo *.**ts a partir de um arquivo de interface (*.ui) do Qt Designer ou Qt Creator , para isso:

pylupdate5 MainWindow.ui \
--ts locales/en_US/LC_MESSAGES/br.natorsc.Exemplo.ts

Ao abrir o arquivo que foi gerado o mesmo terá todos os textos que foram marcados como traduzíveis:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
  <context>
    <name>combobox</name>
    <message>
      <location filename="../../MainWindow.py" line="84" />
      <source>Selecione um idioma.</source>
      <translation>Select a language.</translation>
    </message>
  </context>
  <context>
    <name>label</name>
    <message>
      <location filename="../../MainWindow.py" line="74" />
      <source>Após trocar o idioma é necessário reiniciar o aplicativo.</source>
      <translation>After changing the language it is necessary to restart the application.</translation>
    </message>
  </context>
  <context>
    <name>window_title</name>
    <message>
      <location filename="../../MainWindow.py" line="53" />
      <source>Python e Qt 6: PyQt6 QTranslator() e translate.</source>
      <translation>Python and Qt 6: PyQt6 QTranslator() and translate</translation>
    </message>
  </context>
</TS>
  • <name>: Nome que identifica o componente (widget) na interface gráfica.
  • <source>: Texto original.
  • <translation>: Texto traduzido.

O arquivo de tradução (*.ts) não é utilizando diretamente, para sua utilização é necessário converter o mesmo para um arquivo binário do tipo *.qm.

Para gerar o arquivo binário do tipo *.qm utilize o comando:

lrelease locales/en_US/LC_MESSAGES/br.natorsc.Exemplo.ts \
-qm locales/en_US/LC_MESSAGES/br.natorsc.Exemplo.qm

Após gerar o arquivo *.qm utilize o código de exemplo que está no inicio desse texto para testar o resultado:

Interface gráfica traduzida com QTranslator e translate.

Interface gráfica traduzida com QTranslator e translate.

Extra

Linguist

Uma ferramenta útil para arquivos de tradução é o linguist, para executar o mesmo basta abrir um terminal e digitar:

linguist

Nota: Se o comando não estiver disponível instale as ferramentas de desenvolvimento do Qt 6 (ou 5) no seu sistema operacional.

Ferramentas de desenvolvimento

Ubuntu e derivados
sudo apt install \
pyqt5-dev-tools \
qttools5-dev \
qttools5-dev-tools
Fedora
sudo dnf install \
python-qt5-devel \
qt5-qttools \
qt5-qttools-devel

Para mais exemplos de código acesse o meu repositório no Github: