System.Globalization.CultureInfo.CurrentCulture property

This article provides supplementary remarks to the reference documentation for this API.

The CultureInfo object that's returned by the CurrentCulture property and its associated objects determines the default format for dates, times, numbers, and currency values, the sorting order of text, casing conventions, and string comparisons.

The current culture is a property of the executing thread. When you set this property to a CultureInfo object that represents a new culture, the value of the Thread.CurrentThread.CurrentCulture property also changes. However, we recommend that you always use the CultureInfo.CurrentCulture property to retrieve and set the current culture.

The CultureInfo object that this property returns is read-only. That means you can't mutate the existing object, for example, by changing the DateTimeFormat. To change the date-time format or some other aspect of the current culture, create a new CultureInfo object and assign it to the property.

How a thread's culture is determined

When a thread is started, its culture is initially determined as follows:

  • By retrieving the culture that is specified by the DefaultThreadCurrentCulture property in the application domain in which the thread is executing, if the property value is not null.

  • If the thread is a thread pool thread that is executing a task-based asynchronous operation, its culture is determined by the culture of the calling thread. The following example changes the current culture to Portuguese (Brazil) and launches six tasks, each of which displays its thread ID, its task ID, and its current culture. Each of the tasks (and the threads) has inherited the culture of the calling thread.

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Runtime.Versioning;
    using System.Threading;
    using System.Threading.Tasks;
    
    public class Example14
    {
        public static async Task Main()
        {
            var tasks = new List<Task>();
            Console.WriteLine("The current culture is {0}",
                              Thread.CurrentThread.CurrentCulture.Name);
            Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR");
            // Change the current culture to Portuguese (Brazil).
            Console.WriteLine("Current culture changed to {0}",
                              Thread.CurrentThread.CurrentCulture.Name);
            Console.WriteLine("Application thread is thread {0}",
                              Thread.CurrentThread.ManagedThreadId);
            // Launch six tasks and display their current culture.
            for (int ctr = 0; ctr <= 5; ctr++)
                tasks.Add(Task.Run(() =>
                {
                    Console.WriteLine("Culture of task {0} on thread {1} is {2}",
                                      Task.CurrentId,
                                      Thread.CurrentThread.ManagedThreadId,
                                      Thread.CurrentThread.CurrentCulture.Name);
                }));
    
            await Task.WhenAll(tasks.ToArray());
        }
    }
    // The example displays output like the following:
    //     The current culture is en-US
    //     Current culture changed to pt-BR
    //     Application thread is thread 9
    //     Culture of task 2 on thread 11 is pt-BR
    //     Culture of task 1 on thread 10 is pt-BR
    //     Culture of task 3 on thread 11 is pt-BR
    //     Culture of task 5 on thread 11 is pt-BR
    //     Culture of task 6 on thread 11 is pt-BR
    //     Culture of task 4 on thread 10 is pt-BR
    
    Imports System.Globalization
    Imports System.Threading
    
    Module Example1
        Public Sub S1()
            Dim tasks As New List(Of Task)
            Console.WriteLine("The current culture is {0}",
                            Thread.CurrentThread.CurrentCulture.Name)
            Thread.CurrentThread.CurrentCulture = New CultureInfo("pt-BR")
            ' Change the current culture to Portuguese (Brazil).
            Console.WriteLine("Current culture changed to {0}",
                            Thread.CurrentThread.CurrentCulture.Name)
            Console.WriteLine("Application thread is thread {0}",
                            Thread.CurrentThread.ManagedThreadId)
            ' Launch six tasks and display their current culture.
            For ctr As Integer = 0 To 5
                tasks.Add(Task.Run(Sub()
                                       Console.WriteLine("Culture of task {0} on thread {1} is {2}",
                                                     Task.CurrentId,
                                                     Thread.CurrentThread.ManagedThreadId,
                                                     Thread.CurrentThread.CurrentCulture.Name)
                                   End Sub))
            Next
            Task.WaitAll(tasks.ToArray())
        End Sub
    End Module
    ' The example displays output like the following:
    '     The current culture is en-US
    '     Current culture changed to pt-BR
    '     Application thread is thread 9
    '     Culture of task 2 on thread 11 is pt-BR
    '     Culture of task 1 on thread 10 is pt-BR
    '     Culture of task 3 on thread 11 is pt-BR
    '     Culture of task 5 on thread 11 is pt-BR
    '     Culture of task 6 on thread 11 is pt-BR
    '     Culture of task 4 on thread 10 is pt-BR
    

    For more information, see Culture and task-based asynchronous operations.

  • By calling the GetUserDefaultLocaleName function on Windows or the uloc_getDefault function from ICU, which currently calls the POSIX setlocale function with category LC_MESSAGES, on Unix-like systems.

