KTextAddons

deeplengineplugin.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#include "deeplengineplugin.h"
10using namespace Qt::Literals::StringLiterals;
11
12#include "deeplengineutil.h"
13#include "deepltranslator_debug.h"
14
15#include <KConfigGroup>
16#include <KLocalizedString>
17#include <KSharedConfig>
18#include <QJsonArray>
19#include <QJsonDocument>
20#include <QJsonObject>
21#include <QUrlQuery>
22#include <TextTranslator/TranslatorEngineAccessManager>
23#include <qt6keychain/keychain.h>
24
25DeeplEnginePlugin::DeeplEnginePlugin(QObject *parent)
26 : TextTranslator::TranslatorEnginePlugin(parent)
27{
28 loadSettings();
29}
30
31DeeplEnginePlugin::~DeeplEnginePlugin() = default;
32
33void DeeplEnginePlugin::translate()
34{
35 if (verifyFromAndToLanguage()) {
36 return;
37 }
38 if (mApiKey.isEmpty()) {
39 Q_EMIT translateFailed(i18n("Server needs Api Key."));
40 return;
41 }
42 translateText();
43}
44
45void DeeplEnginePlugin::translateText()
46{
47 clear();
48
49 QUrl url(mServerUrl);
51 query.addQueryItem(QStringLiteral("text"), inputText());
52 query.addQueryItem(QStringLiteral("source_lang"), languageCode(from()));
53 query.addQueryItem(QStringLiteral("target_lang"), languageCode(to()));
54 url.setQuery(query);
55
56 QNetworkRequest request(url);
57 request.setRawHeader(QByteArrayLiteral("Authorization"), "DeepL-Auth-Key " + mApiKey.toLocal8Bit());
58 request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
59
60 QNetworkReply *reply = TextTranslator::TranslatorEngineAccessManager::self()->networkManager()->post(request, QByteArray());
61 connect(reply, &QNetworkReply::errorOccurred, this, [this, reply](QNetworkReply::NetworkError error) {
62 slotError(error);
63 reply->deleteLater();
64 });
65 connect(reply, &QNetworkReply::finished, this, [this, reply]() {
66 reply->deleteLater();
67 parseTranslation(reply);
68 });
69}
70
71void DeeplEnginePlugin::parseTranslation(QNetworkReply *reply)
72{
73 if (reply->error() != QNetworkReply::NoError) {
74 Q_EMIT translateFailed(reply->errorString());
75 reply->deleteLater();
76 return;
77 }
78
79 const QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll());
80 if (hasDebug()) {
81 setJsonDebug(QString::fromUtf8(jsonResponse.toJson(QJsonDocument::Indented)));
82 }
83 const QJsonObject responseObject = jsonResponse.object();
84 // QJsonObject({"translations":[{"detected_source_language":"EN","text":"Bonjour le monde"}]})
85 qCDebug(TRANSLATOR_DEEPL_LOG) << " responseObject " << responseObject;
86 const QJsonArray arrayTranslation = responseObject.value(QStringLiteral("translations")).toArray();
87 qCDebug(TRANSLATOR_DEEPL_LOG) << " arrayTranslation " << arrayTranslation;
88 const QJsonObject obj = arrayTranslation.at(0).toObject();
89
90 setResult(obj.value(QStringLiteral("text")).toString());
91 reply->deleteLater();
92 qCDebug(TRANSLATOR_DEEPL_LOG) << " result " << result();
93 Q_EMIT translateDone();
94}
95
96void DeeplEnginePlugin::loadSettings()
97{
98 KConfigGroup myGroup(KSharedConfig::openConfig(), DeeplEngineUtil::groupName());
99 mUseFreeLicense = myGroup.readEntry(DeeplEngineUtil::freeLicenseKey(), false);
100 mServerUrl = mUseFreeLicense ? QStringLiteral("https://api-free.deepl.com/v2/translate") : QStringLiteral("https://api.deepl.com/v2/translate");
101 auto readJob = new QKeychain::ReadPasswordJob(DeeplEngineUtil::translatorGroupName(), this);
102 connect(readJob, &QKeychain::Job::finished, this, &DeeplEnginePlugin::slotApiKeyRead);
103 readJob->setKey(DeeplEngineUtil::apiGroupName());
104 readJob->start();
105}
106
107void DeeplEnginePlugin::slotApiKeyRead(QKeychain::Job *baseJob)
108{
110 Q_ASSERT(job);
111 if (!job->error()) {
112 mApiKey = job->textData();
113 } else {
114 qCWarning(TRANSLATOR_DEEPL_LOG) << "We have an error during reading password " << job->errorString();
115 }
116}
117
118void DeeplEnginePlugin::slotConfigureChanged()
119{
120 loadSettings();
121}
122
123QString DeeplEnginePlugin::languageCode(const QString &langStr)
124{
125 if (langStr == "auto"_L1) {
126 return QStringLiteral("auto-detect");
127 } else if (langStr == "zh-CN"_L1) {
128 return QStringLiteral("zh");
129 }
130 return langStr;
131}
132
133#include "moc_deeplengineplugin.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)
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
QString errorString() const const
QByteArray readAll()
QJsonValue at(qsizetype i) const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QJsonObject object() const const
QByteArray toJson(JsonFormat format) const const
QJsonValue value(QLatin1StringView key) const const
QJsonArray toArray() const const
QJsonObject toObject() const const
QNetworkReply * post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
NetworkError error() const const
void errorOccurred(QNetworkReply::NetworkError code)
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 toLocal8Bit() const const
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.