How to use Google Translate API With c++ - c++

I'm a beginner in C++ and using Google task API.
How do I write a C++ program that accepts a word, then invokes Google Translate to translate it from English to French, then saves the resulted page to a local file?
For example, if the user inputs "river", the program should invoke Google Translate to translate into French, the resulting page is:
http://translate.google.com/#en|fr|River%0A
This page should be saved.
I read the official documentation through fully: http://code.google.com/apis/language/translate/v2/getting_started.html
but I couldn't understand how to using REST and I'm not familiar with JSON or AJAX.

You cannot use JSON objects straight in C++.
JSON = JavaScript Object Notation
You need to spawn/create something which can parse such objects. For example I've used QNetworkManager in Qt (in C++) to send build javascript and send requests to google APIs. The result would be a JSON object which I had to parse and either display in a browser (which I made in c++) or parse the results into a c++ class and process it differently (do some calculations with it).
If you just need the data, you can request XML instead of JSON and then you can use a standard XML parser to extract the translated word.
EDIT 1:
Google in their example uses:
https://www.googleapis.com/language/translate/v2?key=YOUR-API-KEY&source=en&target=de&q=words+to+translate
This translate from english (en) to german (de). The words to translate are: "words to translate".
Now build an HTTP request in C++ with this URL as the data. Send that with some network manager or sockets and wait for a reply back. Google will give you back data.

I seen this codes below somewhere but I don't remember where, anyway try this:
QString YourClass::translate(QString keyword, QString from, QString to)
{
//Translate URL
QString url = QString("http://translate.google.com/translate_a/t?client=t&text=%0&hl=%1&sl=%2&tl=%1&multires=1&prev=enter&oc=2&ssel=0&tsel=0&uptl=%1&sc=1").arg(keyword).arg(to).arg(from);
QNetworkAccessManager manager;
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
//Get reply from Google
do {
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
} while(!reply->isFinished());
//Convert to string
QString translation(reply->readAll());
reply->close();
//Free memory
delete reply;
//Remove [[[" from the beginning
translation = translation.replace("[[[\"", "");
//Extract final translated string
translation = translation.mid(0, translation.indexOf(",\"") - 1);
return translation;
}

someone advise me to use libcurl, I will try and see.

