svx/source/dialog/langbox.cxx | 44 +++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-)
New commits: commit 9b03f778adfb87a10d781860930ed4d09410af9c Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Jun 6 14:12:38 2023 +0300 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Tue Jun 6 17:52:32 2023 +0200 Language list: sort generic language before country variants In Edit Modules dialog, the language list may include entries added by LanguageTool, and among them are generic language-only entries like "Spanish {es}", stanfing for simple language tags like "es". These languages should go before country variants like "Spanish (Argentina)", but since "{" is sorted after "(", the order is the opposite. This change fixes this. Since other lists do not include generic language-only languages (filtered out by lcl_isPrerequisite and its requireSublang argument), this does not apply to them, but the code will execute nevertheless; hope that this UI-only performance hit will not be noticeable. Change-Id: I97adc1ae8feb4c8a94b567b33363d63d899cabaa Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152676 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/svx/source/dialog/langbox.cxx b/svx/source/dialog/langbox.cxx index fae7cf66e8d8..e552f68cc749 100644 --- a/svx/source/dialog/langbox.cxx +++ b/svx/source/dialog/langbox.cxx @@ -190,16 +190,42 @@ void SvxLanguageBox::AddLanguages(const std::vector< LanguageType >& rLanguageTy static void SortLanguages(std::vector<weld::ComboBoxEntry>& rEntries) { - std::sort(rEntries.begin(), rEntries.end(), - [](const weld::ComboBoxEntry e1, const weld::ComboBoxEntry e2) - { - static const auto aSorter = comphelper::string::NaturalStringSorter( - ::comphelper::getProcessComponentContext(), - Application::GetSettings().GetUILanguageTag().getLocale()); - return aSorter.compare(e1.sString, e2.sString) < 0; - }); + auto langLess = [](const weld::ComboBoxEntry& e1, const weld::ComboBoxEntry& e2) + { + if (e1.sId == e2.sId) + return false; // shortcut + // Make sure that e.g. generic 'Spanish {es}' goes before 'Spanish (Argentina)'. + // We can't depend on MsLangId::getPrimaryLanguage/getSubLanguage, because e.g. + // for generic Bosnian {bs}, the MS-LCID is 0x781A, and getSubLanguage is not 0. + // So we have to do the expensive LanguageTag construction. + LanguageTag lt1(LanguageType(e1.sId.toInt32())), lt2(LanguageType(e2.sId.toInt32())); + if (lt1.getLanguage() == lt2.getLanguage()) + { + const bool isLangOnly1 = lt1.isIsoLocale() && lt1.getCountry().isEmpty(); + const bool isLangOnly2 = lt2.isIsoLocale() && lt2.getCountry().isEmpty(); + + if (isLangOnly1) + { + // lt1 is a generic language-only tag + if (!isLangOnly2) + return true; // lt2 is not + } + else if (isLangOnly2) + { + // lt2 is a generic language-only tag, lt1 is not + return false; + } + } + // Do a normal string comparison for other cases + static const auto aSorter = comphelper::string::NaturalStringSorter( + comphelper::getProcessComponentContext(), + Application::GetSettings().GetUILanguageTag().getLocale()); + return aSorter.compare(e1.sString, e2.sString) < 0; + }; + + std::sort(rEntries.begin(), rEntries.end(), langLess); rEntries.erase(std::unique(rEntries.begin(), rEntries.end(), - [](const weld::ComboBoxEntry e1, const weld::ComboBoxEntry e2) + [](const weld::ComboBoxEntry& e1, const weld::ComboBoxEntry& e2) { return e1.sId == e2.sId; }), rEntries.end()); }