Как менять язык всего интерфейса по команде от пользователя?

Есть два языка на выбор: русский и английский.

Как реализовать так, чтобы например пользователь выбрал русский язык весь интерфейс менялся на русский, если выберет английский то всё менялось на английский.

Как можно реализовать (приложение создано на PyQt5 - графический)?

Пример кода

from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5 import QtWidgets
import window_1
import sys
import ctypes
import os


class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):

        QtWidgets.QMainWindow.__init__(self)

        # создание обьекта для построения меню (в другом классе)
        self.menuBar = QtWidgets.QMenuBar()

        # создание файла для сохранения натроек
        if os.name == "nt":   # проверка на название системы
            self.CONFIG_FILE_NAME = 'settings\\config.ini'

        self.centralWidget = QtWidgets.QWidget() # создаём центральный виджет
        self.setCentralWidget(self.centralWidget)
        self.mainLayout = QtWidgets.QVBoxLayout(self.centralWidget)

        # settings
        self.setFixedSize(640, 600)
        self.setWindowTitle(" B U G ")
        self.setWindowIcon(QtGui.QIcon("settings\\bug.ico"))

        # делаем сборку
        self.widget_main = self.create_page()
        self.mainLayout.addWidget(self.widget_main)
        self.create_menuBar()
        self.create_toolBar()

        # для строки состоянии
        self.label_1 = QtWidgets.QLabel("v 1.0")
        self.label_1.setStyleSheet("font-size: 18px; color: black;")

        self.status_1.addPermanentWidget(self.label_1)
        self.status_1.showMessage("Добро пожаловать!", msecs = 4000)
        self.setStatusBar(self.status_1)

    def create_page(self):

        self.widget_page = QtWidgets.QWidget()

        # создание обьектов
        self.button_1 = QtWidgets.QPushButton("Перейти к поиску телефонных\nномеров и электронных почт")

        self.formbox = QtWidgets.QGridLayout()

        # добавление в box и в окно
        self.formbox.addWidget(self.button_1)

        self.formbox.setSpacing(20)

        self.widget_page.setLayout(self.formbox)

        # датчики и события
        self.button_1.clicked.connect(self.clicked_button_1)

        # сделать главным комонентом в общем
        return self.widget_page  # возращает

    def create_menuBar(self):

        # создание панели-меню и строки состоянии
        self.menu = QtWidgets.QMenuBar()
        self.status_1 = QtWidgets.QStatusBar()  

        # создание категорий меню и функционал в ней
        self.menu_options = QtWidgets.QMenu("Опции")
        self.menu_view = QtWidgets.QMenu('Вид')
        self.menu_help = QtWidgets.QMenu("Справка")

        self.sub_menu_in_options_settings_1 = QtWidgets.QMenu("Настройки")

        # настройки строки состояния
        self.options_settings_status = QtWidgets.QAction("Включить панель состояния")
        self.options_settings_status.setCheckable(True)
        self.options_settings_status.setChecked(True)

        self.sub_menu_in_options_settings_1.addAction(self.options_settings_status)
        self.menu_options.addMenu(self.sub_menu_in_options_settings_1)

        # настройки поиска
        self.sub_menu_options_search = QtWidgets.QMenu("Настройки поиска")

        self.action_search_options_1 = QtWidgets.QAction("Искать всё")
        self.action_search_options_1.setCheckable(True)
        self.action_search_options_1.setChecked(True)
        self.action_search_options_2 = QtWidgets.QAction("Телефонные номера")
        self.action_search_options_2.setCheckable(True)
        self.action_search_options_3 = QtWidgets.QAction("Электронные почты и акк") 
        self.action_search_options_3.setCheckable(True)

        self.group_action_1 = QtWidgets.QActionGroup(self.sub_menu_options_search)

        self.group_action_1.addAction(self.action_search_options_1) # добавление в groupbox
        self.group_action_1.addAction(self.action_search_options_2)
        self.group_action_1.addAction(self.action_search_options_3)

        self.sub_menu_options_search.addAction(self.action_search_options_1) # добавление в вложенное
        self.sub_menu_options_search.addAction(self.action_search_options_2) # меню
        self.sub_menu_options_search.addAction(self.action_search_options_3)

        self.menu_options.addMenu(self.sub_menu_options_search) # добавление в меню опции


        # настройка языка
        self.delimiter_2 = QtWidgets.QAction()
        self.delimiter_2.setSeparator(True)

        self.menu_options.addAction(self.delimiter_2)

        self.language_menu = QtWidgets.QMenu("Язык")

        self.language_russian = QtWidgets.QAction("Русcкий (ru)")
        self.language_russian.setCheckable(True)
        self.language_russian.setChecked(True)
        self.language_english = QtWidgets.QAction("English (en)")
        self.language_english.setCheckable(True)

        self.group_action_6 = QtWidgets.QActionGroup(self.language_menu)

        self.group_action_6.addAction(self.language_english)
        self.group_action_6.addAction(self.language_russian)

        self.language_menu.addAction(self.language_english)
        self.language_menu.addAction(self.language_russian)

        self.menu_options.addMenu(self.language_menu)

        # настройка тем
        self.sub_menu_view_themes = QtWidgets.QMenu("Цветовая схема")

        self.view_theme_1 = QtWidgets.QAction("Тёмно-синяя тема")
        self.view_theme_1.setCheckable(True)
        self.view_theme_2 = QtWidgets.QAction("Светло-серая тема")
        self.view_theme_2.setCheckable(True)
        self.view_theme_2.setChecked(True)
        self.view_theme_3 = QtWidgets.QAction("Тёмно-коричневая тема")
        self.view_theme_3.setCheckable(True)

        self.group_action_5 = QtWidgets.QActionGroup(self.sub_menu_view_themes)

        self.group_action_5.addAction(self.view_theme_1)
        self.group_action_5.addAction(self.view_theme_2)
        self.group_action_5.addAction(self.view_theme_3)

        self.sub_menu_view_themes.addAction(self.view_theme_1)
        self.sub_menu_view_themes.addAction(self.view_theme_2)
        self.sub_menu_view_themes.addAction(self.view_theme_3)

        self.menu_view.addMenu(self.sub_menu_view_themes)

        # добавляем отдельное меню в главное меню
        self.menu.addMenu(self.menu_options)
        self.menu.addMenu(self.menu_view)
        self.menu.addMenu(self.menu_help)

        # датчики
        self.options_settings_status.triggered.connect(self.toggleMenu)

        # добавляем в окно
        self.setMenuBar(self.menu)


    def create_toolBar(self):
        self.toolBar = QtWidgets.QToolBar()

        self.action_back = QtWidgets.QAction("Вернуться назад")
        self.toolBar.addAction(self.action_back)

        self.addToolBar(self.toolBar)

    # функции для датчиков
    def toggleMenu(self, state):

        if state:
            self.statusBar().show()
        else:
            self.statusBar().hide()

    def clicked_button_1(self):
        widget = self.centralWidget.layout().itemAt(0).widget()
        self.centralWidget.layout().removeWidget(widget)     
        widget.hide()
        self.window_1 = window_1.Page_find_numbers(self)                           
        self.action_back.triggered.connect(self.clicked_action_back)
        self.mainLayout.addWidget(self.window_1)

    def clicked_action_back(self):
        widget = self.centralWidget.layout().itemAt(0).widget()
        self.centralWidget.layout().removeWidget(widget)     
        widget.hide()
        self.widget_main = self.create_page()
        self.mainLayout.addWidget(self.widget_main)

