Localizing a Windows Phone (7) application
I’ve been trying to clean up the What’s Shaking, NZ? for Windows Phone 7 codebase recently, as there was quite a bit of duplicated code and plenty of room for problems (read: shitty code). I’ll be migrating it to Windows Phone 8 soon, and want it as clean as possible before I start.
One part of the clean up was localization. Localization of your resources is important, as it allows you to easily distribute your application in multiple languages without having to modify your code. Too few developers do this, and having an application display its content in the language of the device is a great way to make your users feel appreciated. I’ve done localization in Java previously, but never in .NET. I did some Googling and found a few guides, it was pretty simple:
- Add an
AppResources.resx
file (for your default language, as specified in Assembly Info for the project) - Add some strings with keys
- Reference the keys in code wherever the strings are needed
- Additional languages are just
AppResources.xx-YY.resx
, wherexx
is the region andYY
is the language. For example,AppResources.de-DE.resx
. You can see the full list here. - Finally edit the
*.csproj
file to include your newly supported languages.
Pretty simple. However, the guide I was following didn’t detail how to handle the case where you had multiple projects. Oh dear. I couldn’t find anything online about supporting multiple projects - other than just having a new AppResources.resx
file per project, which I didn’t want.
As it turns out, it’s still very simple to do. Instead of adding the AppResources.resx
file to the current project, just add a new project as a Windows Phone class library and then add the AppResources.resx
file to that. Now, you can reference it from anywhere, provided you include a reference and a using
statement from the other project back into the resources project:
1 2 3 4 5 6 7 8 |
|
To access the resources from XAML, you need to add the following class to your resources library:
1 2 3 4 5 6 7 8 9 10 |
|
You will also need to add the following to the App.xaml
file (the guide I linked to above doesn’t detail all of this):
1 2 3 4 5 6 7 8 9 10 |
|
And then to reference the resources in the XAML for each page, change anything that was using hardcoded text to use a binding as follows:
1 2 3 4 |
|
You can see all of these changes in this commit.
There are a few important gotchas with this:
- The DLL filename cannot end in “Resources”. I had some trouble with this, but I eventually found this blog post detailing the fact there are some reserved file names in XAP files. Specifically, you can’t have DLLs ending in ‘Resources’. If you have named your project as “Resources”, everything will compile fine but your app will crash when it runs. It’s easy enough to fix - I renamed my project (and the properties that named the DLL) from
WhatsShakingNZ.Resources
toWhatsShakingNZ.Localization
. After doing this, everything worked perfectly. - You must specify the
AppResources.resx
Access Modifier aspublic
or you won’t be able to access the resource properties: - The default language as specified in the Assembly Information under the project Properties window is the one that your default
AppResources.resx
file is considered to be. If the device your application is running on is running any language other than your default, it will search for the resource string in the corresponding language resource file. If that resource file does not exist (or, if the specific key it is looking for does not exist in that region-specific file), then it will fall back to your default. This means you can have some strings localised and some not, even within the same page. - To support additional languages, you have to add the
AppResources.xx-YY.resx
file, and also declare in the.csproj
file for the main project that it supports the language (not the project containing your resource files). You have to edit this file manually in a text editor, as detailed in step 4 of the guide linked above. You can check out this MSDN blog, this guide or this forum post for a bit more information on how and why.