Using Microsoft Translator in Windows Store Apps

Standard

Microsoft Translator is a translation portal by Microsoft as part of Bing services that can provide a machine-translation of texts or entire web pages in (currently) 40 different languages. Microsoft Translator also provides a set of web service APIs (that can be called via an HTTP REST service, an AJAX callable service, or a SOAP service) for developers who wish to use Microsoft Translator in their applications. In this article we will develop a Windows Store application that uses the SOAP service of Microsoft Translator to translate text between languages, and if supported, speak the translated text.

Microsoft Translator is available on Windows Azure Marketplace and is licensed monthly based on the number of characters sent to the translation service. However, it is free up to 2.000.000 characters each month, so we can just sign up and start using it for free.

We will start by going to Windows Azure Marketplace and signing in with our Live ID. If you don’t have a Windows Azure Marketplace account associated with the Live ID you used to sign in, you will simply create one by entering your name, surname, country (and optionally your organization).

1

2

After your registration is complete, either search for “Microsoft Translator” on Windows Azure Marketplace or click here to go to Microsoft Translator page, and click Sign Up at the bottom offer (2.000.000 characters).

3

At the next screen, after agreeing the Offer Terms and Privacy policy and clicking sign up again, you will see that your order is complete. We will now need to register our application to get a client ID and client secret which we will use to connect to Microsoft Translator. To do this, click “Register your application” at the bottom of the page.

5

Next, we will need to enter a Client ID, Name, Redirect URI and Description for our application. Keep these in mind:
– You will notice that the Client Secret will be already completed. Do not change it, as it is used to connect to your account.
– Give Client ID a meaningful name, because both Client ID and Client Secret will be needed in your application.
– Redirect URI is not used in the translator, so you can just enter any valid URL that uses https, for example: https://www.microsoft.com
– You can leave “Enable subdomain access” unchecked, because the translator does not use it.
– Your Client ID needs to be unique.

6

Click create, and we are ready to start building our Windows 8 application. Let’s open up Visual Studio and create a blank Windows Store Application project.

7

We will begin by adding Microsoft Translator web service to our application. In the Solution Explorer, right-click references, and select “Add a Service Reference”.

8

At the next screen, copy and paste “http://api.microsofttranslator.com/V2/Soap.svc” to the Address bar, and click Go. When the web service is found, give it a name and click “Ok” to add it to the project.

9

Now that we’ve added the web service, we should add the web service reference to our MainPage.xaml.cs file.

using TranslatorTestApp.TranslatorService;

We need an access token before sending a text. We will therefore create an AccessToken class and then a variable that we will use to get the access token. Keep in mind that these access tokens are valid for 10 minutes, so you will need to make sure you get a new token after that. After adding the class, we will initialize the web service, add our ClientID and ClientSecret variables, define data market access uri which we will need to use the translator, and also define an AccessToken object.

        public class AccessToken
        {
            public string access_token { get; set; }
            public string token_type { get; set; }
            public string expires_in { get; set; }
            public string scope { get; set; }
        }
        LanguageServiceClient webService = new LanguageServiceClient();
        string clientId = String.Empty; //Set your own client id here
        string clientSecret = String.Empty; //Set your own client secred here
        string dataMarketAccessUri = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
        AccessToken accessToken;

        public MainPage()
        {
            this.InitializeComponent();
        }

