From 638832455215ff5710d3febf8825aee7c779d316 Mon Sep 17 00:00:00 2001
From: Drake Arconis
Date: Tue, 21 Feb 2012 09:27:10 -0500
Subject: [PATCH] Revert "This works for now. Need to do more testing."
This reverts commit c6d6eed7d33121ac2bbd466ac2e49cccd6f6d921.
---
indra/newview/app_settings/settings.xml | 54 +--
indra/newview/lltranslate.cpp | 465 +++++-------------------
indra/newview/lltranslate.h | 368 +++++--------------
indra/newview/llviewermessage.cpp | 26 +-
4 files changed, 221 insertions(+), 692 deletions(-)
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 7553e8816..2b521fed4 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1,15 +1,16 @@
", 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))
- {
- 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;
-}
-
-// virtual
-bool LLBingTranslationHandler::isConfigured() const
-{
- return !getAPIKey().empty();
-}
-
-// static
-std::string LLBingTranslationHandler::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())
-{
-}
-
-// virtual
-void LLTranslate::TranslationReceiver::completedRaw(
- U32 http_status,
- const std::string& reason,
- const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
-{
- 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;
- 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
- LLStringUtil::replaceString(translation, "<", "<");
- LLStringUtil::replaceString(translation, ">",">");
- LLStringUtil::replaceString(translation, ""","\"");
- LLStringUtil::replaceString(translation, "'","'");
- LLStringUtil::replaceString(translation, "&","&");
- LLStringUtil::replaceString(translation, "'","'");
-
- handleResponse(translation, detected_lang);
- }
- else
- {
- if (err_msg.empty())
- {
- err_msg = LLTrans::getString("TranslationResponseParseError");
- }
-
- llwarns << "Translation request failed: " << err_msg << llendl;
- handleFailure(status, err_msg);
- }
-}
-
-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);
+ LLHTTPClient::get(url, result, m_Header, m_GoogleTimeout);
}
//static
-void LLTranslate::translateMessage(
- TranslationReceiverPtr &receiver,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &mesg)
+void LLTranslate::getTranslateUrl(std::string &translateUrl, const std::string &fromLang, const std::string &toLang, const std::string &mesg)
{
- std::string url;
- receiver->mHandler.getTranslateURL(url, from_lang, to_lang, mesg);
+ std::string escaped_mesg = LLWeb::curlEscape(mesg);
- LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL;
- sendRequest(url, receiver);
+ translateUrl = m_GoogleURL
+ + escaped_mesg + m_GoogleLangSpec
+ + fromLang // 'from' language; empty string for auto
+ + "%7C" // |
+ + toLang; // 'to' language
}
-// static
-void LLTranslate::verifyKey(
- KeyVerificationReceiverPtr& receiver,
- const std::string& key)
+//static
+void LLTranslate::stringReplaceAll(std::string& context, const std::string& from, const std::string& to)
{
- std::string url;
- const LLTranslationAPIHandler& handler = getHandler(receiver->getService());
- handler.getKeyVerificationURL(url, key);
+ size_t lookHere = 0;
+ size_t foundHere;
- LL_DEBUGS("Translate") << "Sending key verification request: " << url << LL_ENDL;
- sendRequest(url, receiver);
+ while((foundHere = context.find(from, lookHere))
+ != std::string::npos) {
+ context.replace(foundHere, from.size(), to);
+ lookHere = foundHere + to.size();
+ }
+}
+
+//static
+BOOL LLTranslate::parseGoogleTranslate(const std::string result, std::string &translation, std::string &detectedLanguage)
+{
+ Json::Value root;
+ Json::Reader reader;
+ BOOL parsingSuccessful = reader.parse(result, root );
+ if ( !parsingSuccessful )
+ {
+ LL_WARNS("JSON") << reader.getFormatedErrorMessages() << LL_ENDL;
+ return FALSE;
+ }
+
+ translation = root[m_GoogleData].get(m_GoogleTranslation, "").asString();
+ detectedLanguage = root[m_GoogleData].get(m_GoogleLanguage, "").asString();
+ return TRUE;
}
//static
std::string LLTranslate::getTranslateLanguage()
{
- std::string language = gSavedSettings.getString("TranslateLanguage");
- if (language.empty() || language == "default")
+ std::string language = "en";
+ if (LLUI::sConfigGroup)
{
- language = LLUI::getLanguage();
+ language = LLUI::sConfigGroup->getString("TranslateLanguage");
+ if (language.empty() || language == "default")
+ {
+ language = LLUI::getLanguage();
+ }
}
language = language.substr(0,2);
return language;
}
-// static
-bool LLTranslate::isTranslationConfigured()
-{
- return getPreferredHandler().isConfigured();
-}
-
-// 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 LLBingTranslationHandler bing;
-
- 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)",
- gVersionChannel,
- gVersionMajor,
- gVersionMinor,
- gVersionPatch,
- gVersionBuild);
-
- sHeader.insert("Accept", "text/plain");
- sHeader.insert("User-Agent", user_agent);
- }
-
- LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT);
-}
diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h
index 870cc1fae..2723c43ff 100644
--- a/indra/newview/lltranslate.h
+++ b/indra/newview/lltranslate.h
@@ -2,27 +2,33 @@
* @file lltranslate.h
* @brief Human language translation class and JSON response receiver.
*
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
#ifndef LL_LLTRANSLATE_H
#define LL_LLTRANSLATE_H
@@ -31,273 +37,89 @@
#include "llbufferstream.h"
#include "jsoncpp/reader.h"
-namespace Json
-{
- class Value;
-}
-
-/**
- * Handler of an HTTP machine translation service.
- *
- * Derived classes know the service URL
- * and how to parse the translation result.
- */
-class LLTranslationAPIHandler
-{
-public:
- /**
- * Get URL for translation of the given string.
- *
- * Sending HTTP GET request to the URL will initiate translation.
- *
- * @param[out] url Place holder for the result.
- * @param from_lang Source language. Leave empty for auto-detection.
- * @param to_lang Target language.
- * @param text Text to translate.
- */
- virtual void getTranslateURL(
- std::string &url,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &text) const = 0;
-
- /**
- * Get URL to verify the given API key.
- *
- * Sending request to the URL verifies the key.
- * Positive HTTP response (code 200) means that the key is valid.
- *
- * @param[out] url Place holder for the URL.
- * @param[in] key Key to verify.
- */
- virtual void getKeyVerificationURL(
- std::string &url,
- const std::string &key) const = 0;
-
- /**
- * Parse translation response.
- *
- * @param[in,out] status HTTP status. May be modified while parsing.
- * @param body Response text.
- * @param[out] translation Translated text.
- * @param[out] detected_lang Detected source language. May be empty.
- * @param[out] err_msg Error message (in case of error).
- */
- virtual bool parseResponse(
- int& status,
- const std::string& body,
- std::string& translation,
- std::string& detected_lang,
- std::string& err_msg) const = 0;
-
- /**
- * @return if the handler is configured to function properly
- */
- virtual bool isConfigured() const = 0;
-
- virtual ~LLTranslationAPIHandler() {}
-
-protected:
- static const int STATUS_OK = 200;
-};
-
-/// Google Translate v2 API handler.
-class LLGoogleTranslationHandler : public LLTranslationAPIHandler
-{
- LOG_CLASS(LLGoogleTranslationHandler);
-
-public:
- /*virtual*/ void getTranslateURL(
- std::string &url,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &text) const;
- /*virtual*/ void getKeyVerificationURL(
- std::string &url,
- const std::string &key) const;
- /*virtual*/ bool parseResponse(
- int& status,
- const std::string& body,
- std::string& translation,
- std::string& detected_lang,
- std::string& err_msg) const;
- /*virtual*/ bool isConfigured() const;
-
-private:
- static void parseErrorResponse(
- const Json::Value& root,
- int& status,
- std::string& err_msg);
- static bool parseTranslation(
- const Json::Value& root,
- std::string& translation,
- std::string& detected_lang);
- static std::string getAPIKey();
-};
-
-/// Microsoft Translator v2 API handler.
-class LLBingTranslationHandler : public LLTranslationAPIHandler
-{
- LOG_CLASS(LLBingTranslationHandler);
-
-public:
- /*virtual*/ void getTranslateURL(
- std::string &url,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &text) const;
- /*virtual*/ void getKeyVerificationURL(
- std::string &url,
- const std::string &key) const;
- /*virtual*/ bool parseResponse(
- int& status,
- const std::string& body,
- std::string& translation,
- std::string& detected_lang,
- std::string& err_msg) const;
- /*virtual*/ bool isConfigured() const;
-private:
- static std::string getAPIKey();
-};
-
-/**
- * Entry point for machine translation services.
- *
- * Basically, to translate a string, we need to know the URL
- * of a translation service, have a valid API for the service
- * and be given the target language.
- *
- * Callers specify the string to translate and the target language,
- * LLTranslate takes care of the rest.
- *
- * API keys for translation are taken from saved settings.
- */
class LLTranslate
{
- LOG_CLASS(LLTranslate);
-
public :
-
- typedef enum e_service {
- SERVICE_BING,
- SERVICE_GOOGLE,
- } EService;
-
- /**
- * Subclasses are supposed to handle translation results (e.g. show them in chat)
- */
class TranslationReceiver: public LLHTTPClient::Responder
{
- public:
+ protected:
+ TranslationReceiver(const std::string &fromLang, const std::string &toLang)
+ : m_fromLang(fromLang),
+ m_toLang(toLang)
+ {
+ }
- /**
- * Using mHandler, parse incoming response.
- *
- * Calls either handleResponse() or handleFailure()
- * depending on the HTTP status code and parsing success.
- *
- * @see handleResponse()
- * @see handleFailure()
- * @see mHandler
- */
- /*virtual*/ void completedRaw(
- U32 http_status,
+ virtual void handleResponse(const std::string &translation, const std::string &recognizedLang) {}
+ virtual void handleFailure() {};
+
+ public:
+ ~TranslationReceiver()
+ {
+ }
+
+ virtual void error(U32 status, const std::string& reason)
+ {
+ LL_WARNS("Translate") << "URL Request error: " << reason << LL_ENDL;
+ handleFailure();
+ }
+
+ virtual void completedRaw(
+ U32 status,
const std::string& reason,
const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer);
+ const LLIOPipe::buffer_ptr_t& buffer)
+ {
+ LLBufferStream istr(channels, buffer.get());
+
+ std::stringstream strstrm;
+ strstrm << istr.rdbuf();
+ const std::string result = strstrm.str();
+
+ std::string translation;
+ std::string detectedLanguage;
+
+ if (!parseGoogleTranslate(result, translation, detectedLanguage))
+ {
+ handleFailure();
+ return;
+ }
+
+ // Fix up the response
+ stringReplaceAll( translation, "<","<");
+ stringReplaceAll( translation, ">",">");
+ stringReplaceAll( translation, ""","\"");
+ stringReplaceAll( translation, "'","'");
+ stringReplaceAll( translation, "&","&");
+ stringReplaceAll( translation, "'","'");
+
+ handleResponse(translation, detectedLanguage);
+ }
protected:
- friend class LLTranslate;
-
- /// Remember source and target languages for subclasses to be able to filter inappropriate results.
- TranslationReceiver(const std::string& from_lang, const std::string& to_lang);
-
- /// Override point to handle successful translation.
- virtual void handleResponse(const std::string &translation, const std::string &recognized_lang) = 0;
-
- /// Override point to handle unsuccessful translation.
- virtual void handleFailure(int status, const std::string& err_msg) = 0;
-
- std::string mFromLang;
- std::string mToLang;
- const LLTranslationAPIHandler& mHandler;
+ const std::string m_toLang;
+ const std::string m_fromLang;
};
- /**
- * Subclasses are supposed to handle API key verification result.
- */
- class KeyVerificationReceiver: public LLHTTPClient::Responder
- {
- public:
- EService getService() const;
-
- protected:
- /**
- * Save the translation service the key belongs to.
- *
- * Subclasses need to know it.
- *
- * @see getService()
- */
- KeyVerificationReceiver(EService service);
-
- /**
- * Parse verification response.
- *
- * Calls setVerificationStatus() with the verification status,
- * which is true if HTTP status code is 200.
- *
- * @see setVerificationStatus()
- */
- /*virtual*/ void completedRaw(
- U32 http_status,
- const std::string& reason,
- const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer);
-
- /**
- * Override point for subclasses to handle key verification status.
- */
- virtual void setVerificationStatus(bool ok) = 0;
-
- EService mService;
- };
-
- typedef boost::intrusive_ptr TranslationReceiverPtr;
- typedef boost::intrusive_ptr KeyVerificationReceiverPtr;
-
- /**
- * Translate given text.
- *
- * @param receiver Object to pass translation result to.
- * @param from_lang Source language. Leave empty for auto-detection.
- * @param to_lang Target language.
- * @param mesg Text to translate.
- */
- static void translateMessage(TranslationReceiverPtr &receiver, const std::string &from_lang, const std::string &to_lang, const std::string &mesg);
-
- /**
- * Verify given API key of a translation service.
- *
- * @param receiver Object to pass verification result to.
- * @param key Key to verify.
- */
- static void verifyKey(KeyVerificationReceiverPtr& receiver, const std::string& key);
-
- /**
- * @return translation target language
- */
+ static void translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &fromLang, const std::string &toLang, const std::string &mesg);
+ static float m_GoogleTimeout;
static std::string getTranslateLanguage();
- /**
- * @return true if translation is configured properly.
- */
- static bool isTranslationConfigured();
-
private:
- static const LLTranslationAPIHandler& getPreferredHandler();
- static const LLTranslationAPIHandler& getHandler(EService service);
- static void sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder);
+ static void getTranslateUrl(std::string &translateUrl, const std::string &fromLang, const std::string &toLang, const std::string &text);
+ static void stringReplaceAll(std::string& context, const std::string& from, const std::string& to);
+ static BOOL parseGoogleTranslate(const std::string result, std::string &translation, std::string &detectedLanguage);
+
+ 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;
};
#endif
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index a060efd09..97ac3eb05 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2957,23 +2957,23 @@ void process_decline_callingcard(LLMessageSystem* msg, void**)
class ChatTranslationReceiver : public LLTranslate::TranslationReceiver
{
public :
- ChatTranslationReceiver(const std::string &from_lang, const std::string &to_lang, LLChat *chat,
+ ChatTranslationReceiver(const std::string &fromLang, const std::string &toLang, LLChat *chat,
const BOOL history)
- : LLTranslate::TranslationReceiver(from_lang, to_lang),
+ : LLTranslate::TranslationReceiver(fromLang, toLang),
m_chat(chat),
m_history(history)
{
}
- static boost::intrusive_ptr build(const std::string &from_lang, const std::string &to_lang, LLChat *chat, const BOOL history)
+ static boost::intrusive_ptr build(const std::string &fromLang, const std::string &toLang, LLChat *chat, const BOOL history)
{
- return boost::intrusive_ptr(new ChatTranslationReceiver(from_lang, to_lang, chat, history));
+ return boost::intrusive_ptr(new ChatTranslationReceiver(fromLang, toLang, chat, history));
}
protected:
void handleResponse(const std::string &translation, const std::string &detectedLanguage)
{
- if (mToLang != detectedLanguage)
+ if (m_toLang != detectedLanguage)
m_chat->mText += " (" + translation + ")";
add_floater_chat(*m_chat, m_history);
@@ -2981,12 +2981,14 @@ protected:
delete m_chat;
}
- void handleFailure(int status, const std::string& err_msg)
+ void handleFailure()
{
- llwarns << "Translation failed for mesg " << m_chat << " toLang " << mToLang << " fromLang " << mFromLang << llendl;
+ LLTranslate::TranslationReceiver::handleFailure();
m_chat->mText += " (?)";
+
add_floater_chat(*m_chat, m_history);
+
delete m_chat;
}
@@ -3015,12 +3017,14 @@ void check_translate_chat(const std::string &mesg, LLChat &chat, const BOOL hist
if (translate && chat.mSourceType != CHAT_SOURCE_SYSTEM)
{
- const std::string &from_lang = "";
- const std::string &to_lang = LLTranslate::getTranslateLanguage();
+ // fromLang hardcoded to "" (autodetection) pending implementation of
+ // SVC-4879
+ const std::string &fromLang = "";
+ const std::string &toLang = LLTranslate::getTranslateLanguage();
LLChat *newChat = new LLChat(chat);
- LLTranslate::TranslationReceiverPtr result = ChatTranslationReceiver::build(from_lang, to_lang, newChat, history);
- LLTranslate::translateMessage(result, from_lang, to_lang, mesg);
+ LLHTTPClient::ResponderPtr result = ChatTranslationReceiver::build(fromLang, toLang, newChat, history);
+ LLTranslate::translateMessage(result, fromLang, toLang, mesg);
}
else
{