if __name__ == '__main__':
    myappid = 'mycompany.myproduct.subproduct.version'
    ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

    app = QtWidgets.QApplication(sys.argv)

    app.setWindowIcon(QtGui.QIcon("settings\\bug.ico"))
    MainWindow = MainWindow() 
    MainWindow.show()
    sys.exit(app.exec_())

window_1 (файл)

from PyQt5 import QtCore
from PyQt5 import QtWidgets
import os
import re


class Page_find_numbers(QtWidgets.QWidget):

    def __init__(self, parent = None):
        super().__init__(parent)
        self.parent = parent

        # списки для хранения найденных данных в тексте
        self.email_text = []
        self.telephon_text = []

        # обьекты
        self.button_clear = QtWidgets.QPushButton("Очистить")    
        self.button_find = QtWidgets.QPushButton("Запустить")
        self.button_save = QtWidgets.QPushButton("Сохранить\nв txt-файл")

        self.label_1 = QtWidgets.QLabel("Вставте сюда текст, в котором хотите\nнайти телефонные номера и электронные\nпочты.")
        self.label_2 = QtWidgets.QLabel("Результат:")

        self.textedit_1 = QtWidgets.QTextEdit()

        self.textedit_2 = QtWidgets.QTextEdit()
        self.textedit_2.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)

        self.gridbox = QtWidgets.QGridLayout()

        # добавление в box
        self.gridbox.addWidget(self.label_1, 0, 0)
        self.gridbox.addWidget(self.label_2, 2, 0)
        self.gridbox.addWidget(self.button_find, 0, 1)
        self.gridbox.addWidget(self.button_clear, 1, 1)
        self.gridbox.addWidget(self.button_save, 4, 1, alignment = QtCore.Qt.AlignTop)
        self.gridbox.addWidget(self.textedit_1, 1, 0)
        self.gridbox.addWidget(self.textedit_2, 4, 0)

        self.gridbox.setVerticalSpacing(18)

        self.setLayout(self.gridbox)

        # датчики событий
        self.button_clear.clicked.connect(self.textedit_1.clear)
        self.button_clear.clicked.connect(self.textedit_2.clear)

        self.button_find.clicked.connect(self.toSeekNomerEmail)
        self.button_save.clicked.connect(self.toSaveNomerEmail)


    def toSeekNomerEmail(self):

        PlainText = self.textedit_1.toPlainText()

        self.action_options_1 = self.parent.action_search_options_1
        self.action_options_2 = self.parent.action_search_options_2
        self.action_options_3 = self.parent.action_search_options_3

        self.status_1 = self.parent.status_1
        self.options_settings_status = self.parent.options_settings_status

        if len(PlainText) > 0: 

            # шаблон для телефонных номеров
            inserted_text_1 = re.compile(r'\W?\D?\d\s?\d\d\d\D?\s?\d\d\d\s?-?\d\d\s?-?\d\d')
            # шаблок для акк и электронных почт
            email_akk = re.compile(r'[a-zA-Z0-9]{1,50}@[a-z]{2,6}\.[a-z]{2,4}')

            # собирает данные
            self.email_text = email_akk.findall(PlainText)
            self.telephon_text = inserted_text_1.findall(PlainText)

            # если в массиве оказались телефонные номера или акк и почты
            if len(self.email_text) > 0 or len(self.telephon_text) > 0:

                # проверка на установленный режим действия
                # искать всё (действие)
                if self.action_options_1.isChecked() == True:

                    text_1 = ''  # для телефонных номеов
                    text_2 = ''  # для почт и аккаунтов

                    # преобразовать в нормальные вид
                    for nomer in self.telephon_text:
                        text_1 += nomer + "\n"

                    for email in self.email_text:
                        text_2 += email + "\n"

                    # проверка на то что будет выводится в тексте
                    # только телефонные номера
                    if len(text_1) > 0 and len(text_2) == 0:
                        self.textedit_2.setText("Телефонные номера:\n" + text_1)

                    # только почты
                    elif len(text_1) == 0 and len(text_2) > 0:
                        self.textedit_2.setText("Электронные почты:\n" + text_2)

                    # всё вместе
                    elif len(text_1) > 0 and len(text_2) > 0:
                        self.textedit_2.setText("Телефонные номера:\n" + text_1\
                                + "\nЭлектронные почты:\n" + text_2)

                    # панель состояние
                    self.status_1.showMessage("Телефонные номера - " + str(len(self.telephon_text))\
                           + "; Электронные почты - " + str(len(self.email_text)), msecs = 3500)

                # искать телефонные номера
                elif self.action_options_2.isChecked() == True:
                    text_1 = ''

                    for nomer in self.telephon_text:
                        text_1 += nomer + "\n"

                    # если оказались данные
                    if len(text_1) > 0:
                        self.textedit_2.setText("Телефонные номера:\n" + text_1)


                    elif len(text_1) == 0:
                        self.textedit_2.setText("Данных не обнаружено!")

                    # панель состояния
                    self.status_1.showMessage("Найдено: телефонные номера - " + str(len(self.telephon_text)), msecs = 3500)


                # искать аккаунты и почты
                elif self.action_options_3.isChecked() == True:
                    text_2 = ''

                    for email in self.email_text:
                        text_2 += email + "\n"

                    # если оказались данные
                    if len(text_2) > 0:
                        self.textedit_2.setText("Электронные почты:\n" + text_2)

                    elif len(text_2) == 0:
                        self.textedit_2.setText("Данных не обнаружено!")

                    # панель состояния
                    self.status_1.showMessage("Найдено: электронные почты и акк - " + str(len(self.email_text)), msecs = 3500)


            # если в списке нет номеров
            elif len(self.email_text) == 0 and len(self.telephon_text) == 0:
                self.textedit_2.setText("Данных не обнаружено!")

        # если в первом тексте не обнаруженно данных для поиска
        elif len(PlainText) == 0:
            self.textedit_2.setText("Введите данные!")


    def toSaveNomerEmail(self):

        if len(self.email_text) > 0 or len(self.telephon_text) > 0:

            # проверка на путь
            if os.path.exists("C:/nomera_email") == False:
                # созданте папки
                os.mkdir('C:/nomera_email')      

                # проверка на установленность действия
                # поиск всего
                if self.action_options_1.isChecked() == True:
                    telephon_nomer_email = open('C:/nomera_email/Telephonnue_nomera_email.txt', 'w')

                    # записывается номера и акк, и почты
                    if len(self.telephon_text) > 0:  # проверка на номера
                        telephon_nomer_email.write("Телефонные номера:\n")

                        for tel_nomer in self.telephon_text:
                            telephon_nomer_email.write(tel_nomer + "\n")
                        telephon_nomer_email.write("")

                    if len(self.email_text) > 0:  # проверка на акк или почта
                        telephon_nomer_email.write("\nАккаунты, электронные почты:\n")

                        for email in self.email_text:
                            telephon_nomer_email.write(email + '\n')
                        telephon_nomer_email.write("")

                    telephon_nomer_email.close()

                # если устновлено поиск телефонных номеров
                elif self.action_options_2.isChecked() == True:

                    # запись телефонный номеров
                    if len(self.telephon_text) > 0:
                        telephon_nomer = open('C:/nomera_email/Telephonnue_nomera.txt', 'w')
                        telephon_nomer.write("Телефонные номера:\n")

                        for tel_nomer in self.telephon_text:
                            telephon_nomer.write(tel_nomer + "\n")
                        telephon_nomer.write("")

                        telephon_nomer.close()

                # поиск почт и аккаунтов
                elif self.action_options_3.isChecked() == True:

                    # запись аккаунтов
                    if len(self.email_text) > 0:             
                        email_file = open('C:/nomera_email/Email.txt', 'w')
                        email_file.write("\nАккаунты, электронные почты:\n")

                        for email in self.email_text:
                            email_file.write(email + '\n')
                        email_file.write("")

                        email_file.close()

            # если путь существует
            elif os.path.exists("C:/nomera_email") == True:                

                # проверка на устновленность режима поиска
                if self.action_options_1.isChecked() == True:

                    telephon_nomer_email = open('C:/nomera_email/Telephonnue_nomera_email.txt', 'a')  

                    # запись номеров
                    if len(self.telephon_text) > 0:
                        telephon_nomer_email.write("\nТелефонные номера:\n")

                        for tel_nomer_1 in self.telephon_text:
                            telephon_nomer_email.write(tel_nomer_1 + "\n")
                        telephon_nomer_email.write("")

                    # запись аккаунтов
                    if len(self.email_text) > 0:
                        telephon_nomer_email.write("\nАккаунты и електронные почты:\n")

                        for email_1 in self.email_text:
                            telephon_nomer_email.write(email_1 + '\n')
                        telephon_nomer_email.write("")

                    telephon_nomer_email.close()

                elif self.action_options_2.isChecked() == True: 

                     if len(self.telephon_text) > 0:   
                        telephon_nomer = open('C:/nomera_email/Telephonnue_nomera.txt', 'a')
                        telephon_nomer.write("\nТелефонные номера:\n")

                        for tel_nomer_1 in self.telephon_text:
                            telephon_nomer.write(tel_nomer_1 + "\n")
                        telephon_nomer.write("")

                        telephon_nomer.close()

                elif self.action_options_3.isChecked() == True:

                    if len(self.email_text) > 0:
                        email_file = open('C:/nomera_email/Email.txt', 'a')
                        email_file.write("\nАккаунты и электронные почты:\n")

                        for email_1 in self.email_text:
                            email_file.write(email_1 + '\n')
                        email_file.write("")

                        email_file.close()

            # вывод информации после сохранения
            self.textedit_2.setText("Вы сохранили в txt-файл,\nна путь - C:\\nomera_email")

        # если данных для сохранения не обнаружено
        elif len(self.email_text) == 0 and len(self.telephon_text) == 0:
            self.textedit_2.setText("Данных для сохранения в\ntxt-файл не обнаружено!")

