Creating Globally Aware Applications

Microsoft Silverlight will reach end of support after October 2021. Learn more.

Globalization is the design and development of applications that support localized user interfaces and regional data for users in multiple cultures. Most Silverlight-based applications are global applications. A user can be located anywhere in the world, especially for applications that can be accessed publicly on the Internet.

The CultureInfo Class

The System.Globalization.CultureInfo class represents either a culture and a language, or only a language. It provides culture-specific information such as the calendar, the currency symbol, the character set, casing and string comparison rules, and the formatting conventions for dates and times.

Each culture that is represented by a CultureInfo class has a predefined, unique name. Typically, a culture name takes the form languageCode-regionCode, where languageCode is a lowercase two-letter code for the language (such as "en" for English or "jp" for Japanese), and regionCode is an uppercase two-letter code for the country or region (such as "AU" for Australia or "TH" for Thailand). (For a list of valid language and country/region codes, see CultureInfo.) A neutral culture is a culture that represents a language only. Its culture name takes the form languageCode, which is a lowercase two-letter code for the language. The invariant culture is loosely based on the English language but is culture-independent.

Instantiating a CultureInfo Object

You can instantiate a CultureInfo object that represents a specific culture by passing its culture name to the CultureInfo class constructor. In addition, you can retrieve a CultureInfo object from several static (shared in Visual Basic) properties of the CultureInfo class. These properties include the following:

NoteNote:

If you retrieve a CultureInfo object that represents either the current culture or the current UI culture, or if you instantiate a new CultureInfo object that represents the user's current culture, the CultureInfo object will reflect any customizations that the user has made.

