diff --git a/src/modules/locale/LocaleNames.cpp b/src/modules/locale/LocaleNames.cpp index 148d214725cf841c0ad56370134be94ba13a8d31..93e8444461d51a1ec8ecf291f2b36f14c3089dd8 100644 --- a/src/modules/locale/LocaleNames.cpp +++ b/src/modules/locale/LocaleNames.cpp @@ -70,3 +70,21 @@ LocaleNameParts::name() const + insertLeadingChar( '@', region ); } } + + +int +LocaleNameParts::similarity( const LocaleNameParts& other ) const +{ + if ( !isValid() || !other.isValid() ) + { + return 0; + } + if ( language != other.language ) + { + return 0; + } + const auto matched_region = ( region == other.region ? 30 : 0 ); + const auto matched_country = ( country == other.country ? 20 : 0 ); + const auto no_other_country_given = ( ( country != other.country && other.country.isEmpty() ) ? 10 : 0 ); + return 50 + matched_region + matched_country + no_other_country_given; +} diff --git a/src/modules/locale/LocaleNames.h b/src/modules/locale/LocaleNames.h index 976ee20b3a5fe0231e3629c327649c1ed07657fe..247a8496c2065fb587696cbe65097ffb47d4f93b 100644 --- a/src/modules/locale/LocaleNames.h +++ b/src/modules/locale/LocaleNames.h @@ -30,6 +30,14 @@ struct LocaleNameParts QString name() const; static LocaleNameParts fromName( const QString& name ); + + /** @brief Compute similarity-score with another locale-name. + * + * Similarity is driven by language and region, then country. + * Returns a number between 0 (no similarity, e.g. the + * language is different) and 100 (complete match). + */ + int similarity( const LocaleNameParts& other ) const; }; #endif diff --git a/src/modules/locale/Tests.cpp b/src/modules/locale/Tests.cpp index 85ec340262fdf87ae6a4b5145b9b323e14a9a29b..fda58059acd84700ebb8e798013f4fcce1fc2c64 100644 --- a/src/modules/locale/Tests.cpp +++ b/src/modules/locale/Tests.cpp @@ -59,6 +59,7 @@ private Q_SLOTS: void testLanguageMappingNeon(); void testLanguageMappingFreeBSD_data(); void testLanguageMappingFreeBSD(); + void testLanguageSimilarity(); private: QStringList m_KDEneonLocales; @@ -536,6 +537,45 @@ LocaleTests::testLocaleNameParts() } } +void +LocaleTests::testLanguageSimilarity() +{ + // Empty + { + QCOMPARE( LocaleNameParts().similarity( LocaleNameParts() ), 0 ); + } + // Some simple Dutch situations + { + auto nl_parts = LocaleNameParts::fromName( QStringLiteral( "nl_NL.UTF-8" ) ); + auto be_parts = LocaleNameParts::fromName( QStringLiteral( "nl_BE.UTF-8" ) ); + auto nl_short_parts = LocaleNameParts::fromName( QStringLiteral( "nl" ) ); + QCOMPARE( nl_parts.similarity( nl_parts ), 100 ); + QCOMPARE( nl_parts.similarity( LocaleNameParts() ), 0 ); + QCOMPARE( nl_parts.similarity( be_parts ), 80 ); // Language + (empty) region match + QCOMPARE( nl_parts.similarity( nl_short_parts ), 90 ); + } + + // Everything matches itself + { + if ( m_KDEneonLocales.isEmpty() ) + { + testKDENeonLanguageData(); + } + QVERIFY( !m_FreeBSDLocales.isEmpty() ); + QVERIFY( !m_KDEneonLocales.isEmpty() ); + for ( const auto& l : m_KDEneonLocales ) + { + auto locale_name = LocaleNameParts::fromName( l ); + auto self_similarity = locale_name.similarity( locale_name ); + if ( self_similarity != 100 ) + { + cDebug() << "Locale" << l << "is unusual."; + } + QCOMPARE( self_similarity, 100 ); + } + } +} + #include "utils/moc-warnings.h"