0% found this document useful (0 votes)
17 views

String Resources

The document discusses strategies for handling localized strings in .NET applications. It introduces the ResStrings library which provides a lightweight solution using a StringsResourceManager class to access localized strings from external files in a type-safe way. The library also supports localization of enumerations by generating EnumItem objects containing the textual description for each value.

Uploaded by

Jani Giannoudis
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

String Resources

The document discusses strategies for handling localized strings in .NET applications. It introduces the ResStrings library which provides a lightweight solution using a StringsResourceManager class to access localized strings from external files in a type-safe way. The library also supports localization of enumerations by generating EnumItem objects containing the textual description for each value.

Uploaded by

Jani Giannoudis
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

.

NET String Resources


Concepts and patterns for the handling of strings in multilingual applications
20/09/2011- Version 1.1.0.0

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

Page 1 of 8 Version: 1.1.0.0


The ResStrings library discussed in the following chapters presents a pragmatic and lightweight solution
for the handling of string resources.

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:

Page 2 of 8 Version: 1.1.0.0


The usage of the strings in the code is simple and transparent:
Console.WriteLine( MyStrings.ApplicationInfo );
Console.WriteLine( MyStrings.CurrentCultureDescription( Thread.CurrentThread.CurrentUICulture ) );

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;

private static readonly StringsResourceManager srm = new StringsResourceManager( typeof( MyStrings ) );

} // 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 )

Page 3 of 8 Version: 1.1.0.0


{
Status = StatusItems[ status ];
} // StatusDemo

// ----------------------------------------------------------------------
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

Enumeration resources with images


For WPF, Silverlight and Windows Phone enumerations can be extended with images. The class
EnumImageItem additionally contains an image which is loaded from an embedded resource using the
following naming convention:
EnumNamespace\{ImagesPath}\EnumType.EnumValue.{ImageExtension}

The values for ImagesPath (Default=Images) and ImageExtension (Default=.png) can be


customized in the StringsResourceManager.
Our example contains the following embedded images:

Analogous to EnumItem/EnumItemCollection, all EnumImageItems can be accessed in an


EnumImageItemCollection. The method GetEnumImageItems offered by
StringsResourceManager generates such a collection.

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",

Page 4 of 8 Version: 1.1.0.0


typeof( EnumImageItem<Status> ),
typeof( MyViewModel ),
null );

// ----------------------------------------------------------------------
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>

Silverlight and Windows Phone


Silverlight and Windows Phone do not offer the possibility to access static objects from within XAML
(no x:Static). As a workaround, static resources can be used from a ResourceDictionary. The
StringsResourceDictionary is a specialized ResourceDictionary, which automatically loads
the string resources and provides them for use in XAML elements. The following files are required for
this:
• MyDictionary.cs – derivation of StringsResourceDictionary
o MyDictionary.resx – strings in the default language
o MyDictionary.local.resx – localized strings (optional)
The declaration of the string dictionary looks as follows:
// ------------------------------------------------------------------------
public class MyDictionary : StringsResourceDictionary
{
} // class MyDictionary

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>

Page 5 of 8 Version: 1.1.0.0


To use several StringsResourceDictionaries together in one XAML, they can be provided with
a context:
// ------------------------------------------------------------------------
public class MyAppDictionary : StringsResourceDictionary
{

// ----------------------------------------------------------------------
public MyAppDictionary() :
base( "AppStrings" )
{
} // MyAppDictionary

} // class MyAppDictionary

Using a MergedDictionary, several StringsResourceDictionaries can be declared as


resources of the XAML element. By prepending the dictionary context, it is possible to reference a
resource from a specific resource dictionary:
<Page ...>

<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}}" />

To reduce the management overhead of a strings class, it is possible to use a


StringsResourceDictionary analogous to Silverlight/Windows Phone. But this also sacrifices
control over invalid string references at design time.

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 binding expression supports the following syntax:


<%$ Strings:{TypeName}, {StringName} %>

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:

The declaration of the StringExpressionBuilder is found in the configuration of the web


application web.config:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<expressionBuilders>
<add expressionPrefix="Strings"
type="Itenso.Community.StringResources.ResStrings.StringsExpressionBuilder,
Itenso.Community.StringResources.ResStrings"/>
</expressionBuilders>
</compilation>
</system.web>

Page 7 of 8 Version: 1.1.0.0


</configuration>

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

Page 8 of 8 Version: 1.1.0.0

You might also like