coderox

Localization in Windows 8 compared to Windows Phone

Tags: Windows 8,Metro,Localization

When porting applications from Windows Phone to Windows 8, you will benefit greatly from having developed your applications in C# and XAML since most of the architecture and technologies are more or less the same. Naturally there are some differences but my experiences in porting applications tells me that most of the investments is in the design surface and overall experience of the application, not in the code.

Localization do have some differences, the first is that there's a new file extension called .resw instead of the previous .resx. The new .resw file has some improved behavior but also lacks the nice auto-generation of property-based localization that could be used in Windows Phone. One behavior I'm really fond of is the possibility to add a resources with the ID "LoginButton.Content" and a value of "Login" which will make sure that the Content-attribute/element of the Button with the additional XAML-attribute x:Uid="LoginButton" is set to the text "Login". This can also be used with other properties which is very suitable for advanced localizations. But the lack of auto-generated properties is something that causes the need for some additional code, especially for the use of getting localized resources from "code-behind".

In Windows Phone I simply use the following syntax to get a localized resource:

MessageBox.Show(Strings.WelcomeMessage);

Here is three slightly different approaches that can be used to simplify getting a hold of the local resources and mimic the behavior above as close as possible:

1) A static class with a method call.

public static class StaticLocalized 
{
    private static readonly ResourceLoader _loader;

    static StaticLocalized()
    {
        _loader = new ResourceLoader();
    }

    public static string Strings(string key)
    {
        if (string.IsNullOrEmpty(key))
            throw new ArgumentNullException("key");
        return _loader.GetString(key);
    }
}

The client code can then use the following syntax to get the local resource:

var dialog = new MessageDialog(StaticLocalized.Strings("WelcomeMessage"));

2) A singleton with an indexer.

The next suggestion is to create a class which implements the Singleton-pattern to be able to expose an indexer:

public class Localized
{
    private static readonly ResourceLoader _loader;

    private static Localized _instance;
    public static Localized Strings
    {
        get
        {
            if (_instance == null)
                _instance = new Localized();
            return _instance;
        }
    }

    static Localized()
    {
        _loader = new ResourceLoader();
    }

    public string this[string key] {
        get {
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("key");
            return _loader.GetString(key);
        }
    }
}

Then the client code can look like this (very minor change I agree):

var dialog = new MessageDialog(Localized.Strings["WelcomeMessage"]);

3) A dynamic-class with properties.

A pretty neat alternative is to derive your resource wrapper from DynamicObject as follows:

public class DynamicLocalized : DynamicObject
{
    private static readonly ResourceLoader _loader;

    static DynamicLocalized()
    {
        _loader = new ResourceLoader();
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (string.IsNullOrEmpty(binder.Name))
            throw new ArgumentNullException("Name");
        result = _loader.GetString(binder.Name);
        return true;
    }
}

And in each page/class that requires localized resources I create an instance of the dynamic object as follows:

dynamic Strings = new DynamicLocalized();

Then the client code can be pretty much the same as the previous Windows Phone alternative:

var dialog = new MessageDialog(Strings.WelcomeMessage);

I still haven't investigated any performance issues with the latter solution but I find it quite appealing since the code is so close to it's Windows Phone alternative. I still miss the strong typing which also gives IntelliSense support when coding, but then again, none of the solutions above have strong types. I hope that Microsoft changes this behavior in a near future or I will try to leverage T4 to create a similar solution.

Add a Comment