Introduction
Localization has become an important feature of many modern applications. In .NET, resource files and the Windows Forms Designer make localization of UI components straightforward, however, there are certain shortcomings. The code included in this article addresses some of the deficiencies, namely localization of string values and message boxes.
Background
Developers hate tedium. If following proper globalization practices is onerous, the developer simply will not adhere to the practice. They will instead embed their strings in the code and (if you're lucky) put a "TODO: Localize" at the top of a file and move on.
Declaring strings (or other resources) in source code is a very bad practice. Hunting down resources in source code is no fun and expressly prohibits software from being localized after it is originally built. Externalizing resources is key to being able to localize applications and is the technique used in this article.
Platform
The included code requires Visual Studio 2008 and targets .NET v2.0.
Usage
The LocalizableContent
is a component that can be dragged and dropped from the Visual Studio Toolbox onto any Component
, e.g. a UserControl
a Form
, or even a custom business object. It contains collections of messages and message boxes whose content is externalized to resource files.
Once an instance has been dropped to the component tray, localizable messages or message boxes can be added by using the context menu.
Newly added content automatically becomes selected in the Properties and Document Outline panes. Once selected, various editable properties can be modified.
Note that LocalizableMessageBox.Text
or LocalizableMessage.Value
can be a format string. If a format string, the arguments are provided when calling LocalizableMessageBox.Show
, otherwise, Show
can be called with no additional parameters (besides the owning handle).
Gotchas
Just like all components, unless the Localizable
property of the class that contains the LocalizableContent
is set to true
, resources will be embedded in the Designer.cs file as opposed to the .resx file!
Originally, the LocalizableMessageBox
and LocalizableMessage
supported a preview feature. This feature is currently unavailable. Adding [DesignTimeVisible(false)]
to the components preclude such functionality. I found that since component trays can become cluttered, it is more desirable to group the content under a single component tray item (hence the creation of LocalizableContent
), so the preview functionality is currently suppressed as you cannot get the context menu that supports it.
Points of Interest
MessageBoxType
was required. System.Windows.Forms.MessageBoxIcon
does not display properly in a property grid (presumably it has duplicate underlying literal values). Adding my own enumeration, while at first undesirable, does have the advantage of reducing the number of options the developer has to choose from. I never liked selecting from MessageBoxIcon
; I find the documentation confusing and don't see the need for more than 3 types, Info
, Warning
, and Error
. This seems better than having to decide if you should use Stop/Error/Hand, or Warning/Exclamation.
The classes in LocalizationUtilities.Design
have some interesting aspects. It has code to make GenerateMember
default to false
(LocalizableContent
exposes no useful programmatic functionality). Additionally, there is code to adhere to a preferred naming convention (prefix fields with a '_').
Commentary
Some may object to a business class being edited like a UI element. In the included code, MyBusinessObject
represents a business object, yet its localizable content can be edited in the designer. Deriving from Component
grants this privilege. I do not take objection to this -- it seems fairly lightweight and provides various opt-out capabilities, for example, applying the ToolboxItem
attribute suppresses display in the Visual Studio Toolbox.
History
- Feb 2010: Initial version