summaryrefslogtreecommitdiff
path: root/linguistic
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2023-03-05 11:06:29 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2023-03-05 14:11:00 +0000
commite7ae5b4793fb74309d5d1f32c3c696d07071d676 (patch)
treeaf9371ce218b6dadec83d45622b5db93248c7e30 /linguistic
parent8400b7d05dafadca2eec85c620f5955ab353eaaf (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')
-rw-r--r--linguistic/source/gciterator.cxx49
-rw-r--r--linguistic/source/gciterator.hxx14
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();