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.h | 87 +++++++++++---------------------------------- 1 file changed, 20 insertions(+), 67 deletions(-) (limited to 'indra/newview/lltranslate.h') 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 -- 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.h | 77 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) (limited to 'indra/newview/lltranslate.h') diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 1dee792f7b..1bf6965fd4 100644 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -30,7 +30,82 @@ #include "llhttpclient.h" #include "llbufferstream.h" -class LLTranslationAPIHandler; +namespace Json +{ + class Value; +} + +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 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*/ bool parseResponse( + int& status, + const std::string& body, + std::string& translation, + std::string& detected_lang, + std::string& err_msg) 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(); +}; + +class LLBingTranslarionHandler : public LLTranslationAPIHandler +{ + LOG_CLASS(LLBingTranslarionHandler); + +public: + /*virtual*/ void getTranslateURL( + std::string &url, + const std::string &from_lang, + const std::string &to_lang, + const std::string &text) const; + /*virtual*/ bool parseResponse( + int& status, + const std::string& body, + std::string& translation, + std::string& detected_lang, + std::string& err_msg) const; +private: + static std::string getAPIKey(); +}; + class LLTranslate { -- 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.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'indra/newview/lltranslate.h') diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 1bf6965fd4..672a56af8b 100644 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -44,6 +44,10 @@ public: const std::string &to_lang, const std::string &text) const = 0; + virtual void getKeyVerificationURL( + std::string &url, + const std::string &key) const = 0; + virtual bool parseResponse( int& status, const std::string& body, @@ -67,6 +71,9 @@ public: 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, @@ -96,6 +103,9 @@ public: 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, @@ -112,6 +122,12 @@ class LLTranslate LOG_CLASS(LLTranslate); public : + + typedef enum e_service { + SERVICE_BING, + SERVICE_GOOGLE, + } EService; + class TranslationReceiver: public LLHTTPClient::Responder { public: @@ -134,13 +150,34 @@ public : const LLTranslationAPIHandler& mHandler; }; + class KeyVerificationReceiver: public LLHTTPClient::Responder + { + public: + EService getService() const; + + protected: + KeyVerificationReceiver(EService service); + /*virtual*/ void completedRaw( + U32 http_status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + virtual void setVerificationStatus(bool ok) = 0; + + EService mService; + }; + typedef boost::intrusive_ptr TranslationReceiverPtr; + typedef boost::intrusive_ptr KeyVerificationReceiverPtr; static void translateMessage(TranslationReceiverPtr &receiver, const std::string &from_lang, const std::string &to_lang, const std::string &mesg); + static void verifyKey(KeyVerificationReceiverPtr& receiver, const std::string& key); static std::string getTranslateLanguage(); private: static const LLTranslationAPIHandler& getPreferredHandler(); + static const LLTranslationAPIHandler& getHandler(EService service); + static void sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder); }; #endif -- 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.h | 109 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 3 deletions(-) (limited to 'indra/newview/lltranslate.h') diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 672a56af8b..c2330daa81 100644 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -35,19 +35,53 @@ 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, @@ -61,6 +95,7 @@ protected: static const int STATUS_OK = 200; }; +/// Google Translate v2 API handler. class LLGoogleTranslationHandler : public LLTranslationAPIHandler { LOG_CLASS(LLGoogleTranslationHandler); @@ -93,9 +128,10 @@ private: static std::string getAPIKey(); }; -class LLBingTranslarionHandler : public LLTranslationAPIHandler +/// Microsoft Translator v2 API handler. +class LLBingTranslationHandler : public LLTranslationAPIHandler { - LOG_CLASS(LLBingTranslarionHandler); + LOG_CLASS(LLBingTranslationHandler); public: /*virtual*/ void getTranslateURL( @@ -116,7 +152,18 @@ 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); @@ -128,9 +175,23 @@ public : 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, @@ -140,9 +201,13 @@ public : 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; @@ -150,18 +215,41 @@ public : 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; @@ -170,7 +258,22 @@ public : 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); static std::string getTranslateLanguage(); -- cgit v1.2.3