【问题标题】:Setting event.textLocale in bot.use (Node.js Microsoft Bot Framework)在 bot.use 中设置 event.textLocale (Node.js Microsoft Bot Framework)
【发布时间】:2018-02-08 15:47:25
【问题描述】:

我正在使用 Azure Web App Bot (Node v 6.9.1),当初始化 Web 聊天中的测试界面时,text 和 textLocale 为空。但是,当从用户接收到第一个输入时, event.textLocale 被分配了一个默认的“en”值,所以我无法在进行语言检测后从 bot.use(receive) 重置一次(因为它不是在这个阶段为空)。

是否有另一种方法可以将 event.textLocale 重置一次,因为我也无法通过任何全局 node.js 变量将语言环境值从 bot.use(receive) 传播到 bot.use(send) 事件?请帮忙,谢谢

app.js 代码段

bot.use({
    receive: function (event, next) {       
        var text = ''; 
        async.waterfall([
            function(callback) {
                text= event.text;
                textLocale = event.textLocale;
                request.get(
                    'http://<<<hostname>>>/translateIntent?intent='+text.toString()+'&textLocale='+(textLocale).toString(), 
                    function (error, response, body) {
                        if (!error && response.statusCode == 200) {
                            var jsonStr = JSON.parse(body);
                            event.text=jsonStr.outputText;
                            // Storing the user's text locale if not already set 
                            // - does not execute as event.textLocale is set by default and global variables are not propagating from receive to send 
                            if(!event.textLocale && (jsonStr.inputLanguageContext != "(Unknown)")) {
                                event.textLocale = jsonStr.inputLanguageContext;
                                console.log("Rewriting event text locale to :" + jsonStr.inputLanguageContext); 
                            }

                            callback(null, event);
                        }
                    }
                );  
            },
            function(event, callback) {
                console.log("Rec after modification:");
                console.log("event.textLocale: " + event.textLocale);
                next();
                callback(null, 'done');
            }
        ]);
    },
    send: function (event, next) {
        // translate response using event.textLocale as languageTo  {event.text, languageFrom='en', event.textLocale}
    } 
});

翻译api:

app.get("/translateIntent", function(request, response) {
    var inputText = request.param('intent');
    if(inputText) {
        var textLocale = '';    var outputText = '';
        // If locale is already set, languageDetectHelper does not need to be called  
        if(request.param('textLocale')) {
            textLocale = request.param('textLocale');
            if(textLocale == 'en') {
                // No translation required, just send back the inputText
                response.end({outputText:inputText, inputLanguageContext:languageCodeDetected}); 
            } else {
                // Call translate, with languageFrom as textLocale, and languageTo = 'en'
                translateHelper.GetTranslation(inputText, textLocale, languageTo).then(jsonStr =>  {
                    response.end(jsonStr);
                }).catch(error => { 
                    console.log("Error: " + error); 
                }) 
            }
        } else {
            // Locale not yet set, call detectLanguage 
            languageDetectHelper.GetTextLanguage(inputText).then(languageCodeDetected => {
                var languageTo = 'en';  
                if(languageCodeDetected == 'en' || languageCodeDetected == '(Unknown)') {
                    // Send back without translation 
                    response.end({outputText:inputText, inputLanguageContext:languageCodeDetected}); 
                } else {
                    // Translate to English 
                    translateHelper.GetTranslation(inputText, languageCodeDetected, languageTo).then(jsonStr =>  {
                        console.log("JSON stringify output in server: " + JSON.stringify(jsonStr));
                        response.end(jsonStr);
                    }).catch(error => { 
                        console.log("Error: " + error); 
                    }) 
                }               
            }).catch(error=> {
                console.log("Error: " + error);
            });     
        }
    } else {
        console.log("No translation required, waiting for the next event"); 
    }
});