# номера и акк для проверки поиска
# щоашгомошвамшто (+5 555) 555 55 55 апрарdfb 89209103333 
# ваииапп 342423 пиа 8 888 888 88-88 dfbdfg [email protected]

Ответы (1 шт):

Автор решения: S. Nick
  1. Я внес необходимые изменения в ваши программу и прокомментировал их.

  2. Формирование файла ru-eng.ts. Введите:

    pylupdate5 main.py -ts ru-eng.ts

Эта команда означает вывод всего текста, который нужно перевести в программном коде main.py, в файл ru-eng.ts

Файл TS по сути является файлом XML. После запуска в каталоге проекта появится файл ru-eng.ts

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="2.0">
<context encoding="UTF-8">
    <name>MainWindow</name>
    <message encoding="UTF-8">
        <location filename="questions-1131567_222.py" line="218"/>
        <source>Перейти к поиску телефонных
номеров и электронных почт</source>
        <translation type="unfinished"></translation>
    </message>
    <message encoding="UTF-8">
        <location filename="questions-1131567_222.py" line="219"/>
        <source>Очистить</source>
        <translation type="unfinished"></translation>
    </message>
    <message encoding="UTF-8">
        <location filename="questions-1131567_222.py" line="220"/>
        <source>Запустить</source>
        <translation type="unfinished"></translation>
    </message>
