Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
33 changes: 33 additions & 0 deletions Dialogs/LanguageConst.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;

namespace EmergencyServicesBot.Dialogs
{
internal static class LanguageConst
{
//TODO change this to have dictionary with language info object (culture + id + display name)

//Set the language to be used; you can change this on-demand to change the langauage across the app
//You will pass this everytime you request a value from the resx file
internal static readonly CultureInfo ciEnglish = new CultureInfo("en-US");
internal static readonly CultureInfo ciSpanish = new CultureInfo("es-US");
internal static readonly CultureInfo ciChinese = new CultureInfo("zh-CN");
internal static readonly CultureInfo ciFrench = new CultureInfo("fr-FR");

internal const string enLanguageId = "en";
internal const string esLanguageId = "es";
internal const string frLanguageId = "fr";
internal const string zhLanguageId = "zh-CN";

internal const string enLanguageName = "English";
internal const string esLanguageName = "Español";
internal const string zhLanguageName = "中文";
internal const string frLanguageName = "Français";

internal static readonly string[] languages = new[] { enLanguageName, esLanguageName, zhLanguageName, frLanguageName };
internal static readonly string[] smsLanguages = new[] { $"1 -{enLanguageName}", $"2 -{esLanguageName}", $"3 -{zhLanguageName}", $"4 -{frLanguageName}" };
}
}
2 changes: 2 additions & 0 deletions Dialogs/QandADialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,12 @@ static async Task<string> GetAuthenticationToken(string key)
}
}

//TODO change to use resources
private bool IsDoneCommand(string commandText) =>
commandText.Equals(@"done", StringComparison.OrdinalIgnoreCase)
|| commandText.StartsWith(@"no", StringComparison.OrdinalIgnoreCase)
|| commandText.Equals(@"exit", StringComparison.OrdinalIgnoreCase)
|| commandText.Equals(@"quitter", StringComparison.OrdinalIgnoreCase)
|| commandText.Equals(@"quit", StringComparison.OrdinalIgnoreCase);
}
}
113 changes: 62 additions & 51 deletions Dialogs/RootDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Configuration;
using System.Net.Http;
using System.Web;
using System.Diagnostics;