【问题讨论】:

    标签: node.js azure locale botframework


    【解决方案1】:

    据我了解,您正在尝试检测用户的输入语言,如果不是英语,请将其翻译成英语,以便您的后端(如 LUIS 服务)可以处理它,并且在处理完您的机器人后,默认情况下会向您的用户,但您想再次将响应翻译回用户的输入语言。

    由于我无法使用您的代码构建复杂的演示,所以我在这里使用 azure 认知服务来创建此演示:

    var tokenHandler = require('./tokenHandler');
    tokenHandler.init();
    
    var TOLOCALE = 'en';
    var FROMLOCALE;
    
    bot.use({
        receive: function (event, next) {
            var token = tokenHandler.token();
    
            //text ayalytics 
            if(event.text != ""){
                var options = {
                    method: 'POST',
                    url: 'https://westcentralus.api.cognitive.microsoft.com/text/analytics/v2.0/languages',
                    body: { documents: [{ id: 'message', text: event.text }]},
                    json: true,
                    headers: {
                        'Ocp-Apim-Subscription-Key': 'YOUR-KEY'
                    }
                };
                request(options, function (error, response, body) {
                    if (!error && body) {
                        if (body.documents && body.documents.length > 0) {
                            var languages = body.documents[0].detectedLanguages;
                            if (languages && languages.length > 0) {
                                event.textLocale = languages[0].iso6391Name;
                                FROMLOCALE = event.textLocale;
                            }
                        }
                    }
                //text translations
                if (token && token !== ""){ //not null or empty string
                    var urlencodedtext = urlencode(event.text); // convert foreign characters to utf8
                    var options = {
                        method: 'GET',
                        url: 'http://api.microsofttranslator.com/v2/Http.svc/Translate'+'?text=' + urlencodedtext + '&from=' + FROMLOCALE +'&to=' + TOLOCALE,
                        headers: {
                            'Authorization': 'Bearer ' + token
                        }
                    };
                    request(options, function (error, response, body){
                        //Check for error
                        if(error){
                            return console.log('Error:', error);
                        } 
                        else if(response.statusCode !== 200){
                            return console.log('Invalid Status Code Returned:', response.statusCode);
                        } 
                        else {
                            parseString(body, function (err, result) {
                                console.log(result.string._);
                                event.text = result.string._;
                                next();
                            });
    
                        }
                    });
                } 
                else{
                        console.log("No token");
                        next();
                    }
                });
            }
            else{
                next();
            }
        },
        send: function (event, next) {
            // translate response using event.textLocale as languageTo  {event.text, languageFrom='en', event.textLocale}
            var token = tokenHandler.token();
            if (token && token !== ""){
                var options = {
                    method: 'GET',
                    url: 'http://api.microsofttranslator.com/v2/Http.svc/Translate'+'?text=' + event.text + '&from=' + TOLOCALE +'&to=' + FROMLOCALE,
                    headers: {
                        'Authorization': 'Bearer ' + token
                    }
                };
                request(options, function (error, response, body){
                    //Check for error
                    if(error){
                        return console.log('Error:', error);
                    } 
                    else if(response.statusCode !== 200){
                        return console.log('Invalid Status Code Returned:', response.statusCode);
                    } 
                    else {
                        parseString(body, function (err, result) {
                            console.log(result.string._);
                            event.text = result.string._;
                            next();
                        });
    
                    }
                });
            }
        }
    });
    
    //=========================================================
    // Bots Dialogs
    //=========================================================
    var luisAppUrl = 'YOUR-LUIS-ENDPOINT';
    var recognizer = new builder.LuisRecognizer(luisAppUrl);
    var intents = new builder.IntentDialog({ recognizers: [recognizer] });
    bot.dialog('/', intents);
    
    //Route the luis intents to the various dialogs
    intents.matches('greeting', (session)=>{
        session.send('You reached Greeting intent, you said \'%s\'.', session.message.text);
    }).onDefault((session)=>{
        session.send('Sorry, I did not understand \'%s\'.', session.message.text);
    });
    

    tokenhandler的代码是这样的:

    var request = require('request');
    
    var token = "";
    var tokeninterval;
    var TRANSLATIONKEY = 'YOUR-KEY';
    
    function getToken() {
    
        var options = {
            method: 'POST',
            url: 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken?Subscription-Key=' + TRANSLATIONKEY
        };
    
        request(options, function (error, response, body){
            //Check for error
            if(error){
                return console.log('Error:', error);
            } else if(response.statusCode !== 200){
                return console.log('Invalid Status Code Returned:', response.statusCode);
            } else {
                //Token gets returned as string in the body
                token = body;
            }
        });
    
        interval = setTimeout(getToken, 540000); // runs once every 9 minutes, token lasts for 10
    }
    
    // Stop the token generation
    function stopInterval() {
        clearTimeout(tokeninterval);
    }
    
    module.exports = {
      init: function() {
          getToken();
      }, 
      stop: function() {
          stopInterval();
      },
      token: function () {
          return token;
      }
    };
    

    这个演示在我身边工作,但是对于你的演示,如果你想使用receive中设置的语言环境,你可以直接在我的代码中定义一个变量,比如FROMLOCALE,设置它的值在receive 中并在send 中使用此变量。

    如果我误解了您的要求,请随时告诉我。

    【讨论】:

    • @grace-feng-msft 是否可以扩展令牌处理程序(例如使用 getLocale 和 setLocale)以通过它从接收到发送传播语言环境?我们试过了,但没有奏效。上述代码的问题在于,由于每次输入都会进行一次语言检测,因此它会从首先检测马来语(这应该是第一次检测后的持久语言环境)切换到在下一个意图中检测印尼语等,因为我们是将 FROMLOCALE 等同于 languageDetector 找到的任何内容,而不是将其等同于某个全局静态变量。
    • @mlnewbie,如果你只想第一次检测locale,可以在语言检测前加一个'if/else'条件,看看FROMLOCALE是不是空值,不管我们是否将这个检测函数封装到一个模块中,仍然需要在翻译前第一次调用它,所以我们可以尝试在这里添加一个条件来实现这个需求。如果你想将它包装到一个模块中并将FROMLOCALE 设置为一个全局变量,那很好。
    • @mlnewbie,您可以参考node.js global variables 了解如何在此处制作FROMLOCALE 以供全球使用。而且我这里只提供一个demo来展示处理这种场景的过程,并不是一个完成的项目,所以如果你有其他需求,你可以在SO中打开一个新的线程进一步讨论,抱歉我不能给你发邮件。最后,如果你觉得这个答案有帮助,你能标记这个答案吗?谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多