Übersetzung per QtLinguist

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
kitebuggy
User
Beiträge: 40
Registriert: Donnerstag 5. August 2021, 21:11

Hallo

Ich habe das Beispiel von der offiziellen PySide6 Seite https://doc.qt.io/qtforpython-6/tutoria ... tions.html ausprobiert, bekomme aber jedesmal die GUI in englisch präsentiert.
Alle benötigten Darwiwn sind vorhanden.
Hier der Quellcode:

Code: Alles auswählen

# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
from __future__ import annotations

import sys

from PySide6.QtCore import (QItemSelection, QLibraryInfo, QLocale, QTranslator,
                            Slot)
from PySide6.QtWidgets import (QAbstractItemView, QApplication, QListWidget,
                               QMainWindow)


import linguist_rc  # noqa: F401


class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        file_menu = self.menuBar().addMenu(self.tr("&File"))
        quit_action = file_menu.addAction(self.tr("Quit"))
        quit_action.setShortcut(self.tr("CTRL+Q"))
        quit_action.triggered.connect(self.close)
        help_menu = self.menuBar().addMenu(self.tr("&Help"))
        about_qt_action = help_menu.addAction(self.tr("About Qt"))
        about_qt_action.triggered.connect(qApp.aboutQt)  # noqa: F821

        self._list_widget = QListWidget()
        self._list_widget.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection)
        self._list_widget.selectionModel().selectionChanged.connect(self.selection_changed)
        self._list_widget.addItem("C++")
        self._list_widget.addItem("Java")
        self._list_widget.addItem("Python")
        self.setCentralWidget(self._list_widget)

    @Slot(QItemSelection, QItemSelection)
    def selection_changed(self, selected, deselected):
        count = len(self._list_widget.selectionModel().selectedRows())
        message = self.tr("%n language(s) selected", "", count)
        self.statusBar().showMessage(message)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    path = QLibraryInfo.path(QLibraryInfo.LibraryPath.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)

    window = Window()
    window.show()
    sys.exit(app.exec())
Die installierte Qt Version ist Qt6.10.1.
Funktioniert die Übersetzung überhaupt mit dieser Methode bzw. wie kann ich debuggen, wo der Fehler liegt, z.B.ob die .qm Datei überhaupt geladen wird?

Vielen Dank für eure Hilfe.
Welpe
User
Beiträge: 29
Registriert: Mittwoch 30. Dezember 2020, 10:39

Moin,

ich bin mit PyQt6 unterwegs aber das sollte bei PySide6 ähnlich sein.

Alle zu übersetzende Texte müssen ein "self.tr" davor bekommen wie z.B.

Code: Alles auswählen

self.setWindowTitle(self.tr('Main | English'))
Anschließend wird aus den .py und, falls vorhanden, den .ui Dateien die .TS Datei erzeugt

Code: Alles auswählen

# für PyQt6
qt6-tools lupdate main.py ui/main.ui -ts example_de.ts

# für PySide6 ?
pyside6-lupdate main.py ui/main.ui -ts example_de.ts
Nun mußt du übersetzen, also den Linguist starten, dort die TS Datei öffnen und den Text in die gewünschte Sprache(n) übersetzen

Code: Alles auswählen

# für PyQt6
qt6-tools linguist

# für PySide6 ?
pyside6-linguist
Ist das getan, speicherst du die TS Datei und übersetzt sie ins Binärformat

Code: Alles auswählen

# für PyQt6
qt6-tools lrelease example_de.ts -qm example_de.qm

# für PySide6 ?
pyside6-lrelease example_de.ts -qm example_de.qm
Die Übersetzungen müssen jetzt zur Laufzeit in die QTranslator-Klasse geladen werden

Code: Alles auswählen

path = QLibraryInfo.path(QLibraryInfo.LibraryPath.TranslationsPath)
    translator = QTranslator(app)
    if translator.load(QLocale.system(), 'qtbase', '_', path):
        app.installTranslator(translator)
Das war mein Ausgangspunkt und das sollte so ähnlich auch unter PySide6 laufen.
Hier mal ein kleines Beispiel für eine GUI, die auf Knopfdruck die Sprache wechselt.
Die .qm Dateien mußt du dir, wie oben beschrieben, erzeugen denn die kann ich hier nicht als Code anzeigen.
In der settings.txt wird die gewählte Sprache für den nächsten Start der App gespeichert, kann also beim ersten Start leer sein.

Code: Alles auswählen

