File indexing completed on 2025-04-27 03:58:38

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2018-02-22
0007  * Description : A text translator using web-services - LibreTranslate methods.
0008  *
0009  * SPDX-FileCopyrightText: 2018-2022 by Hennadii Chernyshchyk <genaloner at gmail dot com>
0010  * SPDX-FileCopyrightText: 2021-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "donlinetranslator_p.h"
0017 
0018 namespace Digikam
0019 {
0020 
0021 void DOnlineTranslator::slotRequestLibreLangDetection()
0022 {
0023     const QString sourceText  = sender()->property(Private::s_textProperty).toString();
0024 
0025     // Generate POST data
0026 
0027     const QByteArray postData = "&q="       + QUrl::toPercentEncoding(sourceText)
0028                               + "&api_key=" + d->libreApiKey;
0029 
0030     // Setup request
0031 
0032     QNetworkRequest request;
0033     request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/x-www-form-urlencoded"));
0034     request.setUrl(QUrl(QString::fromUtf8("%1/detect").arg(d->libreUrl)));
0035 
0036     // Make reply
0037 
0038     d->currentReply            = d->networkManager->post(request, postData);
0039 }
0040 
0041 void DOnlineTranslator::slotParseLibreLangDetection()
0042 {
0043     if ((quintptr)d->currentReply.data() != sender()->property("QNetworkReply").value<quintptr>())
0044     {
0045         return;
0046     }
0047 
0048     d->currentReply->deleteLater();
0049 
0050     // Check for errors
0051 
0052     if (d->currentReply->error() != QNetworkReply::NoError)
0053     {
0054         resetData(NetworkError, d->currentReply->errorString());
0055         return;
0056     }
0057 
0058     const QJsonDocument jsonResponse = QJsonDocument::fromJson(d->currentReply->readAll());
0059     const QJsonObject responseObject = jsonResponse.array().first().toObject();
0060 
0061     if (d->sourceLang == Auto)
0062     {
0063         const QString langCode = responseObject.value(QStringLiteral("language")).toString();
0064         d->sourceLang           = language(LibreTranslate, langCode);
0065 
0066         if (d->sourceLang == NoLanguage)
0067         {
0068             resetData(ParsingError, i18n("Error: Unable to parse autodetected language"));
0069         }
0070     }
0071 }
0072 
0073 void DOnlineTranslator::slotRequestLibreTranslate()
0074 {
0075     const QString sourceText  = sender()->property(Private::s_textProperty).toString();
0076 
0077     // Generate POST data
0078 
0079     const QByteArray postData = "&q="       + QUrl::toPercentEncoding(sourceText)
0080                               + "&source="  + languageApiCode(LibreTranslate, d->sourceLang).toUtf8()
0081                               + "&target="  + languageApiCode(LibreTranslate, d->translationLang).toUtf8()
0082                               + "&api_key=" + d->libreApiKey;
0083 
0084     // Setup request
0085 
0086     QNetworkRequest request;
0087     request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/x-www-form-urlencoded"));
0088     request.setUrl(QUrl(QString::fromUtf8("%1/translate").arg(d->libreUrl)));
0089 
0090     // Make reply
0091 
0092     d->currentReply            = d->networkManager->post(request, postData);
0093 }
0094 
0095 void DOnlineTranslator::slotParseLibreTranslate()
0096 {
0097     if ((quintptr)d->currentReply.data() != sender()->property("QNetworkReply").value<quintptr>())
0098     {
0099         return;
0100     }
0101 
0102     d->currentReply->deleteLater();
0103 
0104     // Check for errors
0105 
0106     if (d->currentReply->error() != QNetworkReply::NoError)
0107     {
0108         resetData(NetworkError, d->currentReply->errorString());
0109         return;
0110     }
0111 
0112     const QJsonDocument jsonResponse = QJsonDocument::fromJson(d->currentReply->readAll());
0113     const QJsonObject responseObject = jsonResponse.object();
0114     d->translation                    = responseObject.value(QStringLiteral("translatedText")).toString();
0115 }
0116 
0117 void DOnlineTranslator::buildLibreDetectStateMachine()
0118 {
0119     // States
0120 
0121     auto* detectState = new QState(d->stateMachine);
0122     auto* finalState  = new QFinalState(d->stateMachine);
0123     d->stateMachine->setInitialState(detectState);
0124 
0125     detectState->addTransition(detectState, &QState::finished, finalState);
0126 
0127     // Setup lang detection state
0128 
0129     const QString text = d->source.left(getSplitIndex(d->source, Private::s_libreTranslateLimit));
0130 
0131     buildNetworkRequestState(detectState,
0132                              &DOnlineTranslator::slotRequestLibreLangDetection,
0133                              &DOnlineTranslator::slotParseLibreLangDetection,
0134                              text);
0135 }
0136 
0137 void DOnlineTranslator::buildLibreStateMachine()
0138 {
0139     // States
0140 
0141     auto* languageDetectionState = new QState(d->stateMachine);
0142     auto* translationState       = new QState(d->stateMachine);
0143     auto* finalState             = new QFinalState(d->stateMachine);
0144     d->stateMachine->setInitialState(languageDetectionState);
0145 
0146     // Transitions
0147 
0148     languageDetectionState->addTransition(languageDetectionState, &QState::finished, translationState);
0149     translationState->addTransition(translationState, &QState::finished, finalState);
0150 
0151     // Setup LibreTranslate lang code detection
0152 
0153     buildNetworkRequestState(languageDetectionState,
0154                              &DOnlineTranslator::slotRequestLibreLangDetection,
0155                              &DOnlineTranslator::slotParseLibreLangDetection,
0156                              d->source);
0157 
0158     // Setup translation state
0159 
0160     buildSplitNetworkRequest(translationState,
0161                              &DOnlineTranslator::slotRequestLibreTranslate,
0162                              &DOnlineTranslator::slotParseLibreTranslate,
0163                              d->source,
0164                              Private::s_libreTranslateLimit);
0165 }
0166 
0167 } // namespace Digikam