The following example instantiates a CultureInfo object that represents the Spanish (Spain) culture, which is designated as "es-ES", and also retrieves the current, current UI, and invariant cultures. It then displays information about each culture. The example includes output produced by a system whose current culture is English (United States), which is designated as "en-US".

      ' Instantiate es-ES culture by calling constructor.   
      Dim esCulture As New CultureInfo("es-ES")
      outputBlock.Text += "Information about culture " + esCulture.Name + vbCrLf
      outputBlock.Text += String.Format("   Name: {0}", esCulture.Name) + vbCrLf
      outputBlock.Text += String.Format("   Display Name: {0}", esCulture.DisplayName) + vbCrLf
      outputBlock.Text += String.Format("   Native Name: {0}", esCulture.NativeName) + vbCrLf
      outputBlock.Text += String.Format("   English Name: {0}", esCulture.EnglishName) + vbCrLf
      outputBlock.Text += String.Format("   Parent Culture Name: {0}", esCulture.Parent.Name) + vbCrLf
      outputBlock.Text += String.Format("   Calendar: {0}", esCulture.Calendar.ToString()) + vbCrLf
      outputBlock.Text += String.Format("   Is read-only: {0}", CStr(esCulture.IsReadOnly)) + vbCrLf 

      ' Retrieve current culture.   
      Dim curCulture As CultureInfo = CultureInfo.CurrentCulture
      outputBlock.Text += "Information about culture " + curCulture.Name + vbCrLf
      outputBlock.Text += String.Format("   Name: {0}", curCulture.Name) + vbCrLf
      outputBlock.Text += String.Format("   Display Name: {0}", curCulture.DisplayName) + vbCrLf
      outputBlock.Text += String.Format("   Native Name: {0}", curCulture.NativeName) + vbCrLf
      outputBlock.Text += String.Format("   English Name: {0}", curCulture.EnglishName) + vbCrLf
      outputBlock.Text += String.Format("   Parent Culture Name: {0}", curCulture.Parent.Name) + vbCrLf
      outputBlock.Text += String.Format("   Calendar: {0}", curCulture.Calendar.ToString()) + vbCrLf
      outputBlock.Text += String.Format("   Is read-only: {0}", curCulture.Calendar.IsReadOnly) + vbCrLf 

      ' Retrieve current UI culture.   
      Dim curUiCulture As CultureInfo = CultureInfo.CurrentUICulture
      outputBlock.Text += "Information about culture " + curUiCulture.Name + vbCrLf
      outputBlock.Text += String.Format("   Name: {0}", curUiCulture.Name) + vbCrLf
      outputBlock.Text += String.Format("   Display Name: {0}", curUiCulture.DisplayName) + vbCrLf
      outputBlock.Text += String.Format("   Native Name: {0}", curUiCulture.NativeName) + vbCrLf
      outputBlock.Text += String.Format("   English Name: {0}", curUiCulture.EnglishName) + vbCrLf
      outputBlock.Text += String.Format("   Parent Culture Name: {0}", curUiCulture.Parent.Name) + vbCrLf
      outputBlock.Text += String.Format("   Calendar: {0}", curUiCulture.Calendar.ToString()) + vbCrLf
      outputBlock.Text += String.Format("   Is read-only: {0}", CStr(curUiCulture.Calendar.IsReadOnly)) + vbCrLf 

      ' Retrieve invariant culture.   
      Dim invCulture As CultureInfo = CultureInfo.InvariantCulture
      outputBlock.Text += "Information about the invariant culture" + vbCrLf
      outputBlock.Text += String.Format("   Name: {0}", invCulture.Name) + vbCrLf
      outputBlock.Text += String.Format("   Display Name: {0}", invCulture.DisplayName) + vbCrLf
      outputBlock.Text += String.Format("   Native Name: {0}", invCulture.NativeName) + vbCrLf
      outputBlock.Text += String.Format("   English Name: {0}", invCulture.EnglishName) + vbCrLf
      outputBlock.Text += String.Format("   Parent Culture Name: {0}", invCulture.Parent.Name) + vbCrLf
      outputBlock.Text += String.Format("   Calendar: {0}", invCulture.Calendar.ToString()) + vbCrLf
      outputBlock.Text += String.Format("   Is read-only: {0}", CStr(invCulture.Calendar.IsReadOnly)) + vbCrLf 
      ' The example displays the following output:
      '       Information about culture es-ES
      '          Name: es-ES
      '          Display Name: Spanish (Spain)
      '          Native Name: español (España)
      '          English Name: Spanish (Spain)
      '          Parent Culture Name: es
      '          Calendar: System.Globalization.GregorianCalendar
      '          Is read-only: False
      '       Information about culture en-US
      '          Name: en-US
      '          Display Name: English (United States)
      '          Native Name: English (United States)
      '          English Name: English (United States)
      '          Parent Culture Name: en
      '          Calendar: System.Globalization.GregorianCalendar
      '          Is read-only: True
      '       Information about culture en-US
      '          Name: en-US
      '          Display Name: English (United States)
      '          Native Name: English (United States)
      '          English Name: English (United States)
      '          Parent Culture Name: en
      '          Calendar: System.Globalization.GregorianCalendar
      '          Is read-only: True
      '       Information about the invariant culture
      '          Name: 
      '          Display Name: Invariant Language (Invariant Country)
      '          Native Name: Invariant Language (Invariant Country)
      '          English Name: Invariant Language (Invariant Country)
      '          Parent Culture Name: 
      '          Calendar: System.Globalization.GregorianCalendar
      '          Is read-only: True

// Instantiate es-ES culture by calling constructor.   
CultureInfo esCulture = new CultureInfo("es-ES");
outputBlock.Text += "Information about culture " + esCulture.Name + "\n";
outputBlock.Text += String.Format("   Name: {0}\n", esCulture.Name);
outputBlock.Text += String.Format("   Display Name: {0}\n", esCulture.DisplayName);
outputBlock.Text += String.Format("   Native Name: {0}\n", esCulture.NativeName);
outputBlock.Text += String.Format("   English Name: {0}\n", esCulture.EnglishName);
outputBlock.Text += String.Format("   Parent Culture Name: {0}\n", esCulture.Parent.Name);
outputBlock.Text += String.Format("   Calendar: {0}\n", esCulture.Calendar.ToString());
outputBlock.Text += String.Format("   Is read-only: {0}\n", esCulture.IsReadOnly); 

