From e2552ec6737fe734ffd5b4768193c6a890d66f70 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine
Date: Tue, 6 Sep 2011 17:45:47 +0300
Subject: STORM-1577 WIP Implemented translation via Microsoft Translator and
Google Translate v2 APIs.
---
indra/newview/lltranslate.cpp | 312 +++++++++++++++++++++++++++++++++++-------
1 file changed, 260 insertions(+), 52 deletions(-)
(limited to 'indra/newview/lltranslate.cpp')
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 2f60b6b90b..e29ea373ce 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -37,74 +37,263 @@
#include "reader.h"
-// These two are concatenated with the language specifiers to form a complete Google Translate URL
-const char* LLTranslate::m_GoogleURL = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=";
-const char* LLTranslate::m_GoogleLangSpec = "&langpair=";
-float LLTranslate::m_GoogleTimeout = 5;
-
-LLSD LLTranslate::m_Header;
-// These constants are for the GET header.
-const char* LLTranslate::m_AcceptHeader = "Accept";
-const char* LLTranslate::m_AcceptType = "text/plain";
-const char* LLTranslate::m_AgentHeader = "User-Agent";
-
-// These constants are in the JSON returned from Google
-const char* LLTranslate::m_GoogleData = "responseData";
-const char* LLTranslate::m_GoogleTranslation = "translatedText";
-const char* LLTranslate::m_GoogleLanguage = "detectedSourceLanguage";
+class LLTranslationAPIHandler
+{
+public:
+ virtual void getTranslateURL(
+ std::string &url,
+ const std::string &from_lang,
+ const std::string &to_lang,
+ const std::string &text) const = 0;
-//static
-void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &from_lang, const std::string &to_lang, const std::string &mesg)
+ virtual bool parseResponse(
+ int& status,
+ const std::string& body,
+ std::string& translation,
+ std::string& detected_lang,
+ std::string& err_msg) const = 0;
+
+ virtual ~LLTranslationAPIHandler() {}
+
+protected:
+ static const int STATUS_OK = 200;
+};
+
+class LLGoogleV1Handler : public LLTranslationAPIHandler
{
- std::string url;
- getTranslateUrl(url, from_lang, to_lang, mesg);
+ LOG_CLASS(LLGoogleV1Handler);
+
+public:
+ /*virtual*/ void getTranslateURL(
+ std::string &url,
+ const std::string &from_lang,
+ const std::string &to_lang,
+ const std::string &text) const
+ {
+ url = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="
+ + LLURI::escape(text)
+ + "&langpair=" + from_lang + "%7C" + to_lang;
+ }
+
+ /*virtual*/ bool parseResponse(
+ int& status,
+ const std::string& body,
+ std::string& translation,
+ std::string& detected_lang,
+ std::string& err_msg) const
+ {
+ Json::Value root;
+ Json::Reader reader;
+
+ if (!reader.parse(body, root))
+ {
+ err_msg = reader.getFormatedErrorMessages();
+ return false;
+ }
+
+ // This API doesn't return proper status in the HTTP response header,
+ // but it is in the body.
+ status = root["responseStatus"].asInt();
+ if (status != STATUS_OK)
+ {
+ err_msg = root["responseDetails"].asString();
+ return false;
+ }
+
+ const Json::Value& response_data = root["responseData"];
+ translation = response_data.get("translatedText", "").asString();
+ detected_lang = response_data.get("detectedSourceLanguage", "").asString();
+ return true;
+ }
+};
+
+class LLGoogleV2Handler : public LLTranslationAPIHandler
+{
+ LOG_CLASS(LLGoogleV2Handler);
+
+public:
+ /*virtual*/ void getTranslateURL(
+ std::string &url,
+ const std::string &from_lang,
+ const std::string &to_lang,
+ const std::string &text) const
+ {
+ url = std::string("https://www.googleapis.com/language/translate/v2?key=")
+ + getAPIKey() + "&q=" + LLURI::escape(text) + "&target=" + to_lang;
+ if (!from_lang.empty())
+ {
+ url += "&source=" + from_lang;
+ }
+ }
+
+ /*virtual*/ bool parseResponse(
+ int& status,
+ const std::string& body,
+ std::string& translation,
+ std::string& detected_lang,
+ std::string& err_msg) const
+ {
+ Json::Value root;
+ Json::Reader reader;
+
+ if (!reader.parse(body, root))
+ {
+ err_msg = reader.getFormatedErrorMessages();
+ return false;
+ }
+
+ if (status != STATUS_OK)
+ {
+ const Json::Value& error = root["error"];
+ err_msg = error["message"].asString();
+ status = error["code"].asInt();
+ return false;
+ }
+
+ const Json::Value& response_data = root["data"]["translations"][0U];
+ translation = response_data["translatedText"].asString();
+ detected_lang = response_data["detectedSourceLanguage"].asString();
+ return true;
+ }
+
+private:
+ static std::string getAPIKey()
+ {
+ return gSavedSettings.getString("GoogleTranslateAPIv2Key");
+ }
+};
+
+class LLBingHandler : public LLTranslationAPIHandler
+{
+ LOG_CLASS(LLBingHandler);
- std::string user_agent = llformat("%s %d.%d.%d (%d)",
- LLVersionInfo::getChannel().c_str(),
- LLVersionInfo::getMajor(),
- LLVersionInfo::getMinor(),
- LLVersionInfo::getPatch(),
- LLVersionInfo::getBuild());
+public:
+ /*virtual*/ void getTranslateURL(
+ std::string &url,
+ const std::string &from_lang,
+ const std::string &to_lang,
+ const std::string &text) const
+ {
+ url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=")
+ + getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + to_lang;
+ if (!from_lang.empty())
+ {
+ url += "&from=" + from_lang;
+ }
+ }
- if (!m_Header.size())
+ /*virtual*/ bool parseResponse(
+ int& status,
+ const std::string& body,
+ std::string& translation,
+ std::string& detected_lang,
+ std::string& err_msg) const
{
- m_Header.insert(m_AcceptHeader, LLSD(m_AcceptType));
- m_Header.insert(m_AgentHeader, LLSD(user_agent));
+ if (status != STATUS_OK)
+ {
+ size_t begin = body.find("Message: ");
+ size_t end = body.find("
", begin);
+ err_msg = body.substr(begin, end-begin);
+ LLStringUtil::replaceString(err_msg, "
", ""); // strip CR
+ return false;
+ }
+
+ // Sample response: Hola
+ size_t begin = body.find(">");
+ if (begin == std::string::npos || begin >= (body.size() - 1))
+ {
+ return false;
+ }
+
+ size_t end = body.find("", ++begin);
+ if (end == std::string::npos || end < begin)
+ {
+ return false;
+ }
+
+ detected_lang = ""; // unsupported by this API
+ translation = body.substr(begin, end-begin);
+ LLStringUtil::replaceString(translation, "
", ""); // strip CR
+ return true;
}
- LLHTTPClient::get(url, result, m_Header, m_GoogleTimeout);
+private:
+ static std::string getAPIKey()
+ {
+ return gSavedSettings.getString("BingTranslateAPIKey");
+ }
+};
+
+LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_lang, const std::string& to_lang)
+: mFromLang(from_lang)
+, mToLang(to_lang)
+, mHandler(LLTranslate::getPreferredHandler())
+{
}
-//static
-void LLTranslate::getTranslateUrl(std::string &translate_url, const std::string &from_lang, const std::string &to_lang, const std::string &mesg)
+// virtual
+void LLTranslate::TranslationReceiver::completedRaw(
+ U32 http_status,
+ const std::string& reason,
+ const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer)
{
- char * curl_str = curl_escape(mesg.c_str(), mesg.size());
- std::string const escaped_mesg(curl_str);
- curl_free(curl_str);
-
- translate_url = m_GoogleURL
- + escaped_mesg + m_GoogleLangSpec
- + from_lang // 'from' language; empty string for auto
- + "%7C" // |
- + to_lang; // 'to' language
+ LLBufferStream istr(channels, buffer.get());
+ std::stringstream strstrm;
+ strstrm << istr.rdbuf();
+
+ const std::string body = strstrm.str();
+ std::string translation, detected_lang, err_msg;
+ int status = http_status;
+ if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg))
+ {
+ // Fix up the response
+ LLStringUtil::replaceString(translation, "<", "<");
+ LLStringUtil::replaceString(translation, ">",">");
+ LLStringUtil::replaceString(translation, ""","\"");
+ LLStringUtil::replaceString(translation, "'","'");
+ LLStringUtil::replaceString(translation, "&","&");
+ LLStringUtil::replaceString(translation, "'","'");
+
+ handleResponse(translation, detected_lang);
+ }
+ else
+ {
+ llwarns << "Translation request failed: " << err_msg << llendl;
+ LL_DEBUGS("Translate") << "HTTP status: " << status << " " << reason << LL_ENDL;
+ LL_DEBUGS("Translate") << "Error response body: " << body << LL_ENDL;
+ handleFailure(status, err_msg);
+ }
}
//static
-bool LLTranslate::parseGoogleTranslate(const std::string& body, std::string &translation, std::string &detected_language)
+void LLTranslate::translateMessage(
+ TranslationReceiverPtr &receiver,
+ const std::string &from_lang,
+ const std::string &to_lang,
+ const std::string &mesg)
{
- Json::Value root;
- Json::Reader reader;
-
- bool success = reader.parse(body, root);
- if (!success)
+ std::string url;
+ receiver->mHandler.getTranslateURL(url, from_lang, to_lang, mesg);
+
+ static const float REQUEST_TIMEOUT = 5;
+ static LLSD sHeader;
+
+ if (!sHeader.size())
{
- LL_WARNS("Translate") << "Non valid response from Google Translate API: '" << reader.getFormatedErrorMessages() << "'" << LL_ENDL;
- return false;
+ std::string user_agent = llformat("%s %d.%d.%d (%d)",
+ LLVersionInfo::getChannel().c_str(),
+ LLVersionInfo::getMajor(),
+ LLVersionInfo::getMinor(),
+ LLVersionInfo::getPatch(),
+ LLVersionInfo::getBuild());
+
+ sHeader.insert("Accept", "text/plain");
+ sHeader.insert("User-Agent", user_agent);
}
-
- translation = root[m_GoogleData].get(m_GoogleTranslation, "").asString();
- detected_language = root[m_GoogleData].get(m_GoogleLanguage, "").asString();
- return true;
+
+ LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL;
+ LLHTTPClient::get(url, receiver, sHeader, REQUEST_TIMEOUT);
}
//static
@@ -119,3 +308,22 @@ std::string LLTranslate::getTranslateLanguage()
return language;
}
+// static
+const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
+{
+ static LLGoogleV1Handler google_v1;
+ static LLGoogleV2Handler google_v2;
+ static LLBingHandler bing;
+
+ std::string service = gSavedSettings.getString("TranslationService");
+ if (service == "google_v2")
+ {
+ return google_v2;
+ }
+ else if (service == "google_v1")
+ {
+ return google_v1;
+ }
+
+ return bing;
+}
--
cgit v1.2.3
From 7975ab138b6ac54fc831613e4d3dfb913c5efbd2 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine
Date: Wed, 7 Sep 2011 16:14:47 +0300
Subject: STORM-1577 Removed support for Google Translate v1 API.
---
indra/newview/lltranslate.cpp | 67 +++++--------------------------------------
1 file changed, 7 insertions(+), 60 deletions(-)
(limited to 'indra/newview/lltranslate.cpp')
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index e29ea373ce..6576cbbe64 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -59,57 +59,9 @@ protected:
static const int STATUS_OK = 200;
};
-class LLGoogleV1Handler : public LLTranslationAPIHandler
+class LLGoogleHandler : public LLTranslationAPIHandler
{
- LOG_CLASS(LLGoogleV1Handler);
-
-public:
- /*virtual*/ void getTranslateURL(
- std::string &url,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &text) const
- {
- url = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="
- + LLURI::escape(text)
- + "&langpair=" + from_lang + "%7C" + to_lang;
- }
-
- /*virtual*/ bool parseResponse(
- int& status,
- const std::string& body,
- std::string& translation,
- std::string& detected_lang,
- std::string& err_msg) const
- {
- Json::Value root;
- Json::Reader reader;
-
- if (!reader.parse(body, root))
- {
- err_msg = reader.getFormatedErrorMessages();
- return false;
- }
-
- // This API doesn't return proper status in the HTTP response header,
- // but it is in the body.
- status = root["responseStatus"].asInt();
- if (status != STATUS_OK)
- {
- err_msg = root["responseDetails"].asString();
- return false;
- }
-
- const Json::Value& response_data = root["responseData"];
- translation = response_data.get("translatedText", "").asString();
- detected_lang = response_data.get("detectedSourceLanguage", "").asString();
- return true;
- }
-};
-
-class LLGoogleV2Handler : public LLTranslationAPIHandler
-{
- LOG_CLASS(LLGoogleV2Handler);
+ LOG_CLASS(LLGoogleHandler);
public:
/*virtual*/ void getTranslateURL(
@@ -159,7 +111,7 @@ public:
private:
static std::string getAPIKey()
{
- return gSavedSettings.getString("GoogleTranslateAPIv2Key");
+ return gSavedSettings.getString("GoogleTranslateAPIKey");
}
};
@@ -311,18 +263,13 @@ std::string LLTranslate::getTranslateLanguage()
// static
const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
{
- static LLGoogleV1Handler google_v1;
- static LLGoogleV2Handler google_v2;
- static LLBingHandler bing;
+ static LLGoogleHandler google;
+ static LLBingHandler bing;
std::string service = gSavedSettings.getString("TranslationService");
- if (service == "google_v2")
- {
- return google_v2;
- }
- else if (service == "google_v1")
+ if (service == "google")
{
- return google_v1;
+ return google;
}
return bing;
--
cgit v1.2.3
From 1fad7d997d99715cc88b6e69ae325f28be413206 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine
Date: Wed, 7 Sep 2011 19:12:35 +0300
Subject: STORM-1577 Made parsing translation responses more robust.
JsonCpp is prone to aborting the program on failed assertions,
so be super-careful and verify the response format.
---
indra/newview/lltranslate.cpp | 72 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 64 insertions(+), 8 deletions(-)
(limited to 'indra/newview/lltranslate.cpp')
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 6576cbbe64..895d8f78eb 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -31,6 +31,7 @@
#include
#include "llbufferstream.h"
+#include "lltrans.h"
#include "llui.h"
#include "llversioninfo.h"
#include "llviewercontrol.h"
@@ -94,21 +95,66 @@ public:
return false;
}
+ if (!root.isObject()) // empty response? should not happen
+ {
+ return false;
+ }
+
if (status != STATUS_OK)
{
- const Json::Value& error = root["error"];
- err_msg = error["message"].asString();
- status = error["code"].asInt();
+ // Request failed. Extract error message from the response.
+ parseErrorResponse(root, status, err_msg);
return false;
}
- const Json::Value& response_data = root["data"]["translations"][0U];
- translation = response_data["translatedText"].asString();
- detected_lang = response_data["detectedSourceLanguage"].asString();
- return true;
+ // Request succeeded, extract translation from the response.
+ return parseTranslation(root, translation, detected_lang);
}
private:
+ static void parseErrorResponse(
+ const Json::Value& root,
+ int& status,
+ std::string& err_msg)
+ {
+ const Json::Value& error = root.get("error", 0);
+ if (!error.isObject() || !error.isMember("message") || !error.isMember("code"))
+ {
+ return;
+ }
+
+ err_msg = error["message"].asString();
+ status = error["code"].asInt();
+ }
+
+ static bool parseTranslation(
+ const Json::Value& root,
+ std::string& translation,
+ std::string& detected_lang)
+ {
+ const Json::Value& data = root.get("data", 0);
+ if (!data.isObject() || !data.isMember("translations"))
+ {
+ return false;
+ }
+
+ const Json::Value& translations = data["translations"];
+ if (!translations.isArray() || translations.size() == 0)
+ {
+ return false;
+ }
+
+ const Json::Value& first = translations[0U];
+ if (!first.isObject() || !first.isMember("translatedText"))
+ {
+ return false;
+ }
+
+ translation = first["translatedText"].asString();
+ detected_lang = first.get("detectedSourceLanguage", "").asString();
+ return true;
+ }
+
static std::string getAPIKey()
{
return gSavedSettings.getString("GoogleTranslateAPIKey");
@@ -143,7 +189,12 @@ public:
{
if (status != STATUS_OK)
{
- size_t begin = body.find("Message: ");
+ static const std::string MSG_BEGIN_MARKER = "Message: ";
+ size_t begin = body.find(MSG_BEGIN_MARKER);
+ if (begin != std::string::npos)
+ {
+ begin += MSG_BEGIN_MARKER.size();
+ }
size_t end = body.find("", begin);
err_msg = body.substr(begin, end-begin);
LLStringUtil::replaceString(err_msg, "
", ""); // strip CR
@@ -211,6 +262,11 @@ void LLTranslate::TranslationReceiver::completedRaw(
}
else
{
+ if (err_msg.empty())
+ {
+ err_msg = LLTrans::getString("TranslationResponseParseError");
+ }
+
llwarns << "Translation request failed: " << err_msg << llendl;
LL_DEBUGS("Translate") << "HTTP status: " << status << " " << reason << LL_ENDL;
LL_DEBUGS("Translate") << "Error response body: " << body << LL_ENDL;
--
cgit v1.2.3
From a21a55482a076aa690ca947411f439dd14d59443 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine
Date: Fri, 9 Sep 2011 20:09:01 +0300
Subject: STORM-1577 WIP Added unit tests.
By the way, fixed minor parsing bugs.
---
indra/newview/lltranslate.cpp | 295 +++++++++++++++++++-----------------------
1 file changed, 136 insertions(+), 159 deletions(-)
(limited to 'indra/newview/lltranslate.cpp')
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 895d8f78eb..a74b252c68 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -38,194 +38,171 @@
#include "reader.h"
-class LLTranslationAPIHandler
-{
-public:
- virtual void getTranslateURL(
- std::string &url,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &text) const = 0;
-
- virtual bool parseResponse(
- int& status,
- const std::string& body,
- std::string& translation,
- std::string& detected_lang,
- std::string& err_msg) const = 0;
-
- virtual ~LLTranslationAPIHandler() {}
-
-protected:
- static const int STATUS_OK = 200;
-};
-
-class LLGoogleHandler : public LLTranslationAPIHandler
+// virtual
+void LLGoogleTranslationHandler::getTranslateURL(
+ std::string &url,
+ const std::string &from_lang,
+ const std::string &to_lang,
+ const std::string &text) const
{
- LOG_CLASS(LLGoogleHandler);
-
-public:
- /*virtual*/ void getTranslateURL(
- std::string &url,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &text) const
+ url = std::string("https://www.googleapis.com/language/translate/v2?key=")
+ + getAPIKey() + "&q=" + LLURI::escape(text) + "&target=" + to_lang;
+ if (!from_lang.empty())
{
- url = std::string("https://www.googleapis.com/language/translate/v2?key=")
- + getAPIKey() + "&q=" + LLURI::escape(text) + "&target=" + to_lang;
- if (!from_lang.empty())
- {
- url += "&source=" + from_lang;
- }
+ url += "&source=" + from_lang;
}
+}
- /*virtual*/ bool parseResponse(
- int& status,
- const std::string& body,
- std::string& translation,
- std::string& detected_lang,
- std::string& err_msg) const
- {
- Json::Value root;
- Json::Reader reader;
-
- if (!reader.parse(body, root))
- {
- err_msg = reader.getFormatedErrorMessages();
- return false;
- }
-
- if (!root.isObject()) // empty response? should not happen
- {
- return false;
- }
-
- if (status != STATUS_OK)
- {
- // Request failed. Extract error message from the response.
- parseErrorResponse(root, status, err_msg);
- return false;
- }
+// virtual
+bool LLGoogleTranslationHandler::parseResponse(
+ int& status,
+ const std::string& body,
+ std::string& translation,
+ std::string& detected_lang,
+ std::string& err_msg) const
+{
+ Json::Value root;
+ Json::Reader reader;
- // Request succeeded, extract translation from the response.
- return parseTranslation(root, translation, detected_lang);
+ if (!reader.parse(body, root))
+ {
+ err_msg = reader.getFormatedErrorMessages();
+ return false;
}
-private:
- static void parseErrorResponse(
- const Json::Value& root,
- int& status,
- std::string& err_msg)
+ if (!root.isObject()) // empty response? should not happen
{
- const Json::Value& error = root.get("error", 0);
- if (!error.isObject() || !error.isMember("message") || !error.isMember("code"))
- {
- return;
- }
+ return false;
+ }
- err_msg = error["message"].asString();
- status = error["code"].asInt();
+ if (status != STATUS_OK)
+ {
+ // Request failed. Extract error message from the response.
+ parseErrorResponse(root, status, err_msg);
+ return false;
}
- static bool parseTranslation(
- const Json::Value& root,
- std::string& translation,
- std::string& detected_lang)
+ // Request succeeded, extract translation from the response.
+ return parseTranslation(root, translation, detected_lang);
+}
+
+// static
+void LLGoogleTranslationHandler::parseErrorResponse(
+ const Json::Value& root,
+ int& status,
+ std::string& err_msg)
+{
+ const Json::Value& error = root.get("error", 0);
+ if (!error.isObject() || !error.isMember("message") || !error.isMember("code"))
{
- const Json::Value& data = root.get("data", 0);
- if (!data.isObject() || !data.isMember("translations"))
- {
- return false;
- }
+ return;
+ }
- const Json::Value& translations = data["translations"];
- if (!translations.isArray() || translations.size() == 0)
- {
- return false;
- }
+ err_msg = error["message"].asString();
+ status = error["code"].asInt();
+}
- const Json::Value& first = translations[0U];
- if (!first.isObject() || !first.isMember("translatedText"))
- {
- return false;
- }
+// static
+bool LLGoogleTranslationHandler::parseTranslation(
+ const Json::Value& root,
+ std::string& translation,
+ std::string& detected_lang)
+{
+ const Json::Value& data = root.get("data", 0);
+ if (!data.isObject() || !data.isMember("translations"))
+ {
+ return false;
+ }
- translation = first["translatedText"].asString();
- detected_lang = first.get("detectedSourceLanguage", "").asString();
- return true;
+ const Json::Value& translations = data["translations"];
+ if (!translations.isArray() || translations.size() == 0)
+ {
+ return false;
}
- static std::string getAPIKey()
+ const Json::Value& first = translations[0U];
+ if (!first.isObject() || !first.isMember("translatedText"))
{
- return gSavedSettings.getString("GoogleTranslateAPIKey");
+ return false;
}
-};
-class LLBingHandler : public LLTranslationAPIHandler
+ translation = first["translatedText"].asString();
+ detected_lang = first.get("detectedSourceLanguage", "").asString();
+ return true;
+}
+
+// static
+std::string LLGoogleTranslationHandler::getAPIKey()
+{
+ return gSavedSettings.getString("GoogleTranslateAPIKey");
+}
+
+// virtual
+void LLBingTranslarionHandler::getTranslateURL(
+ std::string &url,
+ const std::string &from_lang,
+ const std::string &to_lang,
+ const std::string &text) const
{
- LOG_CLASS(LLBingHandler);
-
-public:
- /*virtual*/ void getTranslateURL(
- std::string &url,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &text) const
+ url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=")
+ + getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + to_lang;
+ if (!from_lang.empty())
{
- url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=")
- + getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + to_lang;
- if (!from_lang.empty())
- {
- url += "&from=" + from_lang;
- }
+ url += "&from=" + from_lang;
}
+}
- /*virtual*/ bool parseResponse(
- int& status,
- const std::string& body,
- std::string& translation,
- std::string& detected_lang,
- std::string& err_msg) const
+// virtual
+bool LLBingTranslarionHandler::parseResponse(
+ int& status,
+ const std::string& body,
+ std::string& translation,
+ std::string& detected_lang,
+ std::string& err_msg) const
+{
+ if (status != STATUS_OK)
{
- if (status != STATUS_OK)
+ static const std::string MSG_BEGIN_MARKER = "Message: ";
+ size_t begin = body.find(MSG_BEGIN_MARKER);
+ if (begin != std::string::npos)
{
- static const std::string MSG_BEGIN_MARKER = "Message: ";
- size_t begin = body.find(MSG_BEGIN_MARKER);
- if (begin != std::string::npos)
- {
- begin += MSG_BEGIN_MARKER.size();
- }
- size_t end = body.find("", begin);
- err_msg = body.substr(begin, end-begin);
- LLStringUtil::replaceString(err_msg, "
", ""); // strip CR
- return false;
+ begin += MSG_BEGIN_MARKER.size();
}
-
- // Sample response: Hola
- size_t begin = body.find(">");
- if (begin == std::string::npos || begin >= (body.size() - 1))
+ else
{
- return false;
+ begin = 0;
+ err_msg.clear();
}
-
- size_t end = body.find("", ++begin);
- if (end == std::string::npos || end < begin)
- {
- return false;
- }
-
- detected_lang = ""; // unsupported by this API
- translation = body.substr(begin, end-begin);
- LLStringUtil::replaceString(translation, "
", ""); // strip CR
- return true;
+ size_t end = body.find("", begin);
+ err_msg = body.substr(begin, end-begin);
+ LLStringUtil::replaceString(err_msg, "
", ""); // strip CR
+ return false;
}
-private:
- static std::string getAPIKey()
+ // Sample response: Hola
+ size_t begin = body.find(">");
+ if (begin == std::string::npos || begin >= (body.size() - 1))
{
- return gSavedSettings.getString("BingTranslateAPIKey");
+ begin = 0;
}
-};
+ else
+ {
+ ++begin;
+ }
+
+ size_t end = body.find("", begin);
+
+ detected_lang = ""; // unsupported by this API
+ translation = body.substr(begin, end-begin);
+ LLStringUtil::replaceString(translation, "
", ""); // strip CR
+ return true;
+}
+
+// static
+std::string LLBingTranslarionHandler::getAPIKey()
+{
+ return gSavedSettings.getString("BingTranslateAPIKey");
+}
LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_lang, const std::string& to_lang)
: mFromLang(from_lang)
@@ -248,6 +225,8 @@ void LLTranslate::TranslationReceiver::completedRaw(
const std::string body = strstrm.str();
std::string translation, detected_lang, err_msg;
int status = http_status;
+ LL_DEBUGS("Translate") << "HTTP status: " << status << " " << reason << LL_ENDL;
+ LL_DEBUGS("Translate") << "Response body: " << body << LL_ENDL;
if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg))
{
// Fix up the response
@@ -268,8 +247,6 @@ void LLTranslate::TranslationReceiver::completedRaw(
}
llwarns << "Translation request failed: " << err_msg << llendl;
- LL_DEBUGS("Translate") << "HTTP status: " << status << " " << reason << LL_ENDL;
- LL_DEBUGS("Translate") << "Error response body: " << body << LL_ENDL;
handleFailure(status, err_msg);
}
}
@@ -319,8 +296,8 @@ std::string LLTranslate::getTranslateLanguage()
// static
const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
{
- static LLGoogleHandler google;
- static LLBingHandler bing;
+ static LLGoogleTranslationHandler google;
+ static LLBingTranslarionHandler bing;
std::string service = gSavedSettings.getString("TranslationService");
if (service == "google")
--
cgit v1.2.3
From 8652b2d1052b989e32f4462a07372901d37f9586 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine
Date: Tue, 13 Sep 2011 03:05:57 +0300
Subject: STORM-1577 WIP Added API key verification to the translation settings
floater; new layout.
---
indra/newview/lltranslate.cpp | 107 +++++++++++++++++++++++++++++++++++-------
1 file changed, 89 insertions(+), 18 deletions(-)
(limited to 'indra/newview/lltranslate.cpp')
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index a74b252c68..7b99c20a58 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -53,6 +53,15 @@ void LLGoogleTranslationHandler::getTranslateURL(
}
}
+// virtual
+void LLGoogleTranslationHandler::getKeyVerificationURL(
+ std::string& url,
+ const std::string& key) const
+{
+ url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=")
+ + key + "&target=en";
+}
+
// virtual
bool LLGoogleTranslationHandler::parseResponse(
int& status,
@@ -152,6 +161,15 @@ void LLBingTranslarionHandler::getTranslateURL(
}
}
+// virtual
+void LLBingTranslarionHandler::getKeyVerificationURL(
+ std::string& url,
+ const std::string& key) const
+{
+ url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=")
+ + key;
+}
+
// virtual
bool LLBingTranslarionHandler::parseResponse(
int& status,
@@ -251,6 +269,27 @@ void LLTranslate::TranslationReceiver::completedRaw(
}
}
+LLTranslate::KeyVerificationReceiver::KeyVerificationReceiver(EService service)
+: mService(service)
+{
+}
+
+LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const
+{
+ return mService;
+}
+
+// virtual
+void LLTranslate::KeyVerificationReceiver::completedRaw(
+ U32 http_status,
+ const std::string& reason,
+ const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer)
+{
+ bool ok = (http_status == 200);
+ setVerificationStatus(ok);
+}
+
//static
void LLTranslate::translateMessage(
TranslationReceiverPtr &receiver,
@@ -261,24 +300,21 @@ void LLTranslate::translateMessage(
std::string url;
receiver->mHandler.getTranslateURL(url, from_lang, to_lang, mesg);
- static const float REQUEST_TIMEOUT = 5;
- static LLSD sHeader;
-
- if (!sHeader.size())
- {
- std::string user_agent = llformat("%s %d.%d.%d (%d)",
- LLVersionInfo::getChannel().c_str(),
- LLVersionInfo::getMajor(),
- LLVersionInfo::getMinor(),
- LLVersionInfo::getPatch(),
- LLVersionInfo::getBuild());
+ LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL;
+ sendRequest(url, receiver);
+}
- sHeader.insert("Accept", "text/plain");
- sHeader.insert("User-Agent", user_agent);
- }
+// static
+void LLTranslate::verifyKey(
+ KeyVerificationReceiverPtr& receiver,
+ const std::string& key)
+{
+ std::string url;
+ const LLTranslationAPIHandler& handler = getHandler(receiver->getService());
+ handler.getKeyVerificationURL(url, key);
- LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL;
- LLHTTPClient::get(url, receiver, sHeader, REQUEST_TIMEOUT);
+ LL_DEBUGS("Translate") << "Sending key verification request: " << url << LL_ENDL;
+ sendRequest(url, receiver);
}
//static
@@ -295,15 +331,50 @@ std::string LLTranslate::getTranslateLanguage()
// static
const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
+{
+ EService service = SERVICE_BING;
+
+ std::string service_str = gSavedSettings.getString("TranslationService");
+ if (service_str == "google")
+ {
+ service = SERVICE_GOOGLE;
+ }
+
+ return getHandler(service);
+}
+
+// static
+const LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
{
static LLGoogleTranslationHandler google;
static LLBingTranslarionHandler bing;
- std::string service = gSavedSettings.getString("TranslationService");
- if (service == "google")
+ if (service == SERVICE_GOOGLE)
{
return google;
}
return bing;
}
+
+// static
+void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder)
+{
+ static const float REQUEST_TIMEOUT = 5;
+ static LLSD sHeader;
+
+ if (!sHeader.size())
+ {
+ std::string user_agent = llformat("%s %d.%d.%d (%d)",
+ LLVersionInfo::getChannel().c_str(),
+ LLVersionInfo::getMajor(),
+ LLVersionInfo::getMinor(),
+ LLVersionInfo::getPatch(),
+ LLVersionInfo::getBuild());
+
+ sHeader.insert("Accept", "text/plain");
+ sHeader.insert("User-Agent", user_agent);
+ }
+
+ LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT);
+}
--
cgit v1.2.3
From 1474f8c9a288dbc475ae8c482ee9961a39e94c0a Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine
Date: Fri, 16 Sep 2011 00:38:17 +0300
Subject: STORM-1577 WIP Addressing review feedback.
* Don't enable the "Verify" button if use just moves cursor in the API key input field.
* Fixed copy&paste error in unit tests.
* Fixed a typo: LLBingTranslarionHandler
* Added Doxygen comments to lltranslate.h.
---
indra/newview/lltranslate.cpp | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
(limited to 'indra/newview/lltranslate.cpp')
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 7b99c20a58..7eb54271f4 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -117,6 +117,8 @@ bool LLGoogleTranslationHandler::parseTranslation(
std::string& translation,
std::string& detected_lang)
{
+ // JsonCpp is prone to aborting the program on failed assertions,
+ // so be super-careful and verify the response format.
const Json::Value& data = root.get("data", 0);
if (!data.isObject() || !data.isMember("translations"))
{
@@ -147,7 +149,7 @@ std::string LLGoogleTranslationHandler::getAPIKey()
}
// virtual
-void LLBingTranslarionHandler::getTranslateURL(
+void LLBingTranslationHandler::getTranslateURL(
std::string &url,
const std::string &from_lang,
const std::string &to_lang,
@@ -162,7 +164,7 @@ void LLBingTranslarionHandler::getTranslateURL(
}
// virtual
-void LLBingTranslarionHandler::getKeyVerificationURL(
+void LLBingTranslationHandler::getKeyVerificationURL(
std::string& url,
const std::string& key) const
{
@@ -171,7 +173,7 @@ void LLBingTranslarionHandler::getKeyVerificationURL(
}
// virtual
-bool LLBingTranslarionHandler::parseResponse(
+bool LLBingTranslationHandler::parseResponse(
int& status,
const std::string& body,
std::string& translation,
@@ -217,7 +219,7 @@ bool LLBingTranslarionHandler::parseResponse(
}
// static
-std::string LLBingTranslarionHandler::getAPIKey()
+std::string LLBingTranslationHandler::getAPIKey()
{
return gSavedSettings.getString("BingTranslateAPIKey");
}
@@ -347,7 +349,7 @@ const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
const LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
{
static LLGoogleTranslationHandler google;
- static LLBingTranslarionHandler bing;
+ static LLBingTranslationHandler bing;
if (service == SERVICE_GOOGLE)
{
--
cgit v1.2.3