Introduction
Visual Studio's designer offers a nice tool to localize your dialogs. Simply set the Form's language to whatever you want, and start editing the labels, menus, etc.
However when it comes to localizing strings that are not present on your form (only in code, such as message box texts), there is no support for that. If you manually save these strings in the Form's resx, VS will warn you that you shouldn't be modifying it. So you have to store these localized strings somewhere else (in general in a resx file that is global to the project) which is a poor design since they are related to the form. Also a single resx is hard to maintain when many people are working on a project.
The tool presented in this article addresses two problems at once.
- Save the localized strings within the form's resx.
- Have designer support, for easy translation.
Background
The idea is to take advantage of the localization mode present in VS. How would you do it for a single string? Simply put a hidden label on your form (problem 1 solved), and then read its Text property from your code when you need it. Every localized control on a form have their string stored in the form's resx (problem 2 solved).
Now they are some drawbacks: what if you have 30 strings in your code? It would be cumbersome to put 30 labels on your form. And why would you need to position and size your string containers?
Let's simply use a Control that can hold many localized strings. For example a TabControl, can contain several TabPages, each having a localized tab text. Or a ListView can contain several Columns, each having a localized header.
Cool, now what about the position and the size? We don't need it. So we will make our control not beign a Control, but a Component instead (such as Timer). They have no graphical representation, so no need to position and size them.
We also want that the strings editor pops up when double-clicking the component, so we'll add some designer support code.
Using the code
First, we define a LocalizableString
class that extends Component
, so we get some designer and localization support. This will be the individual strings. The very important thing here is the Localizable
attribute set to true.
[DesignTimeVisible(false)]
public class LocalizableString : Component
{
private string text;
[Localizable(true)]
public string Text
{
get { return text; }
set { this.text = value; }
}
public override string ToString()
{
return text;
}
}
And then we create our main component LocalizableStringsControl
, the one we will be putting on our form. It holds a collection of LocalizableString
s. The code presented here would be sufficient if we would not want to be able to double-click the component to start editing.
[
Localizable(true),
DefaultProperty("Strings"),
Designer(typeof(LocalizableStringsDesigner))
]
public partial class LocalizableStringsControl : Component
{
List<LocalizableString> strings = new List<LocalizableString>();
[
Category("Data"),
Description("Strings"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Editor(typeof(CollectionEditor), typeof(UITypeEditor)),
Browsable(true),
Localizable(true)
]
public List<LocalizableString> Strings
{
get { return strings; }
}
public LocalizableStringsControl()
{
InitializeComponent();
}
... (designer support code)
}
History
Version 1.0