include/sfx2/lokhelper.hxx | 2 include/sfx2/viewsh.hxx | 6 ++ sc/qa/unit/tiledrendering/data/pivotfr.ods |binary sc/qa/unit/tiledrendering/tiledrendering.cxx | 52 ++++++++++++++++++++ sc/source/core/data/global.cxx | 11 ++++ sc/source/ui/docshell/docsh4.cxx | 69 +++++++++++++++++++++------ sc/source/ui/inc/docsh.hxx | 2 sc/source/ui/view/tabvwsh4.cxx | 11 ++++ sfx2/source/view/lokhelper.cxx | 21 ++++++++ sfx2/source/view/viewsh.cxx | 20 +++++++ 10 files changed, 179 insertions(+), 15 deletions(-)
New commits: commit f2d52fd83a1d4fd42c90780357c1552dbed605b4 Author: Dennis Francis <[email protected]> AuthorDate: Sat Nov 15 23:55:25 2025 +0530 Commit: Miklos Vajna <[email protected]> CommitDate: Thu Dec 11 11:35:25 2025 +0100 lok: sc: use view specific calendar conforming to init. locale/language The aim is to allow user/view specific locale/language but we are not there yet. This patch reuses the existing .uno:LanguageStatus to maintain a view specific locale/language and a calendar based on it. One problem is that the status-change of this uno command is broadcast to all views. So if one view sets language X, all client views are forced to use X. Another issue is that changes in tiles due to one view's language settings is broadcast to all views. I'm working on fixing these in a follow-up patches. Before the patch, when a view selects a language it did not had any effect on calendar strings like month names in pivot table with date grouping even after refresh. Signed-off-by: Dennis Francis <[email protected]> Change-Id: I92198c8c1467555f27e2642de6c97b4d5e6118b3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194204 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index 148303d0bda3..1f9e65ba396e 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -141,6 +141,8 @@ public: static void setLoadLanguage(const OUString& rBcp47LanguageTag); /// Set the locale for the given view. static void setViewLocale(int nId, const OUString& rBcp47LanguageTag); + /// Set the language and locale for the given view. + static void setViewLanguageAndLocale(int nId, const OUString& rBcp47LanguageTag); /// Get the device form factor that should be used for a new view. static LOKDeviceFormFactor getDeviceFormFactor(); /// Set the device form factor that should be used for a new view. diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index 90e87bf9d006..de32c158c7bb 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -60,6 +60,7 @@ class SfxLokCallbackInterface; class LOKDocumentFocusListener; class SfxStoringHelper; class VCLXPopupMenu; +class CalendarWrapper; namespace rtl { class OStringBuffer; } namespace vcl { class PrinterController; } @@ -176,6 +177,7 @@ friend class SfxPrinterController; bool mbPrinterSettingsModified; LanguageTag maLOKLanguageTag; LanguageTag maLOKLocale; + std::unique_ptr<CalendarWrapper> mpCalendar; LOKDeviceFormFactor maLOKDeviceFormFactor; bool mbLOKAccessibilityEnabled; rtl::Reference<LOKDocumentFocusListener> mpLOKDocumentFocusListener; @@ -475,6 +477,10 @@ public: void SetLOKLocale(const OUString& rBcp47LanguageTag); /// Get the LibreOfficeKit locale of this view. const LanguageTag& GetLOKLocale() const { return maLOKLocale; } + /// Set the LibreOfficeKit locale and language of this view. + void SetLOKLanguageAndLocale(const OUString& rBcp47LanguageTag); + /// Get the LibreOfficeKit calendar of this view. + CalendarWrapper& GetLOKCalendar(); /// Get the form factor of the device where the lok client is running. LOKDeviceFormFactor GetLOKDeviceFormFactor() const { return maLOKDeviceFormFactor; } /// Check if the lok client is running on a desktop machine. diff --git a/sc/qa/unit/tiledrendering/data/pivotfr.ods b/sc/qa/unit/tiledrendering/data/pivotfr.ods new file mode 100644 index 000000000000..93f3f68e4552 Binary files /dev/null and b/sc/qa/unit/tiledrendering/data/pivotfr.ods differ diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index fc121e347220..87c4b94a55f9 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -3668,6 +3668,58 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testPrintRanges) CPPUNIT_ASSERT_EQUAL(u"{\"printranges\":[{\"sheet\":0,\"ranges\":[[2,6,2,6]]}]}"_ustr, printRanges); } +CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testLOKLanguageStatus) +{ + ScModelObj* pModelObj = createDoc("pivotfr.ods"); + CPPUNIT_ASSERT(pModelObj); + ScDocShell* pDocSh = dynamic_cast< ScDocShell* >( pModelObj->GetEmbeddedObject() ); + CPPUNIT_ASSERT(pDocSh); + ScDocument* pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + + // view #1 + SfxViewShell* pView1 = SfxViewShell::Current(); + ScTabViewShell* pView = dynamic_cast<ScTabViewShell*>(pView1); + CPPUNIT_ASSERT(pView); + + { + // Pivot table is in the same sheet and first data row starts at A17. + pView->SetCursor(0, 16); + dispatchCommand(mxComponent, u".uno:RecalcPivotTable"_ustr, {}); + + // Document language is French(France), which the view must inherit. + CPPUNIT_ASSERT_EQUAL(u"janv."_ustr, pDoc->GetString(ScAddress(0, 16, 0))); + } + + { + uno::Sequence<beans::PropertyValue> aArgs( comphelper::InitPropertySequence({ + { "Language", uno::Any(u"Default_Spanish (Spain)"_ustr) }, + })); + dispatchCommand(mxComponent, u".uno:LanguageStatus"_ustr, aArgs); + + // Pivot table is in the same sheet and first data row starts at A17. + pView->SetCursor(0, 16); + dispatchCommand(mxComponent, u".uno:RecalcPivotTable"_ustr, {}); + + // view language is now Spanish(Spain) + CPPUNIT_ASSERT_EQUAL(u"ene"_ustr, pDoc->GetString(ScAddress(0, 16, 0))); + } + + { + uno::Sequence<beans::PropertyValue> aArgs( comphelper::InitPropertySequence({ + { "Language", uno::Any(u"Default_English (USA)"_ustr) }, + })); + dispatchCommand(mxComponent, u".uno:LanguageStatus"_ustr, aArgs); + + // Pivot table is in the same sheet and first data row starts at A17. + pView->SetCursor(0, 16); + dispatchCommand(mxComponent, u".uno:RecalcPivotTable"_ustr, {}); + + // view language is now English(USA). + CPPUNIT_ASSERT_EQUAL(u"Jan"_ustr, pDoc->GetString(ScAddress(0, 16, 0))); + } +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx index ad62505d2f54..50017bd40553 100644 --- a/sc/source/core/data/global.cxx +++ b/sc/source/core/data/global.cxx @@ -1102,6 +1102,13 @@ const CharClass& ScGlobal::getCharClass() CalendarWrapper& ScGlobal::GetCalendar() { assert(!bThreadedGroupCalcInProgress); + if (comphelper::LibreOfficeKit::isActive()) + { + if (SfxViewShell* pCurr = SfxViewShell::Current()) + { + return pCurr->GetLOKCalendar(); + } + } if ( !oCalendar ) { oCalendar.emplace( ::comphelper::getProcessComponentContext() ); @@ -1149,6 +1156,10 @@ CollatorWrapper& ScGlobal::GetCollator(bool bCaseSensitive) } css::lang::Locale& ScGlobal::GetLocale() { + if (comphelper::LibreOfficeKit::isActive()) + { + return const_cast<css::lang::Locale&>(comphelper::LibreOfficeKit::getLocale().getLocale()); + } return *comphelper::doubleCheckedInit( pLocale, []() { return new css::lang::Locale( Application::GetSettings().GetLanguageTag().getLocale()); }); } diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx index eff11634d595..6e161d02a015 100644 --- a/sc/source/ui/docshell/docsh4.cxx +++ b/sc/source/ui/docshell/docsh4.cxx @@ -118,6 +118,7 @@ #include <svx/xdef.hxx> #include <editeng/lrspitem.hxx> // Defines SvxLRSpaceItem #include <editeng/ulspitem.hxx> // Defines SvxULSpaceItem +#include <sfx2/lokhelper.hxx> using namespace ::com::sun::star; @@ -239,19 +240,45 @@ IMPL_LINK( ScDocShell, ReloadAllLinksHdl, weld::Button&, rButton, void ) namespace { - class LinkHelp +class LinkHelp +{ +public: + DECL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, void); +}; + +void lcl_setLOKLanguageAndLocale(ScDocShell& rDocSh, ScTabViewShell& rViewShell, const LanguageType eLang) +{ + OUString aLang = LanguageTag(eLang).getBcp47(); + SfxLokHelper::setViewLanguageAndLocale(SfxLokHelper::getView(rViewShell), aLang); + if (SfxBindings* pBindings = rDocSh.GetViewBindings()) { - public: - DECL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, void); - }; + pBindings->Invalidate(SID_LANGUAGE_STATUS); + } } +} // end anonymous namespace + IMPL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, rBtn, void) { if (Help* pHelp = Application::GetHelp()) pHelp->Start(HID_UPDATE_LINK_WARNING, &rBtn); } +void ScDocShell::SetLanguage(LanguageType eLatin, LanguageType eCjk, LanguageType eCtl) +{ + if (comphelper::LibreOfficeKit::isActive()) + { + if (ScTabViewShell* pViewShell = GetBestViewShell()) + { + lcl_setLOKLanguageAndLocale(*this, *pViewShell, eLatin); + } + } + else + { + GetDocument().SetLanguage(eLatin, eCjk, eCtl); + } +} + void ScDocShell::Execute( SfxRequest& rReq ) { const SfxItemSet* pReqArgs = rReq.GetArgs(); @@ -1356,7 +1383,17 @@ void ScDocShell::Execute( SfxRequest& rReq ) bool bParagraph = false; ScDocument& rDoc = GetDocument(); - rDoc.GetLanguage( eLatin, eCjk, eCtl ); + if (comphelper::LibreOfficeKit::isActive()) + { + if (ScTabViewShell* pViewShell = GetBestViewShell()) + { + eLatin = pViewShell->GetLOKLocale().getLanguageType(); + } + } + else + { + rDoc.GetLanguage( eLatin, eCjk, eCtl ); + } sal_Int32 nPos = 0; if ( aLangText == "*" ) @@ -1374,19 +1411,19 @@ void ScDocShell::Execute( SfxRequest& rReq ) if ( aLangText == "LANGUAGE_NONE" ) { eLang = LANGUAGE_NONE; - rDoc.SetLanguage( eLang, eCjk, eCtl ); + SetLanguage(eLang, eCjk, eCtl); } else if ( aLangText == "RESET_LANGUAGES" ) { ScModule::GetSpellSettings(eLang, eCjk, eCtl); - rDoc.SetLanguage(eLang, eCjk, eCtl); + SetLanguage(eLang, eCjk, eCtl); } else { eLang = SvtLanguageTable::GetLanguageType( aLangText ); if ( eLang != LANGUAGE_DONTKNOW && SvtLanguageOptions::GetScriptTypeOfLanguage(eLang) == SvtScriptType::LATIN ) { - rDoc.SetLanguage( eLang, eCjk, eCtl ); + SetLanguage(eLang, eCjk, eCtl); } else { @@ -2537,13 +2574,15 @@ void ScDocShell::GetState( SfxItemSet &rSet ) if (comphelper::LibreOfficeKit::isActive()) { - GetDocument().GetLanguage( eLatin, eCjk, eCtl ); - sLanguage = SvtLanguageTable::GetLanguageString(eLatin); - - if (eLatin == LANGUAGE_NONE) - sLanguage += ";-"; - else - sLanguage += ";" + LanguageTag(eLatin).getBcp47(false); + if (ScTabViewShell* pViewShell = GetBestViewShell()) + { + eLatin = pViewShell->GetLOKLocale().getLanguageType(); + sLanguage = SvtLanguageTable::GetLanguageString(eLatin); + if (eLatin == LANGUAGE_NONE) + sLanguage += ";-"; + else + sLanguage += ";" + LanguageTag(eLatin).getBcp47(false); + } } else if (ScTabViewShell* pViewShell = GetBestViewShell()) { diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx index f24fcc03aa3f..1ec7fb13b482 100644 --- a/sc/source/ui/inc/docsh.hxx +++ b/sc/source/ui/inc/docsh.hxx @@ -443,6 +443,8 @@ private: const OUString& rChartName, const ScRangeListRef& rRangeListRef, bool bColHeaders, bool bRowHeaders, bool bAddRange, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab); + + void SetLanguage(LanguageType eLatin, LanguageType eCjk, LanguageType eCtl); }; void UpdateAcceptChangesDialog(); diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx index 8b9fd25159ce..bf43d7191fed 100644 --- a/sc/source/ui/view/tabvwsh4.cxx +++ b/sc/source/ui/view/tabvwsh4.cxx @@ -2185,6 +2185,17 @@ ScTabViewShell::ScTabViewShell( SfxViewFrame& rViewFrame, if (!comphelper::LibreOfficeKit::isActive()) return; + { + // Set the default locale/language of a new view to the document + // language. + ScDocShell* pDocShell = GetViewData().GetDocShell(); + ScDocument& rDoc = pDocShell->GetDocument(); + LanguageType eLatin, eCjk, eCtl; + rDoc.GetLanguage(eLatin, eCjk, eCtl); + OUString aLang = LanguageTag(eLatin).getBcp47(); + SetLOKLanguageAndLocale(aLang); + } + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); // have we already one view ? if (!pViewShell) diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 9348d7fe2856..d0b7fa7ec55b 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -420,6 +420,27 @@ void SfxLokHelper::setViewLanguage(int nId, const OUString& rBcp47LanguageTag) } } +void SfxLokHelper::setViewLanguageAndLocale(int nId, const OUString& rBcp47LanguageTag) +{ + std::vector<SfxViewShell*>& rViewArr = SfxGetpApp()->GetViewShells_Impl(); + + for (SfxViewShell* pViewShell : rViewArr) + { + if (pViewShell->GetViewShellId() == ViewShellId(nId)) + { + pViewShell->SetLOKLanguageAndLocale(rBcp47LanguageTag); + // sync also global getter if we are the current view + bool bIsCurrShell = (pViewShell == SfxViewShell::Current()); + if (bIsCurrShell) + { + comphelper::LibreOfficeKit::setLanguageTag(LanguageTag(rBcp47LanguageTag)); + comphelper::LibreOfficeKit::setLocale(LanguageTag(rBcp47LanguageTag)); + } + return; + } + } +} + void SfxLokHelper::setViewReadOnly(int nId, bool readOnly) { std::vector<SfxViewShell*>& rViewArr = SfxGetpApp()->GetViewShells_Impl(); diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx index 6b66cad338ac..c7e8cc6259a2 100644 --- a/sfx2/source/view/viewsh.cxx +++ b/sfx2/source/view/viewsh.cxx @@ -112,6 +112,7 @@ #include <list> #include <libxml/xmlwriter.h> #include <toolkit/awt/vclxmenu.hxx> +#include <unotools/calendarwrapper.hxx> #include <unordered_map> #include <unordered_set> @@ -3527,6 +3528,25 @@ void SfxViewShell::SetLOKLocale(const OUString& rBcp47LanguageTag) } } +void SfxViewShell::SetLOKLanguageAndLocale(const OUString& rBcp47LanguageTag) +{ + SetLOKLanguageTag(rBcp47LanguageTag); + SetLOKLocale(rBcp47LanguageTag); + mpCalendar = std::make_unique<CalendarWrapper>(::comphelper::getProcessComponentContext()); + mpCalendar->loadDefaultCalendar(GetLOKLocale().getLocale()); +} + +CalendarWrapper& SfxViewShell::GetLOKCalendar() +{ + if (!mpCalendar) + { + mpCalendar = std::make_unique<CalendarWrapper>(::comphelper::getProcessComponentContext()); + mpCalendar->loadDefaultCalendar( GetLOKLocale().getLocale() ); + } + + return *mpCalendar; +} + void SfxViewShell::NotifyCursor(SfxViewShell* /*pViewShell*/) const { }