Next, we will prepare the interface. Our application will be simple: We will get a text from user in English and translate it to 3 other languages (German, Italian and Turkish), and then the user can click a button to speak the translated text out loud. The code for our MainPage.xaml will look like this:

        <MediaElement x:Name="mediaElement" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100"/>
        <TextBox x:Name="sourceTextBox" HorizontalAlignment="Left" Margin="150,200,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="120" Width="250"/>
        <Button x:Name="translateButton" Content="Translate" HorizontalAlignment="Left" Margin="306,325,0,0" VerticalAlignment="Top" Click="translateButton_Click"/>
        <ProgressRing x:Name="progressRing" HorizontalAlignment="Left" Margin="495,200,0,0" VerticalAlignment="Top" Height="135" Width="135"/>
        <TextBlock HorizontalAlignment="Left" Margin="734,200,0,0" TextWrapping="Wrap" Text="German:" VerticalAlignment="Top" FontSize="16" TextAlignment="Right"/>
        <TextBlock x:Name="germanTranslationTextBlock" HorizontalAlignment="Left" Margin="801,200,0,0" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="16"/>
        <TextBlock HorizontalAlignment="Left" Margin="734,260,0,0" TextWrapping="Wrap" Text="Italian:" VerticalAlignment="Top" FontSize="16" Width="59" TextAlignment="Right"/>
        <TextBlock x:Name="italianTranslationTextBlock" HorizontalAlignment="Left" Margin="801,260,0,0" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="16"/>
        <TextBlock HorizontalAlignment="Left" Margin="734,320,0,0" TextWrapping="Wrap" Text="Turkish:" VerticalAlignment="Top" FontSize="16" Width="59" TextAlignment="Right"/>
        <TextBlock x:Name="turkishTranslationTextBlock" HorizontalAlignment="Left" Margin="801,320,0,0" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="16"/>
        <Button x:Name="germanSpeakButton" Content="Speak" HorizontalAlignment="Left" Margin="652,190,0,0" VerticalAlignment="Top"/>
        <Button x:Name="italianSpeakButton" Content="Speak" HorizontalAlignment="Left" Margin="652,250,0,0" VerticalAlignment="Top"/>
        <Button x:Name="turkishSpeakButton" Content="Speak" HorizontalAlignment="Left" Margin="652,310,0,0" VerticalAlignment="Top"/>

10

As you can see we added a textbox, textblocks, buttons and a mediaelement which we will use when we wish to speak the translated text.

We will then get our access token with the following function:

        public MainPage()
        {
            this.InitializeComponent();
            getAccessToken();
        }
        async public void getAccessToken()
        {
            translateButton.IsEnabled = false;
            progressRing.IsActive = true;
            MessageDialog messageDialog;
            HttpClient client = new HttpClient();
            StringContent request = new StringContent(string.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=http://api.microsofttranslator.com", System.Net.WebUtility.UrlEncode(clientId), System.Net.WebUtility.UrlEncode(clientSecret)));
            request.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
            try
            {
                HttpResponseMessage response = await client.PostAsync(dataMarketAccessUri, request);
                if (response.IsSuccessStatusCode)
                {
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AccessToken));
                    //Get deserialized object from JSON stream
                    Stream x = await response.Content.ReadAsStreamAsync();
                    accessToken = (AccessToken)serializer.ReadObject(x);
                }
                else
                {
                    messageDialog = new MessageDialog(response.StatusCode.ToString());
                    await messageDialog.ShowAsync();
                    Application.Current.Exit();
                }
            }
            catch (Exception e)
            {
                messageDialog = new MessageDialog(e.Message);
                messageDialog.ShowAsync();
            }

            translateButton.IsEnabled = true;
            progressRing.IsActive = false;
        }

In the getAccessToken() function, we use our ClientID and ClientSecret to obtain a valid AccessToken. Next, we will need to do the actual translation in the click event of the Translate button:

        async private void translateButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (sourceTextBox.Text.Length > 2000)
                {
                    MessageDialog messageDialog = new MessageDialog("Text must not exceed 2000 characters.");
                    await messageDialog.ShowAsync();
                }
                else if (String.IsNullOrEmpty(sourceTextBox.Text))
                {
                    MessageDialog messageDialog = new MessageDialog("Please enter a text to translate.");
                    await messageDialog.ShowAsync();
                }
                else
                {
                    progressRing.IsActive = true;
                    translateButton.IsEnabled = false;
                    using (OperationContextScope scope = new OperationContextScope(webService.InnerChannel))
                    {
                        germanTranslationTextBlock.Text = await webService.TranslateAsync("Bearer " + accessToken.access_token, sourceTextBox.Text, "en", "de", "text/plain", "");
                        italianTranslationTextBlock.Text = await webService.TranslateAsync("Bearer " + accessToken.access_token, sourceTextBox.Text, "en", "it", "text/plain", "");
                        turkishTranslationTextBlock.Text = await webService.TranslateAsync("Bearer " + accessToken.access_token, sourceTextBox.Text, "en", "tr", "text/plain", "");
                        translateButton.IsEnabled = true;
                        progressRing.IsActive = false;
                    }
                }
            }
            catch (Exception ex)
            {
                translateButton.IsEnabled = true;
                progressRing.IsActive = false;
                MessageDialog messageDialog = new MessageDialog(ex.Message);
                messageDialog.ShowAsync();
            }
        }