Note that if you set a specific culture that is different from the system-installed culture or the user's preferred culture, and your application starts multiple threads, the current culture of those threads will be the culture that is returned by the GetUserDefaultLocaleName function, unless you assign a culture to the DefaultThreadCurrentCulture property in the application domain in which the thread is executing.

For more information about how the culture of a thread is determined, see the "Culture and threads" section in the CultureInfo reference page.

Get the current culture

The CultureInfo.CurrentCulture property is a per-thread setting; that is, each thread can have its own culture. You get the culture of the current thread by retrieving the value of the CultureInfo.CurrentCulture property, as the following example illustrates.

using System;
using System.Globalization;

public class Example5
{
   public static void Main()
   {
      CultureInfo culture = CultureInfo.CurrentCulture;
      Console.WriteLine("The current culture is {0} [{1}]",
                        culture.NativeName, culture.Name);
   }
}
// The example displays output like the following:
//       The current culture is English (United States) [en-US]
Imports System.Globalization

Module Example3
    Public Sub S1()
        Dim culture As CultureInfo = CultureInfo.CurrentCulture
        Console.WriteLine("The current culture is {0} [{1}]",
                        culture.NativeName, culture.Name)
    End Sub
End Module
' The example displays output like the following:
'     The current culture is English (United States) [en-US]

Set the CurrentCulture property explicitly

To change the culture that's used by an existing thread, you set the CultureInfo.CurrentCulture property to the new culture. If you explicitly change a thread's culture in this way, that change persists if the thread crosses application domain boundaries. The following example changes the current thread culture to Dutch (Netherlands). It also shows that, when the current thread crosses application domain boundaries, its current culture remains changed.

using System;
using System.Globalization;
using System.Threading;

public class Info11 : MarshalByRefObject
{
    public void ShowCurrentCulture()
    {
        Console.WriteLine("Culture of {0} in application domain {1}: {2}",
                          Thread.CurrentThread.Name,
                          AppDomain.CurrentDomain.FriendlyName,
                          CultureInfo.CurrentCulture.Name);
    }
}

public class Example11
{
    public static void Main()
    {
        Info11 inf = new Info11();
        // Set the current culture to Dutch (Netherlands).
        Thread.CurrentThread.Name = "MainThread";
        CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("nl-NL");
        inf.ShowCurrentCulture();

        // Create a new application domain.
        AppDomain ad = AppDomain.CreateDomain("Domain2");
        Info11 inf2 = (Info11)ad.CreateInstanceAndUnwrap(typeof(Info11).Assembly.FullName, "Info11");
        inf2.ShowCurrentCulture();
    }
}
// The example displays the following output:
//       Culture of MainThread in application domain ChangeCulture1.exe: nl-NL
//       Culture of MainThread in application domain Domain2: nl-NL
Imports System.Globalization
Imports System.Threading

Public Class Info : Inherits MarshalByRefObject
   Public Sub ShowCurrentCulture()
      Console.WriteLine("Culture of {0} in application domain {1}: {2}",
                        Thread.CurrentThread.Name,
                        AppDomain.CurrentDomain.FriendlyName,
                        CultureInfo.CurrentCulture.Name)
   End Sub
End Class

Module Example2
    Public Sub S1()
        Dim inf As New Info()
        ' Set the current culture to Dutch (Netherlands).
        Thread.CurrentThread.Name = "MainThread"
        CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("nl-NL")
        inf.ShowCurrentCulture()

        ' Create a new application domain.
        Dim ad As AppDomain = AppDomain.CreateDomain("Domain2")
        Dim inf2 As Info = CType(ad.CreateInstanceAndUnwrap(GetType(Info).Assembly.FullName, "Info"),
                          Info)
        inf2.ShowCurrentCulture()
    End Sub
