From 10684b6d82f1843eff3921da40802d335fb3cf5c Mon Sep 17 00:00:00 2001 From: "Felix (xq) Queißner" Date: Wed, 17 Mar 2021 11:54:43 +0100 Subject: Further improves localization (#191). Allows switching and setting the chosen localization properly. --- src/browsertab.cpp | 6 +++ src/browsertab.ui | 34 +++++++++----- src/dialogs/certificateiodialog.cpp | 7 +++ src/dialogs/certificatemanagementdialog.cpp | 6 +++ src/dialogs/certificateselectiondialog.cpp | 7 +++ src/dialogs/newidentitiydialog.cpp | 6 +++ src/dialogs/settingsdialog.cpp | 44 ++++++++++++++++++ src/dialogs/settingsdialog.hpp | 6 +++ src/dialogs/settingsdialog.ui | 70 ++++++++++++++++------------- src/kristall.hpp | 15 +------ src/kristall.pro | 2 + src/localization.cpp | 31 +++++++++++++ src/localization.hpp | 28 ++++++++++++ src/main.cpp | 38 +++++++--------- src/mainwindow.cpp | 11 +++++ src/widgets/mediaplayer.cpp | 8 ++++ src/widgets/ssltrusteditor.cpp | 8 ++++ 17 files changed, 249 insertions(+), 78 deletions(-) create mode 100644 src/localization.cpp create mode 100644 src/localization.hpp (limited to 'src') diff --git a/src/browsertab.cpp b/src/browsertab.cpp index ef6f5e8..fa4ed9a 100644 --- a/src/browsertab.cpp +++ b/src/browsertab.cpp @@ -64,6 +64,12 @@ BrowserTab::BrowserTab(MainWindow *mainWindow) : QWidget(nullptr), { ui->setupUi(this); + connect( // connect with "this" as context, so the connection will die when the window is destroyed + kristall::globals().localization.get(), &Localization::translationChanged, + this, [this]() { this->ui->retranslateUi(this); }, + Qt::DirectConnection + ); + this->setUiDensity(kristall::globals().options.ui_density); addProtocolHandler(); diff --git a/src/browsertab.ui b/src/browsertab.ui index 81c1f05..8e19c0c 100644 --- a/src/browsertab.ui +++ b/src/browsertab.ui @@ -43,7 +43,8 @@ Back - + + .. @@ -59,7 +60,8 @@ Forward - + + .. @@ -75,7 +77,8 @@ Stop - + + .. @@ -91,7 +94,8 @@ Reload - + + .. @@ -107,7 +111,8 @@ Home - + + .. @@ -123,7 +128,8 @@ / - + + .. @@ -139,7 +145,8 @@ P - + + .. @@ -211,11 +218,11 @@ true - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Start surfin!</p></body></html> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> false @@ -267,7 +274,8 @@ p, li { white-space: pre-wrap; } Previous - + + .. @@ -280,7 +288,8 @@ p, li { white-space: pre-wrap; } Next - + + .. @@ -293,7 +302,8 @@ p, li { white-space: pre-wrap; } Hide - + + .. diff --git a/src/dialogs/certificateiodialog.cpp b/src/dialogs/certificateiodialog.cpp index 75b9775..1f2b975 100644 --- a/src/dialogs/certificateiodialog.cpp +++ b/src/dialogs/certificateiodialog.cpp @@ -1,5 +1,6 @@ #include "certificateiodialog.hpp" #include "ui_certificateiodialog.h" +#include "kristall.hpp" #include #include @@ -11,6 +12,12 @@ CertificateIoDialog::CertificateIoDialog(QWidget *parent) : { ui->setupUi(this); + connect( // connect with "this" as context, so the connection will die when the window is destroyed + kristall::globals().localization.get(), &Localization::translationChanged, + this, [this]() { this->ui->retranslateUi(this); }, + Qt::DirectConnection + ); + this->ui->key_type->clear(); this->ui->key_type->addItem("RSA", QVariant::fromValue(QSsl::Rsa)); this->ui->key_type->addItem("ECDSA", QVariant::fromValue(QSsl::Ec)); diff --git a/src/dialogs/certificatemanagementdialog.cpp b/src/dialogs/certificatemanagementdialog.cpp index 9b43ba7..e2db96b 100644 --- a/src/dialogs/certificatemanagementdialog.cpp +++ b/src/dialogs/certificatemanagementdialog.cpp @@ -17,6 +17,12 @@ CertificateManagementDialog::CertificateManagementDialog(QWidget *parent) : { ui->setupUi(this); + connect( // connect with "this" as context, so the connection will die when the window is destroyed + kristall::globals().localization.get(), &Localization::translationChanged, + this, [this]() { this->ui->retranslateUi(this); }, + Qt::DirectConnection + ); + this->ui->certificates->setModel(&identity_set); this->ui->certificates->expandAll(); diff --git a/src/dialogs/certificateselectiondialog.cpp b/src/dialogs/certificateselectiondialog.cpp index 4d7d5ff..334fd7c 100644 --- a/src/dialogs/certificateselectiondialog.cpp +++ b/src/dialogs/certificateselectiondialog.cpp @@ -14,6 +14,13 @@ CertificateSelectionDialog::CertificateSelectionDialog(QWidget *parent) : ui(new Ui::CertificateSelectionDialog) { ui->setupUi(this); + + connect( // connect with "this" as context, so the connection will die when the window is destroyed + kristall::globals().localization.get(), &Localization::translationChanged, + this, [this]() { this->ui->retranslateUi(this); }, + Qt::DirectConnection + ); + this->ui->server_request->setVisible(false); this->ui->certificates->setModel(&kristall::globals().identities); diff --git a/src/dialogs/newidentitiydialog.cpp b/src/dialogs/newidentitiydialog.cpp index 567fc7d..dc22e5f 100644 --- a/src/dialogs/newidentitiydialog.cpp +++ b/src/dialogs/newidentitiydialog.cpp @@ -13,6 +13,12 @@ NewIdentitiyDialog::NewIdentitiyDialog(QWidget *parent) : { ui->setupUi(this); + connect( // connect with "this" as context, so the connection will die when the window is destroyed + kristall::globals().localization.get(), &Localization::translationChanged, + this, [this]() { this->ui->retranslateUi(this); }, + Qt::DirectConnection + ); + ui->display_name->setText("Unnamed"); ui->common_name->setText("Unnamed"); ui->expiration_date->setDate(QDate::currentDate().addYears(1)); diff --git a/src/dialogs/settingsdialog.cpp b/src/dialogs/settingsdialog.cpp index c97d74c..19b0fd9 100644 --- a/src/dialogs/settingsdialog.cpp +++ b/src/dialogs/settingsdialog.cpp @@ -21,6 +21,12 @@ SettingsDialog::SettingsDialog(QWidget *parent) : { ui->setupUi(this); + connect( // connect with "this" as context, so the connection will die when the window is destroyed + kristall::globals().localization.get(), &Localization::translationChanged, + this, [this]() { this->ui->retranslateUi(this); }, + Qt::DirectConnection + ); + static_assert(DocumentStyle::Fixed == 0); static_assert(DocumentStyle::AutoDarkTheme == 1); static_assert(DocumentStyle::AutoLightTheme == 2); @@ -103,6 +109,11 @@ SettingsDialog::SettingsDialog(QWidget *parent) : this->ui->style_scroll_layout->minimumSize().width() + this->ui->style_scroll_area->verticalScrollBar()->sizeHint().width()); }); + + this->ui->selected_language->clear(); + this->ui->selected_language->addItem(QIcon(), tr("System language"), QString("")); + this->ui->selected_language->addItem(QIcon(":/icons/languages/en.svg"), QLocale("en").nativeLanguageName(), QString("en")); + this->ui->selected_language->addItem(QIcon(":/icons/languages/ru.svg"), QLocale("ru").nativeLanguageName(), QString("ru")); } SettingsDialog::~SettingsDialog() @@ -387,6 +398,32 @@ void SettingsDialog::setOptions(const GenericSettings &options) } } +std::optional SettingsDialog::locale() const +{ + QString locale_str = this->ui->selected_language->currentData().toString(); + if(locale_str.isEmpty()) + return std::nullopt; + else + return QLocale(locale_str); +} + +void SettingsDialog::setLocale(std::optional locale) +{ + if(locale == std::nullopt) + { + this->ui->selected_language->setCurrentIndex(0); + } + else + { + switch(locale->language()) + { + default: this->ui->selected_language->setCurrentIndex(0); break; + case QLocale::English: this->ui->selected_language->setCurrentIndex(1); break; + case QLocale::Russian: this->ui->selected_language->setCurrentIndex(2); break; + } + } +} + GenericSettings SettingsDialog::options() const { return this->current_options; @@ -988,3 +1025,10 @@ void SettingsDialog::on_session_restore_behaviour_currentIndexChanged(int index) { this->current_options.session_restore_behaviour = GenericSettings::SessionRestoreBehaviour(this->ui->session_restore_behaviour->itemData(index).toInt()); } + +void SettingsDialog::on_selected_language_currentIndexChanged(int index) +{ + auto const language_id = this->ui->selected_language->itemData(index, Qt::UserRole).toString(); + + kristall::globals().localization->translate(QLocale(language_id)); +} diff --git a/src/dialogs/settingsdialog.hpp b/src/dialogs/settingsdialog.hpp index 97b1549..9176cea 100644 --- a/src/dialogs/settingsdialog.hpp +++ b/src/dialogs/settingsdialog.hpp @@ -2,6 +2,7 @@ #define SETTINGSDIALOG_HPP #include +#include #include "renderers/geminirenderer.hpp" #include "protocolsetup.hpp" @@ -39,6 +40,9 @@ public: GenericSettings options() const; void setOptions(GenericSettings const & options); + std::optional locale() const; + void setLocale(std::optional locale); + private slots: void on_std_change_font_clicked(); @@ -178,6 +182,8 @@ private slots: void on_session_restore_behaviour_currentIndexChanged(int index); + void on_selected_language_currentIndexChanged(int index); + private: void reloadStylePreview(); diff --git a/src/dialogs/settingsdialog.ui b/src/dialogs/settingsdialog.ui index cfcd44f..45d9787 100644 --- a/src/dialogs/settingsdialog.ui +++ b/src/dialogs/settingsdialog.ui @@ -32,42 +32,42 @@ Generic - + Start Page: - + about://blank - + Search engine: - + true - + Additional toolbar buttons - + @@ -99,54 +99,54 @@ - + Startup Behaviour - + - + UI Theme - + - + Icon Theme - + - + UI Density - + - + Enabled Protocols - + @@ -191,14 +191,14 @@ - + Unknown Scheme - + @@ -222,38 +222,38 @@ - + Max. Number of Redirections - + 5 - + Redirection Handling - + - + Network Timeout - + ms @@ -266,6 +266,16 @@ + + + + Language + + + + + + @@ -1651,14 +1661,14 @@ - - - - - - + + + + + + diff --git a/src/kristall.hpp b/src/kristall.hpp index eac5bdd..272525b 100644 --- a/src/kristall.hpp +++ b/src/kristall.hpp @@ -5,8 +5,6 @@ #include #include #include -#include -#include #include "identitycollection.hpp" #include "ssltrust.hpp" @@ -14,6 +12,7 @@ #include "protocolsetup.hpp" #include "documentstyle.hpp" #include "cachehandler.hpp" +#include "localization.hpp" enum class Theme : int { @@ -166,13 +165,6 @@ namespace kristall QDir styles; }; - struct Localization - { - QLocale locale; - QTranslator qt; - QTranslator kristall; - }; - struct Globals { ProtocolSetup protocols; @@ -191,7 +183,7 @@ namespace kristall Dirs dirs; - Localization localization; + std::unique_ptr localization; }; //! returns the instance of the globals structure @@ -233,9 +225,6 @@ namespace kristall //! Saves the current session including all windows, tabs and positions. void saveSession(); - //! Changes the currently used locale - void setLocale(QLocale const & locale); - //! Saves the currently used locale void saveLocale(); } diff --git a/src/kristall.pro b/src/kristall.pro index e286d71..8b8ce98 100644 --- a/src/kristall.pro +++ b/src/kristall.pro @@ -105,6 +105,7 @@ SOURCES += \ favouritecollection.cpp \ identitycollection.cpp \ ioutil.cpp \ + localization.cpp \ main.cpp \ mainwindow.cpp \ renderers/htmlrenderer.cpp \ @@ -155,6 +156,7 @@ HEADERS += \ identitycollection.hpp \ ioutil.hpp \ kristall.hpp \ + localization.hpp \ mainwindow.hpp \ renderers/htmlrenderer.hpp \ renderers/markdownrenderer.hpp \ diff --git a/src/localization.cpp b/src/localization.cpp new file mode 100644 index 0000000..07b69f5 --- /dev/null +++ b/src/localization.cpp @@ -0,0 +1,31 @@ +#include "kristall.hpp" + +#include +#include + +#include "localization.hpp" + +Localization::Localization(QObject *parent) : QObject(parent) +{ + +} + +void Localization::setLocale(const std::optional &locale) +{ + this->locale = locale; + + if(this->locale != std::nullopt) + this->translate(*this->locale); + else + this->translate(QLocale()); +} + +void Localization::translate(const QLocale &locale) +{ + this->qt.load(locale, "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + this->kristall.load(locale, "kristall", "_", ":/i18n"); + + emit this->translationChanged(); + + qDebug() << "new locale is" << locale.bcp47Name() << locale.nativeLanguageName(); +} diff --git a/src/localization.hpp b/src/localization.hpp new file mode 100644 index 0000000..8367ba3 --- /dev/null +++ b/src/localization.hpp @@ -0,0 +1,28 @@ +#ifndef LOCALIZATION_HPP +#define LOCALIZATION_HPP + +#include +#include +#include +#include + +class Localization : public QObject +{ + Q_OBJECT +public: + explicit Localization(QObject *parent = nullptr); + + void setLocale(std::optional const & locale); + + void translate(QLocale const & locale); + +signals: + void translationChanged(); + +public: + std::optional locale; + QTranslator qt; + QTranslator kristall; +}; + +#endif // LOCALIZATION_HPP diff --git a/src/main.cpp b/src/main.cpp index ad51822..a86f2bd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -375,22 +375,15 @@ MainWindow * kristall::openNewWindow(QVector const & urls) return window; } - -//! Changes the currently used locale -void kristall::setLocale(QLocale const & locale) -{ - auto & i18n = kristall::globals().localization; - i18n.locale = locale; - i18n.qt.load(i18n.locale, "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath)); - i18n.kristall.load(i18n.locale, "kristall", "_", ":/i18n"); -} - //! Saves the currently used locale void kristall::saveLocale() { if(app_settings_ptr == nullptr) return; - app_settings_ptr->setValue("language", kristall::globals().localization.locale.bcp47Name()); + if(auto const locale = kristall::globals().localization->locale; locale != std::nullopt) + app_settings_ptr->setValue("language", locale->bcp47Name()); + else + app_settings_ptr->setValue("language", QString("")); app_settings_ptr->sync(); } @@ -450,20 +443,19 @@ int main(int argc, char *argv[]) // Initialize localization { + auto & i18n = kristall::globals().localization; - // Load the currently selected locale - auto const lang_id = app_settings.value("language", QString()).toString(); - if(not lang_id.isEmpty()) { - kristall::setLocale( QLocale(lang_id) ); - } - else { - kristall::setLocale ( QLocale() ); - } + i18n = std::make_unique(); - auto & i18n = kristall::globals().localization; - app.installTranslator(&i18n.qt); - app.installTranslator(&i18n.kristall); - qDebug() << "current locale" << i18n.locale.nativeLanguageName(); + auto const locale_id = app_settings.value("language", QString("")).toString(); + + if(not locale_id.isEmpty()) + i18n->setLocale(QLocale(locale_id)); + else + i18n->setLocale(std::nullopt); + + qApp->installTranslator(&i18n->qt); + qApp->installTranslator(&i18n->kristall); } addEmojiSubstitutions(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4c7169b..d2eeaf8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -33,6 +33,12 @@ MainWindow::MainWindow(QApplication * app, QWidget *parent) : ui->setupUi(this); + connect( // connect with "this" as context, so the connection will die when the window is destroyed + kristall::globals().localization.get(), &Localization::translationChanged, + this, [this]() { this->ui->retranslateUi(this); }, + Qt::DirectConnection + ); + this->url_status->setElideMode(Qt::ElideMiddle); this->statusBar()->addWidget(this->url_status); @@ -469,13 +475,17 @@ void MainWindow::on_actionSettings_triggered() dialog.setOptions(kristall::globals().options); dialog.setGeminiSslTrust(kristall::globals().trust.gemini); dialog.setHttpsSslTrust(kristall::globals().trust.https); + dialog.setLocale(kristall::globals().localization->locale); if(dialog.exec() != QDialog::Accepted) { kristall::setTheme(kristall::globals().options.theme); + kristall::globals().localization->setLocale(kristall::globals().localization->locale); this->setUiDensity(kristall::globals().options.ui_density, false); return; } + kristall::globals().localization->setLocale(dialog.locale()); + kristall::globals().trust.gemini = dialog.geminiSslTrust(); kristall::globals().trust.https = dialog.httpsSslTrust(); kristall::globals().options = dialog.options(); @@ -483,6 +493,7 @@ void MainWindow::on_actionSettings_triggered() kristall::globals().protocols = dialog.protocols(); kristall::globals().document_style = dialog.geminiStyle(); + kristall::saveLocale(); kristall::applySettings(); kristall::saveSettings(); diff --git a/src/widgets/mediaplayer.cpp b/src/widgets/mediaplayer.cpp index 6344cff..d2592c7 100644 --- a/src/widgets/mediaplayer.cpp +++ b/src/widgets/mediaplayer.cpp @@ -1,6 +1,8 @@ #include "mediaplayer.hpp" #include "ui_mediaplayer.h" +#include "kristall.hpp" + #include #include #include @@ -14,6 +16,12 @@ MediaPlayer::MediaPlayer(QWidget *parent) : { ui->setupUi(this); + connect( // connect with "this" as context, so the connection will die when the window is destroyed + kristall::globals().localization.get(), &Localization::translationChanged, + this, [this]() { this->ui->retranslateUi(this); }, + Qt::DirectConnection + ); + this->player.setVideoOutput(this->ui->video_out); connect(&this->player, &QMediaPlayer::durationChanged, this->ui->media_progress, &QSlider::setMaximum); diff --git a/src/widgets/ssltrusteditor.cpp b/src/widgets/ssltrusteditor.cpp index e740977..7ae3090 100644 --- a/src/widgets/ssltrusteditor.cpp +++ b/src/widgets/ssltrusteditor.cpp @@ -1,12 +1,20 @@ #include "ssltrusteditor.hpp" #include "ui_ssltrusteditor.h" +#include "kristall.hpp" + SslTrustEditor::SslTrustEditor(QWidget *parent) : QWidget(parent), ui(new Ui::SslTrustEditor) { ui->setupUi(this); + connect( // connect with "this" as context, so the connection will die when the window is destroyed + kristall::globals().localization.get(), &Localization::translationChanged, + this, [this]() { this->ui->retranslateUi(this); }, + Qt::DirectConnection + ); + this->ui->trust_level->clear(); this->ui->trust_level->addItem(tr("Trust on first encounter"), QVariant::fromValue(SslTrust::TrustOnFirstUse)); this->ui->trust_level->addItem(tr("Trust everything"), QVariant::fromValue(SslTrust::TrustEverything)); -- cgit v1.2.3