Introduction
Microsoft’s Store is a very convenient way to deliver software to end users throughout the world. The usual process to localize applications for Universal Window Platform (UWP) requires linking a discrete resource for every label. This approach might not suit everyone’s needs.
This article provides an alternative solution for handling string localization, inspired by string replacement. This approach doesn’t intend to be best practice, but a solid, usable method that provides additional flexibility.
Existing Approach
The current UWP documentation and examples recommend using the identifier of XAML objects to associate the Text
property with a string definition. These are located inside .resw
files.
For example, consider this label:
<TextBlock x:Uid="Greeting"/>
The localization of this label’s Text
property could be defined as follows:
While this recommended practice is powerful, granular, and straightforward, it requires a discrete definition for each TextBlock
object. This can result in a large amount of data entry, and some people (including me) might prefer to have all identical text occurrences translated from one source, using global string keys that can be reused throughout the application.
Alternate Approach
Instead of directly translating the labels inside the Resource file, we can instead use it to store key string entries. These entries can then be used for lookups, allowing us to get away from the previous object naming scheme:
We then create a static class that parses the resource from a string key argument, and returns our localized string or any appropriate default string if an entry can’t be found:
public class LocalizedStrings { public static LocalizedStrings Current; public string this[string key] { get { ResourceLoader loader = ResourceLoader.GetForViewIndependentUse(); string localized = loader.GetString(key); return localized.Length > 0 ? localized : "Missing"; } } public LocalizedStrings() { Current = this; } }
Since we want to have this class be available from both XAML and C# code-behind, we need to include it in the static application resources from XAML:
<Application.Resources> <ResourceDictionary> <local:LocalizedStrings x:Key="Localized"/> </ResourceDictionary> </Application.Resources>
From there, it’s fairly trivial to use it for XAML Binding:
<TextBlock Text="{Binding Source={StaticResource Localized}, Path=[Delay]}">
But also from C# code-behind:
LocalizedStrings localizedStrings = App.Current.Resources["Localized"] as LocalizedStrings; String greetings_txt = localizedStrings["WelcomeMessage"];
Caveat
The key entry in the resource shouldn’t contain any dots; otherwise, it will be misinterpreted as individual child items.
Similarly, slashes or break lines don’t seem possible either because Visual Studio will complain with compilation errors.
For instance: using the key Greetings.Text
would target the child property Text
of the Greetings
object and not be considered as a single text entry.
Useful Tools
This very handy website simplifies management of terms, and I’m very enthusiastic about it!
- Support for multi-language terms management
- Gitlab integration for easy sync
- Collaborative work
- Wide range of format export (.resw for windows)
- Various optional automatic translation offerings
Conclusion
This solution can greatly help when in comes to cross-platform projects. In my case, it was more aligned with the approach we also used for iOS implementation, and it allowed us to share a single source of terms between the platforms. I am considering to improve this solution further and find ways to inject text (or values) into the localized strings, handle plurals, etc.
Any comments or suggestions you might have about this approach would be warmly welcomed.