AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=957&pId=-1
Implementing Multilingual Applications in Microsoft .NET
page
by Joydip Kanjilal
Feedback
Average Rating: 
Views (Total / Last 10 Days): 53442/ 63

Introduction

The Microsoft .NET Framework was designed keeping in mind the international markets and the necessity of globalization or internationalization of the software applications designed on top of the .NET Framework.  The .NET Framework provides a powerful support for localization through the System.Globalization, System.Resources and System.Threading namespaces.  This article discusses the concepts of Globalization and Localization and how we can implement a multilingual application in .NET.

What is Localization and Globalization?

Localization is the process of adapting a software application for a specific locale.  It is defined as the process of creating and configuring an application for supporting a specific language or locale.  Globalization is defined as the process of identifying the specific portion of the application that needs to be different for different languages and how to isolate them from the application's core. Therefore, it is the process of identifying the localizable resources of the application.

The Microsoft .NET library provides support for globalization and localization using the following namespaces.

·         System.Globalization

·         System.Resources

·         System.Text

·         System.Threading

The System.Globalization namespace provides support for developing multilingual applications in Microsoft .NET by allowing the developers to define culture specific information.  The sections that follow discuss cultures and how to work with them in .NET.  The System.Resources namespace provides support to create, store and manage various culture-specific resources used in an application.  It contains a class called ResourceManager that allows access to resources either from the main assembly or those that are present in Satellite Assemblies.  We will discuss both ResourceManager and Satellite Assemblies in more detail later in this article.  The System.Text namespace provides support for representing various character encodings like ASCII, Unicode, UTF-7 and UTF-8.  The System.Threading namespace contains classes and interfaces that provide support for multithreaded programming.

Culture

The term Culture denotes a combination of a geographical location and the language spoken in it. A Culture can be represented in any of the ways shown below.

·         en-US

·         en-GB

The former refers to English language that is spoken in the US while the latter implies that which is spoken in Great Britain.

Working with Culture Information

Microsoft .NET provides support for working with culture specific information using the CultureInfo class in the System.Globalization namespace.  Culture information can be set both at the page level as well as at the application level.

To set the Culture information at the page levels use the following in the Page directive of the ASP.NET page.

Listing 1

<%@ Page language="C#" Culture="fr-FR"%>

This statement in listing 1 would ensure that the culture information is applicable only for this particular page in the application.

To set the Culture information at the application level, use the following in the Globalization section of the web.config file.

Listing 2

<configuration>
  <system.web>
    <globalization
       culture="en-GB"
    />
  </system.web>
</configuration>

This specification as shown in listing 2 in the web.config file would ensure that the culture information is applicable throughout the application.

Resource Files

A resource file consists of non-executable data that is required by the application and is deployed along with it.  Bitmaps, icons, cursors, etc. are typical examples of resource files.  Microsoft .NET provides support for multilingual applications using resource files.  The resource files used to create a multilingual application contain the culture dependent resources for the application.  A resource file can be used to specify the locale-specific settings.  Note that to support each locale in the application, there should be one resource file created.  These resource files are then compiled into satellite assemblies and accessed by the application.  Resource files can be either text files or resx files in .NET.

The basic advantages of using resource files are given below.

·         Support for Globalization with isolation of the resource content from the application

·         Reusability and the provision for change of the resource content without the need to change the application's code

It should be noted that each resource file has support for a specific culture.  Hence, if we need to have support for "n" cultures, we need to have "n" different resource files.

Creating Resource Files

First create a resource file using the VS.NET IDE and save using either a .txt or a .resx extension.  The resource file should be created using the intended culture if it is to be used for Globalization or Localization purposes.

When creating resource files for specific locales, the following naming convention should be followed.

<base file name>.<locale>.txt

or

<base file name>.<locale>.resx

Therefore the resource file targetted at en-GB locale should be named as TestResource.en-GB.txt or TestResource.en-GB.resx.  Note that the resource file name TestResource.en-GB.resx contains the name of the resource that it is intended at.

The ResourceWriter class in the System.Resources namespace is used to create a resource programmatically.  The sample code below creates a resource file called Test.Resources in the root directory of the C drive.

Listing 3

using System;
using System.Resources;
class CreateResources
{
  public static void Main(string[]args)
  {
    ResourceWriter rw = new ResourceWriter("C:\\Test.resources");
    rw.AddResource("CopyRight", "CopyRight Message in English");
    rw.Close();
  }
}

The ResourceWriter class can also be used to store any other serializable object in the resource file.

Reading Resource Files

