KTextAddons

googleengineplugin.cpp
1/*
2 SPDX-FileCopyrightText: 2022-2025 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "googleengineplugin.h"
8using namespace Qt::Literals::StringLiterals;
9
10#include "googletranslator_debug.h"
11#include <KLocalizedString>
12#include <QJsonDocument>
13#include <QJsonParseError>
14#include <QNetworkAccessManager>
15#include <QNetworkReply>
16#include <QNetworkRequest>
17#include <QRegularExpression>
18#include <QUrlQuery>
19#include <TextTranslator/TranslatorEngineAccessManager>
20
21GoogleEnginePlugin::GoogleEnginePlugin(QObject *parent)
22 : TextTranslator::TranslatorEnginePlugin(parent)
23{
24 connect(TextTranslator::TranslatorEngineAccessManager::self()->networkManager(),
26 this,
27 &GoogleEnginePlugin::slotTranslateFinished);
28}
29
30GoogleEnginePlugin::~GoogleEnginePlugin() = default;
31
32void GoogleEnginePlugin::translate()
33{
34 if (verifyFromAndToLanguage()) {
35 return;
36 }
37
38 clear();
39
40 QUrlQuery urlQuery;
41 urlQuery.addQueryItem(QStringLiteral("client"), QStringLiteral("gtx"));
42 urlQuery.addQueryItem(QStringLiteral("sl"), languageCode(from()));
43 urlQuery.addQueryItem(QStringLiteral("tl"), languageCode(to()));
44 urlQuery.addQueryItem(QStringLiteral("dt"), QStringLiteral("t"));
45 urlQuery.addQueryItem(QStringLiteral("q"), inputText());
46
47 QUrl url;
48 url.setQuery(urlQuery);
49 url.setScheme(QStringLiteral("https"));
50 url.setHost(QStringLiteral("translate.googleapis.com"));
51 url.setPath(QStringLiteral("/translate_a/single"));
52 const QNetworkRequest request(url);
53
54 QNetworkReply *reply = TextTranslator::TranslatorEngineAccessManager::self()->networkManager()->get(request);
55 connect(reply, &QNetworkReply::errorOccurred, this, [this, reply](QNetworkReply::NetworkError error) {
56 slotError(error);
57 reply->deleteLater();
58 });
59}
60
61QString GoogleEnginePlugin::languageCode(const QString &langStr)
62{
63 if (langStr == "iw"_L1) {
64 return QStringLiteral("iw");
65 }
66 return langStr;
67}
68
69void GoogleEnginePlugin::slotTranslateFinished(QNetworkReply *reply)
70{
71 clear();
72 mJsonData = QString::fromUtf8(reply->readAll());
73 reply->deleteLater();
74 // jsonData contains arrays like this: ["foo",,"bar"]
75 // but this is not valid JSON for QJSON, it expects empty strings: ["foo","","bar"]
76 mJsonData.replace(QRegularExpression(QStringLiteral(",{3,3}")), QStringLiteral(",\"\",\"\","));
77 mJsonData.replace(QRegularExpression(QStringLiteral(",{2,2}")), QStringLiteral(",\"\","));
78 qCDebug(TRANSLATOR_GOOGLE_LOG) << mJsonData;
79
80 QJsonParseError parsingError;
81 const QJsonDocument jsonDoc = QJsonDocument::fromJson(mJsonData.toUtf8(), &parsingError);
82 if (parsingError.error != QJsonParseError::NoError || jsonDoc.isNull()) {
83 Q_EMIT translateFailed(i18n("Invalid answer."));
84 return;
85 }
86 const QVariantList json = jsonDoc.toVariant().toList();
87 if (hasDebug()) {
88 setJsonDebug(QString::fromUtf8(jsonDoc.toJson(QJsonDocument::Indented)));
89 }
90 for (const QVariant &level0 : json) {
91 const QVariantList listLevel0 = level0.toList();
92 if (listLevel0.isEmpty()) {
93 continue;
94 }
95 for (const QVariant &level1 : listLevel0) {
96 if (level1.toList().size() <= 2) {
97 continue;
98 }
99 appendResult(level1.toList().at(0).toString());
100 }
101 }
102 Q_EMIT translateDone();
103}
QString i18n(const char *text, const TYPE &arg...)
QByteArray readAll()
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
bool isNull() const const
QByteArray toJson(JsonFormat format) const const
QVariant toVariant() const const
void finished(QNetworkReply *reply)
QNetworkReply * get(const QNetworkRequest &request)
void errorOccurred(QNetworkReply::NetworkError code)
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
QString fromUtf8(QByteArrayView str)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setHost(const QString &host, ParsingMode mode)
void setPath(const QString &path, ParsingMode mode)
void setQuery(const QString &query, ParsingMode mode)
void setScheme(const QString &scheme)
void addQueryItem(const QString &key, const QString &value)
QList< QVariant > toList() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:49:24 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.