Ebooks

C# CultureInfo tutorial

C# CultureInfo tutorial shows how to globalize appications in C# with CultureInfo. C# tutorial is a comprehensive tutorial on C# language.

Globalization is the process of designing the application in such a way that it can be used by users from across the globe (for multiple cultures). Localization is the process of customizing the application to a specific culture.

Note: These terms may have different meanings in other programming languages or platforms.

Types of cultures

Neutral culture is a culture that is associated with a language but not with a country or region. Specific culture is a culture that is associated with both a language and a country or region. For example, fr is the name for the neutral French culture, while fr-FR is the name for the French culture in France.

Invariant culture is culture-insensitive; it is associated with the English language (for historical reasons) but not with any country/region. We specify the invariant culture by name by using an empty string ("") in the call to a CultureInfo instantiation method. CultureInfo.InvariantCulture also retrieves an instance of the invariant culture. Invariant culture is used for storing strings from a variety of cultures in a way where they are not tied to any language or culture. For instance, we can use invariant culture when persisting dates and times.

C# CultureInfo

CultureInfo provides information about a specific culture. The information includes the names for the culture, the writing system, the calendar used, the sort order of strings, and formatting for dates and numbers.

using System.Globalization;

The CultureInfo is part of the System.Globalization namespace.

C# current culture

The CultureInfo.DefaultThreadCurrentCulture property gets or sets the default culture for threads in the current application domain.

Program.cs
using System;
using System.Globalization;

namespace CurrentCulture
{
    class Program
    {
        static void Main(string[] args)
        {
            double val = 1235.56;

            Console.WriteLine($"Current culture: {CultureInfo.CurrentCulture.Name}");
            Console.WriteLine(val);

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-DE");

            Console.WriteLine($"Current culture: {CultureInfo.CurrentCulture.Name}");
            Console.WriteLine(val);
        }
    }
}

The example prints a value in two cultures.

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-DE");

We set the default culture to de-DE.

$ dotnet run
Current culture: en-US
1235.56
Current culture: de-DE
1235,56

This is the output. The two values have different decimal separators.

C# list cultures

The CultureInfo.GetCultures() gets the list of supported cultures filtered by the specified culture type parameter.

Program.cs
using System;
using System.Globalization;

namespace ListCultures
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            Console.WriteLine("{0,-15}{0,-5}{0,-45}{0,-40}", "Culture", "ISO", 
                "Display name", "English Name");

            foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.AllCultures))
            {
                Console.Write("{0,-15}", ci.Name);
                Console.Write("{0,-5}", ci.TwoLetterISOLanguageName);
                Console.Write("{0,-45}", ci.DisplayName);
                Console.WriteLine("{0,-40}", ci.EnglishName);
            }
        }
    }
}

The example lists all installed .NET cultures.

Console.OutputEncoding = System.Text.Encoding.UTF8;

To be able to show various display names of cultures, we set the output encoding to UTF8. In addition, the terminal must have a font that is able to display all these languages.

With the CultureTypes.SpecificCultures filter parameter, we get all specific cultures. With CultureTypes.NeutralCultures, we get all neutral cultures.

Program.cs
using System;
using System;
using System.Globalization;
using static System.Globalization.CultureTypes;

namespace Cultures
{
    class Program
    {
        static void Main(string[] args)
        {
            CultureInfo[] specificCultures = CultureInfo.GetCultures(SpecificCultures);
            Console.WriteLine($"{specificCultures.Length} specific cultures in .NET");

            CultureInfo[] neutralCultures = CultureInfo.GetCultures(NeutralCultures);
            Console.WriteLine($"{neutralCultures.Length} neutral cultures in .NET");
        }
    }
}

The example prints the number of specific and neutral cultures in .NET.

$ dotnet run
569 specific cultures in .NET
279 neutral cultures in .NET

This is the output.

C# invariant culture

Invariant culture is culture independent. We use it when we persist culture information, such as dates. Saving dates in culture-independent way allows us to parse the values later easily.