</context>
</TS>
  1. Использование Qt Linguist - linguist.exe Перевод выполняется в программном обеспечении Qt Linguist, которое находится в том же каталоге, что и Qt Assistant и Qt Designer. Введите:

    linguist.exe ru-eng.ts

Последовательность действий такая:

введите сюда описание изображения

  • для каждой строки перевода выполняем 1, 2, 3

  • ...

  • наконец, мы нажимаем Release (10) в меню File, чтобы получить сгенерированный файл ru-eng.qm, который мы используем в программе.

т.е. на выходе у нас бинарный файл ru-eng.qm и заполненный ru-eng.ts, который мы не используем в дальнейшем.

ru-eng.ts

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_GB" sourcelanguage="ru_RU">
<context>
    <name>MainWindow</name>
    <message>
        <location filename="questions-1131567_222.py" line="218"/>
        <source>Перейти к поиску телефонных
номеров и электронных почт</source>
        <translation>Go to phone search
numbers and emails</translation>
    </message>
    <message>
        <location filename="questions-1131567_222.py" line="219"/>
        <source>Очистить</source>
        <translation>Clear</translation>
    </message>
    <message>
        <location filename="questions-1131567_222.py" line="220"/>
        <source>Запустить</source>
        <translation>Run</translation>
    </message>