namespace EmergencyServicesBot.Dialogs
{
Expand All @@ -22,11 +23,7 @@ public class RootDialog : IDialog<object>
{
static ResourceManager translateDialog = new ResourceManager("EmergencyServicesBot.Resources.Resources", Assembly.GetExecutingAssembly());

//Set the language to be used; you can change this on-demand to change the langauage across the app
//You will pass this everytime you request a value from the resx file
static CultureInfo ciEnglish = new CultureInfo("en-US");
static CultureInfo ciSpanish = new CultureInfo("es-US");
static CultureInfo ciChinese = new CultureInfo("zh-CN");
private const string userDataCultureKey = @"cultureInfo";

public async Task StartAsync(IDialogContext context)
{
Expand Down Expand Up @@ -62,7 +59,7 @@ private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMess

PromptDialog.Choice(context, UserChoiceMade, choices, welcomeMessage);
}

}

private static string[] GetMainMenuChoices(IDialogContext context)
Expand All @@ -78,65 +75,79 @@ private static string[] GetMainMenuChoices(IDialogContext context)

private async Task DetectAndSaveUserLanguageAsync(IDialogContext context, string userText)
{

using (var langDetectClient = new HttpClient())
if (!context.UserData.TryGetValue(@"userLanguage", out string userLanguage))
{
langDetectClient.DefaultRequestHeaders.Add(@"Ocp-Apim-Subscription-Key", ConfigurationManager.AppSettings[@"TranslatorApiKey"]);

try
using (var langDetectClient = new HttpClient())
{
var detectedLanguageXmlResponse = XDocument.Parse(await langDetectClient.GetStringAsync($@"{ConfigurationManager.AppSettings[@"TranslatorEndpoint"]}/Detect?text={HttpUtility.UrlEncode(userText)}"));

context.UserData.SetValue(@"userLanguage", detectedLanguageXmlResponse.Root.Value);
langDetectClient.DefaultRequestHeaders.Add(@"Ocp-Apim-Subscription-Key", ConfigurationManager.AppSettings[@"TranslatorApiKey"]);

if (detectedLanguageXmlResponse.Root.Value == "en")
{
context.UserData.SetValue(@"cultureInfo", ciEnglish);
}
else if (detectedLanguageXmlResponse.Root.Value == "es")
try
{
context.UserData.SetValue(@"cultureInfo", ciSpanish);
var detectedLanguageXmlResponse = XDocument.Parse(await langDetectClient.GetStringAsync($@"{ConfigurationManager.AppSettings[@"TranslatorEndpoint"]}/Detect?text={HttpUtility.UrlEncode(userText)}"));

context.UserData.SetValue(@"userLanguage", detectedLanguageXmlResponse?.Root?.Value);
var userCulture = GetCultureInfoFromLanguageId(detectedLanguageXmlResponse?.Root?.Value);

context.UserData.SetValue(userDataCultureKey, userCulture);
}
else if (detectedLanguageXmlResponse.Root.Value == "zh-CN")
catch (Exception ex)
{
context.UserData.SetValue(@"cultureInfo", ciChinese);
Trace.TraceError($@"Error detecting language from inital user chat: {ex.ToString()}");
}
else { context.UserData.SetValue(@"cultureInfo", ciEnglish); }
}


}
catch (Exception ex)
{
System.Diagnostics.Trace.TraceError($@"Error detecting language from inital user chat: {ex.ToString()}");
}
}
else
{
var userCulture = GetCultureInfoFromLanguageId(userLanguage);

if (context.UserData.GetValue<String>("userLanguage") == "en")
{
context.UserData.SetValue(@"cultureInfo", ciEnglish);
}
else if (context.UserData.GetValue<String>("userLanguage") == "es")
{
context.UserData.SetValue(@"cultureInfo", ciSpanish);
}
else if (context.UserData.GetValue<String>("userLanguage") == "zh-CN")
{
context.UserData.SetValue(@"cultureInfo", ciChinese);
}
else { context.UserData.SetValue(@"cultureInfo", ciEnglish); }

context.UserData.SetValue(userDataCultureKey, userCulture);
}
}

private CultureInfo GetCultureInfoFromLanguageId(string languageId)
{
if (string.IsNullOrWhiteSpace(languageId))
{
return LanguageConst.ciEnglish;
}

CultureInfo userCulture = LanguageConst.ciEnglish;

switch (languageId)
{
case LanguageConst.esLanguageId:
userCulture = LanguageConst.ciSpanish;
break;
case LanguageConst.zhLanguageId:
userCulture = LanguageConst.ciChinese;
break;
case LanguageConst.frLanguageId:
userCulture = LanguageConst.ciFrench;
break;
case LanguageConst.enLanguageId:
default:
userCulture = LanguageConst.ciEnglish;
break;
}

return userCulture;
}

private async Task UserChoiceMade(IDialogContext context, IAwaitable<string> result)
{
var choice = await result;

//TODO change with resource entry directly
if ((choice.IndexOf(@"get answers", 0, StringComparison.OrdinalIgnoreCase) != -1) ||
(choice.IndexOf(@"Obtener Respuestas", 0, StringComparison.OrdinalIgnoreCase) != -1) ||
(choice.IndexOf(@"Obtenir les réponses", 0, StringComparison.OrdinalIgnoreCase) != -1) ||
(choice.IndexOf(@"其他问题", 0, StringComparison.OrdinalIgnoreCase) != -1))
context.Call(new QandADialog(), DoneWithSubdialog);
else if ((choice.IndexOf(@"Select language", 0, StringComparison.OrdinalIgnoreCase) != -1) ||
(choice.IndexOf(@"Seleccione el idioma", 0, StringComparison.OrdinalIgnoreCase) != -1) ||
(choice.IndexOf(@"Sélectionner la langue", 0, StringComparison.OrdinalIgnoreCase) != -1) ||
(choice.IndexOf(@"选择语言", 0, StringComparison.OrdinalIgnoreCase) != -1))
context.Call(new SetLanguage(), DoneWithSubdialog);
}
Expand Down Expand Up @@ -165,26 +176,26 @@ public static async Task SendWelcomeMessage(IMessageActivity activity)

