diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2023-03-05 11:06:29 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2023-03-05 14:11:00 +0000 |
commit | e7ae5b4793fb74309d5d1f32c3c696d07071d676 (patch) | |
tree | af9371ce218b6dadec83d45622b5db93248c7e30 /linguistic/source | |
parent | 8400b7d05dafadca2eec85c620f5955ab353eaaf (diff) |
tdf#152459: fallback to language-only when looking for grammar checker
LanguageTool registers itself for languages like "en-US", "es-AR", "de-DE";
but also for generic "en", "es", "de". When the requested language, like
"fr-CH" or "es-PH", is not found in the registered grammar checkers, the
fallback strings will be attempted.
Change-Id: Id460db8d378f246ea98191d22bdb3537fd1aee1c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148201
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'linguistic/source')
-rw-r--r-- | linguistic/source/gciterator.cxx | 49 | ||||
-rw-r--r-- | linguistic/source/gciterator.hxx | 14 |
2 files changed, 44 insertions, 19 deletions
diff --git a/linguistic/source/gciterator.cxx b/linguistic/source/gciterator.cxx index 5bca138e6517..a43a990a886f 100644 --- a/linguistic/source/gciterator.cxx +++ b/linguistic/source/gciterator.cxx @@ -488,8 +488,30 @@ void GrammarCheckingIterator::ProcessResult( } +std::pair<OUString, std::optional<OUString>> +GrammarCheckingIterator::getServiceForLocale(const lang::Locale& rLocale) const +{ + if (!rLocale.Language.isEmpty()) + { + const OUString sBcp47 = LanguageTag::convertToBcp47(rLocale, false); + GCImplNames_t::const_iterator aLangIt(m_aGCImplNamesByLang.find(sBcp47)); + if (aLangIt != m_aGCImplNamesByLang.end()) + return { aLangIt->second, {} }; + + for (const auto& sFallbackBcp47 : LanguageTag(rLocale).getFallbackStrings(false)) + { + aLangIt = m_aGCImplNamesByLang.find(sFallbackBcp47); + if (aLangIt != m_aGCImplNamesByLang.end()) + return { aLangIt->second, sFallbackBcp47 }; + } + } + + return {}; +} + + uno::Reference< linguistic2::XProofreader > GrammarCheckingIterator::GetGrammarChecker( - const lang::Locale &rLocale ) + lang::Locale &rLocale ) { uno::Reference< linguistic2::XProofreader > xRes; @@ -503,11 +525,11 @@ uno::Reference< linguistic2::XProofreader > GrammarCheckingIterator::GetGrammarC m_bGCServicesChecked = true; } - const LanguageType nLang = LanguageTag::convertToLanguageType( rLocale, false); - GCImplNames_t::const_iterator aLangIt( m_aGCImplNamesByLang.find( nLang ) ); - if (aLangIt != m_aGCImplNamesByLang.end()) // matching configured language found? + if (const auto& [aSvcImplName, oFallbackBcp47] = getServiceForLocale(rLocale); + !aSvcImplName.isEmpty()) // matching configured language found? { - OUString aSvcImplName( aLangIt->second ); + if (oFallbackBcp47) + rLocale = LanguageTag::convertToLocale(*oFallbackBcp47, false); GCReferences_t::const_iterator aImplNameIt( m_aGCReferencesByService.find( aSvcImplName ) ); if (aImplNameIt != m_aGCReferencesByService.end()) // matching impl name found? { @@ -1088,8 +1110,7 @@ void GrammarCheckingIterator::GetConfiguredGCSvcs_Impl() { // only the first entry is used, there should be only one grammar checker per language const OUString aImplName( aImplNames[0] ); - const LanguageType nLang = LanguageTag::convertToLanguageType( rElementName ); - aTmpGCImplNamesByLang[ nLang ] = aImplName; + aTmpGCImplNamesByLang[rElementName] = aImplName; } } else @@ -1137,17 +1158,17 @@ void GrammarCheckingIterator::SetServiceList( { ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); - LanguageType nLanguage = LinguLocaleToLanguage( rLocale ); + OUString sBcp47 = LanguageTag::convertToBcp47(rLocale, false); OUString aImplName; if (rSvcImplNames.hasElements()) aImplName = rSvcImplNames[0]; // there is only one grammar checker per language - if (!LinguIsUnspecified(nLanguage) && nLanguage != LANGUAGE_DONTKNOW) + if (!LinguIsUnspecified(sBcp47) && !sBcp47.isEmpty()) { if (!aImplName.isEmpty()) - m_aGCImplNamesByLang[ nLanguage ] = aImplName; + m_aGCImplNamesByLang[sBcp47] = aImplName; else - m_aGCImplNamesByLang.erase( nLanguage ); + m_aGCImplNamesByLang.erase(sBcp47); } } @@ -1157,11 +1178,7 @@ uno::Sequence< OUString > GrammarCheckingIterator::GetServiceList( { ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); - OUString aImplName; // there is only one grammar checker per language - LanguageType nLang = LinguLocaleToLanguage( rLocale ); - GCImplNames_t::const_iterator aIt( m_aGCImplNamesByLang.find( nLang ) ); - if (aIt != m_aGCImplNamesByLang.end()) - aImplName = aIt->second; + const OUString aImplName = getServiceForLocale(rLocale).first; // there is only one grammar checker per language if (!aImplName.isEmpty()) return { aImplName }; diff --git a/linguistic/source/gciterator.hxx b/linguistic/source/gciterator.hxx index f35c8b412ef9..18984d398165 100644 --- a/linguistic/source/gciterator.hxx +++ b/linguistic/source/gciterator.hxx @@ -39,6 +39,8 @@ #include <i18nlangtag/lang.h> #include <map> +#include <optional> +#include <utility> #include <deque> #include "defs.hxx" @@ -96,8 +98,8 @@ class GrammarCheckingIterator: DocMap_t m_aDocIdMap; - // language -> implname mapping - typedef std::map< LanguageType, OUString > GCImplNames_t; + // BCP-47 language tag -> implname mapping + typedef std::map< OUString, OUString > GCImplNames_t; GCImplNames_t m_aGCImplNamesByLang; // implname -> UNO reference mapping @@ -135,13 +137,19 @@ class GrammarCheckingIterator: sal_Int32 GetSuggestedEndOfSentence( const OUString &rText, sal_Int32 nSentenceStartPos, const css::lang::Locale &rLocale ); void GetConfiguredGCSvcs_Impl(); - css::uno::Reference< css::linguistic2::XProofreader > GetGrammarChecker( const css::lang::Locale & rLocale ); + css::uno::Reference< css::linguistic2::XProofreader > GetGrammarChecker( css::lang::Locale & rLocale ); css::uno::Reference< css::util::XChangesBatch > const & GetUpdateAccess() const; GrammarCheckingIterator( const GrammarCheckingIterator & ) = delete; GrammarCheckingIterator & operator = ( const GrammarCheckingIterator & ) = delete; + // Gets the grammar checker service, using fallback locales if necessary, + // and the BCP-47 tag for the updated locale, if the fallback was used. + // Precondition: MyMutex() is locked. + std::pair<OUString, std::optional<OUString>> + getServiceForLocale(const css::lang::Locale& rLocale) const; + public: void DequeueAndCheck(); |