Microsoft官方的示例在bot的中间件中提供语言翻译,似乎提供了在中间件中按3种不同的方式触发语言翻译。
我的问题是为什么3种不同类型/方式没有重叠。 (触发器如何互斥?)
有问题的代码存在here
似乎被触发了三遍:
1) if (turnContext.Activity.Type == ActivityTypes.Message) //trigger translation
2) turnContext.OnSendActivities(async (newContext, activities, nextSend) => //trigger translation
3) turnContext.OnUpdateActivity(async (newContext, activity, nextUpdate) => //trigger translation
一个可能有助于提高清晰度的单独问题->文档说... "beware short circuiting",但是您不清楚我的(有意还是无意)短路了中间件。以下两个return语句之一会使中间件短路吗?
return await nextSend(); //LINE 83 at time of writing
return await nextUpdate(); //LINE 100 at time of writing
对于后代,参考代码为:
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
namespace Microsoft.BotBuilderSamples.Translation
{
/// <summary>
/// Middleware for translating text between the user and bot.
/// Uses the Microsoft Translator Text API.
/// </summary>
public class TranslationMiddleware : IMiddleware
{
private readonly MicrosoftTranslator _translator;
private readonly IStatePropertyAccessor<string> _languageStateProperty;
/// <summary>
/// Initializes a new instance of the <see cref="TranslationMiddleware"/> class.
/// </summary>
/// <param name="translator">Translator implementation to be used for text translation.</param>
/// <param name="languageStateProperty">State property for current language.</param>
public TranslationMiddleware(MicrosoftTranslator translator, UserState userState)
{
_translator = translator ?? throw new ArgumentNullException(nameof(translator));
if(userState == null)
{
throw new ArgumentNullException(nameof(userState));
}
_languageStateProperty = userState.CreateProperty<string>("LanguagePreference");
}
/// <summary>
/// Processes an incoming activity.
/// </summary>
/// <param name="turnContext">Context object containing information for a single turn of conversation with a user.</param>
/// <param name="next">The delegate to call to continue the bot middleware pipeline.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task OnTurnAsync(ITurnContext turnContext, NextDelegate next, CancellationToken cancellationToken = default(CancellationToken))
{
if (turnContext == null)
{
throw new ArgumentNullException(nameof(turnContext));
}
var translate = await ShouldTranslateAsync(turnContext, cancellationToken);
if (translate)
{
if (turnContext.Activity.Type == ActivityTypes.Message)
{
turnContext.Activity.Text = await _translator.TranslateAsync(turnContext.Activity.Text, TranslationSettings.DefaultLanguage, cancellationToken);
}
}
turnContext.OnSendActivities(async (newContext, activities, nextSend) =>
{
string userLanguage = await _languageStateProperty.GetAsync(turnContext, () => TranslationSettings.DefaultLanguage) ?? TranslationSettings.DefaultLanguage;
bool shouldTranslate = userLanguage != TranslationSettings.DefaultLanguage;
// Translate messages sent to the user to user language
if (shouldTranslate)
{
List<Task> tasks = new List<Task>();
foreach (Activity currentActivity in activities.Where(a => a.Type == ActivityTypes.Message))
{
tasks.Add(TranslateMessageActivityAsync(currentActivity.AsMessageActivity(), userLanguage));
}
if (tasks.Any())
{
await Task.WhenAll(tasks).ConfigureAwait(false);
}
}
return await nextSend();
});
turnContext.OnUpdateActivity(async (newContext, activity, nextUpdate) =>
{
string userLanguage = await _languageStateProperty.GetAsync(turnContext, () => TranslationSettings.DefaultLanguage) ?? TranslationSettings.DefaultLanguage;
bool shouldTranslate = userLanguage != TranslationSettings.DefaultLanguage;
// Translate messages sent to the user to user language
if (activity.Type == ActivityTypes.Message)
{
if (shouldTranslate)
{
await TranslateMessageActivityAsync(activity.AsMessageActivity(), userLanguage);
}
}
return await nextUpdate();
});
await next(cancellationToken).ConfigureAwait(false);
}
private async Task TranslateMessageActivityAsync(IMessageActivity activity, string targetLocale, CancellationToken cancellationToken = default(CancellationToken))
{
if (activity.Type == ActivityTypes.Message)
{
activity.Text = await _translator.TranslateAsync(activity.Text, targetLocale);
}
}
private async Task<bool> ShouldTranslateAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
string userLanguage = await _languageStateProperty.GetAsync(turnContext, () => TranslationSettings.DefaultLanguage, cancellationToken) ?? TranslationSettings.DefaultLanguage;
return userLanguage != TranslationSettings.DefaultLanguage;
}
}
}
答案 0 :(得分:1)
当机器人接收到某些类型的活动时,需要进行消息翻译。某些类型的活动不需要翻译。该协议的活动类型可以在here
中找到 "message",
"contactRelationUpdate",
"conversationUpdate",
"typing",
"endOfConversation",
"event",
"invoke",
"deleteUserData",
"messageUpdate",
"messageDelete",
"installationUpdate",
"messageReaction",
"suggestion",
"trace",
"handoff"
MultiLingualBot示例演示了翻译:
1)将传入的消息活动转换为TranslationSettings.DefaultLanguage,以供漫游器处理
2)将传出的消息活动转换回用户惯用的语言
3)messageUpdate活动
1) if (turnContext.Activity.Type == ActivityTypes.Message) //trigger translation
2) turnContext.OnSendActivities(async (newContext, activities, nextSend) => //trigger translation
3) turnContext.OnUpdateActivity(async (newContext, activity, nextUpdate) => //trigger translation
短路中间件不会调用
await next(cancellationToken).ConfigureAwait(false);
or
return await nextSend();
or
return await nextUpdate();
如果未调用它们,则消息处理停止。堆栈中的其他中间件将不会处理传入的消息。