SL-19209 Switch MS Bing to MS Azure #3
parent
3fc3627f2d
commit
f7210db06e
|
|
@ -132,22 +132,22 @@ void LLFloaterTranslationSettings::onOpen(const LLSD& key)
|
|||
updateControlsEnabledState();
|
||||
}
|
||||
|
||||
void LLFloaterTranslationSettings::setAzureVerified(bool ok, bool alert)
|
||||
void LLFloaterTranslationSettings::setAzureVerified(bool ok, bool alert, S32 status)
|
||||
{
|
||||
if (alert)
|
||||
{
|
||||
showAlert(ok ? "azure_api_key_verified" : "azure_api_key_not_verified");
|
||||
showAlert(ok ? "azure_api_key_verified" : "azure_api_key_not_verified", status);
|
||||
}
|
||||
|
||||
mAzureKeyVerified = ok;
|
||||
updateControlsEnabledState();
|
||||
}
|
||||
|
||||
void LLFloaterTranslationSettings::setGoogleVerified(bool ok, bool alert)
|
||||
void LLFloaterTranslationSettings::setGoogleVerified(bool ok, bool alert, S32 status)
|
||||
{
|
||||
if (alert)
|
||||
{
|
||||
showAlert(ok ? "google_api_key_verified" : "google_api_key_not_verified");
|
||||
showAlert(ok ? "google_api_key_verified" : "google_api_key_not_verified", status);
|
||||
}
|
||||
|
||||
mGoogleKeyVerified = ok;
|
||||
|
|
@ -179,10 +179,15 @@ std::string LLFloaterTranslationSettings::getEnteredGoogleKey() const
|
|||
return mGoogleAPIKeyEditor->getTentative() ? LLStringUtil::null : mGoogleAPIKeyEditor->getText();
|
||||
}
|
||||
|
||||
void LLFloaterTranslationSettings::showAlert(const std::string& msg_name) const
|
||||
void LLFloaterTranslationSettings::showAlert(const std::string& msg_name, S32 status) const
|
||||
{
|
||||
LLStringUtil::format_map_t string_args;
|
||||
// For now just show an http error code, whole 'reason' string might be added later
|
||||
string_args["[STATUS]"] = llformat("%d", status);
|
||||
std::string message = getString(msg_name, string_args);
|
||||
|
||||
LLSD args;
|
||||
args["MESSAGE"] = getString(msg_name);
|
||||
args["MESSAGE"] = message;
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
}
|
||||
|
||||
|
|
@ -222,7 +227,7 @@ void LLFloaterTranslationSettings::updateControlsEnabledState()
|
|||
}
|
||||
|
||||
/*static*/
|
||||
void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, bool alert)
|
||||
void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, bool alert, S32 status)
|
||||
{
|
||||
LLFloaterTranslationSettings* floater =
|
||||
LLFloaterReg::getTypedInstance<LLFloaterTranslationSettings>("prefs_translation");
|
||||
|
|
@ -236,10 +241,10 @@ void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, b
|
|||
switch (service)
|
||||
{
|
||||
case LLTranslate::SERVICE_AZURE:
|
||||
floater->setAzureVerified(ok, alert);
|
||||
floater->setAzureVerified(ok, alert, status);
|
||||
break;
|
||||
case LLTranslate::SERVICE_GOOGLE:
|
||||
floater->setGoogleVerified(ok, alert);
|
||||
floater->setGoogleVerified(ok, alert, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -248,7 +253,7 @@ void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, b
|
|||
void LLFloaterTranslationSettings::verifyKey(int service, const LLSD& key, bool alert)
|
||||
{
|
||||
LLTranslate::verifyKey(static_cast<LLTranslate::EService>(service), key,
|
||||
boost::bind(&LLFloaterTranslationSettings::setVerificationStatus, _1, _2, alert));
|
||||
boost::bind(&LLFloaterTranslationSettings::setVerificationStatus, _1, _2, alert, _3));
|
||||
}
|
||||
|
||||
void LLFloaterTranslationSettings::onEditorFocused(LLFocusableElement* control)
|
||||
|
|
@ -271,7 +276,7 @@ void LLFloaterTranslationSettings::onAzureKeyEdited()
|
|||
|| mAzureAPIEndpointEditor->getValue().isString())
|
||||
{
|
||||
// todo: verify mAzureAPIEndpointEditor url
|
||||
setAzureVerified(false, false);
|
||||
setAzureVerified(false, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,7 +284,7 @@ void LLFloaterTranslationSettings::onGoogleKeyEdited()
|
|||
{
|
||||
if (mGoogleAPIKeyEditor->isDirty())
|
||||
{
|
||||
setGoogleVerified(false, false);
|
||||
setGoogleVerified(false, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,15 +42,15 @@ public:
|
|||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void onOpen(const LLSD& key);
|
||||
|
||||
void setAzureVerified(bool ok, bool alert);
|
||||
void setGoogleVerified(bool ok, bool alert);
|
||||
void setAzureVerified(bool ok, bool alert, S32 status);
|
||||
void setGoogleVerified(bool ok, bool alert, S32 status);
|
||||
void onClose(bool app_quitting);
|
||||
|
||||
private:
|
||||
std::string getSelectedService() const;
|
||||
LLSD getEnteredAzureKey() const;
|
||||
std::string getEnteredGoogleKey() const;
|
||||
void showAlert(const std::string& msg_name) const;
|
||||
void showAlert(const std::string& msg_name, S32 status) const;
|
||||
void updateControlsEnabledState();
|
||||
void verifyKey(int service, const LLSD& key, bool alert = true);
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ private:
|
|||
void onBtnGoogleVerify();
|
||||
void onBtnOK();
|
||||
|
||||
static void setVerificationStatus(int service, bool alert, bool ok);
|
||||
static void setVerificationStatus(int service, bool alert, bool ok, S32 status);
|
||||
|
||||
LLCheckBoxCtrl* mMachineTranslationCB;
|
||||
LLComboBox* mLanguageCombo;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@
|
|||
#include "llurlregistry.h"
|
||||
|
||||
|
||||
static const std::string BING_NOTRANSLATE_OPENING_TAG("<div translate=\"no\">");
|
||||
static const std::string BING_NOTRANSLATE_CLOSING_TAG("</div>");
|
||||
static const std::string AZURE_NOTRANSLATE_OPENING_TAG("<div translate=\"no\">");
|
||||
static const std::string AZURE_NOTRANSLATE_CLOSING_TAG("</div>");
|
||||
|
||||
/**
|
||||
* Handler of an HTTP machine translation service.
|
||||
|
|
@ -103,6 +103,7 @@ public:
|
|||
* @param[out] err_msg Error message (in case of error).
|
||||
*/
|
||||
virtual bool parseResponse(
|
||||
const LLSD& http_response,
|
||||
int& status,
|
||||
const std::string& body,
|
||||
std::string& translation,
|
||||
|
|
@ -176,6 +177,13 @@ void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, LLSD
|
|||
return;
|
||||
}
|
||||
|
||||
std::string::size_type delim_pos = url.find("://");
|
||||
if (delim_pos == std::string::npos)
|
||||
{
|
||||
LL_INFOS("Translate") << "URL is missing a scheme" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD result = verifyAndSuspend(httpAdapter, httpRequest, httpOpts, httpHeaders, url);
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
|
|
@ -190,7 +198,7 @@ void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, LLSD
|
|||
|
||||
if (!fnc.empty())
|
||||
{
|
||||
fnc(service, bOk);
|
||||
fnc(service, bOk, parseResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -221,8 +229,8 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s
|
|||
LL_INFOS("Translate") << "No translation URL" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LL_INFOS() << "Message: " << msg << LL_ENDL;
|
||||
LL_INFOS() << "Requesting: " << url << LL_ENDL;
|
||||
LL_DEBUGS("Translate") << "Message: " << msg << LL_ENDL;
|
||||
LL_DEBUGS("Translate") << "Requesting: " << url << LL_ENDL;
|
||||
|
||||
LLSD result = sendMessageAndSuspend(httpAdapter, httpRequest, httpOpts, httpHeaders, url, msg);
|
||||
|
||||
|
|
@ -245,7 +253,7 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s
|
|||
|
||||
try
|
||||
{
|
||||
res = this->parseResponse(parseResult, body, translation, detected_lang, err_msg);
|
||||
res = this->parseResponse(httpResults, parseResult, body, translation, detected_lang, err_msg);
|
||||
}
|
||||
catch (std::out_of_range&)
|
||||
{
|
||||
|
|
@ -306,6 +314,7 @@ public:
|
|||
const LLSD &response,
|
||||
int status) const override;
|
||||
bool parseResponse(
|
||||
const LLSD& http_response,
|
||||
int& status,
|
||||
const std::string& body,
|
||||
std::string& translation,
|
||||
|
|
@ -380,6 +389,7 @@ bool LLGoogleTranslationHandler::checkVerificationResponse(
|
|||
|
||||
// virtual
|
||||
bool LLGoogleTranslationHandler::parseResponse(
|
||||
const LLSD& http_response,
|
||||
int& status,
|
||||
const std::string& body,
|
||||
std::string& translation,
|
||||
|
|
@ -531,6 +541,7 @@ public:
|
|||
const LLSD &response,
|
||||
int status) const override;
|
||||
bool parseResponse(
|
||||
const LLSD& http_response,
|
||||
int& status,
|
||||
const std::string& body,
|
||||
std::string& translation,
|
||||
|
|
@ -557,6 +568,8 @@ public:
|
|||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string & url) const override;
|
||||
private:
|
||||
static std::string parseErrorResponse(
|
||||
const std::string& body);
|
||||
static LLSD getAPIKey();
|
||||
static std::string getAPILanguageCode(const std::string& lang);
|
||||
|
||||
|
|
@ -574,7 +587,7 @@ std::string LLAzureTranslationHandler::getTranslateURL(
|
|||
if (key.isMap())
|
||||
{
|
||||
std::string endpoint = key["endpoint"].asString();
|
||||
// todo: validate url
|
||||
|
||||
if (*endpoint.rbegin() != '/')
|
||||
{
|
||||
endpoint += "/";
|
||||
|
|
@ -594,7 +607,6 @@ std::string LLAzureTranslationHandler::getKeyVerificationURL(
|
|||
if (key.isMap())
|
||||
{
|
||||
std::string endpoint = key["endpoint"].asString();
|
||||
// todo: validate url
|
||||
if (*endpoint.rbegin() != '/')
|
||||
{
|
||||
endpoint += "/";
|
||||
|
|
@ -609,11 +621,48 @@ bool LLAzureTranslationHandler::checkVerificationResponse(
|
|||
const LLSD &response,
|
||||
int status) const
|
||||
{
|
||||
return status == HTTP_BAD_REQUEST; // would have been 401 if id was wrong
|
||||
if (status == HTTP_UNAUTHORIZED)
|
||||
{
|
||||
LL_DEBUGS("Translate") << "Key unathorised" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (status == HTTP_NOT_FOUND)
|
||||
{
|
||||
LL_DEBUGS("Translate") << "Either endpoint doesn't have requested resource" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (status != HTTP_BAD_REQUEST)
|
||||
{
|
||||
LL_DEBUGS("Translate") << "Unexpected error code" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!response.has("error_body"))
|
||||
{
|
||||
LL_DEBUGS("Translate") << "Unexpected response, no error returned" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Expected: "{\"error\":{\"code\":400000,\"message\":\"One of the request inputs is not valid.\"}}"
|
||||
// But for now just verify response is a valid json with an error
|
||||
|
||||
Json::Value root;
|
||||
Json::Reader reader;
|
||||
|
||||
if (!reader.parse(response["error_body"].asString(), root))
|
||||
{
|
||||
LL_DEBUGS("Translate") << "Failed to parse error_body:" << reader.getFormatedErrorMessages() << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// virtual
|
||||
bool LLAzureTranslationHandler::parseResponse(
|
||||
const LLSD& http_response,
|
||||
int& status,
|
||||
const std::string& body,
|
||||
std::string& translation,
|
||||
|
|
@ -622,6 +671,8 @@ bool LLAzureTranslationHandler::parseResponse(
|
|||
{
|
||||
if (status != HTTP_OK)
|
||||
{
|
||||
if (http_response.has("error_body"))
|
||||
err_msg = parseErrorResponse(http_response["error_body"].asString());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -682,6 +733,36 @@ bool LLAzureTranslationHandler::isConfigured() const
|
|||
return !getAPIKey().isMap();
|
||||
}
|
||||
|
||||
//static
|
||||
std::string LLAzureTranslationHandler::parseErrorResponse(
|
||||
const std::string& body)
|
||||
{
|
||||
// Expected: "{\"error\":{\"code\":400000,\"message\":\"One of the request inputs is not valid.\"}}"
|
||||
// But for now just verify response is a valid json with an error
|
||||
|
||||
Json::Value root;
|
||||
Json::Reader reader;
|
||||
|
||||
if (!reader.parse(body, root))
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (!root.isObject() || !root.isMember("error"))
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const Json::Value& error_map = root["error"];
|
||||
|
||||
if (!error_map.isObject() || !error_map.isMember("message"))
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return error_map["message"].asString();
|
||||
}
|
||||
|
||||
// static
|
||||
LLSD LLAzureTranslationHandler::getAPIKey()
|
||||
{
|
||||
|
|
@ -771,54 +852,65 @@ void LLTranslate::translateMessage(const std::string &from_lang, const std::stri
|
|||
|
||||
std::string LLTranslate::addNoTranslateTags(std::string mesg)
|
||||
{
|
||||
if (getPreferredHandler().getCurrentService() != SERVICE_AZURE)
|
||||
if (getPreferredHandler().getCurrentService() == SERVICE_GOOGLE)
|
||||
{
|
||||
return mesg;
|
||||
}
|
||||
|
||||
std::string upd_msg(mesg);
|
||||
LLUrlMatch match;
|
||||
S32 dif = 0;
|
||||
//surround all links (including SLURLs) with 'no-translate' tags to prevent unnecessary translation
|
||||
while (LLUrlRegistry::instance().findUrl(mesg, match))
|
||||
if (getPreferredHandler().getCurrentService() == SERVICE_AZURE)
|
||||
{
|
||||
upd_msg.insert(dif + match.getStart(), BING_NOTRANSLATE_OPENING_TAG);
|
||||
upd_msg.insert(dif + BING_NOTRANSLATE_OPENING_TAG.size() + match.getEnd() + 1, BING_NOTRANSLATE_CLOSING_TAG);
|
||||
mesg.erase(match.getStart(), match.getEnd() - match.getStart());
|
||||
dif += match.getEnd() - match.getStart() + BING_NOTRANSLATE_OPENING_TAG.size() + BING_NOTRANSLATE_CLOSING_TAG.size();
|
||||
// https://learn.microsoft.com/en-us/azure/cognitive-services/translator/prevent-translation
|
||||
std::string upd_msg(mesg);
|
||||
LLUrlMatch match;
|
||||
S32 dif = 0;
|
||||
//surround all links (including SLURLs) with 'no-translate' tags to prevent unnecessary translation
|
||||
while (LLUrlRegistry::instance().findUrl(mesg, match))
|
||||
{
|
||||
upd_msg.insert(dif + match.getStart(), AZURE_NOTRANSLATE_OPENING_TAG);
|
||||
upd_msg.insert(dif + AZURE_NOTRANSLATE_OPENING_TAG.size() + match.getEnd() + 1, AZURE_NOTRANSLATE_CLOSING_TAG);
|
||||
mesg.erase(match.getStart(), match.getEnd() - match.getStart());
|
||||
dif += match.getEnd() - match.getStart() + AZURE_NOTRANSLATE_OPENING_TAG.size() + AZURE_NOTRANSLATE_CLOSING_TAG.size();
|
||||
}
|
||||
return upd_msg;
|
||||
}
|
||||
return upd_msg;
|
||||
return mesg;
|
||||
}
|
||||
|
||||
std::string LLTranslate::removeNoTranslateTags(std::string mesg)
|
||||
{
|
||||
if (getPreferredHandler().getCurrentService() != SERVICE_AZURE)
|
||||
if (getPreferredHandler().getCurrentService() == SERVICE_GOOGLE)
|
||||
{
|
||||
return mesg;
|
||||
}
|
||||
std::string upd_msg(mesg);
|
||||
LLUrlMatch match;
|
||||
S32 opening_tag_size = BING_NOTRANSLATE_OPENING_TAG.size();
|
||||
S32 closing_tag_size = BING_NOTRANSLATE_CLOSING_TAG.size();
|
||||
S32 dif = 0;
|
||||
//remove 'no-translate' tags we added to the links before
|
||||
while (LLUrlRegistry::instance().findUrl(mesg, match))
|
||||
{
|
||||
if (upd_msg.substr(dif + match.getStart() - opening_tag_size, opening_tag_size) == BING_NOTRANSLATE_OPENING_TAG)
|
||||
{
|
||||
upd_msg.erase(dif + match.getStart() - opening_tag_size, opening_tag_size);
|
||||
dif -= opening_tag_size;
|
||||
|
||||
if (upd_msg.substr(dif + match.getEnd() + 1, closing_tag_size) == BING_NOTRANSLATE_CLOSING_TAG)
|
||||
if (getPreferredHandler().getCurrentService() == SERVICE_AZURE)
|
||||
{
|
||||
std::string upd_msg(mesg);
|
||||
LLUrlMatch match;
|
||||
S32 opening_tag_size = AZURE_NOTRANSLATE_OPENING_TAG.size();
|
||||
S32 closing_tag_size = AZURE_NOTRANSLATE_CLOSING_TAG.size();
|
||||
S32 dif = 0;
|
||||
//remove 'no-translate' tags we added to the links before
|
||||
while (LLUrlRegistry::instance().findUrl(mesg, match))
|
||||
{
|
||||
if (upd_msg.substr(dif + match.getStart() - opening_tag_size, opening_tag_size) == AZURE_NOTRANSLATE_OPENING_TAG)
|
||||
{
|
||||
upd_msg.replace(dif + match.getEnd() + 1, closing_tag_size, " ");
|
||||
dif -= closing_tag_size - 1;
|
||||
upd_msg.erase(dif + match.getStart() - opening_tag_size, opening_tag_size);
|
||||
dif -= opening_tag_size;
|
||||
|
||||
if (upd_msg.substr(dif + match.getEnd() + 1, closing_tag_size) == AZURE_NOTRANSLATE_CLOSING_TAG)
|
||||
{
|
||||
upd_msg.replace(dif + match.getEnd() + 1, closing_tag_size, " ");
|
||||
dif -= closing_tag_size - 1;
|
||||
}
|
||||
}
|
||||
mesg.erase(match.getStart(), match.getUrl().size());
|
||||
dif += match.getUrl().size();
|
||||
}
|
||||
mesg.erase(match.getStart(), match.getUrl().size());
|
||||
dif += match.getUrl().size();
|
||||
return upd_msg;
|
||||
}
|
||||
return upd_msg;
|
||||
|
||||
return mesg;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public :
|
|||
SERVICE_GOOGLE,
|
||||
} EService;
|
||||
|
||||
typedef boost::function<void(EService, bool)> KeyVerificationResult_fn;
|
||||
typedef boost::function<void(EService, bool, S32)> KeyVerificationResult_fn;
|
||||
typedef boost::function<void(std::string , std::string )> TranslationSuccess_fn;
|
||||
typedef boost::function<void(int, std::string)> TranslationFailure_fn;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
title="CHAT TRANSLATION SETTINGS"
|
||||
width="485">
|
||||
|
||||
<string name="azure_api_key_not_verified">Azure service identifier not verified. Please try again.</string>
|
||||
<string name="google_api_key_not_verified">Google API key not verified. Please try again.</string>
|
||||
<string name="azure_api_key_not_verified">Azure service identifier not verified. Status: [STATUS]. Please check your settings and try again.</string>
|
||||
<string name="google_api_key_not_verified">Google API key not verified. Status: [STATUS]. Please check your key and try again.</string>
|
||||
|
||||
<string name="azure_api_key_verified">Azure service identifier verified.</string>
|
||||
<string name="google_api_key_verified">Google API key verified.</string>
|
||||
|
|
@ -147,6 +147,19 @@
|
|||
top_pad="115" />
|
||||
</radio_group>
|
||||
|
||||
<text
|
||||
follows="top|right"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
left="185"
|
||||
length="1"
|
||||
name="google_links_text"
|
||||
top_pad="-142"
|
||||
type="string"
|
||||
width="100">
|
||||
[https://learn.microsoft.com/en-us/azure/cognitive-services/translator/create-translator-resource Setup]
|
||||
</text>
|
||||
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -155,7 +168,7 @@
|
|||
layout="topleft"
|
||||
left="70"
|
||||
name="azure_api_endoint_label"
|
||||
top_pad="-115"
|
||||
top_pad="8"
|
||||
width="85">
|
||||
Endpoint:
|
||||
</text>
|
||||
|
|
|
|||
Loading…
Reference in New Issue