</context>
</TS>

Все запускаем программу.


main.py

from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5 import QtWidgets
from PyQt5.QtCore import QTranslator, QEvent                                        # +++
from PyQt5.QtWidgets import QApplication
import window_1
import sys
import ctypes
import os


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        # создание обьекта для построения меню (в другом классе)
        self.menuBar = QtWidgets.QMenuBar()
        # создание файла для сохранения натроек
        if os.name == "nt":   # проверка на название системы
            self.CONFIG_FILE_NAME = 'settings\\config.ini'
        self.centralWidget = QtWidgets.QWidget() # создаём центральный виджет
        self.setCentralWidget(self.centralWidget)

# ++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
        self.window_1 = window_1.Page_find_numbers(self)                             # +++ !!!
        self.trans = QTranslator(self)                                               # +++ !!!
# ++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        self.mainLayout = QtWidgets.QVBoxLayout(self.centralWidget)
        # settings
        self.setFixedSize(640, 600)
        self.setWindowTitle(" B U G ")
        self.setWindowIcon(QtGui.QIcon("settings\\bug.ico"))
        # делаем сборку
        self.widget_main = self.create_page()
        self.mainLayout.addWidget(self.widget_main)
        self.create_menuBar()
        self.create_toolBar()
        # для строки состоянии
        self.label_1 = QtWidgets.QLabel("v 1.0")
        self.label_1.setStyleSheet("font-size: 18px; color: black;")
        self.status_1.addPermanentWidget(self.label_1)
        self.status_1.showMessage("Добро пожаловать!", msecs = 4000)
        self.setStatusBar(self.status_1)

    def create_page(self):
        self.widget_page = QtWidgets.QWidget()
        # создание обьектов
        self.button_1 = QtWidgets.QPushButton("Перейти к поиску телефонных\nномеров и электронных почт")
        self.formbox = QtWidgets.QGridLayout()
        # добавление в box и в окно
        self.formbox.addWidget(self.button_1)
        self.formbox.setSpacing(20)
        self.widget_page.setLayout(self.formbox)
        # датчики и события
        self.button_1.clicked.connect(self.clicked_button_1)
        # сделать главным комонентом в общем
        return self.widget_page  # возращает

    def create_menuBar(self):
        # создание панели-меню и строки состоянии
        self.menu = QtWidgets.QMenuBar()
        self.status_1 = QtWidgets.QStatusBar()  
        # создание категорий меню и функционал в ней
        self.menu_options = QtWidgets.QMenu("Опции")
        self.menu_view = QtWidgets.QMenu('Вид')
        self.menu_help = QtWidgets.QMenu("Справка")
        self.sub_menu_in_options_settings_1 = QtWidgets.QMenu("Настройки")
        # настройки строки состояния
        self.options_settings_status = QtWidgets.QAction("Включить панель состояния")
        self.options_settings_status.setCheckable(True)
        self.options_settings_status.setChecked(True)
        self.sub_menu_in_options_settings_1.addAction(self.options_settings_status)
        self.menu_options.addMenu(self.sub_menu_in_options_settings_1)
        # настройки поиска
        self.sub_menu_options_search = QtWidgets.QMenu("Настройки поиска")
        self.action_search_options_1 = QtWidgets.QAction("Искать всё")
        self.action_search_options_1.setCheckable(True)
        self.action_search_options_1.setChecked(True)
        self.action_search_options_2 = QtWidgets.QAction("Телефонные номера")
        self.action_search_options_2.setCheckable(True)
        self.action_search_options_3 = QtWidgets.QAction("Электронные почты и акк") 
        self.action_search_options_3.setCheckable(True)
        self.group_action_1 = QtWidgets.QActionGroup(self.sub_menu_options_search)
        self.group_action_1.addAction(self.action_search_options_1) # добавление в groupbox
        self.group_action_1.addAction(self.action_search_options_2)
        self.group_action_1.addAction(self.action_search_options_3)
        self.sub_menu_options_search.addAction(self.action_search_options_1) # добавление в вложенное
        self.sub_menu_options_search.addAction(self.action_search_options_2) # меню
        self.sub_menu_options_search.addAction(self.action_search_options_3)
        self.menu_options.addMenu(self.sub_menu_options_search) # добавление в меню опции
        # настройка языка
        self.delimiter_2 = QtWidgets.QAction()
        self.delimiter_2.setSeparator(True)
        self.menu_options.addAction(self.delimiter_2)

        self.language_menu = QtWidgets.QMenu("Язык")
        self.language_russian = QtWidgets.QAction("Русcкий (ru)")
        self.language_russian.setCheckable(True)
        self.language_russian.setChecked(True)
        self.language_english = QtWidgets.QAction("English (en)")
        self.language_english.setCheckable(True)

        self.group_action_6 = QtWidgets.QActionGroup(self.language_menu)
        self.group_action_6.addAction(self.language_english)
        self.group_action_6.addAction(self.language_russian)
