diff --git a/buzz/buzz.py b/buzz/buzz.py index 6a648ae88..7a0131a31 100644 --- a/buzz/buzz.py +++ b/buzz/buzz.py @@ -48,8 +48,6 @@ def main(): format=log_format, ) - logging.debug("app_dir: %s", APP_BASE_DIR) - if getattr(sys, "frozen", False) is False: stdout_handler = logging.StreamHandler(sys.stdout) stdout_handler.setLevel(logging.DEBUG) @@ -59,6 +57,9 @@ def main(): from buzz.cli import parse_command_line from buzz.widgets.application import Application + logging.debug("app_dir: %s", APP_BASE_DIR) + logging.debug("log_dir: %s", log_dir) + app = Application(sys.argv) parse_command_line(app) sys.exit(app.exec()) diff --git a/buzz/locale.py b/buzz/locale.py index fe6dc1842..299e03067 100644 --- a/buzz/locale.py +++ b/buzz/locale.py @@ -1,3 +1,4 @@ +import logging import gettext from PyQt6.QtCore import QLocale @@ -8,6 +9,8 @@ locale_dir = get_path("locale") gettext.bindtextdomain("buzz", locale_dir) +logging.debug(f"UI locales {QLocale().uiLanguages()}") + translate = gettext.translation( APP_NAME.lower(), locale_dir, languages=QLocale().uiLanguages(), fallback=True ) diff --git a/buzz/locale/lv_LV/LC_MESSAGES/buzz.po b/buzz/locale/lv_LV/LC_MESSAGES/buzz.po index d6fcc78eb..1ad905263 100644 --- a/buzz/locale/lv_LV/LC_MESSAGES/buzz.po +++ b/buzz/locale/lv_LV/LC_MESSAGES/buzz.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-05-18 17:24+0300\n" +"POT-Creation-Date: 2024-05-25 02:23+0300\n" "PO-Revision-Date: 2024-05-18 16:28+0300\n" "Last-Translator: \n" "Language-Team: \n" @@ -128,19 +128,19 @@ msgstr "Jūsu ievadītā URL adrese nav derīga." msgid "Live Recording" msgstr "Dzīvā ierakstīšana" -#: buzz/widgets/recording_transcriber_widget.py:104 +#: buzz/widgets/recording_transcriber_widget.py:109 msgid "Click Record to begin..." msgstr "Klikšķiniet Ierakstīt, lai sāktu..." -#: buzz/widgets/recording_transcriber_widget.py:116 +#: buzz/widgets/recording_transcriber_widget.py:121 msgid "Microphone:" msgstr "Mikrofons:" -#: buzz/widgets/recording_transcriber_widget.py:273 +#: buzz/widgets/recording_transcriber_widget.py:278 msgid "An error occurred while starting a new recording:" msgstr "Sākot jaunu ierakstu notikusi kļūda:" -#: buzz/widgets/recording_transcriber_widget.py:277 +#: buzz/widgets/recording_transcriber_widget.py:282 msgid "" "Please check your audio devices or check the application logs for more " "information." @@ -361,9 +361,13 @@ msgstr "Vai tiešām dzēst izvēlēto modeli?" msgid "Reset to Defaults" msgstr "Atjaunot noklusētos" +#: buzz/widgets/preferences_dialog/preferences_dialog.py:43 +msgid "Preferences" +msgstr "Iestatījumi" + #: buzz/widgets/preferences_dialog/preferences_dialog.py:50 msgid "General" -msgstr "Vizpārīgi" +msgstr "Vispārīgi" #: buzz/widgets/preferences_dialog/preferences_dialog.py:53 msgid "Models" diff --git a/buzz/widgets/preferences_dialog/preferences_dialog.py b/buzz/widgets/preferences_dialog/preferences_dialog.py index 1c27d21ce..71199ebd0 100644 --- a/buzz/widgets/preferences_dialog/preferences_dialog.py +++ b/buzz/widgets/preferences_dialog/preferences_dialog.py @@ -40,7 +40,7 @@ def __init__( self.updated_preferences = copy.deepcopy(preferences) - self.setWindowTitle("Preferences") + self.setWindowTitle(_("Preferences")) layout = QVBoxLayout(self) tab_widget = QTabWidget(self) diff --git a/tests/app_main.py b/tests/app_main.py new file mode 100644 index 000000000..27a8f90f7 --- /dev/null +++ b/tests/app_main.py @@ -0,0 +1,21 @@ +import os +from unittest.mock import patch +from buzz.buzz import main + +class TestMain: + def test_main(self): + with patch('buzz.widgets.application.Application') as mock_application, \ + patch('buzz.cli.parse_command_line') as mock_parse_command_line, \ + patch('buzz.buzz.sys') as mock_sys, \ + patch('buzz.buzz.user_log_dir', return_value='/tmp/buzz') as mock_log_dir: + + mock_application.return_value.exec.return_value = 0 + + mock_sys.argv = ['buzz.py'] + + main() + + mock_application.assert_called_once_with(mock_sys.argv) + mock_parse_command_line.assert_called_once_with(mock_application.return_value) + mock_application.return_value.exec.assert_called_once() + assert os.path.isdir(mock_log_dir.return_value), "Log dir was not created" diff --git a/tests/gui_test.py b/tests/gui_test.py index 9e36bbc1e..f3f110004 100644 --- a/tests/gui_test.py +++ b/tests/gui_test.py @@ -12,6 +12,7 @@ ) from pytestqt.qtbot import QtBot +from buzz.locale import _ from buzz.__version__ import VERSION from buzz.widgets.audio_devices_combo_box import AudioDevicesComboBox from buzz.widgets.transcriber.advanced_settings_dialog import AdvancedSettingsDialog @@ -49,7 +50,7 @@ class TestLanguagesComboBox: def test_should_show_sorted_whisper_languages(self, qtbot): languages_combox_box = LanguagesComboBox("en") qtbot.add_widget(languages_combox_box) - assert languages_combox_box.itemText(0) == "Detect Language" + assert languages_combox_box.itemText(0) == _("Detect Language") assert languages_combox_box.itemText(10) == "Belarusian" def test_should_select_en_as_default_language(self, qtbot): @@ -60,7 +61,7 @@ def test_should_select_en_as_default_language(self, qtbot): def test_should_select_detect_language_as_default(self, qtbot): languages_combo_box = LanguagesComboBox(None) qtbot.add_widget(languages_combo_box) - assert languages_combo_box.currentText() == "Detect Language" + assert languages_combo_box.currentText() == _("Detect Language") class TestAudioDevicesComboBox: @@ -102,7 +103,7 @@ def test_should_check_for_updates(self, qtbot: QtBot): dialog.check_updates_button.click() mock_message_box_information.assert_called_with( - dialog, "", "You're up to date!" + dialog, "", _("You're up to date!") ) @@ -118,7 +119,7 @@ def test_should_update_advanced_settings(self, qtbot: QtBot): transcription_options_mock = Mock() dialog.transcription_options_changed.connect(transcription_options_mock) - assert dialog.windowTitle() == "Advanced Settings" + assert dialog.windowTitle() == _("Advanced Settings") assert dialog.temperature_line_edit.text() == "0.0, 0.8" assert dialog.initial_prompt_text_edit.toPlainText() == "prompt" diff --git a/tests/widgets/import_url_dialog_test.py b/tests/widgets/import_url_dialog_test.py index 2f1870fb0..804c457e1 100644 --- a/tests/widgets/import_url_dialog_test.py +++ b/tests/widgets/import_url_dialog_test.py @@ -1,5 +1,6 @@ from unittest.mock import patch +from buzz.locale import _ from buzz.widgets.import_url_dialog import ImportURLDialog @@ -11,7 +12,7 @@ def test_should_show_error_with_invalid_url(self, qtbot): with patch("PyQt6.QtWidgets.QMessageBox.critical") as mock_critical: dialog.button_box.button(dialog.button_box.StandardButton.Ok).click() mock_critical.assert_called_with( - dialog, "Invalid URL", "The URL you entered is invalid." + dialog, _("Invalid URL"), _("The URL you entered is invalid.") ) def test_should_return_url_with_valid_url(self, qtbot): diff --git a/tests/widgets/main_window_test.py b/tests/widgets/main_window_test.py index 1f0bb769d..014fa807c 100644 --- a/tests/widgets/main_window_test.py +++ b/tests/widgets/main_window_test.py @@ -14,6 +14,7 @@ ) from pytestqt.qtbot import QtBot +from buzz.locale import _ from buzz.db.entity.transcription import Transcription from buzz.db.service.transcription_service import TranscriptionService from buzz.widgets.main_window import MainWindow @@ -25,7 +26,7 @@ mock_transcriptions: List[Transcription] = [ Transcription(status="completed"), Transcription(status="canceled"), - Transcription(status="failed", error_message="Error"), + Transcription(status="failed", error_message=_("Error")), ] @@ -48,7 +49,7 @@ def test_should_run_file_transcription_task( self._import_file_and_start_transcription(window) - open_transcript_action = self._get_toolbar_action(window, "Open Transcript") + open_transcript_action = self._get_toolbar_action(window, _("Open Transcript")) assert open_transcript_action.isEnabled() is False table_widget = self._get_tasks_table(window) @@ -251,7 +252,7 @@ def _import_file_and_start_transcription( "", ) new_transcription_action = TestMainWindow._get_toolbar_action( - window, "New Transcription" + window, _("New Transcription") ) new_transcription_action.trigger() diff --git a/tests/widgets/model_download_progress_dialog.py b/tests/widgets/model_download_progress_dialog.py index 3a47331ac..e9738ddc9 100644 --- a/tests/widgets/model_download_progress_dialog.py +++ b/tests/widgets/model_download_progress_dialog.py @@ -1,5 +1,6 @@ from PyQt6.QtCore import Qt +from buzz.locale import _ from buzz.model_loader import ModelType from buzz.widgets.model_download_progress_dialog import ModelDownloadProgressDialog @@ -8,7 +9,7 @@ class TestModelDownloadProgressDialog: def test_should_show_dialog(self, qtbot): dialog = ModelDownloadProgressDialog(model_type=ModelType.WHISPER, parent=None) qtbot.add_widget(dialog) - assert dialog.labelText() == "Downloading model (0%)" + assert dialog.labelText() == f"{_('Downloading model')} (0%)" def test_should_update_label_on_progress(self, qtbot): dialog = ModelDownloadProgressDialog(model_type=ModelType.WHISPER, parent=None) @@ -16,10 +17,10 @@ def test_should_update_label_on_progress(self, qtbot): dialog.set_value(0.0) dialog.set_value(0.01) - assert dialog.labelText().startswith("Downloading model (1%") + assert dialog.labelText().startswith(f"{_('Downloading model')} (1%") dialog.set_value(0.1) - assert dialog.labelText().startswith("Downloading model (10%") + assert dialog.labelText().startswith(f"{_('Downloading model')} (10%") # Other windows should not be processing while models are being downloaded def test_should_be_an_application_modal(self, qtbot): diff --git a/tests/widgets/preferences_dialog/general_preferences_widget_test.py b/tests/widgets/preferences_dialog/general_preferences_widget_test.py index 8654017b2..20093d7b1 100644 --- a/tests/widgets/preferences_dialog/general_preferences_widget_test.py +++ b/tests/widgets/preferences_dialog/general_preferences_widget_test.py @@ -1,5 +1,6 @@ from PyQt6.QtWidgets import QPushButton, QMessageBox, QLineEdit +from buzz.locale import _ from buzz.widgets.preferences_dialog.general_preferences_widget import ( GeneralPreferencesWidget, ) @@ -18,7 +19,7 @@ def test_should_disable_test_button_if_no_api_key(self, qtbot, mocker): test_button = widget.findChild(QPushButton) assert isinstance(test_button, QPushButton) - assert test_button.text() == "Test" + assert test_button.text() == _("Test") assert not test_button.isEnabled() line_edit = widget.findChild(QLineEdit) @@ -46,7 +47,7 @@ def test_should_test_openai_api_key(self, qtbot, mocker): def mock_called(): message_box_warning_mock.assert_called() - assert message_box_warning_mock.call_args[0][1] == "OpenAI API Key Test" + assert message_box_warning_mock.call_args[0][1] == _("OpenAI API Key Test") assert ( message_box_warning_mock.call_args[0][2] == "Incorrect API key provided: wrong-ap*-key. You can find your " diff --git a/tests/widgets/preferences_dialog/models_preferences_widget_test.py b/tests/widgets/preferences_dialog/models_preferences_widget_test.py index 3571f984f..3da12b3cf 100644 --- a/tests/widgets/preferences_dialog/models_preferences_widget_test.py +++ b/tests/widgets/preferences_dialog/models_preferences_widget_test.py @@ -5,6 +5,7 @@ from PyQt6.QtWidgets import QComboBox, QPushButton from pytestqt.qtbot import QtBot +from buzz.locale import _ from buzz.model_loader import ( TranscriptionModel, ModelType, @@ -29,10 +30,10 @@ def test_should_show_model_list(self, qtbot): qtbot.add_widget(widget) first_item = widget.model_list_widget.topLevelItem(0) - assert first_item.text(0) == "Downloaded" + assert first_item.text(0) == _("Downloaded") second_item = widget.model_list_widget.topLevelItem(1) - assert second_item.text(0) == "Available for Download" + assert second_item.text(0) == _("Available for Download") def test_should_change_model_type(self, qtbot): widget = ModelsPreferencesWidget() @@ -43,10 +44,10 @@ def test_should_change_model_type(self, qtbot): combo_box.setCurrentText("Faster Whisper") first_item = widget.model_list_widget.topLevelItem(0) - assert first_item.text(0) == "Downloaded" + assert first_item.text(0) == _("Downloaded") second_item = widget.model_list_widget.topLevelItem(1) - assert second_item.text(0) == "Available for Download" + assert second_item.text(0) == _("Available for Download") def test_should_download_model(self, qtbot: QtBot, clear_model_cache): # make progress dialog non-modal to unblock qtbot.wait_until @@ -58,7 +59,7 @@ def test_should_download_model(self, qtbot: QtBot, clear_model_cache): assert widget.model.get_local_model_path() is None available_item = widget.model_list_widget.topLevelItem(1) - assert available_item.text(0) == "Available for Download" + assert available_item.text(0) == _("Available for Download") tiny_item = available_item.child(0) assert tiny_item.text(0) == "Tiny" @@ -67,7 +68,7 @@ def test_should_download_model(self, qtbot: QtBot, clear_model_cache): download_button = widget.findChild(QPushButton, "DownloadButton") assert isinstance(download_button, QPushButton) - assert download_button.text() == "Download" + assert download_button.text() == _("Download") download_button.click() def downloaded_model(): @@ -97,7 +98,7 @@ def test_should_show_downloaded_model(self, qtbot, default_model_path): qtbot.add_widget(widget) available_item = widget.model_list_widget.topLevelItem(0) - assert available_item.text(0) == "Downloaded" + assert available_item.text(0) == _("Downloaded") tiny_item = available_item.child(0) assert tiny_item.text(0) == "Tiny" diff --git a/tests/widgets/preferences_dialog/preferences_dialog_test.py b/tests/widgets/preferences_dialog/preferences_dialog_test.py index ac47bc191..1b698322e 100644 --- a/tests/widgets/preferences_dialog/preferences_dialog_test.py +++ b/tests/widgets/preferences_dialog/preferences_dialog_test.py @@ -1,24 +1,68 @@ +import os + from PyQt6.QtCore import QSettings from PyQt6.QtWidgets import QTabWidget from pytestqt.qtbot import QtBot +from buzz.locale import _ from buzz.widgets.preferences_dialog.models.preferences import Preferences from buzz.widgets.preferences_dialog.preferences_dialog import PreferencesDialog class TestPreferencesDialog: + locale_file_path = os.path.abspath( + os.path.join(os.path.dirname(__file__), "../../../buzz/locale/lv_LV/LC_MESSAGES/buzz.mo") + ) + def test_create(self, qtbot: QtBot, shortcuts): dialog = PreferencesDialog( shortcuts=shortcuts, preferences=Preferences.load(QSettings()) ) qtbot.add_widget(dialog) - assert dialog.windowTitle() == "Preferences" + assert dialog.windowTitle() == _("Preferences") + + tab_widget = dialog.findChild(QTabWidget) + assert isinstance(tab_widget, QTabWidget) + assert tab_widget.count() == 4 + assert tab_widget.tabText(0) == _("General") + assert tab_widget.tabText(1) == _("Models") + assert tab_widget.tabText(2) == _("Shortcuts") + assert tab_widget.tabText(3) == _("Folder Watch") + + def test_create_localized(self, qtbot: QtBot, shortcuts, mocker): + mocker.patch( + "PyQt6.QtCore.QLocale.uiLanguages", + return_value=['lv_LV'], + ) + + # Reload the module after the patch + from importlib import reload + import buzz.locale + import buzz.widgets.preferences_dialog.models.preferences + import buzz.widgets.preferences_dialog.preferences_dialog + + reload(buzz.locale) + reload(buzz.widgets.preferences_dialog.models.preferences) + reload(buzz.widgets.preferences_dialog.preferences_dialog) + + from buzz.locale import _ + from buzz.widgets.preferences_dialog.models.preferences import Preferences + from buzz.widgets.preferences_dialog.preferences_dialog import PreferencesDialog + + dialog = PreferencesDialog( + shortcuts=shortcuts, preferences=Preferences.load(QSettings()) + ) + qtbot.add_widget(dialog) + + assert os.path.isfile(self.locale_file_path), "File .mo file does not exist" + assert _("Preferences") == "Iestatījumi" + assert dialog.windowTitle() == "Iestatījumi" tab_widget = dialog.findChild(QTabWidget) assert isinstance(tab_widget, QTabWidget) assert tab_widget.count() == 4 - assert tab_widget.tabText(0) == "General" - assert tab_widget.tabText(1) == "Models" - assert tab_widget.tabText(2) == "Shortcuts" - assert tab_widget.tabText(3) == "Folder Watch" + assert tab_widget.tabText(0) == "Vispārīgi" + assert tab_widget.tabText(1) == "Modeļi" + assert tab_widget.tabText(2) == "Īsinājumi" + assert tab_widget.tabText(3) == "Mapes vērošana" diff --git a/tests/widgets/recording_transcriber_widget_test.py b/tests/widgets/recording_transcriber_widget_test.py index d87a96af2..8d15139f3 100644 --- a/tests/widgets/recording_transcriber_widget_test.py +++ b/tests/widgets/recording_transcriber_widget_test.py @@ -1,5 +1,6 @@ from pytestqt.qtbot import QtBot +from buzz.locale import _ from buzz.widgets.recording_transcriber_widget import RecordingTranscriberWidget import pytest @@ -8,7 +9,7 @@ class TestRecordingTranscriberWidget: def test_should_set_window_title(self, qtbot: QtBot): widget = RecordingTranscriberWidget() qtbot.add_widget(widget) - assert widget.windowTitle() == "Live Recording" + assert widget.windowTitle() == _("Live Recording") widget.close() @pytest.mark.skip(reason="Seg faults on CI") diff --git a/tests/widgets/shortcuts_editor_widget_test.py b/tests/widgets/shortcuts_editor_widget_test.py index 951a88876..98a0d4b4f 100644 --- a/tests/widgets/shortcuts_editor_widget_test.py +++ b/tests/widgets/shortcuts_editor_widget_test.py @@ -1,6 +1,7 @@ from PyQt6.QtWidgets import QPushButton, QLabel from pytestqt.qtbot import QtBot +from buzz.locale import _ from buzz.widgets.preferences_dialog.shortcuts_editor_preferences_widget import ( ShortcutsEditorPreferencesWidget, ) @@ -29,14 +30,14 @@ def test_should_reset_to_defaults(self, qtbot, shortcuts): sequence_edits = widget.findChildren(SequenceEdit) expected = ( - ("Open Record Window", "Ctrl+R"), - ("Import File", "Ctrl+O"), - ("Import URL", "Ctrl+U"), - ("Open Preferences Window", "Ctrl+,"), - ("View Transcript Text", "Ctrl+E"), - ("View Transcript Timestamps", "Ctrl+T"), - ("Clear History", "Ctrl+S"), - ("Cancel Transcription", "Ctrl+X"), + (_("Open Record Window"), "Ctrl+R"), + (_("Import File"), "Ctrl+O"), + (_("Import URL"), "Ctrl+U"), + (_("Open Preferences Window"), "Ctrl+,"), + (_("View Transcript Text"), "Ctrl+E"), + (_("View Transcript Timestamps"), "Ctrl+T"), + (_("Clear History"), "Ctrl+S"), + (_("Cancel Transcription"), "Ctrl+X"), ) for i, (label, sequence_edit) in enumerate(zip(labels, sequence_edits)):