Using the CultureInfo Class

The CultureInfo class contains culture-specific information, such as the language, country/region, calendar, and cultural conventions associated with a specific culture. This class also provides the information required for performing culture-specific operations, such as casing, formatting dates and numbers, and comparing strings.

The CultureInfo class specifies a unique name for each culture based on the RFC 1766 standard. The name is a combination of a two-letter lowercase culture code associated with a language and, a two-letter uppercase subculture code associated with a country or region. The subculture code follows the culture code, separated by a dash (-). Examples include "ja-JP" for Japanese in Japan, "en-US" for U.S. English, or "de-DE" for German in Germany (as opposed to an alternate such as "de-AT" for German in Austria). In cases where a two-letter language code is not available, the three-letter code derived from ISO 639-2 is used; for example, the three-letter code "div" is used for cultures that use the Dhivehi language. Some culture names have suffixes that specify the script; for example, "-Cyrl" specifies the Cyrillic script, "-Latn" specifies the Latin script.

Throughout this topic, the terms "neutral culture" and "specific culture" are used. A neutral culture is specified by only the two-digit lowercase culture code. For example, "fr" specifies the neutral culture for French, and "de" specifies the neutral culture for German. A specific culture is identified by the culture code followed by the two-digit uppercase subculture code. For example, "fr-FR" specifies French in France and "fr-CA specifies French in Canada.

Note   There are two culture names that contradict this rule. The cultures "zh-CHS" (Simplified Chinese) and "zh-CHT" (Traditional Chinese) are neutral cultures.

For a list of culture names, see the CultureInfo Class.

You can also use the CultureInfo.GetCultures method to return a complete list of all cultures. The following code example displays a list of all cultures.

Imports System
Imports System.Globalization

public class printClass
   Public Shared Sub Main()  
      Dim ci As CultureInfo
      For Each ci in _
      CultureInfo.GetCultures(CultureTypes.AllCultures)
         Console.WriteLine(ci)
      Next ci
   End Sub