// Retrieve current culture.   
CultureInfo curCulture = CultureInfo.CurrentCulture;
outputBlock.Text += "Information about culture " + curCulture.Name + "\n";
outputBlock.Text += String.Format("   Name: {0}\n", curCulture.Name);
outputBlock.Text += String.Format("   Display Name: {0}\n", curCulture.DisplayName);
outputBlock.Text += String.Format("   Native Name: {0}\n", curCulture.NativeName);
outputBlock.Text += String.Format("   English Name: {0}\n", curCulture.EnglishName);
outputBlock.Text += String.Format("   Parent Culture Name: {0}\n", curCulture.Parent.Name);
outputBlock.Text += String.Format("   Calendar: {0}\n", curCulture.Calendar.ToString());
outputBlock.Text += String.Format("   Is read-only: {0}\n", curCulture.Calendar.IsReadOnly); 

// Retrieve current UI culture.   
CultureInfo curUiCulture = CultureInfo.CurrentUICulture;
outputBlock.Text += "Information about culture " + curUiCulture.Name + "\n";
outputBlock.Text += String.Format("   Name: {0}\n", curUiCulture.Name);
outputBlock.Text += String.Format("   Display Name: {0}\n", curUiCulture.DisplayName);
outputBlock.Text += String.Format("   Native Name: {0}\n", curUiCulture.NativeName);
outputBlock.Text += String.Format("   English Name: {0}\n", curUiCulture.EnglishName);
outputBlock.Text += String.Format("   Parent Culture Name: {0}\n", curUiCulture.Parent.Name);
outputBlock.Text += String.Format("   Calendar: {0}\n", curUiCulture.Calendar.ToString());
outputBlock.Text += String.Format("   Is read-only: {0}\n", curUiCulture.Calendar.IsReadOnly); 

// Retrieve invariant culture.   
CultureInfo invCulture = CultureInfo.InvariantCulture;
outputBlock.Text += "Information about the invariant culture\n";
outputBlock.Text += String.Format("   Name: {0}\n", invCulture.Name);
outputBlock.Text += String.Format("   Display Name: {0}\n", invCulture.DisplayName);
outputBlock.Text += String.Format("   Native Name: {0}\n", invCulture.NativeName);
outputBlock.Text += String.Format("   English Name: {0}\n", invCulture.EnglishName);
outputBlock.Text += String.Format("   Parent Culture Name: {0}\n", invCulture.Parent.Name);
outputBlock.Text += String.Format("   Calendar: {0}\n", invCulture.Calendar.ToString());
outputBlock.Text += String.Format("   Is read-only: {0}\n", invCulture.Calendar.IsReadOnly); 
// The example displays the following output:
//       Information about culture es-ES
//          Name: es-ES
//          Display Name: Spanish (Spain)
//          Native Name: español (España)
//          English Name: Spanish (Spain)
//          Parent Culture Name: es
//          Calendar: System.Globalization.GregorianCalendar
//          Is read-only: False
//       Information about culture en-US
//          Name: en-US
//          Display Name: English (United States)
//          Native Name: English (United States)
//          English Name: English (United States)
//          Parent Culture Name: en
//          Calendar: System.Globalization.GregorianCalendar
//          Is read-only: True
//       Information about culture en-US
//          Name: en-US
//          Display Name: English (United States)
//          Native Name: English (United States)
//          English Name: English (United States)
//          Parent Culture Name: en
//          Calendar: System.Globalization.GregorianCalendar
//          Is read-only: True
//       Information about the invariant culture
//          Name: 
//          Display Name: Invariant Language (Invariant Country)
//          Native Name: Invariant Language (Invariant Country)
//          English Name: Invariant Language (Invariant Country)
//          Parent Culture Name: 
//          Calendar: System.Globalization.GregorianCalendar
//          Is read-only: True
Important noteImportant Note:

The .NET Framework for Silverlight provides data for the invariant culture, but it retrieves information about all other cultures from the operating system. This means that the information that is available to a specific culture may differ across operating systems or even across versions of the same operating system. In some cases, data may even be unavailable, in which case data from the invariant culture will be used instead. The developer should make no fixed assumptions about the values of particular properties or particular objects returned by specific cultures.

Changing the Current or Current UI Culture

The .NET Framework for Silverlight retrieves the CultureInfo object from two properties: CultureInfo.CurrentCulture, which is used in text casing and comparisons, as well as in formatting dates and numbers; and CultureInfo.CurrentUICulture, which is used to retrieve user interface resources. In some cases, you may want to change the current culture or the current UI culture of your Silverlight-based application. However, the CultureInfo.CurrentCulture and CultureInfo.CurrentUICulture properties are read-only. Therefore, they cannot be used to change the current culture.