We can translate up to 10000 characters at once, so it is a good idea to check if the length of the text is greater than this before the web method call. You can click here for a list of the methods (and their details) in the SOAP service.

If you start the application now, you will see that we are translating our text. The last thing we need to add is to speak the translated text, which we will accomplish in the click events of the speak buttons:

        async private void germanSpeakButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string speakStreamUri = await webService.SpeakAsync("Bearer " + accessToken.access_token, germanTranslationTextBlock.Text, "de", "audio/wav", "MinSize");
                HttpClient client = new HttpClient();
                client.BaseAddress = new Uri("http://api.microsofttranslator.com/v2/Http.svc/");
                var bytes = await client.GetByteArrayAsync(speakStreamUri);
                InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream();
                DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0));
                writer.WriteBytes(bytes.ToArray());
                await writer.StoreAsync();
                mediaElement.SetSource(ms, "audio/wav");
                mediaElement.Play();
            }
            catch (Exception ex)
            {
                MessageDialog messageDialog = new MessageDialog(ex.Message);
                messageDialog.ShowAsync();
            }
        }

        async private void italianSpeakButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string speakStreamUri = await webService.SpeakAsync("Bearer " + accessToken.access_token, italianTranslationTextBlock.Text, "it", "audio/wav", "MinSize");
                HttpClient client = new HttpClient();
                client.BaseAddress = new Uri("http://api.microsofttranslator.com/v2/Http.svc/");
                var bytes = await client.GetByteArrayAsync(speakStreamUri);
                InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream();
                DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0));
                writer.WriteBytes(bytes.ToArray());
                await writer.StoreAsync();
                mediaElement.SetSource(ms, "audio/wav");
                mediaElement.Play();
            }
            catch (Exception ex)
            {
                MessageDialog messageDialog = new MessageDialog(ex.Message);
                messageDialog.ShowAsync();
            }
        }

        async private void turkishSpeakButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string speakStreamUri = await webService.SpeakAsync("Bearer " + accessToken.access_token, turkishTranslationTextBlock.Text, "tr", "audio/wav", "MinSize");
                HttpClient client = new HttpClient();
                client.BaseAddress = new Uri("http://api.microsofttranslator.com/v2/Http.svc/");
                var bytes = await client.GetByteArrayAsync(speakStreamUri);
                InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream();
                DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0));
                writer.WriteBytes(bytes.ToArray());
                await writer.StoreAsync();
                mediaElement.SetSource(ms, "audio/wav");
                mediaElement.Play();
            }
            catch (Exception ex)
            {
                MessageDialog messageDialog = new MessageDialog(ex.Message);
                messageDialog.ShowAsync();
            }
        }

We can now run our application, translate a sentence, and then speak the translated text. Note that speaking the translated text in Turkish language is not supported, therefore when we try that we will get an exception.

11

I hope this article has been useful. 🙂

You can get the source code here (without the client secret, though).

Advertisements

2 thoughts on “Using Microsoft Translator in Windows Store Apps

  1. TCP

    This sample code does not work for me.

    germanTranslationTextBlock.Text = await webService.TranslateAsync(“Bearer ” + accessToken.access_token, sourceTextBox.Text, “en”, “de”, “text/plain”, “”);

    On this line I get an exception, The remote server returned and unexpected response :(417) expectation failed.

    • Hi,

      I’m sorry for the extremely rate reply.

      I’ve just tried running the application to see if there were any errors, and it worked without problems.

      The first thing that comes to my mind is that something may be wrong with the client id and the client secret. You have to add them yourself in the sample code that I provided, they are set to String.Empty as default. Can you confirm that you added your client id and client secret correctly?

Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s