The content of the resource files can be read in the application using the ResourceManager class defined in the System.Resources namespace.  The ResourceManager class looks up culture-specific resources and provides convenient access to culture-specific resources at runtime.  According to MSDN, "The Resource Manager class looks up culture-specific resources, provides resource fallback when a localized resource does not exist, and supports resource serialization."

Listing 4

ResourceManager resourceManager = new
 ResourceManager("Internationalization.en-GB"+culture, Assembly.GetExecutingAssembly());
CultureInfo cultureInfo = new CultureInfo(culture);
string message = resourceManager.GetString("ID",cultureInfo);

Compiling Resource Files

Refer to the section above.  Note that we had created a resource file named TestResource.en-GB.resx.  Now let us compile the resource using the ResGen utility shipped with the Microsoft .NET Framework to create a compiled resource that would have a .resources extension.

Listing 5

resgen Internationalization.en-GB.resx  Internationalization.en-GB.resources

When used, the above command line tool would compile the .resx file to a compiled binary .resources file for the en-GB locale.

Working with Embedded Resource Files

An embedded resource is one that is embedded inside the application's code.  Thus, when the application is compiled, this resource gets stored in the assembly that is generated after the compilation of the application's code.  Let us create a text resource file called TextFile.txt and make the same an embedded resource by selecting the properties of the same file and then setting the Build Action in the item properties to "Embedded Resource."  This means the resource will be embedded directly into the current assembly along with the code.  Further, let the resource file that has just been created contain a text message.

The following code snippet shows how we can retrieve the content of the resource as a string from the current executing assembly.

Listing 6

public string GetResourceFromAssembly(string resourceName) 
{
  Assembly assembly = Assembly.GetExecutingAssembly();
  TextReader txtReader = new
  StreamReader(assembly.GetManifestResourceStream(resourceName));
  string str = txtReader.ReadToEnd();
  txtReader.Close();
  return str;
}

The above method accepts the fully qualified path to the resource as a parameter and returns the resource as a string from the current executing assembly.  Invoke the above method as shown below.

Listing 7

Response.Write(GetResourceFromAssembly("Test.TextFile.txt"));

The GetResourceFromAssembly method would return the resource value from the specified resource file.

It is also possible to list all the embedded resources in the assembly as shown in the section below.  The following method shows how we can display the names of all the embedded resources in the current executing assembly.

Listing 8

public string GetResourceNamesFromAssembly()
{
   Assembly assembly = Assembly.GetExecutingAssembly();
   string [] resourceNames = assembly.GetManifestResourceNames(); 
   StringBuilder stringBuilder = new StringBuilder();
   foreach(string str in resourceNames)
   {
    stringBuilder.Append(str);
    stringBuilder.Append("<BR>");
   }
  return stringBuilder.ToString();
}

The above method would return all the resource names from the current executing assembly. Invoke the above method as shown in the listing below.

Listing 9

Response.Write(GetResourceNamesFromAssembly());
Satellite Assemblies

An assembly is essentially a portable executable or library file containing partially compiled code for use in deployment, security and versioning in Microsoft .NET's managed environment.  The assembly is compiled into the machine language instructions by the CLR.

Satellite Assemblies are special assemblies that only contain resources and are associated with the main assembly.  Satellite assemblies are used to store compiled localized application resources.  They contain only resource data and no other code.  Satellite assemblies are used to load the data dynamically depending upon the culture of the application.  They can be created using the AL utility tool provided with Microsoft .NET SDK.  With satellite assemblies, resources are embedded in a binary format within a DLL.  This makes the resources not very visible to the user and ensures faster access.  These assemblies can be deployed even after deployment of the application.

Refer to the earlier sections where we had already created a resource file that was intended for UK English culture.  We had then compiled the same to create a compiled resource file using the resgen utility.  Now we can use the AL utility shipped with the Microsoft .NET SDK to create a satellite assembly from a compiled resource file as shown below.

Listing 10

al /t:lib /culture:en-GB /embed: Internationalization.en-GB.resources
 /out: Internationalization.resources.dll

The output file Internationalization.en-GB.resources is a satellite assembly file that is created for the en-GB locale from the compiled resource file.  The .NET Framework Developer's Guide, MSDN, states, "Ideally, you should package the resources for the default or neutral assembly with the main assembly and create a separate satellite assembly for each language that your application supports."

Implementing Multilingual Applications

A Multilingual application is one that provides support for multiple languages.  This section discusses how we can implement a multilingual application in .NET using the concepts explained earlier.  The steps for implementing a multilingual application in .NET can be summarized as the following.

·         Create a resource file for each locale.