You need some kind of HTTP library. I second most of what Adrian said, but here's some (incomplete) Qt code which should give you an idea.
namespace {
const QString API_KEY = /* TODO */;
}
MyQObject :: MyQbject ()
: m_manager (new QNetworkAccessManager (this))
{
connect(manager, SIGNAL (finished (QNetworkReply *)),
this, SLOT (reply_finished (QNetworkReply *)));
}
void MyQObject :: fetch_translation (
QString words,
void (*on_receive)(const QString &))
{
// Let's assume asynchronous but non-concurrent requests.
m_on_receive = on_receive;
QString request =
"https://www.googleapis.com/language/translate/v2"
"?key=%1&source=en&target=de&q=%2";
// May want to url-encode 'words' first.
m_manager -> get (QUrl (request .arg (API_KEY) .arg (words));
}
void MyQObject :: reply_finished (QNetworkReply * reply)
{
m_on_receive (reply -> readAll ());
}
// ...
{
my_q_object -> translate ("hello, world", [](const QString & s) {
qWarning () << "translation is: " << s;
});
}

Related

Parse JSON Array with Qt

I'm trying to write a desktop client with Qt for an online dictionary site. I got stuck on something about JSON.
http://ac.tureng.co/?c=?&t=expensive
?(["expensive","expensive habits","expensive medical equipment","expensive question","expensive watch","expensive-looking","expensively","expensiveness"]);
I think the data which come from the above address is JSON array. json.org has the following description:
An array is an ordered collection of values. An array begins with [
(left bracket) and ends with ] (right bracket). Values are separated
by , (comma).*
Also a valid JSON according to the JSON Formatter if a string is written instead of the first question mark:
a([
"expensive",
"expensive habits",
"expensive medical equipment",
"expensive question",
"expensive watch",
"expensive-looking",
"expensively",
"expensiveness"
]);
But this change is not enough for the JSONLint site:
["expensive", "expensive habits", "expensive medical equipment", "expensive question", "expensive watch", "expensive-looking", "expensively", "expensiveness"]
I want to show suggestions to the user at the user input using the data from here. For now I can't extract JSON, so I've reached the desired behavior by acting it as plain text. Is there a way to do this properly by parsing JSON?
The codes I've written so far are:
QString turengOneriMetin = QString("http://ac.tureng.co/?c=?&t=%1").arg(arg1);
QUrl turengOneri(turengOneriMetin);
QNetworkAccessManager manager;
QNetworkReply *response = manager.get(QNetworkRequest(turengOneri));
QEventLoop event;
connect(response, SIGNAL(finished()), &event, SLOT(quit()));
event.exec();
QString content = response->readAll();
content.replace(0,1,"a");
content = content.replace("a([", "").replace("]);", "").replace("\"","");
QStringList wordList;
wordList << content.split(",");
ui->label->setText(content);
// https://stackoverflow.com/questions/24248606/how-to-accomplish-drop-down-word-suggestions-in-qt
QCompleter *completer = new QCompleter(wordList, this);
completer->setCaseSensitivity(Qt::CaseInsensitive);
ui->lineEdit->setCompleter(completer);
Update: After receiving the JSON correctly with help of answers and other resources I've done what I wanted with the following piece of code:
QJsonDocument document = QJsonDocument::fromJson(content.toUtf8());
QJsonArray documentArray = document.array();
QStringList wordList;
for (const QJsonValue &i : documentArray)
{
//qInfo() << i.toString() << endl;
wordList << i.toString();
}
I think that URL should be this - http://ac.tureng.co/?t=expensive
In this case you'll get valid JSON.

Qt parsing json using network response binary

Alright, I found something I just don't understand. I am making a request to a web service using QtNetworkManager. For some reason I can't seem to go from the network response to a jsondoc directly, I have to cast it into a string and then BACK into uft8?
void WebAPIengine::handleNetworkData(QNetworkReply *networkReply)
{
//No network error
if (!networkReply->error()){
//Cast to string
QString strReply = (QString)networkReply->readAll();
//This works, jsonDoc will have the json response from webpage
QJsonDocument jsonDoc = QJsonDocument::fromJson(strReply.toUtf8());
//This doesn't work, networkReply->readAll() is said to return a QByteArray.
QJsonDocument jsonDoc2 = QJsonDocument::fromBinaryData(networkReply->readAll());
QJsonObject jsonObj = jsonDoc.object();
data = jsonObj;
}
//Network error
else{
data["Error"] = "WebAPIengine::handleNetworkData()";
}
Now I can not understand why jsonDoc is working and jsonDoc2 is not. Can someone explain?
Once you do a QNetworkReply->readAll(), the QNetworkReply object will be empty. So if you call the QNetworkReply->readAll() method again, you will not get anything.
Moreover I don't understand why you are converting the QByteArray returned by QNetworkReply->readAll() into a QString and then converting it back to QByteArray(by calling QString::toUtf8()) to give it to the QJsonDocument::fromJson function.
You can try doing this:
QByteArray temp = newReply->readAll();
QJsonDocument jsonDoc = QJsonDocument::fromJson(temp); // This should work
Also make sure to know what the content of the JSon document is, i.e. if it is a map (QJsonObject), array(QJSonArray), array of maps or map with an array as value.

Qt pass additional argument to slot AND keep emitted signal data

I have searched the web on this issue and I've repeatedly got answers referring to the use of QSignalMapper. But my problem is pretty clear, QSignalMapper automatically gets rid of whatever is originally emitted and replaces it with basically nothing, plus the new data that is set via setMapping().
The problem here is simple.
I have a QNetworkAccessManager that parses html and updates a vector containing text data:
void DataManager::startHttpRequest(QString url, int index)
{
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
//QSignalMapper* signalMapper = new QSignalMapper(this);
//connect(manager,SIGNAL(finished(QNetworkReply*)), signalMapper,SLOT(map()));
//signalMapper->setMapping(manager, index);
//connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(insertUpdate(int)));
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(finishHttpRequest(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl(url)));
qDebug() << index;
}
and here is what happens when the request is finished, the normal way:
void DataManager::finishHttpRequest(QNetworkReply *reply)
{
QString html = QString(reply->readAll()).simplified();
QString info;
int start = html.indexOf("<span id=\"SalePrice\" >");
if(start != -1)
{
QString price = html.mid(start + 23, 30);
int end = price.indexOf("</span>");
info = price.mid(0, end - 1);
qWarning() << price.mid(0, end - 1);
}
else
{
info = "NA";
}
// Do more stuff
}
Using the normal way of signals and slots, I would not be able to know the index of the vector I am updating,
Or,
If I am using QSignalMapper, I know the index, but not the data that comes with it.
How do I get BOTH working (index + data)?
(something like mySlot(QNetworkReply *reply, int *index), but we all know that won't work)
Many thanks in advance.
While it's probably not the best,
sender()->setObjectName(const QString & name) allows the sender to name itself.
The sender's name can be accessed from the receiving slot via sender()->ObjectName()
As documented on http://qt-project.org/doc/qt-5/qobject.html#objectName-prop.

Qt, catch form values in QNetworkRequest

I have a QWebView component in my Qt widget application. And I have already created a network manager to handle requests from the QWebView.
What I want to do is catching the values of the web form inside QWebView, up to this point of time I have the QNetworkRequest instance of every network request.
How to extract the form values from the QNetworkRequest instance?
You can use this function of QNetworkRequest class:
QByteArray QNetworkRequest::rawHeader ( const QByteArray & headerName ) const
which returns the raw form of header named headerName.
Are you talking about the values on the get method?
int i= 0;
QPair<QString , QString > values;
while( i < ui->webView->url().queryItems().count() )
{
values = ui->webView->url().queryItems().at( i );
i++;
}

Qt check for valid URL

I am trying to create a Qt application which checks if a URL entered by the user into a text edit is valid.
This is what I have so far but it only ever says the URL entered is valid, even when I enter one which is not.
bool checkUrl(const QUrl &url) {
if (!url.isValid()) {
//qDebug(QString("Invalid URL: %1").arg(url.toString()));
return false;
}
return true;
}
void MainWindow::on_pushButton_clicked()
{
QString usertext = ui->plainTextEdit->toPlainText();
QUrl url = QUrl::fromUserInput(usertext);
if (checkUrl(url))
ui->textEdit->setPlainText("Valid URL.");
else
ui->textEdit->setPlainText("Invalid URL.");
}
Also on the qDebug line there is an error:
/home/user/HTML/mainwindow.cpp:32: error: no matching function for call to ‘qDebug(QString)’
Does anyone know what the problem is as it keeps returning true?
You should use qDebug like this:
qDebug() << QString("Invalid URL: %1").arg(url.toString());
also note that QUrl::isValid() does not check syntax of url. You may want to use regular expressions to validate urls.
QUrl::isValid() only basically checks if the character encoding is right. What are you considering a wrong url?
Re qDebug, the form you use basically encapsulates printf, so it doesn't work with QString. You want to do:
qDebug() << QString("Invalid URL: %1").arg(url.toString());