Files
SingularityViewer/indra/newview/lltranslate.h
2012-02-19 19:43:53 -05:00

304 lines
8.2 KiB
C++

/**
* @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$
*/
#ifndef LL_LLTRANSLATE_H
#define LL_LLTRANSLATE_H
#include "llhttpclient.h"
#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:
/**
* 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,
const std::string& reason,
const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer);
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;
};
/**
* 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<TranslationReceiver> TranslationReceiverPtr;
typedef boost::intrusive_ptr<KeyVerificationReceiver> 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 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);
};
#endif