·         Save the resource files with a .resx extension.

·         Compile the resource files using resgen utility of .NET SDK to create a compiled binary resource file.

·         Create satellite assembly using al utility of .NET SDK.

·         Create folders for storing the satellite assembly and store the satellite assembly there.

·         Read resources from the satellite assembly in the application's source code.

First, we have to create culture specific resources in resource files.  Then we can store the culture specific data in the resource file and save the same with a .resx extension.  Note that the culture name should be provided in the resource file name to follow the resource file naming convention.  We can use Visual Studio .NET to create a resource for a particular culture.  Resource files have been explained in more detail earlier.  Let us assume that a file Internationalization.en-GB.resx be created for en-GB culture and compiled (as shown in listing 4) to create the Internationalization.en-GB.resources file.  This file is the complied resources file.  This compiled resource file can be used to create a satellite assembly.  This satellite assembly can then be used by the application.  Refer to code listing 9.  The file Internationalization.resources.dll is a satellite assembly.  This satellite assembly should now be placed in a sub folder inside the application's main folder and the name of this sub folder should be the same as the name of the culture that the satellite assembly is targeted for.  This satellite assembly can now be used to display locale specific information in the application.

The CultureInfo class

The CultureInfo class of the .NET Framework SDK provides access to the properties of a locale.  An instance of the CultureInfo class can be created by passing the culture name as a string parameter.

The following code can be used to create a CultureInfo instance for French spoken in France.

Listing 11

CultureInfo c = new CultureInfo("en-FR");

The following code can be used to create a CultureInfo instance for UK English locale.

Listing 12

CultureInfo c = new CultureInfo("en-GB");
Configuring Localization in our Application

In order to ensure that we do not require changing the application source code each time we require to have support for a newer culture in the application, we can ensure even loose coupling by setting the culture name in the web.config file.  This ensures that the application's culture settings are configurable.  This information can be read by the application at run time and the appropriate culture settings set accordingly.

The <appSettings> element of the web.config file can be used to specify the culture name as shown below.

Listing 13

<appSettings>
  <add key = "Culture" value = "fr-FR">
  </add>
</appSettings>
 
Or

Listing 14

<appSettings>
  <add key = "Culture" value = "en-GB">
  </add>
</appSettings>

Note that fr-FR refers to French language that is spoken in France while en-GB refers to English language that is spoken in Great Britain.

The culture type that is specified in the web.config file can be read by using System.ConfigurationSettings.AppSettings in the source code.  Note that System.Configuration.ConfigurationSettings.AppSettings is a class in the System.Configuration namespace in the system.dll assembly.  The source code is provided below.

Listing 15

string culture =
 System.Configuration.ConfigurationSettings.AppSettings["Culture"].ToString();
ResourceManager resourceManager = new
 ResourceManager(typeof(TestForm).Namespace.ToString()+"."+culture,
 Assembly.GetExecutingAssembly());
CultureInfo cultureInfo = new CultureInfo(culture);
string message = resourceManager.GetString("ID",cultureInfo);
Response.Write(message);

In the code listing shown above, an instance of the ResourceManager class is created by passing the resource and the assembly in which the resource is embedded as parameters.  Here the culture and a reference of the current executing assembly are passed to it as parameters.  Then an object of the CultureInfo class is created and the culture name passed to the parameterized constructor of the class.  The ResourceManager class enables access to the resources for a particular culture using the GetObject and GetString methods.  Now we have to call the GetString method on the ResourceManager instance and pass the ID string as key and the instance of the CultureInfo class as parameters.  The resource value is returned as string and the same can now be used as needed in the application.  For the sake of simplicity, I have displayed the message using Response.Write method.  This concept can be used to set the text of a particular control in a specific language by reading the locale specific text from the resource.  The current locale is specified in the web.config file.

As an example, to set the copyright on a label control in the web from use the code provided below.

Listing 16

lblCopyright.Text = resourceManager.GetString("Copyright",culture);

Here the copyright message would be displayed in the label control based on the current culture that is set using the web.config file as explained earlier.

Note that either the satellite assembly or the application's assembly should have the resources for all the cultures to be supported by the application.

References
Conclusion

Localization enables the building of software applications that can respond to an increasingly global economy.  This implies designing an application to work in multiple locales.  If the infrastructure is in place, tuning the application to support a new locale is hardly a matter of time and effort.  This article has discussed the related concepts and the techniques involved for developing multilingual applications.  I hope that the readers will find the concepts presented in this article useful.  I would appreciate readers' comments and suggestions.  Happy reading!



©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-28 7:09:31 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search