Click here to Skip to main content
15,884,176 members
Articles / Mobile Apps / Windows Mobile

User Interface Localization with the Compact Framework

Rate me:
Please Sign up or sign in to vote.
4.58/5 (26 votes)
24 Oct 2006CPOL7 min read 179.5K   1.1K   43   93
The Compact Framework does not allow for changing the Culture of your UI at runtime. This solution will allow you to switch cultures while still taking advantage of the majority of the features available in the full framework.

Sample Image - UILocalizationWithCF20.png

Introduction

Over the years, I have done mobility applications on Windows Mobile 2003 & 5.0, and I have done globalized/localized applications in ASP, ASP.NET, and Smart Clients. Recently, I came across my first requirement to bring these things together and write a localized, Smart Client application targeted at the Windows Mobile 5.0 platform (utilizing the Microsoft Compact Framework version 2.0). Like most things new on the Compact Framework, it starts out exciting and quickly turns frustrating, as you discover all new areas of the "full" .NET Framework that were sacrificed in order to reduce the footprint of the "compact" version. This article is about the challenges I faced and the solution I used.

Problem Space

In the full .NET Framework, you have the System.Resources.ResourceManager class, which provides all the built-in functionality you need to easily load resources from external assemblies based on the System.Threading.Thread.CurrentUICulture. The ResourceManager is smart enough to find the right assembly, look for the resource and, if it doesn't find the resource, it will "auto-magically" look for your resource in the parent culture, until it either finds a match, or ends up back at the InvariantCulture (which is basically the unknown or generic culture). Changing the resources used by your user interface is as easy as:

C#
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");

The first limitation with the Compact Framework is that the CurrentThread.CurrentUICulture is not supported. This means that your application will use the culture of the OS (see this article on MSDN for more information). But what if you have a situation where all mobile devices are deployed set for US English (en-US), but some operators may want to use a particular application in Mexican Spanish (es-MX) or French Canadian (fr-CA)? You can't do it with the built-in ResourceManager unless you use the OS' Control Panel to change the culture settings for the entire device.

Problem #1 is that we need a way to change the CultureInfo of just our application and have that be used by the ResourceManager.

Next, if you have done any globalization/localization work within Visual Studio 2005, you may have found that there is a built-in mechanism for making your forms "Localizable". I'm not going to try and get into a full dissertation on how this works. If you are interested, I would recommend a walk down "Google Lane". In short, you can use the IDE's form properties to view your form in different locales and change certain property values (i.e., Control.Text) on a per-locale basis. "Under the covers," the IDE creates localized resource assemblies for each locale you support, and will "auto-magically" select the right set of resources at run-time (a-la the ResourceManager described above).

The second limitation of the Compact Framework is that the mechanism which updates the UI is all tied to the CurrentUICulture of the current thread, which as we saw above, is never going to change (unless it is done at the device level).

Problem #2 is that we need the ability to update our UI on-the-fly whenever a change is detected in the culture settings.

Design Goals

In addition to solving the above problem, there were certain design goals which I had for the final solution.

  • It needed to work (obviously), but in doing so, I didn't want to reinvent the wheel. It needed to use as much of the existing infrastructure as possible. In particular, this meant the logic behind finding/selecting the resource files as well as the fall-back mechanism for missing assemblies or resources.
  • It needed to be as "self-contained" and easy to use as possible. I didn't want the developers to get tied up in implementing the mechanism.
  • It needed to support the addition of new resource assemblies in the future without any change to the source code or binaries.

The Solution

The solution that I deployed for this comes in two parts. The first is a custom ResourceManager (implemented as a Singleton), which gives applications the ability to specify the CultureInfo to be used when looking up resources. The second part is a LocalizedForm (derived from System.Windows.Forms.Form) which is designed to be used as the base class for any form that requires localization support. Please refer to the included source code and example project for full details on how this is implemented.

CompactFramework.Utilities.Localization.ResourceManager

The custom ResourceManager gives your application a way to specify the Assembly and CultureInfo of the resources to use. Whenever the CultureInfo is changed, an event is raised, letting subscribers to the event know that there has been a change. The ResourceManager also exposes some overloaded helper methods which allow the LocalizedForm to more easily retrieve resources.

CompactFramework.Utilities.Localization.LocalizedForm

The LocalizedForm provides a common base-class that can be used to provide the functionality of listening for and responding to the ResourceManager.CultureChanged event. It will loop through all of its child controls and menus and update their appropriate properties (i.e., Control.Text, MenuItem.Text, PictureBox.Image, etc.) with the appropriate, localized resource.

Menus Suck!

Another of those areas where the Compact Framework is just plain annoying is in working with menu controls. The root of the problem is that the MenuItem doesn't actually derive from the Control base-class and, as a result, doesn't actually have a Name property that you can read at run-time. I played briefly with a Reflection-based solution to this problem, but having recently worked through a Reflection-based hardware abstraction layer for a similar application, I knew that I was going to run into limitations of the Compact Framework as well as performance penalties.

Instead, I placed a little of the implementation burden on the developer in order to improve performance. As a result, the LocalizedForm base class maintains a Dictionary<MenuItem, string> which the developer fills as part of the constructor on each form, like so:

C#
this.AddMenuToDictionary(this.menuItem1, "MainMenuLeft");
this.AddMenuToDictionary(this.menuItem2, "MainMenuRight");

The LocalizedForm class uses these strings in lieu of the Control.Name property when looking for the Text value in the resource assembly.

Two Final "Gotchas"

There are two aspects of using localization that you must be careful to do correctly, or it will simply not work (and not throw any errors). If you don't locate and name your resource files correctly, it won't find them. If you don't name your resources correctly, it won't find them. In either case, the ResourceManager will simply return its best match or (worst case) will not make any change to the UI.