To change the current culture, you must assign a new CultureInfo object to the Thread.CurrentCulture property of the current thread. The following example changes the Silverlight-based application's current culture from its default value, which is English (United States) or "en-US", to French (France), which is "fr-FR".

' Display current culture information.
outputBlock.Text += String.Format("The current culture is '{0}'.", CultureInfo.CurrentCulture.Name) + vbCrLf
outputBlock.Text += String.Format("The currrent UI culture is '{0}'.", CultureInfo.CurrentUICulture.Name) + vbCrLf

' Change the current and current UI culture to fr-FR.
Dim frCulture As New CultureInfo("fr-FR")
Thread.CurrentThread.CurrentCulture = frCulture
Thread.CurrentThread.CurrentUICulture = frCulture
' Display new current culture information.
outputBlock.Text += String.Format("The new current culture is '{0}'.", CultureInfo.CurrentCulture.Name) + vbCrLf
outputBlock.Text += String.Format("The new currrent UI culture is '{0}'.", CultureInfo.CurrentUICulture.Name) + vbCrLf
' The example displays the following output:
'       The current culture is 'en-US'.
'       The current UI culture is 'en-US'.
'       The current culture is 'fr-FR'.
'       The current UI culture is 'fr-FR'.
// Display current culture information.
outputBlock.Text += String.Format("The current culture is '{0}'.\n", CultureInfo.CurrentCulture.Name);
outputBlock.Text += String.Format("The currrent UI culture is '{0}'.\n", CultureInfo.CurrentUICulture.Name);

// Change the current and current UI culture to fr-FR.
CultureInfo frCulture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentCulture = frCulture;
Thread.CurrentThread.CurrentUICulture = frCulture;
// Display new current culture information.
outputBlock.Text += String.Format("The new current culture is '{0}'.\n", CultureInfo.CurrentCulture.Name);
outputBlock.Text += String.Format("The new currrent UI culture is '{0}'.\n", CultureInfo.CurrentUICulture.Name);
//       The current culture is 'en-US'.
//       The current UI culture is 'en-US'.
//       The current culture is 'fr-FR'.
//       The current UI culture is 'fr-FR'.

Customizing a CultureInfo Object

In some cases, you may want to change some of the data stored by the CultureInfo object or one of its child objects, such as DateTimeFormatInfo or NumberFormatInfo. However, the CultureInfo objects returned by the CultureInfo.CurrentCulture and CultureInfo.CurrentUICulture properties are read-only and cannot be modified. To customize the values of a read-only CultureInfo object, you must make a copy of the original object by calling the CultureInfo.Clone method. This method returns a read/write copy of the original CultureInfo object. Unlike most Clone methods, it also returns an enhanced shallow copy of the objects returned by the CultureInfo.DateTimeFormat, CultureInfo.NumberFormat, CultureInfo.Calendar, and CultureInfo.TextInfo properties.

NoteNote:

In the .NET Framework for Silverlight, a customized CultureInfo object can be created only by modifying an existing object. You cannot create a new custom CultureInfo object from scratch.

The following example illustrates how to retrieve a CultureInfo object that represents the current culture, modify it, and assign the new CultureInfo object back to the CultureInfo property.

Dim oldCulture, newCulture As CultureInfo
Dim posValue As Decimal = 1603.5471d
Dim negValue As Decimal = -1476.9852d

' Get the current culture.
oldCulture = CultureInfo.CurrentCulture
outputBlock.Text += "Displaying a positive and a negative currency value:" + vbCrLf
outputBlock.Text += String.Format("   {0:C2}", posValue) + vbCrLf
outputBlock.Text += String.Format("   {0:C2}", negValue) + vbCrLf

