KTextAddons

libretranslateengineplugin.cpp
1/*
2 SPDX-FileCopyrightText: 2022-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5
6 based on digikam onlinetranslator code
7
8*/
9
10#include "libretranslateengineplugin.h"
11using namespace Qt::Literals::StringLiterals;
12
13#include "libretranslateengineutil.h"
14#include "libretranslatetranslator_debug.h"
15
16#include <KConfigGroup>
17#include <KLocalizedString>
18#include <KSharedConfig>
19#include <QJsonDocument>
20#include <QJsonObject>
21#include <TextTranslator/TranslatorEngineAccessManager>
22#include <qt6keychain/keychain.h>
23
24LibreTranslateEnginePlugin::LibreTranslateEnginePlugin(QObject *parent)
25 : TextTranslator::TranslatorEnginePlugin(parent)
26{
27 loadSettings();
28}
29
30LibreTranslateEnginePlugin::~LibreTranslateEnginePlugin() = default;
31
32void LibreTranslateEnginePlugin::translate()
33{
34 if (verifyFromAndToLanguage()) {
35 return;
36 }
37 if (mServerUrl.isEmpty()) {
38 Q_EMIT translateFailed(i18n("Server url is not defined."));
39 return;
40 }
41 if (mRequiredApiKey && mApiKey.isEmpty()) {
42 Q_EMIT translateFailed(i18n("Server needs Api Key."));
43 return;
44 }
45 translateText();
46}
47
48void LibreTranslateEnginePlugin::slotConfigureChanged()
49{
50 loadSettings();
51}
52
53void LibreTranslateEnginePlugin::translateText()
54{
55 clear();
56
57 QByteArray postData = "&q=" + QUrl::toPercentEncoding(inputText()) + "&source=" + from().toUtf8() + "&target=" + to().toUtf8();
58 if (!mApiKey.isEmpty()) {
59 postData += "&api_key=" + mApiKey.toUtf8();
60 }
61 const auto url = QUrl(QStringLiteral("%1/translate").arg(mServerUrl));
62 QNetworkRequest request;
63 request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"_L1);
64 request.setUrl(url);
65
66 qCDebug(TRANSLATOR_LIBRETRANSLATE_LOG) << " url " << url;
67
68 QNetworkReply *reply = TextTranslator::TranslatorEngineAccessManager::self()->networkManager()->post(request, postData);
69 connect(reply, &QNetworkReply::errorOccurred, this, [this, reply](QNetworkReply::NetworkError error) {
70 slotError(error);
71 reply->deleteLater();
72 });
73 connect(reply, &QNetworkReply::finished, this, [this, reply]() {
74 reply->deleteLater();
75 parseTranslation(reply);
76 });
77}
78
79void LibreTranslateEnginePlugin::parseTranslation(QNetworkReply *reply)
80{
81 if (reply->error() != QNetworkReply::NoError) {
82 Q_EMIT translateFailed(reply->errorString());
83 reply->deleteLater();
84 return;
85 }
86 const QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll());
87 if (hasDebug()) {
88 setJsonDebug(QString::fromUtf8(jsonResponse.toJson(QJsonDocument::Indented)));
89 }
90
91 const QJsonObject responseObject = jsonResponse.object();
92 setResult(responseObject.value(QStringLiteral("translatedText")).toString());
93 reply->deleteLater();
94 qCDebug(TRANSLATOR_LIBRETRANSLATE_LOG) << " result " << result();
95 Q_EMIT translateDone();
96}
97
98void LibreTranslateEnginePlugin::loadSettings()
99{
100 KConfigGroup myGroup(KSharedConfig::openConfig(), LibreTranslateEngineUtil::groupName());
101 mServerUrl = myGroup.readEntry(LibreTranslateEngineUtil::serverUrlKey(), LibreTranslateEngineUtil::defaultServerUrl());
102 // Fallback
103 if (mServerUrl.isEmpty()) {
104 mServerUrl = LibreTranslateEngineUtil::defaultServerUrl();
105 }
106 mServerUrl = LibreTranslateEngineUtil::adaptUrl(mServerUrl);
107 mRequiredApiKey = myGroup.readEntry(LibreTranslateEngineUtil::serverRequiredApiKey(), false);
108
109 auto readJob = new QKeychain::ReadPasswordJob(LibreTranslateEngineUtil::translatorGroupName(), this);
110 connect(readJob, &QKeychain::Job::finished, this, &LibreTranslateEnginePlugin::slotApiKeyRead);
111 readJob->setKey(LibreTranslateEngineUtil::apiGroupName());
112 readJob->start();
113}
114
115void LibreTranslateEnginePlugin::slotApiKeyRead(QKeychain::Job *baseJob)
116{
118 Q_ASSERT(job);
119 if (!job->error()) {
120 mApiKey = job->textData();
121 } else {
122 qCWarning(TRANSLATOR_LIBRETRANSLATE_LOG) << "We have an error during reading password " << job->errorString();
123 }
124}
125
126#include "moc_libretranslateengineplugin.cpp"
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
QString errorString() const const
QByteArray readAll()
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QJsonObject object() const const
QByteArray toJson(JsonFormat format) const const
QJsonValue value(QLatin1StringView key) const const
QNetworkReply * post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
NetworkError error() const const
void errorOccurred(QNetworkReply::NetworkError code)
void setHeader(KnownHeaders header, const QVariant &value)
void setUrl(const QUrl &url)
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
T qobject_cast(QObject *object)
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
QByteArray toUtf8() const const
QByteArray toPercentEncoding(const QString &input, const QByteArray &exclude, const QByteArray &include)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:51:28 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.