Martin Suchan – BloQ Random #WPdev stuff

26Sep/139

Shared localization for Windows Phone 8 and Windows 8 apps using Portable Class Libraries

When developing Windows Phone 8 or Windows 8 app for more wider audience, you need to think about the localization. Unfortunately the localization on each platform uses completely different approach:

On Windows Phone 8:

  • Standard resx files with strings for each language are used.
  • The default language, for instance "en", has localization in file without any suffix, typically just AppResources.resx.
  • Other languages uses files with culture specific suffix, like AppResources.de.resx, AppResources.cs.resx, etc.
  • For supporting non-default languages it's required to check the additional languages in WMAppManifest.xml file and in the project settings as well
  • Localization in XAML is done typically via databinding to viewmodel class, that has instance of AppResources class, typically:
  • <TextBlock Text="{Binding Loc.AppTitle, Source={StaticResource Localization}}"/>
  • in AppResources.resx:   |   AppTitle   |   Hello world!   |
  • For accessing the localized string programatically you can use:
  • string text = AppResources.AppTitle;
  • Globalization and localization for Windows Phone

On Windows 8(.1)

  • Windows 8 uses for localization new file types ending with .resw, but actually they use completely equal structure as WP8 .resx files.
  • Each file must be placed in a separate folder, for instance English localization should be placed in Strings/en/Resources.resw, German localization in Strings/de/Resources.resw
  • There are no automatically generated Designer.cs files for these resw files, but you can create manually ResourceLoader class for returning localized strings.
  • In Windows 8 the localization of Controls in XAML is done differently. Rather than assigning directly values using databinding, you just name each localizable control with x:Uid property and then add entry for localizing such property directly into resw file:
  • <TextBlock x:Uid="TextBlock1" Text="DesignTimeText"/>
  • in AppResources.resw:   |   TextBlock1.Text   |   Hello world!   |
  • For accessing the localized string programatically you can use:
  • ResourceLoader resourceLoader = new ResourceLoader();
    string text = resourceLoader.GetString("TextBlock1.Text");
  • Application resources and localization sample (Windows 8.1)

As you can see, the recommended localization uses completely different approach in Windows Phone 8 and Windows 8. Sharing resx files using links, or even copying them or renaming is just not feasible to maintain. Beside these obvious differences, there are even other caveats:

  • Accessing localized strings in Windows 8 projects programatically is really cumbersome and you can make simply error, because you have no direct compile time check, that "TextBlock1.Text" actually exists in the resw file.
  • You cannot share any localized XAML code between Windows Phone 8 and Windows 8, because of the different localization method

Let's see, how to solve this mess once and for all

There are few existing approaches for solving this:

I've discovered recently one nice project - ResW File Code Generator for Windows 8 projects. It's a plugin into Visual Studio, that will transparently generate Designer file for your resw localization files and you can then use basically the same localization approach like on Windows Phone 8. Simple and easy. The only two drawbacks I've seen after using this for couple of months - the localized strings are not shown during design-time and you still need to manually copy strings from Windows 8 <-> WP8 projects. This approach is not about sharing, but rather about unified localization string usage.

Another approach is described here: Share localization files between Windows Phone and Windows 8
The author is using another tool, the Multilingual App Toolkit for maintaining single localization file, which is then copied into both projects into the proper format. In my opinion this surely is automatic solution for sharing resource strings, but on the other hand it's even more cumbersome than the original one. The solution I'm proposing below is much, much simpler...

The solution in three words - Portable Class Library

As you already know, Microsoft introduced in Visual Studio 2010 so called Portable Class Libraries, in short PCL. Using these libs you can write code once and reuse it on different platforms - WPF, Silverlight, Windows Phone and Windows 8 apps. Usually PCLs are mostly used for creating single app viewmodel without any platform specific code, and this platform specific code is then injected using Dependency Injection and/or IoC. But PCLs can be also used as a single place for our shared app localization. Basically we just need to copy our localization resx files from Windows Phone project into PCL and we're almost done.

