Как динамически менять языки (переводы) на PyQt5?
Интересно, можно ли динамически изменять языки (переводы), не используя qt designer для создания пользовательского интерфейса? Это означает, что я не хочу использовать функцию retranslateUi() для обновления интерфейса программы.
Вот мой код, но я застрял на линиях, помеченных #1 #2 #3. Не знаю, что я должен использовать для обновления интерфейса.
import sys
from PyQt5.QtCore import Qt, QTranslator
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel,
QComboBox, QVBoxLayout
class Demo(QWidget):
def __init__(self):
super(Demo, self).__init__()
self.button = QPushButton(self.tr('Start'), self)
self.label = QLabel(self.tr('Hello, World'), self)
self.label.setAlignment(Qt.AlignCenter)
self.combo = QComboBox(self)
self.combo.addItem('English')
self.combo.addItem('中文')
self.combo.addItem('français')
self.combo.currentTextChanged.connect(self.change_func)
self.trans = QTranslator(self)
self.v_layout = QVBoxLayout()
self.v_layout.addWidget(self.combo)
self.v_layout.addWidget(self.button)
self.v_layout.addWidget(self.label)
self.setLayout(self.v_layout)
def change_func(self):
print(self.combo.currentText())
if self.combo.currentText() == '中文':
self.trans.load('eng-chs')
_app = QApplication.instance()
_app.installTranslator(self.trans)
# 1
elif self.combo.currentText() == 'français':
self.trans.load('eng-fr')
_app = QApplication.instance()
_app.installTranslator(self.trans)
# 2
else:
_app = QApplication.instance()
_app.removeTranslator(self.trans)
# 3
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = Demo()
demo.show()
sys.exit(app.exec_())
Любая помощь будет оценена.
2 ответа
Краткий ответ: нет необходимости использовать Qt Designer
Длинный ответ:
Вы не должны обязательно использовать Qt Designer, но вы должны использовать ту же технику, то есть создать метод, который может быть вызван retranslateUi()
и в нем установить тексты, используя translate()
вместо tr()
(для более подробной информации прочитайте документы). Вызов этого метода при изменении языка для него должен использовать changeEvent()
событие. Например, в вашем случае код выглядит следующим образом:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Demo(QtWidgets.QWidget):
def __init__(self):
super(Demo, self).__init__()
self.button = QtWidgets.QPushButton()
self.label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
self.combo = QtWidgets.QComboBox(self)
self.combo.currentIndexChanged.connect(self.change_func)
self.trans = QtCore.QTranslator(self)
self.v_layout = QtWidgets.QVBoxLayout(self)
self.v_layout.addWidget(self.combo)
self.v_layout.addWidget(self.button)
self.v_layout.addWidget(self.label)
options = ([('English', ''), ('français', 'eng-fr' ), ('中文', 'eng-chs'), ])
for i, (text, lang) in enumerate(options):
self.combo.addItem(text)
self.combo.setItemData(i, lang)
self.retranslateUi()
@QtCore.pyqtSlot(int)
def change_func(self, index):
data = self.combo.itemData(index)
if data:
self.trans.load(data)
QtWidgets.QApplication.instance().installTranslator(self.trans)
else:
QtWidgets.QApplication.instance().removeTranslator(self.trans)
def changeEvent(self, event):
if event.type() == QtCore.QEvent.LanguageChange:
self.retranslateUi()
super(Demo, self).changeEvent(event)
def retranslateUi(self):
self.button.setText(QtWidgets.QApplication.translate('Demo', 'Start'))
self.label.setText(QtWidgets.QApplication.translate('Demo', 'Hello, World'))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
demo = Demo()
demo.show()
sys.exit(app.exec_())
Затем сгенерируйте.ts:
pylupdate5 main.py -ts eng-chs.ts
pylupdate5 main.py -ts eng-fr.ts
Затем используйте Qt Linguist для выполнения переводов.
И наконец.qm:
lrelease eng-fr.ts eng-chs.ts
Полный проект вы найдете здесь.
Нет, вам придется использовать технику, которую Qt Designer использует с retranslateUi, потому что система виджетов Qt не имеет способа самостоятельно переделать перевод (в противном случае QT Designer использовал бы это для).
Построение такой системы потребовало бы фундаментальных изменений в виджетах, поскольку для каждого свойства строки вам нужно знать, что она содержит переводимую строку (не значение данных), и знание исходной строки для поиска нового перевода будет наилучшим (реверсирование). переводы могут быть неоднозначными).