Skip to content

Commit

Permalink
Merge 609f19b into d078226
Browse files Browse the repository at this point in the history
  • Loading branch information
mdrichardson committed Sep 18, 2019
2 parents d078226 + 609f19b commit c9d7641
Show file tree
Hide file tree
Showing 7 changed files with 531 additions and 31 deletions.
54 changes: 38 additions & 16 deletions libraries/Microsoft.Bot.Builder.Dialogs/Prompts/ChoicePrompt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs.Choices;
using Microsoft.Bot.Schema;
using static Microsoft.Recognizers.Text.Culture;
using static Microsoft.Bot.Builder.Dialogs.Prompts.PromptCultureModels;

namespace Microsoft.Bot.Builder.Dialogs
{
Expand All @@ -16,18 +16,6 @@ namespace Microsoft.Bot.Builder.Dialogs
/// </summary>
public class ChoicePrompt : Prompt<FoundChoice>
{
private static readonly Dictionary<string, ChoiceFactoryOptions> DefaultChoiceOptions = new Dictionary<string, ChoiceFactoryOptions>()
{
{ Spanish, new ChoiceFactoryOptions { InlineSeparator = ", ", InlineOr = " o ", InlineOrMore = ", o ", IncludeNumbers = true } },
{ Dutch, new ChoiceFactoryOptions { InlineSeparator = ", ", InlineOr = " of ", InlineOrMore = ", of ", IncludeNumbers = true } },
{ English, new ChoiceFactoryOptions { InlineSeparator = ", ", InlineOr = " or ", InlineOrMore = ", or ", IncludeNumbers = true } },
{ French, new ChoiceFactoryOptions { InlineSeparator = ", ", InlineOr = " ou ", InlineOrMore = ", ou ", IncludeNumbers = true } },
{ German, new ChoiceFactoryOptions { InlineSeparator = ", ", InlineOr = " oder ", InlineOrMore = ", oder ", IncludeNumbers = true } },
{ Japanese, new ChoiceFactoryOptions { InlineSeparator = "", InlineOr = " または ", InlineOrMore = "、 または ", IncludeNumbers = true } },
{ Portuguese, new ChoiceFactoryOptions { InlineSeparator = ", ", InlineOr = " ou ", InlineOrMore = ", ou ", IncludeNumbers = true } },
{ Chinese, new ChoiceFactoryOptions { InlineSeparator = "", InlineOr = " 要么 ", InlineOrMore = ", 要么 ", IncludeNumbers = true } },
};

/// <summary>
/// Initializes a new instance of the <see cref="ChoicePrompt"/> class.
/// </summary>
Expand All @@ -50,6 +38,18 @@ public ChoicePrompt(string dialogId, PromptValidator<FoundChoice> validator = nu
DefaultLocale = defaultLocale;
}

/// <summary>
/// Gets or sets a dictionary used for custom prompt display based on user-provided locale settings.
/// </summary>
/// <value>The dictionary used for custom prompt display based on user-provided locale settings.</value>
/// <remarks>
/// If set, this replaces DefaultChoiceOptions. Because this is static, it is not thread-safe.
/// Usage: ChoicePrompt.CustomLocaleOptions = new Dictionary<string, ChoiceFactoryOptions>()
/// { "en-US", new ChoiceFactoryOptions {...} }
/// </remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1629:Documentation text should end with a period", Justification = "Doesn't like `Dictionary<string`")]
public static Dictionary<string, ChoiceFactoryOptions> CustomLocaleOptions { get; set; }

/// <summary>
/// Gets or sets the style to use when presenting the prompt to the user.
/// </summary>
Expand All @@ -76,6 +76,28 @@ public ChoicePrompt(string dialogId, PromptValidator<FoundChoice> validator = nu
/// <value>Options to control the recognition strategy.</value>
public FindChoicesOptions RecognizerOptions { get; set; }

/// <summary>
/// Gets a dictionary of Default ChoiceOptions based on Microsoft.Bot.Builder.Dialogs.Prompts.PromptCultureModels.GetSupportedCultures.
/// </summary>
private static Dictionary<string, ChoiceFactoryOptions> DefaultChoiceOptions
{
get
{
if (CustomLocaleOptions == null || CustomLocaleOptions.Count == 0)
{
var defaults = new Dictionary<string, ChoiceFactoryOptions>();
foreach (var culture in GetSupportedCultures())
{
defaults.Add(culture.Locale, new ChoiceFactoryOptions { InlineSeparator = culture.Separator, InlineOr = culture.InlineOr, InlineOrMore = culture.InlineOrMore, IncludeNumbers = true });
}

return defaults;
}

return CustomLocaleOptions;
}
}

/// <summary>
/// Prompts the user for input.
/// </summary>
Expand All @@ -101,10 +123,10 @@ protected override async Task OnPromptAsync(ITurnContext turnContext, IDictionar
}

// Determine culture
var culture = turnContext.Activity.Locale ?? DefaultLocale;
var culture = MapToNearestLanguage(turnContext.Activity.Locale ?? DefaultLocale);
if (string.IsNullOrEmpty(culture) || !DefaultChoiceOptions.ContainsKey(culture))
{
culture = English;
culture = English.Locale;
}

// Format prompt to send
Expand Down Expand Up @@ -152,7 +174,7 @@ protected override Task<PromptRecognizerResult<FoundChoice>> OnRecognizeAsync(IT
var activity = turnContext.Activity;
var utterance = activity.Text;
var opt = RecognizerOptions ?? new FindChoicesOptions();
opt.Locale = activity.Locale ?? opt.Locale ?? DefaultLocale ?? English;
opt.Locale = MapToNearestLanguage(activity.Locale ?? opt.Locale ?? DefaultLocale ?? English.Locale);
var results = ChoiceRecognizers.RecognizeChoices(utterance, choices, opt);
if (results != null && results.Count > 0)
{
Expand Down
52 changes: 37 additions & 15 deletions libraries/Microsoft.Bot.Builder.Dialogs/Prompts/ConfirmPrompt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
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,18 +17,6 @@ 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(""), 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>
/// Initializes a new instance of the <see cref="ConfirmPrompt"/> class.
/// </summary>
Expand All @@ -51,6 +39,18 @@ public ConfirmPrompt(string dialogId, PromptValidator<bool> validator = null, st
DefaultLocale = defaultLocale;
}

/// <summary>
/// Gets or sets a dictionary used for custom prompt display based on user-provided locale settings.
/// </summary>
/// <value>The dictionary used for custom prompt display based on user-provided locale settings.</value>
/// <remarks>
/// If set, this replaces DefaultChoiceOptions. Because this is static, it is not thread-safe.
/// Usage: ChoicePrompt.CustomLocaleOptions = new Dictionary<string, ChoiceFactoryOptions>()
/// { "en-US", (new Choice("Yes"), new Choice("No"), new ChoiceFactoryOptions {...}) }
/// </remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1629:Documentation text should end with a period", Justification = "Doesn't like `Dictionary<string`")]
public static Dictionary<string, (Choice, Choice, ChoiceFactoryOptions)> CustomLocaleOptions { get; set; }

/// <summary>
/// Gets or sets the style of the yes/no choices rendered to the user when prompting.
/// </summary>
Expand Down Expand Up @@ -78,6 +78,28 @@ public ConfirmPrompt(string dialogId, PromptValidator<bool> validator = null, st
/// <value>The yes and no <see cref="Choice"/> for the prompt.</value>
public Tuple<Choice, Choice> ConfirmChoices { get; set; }

/// <summary>
/// Gets a dictionary of Default Choices based on Microsoft.Bot.Builder.Dialogs.Prompts.PromptCultureModels.GetSupportedCultures.
/// </summary>
private static Dictionary<string, (Choice, Choice, ChoiceFactoryOptions)> ChoiceDefaults
{
get
{
if (CustomLocaleOptions == null || CustomLocaleOptions.Count == 0)
{
var defaults = new Dictionary<string, (Choice, Choice, ChoiceFactoryOptions)>();
foreach (var culture in GetSupportedCultures())
{
defaults.Add(culture.Locale, (new Choice(culture.YesInLanguage), new Choice(culture.NoInLanguage), new ChoiceFactoryOptions(culture.Separator, culture.InlineOr, culture.InlineOrMore, true)));
}

return defaults;
}

return CustomLocaleOptions;
}
}

/// <summary>
/// Prompts the user for input.
/// </summary>
Expand Down Expand Up @@ -184,10 +206,10 @@ protected override Task<PromptRecognizerResult<bool>> OnRecognizeAsync(ITurnCont

private string DetermineCulture(Activity activity)
{
var culture = activity.Locale ?? DefaultLocale;
var culture = MapToNearestLanguage(activity.Locale ?? DefaultLocale ?? English.Locale);
if (string.IsNullOrEmpty(culture) || !ChoiceDefaults.ContainsKey(culture))
{
culture = English;
culture = English.Locale;
}

return culture;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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; }
}
}
118 changes: 118 additions & 0 deletions libraries/Microsoft.Bot.Builder.Dialogs/Prompts/PromptCultureModels.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
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 = "",
};

/// <summary>
/// Use Recognizers-Text to normalize various potential Locale strings to a standard.
/// This mostly exists so that you don't need to directly include Recognizers-Text in other class files (there are some name conflicts).
/// </summary>
/// <param name="culture">Represents locale. Examples: "en-US, en-us, EN".</param>
/// <returns>Normalized locale.</returns>
public static string MapToNearestLanguage(string culture) => Culture.MapToNearestLanguage(culture);

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

0 comments on commit c9d7641

Please sign in to comment.