So how to use shared localization for apps using PCL?

  • first create PCL targeting the proper platforms and move there the resx localization files from the Windows Phone 8 project. Make also sure all Windows 8 strings are in there.
  • second, in our Windows 8 project remove all strings except one from each resw file, but keep them in the project. This is necessary, because Windows 8 app can switch itself to other language only if there is localization folder with resw file in it with at least one localized string. So if you want to support localization into en, de and cs, keep the folder Strings/[en|de|cs]/AppResources.resw with at least one string in your project, but you can remove all other strings from there.
  • right click the PCL project and Unload it, now open it as text file and to the first <PropertyGroup> add another tag <SupportedCultures></SupportedCultures>. Here add semicolon separated names for the cultures you want to support. In our case we add there: <SupportedCultures>en;de;cs;</SupportedCultures>. Save the file, right click and Reload. This is a necessary manual step to tell the PCL project to support more than one language. You might even remember that exactly this step was necessary when localizing WP7.0 or WP7.5 apps back then.
  • Make sure you have checked your supported languages in the Windows Phone 8 project properties and in the manifest file.

And that's all. Pros of this solution:

  • single localization file for each language on one place, no complex localization infrastructure or scripts around, no file copying and/or renaming
  • works for Windows 8, Windows Phone 8 and even WPF or Silverlight projects!
  • fully working in design-time when editing XAML files!
  • compile time check for existing strings in the Designer.cs file
  • same localization string usage on both platforms - easy sharing of XAML UserControls

Some Cons you might consider:

  • Windows 8 app localization is done differently, not using the official recommended path with x:Uid naming, but hey, it works!
  • Some manual csproj editing is required, but it's one time job and it's pretty simple.
  • Because we use PCLs, this approach is not supported in Visual Studio Express editions.

Here's the sample with Windows Phone 8, Windows 8 and WPF project using the same shared PCL with localization files.

The summary - we've shown a new and an effective way how to localize your Windows 8 and Windows Phone 8 apps on a single place by placing the localization files into Portable Class Library. In my opinion this is currently the most effective way for sharing localization between apps for different platforms, even better than with Multilingual App Toolkit.

If you liked the article, let me know on Twitter, thanks 🙂

UPDATE If you are running into MissingManifestResourceException when using this approach for Windows Phone 8.1 Universal apps, follow this guide. It worked for me!

  • Cristovao Morgado

    Check my Solution for Win8/WP8 app with MVVM Light and PCL
    https://github.com/cmorgado/MultiPlatform

    I’ve got the Localization, and some more tips 😉

  • Pingback: Shared localization for Windows Phone 8 and Windows 8 apps using Portable Class Libraries()

  • Viktor

    Helped a lot!! Thanks a lot 🙂

  • Kai

    Works perfect! Thanx 🙂

  • summ3r

    If you’re involved in software localization projects, I warmly recommend this collaborative & intuitive online localization tool:https://poeditor.com/

  • Viktor

    Unfortunately I’m facing a problem with this solution. If I access some of the resources in the pcl with AppResources.Login_Title for example, the string won’t be accessible during design time, design time only works with binding to the Localization property in xaml. Do you have some fix for that? 🙂

  • Viktor

    “This is necessary, because Windows 8 app can switch itself to other language only if there is localization folder with resw file in it with at least one localized string.” –> I may have found a better way: In the .appxmanifest in Enter your languages.
    For example:

    Does this work for you? 🙂

  • pooranspress
  • Gerwin Klappe

    I have the problem that it works design time, but not while running the app in W8, have you encountered anything like that?

  • Jozef Čechovský

    Hello, great article. I did it in common way but I encountered one problem. It works pretty good when I run my project in debug/release mode. But when I deploy installation package and install my Win8.1 app, my strings are loaded. But when I change localization nothing happens. I’m desperate about this. Do you have any idea what’s the problem? Thank you

  • Pingback: Tomasz Cielecki: Using RESX files in PCL for Xamarin and Windows projects – XamGeek.com()