With Windows Phone 8 the number of markets where users can get apps and games has been increased to a whopping 191 [1]. And even with Windows Phone 7.8, by the time of writing 95 markets are available [2].
These are quite impressive numbers compared to the opportunities we had when Windows Phone was released initially. Naturally now topics like localization become more and more interesting even for smaller apps, to stimulate customers' interest outside the English-speaking world. Windows Phone supported this from the beginning, however the tooling was somewhat inferior to what we were used to from other Microsoft platforms. In Windows Phone 8, Microsoft has improved the developer experience for localization and made it significantly more comfortable to translate your applications to different languages.
Globalization vs. Localization
Before we start with a hands-on walkthrough of how to localize your app, let's get some clearance on terms that are often mixed or not well understood by a lot of developers: globalization and localization. Here is what the MSDN documentation says on globalization [3]:
"Globalization is the process of designing and developing a software product that functions in multiple cultures/locales."
In other words: globalization ensures that your app will work in different languages and geographic areas with respect to the set of rules that are in place for the respective locale. These rules affect things like: date, time and number formatting, currencies, weight/measurement and other conventions as well as sorting rules. An example would be to display a number like "1.234" as "1,234" in a German environment, because in Germany the decimal separator is a comma, not a point. If you want to learn more on globalization, best practices on Windows Phone and the differences between 8.0 and 7.x, take a look at the MSDN documentation [4].
Localization on the other hand is described as [5]:
"The process of adapting a globalized application […] to a particular culture/locale. […] The localization process refers to translating the application user interface (UI) or adapting graphics for a specific culture/locale."
In contrast to globalization where you ensure that your application adapts to the specific locale gracefully without the need for further action, localization is the step when you actually take your content and create specific versions of it for different locales. Typically this will involve the translation of strings and texts, but of course it's not limited to that. Localization also covers swapping icons and graphics or even sounds and other audio for particular cultures.
Using hard-coded, constant strings or similar constructs prevents you from localizing your app efficiently. To enable your application for localization, you hence need to prepare it properly, for example by separating code and data in a nice way. In the following steps we will see how this can be done with a Windows Phone 8 app.
Getting Started
As I mentioned, one of the nice things about Windows Phone 8 is that the tooling around localization has improved a lot. No more editing of your project files in a text editor or similar manual steps, at least for the main tasks. In fact, when you create a new empty project, you already will be presented with a project structure set up for localization. Just remember to choose "Windows Phone OS 8.0" as target platform – the structure is not created with the 7.1 template, and it's also not added when you later decide to upgrade a 7.1 project to version 8.
The whole setup basically consists of three parts:
- For each supported culture, a resource file is located in the "Resources" folder (as seen in the screenshot above).
- A class named "LocalizedStrings" (again as seen in the screenshot) is created and used as a XAML binding helper construct.
- In the Application class' resources (in App.xaml) an instance of the "LocalizedStrings" helper class is created and provided globally so localized resources can be bound in XAML everywhere in your app:
Some hints to get you quickly started with localization based on these parts are located in the MainPage.xaml as a block of comments:
So basically, with the new template everything already is set up for you so you can start translating your app right away. Let's see how this is done.
First Steps
First of all, let's actually replace the currently hard-coded application title on the main page with the binding that is described in the above comment section. In the following screenshot, I've left the original version in XAML as a comment for comparison:
As you can see in the second binding I'm setting up, we have nice IntelliSense support for the available resources, and the tooltip even provides me with a preview of what the result will look like ("… similar to Hallo World!"). The "Hallo World!" part is taken from the "AppResources.resx" file where I have added the "MainPageTitle" entry like this:
Two things are worth noting here: first of all there are some special entries listed here: "ResourceLanguage" and "ResourceFlowDirection". These two are used in "App.xaml.cs" in code to set the language and flow direction property of the top-level element in your UI:
Usually you don't need to change that code or worry about it. All you need to know is that all your resource files need to have these two entries as sort of a self-description so the UI bits can be set up automatically. We'll see how this works for additional languages in a moment.
The second important thing to remember is that the "AppResources.resx" which has been created automatically is a special resource file that denotes the neutral language. The entries you make here are used whenever no resource for the current culture is found. That means that if someone e.g. uses German with their phone, but you haven't provided German resources, the entries from this file will be used as fallback. All additional resource files that you create will be specific to a certain culture and also technically a bit different (see below). The actual language that is used as neutral language can be set in the "Assembly Information" dialog in the project properties (tab "Application"):
With everything above in place, you will see that the app indeed resolves the two bindings to what we have entered in the resource file when you run it:
Adding A New Supported Culture
The interesting part of course starts when you add additional supported cultures. With the new tooling, this is easier than ever. Just open the project properties of your Windows Phone app and navigate to the "Application" tab. There you will find a "Supported Cultures" section at the bottom. Let's add German to the list of cultures that the app supports:
As soon as you hit the save button for your project, you will see that a new resource file has been created automatically for you. The technical difference is that no code-behind (.Designer.cs) file has been created for it. This is the usual localization mechanism that is no different from other .NET platforms.
Behind the scenes, the "SupportedCultures" node of the project file is edited also, something that you had to do manually in previous versions of the Windows Phone tooling.
The new resource file contains copies of all the entires of the neutral language resource file, but the language and flow direction values have been adjusted automatically to fit your selection. Now you can change the values of the remaining entries to appropriate translations:
To test the new culture, you can switch your phone or the emulator to a different language in the "Settings" area (which requires a restart). Once switched to German, the app indeed presents a translated UI:
Of course you can still override the auto-detected culture by setting it in code, like:
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
This enables you to allow the user to choose a different language from their phone settings. Naturally you would store such a preference in some user-specific configuration data instead of hard-coding it.
Additional Improvements
One thing to note is that culture settings are thread specific. Until now you had to set up your desired culture data for each thread you were using manually. With Windows Phone 8, two new static properties have been added to the CultureInfo class: DefaultThreadCurrentCulture [6] and DefaultThreadCurrentUICulture [7]. This lets you set the default cultures used on an AppDomain level so you don't have to worry anymore about situations where subtle culture-related errors may arise from multi-threading scenarios.
… And The Ugly
Despite the comfortable improvements with Windows Phone 8 and Visual Studio 2012, there are still some areas where localization of Windows Phone apps is a bit more complex than you might expect. Especially those details that integrate more deeply with the underlying (native) system are not exactly obvious to set up. Two of these you inevitably will run into when you localize your app:
The Application Bar
Just like in Windows Phone 7, the application bar elements like the ApplicationBarIconButton and the ApplicationBarMenuItem do not support data binding of their fundamental properties like "Text". This means that you need to create and set up these elements in code manually to support localized content, like this:
// Set the page's ApplicationBar to a new instance of ApplicationBar.
ApplicationBar = new ApplicationBar();
// Create a new button and set the text value to the localized string from AppResources.
var appBarButton = new ApplicationBarIconButton(
new Uri("/Assets/AppBar/appbar.add.rest.png", UriKind.Relative)
);
appBarButton.Text = AppResources.AppBarButtonText;
ApplicationBar.Buttons.Add(appBarButton);
This snippet is taken from the commented hints that are created by the default project template in your project's MainPage.xaml.cs.
One way to elegantly work around this issue and avoid code is to make use of the available frameworks that support bindable application bar elements in XAML. If you are using MVVM as design pattern for your app you probably already have decided for a supporting MVVM framework – take a look at its documentation, most of them come with bindable application bar replacements out of the box.
The App Title
The application title that is used in the application list on the phone (including the texts used for the live tiles) is another example of a rather tedious process that is involved when you want to apply localization. You need to create separate C++ resource-only Win32 dlls to achieve this. Luckily, the whole process is described in elaborate detail on MSDN [8]. Yet still, as you can see there, this quickly gets time-consuming when you want to support a lot of cultures. A nicer solution is to use one of the available tools that generate these dlls automatically for you. Patrick Getzmann for example has created a separate software to help you with this [9] (he also still offers the Windows Phone 7 version [10]).
Conclusion
Localization always takes a bit more effort than single culture apps, as you have to plan ahead and separate code and data thoroughly. This typically involves additional code in the form of bindings and helper classes. However, Windows Phone 8 and Visual Studio 2012 make this significantly easier than previous versions of Windows Phone. We still have some areas that can be improved in the future, but luckily third party developers already came up with various solutions, frameworks and tools that you can use comfortably to work around the current limitations that are still in place.