# Dateiname: de.ts

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE" sourcelanguage="en_GB">
<context>
    <name>Main</name>
    <message>
        <location filename="../main.py" line="15"/>
        <location filename="../main.py" line="51"/>
        <source>Main | English</source>
        <translation>Main | Deutsch</translation>
    </message>
    <message>
        <location filename="../main.py" line="20"/>
        <location filename="../main.py" line="53"/>
        <source>Change Language</source>
        <translation>Sprache ändern</translation>
    </message>
    <message>
        <location filename="../main.py" line="22"/>
        <location filename="../main.py" line="52"/>
        <source>English</source>
        <translation>Deutsch</translation>
    </message>
    <message>
        <location filename="../main.py" line="59"/>
        <source>Select Language</source>
        <translation>Sprache wählen</translation>
    </message>
    <message>
        <location filename="../main.py" line="59"/>
        <source>Language:</source>
        <translation>Sprache:</translation>
    </message>
</context>
</TS>

Code: Alles auswählen

# Dateiname: en.ts

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_GB" sourcelanguage="en_GB">
<context>
    <name>Main</name>
    <message>
        <location filename="../main.py" line="15"/>
        <location filename="../main.py" line="51"/>
        <source>Main | English</source>
        <translation>Main | English</translation>
    </message>
    <message>
        <location filename="../main.py" line="20"/>
        <location filename="../main.py" line="53"/>
        <source>Change Language</source>
        <translation>Change Language</translation>
    </message>
    <message>
        <location filename="../main.py" line="22"/>
        <location filename="../main.py" line="52"/>
        <source>English</source>
        <translation>English</translation>
    </message>
    <message>
        <location filename="../main.py" line="59"/>
        <source>Select Language</source>
        <translation>Select Language</translation>
    </message>
    <message>
        <location filename="../main.py" line="59"/>
        <source>Language:</source>
        <translation>Language:</translation>
    </message>
</context>
</TS>

Code: Alles auswählen

#  main.py

import sys
from PySide6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QLabel, QInputDialog
from PySide6.QtCore import QTranslator, QLibraryInfo, QLocale


class Main(QWidget):
    def __init__(self):
        super().__init__()
        self.translator = QTranslator()
        self.language_file = 'settings.txt'
        self.initUI()
        self.loadLanguageSetting()

    def initUI(self):
        self.setWindowTitle(self.tr('Main | English'))

        layout = QVBoxLayout()

        input_layout = QVBoxLayout()
        self.language_button = QPushButton(self.tr('Change Language'), self)
        self.language_button.clicked.connect(self.changeLanguage)
        self.label = QLabel(self.tr('English'), self)
        input_layout.addWidget(self.language_button)
        input_layout.addWidget(self.label)
        layout.addLayout(input_layout)

        self.setLayout(layout)
        self.show()

    def saveLanguageSetting(self, language):
        with open(self.language_file, 'w') as file:
            file.write(language)

    def loadLanguageSetting(self):
        try:
            with open(self.language_file, 'r') as file:
                language = file.read().strip()
                self.switchTranslator(language)
        except FileNotFoundError:
            self.switchTranslator('en')

    def switchTranslator(self, language):
        if language == 'en':
            self.translator.load(QLibraryInfo.path(QLibraryInfo.LibraryPath.TranslationsPath))
        elif language == 'de':
            self.translator.load('translations/de.qm')
        QApplication.instance().installTranslator(self.translator)
        self.retranslateUi()

    def retranslateUi(self):
        self.setWindowTitle(self.tr('Main | English'))
        self.label.setText(self.tr('English'))
        self.language_button.setText(self.tr('Change Language'))


    def changeLanguage(self):
        languages = ['English (EN)', 'Deutsch (DE)']
        current_language = 'English (EN)'
        language, ok = QInputDialog.getItem(self, self.tr('Select Language'), self.tr('Language:'), languages, languages.index(current_language), False)
        if ok and language:
            if language == 'English (EN)':
                self.saveLanguageSetting('en')
                self.switchTranslator('en')
            elif language == 'Deutsch (DE)':
                self.saveLanguageSetting('de')
                self.switchTranslator('de')


if __name__ == '__main__':
    app = QApplication(sys.argv)

    path = QLibraryInfo.path(QLibraryInfo.LibraryPath.TranslationsPath)
    translator = QTranslator(app)
    if translator.load(QLocale.system(), 'qtbase', '_', path):
        app.installTranslator(translator)

    gui = Main()
    gui.show()
    sys.exit(app.exec())
Antworten