Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better Culture Recognition in Choice/Confirm Prompts #2463

Merged
merged 32 commits into from
Oct 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b9703a0
Better Culture Recognition in Choice/Confirm Prompts
Aug 30, 2019
08f957a
alphabetized
Sep 3, 2019
ebc8d1b
- Added Danish
Sep 3, 2019
4f22a78
fixed Danish "or"
Sep 4, 2019
68b0da8
Made PromptCultureModel a Standard Class
Sep 5, 2019
28f2e7a
Revert "Made PromptCultureModel a Standard Class"
Sep 18, 2019
a42b670
Revert "fixed Danish "or""
Sep 18, 2019
b09af82
Revert "- Added Danish"
Sep 18, 2019
ed4c520
added ability to set custom locale dictionaries
Sep 18, 2019
32d1660
renamed custom dictionary properties
Sep 18, 2019
cd1df13
Revert "renamed custom dictionary properties"
Sep 19, 2019
dd824f7
Revert "added ability to set custom locale dictionaries"
Sep 19, 2019
4513f0a
Revert "Revert "added ability to set custom locale dictionaries""
Sep 27, 2019
a3d159c
Revert "Revert "renamed custom dictionary properties""
Sep 27, 2019
eb48fe9
Revert "renamed custom dictionary properties"
Sep 27, 2019
6ab082e
Revert "added ability to set custom locale dictionaries"
Sep 27, 2019
523d9b4
Revert "Revert "- Added Danish""
Sep 27, 2019
939e84a
Revert "Revert "fixed Danish "or"""
Sep 27, 2019
957782f
back to basics
Sep 27, 2019
71685b7
ConfirmPrompt and tests fixed
Sep 27, 2019
d316f3f
fixed ChoicePrompt and tests
Sep 27, 2019
49c226b
added doc param
Sep 27, 2019
4c21350
added as new ctor
Sep 30, 2019
f567c07
moved param
Sep 30, 2019
2f6701e
fixed spacing and ctor
Sep 30, 2019
d986977
added copyrights
Oct 9, 2019
a9aa356
Merge branch 'master' into cultureRecognizer
mdrichardson Oct 10, 2019
7561e31
touch
Oct 15, 2019
d1f9040
remove unnecessary imports
Oct 15, 2019
997fd7b
Merge branch 'cultureRecognizer' of https://github.com/microsoft/botb…
Oct 15, 2019
a3bb628
fixed tests
Oct 15, 2019
56fc84b
comment update
Oct 15, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
356 changes: 189 additions & 167 deletions libraries/Microsoft.Bot.Builder.Dialogs/Prompts/ChoicePrompt.cs

Large diffs are not rendered by default.

58 changes: 41 additions & 17 deletions libraries/Microsoft.Bot.Builder.Dialogs/Prompts/ConfirmPrompt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs.Choices;
using Microsoft.Bot.Schema;
using Microsoft.Recognizers.Text.Choice;
using static Microsoft.Recognizers.Text.Culture;
using static Microsoft.Bot.Builder.Dialogs.Prompts.PromptCultureModels;

