I’m learning to read and write in Spanish. Because of where I live, I can practice my Spanish by trying to read the bilingual signs that show up in many public places. The thing is, sometimes I get stuck on one particular word and can’t figure it out, or sometimes I’m confused by a whole sentence. It’s also tough to be sure that I’ve understood what I’ve read without a parallel English translation to refer to. I could carry a Spanish-English dictionary with me, but flipping through all of those pages is just so analog.
What I really want, because I always seem to have my phone in my hand, is an easy way for my phone to help me with the translation. Going to Bing with my phone and using the cloud-based Microsoft Translator is helpful, but it takes a lot of key presses to get to the translation screen. If only there were a way—an easy way—to somehow get the translator on my phone. Well, with the advent of Windows Phone 7, there is.
This article serves as an introduction to developing Windows Phone applications and shows how to tie such an app into a Web service in the cloud. You should have some familiarity with C# and Visual Studio, and it would be helpful if you have at least some experience developing applications with Extensible Application Markup Language (XAML), but this isn’t required. I used the April refresh of the community technology preview (CTP) of the Windows Phone tools. By the time you read this, things may have changed, so go to developer.windowsphone.com to read the latest documentation and download the latest tools.
If you’re going to interact with Translator—or any of the Bing Web services—the first step is to get an AppID. It’s used by the service API to validate that a request is coming from a registered Bing application developer.
Go to bing.com/developers/createapp.aspx and sign in with your Windows Live ID. Then fill out the form, which asks you for your application’s name and description, as well as details such as your company name and e-mail address. Your e-mail address is used to notify you when these APIs change, for example, as new versions are rolled out or old versions taken offline. For the Translator API in particular, at the time of this writing the documentation says that old versions will remain online for 90 days following the release of a new version.
Now that you have an AppID, we’re ready to start working on the mobile translator app.
Before I started to work on my first app, I took a look at some successful mobile applications on the market. I looked at applications for Windows phones and other smartphones to try to get a sense of what makes a truly successful mobile application. I read product reviews. I interviewed people. I pestered my friends to let me play with their phones.
After all this research, I concluded that the key to a successful mobile app is simplicity. Every popular app fulfills one or two key user scenarios and fulfills them well. For example, I discovered a whole class of apps whose sole purpose is to generate rude noises. In practice, they’re essentially a re-implementation of the whoopee cushion on a phone. People seem to find them amusing, at least enough to pay money to load them onto their phones.
Similarly, there are apps that roll simulated dice, recommend a restaurant for dinner and even calculate the tip amount for that particular dinner. All of these have a focused user scenario and execute on that scenario in a way that’s simple and intuitive. This approach isn’t unique to any particular brand of smartphone. The idea that we should have a polished, intuitive user experience is reinforced by the Windows Phone UI Design and Interaction Guide published at developer.windowsphone.com/windows-phone-7.
So when I started to work on my translator app, it was important to focus on exactly what I wanted the app to accomplish, and nothing else. To do this, I first had to have a clear picture of what I wanted to accomplish. Once I had this picture in mind, I could resist the temptation to add cool new features that—while interesting—wouldn’t serve the main user scenario. I decided my app should translate between English and Spanish. It should easily switch translation modes from Spanish to English or English to Spanish, and it should deal with only single words or simple sentences. Moreover, I only cared about Spanish and English, so my app would ignore other languages.
To get started building the translator app, open Visual Studio Express 2010 for Windows Phone. Choose “New project...” and select “Windows Phone Application.” This opens the default Windows Phone project with a screen divided into two sections: Title and Content. These sections are delineated with a XAML Grid object, which lets us define a series of rows and columns in which we can position child UI elements such as Buttons and TextBlocks (see Figure 1).
Figure 1 Default Windows Phone Project with Display and Code Views
First, edit the application name and the page title by selecting these UI elements in the designer. This highlights the related XAML in the code view window of the designer, showing you which element you need to edit. Next, open the toolbox and drag some UI elements to the lower grid on the page, which is named ContentGrid. Choose a TextBox, where we’ll put the words we want to translate, then a TextBlock, where the translation will be rendered. Finally, add two buttons (see Figure 2).
Figure 2 Adding TextBox, TextBlock and Button UI Elements
One button will execute the translation and the second will toggle the direction of the translation from Spanish to English or back again.
The heart of the Windows Phone 7 user experience is the design system code-named “Metro.” And the heart of implementing a UI according to the Metro system is XAML. If you’ve worked with Silverlight or Windows Presentation Foundation (WPF) before, XAML is probably familiar to you. If you haven’t, this section provides a brief introduction.
XAML is a way to declaratively structure your UI, giving you a strict separation between your app’s logic and its look and feel. You’ll notice that the code for your app’s main page, for example, is contained in Mainpage.xaml.cs, but the basic layout of your app is contained in Mainpage.xaml. Unlike traditional Windows Forms development, there’s no mixing of app code with app UI layout. Every UI element in your application is modeled as an XML element in a XAML file.
This is an advantage because it allows one person to work independently on the app’s look and feel while another works on the app’s logic. For example, now that we’ve outlined the basic UI of our translator app, we could hand the XAML to a UI expert while we continue to work on the code. The designer wouldn’t need to know anything about the implementation of my app and I wouldn’t need to know anything about the color palette he’s chosen.
Of course, I don’t have any budget for a UI designer, but I do have MSPaint, and that’s enough to demonstrate how easy it is to update the graphic assets that accompany my app.
I double-click the default ApplicationIcon.png that was automatically added to the project when I created it. This opens my image-editing software, which is MSPaint on my dev machine. I replace the boring gear icon with a capital letter T. Then I erase the black background and fill it in with a monochrome pink. I probably won’t win any awards for graphic design, but I like it (see Figure 3).
Figure 3 A New Project Icon Created with MSPaint
To review the change, I hit the start button to deploy the application to the Windows Phone 7 emulator. If you’ve worked with previous versions of Windows Phone emulators, you’ll see right away how much the developer experience has improved. Working with the emulator for Windows Phone 6.5 can be a pain and involves manual configuration steps to start and attach the debugger to the emulator. Here in the Windows Phone 7 development environment, everything just works once I hit the green start button. I’m even happy with how quickly the emulator loads and displays the app’s main UI (see Figure 4).
Figure 4 The App Displayed by the Windows Phone 7 Emulator
To see the app icon, I exit from the main UI and navigate to the emulator’s main screen. The translator graphic is there, and it looks OK (see Figure 5).
Figure 5 Checking the New App Icon in the Emulator
The application icon is defined in a file called WMAppManifest.xml, which is located in your project’s Properties folder. To rename your app icon, change the name of the ApplicationIcon.png in your project and then make sure you reflect the change here, in the IconPath element:
If your app can’t find its icon, it will be assigned the runtime default, which looks something like a white circle on a black background.
Another element of this file that bears examination is the Capabilities element, which contains the specific capabilities your application wants to use. It’s a good idea to request exactly what your application needs, nothing more. If you scan the file, you’ll see it’s got a number of capabilities we probably aren’t going to use in our translator application.
For example, ID_CAP_GAMERSERVICES declares that your app needs to interact with the XBox game APIs. The ID_CAP_LOCATION capability says that the app wants to make use of the device’s location capability. And ID_CAP_PUSH_NOTIFICATION says that the app wants to interact with the push notification feature of Windows Phone 7. All of these are great features, but we don’t need them for our app, so out they go. In fact, we probably need only the ID_CAP_NETWORKING capability, which says our app wants to use the network to send and receive data.
Microsoft Translator exposes three kinds of APIs. The SOAP API gives the consumer strong typing and ease of use. The AJAX API is primarily useful for Web page developers who want to embed translation into their UI. The HTTP API is useful when neither the SOAP nor the AJAX API is appropriate.
We’re going to choose the SOAP interface, because it’s easiest to work with for our purposes. Go to Solution Explorer and right-click References. Then choose “Add a Service Reference” and input the endpoint for the SOAP interface to the Translator API: http://api.microsofttranslator.com/V2/Soap.svc. Give the service endpoint the name TranslatorService in the namespace textbox and click OK (see Figure 6).
Figure 6 Adding a SOAP Service Reference
Visual Studio takes care of the rest, generating the SOAP interface client code for you.
Now add some code to your application. Add the AppID and a reference to the TranslatorService client in the declaration of your app’s MainPage class:
string appID = <<your appID>>;
TranslationService.LanguageServiceClient client =
IntelliSense shows us that the translator service has a number of interesting methods available. The first thing to notice is that all of the methods are asynchronous. This makes sense, because there’s no good reason to block the client application while we’re waiting for a network operation to complete. It means we’ll need to register a delegate for each specific operation we perform. In our case, we’re only interested in the TranslateAsync method and the TranslateAsyncComplete event exposed by the LanguageServiceClient. But the other methods certainly do look interesting. Let’s take a look at them and see if they fit into our user scenario.
Two methods that stand out are GetLanguagesForTranslateAsync and GetLanguageNamesAsync. The first method provides a list of language codes supported by the Translator service. By calling this method, you can see the language code for Spanish is “es.” The GetLanguageNamesAsync method returns a list of language names for a given set of language codes, localized for a given locale. For example, if you pass “es” into this method as the locale and the language code, you get back the string “Español.” If we were doing a multilingual translator, these would both be useful.
Another interesting method is named SpeakAsync. It accepts a string and a locale and returns a URL to a WAV file that’s the native-sounding pronunciation of a word. This is an awesome feature. For example, I could type in a string, get the translation and then pass this string to the SpeakAsync method to get a WAV file I could use to communicate with others in Spanish. Or if I were unsure of the pronunciation of a particular word, I could use the SpeakAsync method to hear what it was supposed to sound like.
These are pretty cool, and it’s tough to resist the temptation to put them into the app just because they’re cool. For now, though, we should stand firm and focus only on fulfilling the user scenario we outlined at the start. Having this clear picture in mind makes it easier when faced with the temptation to add “just one more feature.” I’m sure I’ll end up using the features offered in the Translator API at some point, just not right now.
Wiring up the code to make our translator app is easy. First, we register the delegates for TranslateCompleted:
client.TranslateCompleted += new
Then we implement the event handler for the TranslateCompleted, which sets the text of our TextBlock to the translated text:
void client_TranslateCompleted(object sender,
TranslatedTextBlock.Text = e.Result;
We wire up the button to submit the text we’ve entered for translation:
private void TranslateButton_Click(object sender,
client.TranslateAsync(appID, TranslateTextBox.Text, fromLanguage,
Then we add some simple code to the second button to toggle between translation modes, from “Spanish to English” or from “English to Spanish.” This button manages a global state variable and changes the text of our translate button to indicate that state.
Finally, we deploy the app to the emulator to test it. We’ve now got a fully functional translator app, with just a few lines of code and an hour or so of development time.
The simple translator app is nice, but we could take it further by expanding our user scenario. It would be great if we could tie more of the languages offered by the Translator API into our app in a way that fits with the Metro design guidelines. And it would be even better if we could eliminate the button that manages the translation direction and instead have a simpler, more intuitive way of managing the direction of the translation. Whatever we do, it has to be friendly to a person using his fingers to interact with the device, and it has to feel fast and easy.
So what do we do? We build an application using the default list project. Start a new project and select “Windows Phone List Application.” This gives you a default screen with a ListBox control in the ContentGrid. The ListBox will contain six languages we want to translate our text into, replacing the dummy text (see Figure 7).
Figure 7 The Default Windows Phone List Application
We’ll edit the MainViewModelSampleData.xaml file, which is contained in the SampleData folder in your project. You’ll see some XML that looks something like this:
<local:ItemViewModel LineOne="design one" LineTwo="Maecenas praesent accumsan bibendum" LineThree="Maecenas praesent accumsan bibendum dictumst eleifend facilisi faucibus habitant inceptos interdum lobortis nascetur"/>
By editing the XML, you can change the design-time view of the ListBox to include all of the languages we want to work with: Spanish, German, English, Portuguese, Italian and French. Notice that after you save this file, the design-time view will reflect your changes. This is because the ListBox control is databound to the Items element defined in MainViewModelSampleData.xaml. This is controlled by the ItemsSource attribute of the ListBox control.
You can also update the contents of the ListBox at run time. If you look into the file generated by Visual Studio, you’ll see an ObservableCollection<ItemViewCollection> being filled with placeholder data similar to that contained in the MainViewModelSampleData.xaml file. For example, if I wanted to dynamically generate the list of languages in the UI based on the languages returned by the GetLanguageNamesAsync method, I would edit the MainViewModel.cs file to populate the Items collection. I prefer to specify a static list of languages for now and just edit the collection of ItemViewModel objects directly. Now when we run the list application, we should see a UI something like Figure 8.
Figure 8 The List Application UI
When the user touches one of these buttons, he’ll be taken to a details page that looks essentially the same as the UI of our SimpleTranslator. There’s a TextBox to enter the words to translate, a TextBlock to contain the translated text and a button to submit the translation. Instead of adding another button to manage the direction of the translation, however, we’ll rely on the Translator API. The bidirectional translation of our SimpleTranslator app doesn’t make sense in this multilingual scenario, and adding additional layers of UI would make the app start to feel clunky instead of smooth. Fortunately, the Translator API provides a way to automatically detect the language being passed in.
We add some code to first call the DetectAsync method of the translator client, passing in the text we want to translate, then call TranslateAsync from the DetectAsyncComplete event handler. The event handler now looks like this:
void client_DetectCompleted(object sender,
string languageCode = e.Result;
client.TranslateAsync(appID, TranslateTextBox.Text, fromLanguage, tolanguage);
We know the language we want to translate into because of the button the user selected. We know the language that we want to translate from because the Translator API has autodetected it. We’re able to create a simple, multilingual translator that allows the user to get a translation with just two touches—not counting typing—and less than an hour of coding.
Simplicity is at the heart of development for Windows Phone 7. An app should focus on fulfilling one user scenario, and fulfilling it well. The tools that come with the Windows Phone 7 SDK CTP make it not only possible but easy to deliver apps that are both simple and powerful. We’ve also seen that interacting with the cloud is straightforward, and that the Microsoft Translator Web service can be wired into a Windows Phone app with just a small investment of developer time. By taking familiar tools such as Visual Studio and clear guidelines such as Metro, Windows Phone and the cloud come together to open up a world of new opportunities for developers and users.
Ramon Arjona is a senior test lead working on the Windows team at Microsoft.
Thanks to the following technical experts for reviewing this article: VikramDendi and Sandor Maurice
Please can anyone help!! is this code compatable with visual studio 2010 ultimate, not the expres version because i keep getting an error when i insert the follwing code: client.TranslateCompleted += new EventHandler<TranslatorService.TranslateCompletedEventArgs> client_TranslateCompleted();
is there an API that allows you to exlore the phones directory and upload content to the internet? Please advise
Where a source code? Nothing don't work. First in Figure 6 you wrote: TranslatorService, then in code you write TranslationService. Try your code first from article
Nick, you forget that the only way to distribute apps on WP7 is through Marketplace, and that there is no official way to copy an app executable off the phone, as there is no accessible file system, or side loading mechanism. So it's not trivial to extract the appId from the software, and IMHO calling a web service to retrieve it is not inherently safer than embedding it. My $.02, Frank
Essentially the appid needs to reside behind a service that can be called (authenticated or otherwise) to retrieve the appid prior to any api calls being made. The app can either perist the key (this leaves it open to being hacked but less so than embedding in the app itself) or it can just dispose of it after making the necessary api calls.
Nick, where DO we put the appId?
Please, please, please, do NOT include your appId in your Windows Phone 7 application. This is extremely bad practice as you should never include api keys in a client application. Other than that, great article!
More MSDN Magazine Blog entries >
Browse All MSDN Magazines
Subscribe to MSDN Flash newsletter
Receive the MSDN Flash e-mail newsletter every other week, with news and information personalized to your interests and areas of focus.