LINUX.ORG.RU

Pyqt5 локализация диалоговых окон и др.

 , , ,


2

1

Доброго времени суток! Подскажите как решить проблему локализации в PYQT5? Перерыл кучу статей либо они для PYQT4 или для QT и языка C++. В общем не разобрался самостоятельно. А хочется решить этот вопрос. Помогите пожалуйста, я новичок еще ) сильно не пинайте.

Знаю есть PyQt5.QtCore.QTranslator() но как правильно пользоваться не разобрался (возможно это и не нужно). Кто-то на форумах писал что можно сделать свое диалоговое окно, но зачем если оно уже есть в PyQT5? А вот если бы была возможность переназначить текст кнопок, было бы интересно посмотреть пример.

Если несложно покажите как это сделать на примере ниже. Это просто форма которая при событии closeEvent выводит диалоговое окно. Как на кнопках поменять надписи?

 
import sys
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication
class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
    def initUI(self):               
        self.setGeometry(300, 300, 250, 150)        
        self.setWindowTitle('Message box')    
        self.show()
    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Заголовок окна', "Кнопки не русские, как исправить?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

Ответ на: комментарий от anonymous

Уважаемый anonymous, добавил данные в /etc/default/locale LC_ALL=«ru_RU.UTF-8» но это ничего не дало (у меня Ubuntu 18.04).

У меня вопрос о Pyqt5, а не системных локалях. Проблема с выводом в системе. Это другая тема.

Спасибо за ответ.

Alecsandr1980 ()
Ответ на: комментарий от Alecsandr1980

Это для перевода стандартных кнопок , локаль конечно русская должна быть.

anonymous ()

Нужно подгрузить файлы переводов из Qt для самой библиотеки Qt.

В C++ это делается так:

https://github.com/EXLMOTODEV/coolreader/blob/4ee09f2eb34169c4bef5312e2ad5fde3bc914e89/cr3qt/src/main.cpp#L206-L214

В Python/PyQt должно быть похоже.

Файл qtbase_‘локаль’.qm для Qt 5 можно взять из дистрибутива Qt (или даже дистрибутива пакета).

EXL ★★★★★ ()
Ответ на: комментарий от anonymous

anonymous все делал и sudo locale-gen и qttranslations5-l10n, но как все было так и осталось. Дело в том что и под Windows тажа песня. С локалью системы проблем нет.

А вот то, о чем писал EXL мне кажется и есть решение. Только мне нужно это применить не к QT5 а к PyQT5. Спасибо, что отвечаете! )

Alecsandr1980 ()
Ответ на: комментарий от EXL

Спасибо за ссылку, я об этом читал и что-то похожее находил. Но в силу своих возможностей (я пока чайник) я не смог это применить к PyqT5. Поэтому и задал вопрос.

Вообще странная вещь, разработчиков на PyQT5 достаточно много, полно информации от русскоязычного сообщества о выводе диалоговых окон (сообщения, сохранения или открытия файлов и пр.), но все они в примерах имеют английские названия и никто об этом не говорит, не решает проблему... До этого изучал библиотеку Tkinter она очень простая, но там этой проблемы нет, все работает из коробки.

Я в тоске. Три дня бьюсь и все никак, либо пример для PyQT4 и не хватает знаний адаптировать под PyQT5, либо все для C++ и QT тут отличия существенные и знаний опять не хватает. А я стараюсь, но... (

Alecsandr1980 ()
Ответ на: комментарий от Alecsandr1980

Нашел такую инфу (смотрите ниже). Осталось как-то это применить PyQT5 если это применимо.

Объект класса QTranslator используется для загрузки переводов из специального файла с расширением .qm, который является шестнадцатеричным файлом переводов. Данный файл компилируется из файла переводов в XML формате, который имеет расширение ts и прописывается в pro файле проекта. Данный файл содержит все строки приложения, которые были заключены в функцию tr().


    #include "mainwindow.h"
    #include <QApplication>
    #include <QTranslator>
    #include <QLibraryInfo>
     
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
     
        QTranslator qtLanguageTranslator;
        qtLanguageTranslator.load(QString("QtLanguage_") + QString("ru_RU"));
        qApp->installTranslator(&qtLanguageTranslator);
     
        MainWindow w;
        w.show();
     
        return a.exec();
    }
Alecsandr1980 ()
Ответ на: комментарий от Alecsandr1980

Я в тоске. Три дня бьюсь и все никак, либо пример для PyQT4 и не хватает знаний адаптировать под PyQT5, либо все для C++ и QT тут отличия существенные и знаний опять не хватает. А я стараюсь, но… (

Никаких существенных отличий вообще нет. В чём у вас возникла проблема?

Код:

#!/usr/bin/python3

import os
import sys
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication
from PyQt5.QtCore import QTranslator, QLocale

I18N_QT_PATH = '/usr/share/qt/translations/'

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
    def initUI(self):
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Message box')
        self.show()
    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Заголовок окна', "Кнопки не русские, как исправить?", \
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
if __name__ == '__main__':
    app = QApplication(sys.argv)
    locale = QLocale.system().name()
    translator = QTranslator(app)
    translator.load('{}qtbase_{}.qm'.format(I18N_QT_PATH, locale))
    app.installTranslator(translator)
    ex = Example()
    sys.exit(app.exec_())

Результат:

http://esxi.z-lab.me:666/~exl_lab/screens/PyQt5_I18N.png

Путь до скомпилированных qm-файлов переводов Qt может отличаться в вашем дистрибутиве, так что поправьте его под своё окружение.

EXL ★★★★★ ()
Ответ на: комментарий от EXL

EXL огромное спасибо за ответ... ) Да, у меня путь немного другой оказался «/usr/share/qt5/translations/» :)

У меня возникла проблема в том что: 1 - о *.qm файлах узнал буквально недавно 2 - почитав о том как их (*.qt файлы) получить, я подумал что сначала нужно получить из файла «*.ts» которого нет, но с помощью pylupdate5 можно получить. Так пишут в сети. Еще прочитал о утилите QT5 Linguist которая занимаестя переводами на основе ts файлов.

Оказалось все проще ! Огромное Вам спасибо. Я чайник еще, но учусь :) Иногда информация взятая с разных источников больше запутывает чем приводит к решению. Вот я и запутался :(

Если можно, еще один вопрос Вам. Для мультиплатформенности нужно определять OS и на базе этого подставлять ссылку на «*.qm» файл или есть более элегантное решение?

Alecsandr1980 ()
Ответ на: комментарий от Alecsandr1980

ОГРОМНОЕ СПАСИБО ВСЕМ КТО ОТВЕЧАЛ anonymous и EXL!

Для тех кто ищет ответ как и я.

В установленном PyQT5 уже имеются файлы локализации «*qm» расположенные в папке /usr/share/qt5/translations (в моем случае на Ubuntu 18.04)

Для реализации перевода на родной язык (русский для примера) достаточно подключить файл «*.qm» (qtbase_ru.qm в мое случае)

Пример ниже, спасибо EXL:

import os
import sys
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication
from PyQt5.QtCore import QTranslator, QLocale

I18N_QT_PATH = '/usr/share/qt5/translations/'  #/usr/share/qt5/translations

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
    def initUI(self):
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Message box')
        self.show()
    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Заголовок окна', "Русские кнопки", \
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
if __name__ == '__main__':
    app = QApplication(sys.argv)
    locale = QLocale.system().name()
    translator = QTranslator(app)
    translator.load('{}qtbase_{}.qm'.format(I18N_QT_PATH, locale))
    app.installTranslator(translator)
    ex = Example()
    sys.exit(app.exec_())
Как я понимаю данный файл берется на основе ваших настроек локализации системы. Смею предположить, что изменив немного код, можно задать локализацию принудительно «load('{}qtbase_{}.qm'.format(I18N_QT_PATH, locale)» изменив данную строку.

Alecsandr1980 ()
Ответ на: комментарий от Alecsandr1980

В C++/Qt 5 для интернационализации приложений конвейер следующий:

  1. В своём коде вы пишете все строки на английском языке не вылезая за пределы таблицы ASCII-символов.
  2. Строки, которые нужно локализовать, вы оборачиваете в специальную функцию tr("string").
  3. С помощью утилиты lupdate вы собираете все эти строки в своём проекте в .ts-файлы.
  4. С помощью программы Qt Linguist вы, или нанятый вами переводчик, переводит .ts-файлы на нужные языки.
  5. С помощью утилиты lrelease или просто с помощью той же программы Qt Linguist вы компилируете .ts-файлы в .qm-файлы.
  6. Внутри исходного кода своей программы с помощью нескольких объектов класса QTranslator вы применяете к своей программе переводы строк в зависимости от системной локали.

Подгружать нужно два .qm-файла – своей программы и тот, что относится к библиотеке Qt, то бишь про то, что вы спрашивали.

В PyQt5, судя по его документации, ситуация должна быть похожа за тем лишь исключением, что вместо lupdate используется утилита pylupdate5, а вместо tr("string") используется self.tr('string'), при этом self должен быть наследником QObject-класса (QWidget тоже подойдёт, потому что он тоже наследник QObject).

Соответственно, если вы обернёте свои строки в эту функцию:

reply = QMessageBox.question(self, self.tr('Window Title'), self.tr('How to translate button labels to Russian?'), \
        QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

Вы сможете сделать .ts-файл для своей программы с помощью команды в терминале:

$ pylupdate5 PyQt5_i18n.py -ts ru_RU.ts

Где PyQt5_i18n.py – название фашего исходного .py-файла; если их несколько их можно просто там перечислить.

Получив .ts-файл, действуйте по инструкции выше и по аналогии.

EXL ★★★★★ ()
Ответ на: комментарий от Alecsandr1980

Если можно, еще один вопрос Вам. Для мультиплатформенности нужно определять OS и на базе этого подставлять ссылку на «*.qm» файл или есть более элегантное решение?

Файлы .qm являются независимыми от платформы, но они зависят от версии Qt, поэтому лучше всего «таскать» все файлы переводов с собой в отдельном каталоге дистрибутива вашей PyQt5 программы. Особенно это справедливо для Windows и macOS, на которых Qt 5 может быть вообще не установлен.

Как пример того что я описал выше:

http://esxi.z-lab.me:666/~exl_lab/software/PyQt5_i18n.zip

EXL ★★★★★ ()
Ответ на: комментарий от EXL

Огромное спасибо! :) Разложили все по полочкам, очень рад общению с вами. Спасибо, за информацию!!! В голове что-то похожее выстраивалось но очень отдаленно и как применить, как правильно написать код не понимал, а тут Вы все очень подробно с примером «PyQt5_i18n.zip»

Alecsandr1980 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.