From 311af6de5d9a4d157ec6d888e6b85b0aaf9441a1 Mon Sep 17 00:00:00 2001 From: Harald Sitter Date: Thu, 5 Apr 2018 11:57:23 +0200 Subject: [PATCH 1/7] [locale] prefer native language and country names when available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This basically means we talk about localization in the respective localized variant. e.g. "German (Germany)" ➡ "Deutsch (Deutschland)". If geoip lookup failed or isn't configured for whatever reason it's a stretch to expect the user to know english enough to find their own language. Preferring the localized strings resolves this issue. Additionally this happens to bypass #712 respectively https://bugreports.qt.io/browse/QTBUG-34287 as the native names are properly spelled. So, as long as Qt has localized names the names will also be properly spelled. --- src/modules/keyboard/KeyboardPage.cpp | 2 ++ src/modules/locale/LocalePage.cpp | 9 +++++++-- src/modules/welcome/WelcomePage.cpp | 1 - 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp index 6f4473014..9056ba273 100644 --- a/src/modules/keyboard/KeyboardPage.cpp +++ b/src/modules/keyboard/KeyboardPage.cpp @@ -369,6 +369,8 @@ KeyboardPage::onActivate() { const auto langParts = lang.split( '_', QString::SkipEmptyParts ); + // Note that this his string is not fit for display purposes! + // It doesn't come from QLocale::nativeCountryName. QString country = QLocale::countryToString( QLocale( lang ).country() ); cDebug() << " .. extracted country" << country << "::" << langParts; diff --git a/src/modules/locale/LocalePage.cpp b/src/modules/locale/LocalePage.cpp index 9aad283c6..50f2d9889 100644 --- a/src/modules/locale/LocalePage.cpp +++ b/src/modules/locale/LocalePage.cpp @@ -477,8 +477,13 @@ LocalePage::prettyLCLocale( const QString& lcLocale ) const QLocale locale( localeString ); //: Language (Country) - return tr( "%1 (%2)" ).arg( QLocale::languageToString( locale.language() ) ) - .arg( QLocale::countryToString( locale.country() ) ); + const QString lang = !locale.nativeLanguageName().isEmpty() ? + locale.nativeLanguageName() : + QLocale::languageToString( locale.language() ); + const QString country = !locale.nativeCountryName().isEmpty() ? + locale.nativeCountryName() : + QLocale::countryToString( locale.country() ); + return tr( "%1 (%2)" ).arg( lang ).arg( country ); } void diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index 0a1d2fb7d..4fc44e0d5 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -345,4 +345,3 @@ WelcomePage::focusInEvent( QFocusEvent* e ) ui->languageWidget->setFocus(); e->accept(); } - From 084f4d24450b018999b97f53f3580cc69507cc5c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 14 Dec 2018 10:52:55 +0100 Subject: [PATCH 2/7] [libcalamaresui] Refactor: move LocaleLabel to UI library - This is prep-work for making locale labels consistent everywhere. - While here, improve code documentation. --- .../utils/CalamaresUtilsGui.cpp | 37 ++++++++++ src/libcalamaresui/utils/CalamaresUtilsGui.h | 65 ++++++++++++++++- src/modules/welcome/WelcomePage.cpp | 72 +------------------ 3 files changed, 103 insertions(+), 71 deletions(-) diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp index 425ee1811..41465ca02 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp @@ -266,5 +266,42 @@ clearLayout( QLayout* layout ) } } +LocaleLabel::LocaleLabel( const QString& locale ) + : m_locale( LocaleLabel::getLocale( locale ) ) + , m_localeId( locale ) +{ + QString sortKey = QLocale::languageToString( m_locale.language() ); + QString label = m_locale.nativeLanguageName(); + + if ( label.isEmpty() ) + label = QString( QLatin1Literal( "* %1 (%2)" ) ).arg( locale, sortKey ); + + if ( locale.contains( '_' ) && QLocale::countriesForLanguage( m_locale.language() ).count() > 2 ) + { + QLatin1Literal countrySuffix( " (%1)" ); + + sortKey.append( QString( countrySuffix ).arg( QLocale::countryToString( m_locale.country() ) ) ); + + // If the language name is RTL, make this parenthetical addition RTL as well. + QString countryFormat = label.isRightToLeft() ? QString( QChar( 0x202B ) ) : QString(); + countryFormat.append( countrySuffix ); + label.append( countryFormat.arg( m_locale.nativeCountryName() ) ); + } + + m_sortKey = sortKey; + m_label = label; +} + +QLocale LocaleLabel::getLocale( const QString& localeName ) +{ + if ( localeName.contains( "@latin" ) ) + { + QLocale loc( localeName ); // Ignores @latin + return QLocale( loc.language(), QLocale::Script::LatinScript, loc.country() ); + } + else + return QLocale( localeName ); +} + } diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.h b/src/libcalamaresui/utils/CalamaresUtilsGui.h index 4b041466d..1e5f283b1 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.h +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.h @@ -23,6 +23,7 @@ #include "utils/CalamaresUtils.h" #include "UiDllMacro.h" +#include #include #include @@ -125,6 +126,68 @@ constexpr int windowMinimumWidth = 800; constexpr int windowMinimumHeight = 520; constexpr int windowPreferredWidth = 1024; constexpr int windowPreferredHeight = 520; -} + +/** + * @brief Consistent locale (language + country) naming. + * + * Support class to turn locale names (as used by Calamares's + * translation system) into QLocales, and also into consistent + * human-readable text labels. + */ +class LocaleLabel : public QObject +{ + Q_OBJECT + +public: + /** @brief Construct from a locale name. + * + * The locale name should be one that Qt recognizes, e.g. en_US or ar_EY. + */ + LocaleLabel( const QString& localeName ); + + /** @brief Define a sorting order. + * + * English (@see isEnglish() -- it means en_US) is sorted at the top. + */ + bool operator <(const LocaleLabel& other) const + { + if ( isEnglish() ) + return !other.isEnglish(); + if ( other.isEnglish() ) + return false; + return m_sortKey < other.m_sortKey; + } + + /** @brief Is this locale English? + * + * en_US and en (American English) is defined as English. The Queen's + * English -- proper English -- is relegated to non-English status. + */ + bool isEnglish() const + { + return m_localeId == QLatin1Literal( "en_US" ) || m_localeId == QLatin1Literal( "en" ); + } + + /** @brief Get the human-readable name for this locale. */ + QString label() const { return m_label; } + /** @brief Get the Qt locale. */ + QLocale locale() const { return m_locale; } + + /** @brief Get a Qt locale for the given @p localeName + * + * This special-cases `sr@latin`, which is used as a translation + * name in Calamares, while Qt recognizes `sr@latn`. + */ + static QLocale getLocale( const QString& localeName ); + +protected: + QLocale m_locale; + QString m_localeId; // the locale identifier, e.g. "en_GB" + QString m_sortKey; // the English name of the locale + QString m_label; // the native name of the locale +} ; + + +} // namespace CalamaresUtils #endif // CALAMARESUTILSGUI_H diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index 4fc44e0d5..8ffb153bf 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -132,74 +132,6 @@ bool matchLocale( QComboBox& list, QLocale& matchFound, std::function 2 ) - { - QLatin1Literal countrySuffix( " (%1)" ); - - sortKey.append( QString( countrySuffix ).arg( QLocale::countryToString( m_locale.country() ) ) ); - - // If the language name is RTL, make this parenthetical addition RTL as well. - QString countryFormat = label.isRightToLeft() ? QString( QChar( 0x202B ) ) : QString(); - countryFormat.append( countrySuffix ); - label.append( countryFormat.arg( m_locale.nativeCountryName() ) ); - } - - m_sortKey = sortKey; - m_label = label; - } - - QLocale m_locale; - QString m_localeId; // the locale identifier, e.g. "en_GB" - QString m_sortKey; // the English name of the locale - QString m_label; // the native name of the locale - - /** @brief Define a sorting order. - * - * English (@see isEnglish() -- it means en_US) is sorted at the top. - */ - bool operator <(const LocaleLabel& other) const - { - if ( isEnglish() ) - return !other.isEnglish(); - if ( other.isEnglish() ) - return false; - return m_sortKey < other.m_sortKey; - } - - /** @brief Is this locale English? - * - * en_US and en (American English) is defined as English. The Queen's - * English -- proper English -- is relegated to non-English status. - */ - bool isEnglish() const - { - return m_localeId == QLatin1Literal( "en_US" ) || m_localeId == QLatin1Literal( "en" ); - } - - static QLocale getLocale( const QString& localeName ) - { - if ( localeName.contains( "@latin" ) ) - { - QLocale loc( localeName ); - return QLocale( loc.language(), QLocale::Script::LatinScript, loc.country() ); - } - else - return QLocale( localeName ); - } -} ; - void WelcomePage::initLanguages() { @@ -208,7 +140,7 @@ WelcomePage::initLanguages() ui->languageWidget->setInsertPolicy( QComboBox::InsertAtBottom ); { - std::list< LocaleLabel > localeList; + std::list< CalamaresUtils::LocaleLabel > localeList; const auto locales = QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';'); for ( const QString& locale : locales ) { @@ -219,7 +151,7 @@ WelcomePage::initLanguages() for ( const auto& locale : localeList ) { - ui->languageWidget->addItem( locale.m_label, locale.m_locale ); + ui->languageWidget->addItem( locale.label(), locale.locale() ); } } From 1f4ac45bb5d6ad4712109bd126a33cf306d35e9d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 14 Dec 2018 11:22:47 +0100 Subject: [PATCH 3/7] [libcalamaresui] Cleanup locale-labeling code - Support translations of the "language (country)" format instead of forcing English parenthesis. --- .../utils/CalamaresUtilsGui.cpp | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp index 41465ca02..5e4b8e069 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp @@ -270,26 +270,27 @@ LocaleLabel::LocaleLabel( const QString& locale ) : m_locale( LocaleLabel::getLocale( locale ) ) , m_localeId( locale ) { + QString longFormat = tr( "%1 (%2)", "Language (Country)" ); + QString sortKey = QLocale::languageToString( m_locale.language() ); - QString label = m_locale.nativeLanguageName(); + QString languageName = m_locale.nativeLanguageName(); + QString countryName; - if ( label.isEmpty() ) - label = QString( QLatin1Literal( "* %1 (%2)" ) ).arg( locale, sortKey ); + if ( languageName.isEmpty() ) + languageName = QString( QLatin1Literal( "* %1 (%2)" ) ).arg( locale, sortKey ); - if ( locale.contains( '_' ) && QLocale::countriesForLanguage( m_locale.language() ).count() > 2 ) - { - QLatin1Literal countrySuffix( " (%1)" ); + bool needsCountryName = locale.contains( '_' ) && QLocale::countriesForLanguage( m_locale.language() ).count() > 2; - sortKey.append( QString( countrySuffix ).arg( QLocale::countryToString( m_locale.country() ) ) ); + if ( needsCountryName ) + { + sortKey.append( '+' ); + sortKey.append( QLocale::countryToString( m_locale.country() ) ); - // If the language name is RTL, make this parenthetical addition RTL as well. - QString countryFormat = label.isRightToLeft() ? QString( QChar( 0x202B ) ) : QString(); - countryFormat.append( countrySuffix ); - label.append( countryFormat.arg( m_locale.nativeCountryName() ) ); + countryName = m_locale.nativeCountryName(); } m_sortKey = sortKey; - m_label = label; + m_label = needsCountryName ? longFormat.arg( languageName ).arg( countryName ) : languageName; } QLocale LocaleLabel::getLocale( const QString& localeName ) From 3dda9ab860f1d2aec92e505465f4bc1c97d6d664 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 14 Dec 2018 11:30:05 +0100 Subject: [PATCH 4/7] [libcalamaresui] LocaleLabel doesn't need to inherit QObject - Use static QObject::tr instead. --- src/libcalamaresui/utils/CalamaresUtilsGui.cpp | 2 +- src/libcalamaresui/utils/CalamaresUtilsGui.h | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp index 5e4b8e069..803e1b050 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp @@ -270,7 +270,7 @@ LocaleLabel::LocaleLabel( const QString& locale ) : m_locale( LocaleLabel::getLocale( locale ) ) , m_localeId( locale ) { - QString longFormat = tr( "%1 (%2)", "Language (Country)" ); + QString longFormat = QObject::tr( "%1 (%2)", "Language (Country)" ); QString sortKey = QLocale::languageToString( m_locale.language() ); QString languageName = m_locale.nativeLanguageName(); diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.h b/src/libcalamaresui/utils/CalamaresUtilsGui.h index 1e5f283b1..9cbc7a4a3 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.h +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.h @@ -134,10 +134,8 @@ constexpr int windowPreferredHeight = 520; * translation system) into QLocales, and also into consistent * human-readable text labels. */ -class LocaleLabel : public QObject +class LocaleLabel { - Q_OBJECT - public: /** @brief Construct from a locale name. * From 8790985fca581469b96b61cb71f1c631a2291b2a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 14 Dec 2018 11:33:13 +0100 Subject: [PATCH 5/7] [libcalamaresui] Code-formatting, remove dead code --- src/libcalamaresui/utils/CalamaresUtilsGui.cpp | 8 ++------ src/libcalamaresui/utils/CalamaresUtilsGui.h | 14 ++++++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp index 803e1b050..789b41c4f 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp @@ -170,11 +170,7 @@ createRoundedImage( const QPixmap& pixmap, const QSize& size, float frameWidthPc painter.setBrush( brush ); painter.setPen( pen ); - painter.drawRoundedRect( outerRect, qreal(frameWidthPct) * 100.0, qreal(frameWidthPct) * 100.0, Qt::RelativeSize ); - -/* painter.setBrush( Qt::transparent ); - painter.setPen( Qt::white ); - painter.drawRoundedRect( outerRect, frameWidthPct, frameWidthPct, Qt::RelativeSize ); */ + painter.drawRoundedRect( outerRect, qreal( frameWidthPct ) * 100.0, qreal( frameWidthPct ) * 100.0, Qt::RelativeSize ); return frame; } @@ -246,7 +242,7 @@ setDefaultFontSize( int points ) QSize defaultIconSize() { - const int w = int(defaultFontHeight() * 1.6); + const int w = int( defaultFontHeight() * 1.6 ); return QSize( w, w ); } diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.h b/src/libcalamaresui/utils/CalamaresUtilsGui.h index 9cbc7a4a3..e75eee210 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.h +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.h @@ -147,7 +147,7 @@ public: * * English (@see isEnglish() -- it means en_US) is sorted at the top. */ - bool operator <(const LocaleLabel& other) const + bool operator <( const LocaleLabel& other ) const { if ( isEnglish() ) return !other.isEnglish(); @@ -163,13 +163,19 @@ public: */ bool isEnglish() const { - return m_localeId == QLatin1Literal( "en_US" ) || m_localeId == QLatin1Literal( "en" ); + return m_localeId == QLatin1Literal( "en_US" ) || m_localeId == QLatin1Literal( "en" ); } /** @brief Get the human-readable name for this locale. */ - QString label() const { return m_label; } + QString label() const + { + return m_label; + } /** @brief Get the Qt locale. */ - QLocale locale() const { return m_locale; } + QLocale locale() const + { + return m_locale; + } /** @brief Get a Qt locale for the given @p localeName * From 210965aca48dac26837335f1d7538fc4a6fc5183 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 14 Dec 2018 13:20:32 +0100 Subject: [PATCH 6/7] [libcalamaresui] Allow always-show-country setting in locale label --- src/libcalamaresui/utils/CalamaresUtilsGui.cpp | 5 +++-- src/libcalamaresui/utils/CalamaresUtilsGui.h | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp index 789b41c4f..a7783af3e 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp @@ -262,7 +262,7 @@ clearLayout( QLayout* layout ) } } -LocaleLabel::LocaleLabel( const QString& locale ) +LocaleLabel::LocaleLabel( const QString& locale, LabelFormat format ) : m_locale( LocaleLabel::getLocale( locale ) ) , m_localeId( locale ) { @@ -275,7 +275,8 @@ LocaleLabel::LocaleLabel( const QString& locale ) if ( languageName.isEmpty() ) languageName = QString( QLatin1Literal( "* %1 (%2)" ) ).arg( locale, sortKey ); - bool needsCountryName = locale.contains( '_' ) && QLocale::countriesForLanguage( m_locale.language() ).count() > 2; + bool needsCountryName = ( format == LabelFormat::AlwaysWithCountry ) || + (locale.contains( '_' ) && QLocale::countriesForLanguage( m_locale.language() ).count() > 1 ); if ( needsCountryName ) { diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.h b/src/libcalamaresui/utils/CalamaresUtilsGui.h index e75eee210..6a036b218 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.h +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.h @@ -137,11 +137,16 @@ constexpr int windowPreferredHeight = 520; class LocaleLabel { public: + /** @brief Formatting option for label -- add (country) to label. */ + enum class LabelFormat { AlwaysWithCountry, IfNeededWithCountry } ; + /** @brief Construct from a locale name. * - * The locale name should be one that Qt recognizes, e.g. en_US or ar_EY. + * The @p localeName should be one that Qt recognizes, e.g. en_US or ar_EY. + * The @p format determines whether the country name is always present + * in the label (human-readable form) or only if needed for disambiguation. */ - LocaleLabel( const QString& localeName ); + LocaleLabel( const QString& localeName, LabelFormat format = LabelFormat::IfNeededWithCountry ); /** @brief Define a sorting order. * From 56a71c232f73113843272bc85bfb7ee904379d21 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 14 Dec 2018 13:27:32 +0100 Subject: [PATCH 7/7] [locale] Use the re-factored LocaleLabel --- src/modules/locale/LocalePage.cpp | 31 ++++++++----------------------- src/modules/locale/LocalePage.h | 1 - 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/src/modules/locale/LocalePage.cpp b/src/modules/locale/LocalePage.cpp index 50f2d9889..ea77d6b9f 100644 --- a/src/modules/locale/LocalePage.cpp +++ b/src/modules/locale/LocalePage.cpp @@ -21,6 +21,7 @@ #include "timezonewidget/timezonewidget.h" #include "SetTimezoneJob.h" +#include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" #include "utils/Retranslator.h" #include "GlobalStorage.h" @@ -383,12 +384,14 @@ LocalePage::init( const QString& initialRegion, std::pair< QString, QString > LocalePage::prettyLocaleStatus( const LocaleConfiguration& lc ) const { + using CalamaresUtils::LocaleLabel; + + LocaleLabel lang( lc.lang, LocaleLabel::LabelFormat::AlwaysWithCountry ); + LocaleLabel num( lc.lc_numeric, LocaleLabel::LabelFormat::AlwaysWithCountry ); + return std::make_pair< QString, QString >( - tr( "The system language will be set to %1." ) - .arg( prettyLCLocale( lc.lang ) ), - tr( "The numbers and dates locale will be set to %1." ) - .arg( prettyLCLocale( lc.lc_numeric ) ) - ); + tr( "The system language will be set to %1." ).arg( lang.label() ), + tr( "The numbers and dates locale will be set to %1." ).arg( num.label() ) ); } QString @@ -468,24 +471,6 @@ LocalePage::guessLocaleConfiguration() const } -QString -LocalePage::prettyLCLocale( const QString& lcLocale ) const -{ - QString localeString = lcLocale; - if ( localeString.endsWith( " UTF-8" ) ) - localeString.remove( " UTF-8" ); - - QLocale locale( localeString ); - //: Language (Country) - const QString lang = !locale.nativeLanguageName().isEmpty() ? - locale.nativeLanguageName() : - QLocale::languageToString( locale.language() ); - const QString country = !locale.nativeCountryName().isEmpty() ? - locale.nativeCountryName() : - QLocale::countryToString( locale.country() ); - return tr( "%1 (%2)" ).arg( lang ).arg( country ); -} - void LocalePage::updateGlobalStorage() { diff --git a/src/modules/locale/LocalePage.h b/src/modules/locale/LocalePage.h index c4ca20503..fae16cfb9 100644 --- a/src/modules/locale/LocalePage.h +++ b/src/modules/locale/LocalePage.h @@ -51,7 +51,6 @@ public: private: LocaleConfiguration guessLocaleConfiguration() const; - QString prettyLCLocale( const QString& localesMap ) const; // For the given locale config, return two strings describing // the settings for language and numbers.