String Resources
String Resources
Introduction
Internet and globalization have led to the same software being used in different languages, the availability
of localized versions. Even if an application is initially only targeting a single language, it is advisable to
keep the language dependent elements separate from the actual code, right from the start. Doing so after
finishing with the programming is a daunting, time intensive and error prone task.
The .NET framework offers the ResourceManager as a basis for dealing with externalized strings and
their translations. This article extends these capabilities of standard .NET string handling by the following
functionality:
o Controlled access to strings
o Type safe formatting of variable string elements
o Strings for enumerations (optionally with image)
o XAML strings
o User defined string resource files in ASP.NET
An important goal which leads to the presented solution was the uniform usage of the tools in the .NET
run time and development environments for:
o Library/DLL
o Console application
o Windows Forms
o ASP.NET
o WPF
o Silverlight
o Windows Phone 7
String resources
The handling of string resources happens through the StringsResourceManager, which extends its
base class ResourceManager with several methods. In addition to GetString the
StringsResourceManager offers the method Format, which interprets the content of the resource
as a composite format string and applies it to the method String.Format.
The following indicators mark erroneous string resources:
• UnknownResFormat: unknown resource – Default=?name?
• MissingResFormat: missing resource content – Default=*name*
• InvalidResFormat: invalid resource content e.g. for Format – Default=!name!
The usage of these indicators can be turned off with the property UseStringIndicators. The
StringsResourceManager is used in a class which is associated with several resource files:
• MyStrings.cs – declaration of the strings (contains the StringsResourceManager)
o MyStrings.resx – strings in the default language
o MyStrings.local.resx – localized strings (optional)
The following example shows the class MyStrings.cs offering some strings:
// ------------------------------------------------------------------------
internal static class MyStrings
{
// ----------------------------------------------------------------------
public static string ApplicationInfo
{
get { return srm.Format( "ApplicationInfo", VersionTool.VersionOf( typeof( MyStrings ) ) ); }
} // ApplicationInfo
// ----------------------------------------------------------------------
public static string CurrentCultureDescription( CultureInfo culture )
{
return srm.Format( "CurrentCultureDescription", culture.DisplayName );
} // CurrentCultureDescription
// ----------------------------------------------------------------------
// members
private static readonly StringsResourceManager srm = new StringsResourceManager( typeof( MyStrings ) );
} // class MyStrings
The class is being declared statically so UI-Designers can access the provided strings at development
time. With the exception of pure resource libraries it is advisable to only use this class from within the
Assembly, hence it is declared internal. The recycling of strings from other libraries can lead to a
dependency nightmare.
Each string is represented as a property or a method and thus ensures that no invalid string references
exist at compile time. The method parameters further ensure the correct number and type of arguments for
the required formatting parameters.
The next task is the creation of the resource file MyStrings.resx with texts in the default language:
For each additional language another resource file is created, as the following example for the German
language MyStrings.de.resx illustrates:
Enumeration resources
For the localization of enumerations the library generates an EnumItem via reflection for each of its
values. In addition to the enumeration value each of these EnumItems contains a textual description and
has the following special behavior:
• ToString displays the textual description
• Equals only compares the enumeration value and ignores the textual description
All values of an enumeration can be accessed in an EnumItemCollection. By implementing
IEnumerable it can be used for collection bindings. The StringsResourceManager has special
support for enumerations through its method GetEnumItems which creates a new instance of an
EnumItemCollection.
Let’s assume the following enumeration:
// ------------------------------------------------------------------------
public enum Status
{
Ok,
Info,
Warning,
Error,
} // enum Status
The integration of this enumeration into the strings class looks as follows:
// ------------------------------------------------------------------------
internal static class MyStrings
{
// ----------------------------------------------------------------------
public static EnumItemCollection<Status> StatusItems
{
get { return statusItems ?? ( statusItems = srm.GetEnumItems<Status>() ); }
} // StatusItems
// ----------------------------------------------------------------------
// members
private static EnumItemCollection<Status> statusItems;
} // class MyStrings
The StringsResourceManager loads a string from the resource file for each of the enumeration's
values, named according to the pattern EnumType.EnumValue:
In case the resource file doesn't contain a text for an enumeration value, its value is used. The following
example illustrates the usage of the Status enumeration:
// ------------------------------------------------------------------------
public class StatusDemo
{
// ----------------------------------------------------------------------
public StatusDemo( Status status = Status.Ok )
// ----------------------------------------------------------------------
public IEnumerable StatusItems
{
get { return MyStrings.StatusItems; }
} // StatusItems
// ----------------------------------------------------------------------
public EnumItem<Status> Status { get; set; }
} // class StatusDemo
For public access to enumerations of a library it is advisable to declare a utility class which makes the
EnumItemCollection available as a property:
// ------------------------------------------------------------------------
public static class StatusHelper
{
// ----------------------------------------------------------------------
public static EnumItemCollection<Status> StatusItems
{
get { return MyStrings.StatusItems; }
} // StatusItems
} // class StatusHelper
MVVM Enumerations
To use the strings of enumerations in an MVVM application, it is necessary to integrate the EnumItem
respectively the EnumImageItem into the view model:
// ------------------------------------------------------------------------
public class MyViewModel : DependencyObject
{
// ----------------------------------------------------------------------
public static readonly DependencyProperty StatusProperty = DependencyProperty.Register(
"Status",
// ----------------------------------------------------------------------
public IEnumerable StatusItems
{
get { return StatusHelper.StatusImageItems; }
} // StatusItems
// ----------------------------------------------------------------------
public EnumImageItem<Status> Status
{
get { return (EnumImageItem<Status>)GetValue( StatusProperty ); }
set { SetValue( StatusProperty, value ); }
} // Status
} // class MyViewModel
In the XAML view the textual description of an enumeration value can be displayed using a binding to
the property Description. Images from EnumImageItem enumeration values can be used by binding
to the property Image:
<ListBox
ItemsSource="{Binding StatusItems}"
SelectedItem="{Binding Status, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel
Orientation="Horizontal">
<Image
Source="{Binding Image.Source}" />
<TextBlock
Text="{Binding Description}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Because the strings are directly accessed from the corresponding resource file (.resx), no properties or
methods are necessary.
To use the StringsResourceDictionary in XAML, it must be declared as a resource of the main
element. Accessing the strings happens via StaticResource:
<Page ...>
<Page.Resources>
<app:MyDictionary />
</Page.Resources>
<Grid>
<StackPanel
Orientation="Horizontal"
<TextBlock
Text="{StaticResource MediaDurationLabel}" />
<TextBlock
Text="{Binding MediaDuration, StringFormat={StaticResource DurationFormatString}}" />
</StackPanel>
</Grid>
</Page>
// ----------------------------------------------------------------------
public MyAppDictionary() :
base( "AppStrings" )
{
} // MyAppDictionary
} // class MyAppDictionary
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<app:MyDictionary />
<app:MyAppDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
<Grid>
<StackPanel
Orientation="Horizontal"
<TextBlock
Text="{StaticResource AppStrings.ApplicationInfoLabel}" />
<TextBlock
Text="{StaticResource AppStrings.ApplicationInfo}" />
</StackPanel>
</Grid>
</Page>
WPF
When localizing WPF, string resources can be integrated as static values:
<TextBlock
Text="{x:Static app:MyStrings.MediaDurationLabel}" />
<TextBlock
Text="{Binding MediaDuration, StringFormat={x:Static app:MyStrings.DurationFormatString}}" />
Composite WPF
In certain scenarios it is desirable to share string resources between WPF and Silverlight/Windows Phone.
If no type safety is required for WPF, it is possible to use the StringsResourceDictionary for all
systems.
If WPF strings are handled via StringsResourceManager, they can be transferred to the
Silverlight/Windows Phone StringsResourceDictionary with the following pattern:
// ------------------------------------------------------------------------
public class MyDictionary : StringsResourceDictionary
{
// ----------------------------------------------------------------------
public class MyDictionary :
base( typeof( MyStrings )
{
} // MyDictionary
} // class MyDictionary
ASP.NET
ASP.NET offers the possibility to use string resources through App_GlobalResources and
App_LocalResources. But these mechanisms lack support for the following functionality:
Page 6 of 8 Version: 1.1.0.0
• dynamically composed strings
• strings for enumerations
• strings from libraries
Using the StringExpressionBuilder, it is possible to use strings from the
StringsResourceManager in a web control via expression binding:
<asp:Label ID="AppTextLabel" runat="server" Text="<%$ Strings:MyCompany.MyApp.MyStrings, AppText %>" />
<asp:Label ID="LibTextLabel" runat="server" Text="<%$ Strings:MyCompany.MyLib.MyStrings, LibText %>" />
The type referenced by TypeName has to be declared public and can be one of the following:
• Static class with strings: StringName represents a public and static method of that class
• Derivation of StringsResourceManager: StringName represents the name of the resource
In case of a source which derives from StringsResourceManager, the following files are required:
MyStrings.cs – derivation of StringsResourceManager
MyStrings.resx – strings in the default language
MyStrings.local.resx – localized strings (optional)
Because access to the string resources happens directly, no declaration of properties is required and the
following syntax is sufficient:
// ------------------------------------------------------------------------
public class MyStrings : StringsResourceManager
{
} // class MyStrings
Based on the StringExpressionEditor, the strings are even available in design mode. The binding
is calculated live, which immediately reveals an invalid binding:
Windows Forms
The concepts presented so far can be used without restrictions in a Windows Forms application. The
management of Windows Forms string resources preferably happens through its integrated tools which
also support the proper display in design mode.
Library
The ResStrings library is available in the following versions:
Project Content CLR
ResStrings StringsResourceManager 2.0
EnumItem
ResStrings.Web StringsResourceManager 2.0 Web
StringExpressionBuilder
EnumItem
ResStrings.Desktop StringsResourceManager 4.0 WPF
StringsResourceDictionary
EnumItem
EnumImageItem
ResStrings.Silverlight StringsResourceManager SL 4
StringsResourceDictionary
EnumItem
EnumImageItem
ResStrings.WindowsPhone StringsResourceManager SL 4 WP
StringsResourceDictionary
EnumItem
EnumImageItem
Each version is accompanied by a sample application. Usage of the ResStrings CLR 2.0 library is
demonstrated in a Windows Forms project.
Further information about developing libraries for different platforms can be found in the article Time
Period Library for .NET in the chapter Composite Library Development.
The basics concerning localization offered by Microsoft can be found here:
• Localizing Applications
• Silverlight
• Windows Phone
• WPF
• ASP.NET
• Windows Forms