From 0ed2a3e35f56db9cc173a725187f63a3ba770997 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 11 Dec 2019 06:40:22 -0500 Subject: [PATCH] [libcalamares] Refactor translation-setting - Split the actual loading of translations into classes to encapsulate the loading logic, - Build a collection of classes to do the different kinds of translation loading, - Build a generic function to load something and update a static pointer to the translation. This makes installTranslator() much easier to read, and encapsulates the type-specific loading somewhere else. While here, add a timezone- translations loader so that the split-out TZ translations also work. --- src/libcalamares/utils/Retranslator.cpp | 170 ++++++++++++++++-------- 1 file changed, 118 insertions(+), 52 deletions(-) diff --git a/src/libcalamares/utils/Retranslator.cpp b/src/libcalamares/utils/Retranslator.cpp index d761263ac..047f642e4 100644 --- a/src/libcalamares/utils/Retranslator.cpp +++ b/src/libcalamares/utils/Retranslator.cpp @@ -25,90 +25,156 @@ #include #include - -namespace CalamaresUtils +/** @brief Helper class for loading translations + * + * This is used by the loadSingletonTranslator() function to hand off + * work to translation-type specific code. + */ +struct TranslationLoader { -static QTranslator* s_brandingTranslator = nullptr; -static QTranslator* s_translator = nullptr; -static QString s_translatorLocaleName; + static QString mungeLocaleName( const QLocale& locale ) + { + QString localeName = locale.name(); + localeName.replace( "-", "_" ); -void -installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* parent ) -{ - QString localeName = locale.name(); - localeName.replace( "-", "_" ); + if ( localeName == "C" ) + { + localeName = "en"; + } - if ( localeName == "C" ) - { - localeName = "en"; + // Special case of sr@latin + // + // See top-level CMakeLists.txt about special cases for translation loading. + if ( locale.language() == QLocale::Language::Serbian && locale.script() == QLocale::Script::LatinScript ) + { + localeName = QStringLiteral( "sr@latin" ); + } + return localeName; } - // Special case of sr@latin - // - // See top-level CMakeLists.txt about special cases for translation loading. - if ( locale.language() == QLocale::Language::Serbian && locale.script() == QLocale::Script::LatinScript ) + TranslationLoader( const QLocale& locale ) + : m_locale( locale ) + , m_localeName( mungeLocaleName( locale ) ) { - localeName = QStringLiteral( "sr@latin" ); } - cDebug() << "Looking for translations for" << localeName; + virtual ~TranslationLoader() {}; + /// @brief Loads @p translator with the specific translations of this type + virtual bool tryLoad( QTranslator* translator ) = 0; + + const QLocale& m_locale; + QString m_localeName; +}; - QTranslator* translator = nullptr; +struct BrandingLoader : public TranslationLoader +{ + BrandingLoader( const QLocale& locale, const QString& prefix ) + : TranslationLoader( locale ) + , m_prefix( prefix ) + { + } - // Branding translations - if ( !brandingTranslationsPrefix.isEmpty() ) + bool tryLoad( QTranslator* translator ) override { - QString brandingTranslationsDirPath( brandingTranslationsPrefix ); - brandingTranslationsDirPath.truncate( brandingTranslationsPrefix.lastIndexOf( QDir::separator() ) ); + if ( m_prefix.isEmpty() ) + { + return false; + } + QString brandingTranslationsDirPath( m_prefix ); + brandingTranslationsDirPath.truncate( m_prefix.lastIndexOf( QDir::separator() ) ); QDir brandingTranslationsDir( brandingTranslationsDirPath ); if ( brandingTranslationsDir.exists() ) { - QString filenameBase( brandingTranslationsPrefix ); - filenameBase.remove( 0, brandingTranslationsPrefix.lastIndexOf( QDir::separator() ) + 1 ); - translator = new QTranslator( parent ); - if ( translator->load( locale, filenameBase, "_", brandingTranslationsDir.absolutePath() ) ) + QString filenameBase( m_prefix ); + filenameBase.remove( 0, m_prefix.lastIndexOf( QDir::separator() ) + 1 ); + if ( translator->load( m_locale, filenameBase, "_", brandingTranslationsDir.absolutePath() ) ) { - cDebug() << Logger::SubEntry << "Branding using locale:" << localeName; + cDebug() << Logger::SubEntry << "Branding using locale:" << m_localeName; + return true; } else { - cDebug() << Logger::SubEntry << "Branding using default, system locale not found:" << localeName; - translator->load( brandingTranslationsPrefix + "en" ); - } - - if ( s_brandingTranslator ) - { - QCoreApplication::removeTranslator( s_brandingTranslator ); - delete s_brandingTranslator; + cDebug() << Logger::SubEntry << "Branding using default, system locale not found:" << m_localeName; + // TODO: this loads something completely different + return translator->load( m_prefix + "en" ); } - - QCoreApplication::installTranslator( translator ); - s_brandingTranslator = translator; } + return false; } - // Calamares translations - translator = new QTranslator( parent ); - if ( translator->load( QString( ":/lang/calamares_" ) + localeName ) ) + QString m_prefix; +}; + +struct CalamaresLoader : public TranslationLoader +{ + using TranslationLoader::TranslationLoader; + + bool tryLoad( QTranslator* translator ) override { - cDebug() << Logger::SubEntry << "Calamares using locale:" << localeName; + if ( translator->load( QString( ":/lang/calamares_" ) + m_localeName ) ) + { + cDebug() << Logger::SubEntry << "Calamares using locale:" << m_localeName; + return true; + } + else + { + cDebug() << Logger::SubEntry << "Calamares using default, system locale not found:" << m_localeName; + return translator->load( QString( ":/lang/calamares_en" ) ); + } } - else +}; + +struct TZLoader : public TranslationLoader +{ + using TranslationLoader::TranslationLoader; + bool tryLoad( QTranslator* translator ) override { - cDebug() << Logger::SubEntry << "Calamares using default, system locale not found:" << localeName; - translator->load( QString( ":/lang/calamares_en" ) ); + if ( translator->load( QString( ":/lang/tz_" ) + m_localeName ) ) + { + cDebug() << Logger::SubEntry << "Calamares Timezones using locale:" << m_localeName; + return true; + } + else + { + cDebug() << Logger::SubEntry + << "Calamares Timezones using default, system locale not found:" << m_localeName; + return translator->load( QString( ":/lang/tz_en" ) ); + } } +}; - if ( s_translator ) +static void +loadSingletonTranslator( TranslationLoader&& loader, QTranslator*& translator_p ) +{ + QTranslator* translator = new QTranslator(); + loader.tryLoad( translator ); + + if ( translator_p ) { - QCoreApplication::removeTranslator( s_translator ); - delete s_translator; + QCoreApplication::removeTranslator( translator_p ); + delete translator_p; } QCoreApplication::installTranslator( translator ); - s_translator = translator; + translator_p = translator; +} + +namespace CalamaresUtils +{ +static QTranslator* s_brandingTranslator = nullptr; +static QTranslator* s_translator = nullptr; +static QTranslator* s_tztranslator = nullptr; +static QString s_translatorLocaleName; + +void +installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* parent ) +{ + loadSingletonTranslator( BrandingLoader( locale, brandingTranslationsPrefix ), s_brandingTranslator ); + loadSingletonTranslator( TZLoader( locale ), s_tztranslator ); - s_translatorLocaleName = localeName; + CalamaresLoader l( locale ); // because we want the extracted localeName + loadSingletonTranslator( std::move( l ), s_translator ); + s_translatorLocaleName = l.m_localeName; }