' Clone the current culture and modify its currency pattern properties.
newCulture = DirectCast(oldCulture.Clone(), CultureInfo)
newCulture.NumberFormat.CurrencyNegativePattern = 15
newCulture.NumberFormat.CurrencyPositivePattern = 3
' Make the new CultureInfo object the current culture.
Thread.CurrentThread.CurrentCulture = newCulture
outputBlock.Text += "Modified the current culture..." + vbCrLf
outputBlock.Text += "Displaying a positive and a negative currency value:" + vbCrLf
outputBlock.Text += String.Format("   {0:C2}", posValue) + vbCrLf
outputBlock.Text += String.Format("   {0:C2}", negValue) + vbCrLf
' The example displays the following output:
'   Displaying a positive and a negative currency value:
'      $1,603.55
'      ($1,476.99)
'   Modified the current culture...
'   Displaying a positive and a negative currency value:
'      1,603.55 $
'      (1,476.99 $)
CultureInfo oldCulture, newCulture;
decimal posValue = 1603.5471m;
decimal negValue = -1476.9852m;

// Get the current culture.
oldCulture = CultureInfo.CurrentCulture;
outputBlock.Text += "Displaying a positive and a negative currency value:\n";
outputBlock.Text += String.Format("   {0:C2}\n", posValue);
outputBlock.Text += String.Format("   {0:C2}\n", negValue);

// Clone the current culture and modify its currency pattern properties.
newCulture = (CultureInfo) oldCulture.Clone();
newCulture.NumberFormat.CurrencyNegativePattern = 15;
newCulture.NumberFormat.CurrencyPositivePattern = 3;
// Make the new CultureInfo object the current culture.
Thread.CurrentThread.CurrentCulture = newCulture;
outputBlock.Text += "Modified the current culture...\n";
outputBlock.Text += "Displaying a positive and a negative currency value:\n";
outputBlock.Text += String.Format("   {0:C2}\n", posValue);
outputBlock.Text += String.Format("   {0:C2}\n", negValue);
// The example displays the following output:
//   Displaying a positive and a negative currency value:
//      $1,603.55
//      ($1,476.99)
//   Modified the current culture...
//   Displaying a positive and a negative currency value:
//      1,603.55 $
//      (1,476.99 $)

The Invariant Culture

The culture that is returned by the CultureInfo.InvariantCulture property represents neither a neutral nor a specific culture. It represents a third type of culture that is culture-insensitive. This culture is associated with the English language, but it is not associated with a country or region. You can use the InvariantCulture property with almost any method in the System.Globalization namespace that requires a culture. You can also use the property with ToString and Parse methods that have an IFormatProvider parameter.

Important noteImportant Note:

Use the invariant culture for operations that require culture-independent results. In other cases, it might produce results that are linguistically incorrect or culturally inappropriate.

Performing Culture-Sensitive Operations on Data

The .NET Framework for Silverlight enables you to perform operations such as formatting dates and times, or sorting strings depending on either the current culture or a specified culture. The default overloads of most culture-sensitive methods automatically use the conventions of the user's current culture. The default methods take much of the guesswork out of determining the user's language and culture. The next section describes an important cultural consideration for supplying string values in XAML attribute usage. The other sections explain how to format date, time, and numeric values for code usages (not XAML).

Formatting Values for XAML

The XAML parser in Silverlight 4 always uses the English ("en-us") culture when it invokes type conversion for processing XAML attribute values. If your application generates XAML dynamically, and then loads XAML at run time by using the XamlReader.Load method, any numeric data should be formatted using the conventions of the "en-us" culture rather than the current culture. The reason for this behavior is that XAML processing is split into markup compile roles and run-time parse roles. One culture as "default" for XAML behavior was needed for consistency, to prevent issues from emerging when XAML is markup-compiled by one culture on the developer's machine and parsed by another in the deployed application. Invariant culture has some undefined behaviors, and could not be used to provide the default culture conditions for parsing XAML. This same behavior for treating en_us as the XAML default is true for WPF XAML. For more information, see TypeConverters and XAML.

This does not mean XAML cannot pass culture values to user code. There are dedicated culture properties, including the Language property that can use the xml:lang values from an XMLDOM. Also, many controls process culture information in order to react to culture-specific input, or to enable culture-specific visual appearance such as right-to-left layout. Beyond this, there are recommended techniques for specifying XAML values such that they can be localized separately, regardless of whether type conversion is involved. For more information, see Localizing Silverlight-based Applications.

Formatting Dates and Times for a Specific Culture

