linguistic/source/translate.cxx | 1 sw/source/ui/misc/translatelangselect.cxx | 46 ++++----------------------- sw/source/uibase/inc/translatehelper.hxx | 17 +++------ sw/source/uibase/inc/translatelangselect.hxx | 4 -- sw/source/uibase/shells/textsh1.cxx | 23 +------------ sw/source/uibase/shells/translatehelper.cxx | 42 ++++++++++++++++++------ 6 files changed, 49 insertions(+), 84 deletions(-)
New commits: commit 72e690af9644679a59422b0d917ca35989af0885 Author: Mike Kaganski <[email protected]> AuthorDate: Tue Dec 23 16:06:15 2025 +0500 Commit: Mike Kaganski <[email protected]> CommitDate: Sun Dec 28 12:09:54 2025 +0100 Move DeepL configuration check into SwTranslateHelper Avoids code duplication, and makes the API simpler. Change-Id: I63ec590cfce35c6ffe7dfdc647b566a8f15fbc4e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196258 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> diff --git a/sw/source/ui/misc/translatelangselect.cxx b/sw/source/ui/misc/translatelangselect.cxx index 15a2a406ad3f..d8f76be757b8 100644 --- a/sw/source/ui/misc/translatelangselect.cxx +++ b/sw/source/ui/misc/translatelangselect.cxx @@ -17,28 +17,12 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <sal/config.h> + #include <vcl/svapp.hxx> -#include <osl/diagnose.h> #include <uitool.hxx> -#include <swtypes.hxx> -#include <wrtsh.hxx> -#include <view.hxx> -#include <viewopt.hxx> #include <translatelangselect.hxx> -#include <pagedesc.hxx> -#include <poolfmt.hxx> -#include <o3tl/string_view.hxx> -#include <sal/log.hxx> -#include <ndtxt.hxx> -#include <shellio.hxx> -#include <vcl/idle.hxx> -#include <mdiexp.hxx> -#include <strings.hrc> -#include <com/sun/star/task/XStatusIndicator.hpp> -#include <sfx2/viewfrm.hxx> -#include <com/sun/star/task/XStatusIndicatorFactory.hpp> -#include <linguistic/translate.hxx> -#include <officecfg/Office/Linguistic.hxx> +#include <translatehelper.hxx> static const std::vector<SwLanguageListItem>& getLanguageVec() { @@ -136,30 +120,14 @@ IMPL_LINK_NOARG(SwTranslateLangSelectDlg, LangSelectTranslateHdl, weld::Button&, return; } - std::optional<OUString> oDeeplAPIUrl - = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get(); - std::optional<OUString> oDeeplKey - = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get(); - auto sApiUrlTrimmed = oDeeplAPIUrl ? o3tl::trim(*oDeeplAPIUrl) : std::u16string_view(); - auto sKeyTrimmed = oDeeplKey ? o3tl::trim(*oDeeplKey) : std::u16string_view(); - if (sApiUrlTrimmed.empty() || sKeyTrimmed.empty()) - { - SAL_WARN("sw.ui", "SwTranslateLangSelectDlg: API options are not set"); - m_xDialog->response(RET_CANCEL); - return; - } - - const OString aAPIUrl - = OUStringToOString(sApiUrlTrimmed, RTL_TEXTENCODING_UTF8) + "?tag_handling=html"; - const OString aAuthKey = OUStringToOString(sKeyTrimmed, RTL_TEXTENCODING_UTF8); const auto aTargetLang = getLanguageVec().at(SwTranslateLangSelectDlg::selectedLangIdx).getLanguage(); m_bTranslationStarted = true; - - SwTranslateHelper::TranslateAPIConfig aConfig({ aAPIUrl, aAuthKey, aTargetLang }); - SwTranslateHelper::TranslateDocumentCancellable(m_rWrtSh, aConfig, m_bCancelTranslation); - m_xDialog->response(RET_OK); + m_xBtnTranslate->set_sensitive(false); + bool bRet = SwTranslateHelper::TranslateDocumentCancellable(m_rWrtSh, aTargetLang, + m_bCancelTranslation); + m_xDialog->response(bRet ? RET_OK : RET_CANCEL); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/inc/translatehelper.hxx b/sw/source/uibase/inc/translatehelper.hxx index de8d370b1a4a..2fd45b733d2d 100644 --- a/sw/source/uibase/inc/translatehelper.hxx +++ b/sw/source/uibase/inc/translatehelper.hxx @@ -21,27 +21,22 @@ #include <sal/config.h> #include <config_features.h> -#include <config_wasm_strip.h> -#include <swtypes.hxx> +#include <rtl/string.hxx> + +#include <swdllapi.h> class SwWrtShell; class SwPaM; namespace SwTranslateHelper { -struct SW_DLLPUBLIC TranslateAPIConfig final -{ - const OString m_xAPIUrl; - const OString m_xAuthKey; - const OString m_xTargetLanguage; -}; SW_DLLPUBLIC OString ExportPaMToHTML(SwPaM* pCursor); SW_DLLPUBLIC void PasteHTMLToPaM(SwWrtShell& rWrtSh, const SwPaM* pCursor, const OString& rData); #if HAVE_FEATURE_CURL -SW_DLLPUBLIC void TranslateDocument(SwWrtShell& rWrtSh, const TranslateAPIConfig& rConfig); -SW_DLLPUBLIC void TranslateDocumentCancellable(SwWrtShell& rWrtSh, - const TranslateAPIConfig& rConfig, +SW_DLLPUBLIC void TranslateDocument(SwWrtShell& rWrtSh, const OString& rTargetLang); +SW_DLLPUBLIC bool TranslateDocumentCancellable(SwWrtShell& rWrtSh, const OString& rTargetLang, const bool& rCancelTranslation); +SW_DLLPUBLIC bool IsTranslationServiceConfigured(); #endif } diff --git a/sw/source/uibase/inc/translatelangselect.hxx b/sw/source/uibase/inc/translatelangselect.hxx index ed7a39cc9c86..61de53e1f956 100644 --- a/sw/source/uibase/inc/translatelangselect.hxx +++ b/sw/source/uibase/inc/translatelangselect.hxx @@ -20,10 +20,8 @@ #pragma once #include <vcl/weld/DialogController.hxx> #include <vcl/weld/weld.hxx> -#include <rtl/string.h> -#include <vector> +#include <rtl/string.hxx> #include <optional> -#include "translatehelper.hxx" class SwWrtShell; diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx index 78b90721acb9..981ab67b0709 100644 --- a/sw/source/uibase/shells/textsh1.cxx +++ b/sw/source/uibase/shells/textsh1.cxx @@ -122,7 +122,6 @@ #include <config_wasm_strip.h> #if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA #include <officecfg/Office/Common.hxx> -#include <officecfg/Office/Linguistic.hxx> #include <svl/visitem.hxx> #include <translatelangselect.hxx> #endif // HAVE_FEATURE_CURL && ENABLE_WASM_STRIP_EXTRA @@ -2303,21 +2302,8 @@ void SwTextShell::Execute(SfxRequest &rReq) const SfxPoolItem* pTargetLangStringItem = nullptr; if (pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_TARGETLANG_STR, false, &pTargetLangStringItem)) { - std::optional<OUString> oDeeplAPIUrl = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get(); - std::optional<OUString> oDeeplKey = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get(); - auto sApiUrlTrimmed = oDeeplAPIUrl ? o3tl::trim(*oDeeplAPIUrl) : std::u16string_view(); - auto sKeyTrimmed = oDeeplKey ? o3tl::trim(*oDeeplKey) : std::u16string_view(); - if (sApiUrlTrimmed.empty() || sKeyTrimmed.empty()) - { - SAL_WARN("sw.ui", "SID_FM_TRANSLATE: API options are not set"); - break; - } - const OString aAPIUrl - = OUStringToOString(sApiUrlTrimmed, RTL_TEXTENCODING_UTF8) + "?tag_handling=html"; - const OString aAuthKey = OUStringToOString(sKeyTrimmed, RTL_TEXTENCODING_UTF8); OString aTargetLang = OUStringToOString(static_cast<const SfxStringItem*>(pTargetLangStringItem)->GetValue(), RTL_TEXTENCODING_UTF8); - SwTranslateHelper::TranslateAPIConfig aConfig({aAPIUrl, aAuthKey, aTargetLang}); - SwTranslateHelper::TranslateDocument(rWrtSh, aConfig); + SwTranslateHelper::TranslateDocument(rWrtSh, aTargetLang); } else { @@ -3967,12 +3953,7 @@ void SwTextShell::GetState( SfxItemSet &rSet ) rSet.Put(SfxVisibilityItem(nWhich, false)); break; } - std::optional<OUString> oDeeplAPIUrl = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get(); - std::optional<OUString> oDeeplKey = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get(); - auto sApiUrlTrimmed - = oDeeplAPIUrl ? o3tl::trim(*oDeeplAPIUrl) : std::u16string_view(); - auto sKeyTrimmed = oDeeplKey ? o3tl::trim(*oDeeplKey) : std::u16string_view(); - if (sApiUrlTrimmed.empty() || sKeyTrimmed.empty()) + if (!SwTranslateHelper::IsTranslationServiceConfigured()) { rSet.DisableItem(nWhich); } diff --git a/sw/source/uibase/shells/translatehelper.cxx b/sw/source/uibase/shells/translatehelper.cxx index d0dc8b45bb5b..c147bf1cb334 100644 --- a/sw/source/uibase/shells/translatehelper.cxx +++ b/sw/source/uibase/shells/translatehelper.cxx @@ -20,19 +20,16 @@ #include <sal/config.h> #include <config_features.h> -#include <config_wasm_strip.h> #include <wrtsh.hxx> #include <pam.hxx> #include <node.hxx> #include <ndtxt.hxx> #include <translatehelper.hxx> +#include <o3tl/string_view.hxx> #include <sal/log.hxx> #include <rtl/string.h> #include <shellio.hxx> -#include <vcl/scheduler.hxx> #include <vcl/svapp.hxx> -#include <boost/property_tree/ptree.hpp> -#include <boost/property_tree/json_parser.hpp> #include <vcl/htmltransferable.hxx> #include <vcl/transfer.hxx> #include <swdtflvr.hxx> @@ -40,6 +37,7 @@ #include <com/sun/star/task/XStatusIndicator.hpp> #include <sfx2/viewfrm.hxx> #include <com/sun/star/task/XStatusIndicatorFactory.hpp> +#include <officecfg/Office/Linguistic.hxx> #include <strings.hrc> namespace SwTranslateHelper @@ -95,15 +93,39 @@ void PasteHTMLToPaM(SwWrtShell& rWrtSh, const SwPaM* pCursor, const OString& rDa } #if HAVE_FEATURE_CURL -void TranslateDocument(SwWrtShell& rWrtSh, const TranslateAPIConfig& rConfig) +void TranslateDocument(SwWrtShell& rWrtSh, const OString& rTargetLang) { bool bCancel = false; - TranslateDocumentCancellable(rWrtSh, rConfig, bCancel); + TranslateDocumentCancellable(rWrtSh, rTargetLang, bCancel); } -void TranslateDocumentCancellable(SwWrtShell& rWrtSh, const TranslateAPIConfig& rConfig, +static bool IsTranslationServiceConfigured(OString* pAPIUrl, OString* pKey) +{ + auto oDeeplAPIUrl = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get(); + auto oDeeplKey = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get(); + auto sApiUrlTrimmed = oDeeplAPIUrl ? o3tl::trim(*oDeeplAPIUrl) : std::u16string_view(); + auto sKeyTrimmed = oDeeplKey ? o3tl::trim(*oDeeplKey) : std::u16string_view(); + if (sApiUrlTrimmed.empty() || sKeyTrimmed.empty()) + return false; + if (pAPIUrl) + *pAPIUrl = OUStringToOString(sApiUrlTrimmed, RTL_TEXTENCODING_UTF8) + "?tag_handling=html"; + if (pKey) + *pKey = OUStringToOString(sKeyTrimmed, RTL_TEXTENCODING_UTF8); + return true; +} + +bool IsTranslationServiceConfigured() { return IsTranslationServiceConfigured(nullptr, nullptr); } + +bool TranslateDocumentCancellable(SwWrtShell& rWrtSh, const OString& rTargetLang, const bool& rCancelTranslation) { + OString aAPIUrl, aAuthKey; + if (!IsTranslationServiceConfigured(&aAPIUrl, &aAuthKey)) + { + SAL_WARN("sw.ui", "TranslateDocumentCancellable: API options are not set"); + return false; + } + auto m_pCurrentPam = rWrtSh.GetCursor(); bool bHasSelection = rWrtSh.HasSelection(); @@ -188,8 +210,7 @@ void TranslateDocumentCancellable(SwWrtShell& rWrtSh, const TranslateAPIConfig& } const auto aOut = SwTranslateHelper::ExportPaMToHTML(cursor.get()); - const auto aTranslatedOut = linguistic::Translate( - rConfig.m_xTargetLanguage, rConfig.m_xAPIUrl, rConfig.m_xAuthKey, aOut); + const auto aTranslatedOut = linguistic::Translate(rTargetLang, aAPIUrl, aAuthKey, aOut); if (!aTranslatedOut.isEmpty()) { SwTranslateHelper::PasteHTMLToPaM(rWrtSh, cursor.get(), aTranslatedOut); @@ -221,6 +242,7 @@ void TranslateDocumentCancellable(SwWrtShell& rWrtSh, const TranslateAPIConfig& if (xStatusIndicator.is()) xStatusIndicator->end(); + return true; } #endif // HAVE_FEATURE_CURL } commit 2f8ddd4b31e1540c6122ed09cc37be8e1193db2c Author: Mike Kaganski <[email protected]> AuthorDate: Tue Dec 23 16:05:04 2025 +0500 Commit: Mike Kaganski <[email protected]> CommitDate: Sun Dec 28 12:09:49 2025 +0100 Use a reasonable name for idle It was obviously just a copypaste Change-Id: I9350e046e163eec6779450f0a0ccd7be5ad2ff4d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196257 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> diff --git a/sw/source/uibase/shells/translatehelper.cxx b/sw/source/uibase/shells/translatehelper.cxx index bc2a1eaef785..d0dc8b45bb5b 100644 --- a/sw/source/uibase/shells/translatehelper.cxx +++ b/sw/source/uibase/shells/translatehelper.cxx @@ -206,7 +206,7 @@ void TranslateDocumentCancellable(SwWrtShell& rWrtSh, const TranslateAPIConfig& if (xStatusIndicator.is() && nCount) xStatusIndicator->setValue((100 * ++nProgress) / nCount); - Idle aIdle("ProgressBar::SetValue aIdle"); + Idle aIdle("TranslateDocumentCancellable aIdle"); aIdle.SetPriority(TaskPriority::POST_PAINT); aIdle.Start(); commit 93b9820c09bc5f06b2f4b6a553f2924ad88a2dbf Author: Mike Kaganski <[email protected]> AuthorDate: Tue Dec 23 16:02:07 2025 +0500 Commit: Mike Kaganski <[email protected]> CommitDate: Sun Dec 28 12:09:43 2025 +0100 Return an empty result in case there was no translations I don't know if this is possible (but the response is from an external server, so untrusted and may potentially be anything); just make sure we don't crash below, trying to access the first result of none. Change-Id: Iabd6b31b558c91ae435d552594ae24662826e319 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196256 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> diff --git a/linguistic/source/translate.cxx b/linguistic/source/translate.cxx index 8c3410777003..acc811e63f2d 100644 --- a/linguistic/source/translate.cxx +++ b/linguistic/source/translate.cxx @@ -74,6 +74,7 @@ OString Translate(const OString& rTargetLang, const OString& rAPIUrl, const OStr if (size <= 0) { SAL_WARN("linguistic", "Translate: API did not return any translations"); + return {}; } // take the first one const boost::property_tree::ptree& translation = translations.begin()->second;