Location and Name of Your Resource Files

There is one last thing that you have to be sure to do in order for the "built-in" functionality of the underlying ResourceManager to function properly. When you add these resource files to your project, they must be located inside of a project directory named "Resources" and they must be named Resources.<culture-code>.resx (see the image at the top of this article for an example). If you do not do these two things, the ResourceManager will not be able to locate your resource files and you will not get any localized updates.

Naming Your Resources

As you can see in the image at the top of the article, this infrastructure utilizes the name of the control, combined with the name of the parent form, to uniquely identify a resource. If you do not follow this naming convention in your resource files, a match will not be found and no change will be made to the UI (and no error thrown).

What's Remaining?

Right now, I handle the basic controls (TextBox, Label, Button, CheckBox, TabPage, Form, RadioButton, and PictureBox). Additional controls can certainly be added by updating the LocalizedForm.UpdateControls() function.

Summary

I hope that this was interesting and/or useful to you. I enjoy doing them, I appreciate feedback (both positive and constructive criticism), and I like seeing what people do with these in their own solutions. If this was useful or interesting to you, please take a moment to rate the article. If you have questions or suggestions, feel free to post them below.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Wyvern Software
United States United States
Tony Selke is an independant consultant who has spent the last 20 years working with Microsoft technologies (VB, VC++, ASP, J++, C#, VB.NET, SQL Server, etc.) to develop solutions used in all kinds of market verticals (industrial, pharmaceutical, financial, marketing, multimedia, educational, telecommunications, etc.). He obtained his first MCSD certification in 1998 and his second in 2004, with an MCDBA in 2005. In addition, he has taught courses for MCSD certification students as well as programming classes at Penn State University.

Comments and Discussions

 
GeneralMissingManifestResourceException when I try to use it ... Pin
it-bergmann21-Oct-08 8:31
it-bergmann21-Oct-08 8:31 
GeneralRe: MissingManifestResourceException when I try to use it ... Pin
Tony Selke21-Oct-08 8:39
Tony Selke21-Oct-08 8:39 
GeneralRe: MissingManifestResourceException when I try to use it ... [modified] Pin
it-bergmann21-Oct-08 10:35
it-bergmann21-Oct-08 10:35 
RantRe: MissingManifestResourceException when I try to use it ... Pin
Tony Selke23-Oct-08 2:08
Tony Selke23-Oct-08 2:08 
GeneralRe: MissingManifestResourceException when I try to use it ... Pin
Francisco Del Valle Hernández9-Mar-09 3:06
Francisco Del Valle Hernández9-Mar-09 3:06 
GeneralRe: MissingManifestResourceException when I try to use it ... Pin
CarlG24-Jun-09 4:39
CarlG24-Jun-09 4:39 
QuestionMulti-form application? Pin
Brenden Kehren13-Oct-08 7:44
Brenden Kehren13-Oct-08 7:44 
AnswerRe: Multi-form application? Pin
Tony Selke13-Oct-08 7:51
Tony Selke13-Oct-08 7:51 
You can have as many forms in your project as you want respond to the localization changed event by having those forms derive from CompactFramework.Utilities.Localization.LocalizedForm. All of the LocalizedForm classes will use the same ResourceManager instance, because it is a Singleton.
GeneralRe: Multi-form application? Pin
Brenden Kehren13-Oct-08 7:54
Brenden Kehren13-Oct-08 7:54 
AnswerRe: Multi-form application? Pin
Tony Selke13-Oct-08 8:11
Tony Selke13-Oct-08 8:11 
GeneralRe: Multi-form application? Pin
Brenden Kehren13-Oct-08 8:47
Brenden Kehren13-Oct-08 8:47 
AnswerRe: Multi-form application? Pin
Tony Selke13-Oct-08 9:55
Tony Selke13-Oct-08 9:55 
GeneralRe: Multi-form application? Pin
Brenden Kehren14-Oct-08 4:42
Brenden Kehren14-Oct-08 4:42 
GeneralRe: Multi-form application? Pin
Tony Selke14-Oct-08 4:48
Tony Selke14-Oct-08 4:48 
GeneralRe: Multi-form application? Pin
Brenden Kehren14-Oct-08 4:59
Brenden Kehren14-Oct-08 4:59 
AnswerRe: Multi-form application? Pin
Tony Selke14-Oct-08 5:09
Tony Selke14-Oct-08 5:09 
GeneralRe: Multi-form application? Pin
Brenden Kehren14-Oct-08 5:16
Brenden Kehren14-Oct-08 5:16 
GeneralRe: Multi-form application? Pin
Tony Selke14-Oct-08 5:25
Tony Selke14-Oct-08 5:25 
GeneralRe: Multi-form application? Pin
Tony Selke14-Oct-08 5:44
Tony Selke14-Oct-08 5:44 
GeneralRe: Multi-form application? Pin
Brenden Kehren14-Oct-08 5:48
Brenden Kehren14-Oct-08 5:48 
GeneralRe: Multi-form application? Pin
Brenden Kehren14-Oct-08 6:23
Brenden Kehren14-Oct-08 6:23 
AnswerRe: Multi-form application? Pin
Tony Selke14-Oct-08 7:58
Tony Selke14-Oct-08 7:58 
GeneralRe: Multi-form application? Pin
Brenden Kehren14-Oct-08 8:30
Brenden Kehren14-Oct-08 8:30 
GeneralRe: Multi-form application? Pin
Tony Selke14-Oct-08 8:53
Tony Selke14-Oct-08 8:53 
GeneralRe: Multi-form application? Pin
Brenden Kehren14-Oct-08 11:21
Brenden Kehren14-Oct-08 11:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.