End Class
[C#]
using System;
using System.Globalization;

public class printClass
{
   public static void Main()
   {
      foreach (CultureInfo ci in
      CultureInfo.GetCultures(CultureTypes.AllCultures))
      {
         Console.WriteLine(ci);
      }
   }
}

Using CultureInfo with Unmanaged Code

.NET Framework applications can access unmanaged functions in dynamic link libraries using the Platform Invoke service. However, when you pass a CultureInfo object to the Win32 API, GetLocaleInfo, you should be aware that the result returned by GetLocaleInfo is not always consistent with the result returned by the RegionInfo class. A .NET Framework RegionInfo object corresponds to a country/region. To initialize a RegionInfo object using a CultureInfo object, you must specify a CultureInfo object that represents a specific culture, such as Ar-DZ for Arabic in Algeria. An attempt to initialize a RegionInfo object with a CultureInfo object that represents a neutral culture, such as Ar (Arabic), throws an exception. This is because Ar is a neutral culture, associated with only a language. It does not specify the region or country information necessary to map it to a country/region. The GetLocaleInfo method differs from the RegionInfo constructor in that it returns a country/region for a CultureInfo object that represents either a specific culture or a neutral culture. For example, if you pass a CultureInfo object that represents the neutral culture Ar (Arabic) to GetLocaleInfo, the method maps the neutral culture to the default country/region it is associated with. In this case, GetLocaleInfo returns Saudi Arabia. Be careful when using the GetLocaleInfo method, as the default country/region mapping it provides might be culturally inappropriate for your application. To eliminate this discrepancy, use only specific cultures when interoperating with the Win32 API.

The following example demonstrates how the RegionInfo class constructor and the Win32 GetLocaleInfo method can return different values when passed the same CultureInfo object. Note that when the CultureInfo object represents the specific culture Ar-DZ (Arabic in Algeria), both methods return Algeria as the country/region name. However, when the CultureInfo object represents the neutral culture Ar (Arabic), the results differ. The RegionInfo constructor fails to return a country/region while GetLocaleInfo returns Algeria.

Imports System
Imports System.Globalization
Imports System.Runtime.InteropServices
Imports Microsoft.VisualBasic

Namespace CountryRegionName
   Class CountryRegionName
      ' The name of a country or region in English.
      Private LOCALE_SENGCOUNTRY As Integer = &H1002

      ' Use COM interop to call the Win32 API GetLocalInfo.
      Declare Unicode Function GetLocaleInfoW Lib "Kernel32.dll" _
         (Locale As Integer, LCType As Integer,<[In](), _
          MarshalAs(UnmanagedType.LPWStr)> lpLCData As String, _
          cchData As Integer) As Integer
      
      ' A method to retrieve the .NET Framework Country/Region
      ' that maps to the specified CultureInfo.
      Public Function GetNetCountryRegionName(ci As CultureInfo) As String
         ' If the specified CultureInfo represents a specific culture,
         ' the attempt to create a RegionInfo succeeds.
         Try
            Dim ri As New RegionInfo(ci.LCID)
            Return ri.EnglishName
         ' Otherwise, the specified CultureInfo represents a neutral
         'culture, and the attempt to create a RegionInfo fails.
         Catch
            Return String.Empty
         End Try
      End Function
      
      ' A method to retrieve the Win32 API Country/Region
      ' that maps to the specified CultureInfo.
      Public Function GetWinCountryRegionName(ci As CultureInfo) As String
         Dim size As Integer = GetLocaleInfoW(ci.LCID, _
            LOCALE_SENGCOUNTRY, Nothing, 0)
         Dim str As New String(" "c, size)
         Dim err As Integer = GetLocaleInfoW(ci.LCID, _
            LOCALE_SENGCOUNTRY, str, size)
         ' If the string is not empty, GetLocaleInfoW succeeded.
         ' It will succeed regardless of whether ci represents
         ' a neutral or specific culture.
         If err <> 0 Then
            Return str
         Else
            Return String.Empty
         End If
      End Function

      <STAThread()> _
      Public Shared Sub Main(args() As String)
         Dim crn As New CountryRegionName()
         
         ' Create a CultureInfo initialized to the neutral Arabic culture.
         Dim ci1 As New CultureInfo(&H1)
         Console.WriteLine(ControlChars.NewLine + _
            "The .NET Region name: {0}", _
            crn.GetNetCountryRegionName(ci1))
         Console.WriteLine("The Win32 Region name: {0}", _
            crn.GetWinCountryRegionName(ci1))
         
         ' Create a CultureInfo initialized to the specific 
         ' culture Arabic in Algeria.
         Dim ci2 As New CultureInfo(&H1401)
         Console.WriteLine(ControlChars.NewLine + _
            "The .NET Region name: {0}", _
            crn.GetNetCountryRegionName(ci2))
         Console.WriteLine("The Win32 Region name: {0}", _
            crn.GetWinCountryRegionName(ci2))
      End Sub
   End Class
End Namespace
[C#]
using System;
using System.Globalization;
using System.Runtime.InteropServices;

namespace CountryRegionName
{
  class CountryRegionName
  {
    // The name of a country or region in English
    int LOCALE_SENGCOUNTRY     = 0x1002;

    // Use COM interop to call the Win32 API GetLocalInfo.
    [DllImport("kernel32.dll", CharSet=CharSet.Unicode)]
    public static extern int GetLocaleInfo(
       // The locale identifier.
       int Locale,
       // The information type.
       int LCType,
       // The buffer size.
       [In, MarshalAs(UnmanagedType.LPWStr)] string lpLCData,int cchData
     );

    // A method to retrieve the .NET Framework Country/Region
    // that maps to the specified CultureInfo.
    public String GetNetCountryRegionName(CultureInfo ci)
    {
      // If the specified CultureInfo represents a specific culture,
      // the attempt to create a RegionInfo succeeds.
      try
      {
        RegionInfo ri = new RegionInfo(ci.LCID);
        return ri.EnglishName;
      }
      // Otherwise, the specified CultureInfo represents a neutral
      // culture, and the attempt to create a RegionInfo fails.
      catch
      {
        return String.Empty;
      }
    }

    // A method to retrieve the Win32 API Country/Region
    // that maps to the specified CultureInfo.
    public String GetWinCountryRegionName(CultureInfo ci)
    {
      int size = GetLocaleInfo(ci.LCID, LOCALE_SENGCOUNTRY, null, 0);
      String str = new String(' ', size);
      int err  = GetLocaleInfo(ci.LCID, LOCALE_SENGCOUNTRY, str, size);
      // If the string is not empty, GetLocaleInfo succeeded.
      // It will succeed regardless of whether ci represents
      // a neutral or specific culture.
      if(err != 0)  
        return str;
      else
        return String.Empty;
    }

    [STAThread]
    static void Main(string[] args)
    {
      CountryRegionName crn = new CountryRegionName();

      // Create a CultureInfo initialized to the neutral Arabic culture.
      CultureInfo ci1 = new CultureInfo(0x1);  
      Console.WriteLine("\nThe .NET Region name: {0}", 
         crn.GetNetCountryRegionName(ci1));
      Console.WriteLine("The Win32 Region name: {0}",
         crn.GetWinCountryRegionName(ci1));

      // Create a CultureInfo initialized to the specific 
      // culture Arabic in Algeria.
      CultureInfo ci2 = new CultureInfo(0x1401);  
      Console.WriteLine("\nThe .NET Region name: {0}", 
         crn.GetNetCountryRegionName(ci2));
      Console.WriteLine("The Win32 Region name: 
         {0}",crn.GetWinCountryRegionName(ci2));
    }
   }
}

This code produces the following output:

The .NET Region name:
The Win32 Region name: Saudi Arabia

The .NET Region name: Algeria
The Win32 Region name: Algeria

See Also

Developing World-Ready Applications | CultureInfo Class | Using the CurrentUICulture Property | Using the CurrentCulture Property | Using the InvariantCulture Property