Program.cs
using System;
using System.IO;
using System.Globalization;

namespace InvariantCulture
{
    class Program
    {
        static void Main(string[] args)
        {
            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");

            DateTime[] dates = {
                new DateTime(2019, 10, 9),
                new DateTime(2020, 1, 2)
            };

            using var sw = new StreamWriter(@"C:\Users\Jano\Documents\tmp\dates.dat");
            sw.Write(String.Format(CultureInfo.InvariantCulture,
                "{0:d}|{1:d}", dates[0], dates[1]));
        }
    }
}

The example writes two dates with CultureInfo.InvariantCulture format.

sw.Write(String.Format(CultureInfo.InvariantCulture,
    "{0:d}|{1:d}", dates[0], dates[1]));

We pass the CultureInfo.InvariantCulture to the String.Format() method.

$ cat C:\Users\Jano\Documents\tmp\dates.dat
10/09/2019|01/02/2020

This are the file contents.

Program.cs
using System;
using System.IO;
using System.Globalization;

namespace InvariantCulture2
{
    class Program
    {
        static void Main(string[] args)
        {
            using var sr = new StreamReader(@"C:\Users\Jano\Documents\tmp\dates.dat");
            string contents = sr.ReadToEnd();
            string[] dateStrings = contents.Split('|');

            Console.WriteLine($"Current Culture: {CultureInfo.CurrentCulture.Name}");

            foreach (var dateStr in dateStrings)
            {
                DateTime dateVal;
                if (DateTime.TryParse(dateStr, CultureInfo.InvariantCulture,
                                      DateTimeStyles.None, out dateVal))
                {
                    Console.WriteLine("The date is {0:D}", dateVal);
                } else
                {
                    Console.WriteLine("ERROR: Unable to parse {0}", dateStr);
                }
            }

            Console.WriteLine();

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("sk-SK");
            Console.WriteLine($"Current Culture: {CultureInfo.CurrentCulture.Name}");

            foreach (var dateStr in dateStrings)
            {
                DateTime dateVal;
                if (DateTime.TryParse(dateStr, CultureInfo.InvariantCulture,
                                      DateTimeStyles.None, out dateVal))
                {
                    Console.WriteLine("Dátum je {0:D}", dateVal);
                } else
                {
                    Console.WriteLine("ERROR: Unable to parse {0}", dateStr);
                }
            }
        }
    }
}

In the example, we restore the data and display the dates in two different cultures.

if (DateTime.TryParse(dateStr, CultureInfo.InvariantCulture,
                      DateTimeStyles.None, out dateVal))
{ 
...

We pass the CultureInfo.InvariantCulture as the second paramter of the TryParse() method.

$ dotnet run
Current Culture: en-US
The date is Wednesday, October 9, 2019
The date is Thursday, January 2, 2020

Current Culture: sk-SK
Dátum je streda 9. októbra 2019
Dátum je štvrtok 2. januára 2020

This is the output.

C# CultureInfo sorting

Sorting strings is culture specific. Setting the correct culture for the language will do the correct sorting.

Program.cs
using System;
using System.Globalization;
using System.Collections.Generic;

namespace Sorting
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;
            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("sk-SK");

            var words = new List<string> { "čaj", "auto", "drevo", "cibuľa", 
                    "čučoriedka", "banán", "čerešňa", "červený", "čierny", "cesnak" };

            words.Sort();

            foreach (var word in words)
            {
                Console.WriteLine(word);
            }
        }
    }
}

The example has a list of Slovak words. Setting the correct culture will sort the words according to the rules of the Slovak language.

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("sk-SK");

We set the Slovak culture.

var words = new List<string> { "čaj", "auto", "drevo", "cibuľa", 
        "čučoriedka", "banán", "čerešňa", "červený", "čierny", "cesnak" };

We have a list of Slovak words.

words.Sort();

We sort the words. The Sort() method takes the culture into account when sorting the data.

