From 8ea4091c7b6d14e52367ef2f8bda8dfee2ec23b5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 22:56:41 +0200 Subject: [PATCH 1/7] [libcalamares] Add a TranslatedString class to locale/ - While QObject::tr and gettext give us translations **most** of the time via the translation mechanism, we sometimes have strings embedded in configuration files that need to be shown to people as well. Follow the .desktop style in handling this. - A key's value **might** be translated; use `key[lang]` for the translation into one of the languages that Calamares understands. Code that expects a translated (human-readable) string in a configuration file can use TranslatedString to collect all the translations of a given key, so that it displays the right string from the configuration when needed. --- src/libcalamares/CMakeLists.txt | 1 + .../locale/TranslatableConfiguration.cpp | 67 +++++++++++++++++++ .../locale/TranslatableConfiguration.h | 54 +++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 src/libcalamares/locale/TranslatableConfiguration.cpp create mode 100644 src/libcalamares/locale/TranslatableConfiguration.h diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index 19bcc921d..0aca79233 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -34,6 +34,7 @@ set( libSources locale/Label.cpp locale/LabelModel.cpp locale/Lookup.cpp + locale/TranslatableConfiguration.cpp # Partition service partition/PartitionSize.cpp diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp new file mode 100644 index 000000000..6d4684121 --- /dev/null +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -0,0 +1,67 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "TranslatableConfiguration.h" + +#include "LabelModel.h" + +#include "utils/Logger.h" +#include "utils/Variant.h" + +#include +#include + +namespace CalamaresUtils +{ +namespace Locale +{ +TranslatedString::TranslatedString(const QString& string) +{ + m_strings[QString()]=string; +} +TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) +{ + // Get the un-decorated value for the key + QString value = CalamaresUtils::getString( map, key ); + if ( value.isEmpty() ) + { + value = key; + } + m_strings[QString()] = value; + + for ( auto it = m_strings.constKeyValueBegin(); it != m_strings.constKeyValueEnd(); ++it ) + { + QString subkey = (*it).first; + if ( subkey == key ) + { + // Already obtained, above + } + else if ( subkey.startsWith( key ) ) + { + QRegularExpressionMatch match; + if ( subkey.indexOf( QRegularExpression("\\[([a-zA-Z_@]*)\\]"), 0, &match ) > 0 ) + { + QString language = match.captured(1); + cDebug() << "Found translation" << key << '[' << language << ']'; + } + } + } +} + +} // namespace Locale +} // namespace CalamaresUtils diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h new file mode 100644 index 000000000..8cc02fadd --- /dev/null +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -0,0 +1,54 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef LOCALE_TRANSLATABLECONFIGURATION_H +#define LOCALE_TRANSLATABLECONFIGURATION_H + +#include "DllMacro.h" + +#include +#include +#include + +namespace CalamaresUtils +{ +namespace Locale +{ + /** @brief A human-readable string from a configuration file + * + * The configuration files can contain human-readable strings, + * but those need their own translations and are not supported + * by QObject::tr or anything else. + */ + class DLLEXPORT TranslatedString + { + public: + /** @brief Get all the translations connected to @p key + */ + TranslatedString( const QVariantMap& map, const QString& key ); + /** @brief Not-actually-translated string. + */ + TranslatedString( const QString& string ); + private: + // Maps locale name to human-readable string, "" is English + QMap< QString, QString > m_strings; + }; +} // namespace Locale +} // namespace CalamaresUtils + +#endif From 18e2f2ae527f6c83a1bb33d0e046bc0556e33a4f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 17:57:32 +0200 Subject: [PATCH 2/7] [libcalamares] Add tests for new TranslatedString - Test that construction works as expected - Add count() method to TranslatedString for testing purposes. --- src/libcalamares/locale/Tests.cpp | 47 +++++++++++++++++++ src/libcalamares/locale/Tests.h | 3 ++ .../locale/TranslatableConfiguration.cpp | 5 +- .../locale/TranslatableConfiguration.h | 3 ++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 9e2071a31..a87de8a98 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -19,7 +19,10 @@ #include "Tests.h" #include "locale/LabelModel.h" +#include "locale/TranslatableConfiguration.h" + #include "utils/Logger.h" +#include "CalamaresVersion.h" #include @@ -81,3 +84,47 @@ LocaleTests::testEsperanto() QCOMPARE( QLocale( "eo" ).language(), QLocale::C ); } + +static const QStringList& +someLanguages() +{ + static QStringList languages{ "nl", "de", "da", "nb", "sr@latin", "ar", "ru" }; + return languages; + } + + + void LocaleTests::testTranslatableLanguages() +{ + QStringList availableLanguages = QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';' ); + cDebug() << "Translation languages:" << availableLanguages; + for ( const auto& language: someLanguages() ) + { + // Could be QVERIFY, but then we don't see what language code fails + QCOMPARE( availableLanguages.contains( language ) ? language : QString(), language ); + } +} + +void LocaleTests::testTranslatableConfig1() +{ + CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); + QCOMPARE( ts1.count(), 1 ); + + QVariantMap map; + map.insert( "description", "description (no language)" ); + CalamaresUtils::Locale::TranslatedString ts2(map, "description"); + QCOMPARE( ts2.count(), 1 ); +} + +void LocaleTests::testTranslatableConfig2() +{ + QVariantMap map; + + for ( const auto& language: someLanguages() ) + { + map.insert( QString("description[%1]").arg(language), QString("description (language %1)").arg(language) ); + } + + CalamaresUtils::Locale::TranslatedString s(map, "description"); + // The +1 is because "" is always also inserted + QCOMPARE( s.count(), someLanguages().count()+1 ); +} diff --git a/src/libcalamares/locale/Tests.h b/src/libcalamares/locale/Tests.h index be712388f..c6949f3e4 100644 --- a/src/libcalamares/locale/Tests.h +++ b/src/libcalamares/locale/Tests.h @@ -33,6 +33,9 @@ private Q_SLOTS: void testLanguageModelCount(); void testEsperanto(); + void testTranslatableLanguages(); + void testTranslatableConfig1(); + void testTranslatableConfig2(); }; #endif diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index 6d4684121..d6c078303 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -44,7 +44,7 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) } m_strings[QString()] = value; - for ( auto it = m_strings.constKeyValueBegin(); it != m_strings.constKeyValueEnd(); ++it ) + for ( auto it = map.constKeyValueBegin(); it != map.constKeyValueEnd(); ++it ) { QString subkey = (*it).first; if ( subkey == key ) @@ -53,11 +53,12 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) } else if ( subkey.startsWith( key ) ) { + cDebug() << "Checking" << subkey; QRegularExpressionMatch match; if ( subkey.indexOf( QRegularExpression("\\[([a-zA-Z_@]*)\\]"), 0, &match ) > 0 ) { QString language = match.captured(1); - cDebug() << "Found translation" << key << '[' << language << ']'; + m_strings[language] = (*it).second.toString(); } } } diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index 8cc02fadd..01bdf8ed6 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -44,6 +44,9 @@ namespace Locale /** @brief Not-actually-translated string. */ TranslatedString( const QString& string ); + + int count() const { return m_strings.count(); } + private: // Maps locale name to human-readable string, "" is English QMap< QString, QString > m_strings; From 28293ef77a607d3b694e8d86b0dffbca9f0d1827 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 23:30:51 +0200 Subject: [PATCH 3/7] [libcalamares] Expand tests of TranslatableString --- src/libcalamares/locale/Tests.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index a87de8a98..46b1df150 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -122,9 +122,17 @@ void LocaleTests::testTranslatableConfig2() for ( const auto& language: someLanguages() ) { map.insert( QString("description[%1]").arg(language), QString("description (language %1)").arg(language) ); + if ( language != "nl" ) + { + map.insert( QString("name[%1]").arg(language), QString("name (language %1)").arg(language) ); + } } - CalamaresUtils::Locale::TranslatedString s(map, "description"); + CalamaresUtils::Locale::TranslatedString ts1(map, "description"); // The +1 is because "" is always also inserted - QCOMPARE( s.count(), someLanguages().count()+1 ); + QCOMPARE( ts1.count(), someLanguages().count()+1 ); + + CalamaresUtils::Locale::TranslatedString ts2(map, "name"); + // We skipped dutch this time + QCOMPARE( ts2.count(), someLanguages().count() ); } From e0edd1f3e2bc57f826acd9b9713110dacbd107be Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 23:32:13 +0200 Subject: [PATCH 4/7] [libcalamares] Fix misleading comment, add accessor - the sort order is not English-at-the-top - add accessor for the locale ID. --- src/libcalamares/locale/Label.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/locale/Label.h b/src/libcalamares/locale/Label.h index ab3e80ad0..0fe61d909 100644 --- a/src/libcalamares/locale/Label.h +++ b/src/libcalamares/locale/Label.h @@ -58,7 +58,7 @@ public: /** @brief Define a sorting order. * - * English (@see isEnglish() -- it means en_US) is sorted at the top. + * Locales are sorted by their id, which means the ISO 2-letter code + country. */ bool operator<( const Label& other ) const { return m_localeId < other.m_localeId; } @@ -78,6 +78,7 @@ public: QLocale locale() const { return m_locale; } QString name() const { return m_locale.name(); } + QString id() const { return m_localeId; } /// @brief Convenience accessor to the language part of the locale QLocale::Language language() const { return m_locale.language(); } From 50d74c4eca3e919b9bd7f769d2381e3f4432ccc0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 23:37:25 +0200 Subject: [PATCH 5/7] [libcalamares] Add get() to the string - Look up the translation of the requested string with the current or a specific locale. This implementation is a stub. - Add tests for the getter. --- src/libcalamares/locale/Tests.cpp | 9 +++++++++ .../locale/TranslatableConfiguration.cpp | 13 ++++++++++++- src/libcalamares/locale/TranslatableConfiguration.h | 6 ++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 46b1df150..1cfd733a0 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -109,10 +109,16 @@ void LocaleTests::testTranslatableConfig1() CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); QCOMPARE( ts1.count(), 1 ); + QCOMPARE( ts1.get(), "Hello" ); + QCOMPARE( ts1.get( QLocale("nl")), "Hello" ); + QVariantMap map; map.insert( "description", "description (no language)" ); CalamaresUtils::Locale::TranslatedString ts2(map, "description"); QCOMPARE( ts2.count(), 1 ); + + QCOMPARE( ts2.get(), "description (no language)"); + QCOMPARE( ts2.get( QLocale( "nl" ) ), "description (no language)"); } void LocaleTests::testTranslatableConfig2() @@ -131,6 +137,9 @@ void LocaleTests::testTranslatableConfig2() CalamaresUtils::Locale::TranslatedString ts1(map, "description"); // The +1 is because "" is always also inserted QCOMPARE( ts1.count(), someLanguages().count()+1 ); + + QCOMPARE( ts1.get(), "description"); // it wasn't set + QCOMPARE( ts1.get( QLocale( "nl" ) ), "description (language nl)"); CalamaresUtils::Locale::TranslatedString ts2(map, "name"); // We skipped dutch this time diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index d6c078303..d7066a57c 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -53,7 +53,6 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) } else if ( subkey.startsWith( key ) ) { - cDebug() << "Checking" << subkey; QRegularExpressionMatch match; if ( subkey.indexOf( QRegularExpression("\\[([a-zA-Z_@]*)\\]"), 0, &match ) > 0 ) { @@ -64,5 +63,17 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) } } +QString TranslatedString::get() const +{ + return get( QLocale() ); +} + +QString TranslatedString::get(const QLocale& locale) const +{ + cDebug() << "Getting locale" << locale.name(); + return m_strings[QString()]; +} + + } // namespace Locale } // namespace CalamaresUtils diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index 01bdf8ed6..b5a18ee73 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -47,6 +47,12 @@ namespace Locale int count() const { return m_strings.count(); } + /// @brief Gets the string in the current locale + QString get() const; + + /// @brief Gets the string from the given locale + QString get(const QLocale&) const; + private: // Maps locale name to human-readable string, "" is English QMap< QString, QString > m_strings; From a9292d0c75316d2956ea70df0ce0aae7222c583f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 23:54:53 +0200 Subject: [PATCH 6/7] [libcalamares] Implement getting the string --- src/libcalamares/locale/Tests.cpp | 56 ++++++++++--------- .../locale/TranslatableConfiguration.cpp | 53 +++++++++++++----- .../locale/TranslatableConfiguration.h | 54 +++++++++--------- 3 files changed, 97 insertions(+), 66 deletions(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 1cfd733a0..6f8310233 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -21,8 +21,8 @@ #include "locale/LabelModel.h" #include "locale/TranslatableConfiguration.h" -#include "utils/Logger.h" #include "CalamaresVersion.h" +#include "utils/Logger.h" #include @@ -88,60 +88,64 @@ LocaleTests::testEsperanto() static const QStringList& someLanguages() { - static QStringList languages{ "nl", "de", "da", "nb", "sr@latin", "ar", "ru" }; + static QStringList languages { "nl", "de", "da", "nb", "sr@latin", "ar", "ru" }; return languages; - } +} - - void LocaleTests::testTranslatableLanguages() + +void +LocaleTests::testTranslatableLanguages() { QStringList availableLanguages = QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';' ); cDebug() << "Translation languages:" << availableLanguages; - for ( const auto& language: someLanguages() ) + for ( const auto& language : someLanguages() ) { // Could be QVERIFY, but then we don't see what language code fails QCOMPARE( availableLanguages.contains( language ) ? language : QString(), language ); } } -void LocaleTests::testTranslatableConfig1() +void +LocaleTests::testTranslatableConfig1() { CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); QCOMPARE( ts1.count(), 1 ); - + QCOMPARE( ts1.get(), "Hello" ); - QCOMPARE( ts1.get( QLocale("nl")), "Hello" ); - + QCOMPARE( ts1.get( QLocale( "nl" ) ), "Hello" ); + QVariantMap map; map.insert( "description", "description (no language)" ); - CalamaresUtils::Locale::TranslatedString ts2(map, "description"); + CalamaresUtils::Locale::TranslatedString ts2( map, "description" ); QCOMPARE( ts2.count(), 1 ); - - QCOMPARE( ts2.get(), "description (no language)"); - QCOMPARE( ts2.get( QLocale( "nl" ) ), "description (no language)"); + + QCOMPARE( ts2.get(), "description (no language)" ); + QCOMPARE( ts2.get( QLocale( "nl" ) ), "description (no language)" ); } -void LocaleTests::testTranslatableConfig2() +void +LocaleTests::testTranslatableConfig2() { QVariantMap map; - - for ( const auto& language: someLanguages() ) + + for ( const auto& language : someLanguages() ) { - map.insert( QString("description[%1]").arg(language), QString("description (language %1)").arg(language) ); + map.insert( QString( "description[%1]" ).arg( language ), + QString( "description (language %1)" ).arg( language ) ); if ( language != "nl" ) { - map.insert( QString("name[%1]").arg(language), QString("name (language %1)").arg(language) ); + map.insert( QString( "name[%1]" ).arg( language ), QString( "name (language %1)" ).arg( language ) ); } } - - CalamaresUtils::Locale::TranslatedString ts1(map, "description"); + + CalamaresUtils::Locale::TranslatedString ts1( map, "description" ); // The +1 is because "" is always also inserted - QCOMPARE( ts1.count(), someLanguages().count()+1 ); + QCOMPARE( ts1.count(), someLanguages().count() + 1 ); + + QCOMPARE( ts1.get(), "description" ); // it wasn't set + QCOMPARE( ts1.get( QLocale( "nl" ) ), "description (language nl)" ); - QCOMPARE( ts1.get(), "description"); // it wasn't set - QCOMPARE( ts1.get( QLocale( "nl" ) ), "description (language nl)"); - - CalamaresUtils::Locale::TranslatedString ts2(map, "name"); + CalamaresUtils::Locale::TranslatedString ts2( map, "name" ); // We skipped dutch this time QCOMPARE( ts2.count(), someLanguages().count() ); } diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index d7066a57c..0b4a6ff71 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -30,11 +30,11 @@ namespace CalamaresUtils { namespace Locale { -TranslatedString::TranslatedString(const QString& string) +TranslatedString::TranslatedString( const QString& string ) { - m_strings[QString()]=string; + m_strings[ QString() ] = string; } -TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) +TranslatedString::TranslatedString( const QVariantMap& map, const QString& key ) { // Get the un-decorated value for the key QString value = CalamaresUtils::getString( map, key ); @@ -42,11 +42,11 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) { value = key; } - m_strings[QString()] = value; - + m_strings[ QString() ] = value; + for ( auto it = map.constKeyValueBegin(); it != map.constKeyValueEnd(); ++it ) { - QString subkey = (*it).first; + QString subkey = ( *it ).first; if ( subkey == key ) { // Already obtained, above @@ -54,24 +54,51 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) else if ( subkey.startsWith( key ) ) { QRegularExpressionMatch match; - if ( subkey.indexOf( QRegularExpression("\\[([a-zA-Z_@]*)\\]"), 0, &match ) > 0 ) + if ( subkey.indexOf( QRegularExpression( "\\[([a-zA-Z_@]*)\\]" ), 0, &match ) > 0 ) { - QString language = match.captured(1); - m_strings[language] = (*it).second.toString(); + QString language = match.captured( 1 ); + m_strings[ language ] = ( *it ).second.toString(); } } } } -QString TranslatedString::get() const +QString +TranslatedString::get() const { return get( QLocale() ); } -QString TranslatedString::get(const QLocale& locale) const +QString +TranslatedString::get( const QLocale& locale ) const { - cDebug() << "Getting locale" << locale.name(); - return m_strings[QString()]; + QString localeName = locale.name(); + cDebug() << "Getting locale" << localeName; + if ( m_strings.contains( localeName ) ) + { + return m_strings[ localeName ]; + } + int index = localeName.indexOf( '@' ); + if ( index > 0 ) + { + localeName.truncate( index ); + if ( m_strings.contains( localeName ) ) + { + return m_strings[ localeName ]; + } + } + + index = localeName.indexOf( '_' ); + if ( index > 0 ) + { + localeName.truncate( index ); + if ( m_strings.contains( localeName ) ) + { + return m_strings[ localeName ]; + } + } + + return m_strings[ QString() ]; } diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index b5a18ee73..0735a2274 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -29,34 +29,34 @@ namespace CalamaresUtils { namespace Locale { - /** @brief A human-readable string from a configuration file - * - * The configuration files can contain human-readable strings, - * but those need their own translations and are not supported - * by QObject::tr or anything else. +/** @brief A human-readable string from a configuration file + * + * The configuration files can contain human-readable strings, + * but those need their own translations and are not supported + * by QObject::tr or anything else. + */ +class DLLEXPORT TranslatedString +{ +public: + /** @brief Get all the translations connected to @p key + */ + TranslatedString( const QVariantMap& map, const QString& key ); + /** @brief Not-actually-translated string. */ - class DLLEXPORT TranslatedString - { - public: - /** @brief Get all the translations connected to @p key - */ - TranslatedString( const QVariantMap& map, const QString& key ); - /** @brief Not-actually-translated string. - */ - TranslatedString( const QString& string ); - - int count() const { return m_strings.count(); } - - /// @brief Gets the string in the current locale - QString get() const; - - /// @brief Gets the string from the given locale - QString get(const QLocale&) const; - - private: - // Maps locale name to human-readable string, "" is English - QMap< QString, QString > m_strings; - }; + TranslatedString( const QString& string ); + + int count() const { return m_strings.count(); } + + /// @brief Gets the string in the current locale + QString get() const; + + /// @brief Gets the string from the given locale + QString get( const QLocale& ) const; + +private: + // Maps locale name to human-readable string, "" is English + QMap< QString, QString > m_strings; +}; } // namespace Locale } // namespace CalamaresUtils From 764c775f08e77a3eb66209edc2a6bb1e54dafa77 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:05:24 +0200 Subject: [PATCH 7/7] [libcalamares] Tighten tests, add special case - The tests should be run in C locale, otherwise the plain get() function uses the current locale, which will fail (e.g. running LANG=nl ./libcalamareslocaletest returns the Dutch strings for plain get, which isn't what we expect). - sr@latin is still special. --- src/libcalamares/locale/Tests.cpp | 16 ++++++++++++++++ .../locale/TranslatableConfiguration.cpp | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 6f8310233..241d66bbd 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -108,6 +108,7 @@ LocaleTests::testTranslatableLanguages() void LocaleTests::testTranslatableConfig1() { + QCOMPARE( QLocale().name(), "C" ); // Otherwise plain get() is dubious CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); QCOMPARE( ts1.count(), 1 ); @@ -126,6 +127,7 @@ LocaleTests::testTranslatableConfig1() void LocaleTests::testTranslatableConfig2() { + QCOMPARE( QLocale().name(), "C" ); // Otherwise plain get() is dubious QVariantMap map; for ( const auto& language : someLanguages() ) @@ -144,6 +146,20 @@ LocaleTests::testTranslatableConfig2() QCOMPARE( ts1.get(), "description" ); // it wasn't set QCOMPARE( ts1.get( QLocale( "nl" ) ), "description (language nl)" ); + for ( const auto& language : someLanguages() ) + { + // Skip Serbian (latin) because QLocale() constructed with it + // doesn't retain the @latin part. + if ( language == "sr@latin" ) + { + continue; + } + // Could be QVERIFY, but then we don't see what language code fails + QCOMPARE( ts1.get( language ) == QString( "description (language %1)" ).arg( language ) ? language : QString(), + language ); + } + QCOMPARE( ts1.get( QLocale( QLocale::Language::Serbian, QLocale::Script::LatinScript, QLocale::Country::Serbia ) ), + "description (language sr@latin)" ); CalamaresUtils::Locale::TranslatedString ts2( map, "name" ); // We skipped dutch this time diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index 0b4a6ff71..82923a5fa 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -73,6 +73,12 @@ QString TranslatedString::get( const QLocale& locale ) const { QString localeName = locale.name(); + // Special case, sr@latin doesn't have the @latin reflected in the name + if ( locale.language() == QLocale::Language::Serbian && locale.script() == QLocale::Script::LatinScript ) + { + localeName = QStringLiteral( "sr@latin" ); + } + cDebug() << "Getting locale" << localeName; if ( m_strings.contains( localeName ) ) {