C# CultureInfo
last modified January 19, 2024
In this article we show how to globalize appications in C# with CultureInfo.
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.
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.
using System.Globalization; 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
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.
using System.Globalization; 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.
using System.Globalization; using static System.Globalization.CultureTypes; Console.WriteLine($".NET version: {Environment.Version}"); 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 .NET version: 8.0.1 593 specific cultures in .NET 276 neutral cultures in .NET
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.
using System.Globalization; CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); DateTime[] dates = [ new (2019, 10, 9), new (2020, 1, 2) ]; using var sw = new StreamWriter(@"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 dates.dat 10/09/2019|01/02/2020
This are the file contents.
using System.Globalization; using var sr = new StreamReader("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
C# CultureInfo sorting
Sorting strings is culture specific. Setting the correct culture for the language will do the correct sorting.
using System.Globalization; Console.OutputEncoding = System.Text.Encoding.UTF8; CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("sk-SK"); List<string> words = [ "č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.
List<string> words = [ "č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
In the Slovak language, the č letter goes after the c letter. English sorting would not make a difference between these two letters.
NumberFormatInfo
The NumberFormatInfo
provides culture-specific information for
formatting and parsing numeric values.
using System.Globalization; Console.OutputEncoding = Encoding.UTF8; CultureInfo sci = new("sk-SK"); NumberFormatInfo nfi = sci.NumberFormat; Console.WriteLine(nfi.CurrencyDecimalDigits); Console.WriteLine(nfi.CurrencyDecimalSeparator); Console.WriteLine(nfi.CurrencySymbol); Console.WriteLine(nfi.PercentSymbol); Console.WriteLine(nfi.PerMilleSymbol); Console.WriteLine(nfi.NumberDecimalSeparator); Console.WriteLine(nfi.NumberGroupSeparator);
The example shows number format information for the Slovak culture including currency decimal separator, percent symbol, and number group separator.
NumberFormatInfo nfi = sci.NumberFormat;
The NumberFormatInfo
is retrived from the NumberFormat
property of the CultureInfo
object.
$ dotnet run 2 , € % ‰ ,
C# CultureInfo percentage
There are two different characters that are used for a percent sign. The percent sign might have a space and can be written before or after the value. Also, the default number of decimal digits differ.
using System.Globalization; Console.OutputEncoding = Encoding.UTF8; double v = 0.68; var trCi = new CultureInfo("tr"); CultureInfo.DefaultThreadCurrentCulture = trCi; Console.WriteLine(trCi.NumberFormat.PercentDecimalDigits); Console.WriteLine(v.ToString("P")); Console.WriteLine("-------------------------"); var skCi = new CultureInfo("sk-SK"); CultureInfo.DefaultThreadCurrentCulture = skCi; Console.WriteLine(skCi.NumberFormat.PercentDecimalDigits); Console.WriteLine(v.ToString("P")); Console.WriteLine("-------------------------"); var peCi = new CultureInfo("fa-IR"); CultureInfo.DefaultThreadCurrentCulture = peCi; Console.WriteLine(peCi.NumberFormat.PercentDecimalDigits); Console.WriteLine(v.ToString("P"));
The example displays percentages in Turkish, Slovak, and Persian cultures.
Console.WriteLine(trCi.NumberFormat.PercentDecimalDigits);
The NumberFormat's
PercentDecimalDigits
returns the
number of decimal places used in percent values.
Console.WriteLine(v.ToString("P"));
The P
specifier shows a number multiplied by 100 and displayed with
a percent symbol.
$ dotnet run 3 %68,000 ------------------------- 2 68,00 % ------------------------- 3 68٫000٪
C# CultureInfo decimal separator
Cultures use decimal point (Israel, Japan, UK) or comma (Slovakia, France, Germany) as decimal separators. Persian uses a forward slash (/).
using System.Globalization; Console.OutputEncoding = System.Text.Encoding.UTF8; decimal val = 1278.112m; 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
C# CultureInfo thousands separator
Cultures use different ways to group digits with a delimiter for ease of reading.
using System.Globalization; 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,000 12,156,320.000 12’156’320.000 1,21,56,320.000 12.156.320,000
C# CultureInfo currency
Cultures use different currency symbols. The symbol can be prepended or appended to the currency value.
using System.Globalization; Console.OutputEncoding = System.Text.Encoding.UTF8; decimal val = 12_156_320.54m; 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 NGN ₱12,156,320.54 ¥12,156,320.54 $12,156,320.54
CultureInfo Calendar
A calendar is a system of organizing datetime units. Cultures use different calendars. Some cultures can use multiple calendars.
using System.Globalization; Console.OutputEncoding = System.Text.Encoding.UTF8; var perCi = new CultureInfo("fa-IR"); Console.WriteLine($"Default calendar: {perCi.Calendar}"); DateTime now = DateTime.Now; foreach (var oc in perCi.OptionalCalendars) { perCi.DateTimeFormat.Calendar = oc; Console.WriteLine($"{now.ToString("F", perCi)}"); }
Persian culture uses PersianCalendar as the default one and GregorianCalendar and HijriCalendar as optional calendars. We display the current datetime in all supported Persian calendars.
var perCi = new CultureInfo("fa-IR");
We create a Persian CultureInfo
.
DateTime now = DateTime.Now;
We get the current datetime value.
foreach (var oc in perCi.OptionalCalendars) { perCi.DateTimeFormat.Calendar = oc; Console.WriteLine($"{now.ToString("F", perCi)}"); }
We go through the array of supported calendars. We set the
DateTimeFormat.Calendar
to the currently selected calendar and
print the datetime.
$ dotnet run Default calendar: System.Globalization.PersianCalendar 1402 دی 29, جمعه 22:31:07 2024 ژانویهٔ 19, جمعه 22:31:07 1445 رجب 9, جمعه 22:31:07
C# CultureInfo first day of week
The first day of the week in cultures is Sunday, Monday, or Saturday.
using System.Globalization; 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
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.
using System.Globalization; 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
C# CultureInfo day names
The CultureInfo.DateTimeFormat.DayNames
gets an array that contains
the culture-specific full names of the days of the week.
using System.Globalization; 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
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
.
using System.Globalization; 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.
C# CultureInfo datetime formats
Cultures use different datetime formats.
using System.Globalization; 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 piatok 19. januára 2024 22:32:19 dddd d. MMMM yyyy piatok 19. januára 2024 H:mm 22:32
Source
CultureInfo class - language reference
In this article we have worked with C# CultureInfo
, which is used
to globalize C# applications.
Author
List all C# tutorials.