$ dotnet run
auto
banán 
cesnak
cibuľa
čaj
čerešňa
červený
čierny
čučoriedka
drevo

This is the output. In the Slovak language, the č letter goes after the c letter. English sorting would not make a difference between these two letters.

C# CultureInfo decimal separator

Cultures use decimal point (Israel, Japan, UK) or comma (Slovakia, France, Germany) as decimal separators. Persian uses a forward slash (/).

Program.cs
using System;
using System.Globalization;

namespace DecimalSeparator
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            double val = 1278.112;

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("sk-SK");
            Console.WriteLine($"{val}");

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
            Console.WriteLine($"{val}");

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("fa-IR");
            Console.WriteLine($"{val}");
        }
    }
}

The example prints a decimal value in three different cultures.

$ dotnet run
1278,112
1278.112
1278/112

This is the output.

C# CultureInfo thousands separator

Cultures use different ways to group digits with a delimiter for ease of reading.

Program.cs
using System;
using System.Globalization;

namespace ThousandsSeparator
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            int val = 12_156_320;

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("sk-SK");
            Console.WriteLine($"{val:N}");

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
            Console.WriteLine($"{val:N}");

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-CH");
            Console.WriteLine($"{val:N}");

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("hi-IN");
            Console.WriteLine($"{val:N}");

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("es-ES");
            Console.WriteLine($"{val:N}");
        }
    }
}

The example prints a integer value in five different cultures.

$ dotnet run
12 156 320,00
12,156,320.00
12’156’320.00
1,21,56,320.00
12.156.320,00

This is the output.

C# CultureInfo currency

Cultures use different currency symbols. The symbol can be prepended or appended to the currency value.

Program.cs
using System;
using System.Globalization;

namespace CurrencyEx
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            double val = 12_156_320.54;

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("sk-SK");
            Console.WriteLine($"{val:c}");

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("ff-NG");
            Console.WriteLine($"{val:c}");

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("fil-PH");
            Console.WriteLine($"{val:c}");

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("zh-CN");
            Console.WriteLine($"{val:c}");

            CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
            Console.WriteLine($"{val:c}");
        }
    }
}

The example prints currency value in five cultures.

$ dotnet run
12 156 320,54 €
₦ 12,156,320.54
₱12,156,320.54
¥12,156,320.54
$12,156,320.54

This is the output.

C# CultureInfo first day of week

The first day of the week in cultures is Sunday, Monday, or Saturday.

Program.cs
using System;
using System.Globalization;

namespace FirstDayOfWeek
{
    class Program
    {
        static void Main(string[] args)
        {
            var enUs = new CultureInfo("en-US");

            var firstDay = enUs.DateTimeFormat.FirstDayOfWeek.ToString();
            var name = enUs.DisplayName;
            Console.WriteLine($"First day of the week in {name}: {firstDay}");

            var skSk = new CultureInfo("sk-Sk");

            var name2 = skSk.DisplayName;
            var firstDay2 = skSk.DateTimeFormat.FirstDayOfWeek.ToString();
            Console.WriteLine($"First day of the week in {name2}:: {firstDay2}");

            var faIr = new CultureInfo("fa-IR");

            var name3 = faIr.DisplayName;
            var firstDay3 = faIr.DateTimeFormat.FirstDayOfWeek.ToString();
            Console.WriteLine($"First day of the week in {name3}:: {firstDay3}");
        }
    }
}

The example prints the first day of week in three cultures.

$ dotnet run
First day of the week in English (United States): Sunday
First day of the week in Slovak (Slovakia):: Monday
First day of the week in Persian (Iran):: Saturday

This is the output.

C# CultureInfo first week

There are different rules to define the first week of the year in cultures, including first day of the new year or first four or more days in a week.

Program.cs
using System;
using System.Globalization;