The DateTime and DateTimeOffset structures provide methods that enable your applications to perform culture-sensitive parsing and formatting operations with date and time values. Information on date and time formats is provided by the DateTimeFormatInfo object, which is returned by the CultureInfo.DateTimeFormat property. The DateTimeFormatInfo class includes information about a particular culture's full and abbreviated day and month names, its A.M. and P.M. designators, and a variety of its time formats.

The following example displays a date and time value by calling the DateTime.ToString(IFormatProvider) method and passing it three CultureInfo objects. It then displays the date and time by calling the default DateTime.ToString() method. In this example, French (France), designated as "fr-FR", is the system's current culture. The example illustrates that the default overload of the ToString() method is culture-sensitive, because its output is identical to the output of a ToString method that specifies the "fr-FR" culture.

Imports System.Globalization

Public Module Example
   Public Sub Demo(outputBlock As System.Windows.Controls.TextBlock)
      outputBlock.FontFamily = New FontFamily("Courier New")

      Dim cultureNames() As String = { "en-US", "fr-FR", "ru-RU" }
      Dim dateValue As Date = #9/14/2011 5:32AM#
      outputBlock.Text += String.Format("{0,-9} {1,-17} {2}", "Culture", _
                                        "Current Culture", "Date") + vbCrLf + vbCrLf

      ' Display date using each of three cultures.
      outputBlock.Text += "Calling ToString with a Specific Culture:" + vbCrLf
      For Each cultureName As String In cultureNames
         Dim ci As New CultureInfo(cultureName)
         outputBlock.Text += String.Format("{0,-9} {1,-17} {2}", ci.Name, _
                                           IIf(ci.Equals(CultureInfo.CurrentCulture), _
                                               Boolean.TrueString, Boolean.FalseString), _
                                           dateValue.ToString(ci)) + vbCrLf
      Next

      ' Display date using default overload of ToString.
      outputBlock.Text += vbCrLf
      outputBlock.Text += "Calling the Parameterless Version of ToString:" + vbCrLF
      outputBlock.Text += String.Format("{0,-9} {1,-17} {2}", CultureInfo.CurrentCulture.Name, _
                                        "True", dateValue.ToString()) + vbCrLf
   End Sub
End Module
' The example displays the following output:
'    Culture   Current Culdture   Date
'
'    Calling ToString with a Soecific Culture:
'    en-US     False              9/14/2011 5:32:00 AM
'    fr-FR     True               14/09/2011 05:32:00
'    ru-RU     False              14.09.2011 5:32:00
'
'    Calling the parameterless version of ToString:
'    fr-FR     True               14/09/2011 05:32:00     
using System;
using System.Globalization;
using System.Windows.Media;

public class Example
{
   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {
      outputBlock.FontFamily = new FontFamily("Courier New");

      string[] cultureNames = { "en-US", "fr-FR", "ru-RU" };
      DateTime dateValue = new DateTime(2011, 9, 14, 5, 32, 0);
      outputBlock.Text += String.Format("{0,-9} {1,-17} {2}\n\n", "Culture", 
                                        "Current Culture", "Date");

      // Display date using each of three cultures.
      outputBlock.Text += "Calling ToString with a Specific Culture:\n";
      foreach (string cultureName in cultureNames)
      {
         CultureInfo ci = new CultureInfo(cultureName);
         outputBlock.Text += String.Format("{0,-9} {1,-17} {2}\n", ci.Name, 
                                           ci.Equals(CultureInfo.CurrentCulture) ?
                                               Boolean.TrueString : Boolean.FalseString, 
                                           dateValue.ToString(ci));
      }

      // Display date using default overload of ToString.
      outputBlock.Text += "\n";
      outputBlock.Text += "Calling the Parameterless Version of ToString:\n";
      outputBlock.Text += String.Format("{0,-9} {1,-17} {2}\n", CultureInfo.CurrentCulture.Name, 
                                        "True", dateValue.ToString());
   }
}
// The example displays the following output:
//    Culture   Current Culdture   Date
//
//    Calling ToString with a Soecific Culture:
//    en-US     False              9/14/2011 5:32:00 AM
//    fr-FR     True               14/09/2011 05:32:00
//    ru-RU     False              14.09.2011 5:32:00
//
//    Calling the parameterless version of ToString:
//    fr-FR     True               14/09/2011 05:32:00     

Formatting Numeric Values for a Specific Culture

