From 0dcc1f614b2ab4f0d4bbac5fd29676595072a133 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 11 Mar 2021 15:35:56 +0100 Subject: REFAC(client): Separate translation handling Instead of doing everything in main.cpp, there is now a dedicated source files that deals with that. --- src/mumble/CMakeLists.txt | 2 + src/mumble/Translations.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++++ src/mumble/Translations.h | 26 +++++++++++ src/mumble/main.cpp | 89 +++++++----------------------------- 4 files changed, 151 insertions(+), 73 deletions(-) create mode 100644 src/mumble/Translations.cpp create mode 100644 src/mumble/Translations.h (limited to 'src') diff --git a/src/mumble/CMakeLists.txt b/src/mumble/CMakeLists.txt index 768f8daad..96266ee8f 100644 --- a/src/mumble/CMakeLists.txt +++ b/src/mumble/CMakeLists.txt @@ -203,6 +203,8 @@ set(MUMBLE_SOURCES "Tokens.cpp" "Tokens.h" "Tokens.ui" + "Translations.cpp" + "Translations.h" "Usage.cpp" "Usage.h" "UserEdit.cpp" diff --git a/src/mumble/Translations.cpp b/src/mumble/Translations.cpp new file mode 100644 index 000000000..bf93f78da --- /dev/null +++ b/src/mumble/Translations.cpp @@ -0,0 +1,107 @@ +// Copyright 2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#include "Translations.h" + +#include +#include +#include +#include +#include + +namespace Mumble { +namespace Translations { + + QStringList getDefaultTranslationDirectories() { + QStringList translationDirs; + + const QString translationDirName = "MumbleTranslations"; + + // AppData directories + for (const QString ¤tConfigPath : QStandardPaths::standardLocations(QStandardPaths::AppDataLocation)) { + translationDirs.append(QDir::cleanPath(currentConfigPath)); + } + // Directories in the config locations + for (const QString ¤tConfigPath : QStandardPaths::standardLocations(QStandardPaths::ConfigLocation)) { + translationDirs.append(QDir::cleanPath(currentConfigPath + QDir::separator() + translationDirName)); + } + // A directory in the home directory + for (const QString ¤tHomePath : QStandardPaths::standardLocations(QStandardPaths::HomeLocation)) { + translationDirs.append(QDir::cleanPath(currentHomePath + QDir::separator() + translationDirName)); + } + + return translationDirs; + } + + QStringList getTranslationDirectories(const QApplication &app, const QStringList &extraDirectories) { + QStringList directories; + + // The extra directories have highest priority + directories += extraDirectories; + + // Next up is the application's root path + directories.append(app.applicationDirPath()); + + // And finally the default locations + directories += getDefaultTranslationDirectories(); + + return directories; + } + + void installTranslators(const QLocale &locale, QApplication &app, const QStringList &extraDirectories) { + // First install a translator that uses the bundled translations + QTranslator bundledTranslator; + if (bundledTranslator.load(locale, ":mumble_")) { + app.installTranslator(&bundledTranslator); + } else { + qWarning("Unable to find bundled translations for locale \"%s\"", qUtf8Printable(locale.name())); + } + + // Now try to add another translator that can overwrite the bundled translations based + // on translations found in one of the translation directories. + // The first matching translation file that is found, will be used (first come, first served) + QTranslator overwriteTranslator; + + const QString prefix = ""; + + for (const QString ¤tDir : getTranslationDirectories(app, extraDirectories)) { + if (overwriteTranslator.load(locale, "mumble_", prefix, currentDir)) { + app.installTranslator(&overwriteTranslator); + + qWarning("Using extra translation file for locale \"%s\" from directory \"%s\"", + qUtf8Printable(locale.name()), qUtf8Printable(currentDir)); + break; + } + } + + // With modularization of Qt 5 some - but not all - of the qt_.ts files have become + // so-called meta catalogues which no longer contain actual translations but refer to other + // more specific ts files like qtbase_.ts . To successfully load a meta catalogue all + // of its referenced translations must be available. As we do not want to bundle them all + // we now try to load the old qt_.ts file first and then fall back to loading + // qtbase_.ts if that failed. + // + // See http://doc.qt.io/qt-5/linguist-programmers.html#deploying-translations for more information + QTranslator qttranslator; + // First we try and see if there is a translation packaged with Mumble that shall overwrite any potentially + // existing Qt translations. If not, we try to load the qt-translations installed on the host-machine and if + // that fails as well, we try to load translations bundled in Mumble. Note: Resource starting with :/ are + // bundled resources specified in a .qrc file + if (qttranslator.load(locale, ":/mumble_overwrite_qt_")) { + app.installTranslator(&qttranslator); + } else if (qttranslator.load(locale, ":/mumble_overwrite_qtbase_")) { + app.installTranslator(&qttranslator); + } else if (qttranslator.load(locale, "qt_", QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + app.installTranslator(&qttranslator); + } else if (qttranslator.load(locale, "qtbase_", QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + app.installTranslator(&qttranslator); + } else if (qttranslator.load(locale, ":/qt_")) { + app.installTranslator(&qttranslator); + } else if (qttranslator.load(locale, ":/qtbase_")) { + app.installTranslator(&qttranslator); + } + } +}; // namespace Translations +}; // namespace Mumble diff --git a/src/mumble/Translations.h b/src/mumble/Translations.h new file mode 100644 index 000000000..4e472e635 --- /dev/null +++ b/src/mumble/Translations.h @@ -0,0 +1,26 @@ +// Copyright 2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#ifndef MUMBLE_MUMBLE_TRANSLATIONS_H_ +#define MUMBLE_MUMBLE_TRANSLATIONS_H_ + +#include + +class QApplication; +class QLocale; + +namespace Mumble { +namespace Translations { + + QStringList getDefaultTranslationDirectories(); + + QStringList getTranslationDirectories(const QApplication &app, const QStringList &extraDirectories); + + void installTranslators(const QLocale &locale, QApplication &app, const QStringList &extraDirectories); + +}; // namespace Translations +}; // namespace Mumble + +#endif // MUMBLE_MUMBLE_TRANSLATIONS_H_ diff --git a/src/mumble/main.cpp b/src/mumble/main.cpp index 587e84b25..947d419fe 100644 --- a/src/mumble/main.cpp +++ b/src/mumble/main.cpp @@ -39,16 +39,15 @@ #include "SSL.h" #include "SocketRPC.h" #include "TalkingUI.h" +#include "Translations.h" #include "Themes.h" #include "UserLockFile.h" #include "VersionCheck.h" -#include #include -#include -#include #include #include +#include #include #ifdef USE_DBUS @@ -400,30 +399,11 @@ int main(int argc, char **argv) { } } - // Populate extra translation dirs (directories in which Mumble shall look for - // translation files that can overwrite the bundled one if present). The order - // in which they are added to this list determines the priority (first match - // will win). - // Start with the directory the Mumble executable lives in. - extraTranslationDirs.append(a.applicationDirPath()); - // Next add AppData directories - for (const QString ¤tConfigPath : QStandardPaths::standardLocations(QStandardPaths::AppDataLocation)) { - extraTranslationDirs.append(QDir::cleanPath(currentConfigPath)); - } - // Next add directories in the config locations - for (const QString ¤tConfigPath : QStandardPaths::standardLocations(QStandardPaths::ConfigLocation)) { - extraTranslationDirs.append(QDir::cleanPath(currentConfigPath + QDir::separator() + "MumbleTranslations")); - } - // Finally add a dir in the home directory - for (const QString ¤tHomePath : QStandardPaths::standardLocations(QStandardPaths::HomeLocation)) { - extraTranslationDirs.append(QDir::cleanPath(currentHomePath + QDir::separator() + "MumbleTranslations")); - } - if (printTranslationDirs) { QString infoString = QObject::tr("The directories in which Mumble searches for extra translation files are:\n"); int counter = 1; - for (const QString ¤tTranslationDir : extraTranslationDirs) { + for (const QString ¤tTranslationDir : Mumble::Translations::getTranslationDirectories(a, extraTranslationDirs)) { infoString += QString::fromLatin1("%1. ").arg(counter) + currentTranslationDir + "\n"; counter++; } @@ -555,65 +535,28 @@ int main(int argc, char **argv) { Themes::apply(); - QString qsSystemLocale = QLocale::system().name(); + QLocale systemLocale = QLocale::system(); #ifdef Q_OS_MAC if (os_lang) { - qWarning("Using Mac OS X system language as locale name"); - qsSystemLocale = QLatin1String(os_lang); - } -#endif - - const QString locale = Global::get().s.qsLanguage.isEmpty() ? qsSystemLocale : Global::get().s.qsLanguage; - qWarning("Locale is \"%s\" (System: \"%s\")", qPrintable(locale), qPrintable(qsSystemLocale)); + const QLocale macOSLocale = QLocale(QString::fromLatin1(os_lang)); - QTranslator translator; - if (translator.load(QLatin1String(":mumble_") + locale)) - a.installTranslator(&translator); - - // Create a second translator that tries to load translation files from several directories on - // disk. If found, these translation files can overwrite strings from the bundled translations - QTranslator loctranslator; - QString translationFilename = QLatin1String("mumble_") + locale; - for (const QString ¤tTranslationDir : extraTranslationDirs) { - if (loctranslator.load(translationFilename, currentTranslationDir)) { - a.installTranslator(&loctranslator); - - // First match wins - qWarning("Using extra translation file from directory: \"%s\"", currentTranslationDir.toUtf8().data()); - break; + if (macOSLocale != QLocale::c()) { + qWarning("Using Mac OS X system language as locale name"); + systemLocale = macOSLocale; } } +#endif - // With modularization of Qt 5 some - but not all - of the qt_.ts files have become - // so-called meta catalogues which no longer contain actual translations but refer to other - // more specific ts files like qtbase_.ts . To successfully load a meta catalogue all - // of its referenced translations must be available. As we do not want to bundle them all - // we now try to load the old qt_.ts file first and then fall back to loading - // qtbase_.ts if that failed. - // - // See http://doc.qt.io/qt-5/linguist-programmers.html#deploying-translations for more information - QTranslator qttranslator; - // First we try and see if there is a translation packaged with Mumble that shall overwrite any potentially existing - // Qt translations. If not, we try to load the qt-translations installed on the host-machine and if that fails as - // well, we try to load translations bundled in Mumble. Note: Resource starting with :/ are bundled resources - // specified in a .qrc file - if (qttranslator.load(QLatin1String(":/mumble_overwrite_qt_") + locale)) { - a.installTranslator(&qttranslator); - } else if (qttranslator.load(QLatin1String(":/mumble_overwrite_qtbase_") + locale)) { - a.installTranslator(&qttranslator); - } else if (qttranslator.load(QLatin1String("qt_") + locale, - QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { - a.installTranslator(&qttranslator); - } else if (qttranslator.load(QLatin1String("qtbase_") + locale, - QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { - a.installTranslator(&qttranslator); - } else if (qttranslator.load(QLatin1String(":/qt_") + locale)) { - a.installTranslator(&qttranslator); - } else if (qttranslator.load(QLatin1String(":/qtbase_") + locale)) { - a.installTranslator(&qttranslator); + QLocale settingsLocale = QLocale(Global::get().s.qsLanguage); + if (settingsLocale == QLocale::c()) { + settingsLocale = systemLocale; } + qWarning("Locale is \"%s\" (System: \"%s\")", qUtf8Printable(settingsLocale.name()), qUtf8Printable(systemLocale.name())); + + Mumble::Translations::installTranslators(settingsLocale, a, extraTranslationDirs); + // Initialize proxy settings NetworkConfig::SetupProxy(); -- cgit v1.2.3