Click here to Skip to main content
Click here to Skip to main content

User Interface Localization with the Compact Framework

, 24 Oct 2006
Rate this:
Please Sign up or sign in to vote.
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:

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:

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)

About the Author

Tony Selke
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

 
QuestionHow to do apply to User Controls? Pinmemberbagu4it14-Jun-13 2:26 
QuestionChinese/Slovakian Language Support in Windows CE Pinmembershellycooper6-Jun-12 1:04 
GeneralUsing this lib for translating libs PinmemberCarlG15-Mar-10 4:19 
AnswerRe: Using this lib for translating libs PinmemberTony Selke16-Mar-10 5:24 
GeneralRe: Using this lib for translating libs PinmemberCarlG16-Mar-10 9:25 
GeneralMissingManifestException - but I found a workaround PinmemberBernhard11-Mar-10 22:52 
GeneralRe: MissingManifestException - but I found a workaround PinmemberTony Selke12-Mar-10 2:34 
GeneralSet the DefaultUICulture - via reflection Pinmembertfpds29-Oct-09 8:27 
GeneralRe: Set the DefaultUICulture - via reflection PinmemberTony Selke10-Dec-10 2:33 
GeneralRe: Set the DefaultUICulture - via reflection Pinmemberkrish_bhavya6-Jan-11 18:13 
QuestionUsing several ressouces files Pinmemberaurelien70813-May-09 23:24 
GeneralUse Control.Name instead of Control.ToString() PinmemberMember 45927302-Mar-09 6:56 
GeneralRe: Use Control.Name instead of Control.ToString() PinmemberTony Selke2-Mar-09 7:00 
GeneralBest Localization Plug-in for Visual Studio. PinmemberAlexander Nesterenko17-Dec-08 21:35 
QuestionWhat about VB? PinmemberGustavo Regal15-Dec-08 7:54 
QuestionWhy does this not work on the desktop (full framework)? PinmemberVooDooMatrix12-Nov-08 4:32 
AnswerRe: Why does this not work on the desktop (full framework)? PinmemberTony Selke12-Nov-08 4:55 
GeneralRe: Why does this not work on the desktop (full framework)? PinmemberVooDooMatrix12-Nov-08 5:03 
GeneralRe: Why does this not work on the desktop (full framework)? PinmemberVooDooMatrix13-Nov-08 2:37 
GeneralRe: Why does this not work on the desktop (full framework)? PinmemberTony Selke13-Nov-08 2:43 
GeneralRe: Why does this not work on the desktop (full framework)? PinmemberVooDooMatrix13-Nov-08 13:46 
GeneralMissingManifestResourceException when I try to use it ... Pinmemberit-bergmann21-Oct-08 8:31 
GeneralRe: MissingManifestResourceException when I try to use it ... PinmemberTony Selke21-Oct-08 8:39 
GeneralRe: MissingManifestResourceException when I try to use it ... [modified] Pinmemberit-bergmann21-Oct-08 10:35 
RantRe: MissingManifestResourceException when I try to use it ... PinmemberTony Selke23-Oct-08 2:08 
GeneralRe: MissingManifestResourceException when I try to use it ... PinmemberFrancisco Del Valle Hernández9-Mar-09 3:06 
GeneralRe: MissingManifestResourceException when I try to use it ... PinmemberCarlG24-Jun-09 4:39 
QuestionMulti-form application? PinmemberBrenden Kehren13-Oct-08 7:44 
AnswerRe: Multi-form application? PinmemberTony Selke13-Oct-08 7:51 
GeneralRe: Multi-form application? PinmemberBrenden Kehren13-Oct-08 7:54 
AnswerRe: Multi-form application? PinmemberTony Selke13-Oct-08 8:11 
GeneralRe: Multi-form application? PinmemberBrenden Kehren13-Oct-08 8:47 
AnswerRe: Multi-form application? PinmemberTony Selke13-Oct-08 9:55 
GeneralRe: Multi-form application? PinmemberBrenden Kehren14-Oct-08 4:42 
GeneralRe: Multi-form application? PinmemberTony Selke14-Oct-08 4:48 
GeneralRe: Multi-form application? PinmemberBrenden Kehren14-Oct-08 4:59 
AnswerRe: Multi-form application? PinmemberTony Selke14-Oct-08 5:09 
GeneralRe: Multi-form application? PinmemberBrenden Kehren14-Oct-08 5:16 
GeneralRe: Multi-form application? PinmemberTony Selke14-Oct-08 5:25 
GeneralRe: Multi-form application? PinmemberTony Selke14-Oct-08 5:44 
GeneralRe: Multi-form application? PinmemberBrenden Kehren14-Oct-08 5:48 
GeneralRe: Multi-form application? PinmemberBrenden Kehren14-Oct-08 6:23 
AnswerRe: Multi-form application? PinmemberTony Selke14-Oct-08 7:58 
GeneralRe: Multi-form application? PinmemberBrenden Kehren14-Oct-08 8:30 
GeneralRe: Multi-form application? PinmemberTony Selke14-Oct-08 8:53 
GeneralRe: Multi-form application? PinmemberBrenden Kehren14-Oct-08 11:21 
QuestionWhat about Error messages text PinmemberJenny Faifel2-Oct-08 9:22 
AnswerRe: What about Error messages text PinmemberTony Selke2-Oct-08 11:15 
GeneralRe: What about Error messages text PinmemberJenny Faifel2-Oct-08 12:38 
AnswerRe: What about Error messages text PinmemberTony Selke2-Oct-08 14:57 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 24 Oct 2006
Article Copyright 2006 by Tony Selke
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid