/* Copyright (c) 2012-2013 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "googletranslator.h" #include "translatorutil.h" #include "translatordebugdialog.h" #include #include #include #include #include using namespace PimCommon; GoogleTranslator::GoogleTranslator() : AbstractTranslator(), mNetworkAccessManager(new QNetworkAccessManager(this)) { connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotTranslateFinished(QNetworkReply*))); } GoogleTranslator::~GoogleTranslator() { } QMap > GoogleTranslator::initListLanguage(KComboBox *from) { QMap > listLanguage; QList > fullListLanguage; fullListLanguage.append(TranslatorUtil::automatic); fullListLanguage.append(TranslatorUtil::en); fullListLanguage.append(TranslatorUtil::nl); fullListLanguage.append(TranslatorUtil::fr); fullListLanguage.append(TranslatorUtil::de); fullListLanguage.append(TranslatorUtil::el); fullListLanguage.append(TranslatorUtil::it); fullListLanguage.append(TranslatorUtil::ja); fullListLanguage.append(TranslatorUtil::ko); fullListLanguage.append(TranslatorUtil::pt); fullListLanguage.append(TranslatorUtil::ru); fullListLanguage.append(TranslatorUtil::es); fullListLanguage.append(TranslatorUtil::af); fullListLanguage.append(TranslatorUtil::sq); fullListLanguage.append(TranslatorUtil::ar); fullListLanguage.append(TranslatorUtil::hy); fullListLanguage.append(TranslatorUtil::az); fullListLanguage.append(TranslatorUtil::eu); fullListLanguage.append(TranslatorUtil::be); fullListLanguage.append(TranslatorUtil::bg); fullListLanguage.append(TranslatorUtil::ca); fullListLanguage.append(TranslatorUtil::zh_cn_google); // For google only fullListLanguage.append(TranslatorUtil::zh_tw_google); // For google only fullListLanguage.append(TranslatorUtil::hr); fullListLanguage.append(TranslatorUtil::cs); fullListLanguage.append(TranslatorUtil::da); fullListLanguage.append(TranslatorUtil::et); fullListLanguage.append(TranslatorUtil::tl); fullListLanguage.append(TranslatorUtil::fi); fullListLanguage.append(TranslatorUtil::gl); fullListLanguage.append(TranslatorUtil::ka); fullListLanguage.append(TranslatorUtil::ht); fullListLanguage.append(TranslatorUtil::iw); fullListLanguage.append(TranslatorUtil::hi); fullListLanguage.append(TranslatorUtil::hu); fullListLanguage.append(TranslatorUtil::is); fullListLanguage.append(TranslatorUtil::id); fullListLanguage.append(TranslatorUtil::ga); fullListLanguage.append(TranslatorUtil::lv); fullListLanguage.append(TranslatorUtil::lt); fullListLanguage.append(TranslatorUtil::mk); fullListLanguage.append(TranslatorUtil::ms); fullListLanguage.append(TranslatorUtil::mt); fullListLanguage.append(TranslatorUtil::no); fullListLanguage.append(TranslatorUtil::fa); fullListLanguage.append(TranslatorUtil::pl); fullListLanguage.append(TranslatorUtil::ro); fullListLanguage.append(TranslatorUtil::sr); fullListLanguage.append(TranslatorUtil::sk); fullListLanguage.append(TranslatorUtil::sl); fullListLanguage.append(TranslatorUtil::sw); fullListLanguage.append(TranslatorUtil::sv); fullListLanguage.append(TranslatorUtil::th); fullListLanguage.append(TranslatorUtil::tr); fullListLanguage.append(TranslatorUtil::uk); fullListLanguage.append(TranslatorUtil::ur); fullListLanguage.append(TranslatorUtil::vi); fullListLanguage.append(TranslatorUtil::cy); fullListLanguage.append(TranslatorUtil::yi); const int fullListLanguageSize(fullListLanguage.count()); for (int i=0;i currentLanguage = fullListLanguage.at(i); PimCommon::TranslatorUtil::addItemToFromComboBox( from, currentLanguage ); QMap toList; for (int j=0;jpost(request, postData.encodedQuery()); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); } void GoogleTranslator::slotError(QNetworkReply::NetworkError /*error*/) { Q_EMIT translateFailed(false); } void GoogleTranslator::slotTranslateFinished(QNetworkReply *reply) { mJsonData = QString::fromUtf8(reply->readAll()); reply->deleteLater(); // jsonData contains arrays like this: ["foo",,"bar"] // but this is not valid JSON for QJSON, it expects empty strings: ["foo","","bar"] mJsonData = mJsonData.replace(QRegExp(QLatin1String(",{3,3}")), QLatin1String(",\"\",\"\",")); mJsonData = mJsonData.replace(QRegExp(QLatin1String(",{2,2}")), QLatin1String(",\"\",")); //qDebug() << mJsonData; QJson::Parser parser; bool ok; const QVariantList json = parser.parse(mJsonData.toUtf8(), &ok).toList(); if (!ok) { Q_EMIT translateFailed(ok); return; } //qDebug()<<" json"< > sentences; // we are going recursively through the nested json-array // level0 contains the data of the outer array, level1 of the next one and so on Q_FOREACH (const QVariant& level0, json) { const QVariantList listLevel0 = level0.toList(); if (listLevel0.isEmpty()) { continue; } Q_FOREACH (const QVariant& level1, listLevel0) { if (level1.toList().size() <= 2 || level1.toList().at(2).toList().isEmpty()) { continue; } const int indexLevel1 = listLevel0.indexOf(level1); const QVariantList listLevel1 = level1.toList().at(2).toList(); foreach (const QVariant& level2, listLevel1) { const QVariantList listLevel2 = level2.toList(); // The JSON we get from Google has not always the same structure. // There is a version with additional information like synonyms and frequency, // this is called newVersion oldVersion doesn't cointain something like this. const bool foundWordNew = (listLevel2.size() > 1) && (!listLevel2.at(1).toList().isEmpty()); const bool foundWordOld = (listLevel2.size() == 4) && (oldVersion == true) && (listLevel2.at(1).toDouble() > 0); if (foundWordNew || foundWordOld) { if (!level1.toList().at(0).toString().isEmpty() && foundWordOld) { // sentences are translated phrase by phrase // first we have to add all phrases to sentences and then rebuild them sentences.insert(indexLevel1, qMakePair(listLevel2.at(0).toString(), listLevel2.at(1).toDouble() / 1000)); } else { if (foundWordNew) { oldVersion = false; mResult = listLevel2.at(0).toString(); } } } } } } if (!sentences.isEmpty()) { QPair pair; QMapIterator > it(sentences); int currentKey = -1; double currentRel = 1; QString currentString; while (it.hasNext()) { pair = it.next().value(); // we're on to another key, process previous results, if any if (currentKey != it.key()) { currentKey = it.key(); currentRel = 1; currentString.append(QLatin1Char(' ')).append(pair.first); currentRel *= pair.second; } } if (!currentString.isEmpty()) { mResult = currentString; Q_EMIT translateDone(); } } else { //Same value mResult = mInputText; Q_EMIT translateDone(); } } void GoogleTranslator::debug() { #if !defined(NDEBUG) QPointer dlg = new TranslatorDebugDialog; dlg->setDebug(mJsonData); dlg->exec(); delete dlg; #endif } void GoogleTranslator::clear() { mJsonData.clear(); }