ConnectorClient client = new ConnectorClient(new Uri(activity.ServiceUrl));

var title = translateDialog.GetString("WelcomeTitle", ciEnglish);
var title = translateDialog.GetString("WelcomeTitle", LanguageConst.ciEnglish);

IList<Attachment> cardsAttachment = new List<Attachment>();
var reply = ((Activity)activity).CreateReply();

CardImage CI = new CardImage
{
Url = translateDialog.GetString("WelcomeImageUrl", ciEnglish),
Url = translateDialog.GetString("WelcomeImageUrl", LanguageConst.ciEnglish),
};


//TODO change by adding resources instead of hardcoded text
var heroCard = new HeroCard
{
Title = title,
Subtitle = "Hello. Hola. 你好.",
Text = "Say \"hi\" to begin, diga \"hola\" para comenzar, 说“嗨”开始",
Subtitle = "Hello. Hola. 你好. Bonjour.",
Text = "Say \"hi\" to begin, diga \"hola\" para comenzar, 说“嗨”开始, dites \"Bonjour\" pour commencer",
Images = new List<CardImage> { CI }
};


cardsAttachment.Add(heroCard.ToAttachment());

reply.Attachments = cardsAttachment;
Expand All @@ -203,6 +214,6 @@ public class BasicQnAMakerDialog : QnAMakerDialog
// Required: subscriptionKey, knowledgebaseId,
// Optional: defaultMessage, scoreThreshold[Range 0.0 – 1.0]
public BasicQnAMakerDialog() : base(new QnAMakerService(new QnAMakerAttribute(Utils.GetAppSetting("QnASubscriptionKey"), Utils.GetAppSetting("QnAKnowledgebaseId"), "I could not find an answer to your question. Please try again or contact Houston 311.", 0.5)))
{}
{ }
}
}
55 changes: 26 additions & 29 deletions Dialogs/SetLanguage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,15 @@ public class SetLanguage : IDialog<object>

//Set the language to be used; you can change this on-demand to change the langauage across the app
//You will pass this everytime you request a value from the resx file
static CultureInfo ciEnglish = new CultureInfo("en-US");
static CultureInfo ciSpanish = new CultureInfo("es-US");
static CultureInfo ciChinese = new CultureInfo("zh-CN");


public async Task StartAsync(IDialogContext context)
{
// offer user languages currently supported
string[] choices = new[] { @"English", @"Español", @"中文" };
if (context.Activity.ChannelId == ChannelIds.Sms)
{ // on SMS, communicate they can choose by replying with "1" or "2"
choices = new[] { @"1 - English", @"2 - Español", @"3 - 中文" };
}

PromptDialog.Choice(
context,
this.onLanguageSelect,
choices,
translateDialog.GetString("SetLanguage", context.UserData.GetValue<CultureInfo>("cultureInfo")));
context,
this.onLanguageSelect,
context.Activity.ChannelId == ChannelIds.Sms ? LanguageConst.smsLanguages : LanguageConst.languages,
translateDialog.GetString("SetLanguage", context.UserData.GetValue<CultureInfo>("cultureInfo")));
}

