File indexing completed on 2024-11-24 04:16:56

0001 /*
0002   SPDX-FileCopyrightText: 2022-2024 Laurent Montel <montel@kde.org>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later
0005 
0006   based on digikam onlinetranslator code
0007 
0008 */
0009 
0010 #include "libretranslateengineplugin.h"
0011 #include "libretranslateengineutil.h"
0012 #include "libretranslatetranslator_debug.h"
0013 
0014 #include <KConfigGroup>
0015 #include <KLocalizedString>
0016 #include <KSharedConfig>
0017 #include <QJsonDocument>
0018 #include <QJsonObject>
0019 #include <TextTranslator/TranslatorEngineAccessManager>
0020 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0021 #include <qt5keychain/keychain.h>
0022 #else
0023 #include <qt6keychain/keychain.h>
0024 #endif
0025 
0026 LibreTranslateEnginePlugin::LibreTranslateEnginePlugin(QObject *parent)
0027     : TextTranslator::TranslatorEnginePlugin(parent)
0028 {
0029     loadSettings();
0030 }
0031 
0032 LibreTranslateEnginePlugin::~LibreTranslateEnginePlugin() = default;
0033 
0034 void LibreTranslateEnginePlugin::translate()
0035 {
0036     if (verifyFromAndToLanguage()) {
0037         return;
0038     }
0039     if (mServerUrl.isEmpty()) {
0040         Q_EMIT translateFailed(i18n("Server url is not defined."));
0041         return;
0042     }
0043     if (mRequiredApiKey && mApiKey.isEmpty()) {
0044         Q_EMIT translateFailed(i18n("Server needs Api Key."));
0045         return;
0046     }
0047     translateText();
0048 }
0049 
0050 void LibreTranslateEnginePlugin::slotConfigureChanged()
0051 {
0052     loadSettings();
0053 }
0054 
0055 void LibreTranslateEnginePlugin::translateText()
0056 {
0057     clear();
0058 
0059     QByteArray postData = "&q=" + QUrl::toPercentEncoding(inputText()) + "&source=" + from().toUtf8() + "&target=" + to().toUtf8();
0060     if (!mApiKey.isEmpty()) {
0061         postData += "&api_key=" + mApiKey.toUtf8();
0062     }
0063     const auto url = QUrl(QStringLiteral("%1/translate").arg(mServerUrl));
0064     QNetworkRequest request;
0065     request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/x-www-form-urlencoded"));
0066     request.setUrl(url);
0067 
0068     qCDebug(TRANSLATOR_LIBRETRANSLATE_LOG) << " url " << url;
0069 
0070     QNetworkReply *reply = TextTranslator::TranslatorEngineAccessManager::self()->networkManager()->post(request, postData);
0071     connect(reply, &QNetworkReply::errorOccurred, this, [this, reply](QNetworkReply::NetworkError error) {
0072         slotError(error);
0073         reply->deleteLater();
0074     });
0075     connect(reply, &QNetworkReply::finished, this, [this, reply]() {
0076         reply->deleteLater();
0077         parseTranslation(reply);
0078     });
0079 }
0080 
0081 void LibreTranslateEnginePlugin::parseTranslation(QNetworkReply *reply)
0082 {
0083     if (reply->error() != QNetworkReply::NoError) {
0084         Q_EMIT translateFailed(reply->errorString());
0085         reply->deleteLater();
0086         return;
0087     }
0088     const QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll());
0089     if (hasDebug()) {
0090         setJsonDebug(QString::fromUtf8(jsonResponse.toJson(QJsonDocument::Indented)));
0091     }
0092 
0093     const QJsonObject responseObject = jsonResponse.object();
0094     setResult(responseObject.value(QStringLiteral("translatedText")).toString());
0095     reply->deleteLater();
0096     qCDebug(TRANSLATOR_LIBRETRANSLATE_LOG) << " result " << result();
0097     Q_EMIT translateDone();
0098 }
0099 
0100 void LibreTranslateEnginePlugin::loadSettings()
0101 {
0102     KConfigGroup myGroup(KSharedConfig::openConfig(), LibreTranslateEngineUtil::groupName());
0103     mServerUrl = myGroup.readEntry(LibreTranslateEngineUtil::serverUrlKey(), LibreTranslateEngineUtil::defaultServerUrl());
0104     // Fallback
0105     if (mServerUrl.isEmpty()) {
0106         mServerUrl = LibreTranslateEngineUtil::defaultServerUrl();
0107     }
0108     mServerUrl = LibreTranslateEngineUtil::adaptUrl(mServerUrl);
0109     mRequiredApiKey = myGroup.readEntry(LibreTranslateEngineUtil::serverRequiredApiKey(), false);
0110 
0111     auto readJob = new QKeychain::ReadPasswordJob(LibreTranslateEngineUtil::translatorGroupName(), this);
0112     connect(readJob, &QKeychain::Job::finished, this, &LibreTranslateEnginePlugin::slotApiKeyRead);
0113     readJob->setKey(LibreTranslateEngineUtil::apiGroupName());
0114     readJob->start();
0115 }
0116 
0117 void LibreTranslateEnginePlugin::slotApiKeyRead(QKeychain::Job *baseJob)
0118 {
0119     auto job = qobject_cast<QKeychain::ReadPasswordJob *>(baseJob);
0120     Q_ASSERT(job);
0121     if (!job->error()) {
0122         mApiKey = job->textData();
0123     } else {
0124         qCWarning(TRANSLATOR_LIBRETRANSLATE_LOG) << "We have an error during reading password " << job->errorString();
0125     }
0126 }
0127 
0128 #include "moc_libretranslateengineplugin.cpp"