diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index 48f3677d..a2d3d823 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -295,6 +295,8 @@ void ContentManager::setLanguages() for (auto language : languageData) { auto langCode = QString::fromStdString(language); auto selfName = QString::fromStdString(kiwix::getLanguageSelfName(language)); + // qDebug() << langCode; + // qDebug() << selfName << "!"; languages.push_back({langCode, selfName}); } m_languages = languages; diff --git a/src/kiwixapp.cpp b/src/kiwixapp.cpp index eb7ff09f..277f30ba 100644 --- a/src/kiwixapp.cpp +++ b/src/kiwixapp.cpp @@ -35,21 +35,7 @@ KiwixApp::KiwixApp(int& argc, char *argv[]) m_server(m_library.getKiwixLibrary(), mp_nameMapper), mp_session(nullptr) { - try { - m_translation.setTranslation(QLocale()); - } catch (std::exception& e) { - QMessageBox::critical(nullptr, "Translation error", e.what()); - return; - } - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - QString path = QLibraryInfo::location(QLibraryInfo::TranslationsPath); -#else - QString path = QLibraryInfo::path(QLibraryInfo::TranslationsPath); -#endif - loadAndInstallTranslations(m_qtTranslator, "qt", path); - loadAndInstallTranslations(m_appTranslator, "kiwix-desktop", ":/i18n/"); - + setAppLanguage(); QFontDatabase::addApplicationFont(":/fonts/Selawik/selawkb.ttf"); QFontDatabase::addApplicationFont(":/fonts/Selawik/selawkl.ttf"); QFontDatabase::addApplicationFont(":/fonts/Selawik/selawksb.ttf"); @@ -250,6 +236,28 @@ void KiwixApp::openZimFile(const QString &zimfile) openUrl(QUrl("zim://"+zimId+".zim/")); } +void KiwixApp::setAppLanguage() +{ + const QList languageCodes = getSettingsManager()->getLanguageCodes(); + const QString code = languageCodes.at(getSettingsManager()->getAppLanguageIndex()); + QLocale appLanguage(code); + try { + m_translation.setTranslation(appLanguage); + } catch (std::exception& e) { + QMessageBox::critical(nullptr, "Translation error", e.what()); + return; + } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QString qtTranslatorSuffix = QLibraryInfo::location(QLibraryInfo::TranslationsPath); +#else + QString qtTranslatorSuffix = QLibraryInfo::path(QLibraryInfo::TranslationsPath); +#endif + m_qtTranslator.load(appLanguage, "qt", "_", qtTranslatorSuffix); + installTranslator(&m_qtTranslator); + m_appTranslator.load(appLanguage, "kiwix-desktop", "_", ":/i18n/"); + installTranslator(&m_appTranslator); +} + void KiwixApp::printPage() { if(!getTabWidget()->currentZimView()) diff --git a/src/kiwixapp.h b/src/kiwixapp.h index ee7901ec..8fbd05ee 100644 --- a/src/kiwixapp.h +++ b/src/kiwixapp.h @@ -92,6 +92,7 @@ class KiwixApp : public QtSingleApplication public slots: void newTab(); void openZimFile(const QString& zimfile=""); + void setAppLanguage(); void openUrl(const QString& url, bool newTab=true); void openUrl(const QUrl& url, bool newTab=true); void printPage(); diff --git a/src/settingsmanager.cpp b/src/settingsmanager.cpp index e475bcd0..1fdbd27e 100644 --- a/src/settingsmanager.cpp +++ b/src/settingsmanager.cpp @@ -19,8 +19,7 @@ SettingsView* SettingsManager::getView() { if (m_view == nullptr) { auto view = new SettingsView(); - view->init(m_zoomFactor * 100, m_downloadDir, m_monitorDir, - m_moveToTrash, m_reopenTab); + view->init(m_zoomFactor * 100, m_downloadDir, m_monitorDir, m_appLangIndex, m_moveToTrash, m_reopenTab); connect(view, &QObject::destroyed, this, [=]() { m_view = nullptr; }); m_view = view; } @@ -127,13 +126,20 @@ SettingsManager::FilterList SettingsManager::deducePair(QList variantL return pairList; } -void SettingsManager::setLanguage(FilterList langList) +void SettingsManager::setLanguage(FilterList langList) // This regards the search filter languages { m_langList = flattenPair(langList); setSettings("language", m_langList); emit(languageChanged(m_langList)); } +void SettingsManager::setAppLanguage(int languageIndex) // This regards the application language +{ + m_appLangIndex = languageIndex; + KiwixApp::instance()->setAppLanguage(); + m_settings.setValue("app/languageIndex", languageIndex); +} + void SettingsManager::setCategory(FilterList categoryList) { m_categoryList = flattenPair(categoryList); @@ -148,6 +154,42 @@ void SettingsManager::setContentType(FilterList contentTypeList) emit(contentTypeChanged(m_contentTypeList)); } +QString SettingsManager::getLanguageName(QString fileName) // Get native language name based on filename +{ + QString dirPath = "resources/i18n"; + QFile file(dirPath + "/" + fileName); + file.open(QIODevice::ReadOnly); + QByteArray jsonData = file.readAll(); + file.close(); + + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(jsonData, &error); + if (error.error != QJsonParseError::NoError) { + qDebug() << "Error parsing JSON " << fileName << ":" << error.errorString(); + return QString(); + } + + QJsonObject obj = doc.object(); + if (obj.contains("name")) { return obj.value("name").toString(); } + else { qDebug() << "Cannot find element \"name\" in " << fileName; } + + return QString(); +} + +void SettingsManager::loadAvailableLanguages() { + QString dirPath = "resources/i18n"; + QDir directory(dirPath); + if (!directory.exists()) { + qDebug() << "Directory does not exist:" << dirPath; + return; + } + QStringList jsonFiles = directory.entryList(QDir::Files); + for(QString &fileName : jsonFiles) { + if(getLanguageName(fileName).isEmpty() || fileName == "qqq.json") { continue; } + m_appLangCodes.append(fileName.split(".")[0]); + } +} + void SettingsManager::initSettings() { m_kiwixServerPort = m_settings.value("localKiwixServer/port", 8080).toInt(); @@ -157,8 +199,26 @@ void SettingsManager::initSettings() m_monitorDir = m_settings.value("monitor/dir", QString("")).toString(); m_moveToTrash = m_settings.value("moveToTrash", true).toBool(); m_reopenTab = m_settings.value("reopenTab", false).toBool(); - QString defaultLang = QLocale::languageToString(QLocale().language()) + '|' + QLocale().name().split("_").at(0); - + // This regards the application language + loadAvailableLanguages(); + + int i = 0, defaultLanguage = -1; + for (const QString& code : m_appLangCodes) { + QString name = QLocale::languageToString(QLocale(code).language()); + if(name == "English") + { + defaultLanguage = i; + break; + } + i++; + } + m_appLangIndex = m_settings.value("app/languageIndex", defaultLanguage).toInt(); + // Below regards the search filters + QString defaultLang = QLocale::languageToString(QLocale().language()) + '|' + QLocale().name().split("_").at(0); // TODO maybe needs fix + QList defaultLangList; // Qt5 QList doesn't support supplying a constructor list + defaultLangList.append(defaultLang); + QVariant defaultLangVariant(defaultLangList); + m_langList = m_settings.value("language", defaultLangVariant).toList(); /* * Qt5 & Qt6 have slightly different behaviors with regards to initializing QVariant. * The below approach is specifically chosen to work with both versions. @@ -170,11 +230,6 @@ void SettingsManager::initSettings() * * QList(QVariant(QChar, 'E'), QVariant(QChar, 'n'), QVariant(QChar, 'g'), ... */ - QList defaultLangList; // Qt5 QList doesn't support supplying a constructor list - defaultLangList.append(defaultLang); - QVariant defaultLangVariant(defaultLangList); - m_langList = m_settings.value("language", defaultLangVariant).toList(); - m_categoryList = m_settings.value("category", {}).toList(); m_contentTypeList = m_settings.value("contentType", {}).toList(); } diff --git a/src/settingsmanager.h b/src/settingsmanager.h index 3b60306c..e333050e 100644 --- a/src/settingsmanager.h +++ b/src/settingsmanager.h @@ -30,6 +30,10 @@ class SettingsManager : public QObject QString getMonitorDir() const { return m_monitorDir; } bool getMoveToTrash() const { return m_moveToTrash; } bool getReopenTab() const { return m_reopenTab; } + QList getLanguageCodes() { return m_appLangCodes; } + int getAppLanguageIndex() { return m_appLangIndex; } + QString getLanguageName(QString fileName); + void loadAvailableLanguages(); FilterList getLanguageList() { return deducePair(m_langList); } FilterList getCategoryList() { return deducePair(m_categoryList); } FilterList getContentType() { return deducePair(m_contentTypeList); } @@ -43,6 +47,7 @@ public slots: void setMoveToTrash(bool moveToTrash); void setReopenTab(bool reopenTab); void setLanguage(FilterList langList); + void setAppLanguage(int languageIndex); void setCategory(FilterList categoryList); void setContentType(FilterList contentTypeList); @@ -72,9 +77,11 @@ public slots: QString m_monitorDir; bool m_moveToTrash; bool m_reopenTab; + int m_appLangIndex; QList m_langList; QList m_categoryList; QList m_contentTypeList; + QList m_appLangCodes; }; #endif // SETTINGSMANAGER_H diff --git a/src/settingsview.cpp b/src/settingsview.cpp index bffa528d..27361fd2 100644 --- a/src/settingsview.cpp +++ b/src/settingsview.cpp @@ -35,16 +35,15 @@ SettingsView::SettingsView(QWidget *parent) ui->moveToTrashLabel->setText(gt("move-files-to-trash")); ui->reopenTabLabel->setText(gt("open-previous-tabs-at-startup")); #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - ui->line_5->hide(); + ui->lineMonitor->hide(); ui->moveToTrashLabel->hide(); ui->moveToTrashToggle->hide(); #endif } -void SettingsView::init(int zoomPercent, const QString &downloadDir, - const QString &monitorDir, const bool moveToTrash, - bool reopentab) + +void SettingsView::init(int zoomPercent, const QString &downloadDir, const QString &monitorDir, const int &langIndex, const bool moveToTrash, bool reopentab) { ui->zoomPercentSpinBox->setValue(zoomPercent); ui->downloadDirPath->setText(downloadDir); @@ -52,8 +51,22 @@ void SettingsView::init(int zoomPercent, const QString &downloadDir, ui->monitorClear->hide(); } ui->monitorDirPath->setText(monitorDir); + // Application Language Code + const QList languageCodes = KiwixApp::instance()->getSettingsManager()->getLanguageCodes(); + QStringList languageList; + for (const QString& code : languageCodes) { + QString name = KiwixApp::instance()->getSettingsManager()->getLanguageName(code + ".json"); + QString qName = QLocale::languageToString(QLocale(code).language()); + if("C" == qName) { continue; } + // qInfo() << name; + languageList.append(name); + } + ui->comboBoxLanguage->addItems(languageList); + ui->comboBoxLanguage->setCurrentIndex(langIndex); ui->moveToTrashToggle->setChecked(moveToTrash); ui->reopenTabToggle->setChecked(reopentab); + // Connect comboBox to change handler after initialization to avoid false calls + connect(ui->comboBoxLanguage, QOverload::of(&QComboBox::currentIndexChanged), this, &SettingsView::languageSelected); } bool SettingsView::confirmDialog( QString messageText, QString messageTitle) { @@ -159,6 +172,30 @@ void SettingsView::onDownloadDirChanged(const QString &dir) ui->downloadDirPath->setText(dir); } +void SettingsView::languageSelected(const int &languageIndex) +{ + // QMessageBox msgBox; + // msgBox.setIcon(QMessageBox::Question); + // msgBox.setText("Restart to apply language change?"); + // msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + // msgBox.setDefaultButton(QMessageBox::Yes); + // int ret = msgBox.exec(); + // if (ret == QMessageBox::Yes) { + // ui->comboBoxLanguage->setCurrentIndex(languageIndex); + // KiwixApp::instance()->getSettingsManager()->setAppLanguage(languageIndex); + // qInfo() << "restarting"; + // qApp->quit(); + // // QProcess::startDetached(qApp->arguments()[0], qApp->arguments()); + // exit(0); + // } else { + // int previousIndex = KiwixApp::instance()->getSettingsManager()->getAppLanguageIndex(); + // ui->comboBoxLanguage->setCurrentIndex(previousIndex); // TODO causes issues with re emit + // } + + ui->comboBoxLanguage->setCurrentIndex(languageIndex); + KiwixApp::instance()->getSettingsManager()->setAppLanguage(languageIndex); +} + void SettingsView::onMonitorDirChanged(const QString &dir) { if (dir == "") { diff --git a/src/settingsview.h b/src/settingsview.h index e59ff494..30127832 100644 --- a/src/settingsview.h +++ b/src/settingsview.h @@ -11,10 +11,8 @@ class SettingsView : public QWidget public: SettingsView(QWidget *parent = nullptr); ~SettingsView(){}; - void init(int zoomPercent, const QString &downloadDir, - const QString &monitorDir, const bool moveToTrash, - bool reopentab); - public Q_SLOTS: + void init(int zoomPercent, const QString &downloadDir, const QString &monitorDir, const int &langIndex, const bool moveToTrash, bool reopentab); +public Q_SLOTS: void resetDownloadDir(); void browseDownloadDir(); void browseMonitorDir(); @@ -23,6 +21,7 @@ class SettingsView : public QWidget void setMoveToTrash(bool moveToTrash); void setReopenTab(bool reopen); void onDownloadDirChanged(const QString &dir); + void languageSelected(const int &languageIndex); void onMonitorDirChanged(const QString &dir); void onZoomChanged(qreal zoomFactor); void onMoveToTrashChanged(bool moveToTrash); diff --git a/ui/settings.ui b/ui/settings.ui index 949712c2..ca1f1bc5 100644 --- a/ui/settings.ui +++ b/ui/settings.ui @@ -51,14 +51,14 @@ - + Qt::Horizontal - + @@ -67,7 +67,7 @@ - + Qt::Horizontal @@ -104,7 +104,7 @@ - + QFrame::Plain @@ -114,7 +114,7 @@ - + @@ -123,7 +123,7 @@ - + Qt::Horizontal @@ -145,9 +145,9 @@ - + - + Qt::Horizontal @@ -200,14 +200,14 @@ - + Qt::Horizontal - + @@ -232,7 +232,7 @@ - + Qt::Horizontal @@ -254,9 +254,9 @@ - + - + Qt::Horizontal @@ -285,7 +285,45 @@ - + + + Qt::Horizontal + + + + + + + + + Language + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + Qt::Horizontal