namespace Microsoft.Bot.Builder.Dialogs
{
Expand All @@ -17,17 +18,17 @@ namespace Microsoft.Bot.Builder.Dialogs
/// </summary>
public class ConfirmPrompt : Prompt<bool>
{
private static readonly Dictionary<string, (Choice, Choice, ChoiceFactoryOptions)> ChoiceDefaults = new Dictionary<string, (Choice, Choice, ChoiceFactoryOptions)>()
{
{ Spanish, (new Choice("Sí"), new Choice("No"), new ChoiceFactoryOptions(", ", " o ", ", o ", true)) },
{ Dutch, (new Choice("Ja"), new Choice("Nee"), new ChoiceFactoryOptions(", ", " of ", ", of ", true)) },
{ English, (new Choice("Yes"), new Choice("No"), new ChoiceFactoryOptions(", ", " or ", ", or ", true)) },
{ French, (new Choice("Oui"), new Choice("Non"), new ChoiceFactoryOptions(", ", " ou ", ", ou ", true)) },
{ German, (new Choice("Ja"), new Choice("Nein"), new ChoiceFactoryOptions(", ", " oder ", ", oder ", true)) },
{ Japanese, (new Choice("はい"), new Choice("いいえ"), new ChoiceFactoryOptions("、 ", " または ", "、 または ", true)) },
{ Portuguese, (new Choice("Sim"), new Choice("Não"), new ChoiceFactoryOptions(", ", " ou ", ", ou ", true)) },
{ Chinese, (new Choice("是的"), new Choice("不"), new ChoiceFactoryOptions(", ", " 要么 ", ", 要么 ", true)) },
};
/// <summary>
/// A dictionary of Default Choices based on <seealso cref="GetSupportedCultures"/>.
/// Can be replaced by user using the constructor that contains choiceDefaults.
/// </summary>
private readonly Dictionary<string, (Choice, Choice, ChoiceFactoryOptions)> _choiceDefaults =
new Dictionary<string, (Choice, Choice, ChoiceFactoryOptions)>(
GetSupportedCultures().ToDictionary(
culture => culture.Locale, culture =>
(new Choice(culture.YesInLanguage),
new Choice(culture.NoInLanguage),
new ChoiceFactoryOptions(culture.Separator, culture.InlineOr, culture.InlineOrMore, true))));

/// <summary>
/// Initializes a new instance of the <see cref="ConfirmPrompt"/> class.
Expand All @@ -51,6 +52,29 @@ public ConfirmPrompt(string dialogId, PromptValidator<bool> validator = null, st
DefaultLocale = defaultLocale;
}

/// <summary>
/// Initializes a new instance of the <see cref="ConfirmPrompt"/> class.
/// </summary>
/// <param name="dialogId">The ID to assign to this prompt.</param>
/// <param name="validator">Optional, a <see cref="PromptValidator{FoundChoice}"/> that contains additional,
/// custom validation for this prompt.</param>
/// <param name="defaultLocale">Optional, the default locale used to determine language-specific behavior of the prompt.
/// The locale is a 2, 3, or 4 character ISO 639 code that represents a language or language family.</param>
/// <param name="choiceDefaults">Overrides the dictionary of Bot Framework SDK-supported _choiceDefaults (for prompt localization).
/// Must be passed in to each ConfirmPrompt that needs the custom choice defaults.</param>
/// <remarks>The value of <paramref name="dialogId"/> must be unique within the
/// <see cref="DialogSet"/> or <see cref="ComponentDialog"/> to which the prompt is added.
/// <para>If the <see cref="Activity.Locale"/>
/// of the <see cref="DialogContext"/>.<see cref="DialogContext.Context"/>.<see cref="ITurnContext.Activity"/>
/// is specified, then that local is used to determine language specific behavior; otherwise
/// the <paramref name="defaultLocale"/> is used. US-English is the used if no language or
/// default locale is available, or if the language or locale is not otherwise supported.</para></remarks>
public ConfirmPrompt(string dialogId, Dictionary<string, (Choice, Choice, ChoiceFactoryOptions)> choiceDefaults, PromptValidator<bool> validator = null, string defaultLocale = null)
: this(dialogId, validator, defaultLocale)
{
_choiceDefaults = choiceDefaults;
}

/// <summary>
/// Gets or sets the style of the yes/no choices rendered to the user when prompting.
/// </summary>
Expand Down Expand Up @@ -106,7 +130,7 @@ protected override async Task OnPromptAsync(ITurnContext turnContext, IDictionar
IMessageActivity prompt;
var channelId = turnContext.Activity.ChannelId;
var culture = DetermineCulture(turnContext.Activity);
var defaults = ChoiceDefaults[culture];
var defaults = _choiceDefaults[culture];
var choiceOptions = ChoiceOptions ?? defaults.Item3;
var confirmChoices = ConfirmChoices ?? Tuple.Create(defaults.Item1, defaults.Item2);
var choices = new List<Choice> { confirmChoices.Item1, confirmChoices.Item2 };
Expand Down Expand Up @@ -160,7 +184,7 @@ protected override Task<PromptRecognizerResult<bool>> OnRecognizeAsync(ITurnCont
else
{
// First check whether the prompt was sent to the user with numbers - if it was we should recognize numbers
var defaults = ChoiceDefaults[culture];
var defaults = _choiceDefaults[culture];
var choiceOptions = ChoiceOptions ?? defaults.Item3;

// This logic reflects the fact that IncludeNumbers is nullable and True is the default set in Inline style
Expand All @@ -184,10 +208,10 @@ protected override Task<PromptRecognizerResult<bool>> OnRecognizeAsync(ITurnCont

private string DetermineCulture(Activity activity)
{
var culture = activity.Locale ?? DefaultLocale;
if (string.IsNullOrEmpty(culture) || !ChoiceDefaults.ContainsKey(culture))
var culture = MapToNearestLanguage(activity.Locale ?? DefaultLocale ?? English.Locale);
if (string.IsNullOrEmpty(culture) || !_choiceDefaults.ContainsKey(culture))
mdrichardson marked this conversation as resolved.
Show resolved Hide resolved
{
culture = English;
culture = English.Locale;
}

return culture;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Microsoft.Bot.Builder.Dialogs.Prompts
{
/// <summary>
/// Culture model used in Choice and Confirm Prompts.
/// </summary>
public class PromptCultureModel
{
/// <summary>
/// Gets or Sets Culture Model's Locale.
/// </summary>
/// <value>
/// Ex: Locale. Example: "en-US".
/// </value>
public string Locale { get; set; }

/// <summary>
/// Gets or Sets Culture Model's InlineSeparator.
/// </summary>
/// <value>
/// Ex: Locale. Example: ", ".
/// </value>
public string Separator { get; set; }

/// <summary>
/// Gets or Sets Culture Model's InlineOr.
/// </summary>
/// <value>
/// Ex: Locale. Example: " or ".
/// </value>
public string InlineOr { get; set; }

/// <summary>
/// Gets or Sets Culture Model's InlineOrMore.
/// </summary>
/// <value>
/// Ex: Locale. Example: ", or ".
/// </value>
public string InlineOrMore { get; set; }

/// <summary>
/// Gets or Sets Equivalent of "Yes" in Culture Model's Language.
/// </summary>
/// <value>
/// Ex: Locale. Example: "Yes".
/// </value>
public string YesInLanguage { get; set; }

/// <summary>
/// Gets or Sets Equivalent of "No" in Culture Model's Language.
/// </summary>
/// <value>
/// Ex: Locale. Example: "No".
/// </value>
public string NoInLanguage { get; set; }
}
}
119 changes: 119 additions & 0 deletions libraries/Microsoft.Bot.Builder.Dialogs/Prompts/PromptCultureModels.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Microsoft.Recognizers.Text;

namespace Microsoft.Bot.Builder.Dialogs.Prompts
{
/// <summary>
/// Class container for currently-supported Culture Models in Confirm and Choice Prompt.
/// </summary>
public static class PromptCultureModels
{
public static PromptCultureModel Chinese =>
new PromptCultureModel
{
InlineOr = " 要么 ",
InlineOrMore = ", 要么 ",
Locale = Culture.Chinese,
NoInLanguage = "不",
Separator = ", ",
YesInLanguage = "是的",
};

public static PromptCultureModel Dutch =>
new PromptCultureModel
{
InlineOr = " of ",
InlineOrMore = ", of ",
Locale = Culture.Dutch,
NoInLanguage = "Nee",
Separator = ", ",
YesInLanguage = "Ja",
};

public static PromptCultureModel English =>
new PromptCultureModel
{
InlineOr = " or ",
InlineOrMore = ", or ",
Locale = Culture.English,
NoInLanguage = "No",
Separator = ", ",
YesInLanguage = "Yes",
};

public static PromptCultureModel French =>
new PromptCultureModel
{
InlineOr = " ou ",
InlineOrMore = ", ou ",
Locale = Culture.French,
NoInLanguage = "Non",
Separator = ", ",
YesInLanguage = "Oui",
};

public static PromptCultureModel German =>
new PromptCultureModel
{
InlineOr = " oder ",
InlineOrMore = ", oder ",
Locale = Culture.German,
NoInLanguage = "Nein",
Separator = ", ",
YesInLanguage = "Ja",
};

public static PromptCultureModel Japanese =>
new PromptCultureModel
{
InlineOr = " または ",
InlineOrMore = "、 または ",
Locale = Culture.Japanese,
NoInLanguage = "いいえ",
Separator = "、 ",
YesInLanguage = "はい",
};

public static PromptCultureModel Portuguese =>
new PromptCultureModel
{
InlineOr = " ou ",
InlineOrMore = ", ou ",
Locale = Culture.Portuguese,
NoInLanguage = "Não",
Separator = ", ",
YesInLanguage = "Sim",
};

public static PromptCultureModel Spanish =>
new PromptCultureModel
{
InlineOr = " o ",
InlineOrMore = ", o ",
Locale = Culture.Spanish,
NoInLanguage = "No",
Separator = ", ",
YesInLanguage = "Sí",
};

/// <summary>
/// Use Recognizers-Text to normalize various potential Locale strings to a standard.
/// <param name="cultureCode">Represents locale. Examples: "en-US, en-us, EN".</param>
/// <returns>Normalized locale.</returns>
public static string MapToNearestLanguage(string cultureCode) => Culture.MapToNearestLanguage(cultureCode);

public static PromptCultureModel[] GetSupportedCultures() => new PromptCultureModel[]
{
Chinese,
Dutch,
English,
French,
German,
Japanese,
Portuguese,
Spanish,
};
}
}
Loading