namespace FirstWeek
{
    class Program
    {
        static void Main(string[] args)
        {
            var enUs = new CultureInfo("en-US");

            var weekRule = enUs.DateTimeFormat.CalendarWeekRule.ToString();
            Console.WriteLine($"First calendar week starts with: {weekRule}");

            var skSk = new CultureInfo("sk-Sk");

            var weekRule2 = skSk.DateTimeFormat.CalendarWeekRule.ToString();
            Console.WriteLine($"First calendar week starts with: {weekRule2}");
        }
    }
}

The example prints the first week rule for two cultures.

$ dotnet run
First calendar week in English (United States) starts with: FirstDay
First calendar week in Slovak (Slovakia) starts with: FirstFourDayWeek

This is the output.

C# CultureInfo day names

The CultureInfo.DateTimeFormat.DayNames gets an array that contains the culture-specific full names of the days of the week.

Program.cs
using System;
using System.Globalization;

namespace DayNames
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            var enUs = new CultureInfo("en-US");

            foreach (var dayName in enUs.DateTimeFormat.DayNames)
            {
                Console.WriteLine(dayName);
            }

            Console.WriteLine("***************************");

            var skSk = new CultureInfo("sk-SK");

            foreach (var dayName in skSk.DateTimeFormat.DayNames)
            {
                Console.WriteLine(dayName);
            }
        }
    }
}

The example prints the names of the days in en-US and sk-SK cultures.

$ dotnet run
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
***************************
nedeľa
pondelok
utorok
streda
štvrtok
piatok
sobota

This is the output.

C# CultureInfo month names

With the CultureInfo.DateTimeFormat.MonthNames property we get the array of culture-specific full names of the months. Likewise, we get the culture-specific abbreviated names of the months with the CultureInfo.DateTimeFormat.AbbreviatedMonthNames.

Program.cs
using System;
using System.Globalization;

namespace MonthNames
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            var huHu = new CultureInfo("hu-HU");
            var name = huHu.NativeName;

            Console.WriteLine($"{name}: Hónap nevek");

            foreach (var monthName in huHu.DateTimeFormat.MonthNames)
            {
                Console.WriteLine(monthName);
            }

            Console.WriteLine("**********************");

            foreach (var abbMonthName in huHu.DateTimeFormat.AbbreviatedMonthNames)
            {
                Console.WriteLine(abbMonthName);
            }
        }
    }
}

The example prints month names in Hungarian. We print full and abbreviated month names.

$ dotnet run
magyar (Magyarország): Hónap nevek
január
február
március
április
május
június
július
augusztus
szeptember
október
november
december

**********************
jan.
febr.
márc.
ápr.
máj.
jún.
júl.
aug.
szept.
okt.
nov.
dec.

This is the output.

C# CultureInfo datetime formats

Cultures use different datetime formats.

Program.cs
using System;
using System.Globalization;

namespace DateTimeFormats
{
    class Program
    {
        static void Main(string[] args)
        {
            var now = DateTime.Now;

            var skSk = new CultureInfo("sk-SK");
            CultureInfo.DefaultThreadCurrentCulture = skSk;

            Console.WriteLine(skSk.DateTimeFormat.FullDateTimePattern);
            Console.WriteLine(now.ToString(skSk.DateTimeFormat.FullDateTimePattern));

            Console.WriteLine();

            Console.WriteLine(skSk.DateTimeFormat.LongDatePattern);
            Console.WriteLine(now.ToString(skSk.DateTimeFormat.LongDatePattern));

            Console.WriteLine();

            Console.WriteLine(skSk.DateTimeFormat.ShortTimePattern);
            Console.WriteLine(now.ToString(skSk.DateTimeFormat.ShortTimePattern));
        }
    }
}

The example prints today's date in Slovak culture in different formats.

$ dotnet run
dddd d. MMMM yyyy H:mm:ss
pondelok 6. januára 2020 14:28:41

dddd d. MMMM yyyy
pondelok 6. januára 2020

H:mm
14:28

This is a sample output.

In this tutorial, we have worked with C# CultureInfo, which is used to globalize C# applications.

List all C# tutorials.