private async Task onLanguageSelect(IDialogContext context, IAwaitable<string> result)
Expand All @@ -44,29 +35,35 @@ private async Task onLanguageSelect(IDialogContext context, IAwaitable<string> r
var choice = await result;
CultureInfo culture;

if (choice.IndexOf(@"english", 0, StringComparison.OrdinalIgnoreCase) != -1)
if (choice.IndexOf(LanguageConst.enLanguageName, 0, StringComparison.OrdinalIgnoreCase) != -1)
{
choice = LanguageConst.enLanguageId;
selectedLanguage = LanguageConst.enLanguageName;
culture = LanguageConst.ciEnglish;
}
else if (choice.IndexOf(LanguageConst.esLanguageName, 0, StringComparison.OrdinalIgnoreCase) != -1)
{
choice = "en";
selectedLanguage = "English";
culture = ciEnglish;
choice = LanguageConst.esLanguageId;
selectedLanguage = LanguageConst.esLanguageName;
culture = LanguageConst.ciSpanish;
}
else if (choice.IndexOf(@"español", 0, StringComparison.OrdinalIgnoreCase) != -1)
else if (choice.IndexOf(LanguageConst.zhLanguageName, 0, StringComparison.OrdinalIgnoreCase) != -1)
{
choice = "es";
selectedLanguage = "Español";
culture = ciSpanish;
choice = LanguageConst.zhLanguageId;
selectedLanguage = LanguageConst.zhLanguageName;
culture = LanguageConst.ciChinese;
}
else if (choice.IndexOf(@"中文", 0, StringComparison.OrdinalIgnoreCase) != -1)
else if (choice.IndexOf(LanguageConst.frLanguageName, 0, StringComparison.OrdinalIgnoreCase) != -1)
{
choice = "zh-CN";
selectedLanguage = "中文";
culture = ciChinese;
choice = LanguageConst.frLanguageId;
selectedLanguage = LanguageConst.frLanguageName;
culture = LanguageConst.ciFrench;
}
else
{
choice = "en";
selectedLanguage = "English";
culture = ciEnglish;
choice = LanguageConst.enLanguageId;
selectedLanguage = LanguageConst.enLanguageName;
culture = LanguageConst.ciEnglish;
}

context.UserData.SetValue(@"userLanguage", choice);
Expand Down
14 changes: 12 additions & 2 deletions EmergencyServicesBot.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props" Condition="Exists('packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props')" />
<Import Project="packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.8\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.8\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
<Import Project="packages\Microsoft.Net.Compilers.2.6.1\build\Microsoft.Net.Compilers.props" Condition="Exists('packages\Microsoft.Net.Compilers.2.6.1\build\Microsoft.Net.Compilers.props')" />
<Import Project=".\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.1\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('.\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.1\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
Expand Down Expand Up @@ -175,6 +175,7 @@
<ItemGroup>
<Compile Include="App_Start\WebApiConfig.cs" />
<Compile Include="Controllers\DirectLineController.cs" />
<Compile Include="Dialogs\LanguageConst.cs" />
<Compile Include="Dialogs\QandADialog.cs" />
<Compile Include="Dialogs\RootDialog.cs" />
<Compile Include="Controllers\MessagesController.cs" />
Expand All @@ -183,6 +184,11 @@
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources\Resources.fr-FR.Designer.cs">
<DependentUpon>Resources.fr-FR.resx</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Resources\Resources.en-US.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
Expand Down Expand Up @@ -211,6 +217,10 @@
</None>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Resources.fr-FR.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.fr-FR.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Resources.en-US.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.en-US.Designer.cs</LastGenOutput>
Expand Down Expand Up @@ -256,9 +266,9 @@
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Microsoft.Net.Compilers.2.6.1\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Net.Compilers.2.6.1\build\Microsoft.Net.Compilers.props'))" />
<Error Condition="!Exists('packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.8\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.8\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
<Error Condition="!Exists('packages\Microsoft.Azure.DocumentDB.1.20.2\build\Microsoft.Azure.DocumentDB.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Azure.DocumentDB.1.20.2\build\Microsoft.Azure.DocumentDB.targets'))" />
<Error Condition="!Exists('packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
4 changes: 2 additions & 2 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SimpleEchoBot")]
[assembly: AssemblyTitle("EmergencyServicesBot")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SimpleEchoBot")]
[assembly: AssemblyProduct("EmergencyServicesBot")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
Expand Down
Empty file.
Loading