diff --git a/localization/rssguard_en.ts b/localization/rssguard_en.ts index dbdc8b784..8b39ff2b6 100755 --- a/localization/rssguard_en.ts +++ b/localization/rssguard_en.ts @@ -5294,7 +5294,7 @@ Login tokens expiration: %2 - + LANG_AUTHOR Name of translator - optional. Martin Rotter @@ -6775,25 +6775,45 @@ Description: %3 SettingsLocalization - + Language Language - + Code Code - + Author Author - + + Translation progress + + + + Help us to improve %1 <a href="%2">translations</a>. + + + Translators needed! + + + + + The translation '%1' is incomplete and anyone able to help with translating %2 is greatly welcomed. + + + + + Do you want to help with the translation now? + + Localization diff --git a/src/librssguard/gui/settings/settingslocalization.cpp b/src/librssguard/gui/settings/settingslocalization.cpp index fbe8a9bab..edb8fc786 100644 --- a/src/librssguard/gui/settings/settingslocalization.cpp +++ b/src/librssguard/gui/settings/settingslocalization.cpp @@ -2,20 +2,26 @@ #include "gui/settings/settingslocalization.h" +#include "gui/messagebox.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" #include "miscellaneous/localization.h" #include "miscellaneous/settings.h" +#include "network-web/networkfactory.h" #include "network-web/webfactory.h" +#include +#include +#include + SettingsLocalization::SettingsLocalization(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent), m_ui(new Ui::SettingsLocalization) { m_ui->setupUi(this); - m_ui->m_treeLanguages->setColumnCount(3); + m_ui->m_treeLanguages->setColumnCount(4); m_ui->m_treeLanguages->setHeaderHidden(false); - m_ui->m_treeLanguages->setHeaderLabels(QStringList() - << /*: Language column of language list. */ tr("Language") - << /*: Lang. code column of language list. */ tr("Code") << tr("Author")); + m_ui->m_treeLanguages->setHeaderLabels(QStringList() << /*: Language column of language list. */ tr("Language") + << /*: Lang. code column of language list. */ tr("Code") + << tr("Translation progress") << tr("Author")); m_ui->m_lblHelp->setText(tr(R"(Help us to improve %1 translations.)") .arg(QSL(APP_NAME), QSL("https://crowdin.com/project/rssguard"))); @@ -26,6 +32,7 @@ SettingsLocalization::SettingsLocalization(Settings* settings, QWidget* parent) m_ui->m_treeLanguages->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents); m_ui->m_treeLanguages->header()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents); m_ui->m_treeLanguages->header()->setSectionResizeMode(2, QHeaderView::ResizeMode::ResizeToContents); + m_ui->m_treeLanguages->header()->setSectionResizeMode(3, QHeaderView::ResizeMode::ResizeToContents); connect(m_ui->m_treeLanguages, &QTreeWidget::currentItemChanged, this, &SettingsLocalization::requireRestart); connect(m_ui->m_treeLanguages, &QTreeWidget::currentItemChanged, this, &SettingsLocalization::dirtifySettings); } @@ -39,16 +46,60 @@ void SettingsLocalization::loadSettings() { auto langs = qApp->localization()->installedLanguages(); + // Also, load statistics with restricted access token. + QByteArray stats_out; + QMap percentages_langs; + NetworkResult stats_res = NetworkFactory:: + performNetworkOperation(QSL("https://api.crowdin.com/api/v2/projects/608575/languages/progress"), + qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(), + {}, + stats_out, + QNetworkAccessManager::Operation::GetOperation, + {{"Authorization", + "Bearer " + "0fbcad4c39d21a55f63f8a1b6d07cc56bb1e2eb2047bfaf1ee22425e3edf1c2b217f4d13b3cebba9"}}); + + if (stats_res.m_networkError == QNetworkReply::NetworkError::NoError) { + QJsonDocument stats_doc = QJsonDocument::fromJson(stats_out); + + for (const QJsonValue& val_lang : stats_doc.object()["data"].toArray()) { + QString lang_id = val_lang.toObject()["data"].toObject()["languageId"].toString().replace(QSL("-"), QSL("_")); + int lang_completion = val_lang.toObject()["data"].toObject()["translationProgress"].toInt(); + + percentages_langs.insert(lang_id, lang_completion); + } + } + for (const Language& language : qAsConst(langs)) { auto* item = new QTreeWidgetItem(m_ui->m_treeLanguages); + int perc_translated = percentages_langs.value(language.m_code); item->setText(0, language.m_name); item->setText(1, language.m_code); - item->setText(2, language.m_author); + + if (perc_translated >= 0) { + item->setToolTip(2, QString::number(perc_translated)); + } + + item->setText(2, QSL("%1 %").arg(perc_translated >= 0 ? QString::number(perc_translated) : QSL("-"))); + item->setText(3, language.m_author); item->setIcon(0, qApp->icons()->miscIcon(QSL(FLAG_ICON_SUBFOLDER) + QDir::separator() + language.m_code)); + + if (perc_translated < 40) { + item->setBackground(2, + qApp->skins()->colorForModel(SkinEnums::PaletteColors::FgError).value().darker(110)); + } + else if (perc_translated < 75) { + item->setBackground(2, + qApp->skins()->colorForModel(SkinEnums::PaletteColors::FgError).value().darker(90)); + } + else { + item->setBackground(2, qApp->skins()->colorForModel(SkinEnums::PaletteColors::Allright).value()); + } } m_ui->m_treeLanguages->sortByColumn(0, Qt::SortOrder::AscendingOrder); + QList matching_items = m_ui->m_treeLanguages->findItems(qApp->localization()->loadedLanguage(), Qt::MatchFlag::MatchContains, 1); @@ -72,6 +123,25 @@ void SettingsLocalization::saveSettings() { // Save prompt for restart if language has changed. if (new_lang != actual_lang) { + int perc = m_ui->m_treeLanguages->currentItem()->toolTip(2).toInt(); + + if (perc > 0 && perc < 75) { + const QMessageBox::StandardButton clicked_button = MsgBox:: + show(this, + QMessageBox::Icon::Question, + tr("Translators needed!"), + tr("The translation '%1' is incomplete and anyone able to help with translating %2 is greatly welcomed.") + .arg(new_lang, QSL(APP_NAME)), + tr("Do you want to help with the translation now?"), + {}, + QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, + QMessageBox::StandardButton::Yes); + + if (clicked_button == QMessageBox::StandardButton::Yes) { + qApp->web()->openUrlInExternalBrowser(QSL("https://crowdin.com/project/rssguard")); + } + } + requireRestart(); settings()->setValue(GROUP(General), General::Language, new_lang); } diff --git a/src/librssguard/miscellaneous/localization.cpp b/src/librssguard/miscellaneous/localization.cpp index dacb0b5ea..58f7ebb9e 100644 --- a/src/librssguard/miscellaneous/localization.cpp +++ b/src/librssguard/miscellaneous/localization.cpp @@ -67,7 +67,8 @@ QList Localization::installedLanguages() const { QList languages; const QDir file_dir(APP_LANG_PATH); QTranslator translator; - auto lang_files = file_dir.entryInfoList(QStringList() << QSL("rssguard_*.qm"), QDir::Files, QDir::Name); + auto lang_files = + file_dir.entryInfoList(QStringList() << QSL("rssguard_*.qm"), QDir::Filter::Files, QDir::SortFlag::Name); // Iterate all found language files. for (const QFileInfo& file : qAsConst(lang_files)) {