1

In my app, I want to give the user the opportunity to switch a light on and off with voice commands (via Cortana for example). I understand the VCD concept and really like but I don't know how to handle the different languages in my code.

Given I have two languages (English and German):

<CommandSet xml:lang="en" Name="LightSwitch_en">
    <CommandPrefix>Switch the light</CommandPrefix>
    <Example>Switch the light on.</Example>
    <Command Name="switchLight">
        <Example>on</Example>
        <ListenFor>{status}</ListenFor>
        <Feedback>Light will be switched {status}.</Feedback>
        <Navigate />
    </Command>
    <PhraseList Label="status">
        <Item>on</Item>
        <Item>off</Item>
    </PhraseList>        
</CommandSet>

<CommandSet xml:lang="de" Name="LightSwitch_de">
    <CommandPrefix>Schalte das licht</CommandPrefix>
    <Example>Schalte das Licht ein.</Example>
    <Command Name="switchLight">
        <Example>ein</Example>
        <ListenFor>{status}</ListenFor>
        <Feedback>Licht wird {status}geschaltet.</Feedback>
        <Navigate />
    </Command>
    <PhraseList Label="status">
        <Item>ein</Item>
        <Item>aus</Item>
    </PhraseList>        
</CommandSet>

When my app launches by a voice command, I can easily extract the spoken words and can access the status parameter. But because it's a string I will get a different result depending on which language the user has spoken.

So if the user speaks English, the string is "on", but if he speaks German, the string would be "ein". So how do I know, which string I need to listen for inside my app? I am targeting something like this:

if (arg.Equals("on"))
    Light.On();
else if (arg.Equals("off"))
    Light.Off();

But this only works in English of cause, not in German. I resent checking for all different strings in all languages, that can't be the right way. Unfortuantely it is also not possible to give the <Item> tags an additional attribute due to they are just strings.

I could do something like if (arg.Equals("on") || arg.Equals("ein")) Light.On(); but as you can see this is really ugly and I have to adjust it every time I change something and well, imagine I had about 15 languages to check...

Do you know a smarter solution?

Robin-Manuel Thiel
  • 2,206
  • 19
  • 26
  • I am not familiar with this API, but what is exactly the question? It returns `arg`, and you are asking how to handle what the `arg` is? Why not `if(arg.Equals("on") || arg.Equals("ein") Light.On();`? Also the "ResourceDictionary" API might be helpful for you. – Paweł Mach Nov 25 '15 at 14:40
  • Going `if(arg.Equals("on") || arg.Equals("ein") Light.On();` is exactly what I want to avoid. Imagine, I had 15 different languages... The ResourceDictionary idea could be a nice solution, like Matt Lacey pointed out. – Robin-Manuel Thiel Nov 25 '15 at 17:53

2 Answers2

2

As Cortana will use the same localization as the built in app localization method can you not put all your strings in resource files and then compare the returned string with the localized resource?

Matt Lacey
  • 65,560
  • 11
  • 91
  • 143
  • 1
    Good idea but then I also have to adjust these properties in both files. But you gave me an idea: I could generate the `PhraseList` out of a resource file. I will try it out and post it if it worked. – Robin-Manuel Thiel Nov 26 '15 at 12:00
  • 1
    @einRobby yes, you'd have the text in two places but you have that with the hardcoded strings too. If you're localizing content I'd hope you have a process for managing all the localized resources such that these resources could just be an extra output from that. – Matt Lacey Nov 26 '15 at 16:48
2

In case you just need to solve that particular case you can do the following, instead a list just define two commands per language:

 <Command Name="oncommand" >
    <Example>switch on</Example>
    <ListenFor>switch on</ListenFor>
    <Feedback>Light will be switched on.</Feedback>
    <Navigate />
</Command>

<Command Name="offcommand">
    <Example>switch off</Example>
    <ListenFor>switch off</ListenFor>
    <Feedback>Light will be switched off.</Feedback>
    <Navigate />
</Command>

and then detect in code what command was called:

if (args.Kind == ActivationKind.VoiceCommand)
        {
            var commandArgs = args as VoiceCommandActivatedEventArgs;
            var speechRecognitionResult = commandArgs.Result;
            string voiceCommandName = speechRecognitionResult.RulePath.First();
            string textSpoken = speechRecognitionResult.Text;
            return voiceCommandName;
        }

where voiceCommandName is 'oncommand' or 'offcommand'.

Juan Pablo Garcia Coello
  • 3,192
  • 1
  • 23
  • 33
  • Yes, that could be a nice solution for this example, as you already pointed out. But imagine, I would also want do create a variable for `Lamp` where the user can chose between `Lamp`, `Heater` and `TV`. Then I would have to implement a command for every possible electronical device... But I like your solution and think I will use it in this case. – Robin-Manuel Thiel Nov 26 '15 at 11:50
  • Sure, hope the team realized about that and create Keys or have a way to have the indexes of which item was selected. – Juan Pablo Garcia Coello Nov 26 '15 at 12:44
  • Yeah, I guess handling `Item`s in a `PhraseList` not just as strings but as objects that I can give an identifier would be a good solution. – Robin-Manuel Thiel Nov 26 '15 at 14:01