All integer and floating-point data types have methods that perform culture-sensitive parsing and formatting operations. Information on numeric formats is provided by the System.Globalization.NumberFormatInfo object, which is returned by the CultureInfo.NumberFormat property. The NumberFormatInfo class includes information about a particular culture's currency symbol, positive and negative signs, thousands separator, decimal separator, and the format of ordinary numeric values, currency values, and percentages.

The following example displays a Decimal value by passing the standard currency format specifier ("c") to the Decimal.ToString(String) method. It then displays a Decimal value by passing the standard currency format specifier and a CultureInfo object for three different cultures to the ToString method. In this example, Russian (Russia), which is designated as "ru-RU", is the system's current culture. The example illustrates that the default overload of the ToString() method is culture-sensitive, because its output is identical to the output of a ToString method that specifies the "ru-RU" culture.

Imports System.Globalization

Public Module Example
   Public Sub Demo(outputBlock As System.Windows.Controls.TextBlock)
      outputBlock.FontFamily = New FontFamily("Courier New")

      Dim cultureNames() As String = { "en-US", "fr-FR", "ru-RU" }
      Dim value As Decimal = 192431.71d
      outputBlock.Text += String.Format("{0,-7} {1,-15} {2}", "Culture", _
                                        "Value", "Current Culture") + vbCrLf + vbCrLf

      ' Display value using ToString with format specifier only.
      outputBlock.Text += "Calling ToString with a Format Specifier Only:" + vbCrLF
      outputBlock.Text += String.Format("{0,-7} {1,-15} {2}", CultureInfo.CurrentCulture.Name, _
                                        value.ToString("C"), "True") + vbCrLf + vbCrLf

      ' Display value using each of three cultures.
      outputBlock.Text += "Calling ToString with a Specific Culture:" + vbCrLf
      For Each cultureName As String In cultureNames
         Dim ci As New CultureInfo(cultureName)
         outputBlock.Text += String.Format("{0,-7} {1,-15} {2}", ci.Name, _
                                           value.ToString("C", ci), _
                                           IIf(ci.Equals(CultureInfo.CurrentCulture), _
                                               Boolean.TrueString, Boolean.FalseString)) + vbCrLf
      Next
      outputBlock.Text += vbCrLf
   End Sub
End Module
' The example displays the following output:
'       Culture Value           Current Culture
'       
'       Calling ToString with a Format Specifier Only:
'       ru-RU   192 431,71р.    True
'       
'       Calling ToString with a Specific Culture:
'       en-US   $192,431.71     False
'       fr-FR   192 431,71 €    False
'       ru-RU   192 431,71р.    True
using System;
using System.Globalization;
using System.Windows.Media;

public class Example
{
   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {
      outputBlock.FontFamily = new FontFamily("Courier New");

      string[] cultureNames = { "en-US", "fr-FR", "ru-RU" };
      decimal value = 192431.71m;
      outputBlock.Text += String.Format("{0,-7} {1,-15} {2}\n\n", "Culture", 
                                        "Value", "Current Culture");

      // Display value using ToString with format specifier only.
      outputBlock.Text += "Calling ToString with a Format Specifier Only:\n";
      outputBlock.Text += String.Format("{0,-7} {1,-15} {2}\n\n", CultureInfo.CurrentCulture.Name, 
                                        value.ToString("C"), "True");

      // Display value using each of three cultures.
      outputBlock.Text += "Calling ToString with a Specific Culture:\n";
      foreach (string cultureName in cultureNames)
      {
         CultureInfo ci = new CultureInfo(cultureName);
         outputBlock.Text += String.Format("{0,-7} {1,-15} {2}\n", ci.Name,
                                           value.ToString("C", ci),  
                                           ci.Equals(CultureInfo.CurrentCulture) ?
                                               Boolean.TrueString : Boolean.FalseString); 
      }
      outputBlock.Text += "\n";
   }
}
// The example displays the following output:
//       Culture Value           Current Culture
//       
//       Calling ToString with a Format Specifier Only:
//       ru-RU   192 431,71р.    True
//       
//       Calling ToString with a Specific Culture:
//       en-US   $192,431.71     False
//       fr-FR   192 431,71 €    False
//       ru-RU   192 431,71р.    True