End Module
' This example displays the following output:
'       Culture of MainThread in application domain Example.exe: nl-NL
'       Culture of MainThread in application domain Domain2: nl-NL

Note

Changing the culture by using the CultureInfo.CurrentCulture property requires a SecurityPermission permission with the ControlThread value set. Manipulating threads is dangerous because of the security state associated with threads. Therefore, this permission should be given only to trustworthy code, and then only as necessary. You cannot change thread culture in semi-trusted code.

Starting with .NET Framework 4, you can explicitly change the current thread culture to either a specific culture (such as French (Canada)) or a neutral culture (such as French). When a CultureInfo object represents a neutral culture, the values of CultureInfo properties such as Calendar, CompareInfo, DateTimeFormat, NumberFormat, and TextInfo reflect the specific culture that is associated with the neutral culture. For example, the dominant culture for the English neutral culture is English (United States); the dominant culture for the German culture is German (Germany). The following example illustrates the difference in formatting when the current culture is set to a specific culture, French (Canada), and a neutral culture, French.

using System;
using System.Globalization;
using System.Threading;

public class Example12
{
   public static void Main()
   {
      double value = 1634.92;
      CultureInfo.CurrentCulture = new CultureInfo("fr-CA");
      Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name);
      Console.WriteLine("{0:C2}\n", value);

      Thread.CurrentThread.CurrentCulture = new CultureInfo("fr");
      Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name);
      Console.WriteLine("{0:C2}", value);
   }
}
// The example displays the following output:
//       Current Culture: fr-CA
//       1 634,92 $
//
//       Current Culture: fr
//       1 634,92 €
Imports System.Globalization
Imports System.Threading

Module Example4
    Public Sub S1()
        Dim value As Double = 1634.92
        CultureInfo.CurrentCulture = New CultureInfo("fr-CA")
        Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name)
        Console.WriteLine("{0:C2}", value)
        Console.WriteLine()

        Thread.CurrentThread.CurrentCulture = New CultureInfo("fr")
        Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name)
        Console.WriteLine("{0:C2}", value)
    End Sub
End Module
' The example displays the following output:
'       Current Culture: fr-CA
'       1 634,92 $
'       
'       Current Culture: fr
'       1 634,92 €

You can also use the CultureInfo.CurrentCulture property along with the HttpRequest.UserLanguages property to set the CurrentCulture property of an ASP.NET application to the user's preferred culture, as the following example illustrates.

CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(Request13.UserLanguages[0]);
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Request.UserLanguages(0))

The current culture and user overrides

Windows allows users to override the standard property values of the CultureInfo object and its associated objects by using Regional and Language Options in Control Panel. The CultureInfo object returned by the CurrentCulture property reflects these user overrides in the following cases:

  • If the current thread culture is set implicitly by the Windows GetUserDefaultLocaleName function.

  • If the current thread culture defined by the DefaultThreadCurrentCulture property corresponds to the current Windows system culture.

  • If the current thread culture is set explicitly to a culture returned by the CreateSpecificCulture method, and that culture corresponds to the current Windows system culture.

  • If the current thread culture is set explicitly to a culture instantiated by the CultureInfo(String) constructor, and that culture corresponds to the current Windows system culture.

In some cases, particularly for server applications, setting the current culture to a CultureInfo object that reflects user overrides may be undesirable. Instead, you can set the current culture to a CultureInfo object that does not reflect user overrides in the following ways:

The current culture and UWP apps

In Universal Windows Platform (UWP) apps, the CurrentCulture property is read-write, just as it is in .NET Framework and .NET Core apps; you can use it both to get and to set the current culture. However, UWP apps do not distinguish between the current culture and the current UI culture. The CurrentCulture and CurrentUICulture properties map to the first value in the Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages collection.

In .NET Framework and .NET Core apps, the current culture is a per-thread setting, and the CurrentCulture property reflects the culture of the current thread only. In UWP apps, the current culture maps to the Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages property, which is a global setting. Setting the CurrentCulture property changes the culture of the entire app; culture cannot be set on a per-thread basis.