# +++   
        self.group_action_6.triggered.connect(self.clicked_language)                # +++ !!!

        self.language_menu.addAction(self.language_english)
        self.language_menu.addAction(self.language_russian)

        self.menu_options.addMenu(self.language_menu)

        # настройка тем
        self.sub_menu_view_themes = QtWidgets.QMenu("Цветовая схема")

        self.view_theme_1 = QtWidgets.QAction("Тёмно-синяя тема")
        self.view_theme_1.setCheckable(True)
        self.view_theme_2 = QtWidgets.QAction("Светло-серая тема")
        self.view_theme_2.setCheckable(True)
        self.view_theme_2.setChecked(True)
        self.view_theme_3 = QtWidgets.QAction("Тёмно-коричневая тема")
        self.view_theme_3.setCheckable(True)

        self.group_action_5 = QtWidgets.QActionGroup(self.sub_menu_view_themes)

        self.group_action_5.addAction(self.view_theme_1)
        self.group_action_5.addAction(self.view_theme_2)
        self.group_action_5.addAction(self.view_theme_3)

        self.sub_menu_view_themes.addAction(self.view_theme_1)
        self.sub_menu_view_themes.addAction(self.view_theme_2)
        self.sub_menu_view_themes.addAction(self.view_theme_3)

        self.menu_view.addMenu(self.sub_menu_view_themes)

        # добавляем отдельное меню в главное меню
        self.menu.addMenu(self.menu_options)
        self.menu.addMenu(self.menu_view)
        self.menu.addMenu(self.menu_help)

        # датчики
        self.options_settings_status.triggered.connect(self.toggleMenu)

        # добавляем в окно
        self.setMenuBar(self.menu)


# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    def clicked_language(self, lang):
        if lang.text() == "English (en)":
            # здесь мы загружаем наши переводы из файла `ru-eng.qm`
            self.trans.load('ru-eng')                             # без расширения `qm` - !!!
            _app = QApplication.instance()
            _app.installTranslator(self.trans)
        else:
            _app = QApplication.instance()
            _app.removeTranslator(self.trans)  

    # здесь мы должны прописать все что будем иереводить!
    # Внимание! т.к. мы подгружаем модуль window_1 с классом Page_find_numbers
    # и в нем также есть текст, который надо переводить, важно правильно указать объекты.
    # Например: self.window_1.button_clear...
    def retranslateUi(self):                                               # 1
        self.button_1.setText(QApplication.translate('MainWindow', 'Перейти к поиску телефонных\nномеров и электронных почт'))
        # ...
        # vvvvvvvvvvvvvvvvvvvvvvvv
        self.window_1.button_clear.setText(QApplication.translate('MainWindow', 'Очистить'))
        self.window_1.button_find.setText(QApplication.translate('MainWindow', 'Запустить'))
        # ...
        # и т.д. все что надо переводить
        # Если что-то не знаете как правильно записать, Qt Designer вам в помощь.
        # Создайте там нужный виджет и посмотрите метод `def retranslateUi(self, ...):`


    # нам нужно переопределить функцию события changeEvent().
    # Всякий раз, когда язык интерфейса программы изменяется, вызывается функция события,
    # и в нем вызывается метод retranslateUi() для завершения обновления интерфейса.
    def changeEvent(self, event):                                          # 2
        if event.type() == QEvent.LanguageChange:
            self.retranslateUi()
# ++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


    def create_toolBar(self):
        self.toolBar = QtWidgets.QToolBar()
        self.action_back = QtWidgets.QAction("Вернуться назад")
        self.toolBar.addAction(self.action_back)
        self.addToolBar(self.toolBar)

    # функции для датчиков
    def toggleMenu(self, state):
        if state:
            self.statusBar().show()
        else:
            self.statusBar().hide()

    def clicked_button_1(self):
        widget = self.centralWidget.layout().itemAt(0).widget()
        self.centralWidget.layout().removeWidget(widget)     
        widget.hide()

#        self.window_1 = window_1.Page_find_numbers(self)                           # --- 
        self.window_1.show()                                                        # +++

        self.action_back.triggered.connect(self.clicked_action_back)
        self.mainLayout.addWidget(self.window_1)

    def clicked_action_back(self):
        widget = self.centralWidget.layout().itemAt(0).widget()
        self.centralWidget.layout().removeWidget(widget)     
        widget.hide()
        self.widget_main = self.create_page()
        self.mainLayout.addWidget(self.widget_main)

# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 
        # это важно, т.к. мы переключаемся между окнами !       
        if self.language_english.isChecked():
            self.language_english.trigger()                                        
        else:
            self.language_russian.trigger()
# ++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


if __name__ == '__main__':
    myappid = 'mycompany.myproduct.subproduct.version'
    ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

    app = QtWidgets.QApplication(sys.argv)

    app.setWindowIcon(QtGui.QIcon("settings\\bug.ico"))
    MainWindow = MainWindow() 
    MainWindow.show()
    sys.exit(app.exec_())

введите сюда описание изображения

введите сюда описание изображения

→ Ссылка