- Table of Contents
- .NET Book Recommendations
- What Is .NET?
- The Microsoft .NET Framework
- The Common Language Runtime (CLR), the Common Type System (CTS), and the Common Language Specification (CLS)
- .NET Framework Class Library
- Visual Studio .NET
- .NET Enterprise Servers and .NET My Services
- .NET Compliant Languages
- C#
- Visual Basic .NET (VB .NET)
- ASP.NET
- XML Web Services
- ADO.NET
- XML.NET
- Windows Forms
- Why .NET?
- Displaying Errors with the Error Provider
- COM Interoperability
- Comparing Java and .NET
- Calling Unmanaged Code
- .NET Application Security
- Code Access Security
- .NET Standards Support
- Numeric Types in the .NET Framework
- Working with Strings
- Formatting Strings
- Trimming Character Strings
- Comparing Strings in .NET 2.0
- Arrays and Collections
- Arrays as Class Members
- Sorting a Multi-Dimensional Array
- Sorting a Multi-Dimensional Array with LINQ
- File I/O (System.IO)
- Working with File Names
- Using the File System
- Working with Files and Directories
- Monitoring the File System
- Working with Streams
- Working with Text Encodings
- Working with Date and Time
- Extending the DateTime Class
- Fun with Dates
- Exceptions
- Delegates
- Events
- Asynchronous Programming
- Asynchronous File I/O
- Timers
- Random Numbers
- Cryptographically Secure Random Numbers
- Serialization
- MultiThreading (System.Threading)
- Multi-Threading Overview
- The Managed Thread Pool
- Managed Threading
- Thread Synchronization
- Synchronizing Data Access
- Trace Debugging
- Tracing in .NET 2.0
- ASP.NET Trace
- Validating User Input in ASP.NET Web Pages
- Event Logging
- Monitoring Application Performance
- Accessing the Registry
- Accessing Environment Information
- Environment Variables in .NET 2.0
- Managing Windows Forms Applications
- Working with Email
- Working with Graphics
- Animating a Background
- Working with Images
- Drawing Cycloid Curves
- Simulating the Spirograph
- Building International Web Applications
- .NET Compact Framework
- Mobile Web Development with ASP.NET
- Speech Technologies
- Microsoft MapPoint Web Service
- Working with Typed DataSets
- Using Relationships in DataSets
- DataColumn Expressions
- Playing Simple Sounds
- Playing Sounds with .NET 2.0
- Returning an Image in a Web Page
- RSS
- Best Practices Project Structure
- Best Practices Application Blocks
- The Data Access Application Block
- The Exception Management Application Block
- Best Practices — Performance
- Best Practices — Performance and Scalability
- Best Practices - Testing
- Reading the Tea Leaves, 2005
- Predictions: A Look Back at 2005, and a Look Ahead to 2006
- .NET Downloads
- Application Deployment Overview
- Application Deployment — Versioning
- Application Deployment — Version Policy
- Application Deployment — Packaging and Distribution
- .NET Remoting Overview
- A Remoting Demonstration
- Remoting Configuration
- Remoting: Lifetimes and Leases
- Remoting: Other Issues
- Attributes
- Writing Custom Attributes
- Accessing Attributes in Code
- Reflection
- Class Design: Inheritance, Interface, or Composition?
- The TriTryst Game
- Console Applications in .NET 2.0
- New File I/O Methods in .NET 2.0
- Building Projects with MSBuild
- Unmanaged Callbacks in .NET 2.0
- Timer Troubles
- Non-Rectangular Windows Forms
- Windows Forms Transparency
- 10 Things I Hate About Visual Basic
- 10 Things I Hate About C#
- Background Processing with Idle Time
- Scaling Windows Forms
- Reading and Writing Binary Data
- New Memory Management Functions in .NET 2.0
- Compatibility Between .NET 1.1 and .NET 2.0
- Managed Debugging Assistants in .NET 2.0
- XDir: A Program for Viewing Directory Sizes
- The Microsoft.VisualBasic Namespace
- Operator Overloading
- Working with GPS Data
- Hidden Visual Studio Tools
- .NET 3.0
- The .NET 2.0 Stopwatch Class
- Nullable Types
- Drawing Rotated Text
- Unsafe Code
- Other .NET Languages
- Compiler Directives
- Safe Handles
- Predictions, 2007 Edition
- New Features in C# 3.0
- Generics
- Network Client Programming
- On the Misuse of Exceptions
- Maximum Object Size in .NET
- More on Maximum Object Sizes
- Keyed Collection Memory Limitations
- Matching String Endings
- Allocating Small Data Structures
- Grumbling About Limitations
- Some Thoughts on the Nature of What We Do
- Working with Predicates in Collections
- Working with DataReaders
- Outputting XML with XmlWriter
- Writing XML Data
- Working with Compression
- Another Look at Compressed Streams
- Compressing a Very Large File
- Canonical URIs
- Constructing URIs
- Using OneWayAttribute for Remote Calls
- Selecting a Garbage Collector
- Linked List
- Linked List Application - The MRU List
- Auto-implemented Properties in C#
- The HashSet Collection
- Looking Ahead: 2018
- An Experiment in Optimization
- A Larger Integer
- Extension Methods
- Language Integrated Query (LINQ)
- Variable Length Parameter Lists
- The ReaderWriterLockSlim Synchronization Primitive
- Sorting a Text File
- Sorting a Large Text File
- Using ListView with Large Data Sets
- LINQ One-Liners
- Regular Expression Optimization
- Random File I/O
- Computing the Size of a Structure
- More on Computing Structure Sizes
- UnmanagedMemoryStream
- Dynamically Loading Code
- Building a String Table
- Delegates Versus Function Pointers
- Visual Studio Editor Features
- A Simple Profile Timer
- New Features in C# 4.0
- IEnumerator or IList?
- New Features in .NET 4.0
- Set Operations with IEnumerable and HashSet
- Using File Locks
- Extending Object Functionality
- Clearing a HashSet
- When Hash Codes Matter
- Parsing Command Line Options
- Creating a Single-Instance Program
- Asynchronous Windows Forms Events
- The BackgroundWorker Component
- Fixing a Dumb Mistake
- Thinking About Multi-Threaded Programs
- JavaScript Object Notation
- Useful .NET-related Sites
- Markov Models
- Building an Order 0 Markov Model
- Higher Order Markov Models
- Webmaster's Guide to robots.txt
- An Overview of the Parallel Extensions to .NET
- Parallel Extensions Synchronization Objects
- Thread Safe Collections
- A Bug and a Conundrum
- Another Bug and an Answer
- Task Parallel Library
- Good and Bad Ideas in C#
- Parallel LINQ
- Copying Large Files
- Replacing File.Copy
- Learning from Our Mistakes
- Symbolic Links
- There Is No Easy Fix
- Tracking Hurricanes
- Examining Hurricane Data
- Searching for Multiple Strings
- Simple JSON Processing
- Aho-Corasick String Searching
- Writing a Web Crawler
- Web Crawler Politeness
- Source Control Management
- Subversion
- Communicating with Datagrams
- Fun with Actions and Funcs New
- The Future of Media
- The Importance of Metadata
- Of Comparison and IComparer
- IComparer, Comparer, IComparable, Oh My!
- Comparing Generic Types New
- A Simple HTTP Server New
- Informit Reference Library
Building International Web Applications
Last updated Jan 1, 2004.
With the System.Globalization namespace, the .NET Framework provides wide-ranging support for the development of world-ready applications . Internationalization (also called i18n because there are 18 letters between the initial i and final n in the word internationalization) is the process of making an application work in all supported local cultures.
The namespaces in the .NET Framework for globalizing and localizing applications are as follows:
The System.Globalization namespace contains classes that define culture-related information such as language, country/region, sort order for strings, calendars in use (both Gregorian and nonGregorian calendars), numeric formatting, date/time formatting, and so on.
The System.Resources namespace contains classes and interfaces to build and manage various culture-specific resources. By using the ResourceManager class, for example, you can access and control resources stored in the main assembly or in resource satellite assemblies (culture-specific assemblies that contain only localized resources).
The System.Text namespace contains classes representing ASCII, Unicode, UTF-7, UTF-8, and other character encodings.
Before diving deep into the code examples, let's consider a few basic points about internationalization.
Internationalizing Your Application
There are three main steps to developing world-ready, internationalized applications:
Globalize the application by making it culture-neutral and language-neutral (adaptable to different cultures). During this process, you have to set the correct conventions for numeric formats, currency formats, date and time format, calendars, and so on. Note that in this phase the developed application is flexible enough to support all cultures and regions.
Prepare the application for localization by isolating or detaching the localizable resources from the application's executable code (the main assembly and resources in resource files). This reduces or avoids code modification during the localization process.
Localize the application by translating/customizing the application's resources into localized versions (specific cultures or regions). At this stage, the developed application has two sections:
The user interface section includes localizable elements such as strings, error messages, etc.
The code section contains application code common for all cultures that your application supports.
Think of it this way:
localized user interface + common code section = localized application
To identify the user's preferred language, use the following code:
C#
string Lan = Request.UserLanguages[0];
Visual Basic .NET
Dim Lan As String Lan = Request.UserLanguages(0)
Establishing the Culture Settings in Web Forms
There are three methods for setting the culture and user interface culture for web forms:
Add the Culture and UICulture values to the Page directive.
Use the <globalization> section of the web.config file.
Add code to set the CurrentCulture and CurrentUICulture properties at runtime.
Using the Culture and UICulture settings is simple:
<%@ Page UICulture="de" Culture="en-US" . . . %>
The other two methods are a bit more complex, but give you more options.
The <globalization> section in the web.config file configures the globalization settings for an application. <globalization> supports five attributes:
requestEncoding indicates the default encoding for all requests.
responseEncoding indicates the default encoding for all responses.
fileEncoding indicates the default encoding for all .aspx, .asmx, .asax, and .aspc files.
culture is the default culture used to process requests. It includes information about language, writing system, and calendar, as well as methods for common operations such as printing dates and sorting strings. For instance, the culture name and culture identifier for the TamilIndia language-country/region are ta-IN and 0x0449, respectively.
uiculture indicates the default culture for processing locale-dependent resource searches.
For example, here's how you set the globalization for India, with the Hindi language:
<configuration>
<system.web>
<globalization
requestEncoding="utf-8"
responseEncoding="utf-8"
fileEncoding="utf-8"
culture="hi-IN"
/>
</system.web>
</configuration>
If you then insert a calendar control in a web form and run the form, you get the culture-specific output for the culture hi-IN (HindiIndia), as shown in the following figure.
Figure
14 Culture-specific response for hi-IN (HindiIndia).
In some cases, you need right-to-left formatting (in Arabic, for example). In that scenario, you have to set the HTML dir attribute for the page's <body> element, like this:
<body dir="rtl">
The calendar in the following figure shows the output for culture ar-SA (ArabicSaudi Arabia), formatting the dates right to left.
Figure
15 Culture-specific response for ar-SA (ArabicSaudi Arabia)
with right-to-left formatting.
Alternatively, you can add code to set the culture and user interface culture settings properties at runtime. The CultureInfo class provides culture-specific information, with access to culture-specific instances of DateTimeFormatInfo, NumberFormatInfo, CompareInfo, and TextInfo. The CurrentCulture property handles date and number formatting, string comparison, and so on. The CurrentUICulture property is used by the Common Language Runtime to load the appropriate resources for the user interface. You can set these properties dynamically at runtime using the Thread class's CurrentCulture property as follows:
C#
string Lan = Request.UserLanguages[0]; Thread.CurrentThread.CurrentCulture = new CultureInfo(Lan); Thread.CurrentThread.CurrentUICulture = new CultureInfo(Lan);
VB .NET
Dim Lan As String Lan = Request.UserLanguages(0) Thread.CurrentThread.CurrentCulture = New CultureInfo(Lan) Thread.CurrentThread.CurrentUICulture = New CultureInfo(Lan)
This code identifies the user's culture and then sets the UICulture to the current thread.
Creating Satellite Assemblies
Satellite assemblies enclose culture-specific strings in resource files and resources such as .jpg files (localized resources onlyno executable code). Each satellite assembly file encloses the resources for one culture. The steps to include resource files in a Visual Studio .NET project are as follows:
From the Project menu, select Add New Item and then select Assembly Resource File from the Templates list.
Name the resource file (for this example, Resfile.resx) and click Open. (In a real-time application, try to follow the naming format formname.controlname: for example, webform1.label1.) Visual Studio .NET creates the new resource file and displays it in XML Designer in Data view (see the following figure).
Enter the data for name and value, as shown in the figure.
Figure
16 XML Designer in Data view.
NOTE
To keep the example simple, I put both the culture-specific strings in one resource file. In a real-time application, however, I recommend creating separate resource files with appropriate naming conventions. An application can contain many resource files. For instance, you might name the resource file in the format filename.languagecode.resx (such as strings.es.resx). You should also create a fallback resource file with the format filename.resx (such as strings.resx), containing the default strings. It will be used if the application can't find resources more suitable to the specified user interface culture. The fallback resources are built into the main assembly, which contains the application code.
You can also use the Resource Generator (resgen.exe), which converts a text file (containing a name-value entry for each string) to a resource file. This module is then linked or embedded into the assembly.
Using Satellite Assemblies To Access and Display Resources
To load the resources for the web form, use the ResourceManager class:
protected ResourceManager Resvalue = new
ResourceManager("globalization.Resfile", typeof(WebForm1).Assembly);
The ResourceManager constructor takes two arguments: the root name of the resources, and the main assembly.
Displaying Resource Strings
It's easy to retrieve and display the string by using the ResourceManager object's GetStrings method:
this.Label1.Text = Resvalue.GetString("text1");
Finally, let's consider an example that displays a calendar with culture-specific details based on a selection from a drop-down list:
/* In the Code Editor, import the System.Resources,
System.Globalization, and System.Threading namespaces. */
using System;
...
using System.Globalization;
using System.Threading;
using System.Resources;
namespace globalization
{
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.DropDownList DropDownList1;
protected System.Web.UI.WebControls.Calendar Calendar1;
protected System.Web.UI.WebControls.Label Label1;
protected System.Web.UI.WebControls.Label Label2;
protected System.Web.UI.WebControls.Label Label3;
protected System.Web.UI.WebControls.Label Label4;
/* Code to load the resources */
protected ResourceManager Resvalue = new
ResourceManager("globalization.Resfile", typeof(WebForm1).Assembly);
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
/* List all available cultures in the drop-down list */
foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
{
DropDownList1.Items.Add(ci.ToString());
/* Select the current culture in the drop-down list */
if (ci.Name == Thread.CurrentThread.CurrentCulture.Name)
DropDownList1.SelectedIndex = DropDownList1.Items.Count - 1;
}
}
/* Set the selected culture to the current thread */
Thread.CurrentThread.CurrentCulture = new CultureInfo(this.DropDownList1.SelectedItem.Text);
Label1.Text = DateTime.Now.ToString("F");
Label2.Text = 100000.ToString("C");
Label3.Text = Thread.CurrentThread.CurrentCulture.NativeName;
/* For the culture "ta-IN", retrieve and display the value of "text2"
from resource file. For all others, retrieve and display the "text1"
value from the resource file. */
if (this.DropDownList1.SelectedItem.Text == "ta-IN")
{
Label4.Text = Resvalue.GetString("text2");
}
Label4.Text = Resvalue.GetString("text1");
}
#region Web Form Designer generated code
#endregion
private void DropDownList1_SelectedIndexChanged(object sender, System.EventArgs e)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo(this.DropDownList1.SelectedItem.Text);
}
}
}
The out put will be as follows. The first figure shows the default culture setting en-US (EnglishUnited States) and the second shows the culture-specific response (my mother tongue!) for culture ta-IN (TamilIndia).
Figure
17 Default setting en-US (EnglishUnited States).
Figure
18 Culture-specific response ta-IN (TamilIndia).
Unicode
In the past, it was very difficult to develop international applications because no standard universal character-encoding existed. Unicode, a universal character-encoding standard and data encoding scheme, simplifies localization by enabling all international characters to be represented in a single encoding. Unicode supports all character sets and simplifies the development of world-ready applications. The Unicode Standard is maintained by the nonprofit Unicode Consortium (founded in 1991).
"Unicode provides a unique number for every character, no matter what the platform, no matter what the program, no matter what the language. The Unicode Standard has been adopted by such industry leaders as Apple, HP, IBM, JustSystem, Microsoft, Oracle, SAP, Sun, Sybase, Unisys, and many others." www.unicode.org
All ASCII characters are incorporated in Unicode as "widened" characters, with each character being two bytes long. Unicode utilizes three Unicode Transformation Formats (UTFs): UTF-8, UTF-16, and UTF-32. The .NET Framework and Visual Studio .NET use Unicode UTF-16 to represent all characters.
Let's consider a simple C# program that renders text in different languagesin this example, English, Tamil, French, German, Chinese, Japanese, and Russianusing Unicode values. In the code, "\uaaaa", "aaaa" represents a hexadecimal value. For each character defined in Unicode, a hexadecimal number is used to symbolize that character in computer data.
private void Page_Load(object sender, System.EventArgs e)
{
this.EngLbl.Text = "\u0057" + "\u0065" + "\u006C"+ "\u0063"
+ "\u006F" + "\u006D" + "\u0065" + "\u0020" + "\u0074"
+ "\u006F" + "\u0020" + "InformIT" + "\u0021";
this.TamLbl.Text = "InformIT" + "\u0B95" +"\u0BCD"+ "\u0B95"
+ "\u0BC1" + "\u0020" + "\u0BA8" + "\u0BB2" + "\u0BCD"
+ "\u0BB5" + "\u0BB0" + "\u0BB5" + "\u0BBE"+ "\u0B95"
+ "\u0BC1" + "\u0B95" + "\u0021";
this.FrenLbl.Text = "\u0042" + "\u0069" + "\u0065"+ "\u006E"
+ "\u0076" + "\u0065" + "\u006E" + "\u0075" + "\u0065"
+ "\u0020" + "\u0061" + "\u0075" + "\u0020"
+ "InformIT" + "\u0021";
this.GerLbl.Text = "\u0057" + "\u0069" + "\u006C"+ "\u006B"
+ "\u006F" + "\u006D" + "\u006D" + "\u0065" + "\u006E"
+ "\u0020" + "\u007A" + "\u0075" + "\u0020"
+ "InformIT" + "\u0021";
this.ChiLbl.Text = "\u6B22" + "\u8FCE" + "\u4F7F"+ "\u7528"
+ "\u0020" + "InformIT" + "\u0021";
this.JapLbl.Text = "InformIT" + "\u3078" + "\u3087"
+ "\u3045"+ "\u3053" + "\u305D" + "\u0021";
this.RussLbl.Text = "\u0414" + "\u043E" + "\u0431"+ "\u0440"
+ "\u043E" + "\u0020" + "\u043F" + "\u043E" + "\u0436"
+ "\u0430" + "\u043B" + "\u043E" + "\u0432" + "\u0430"
+ "\u0442" + "\u044A" + "\u0020" + "\u0432" +"\u0020"
+ "InformIT" + "\u0021";
}
The following figure shows the output of the Unicode program.
Figure Rendering
different language text using Unicode values.
Code Charts
You can check the online code charts to find the Unicode values for languages and characters. The code charts are organized into blocks, which are groupings of related characters.
TIP
For more details, see the online version of The Unicode Standard, Version 3.0 (Addison-Wesley, 2000, ISBN 0201616335). You can also buy the print version, if you prefer.
Sometimes you may not find the exact character (shape) you want, because you only get a representative shape for identification. You may even have to use two code values for a single character. For the majority of characters, Unicode defines characters distinctively, but some characters can be combined to form others, such as accented characters. To display the Asian characters in a Windows application, for example, you need to install the proper language files, using the Regional Options settings in the Windows Control Panel.
You can also use Unicode values to represent mathematical operators, geometric shapes, musical symbols, optical character recognition characters, currency symbols, phonetic extensions, superscripts and subscripts, and more. Check out the code charts for more info.
The following table shows some sample scripts and code values:
|
Arabic |
U+0600 |
U+06FF |
|
Basic Latin |
U+0000 |
U+007F |
|
Bengali |
U+0980 |
U+09FF |
|
Devanagari |
U+0900 |
U+097F |
|
Greek |
U+0370 |
U+03FF |
|
Gujarati |
U+0A80 |
U+0AFF |
|
Gurmukhi |
U+0A00 |
U+0A7F |
|
Hiragana |
U+3040 |
U+309F |
|
Kannada |
U+0C80 |
U+0CFF |
|
Katakana |
U+30A0 |
U+30FF |
|
Khmer |
U+1780 |
U+17FF |
|
Lao |
U+0E80 |
U+0EFF |
|
Malayalam |
U+0D00 |
U+0D7F |
|
Myanmar |
U+1000 |
U+109F |
|
Oriya |
U+0B00 |
U+0B7F |
|
Sihhala |
U+0D80 |
U+0DFF |
|
Tamil |
U+0B80 |
U+0BFF |
|
Telugu |
U+0C00 |
U+0C7F |
|
Thai |
U+0E00 |
U+0E7F |
|
Tibetan |
U+0F00 |
U+0FBF |



Account Sign In
View your cart