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/app_settings/settings.xml | 33 ++++
indra/newview/lltranslate.cpp | 312 ++++++++++++++++++++++++++------
indra/newview/lltranslate.h | 87 ++-------
indra/newview/llviewermessage.cpp | 7 +-
4 files changed, 316 insertions(+), 123 deletions(-)
(limited to 'indra/newview')
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 0996f75fbb..2549538df2 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10922,6 +10922,39 @@
Value
0
+ TranslationService
+
+ GoogleTranslateAPIv2Key
+
+ BingTranslateAPIKey
+
TutorialURL
", 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;
+}
diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h
index e85a42e878..1dee792f7b 100644
--- a/indra/newview/lltranslate.h
+++ b/indra/newview/lltranslate.h
@@ -30,89 +30,42 @@
#include "llhttpclient.h"
#include "llbufferstream.h"
+class LLTranslationAPIHandler;
+
class LLTranslate
{
LOG_CLASS(LLTranslate);
+
public :
class TranslationReceiver: public LLHTTPClient::Responder
{
- protected:
- TranslationReceiver(const std::string &from_lang, const std::string &to_lang)
- : m_fromLang(from_lang),
- m_toLang(to_lang)
- {
- }
-
- virtual void handleResponse(const std::string &translation, const std::string &recognized_lang) {};
- virtual void handleFailure() {};
-
public:
- ~TranslationReceiver()
- {
- }
-
- virtual void completedRaw( U32 status,
- const std::string& reason,
- const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
- {
- if (200 <= status && status < 300)
- {
- LLBufferStream istr(channels, buffer.get());
- std::stringstream strstrm;
- strstrm << istr.rdbuf();
+ /*virtual*/ void completedRaw(
+ U32 http_status,
+ const std::string& reason,
+ const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer);
- const std::string result = strstrm.str();
- std::string translation;
- std::string detected_language;
+ protected:
+ friend class LLTranslate;
- if (!parseGoogleTranslate(result, translation, detected_language))
- {
- handleFailure();
- return;
- }
-
- // Fix up the response
- LLStringUtil::replaceString(translation, "<", "<");
- LLStringUtil::replaceString(translation, ">",">");
- LLStringUtil::replaceString(translation, ""","\"");
- LLStringUtil::replaceString(translation, "'","'");
- LLStringUtil::replaceString(translation, "&","&");
- LLStringUtil::replaceString(translation, "'","'");
+ TranslationReceiver(const std::string& from_lang, const std::string& to_lang);
- handleResponse(translation, detected_language);
- }
- else
- {
- LL_WARNS("Translate") << "HTTP request for Google Translate failed with status " << status << ", reason: " << reason << LL_ENDL;
- handleFailure();
- }
- }
+ virtual void handleResponse(const std::string &translation, const std::string &recognized_lang) = 0;
+ virtual void handleFailure(int status, const std::string& err_msg) = 0;
- protected:
- const std::string m_toLang;
- const std::string m_fromLang;
+ std::string mFromLang;
+ std::string mToLang;
+ const LLTranslationAPIHandler& mHandler;
};
- static void translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &from_lang, const std::string &to_lang, const std::string &mesg);
- static float m_GoogleTimeout;
+ typedef boost::intrusive_ptr TranslationReceiverPtr;
+
+ static void translateMessage(TranslationReceiverPtr &receiver, const std::string &from_lang, const std::string &to_lang, const std::string &mesg);
static std::string getTranslateLanguage();
private:
- static void getTranslateUrl(std::string &translate_url, const std::string &from_lang, const std::string &to_lang, const std::string &text);
- static bool parseGoogleTranslate(const std::string& body, std::string &translation, std::string &detected_language);
-
- static LLSD m_Header;
- static const char* m_GoogleURL;
- static const char* m_GoogleLangSpec;
- static const char* m_AcceptHeader;
- static const char* m_AcceptType;
- static const char* m_AgentHeader;
- static const char* m_UserAgent;
-
- static const char* m_GoogleData;
- static const char* m_GoogleTranslation;
- static const char* m_GoogleLanguage;
+ static const LLTranslationAPIHandler& getPreferredHandler();
};
#endif
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 68745d5aeb..ff02214194 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -3138,7 +3138,7 @@ protected:
{
// filter out non-interesting responeses
if ( !translation.empty()
- && (m_toLang != detected_language)
+ && (mToLang != detected_language)
&& (LLStringUtil::compareInsensitive(translation, m_origMesg) != 0) )
{
m_chat.mText += " (" + translation + ")";
@@ -3147,9 +3147,8 @@ protected:
LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
}
- void handleFailure()
+ void handleFailure(int status, const std::string& err_msg)
{
- LLTranslate::TranslationReceiver::handleFailure();
m_chat.mText += " (?)";
LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
@@ -3388,7 +3387,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
const std::string from_lang = ""; // leave empty to trigger autodetect
const std::string to_lang = LLTranslate::getTranslateLanguage();
- LLHTTPClient::ResponderPtr result = ChatTranslationReceiver::build(from_lang, to_lang, mesg, chat, args);
+ LLTranslate::TranslationReceiverPtr result = ChatTranslationReceiver::build(from_lang, to_lang, mesg, chat, args);
LLTranslate::translateMessage(result, from_lang, to_lang, mesg);
}
else
--
cgit v1.2.3