ZetCode

C# CultureInfo

上次修改时间:2024 年 1 月 19 日

在本文中,我们将展示如何使用 C# 中的 CultureInfo 实现应用程序的全球化。

全球化是指以一种可以被来自全球各地的用户(针对多种文化)使用的方式来设计应用程序的过程。本地化是指根据特定文化自定义应用程序的过程。

注意: 这些术语在其他编程语言或平台中可能具有不同的含义。

文化的类型

非特定区域性是指与一种语言相关联但不与国家或地区相关联的区域性。特定区域性是指与一种语言和一个国家或地区相关联的区域性。例如,fr 是法语非特定区域性的名称,而 fr-FR 是法国法语区域性的名称。

固定区域性是指不区分区域性的区域性;它与英语(由于历史原因)相关联,但不与任何国家/地区相关联。我们通过在对 CultureInfo 实例化方法的调用中使用空字符串 ("") 按名称指定固定区域性。

CultureInfo.InvariantCulture 还会检索固定区域性的实例。固定区域性用于以一种不与任何语言或文化相关联的方式存储来自各种文化的字符串。例如,我们可以在持久化日期和时间时使用固定区域性。

C# CultureInfo

CultureInfo 提供有关特定区域性的信息。该信息包括区域性的名称、书写系统、使用的日历、字符串的排序顺序以及日期和数字的格式。

using System.Globalization;

CultureInfoSystem.Globalization 命名空间的一部分。

C# 当前区域性

CultureInfo.DefaultThreadCurrentCulture 属性获取或设置当前应用程序域中线程的默认区域性。

Program.cs
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);

该示例以两种区域性打印一个值。

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

我们将默认区域性设置为 de-DE

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

这两个值具有不同的十进制分隔符。

C# 列出区域性

CultureInfo.GetCultures 获取由指定的区域性类型参数过滤的受支持区域性的列表。

Program.cs
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);
}

该示例列出了所有已安装的 .NET 区域性。

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

为了能够显示各种区域性的显示名称,我们将输出编码设置为 UTF8。此外,终端必须具有能够显示所有这些语言的字体。

使用 CultureTypes.SpecificCultures 过滤器参数,我们可以获取所有特定区域性。使用 CultureTypes.NeutralCultures,我们可以获取所有非特定区域性。

Program.cs
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");

该示例打印 .NET 中特定区域性和非特定区域性的数量。

$ dotnet run
.NET version: 8.0.1
593 specific cultures in .NET
276 neutral cultures in .NET

C# 固定区域性

固定区域性是独立于区域性的。我们在持久化区域性信息(例如日期)时使用它。以独立于区域性的方式保存日期使我们以后可以轻松解析这些值。

Program.cs
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]));

该示例使用 CultureInfo.InvariantCulture 格式写入两个日期。

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

我们将 CultureInfo.InvariantCulture 传递给 String.Format 方法。

$ cat dates.dat
10/09/2019|01/02/2020

这些是文件内容。

Program.cs
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);
    }
}

在该示例中,我们恢复数据并在两种不同的区域性中显示日期。

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

我们将 CultureInfo.InvariantCulture 作为 TryParse 方法的第二个参数传递。

$ 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 排序

字符串排序是特定于区域性的。为语言设置正确的区域性将进行正确的排序。

Program.cs
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);
}

该示例有一个斯洛伐克语单词列表。设置正确的区域性将根据斯洛伐克语的规则对单词进行排序。

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();

我们对单词进行排序。Sort 方法在排序数据时会考虑区域性。

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

在斯洛伐克语中,č 字母位于 c 字母之后。英语排序不会区分这两个字母。

NumberFormatInfo

NumberFormatInfo 提供特定于区域性的信息,用于格式化和解析数值。

Program.cs
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);

该示例显示了斯洛伐克区域性的数字格式信息,包括货币小数分隔符、百分比符号和数字组分隔符。

NumberFormatInfo nfi = sci.NumberFormat;

NumberFormatInfo 是从 CultureInfo 对象的 NumberFormat 属性中检索的。

$ dotnet run
2
,
€
%
‰
,

C# CultureInfo 百分比

有两种不同的字符用于百分号。百分号可能有一个空格,并且可以写在值之前或之后。此外,默认的小数位数也不同。

Program.cs
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"));

该示例显示了土耳其语、斯洛伐克语和波斯语区域性中的百分比。

Console.WriteLine(trCi.NumberFormat.PercentDecimalDigits);

NumberFormat's PercentDecimalDigits 返回百分比值中使用的小数位数。

Console.WriteLine(v.ToString("P"));

P 说明符显示一个乘以 100 并用百分比符号显示的数字。

$ dotnet run
3
%68,000
-------------------------
2
68,00 %
-------------------------
3
68٫000٪

C# CultureInfo 小数分隔符

区域性使用小数点(以色列、日本、英国)或逗号(斯洛伐克、法国、德国)作为小数分隔符。波斯语使用正斜杠 (/)。

Program.cs
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}");

该示例以三种不同的区域性打印一个十进制值。

$ dotnet run
1278,112
1278.112
1278٫112

C# CultureInfo 千位分隔符

区域性使用不同的方法,用分隔符对数字进行分组,以便于阅读。

Program.cs
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}");

该示例以五种不同的区域性打印一个整数值。

$ 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 货币

区域性使用不同的货币符号。该符号可以添加到货币值的前面或后面。

Program.cs
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}");

该示例以五种区域性打印货币值。

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

CultureInfo 日历

日历是组织日期时间单位的系统。区域性使用不同的日历。某些区域性可以使用多个日历。

Program.cs
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)}");
}

波斯语区域性使用波斯历作为默认日历,并使用公历和伊斯兰历作为可选日历。我们以所有支持的波斯日历显示当前的日期时间。

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

我们创建一个波斯语 CultureInfo

DateTime now = DateTime.Now;

我们获取当前的日期时间值。

foreach (var oc in perCi.OptionalCalendars)
{
    perCi.DateTimeFormat.Calendar = oc;
    Console.WriteLine($"{now.ToString("F", perCi)}");
}

我们遍历支持的日历数组。我们将 DateTimeFormat.Calendar 设置为当前选定的日历并打印日期时间。

$ dotnet run
Default calendar: System.Globalization.PersianCalendar
1402 دی 29, جمعه 22:31:07
2024 ژانویهٔ 19, جمعه 22:31:07
1445 رجب 9, جمعه 22:31:07

C# CultureInfo 每周的第一天

区域性中每周的第一天是星期日、星期一或星期六。

Program.cs
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}");

该示例打印三种区域性中每周的第一天。

$ 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 第一周

在文化中定义一年中第一周有不同的规则,包括新年的第一天或一周中的前四天或更多天。

Program.cs
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}");

该示例打印两种区域性的第一周规则。

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

C# CultureInfo 星期几名称

CultureInfo.DateTimeFormat.DayNames 获取一个数组,其中包含特定于区域性的星期几的全名。

Program.cs
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);
}

该示例打印 en-USsk-SK 区域性中星期几的名称。

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

C# CultureInfo 月份名称

使用 CultureInfo.DateTimeFormat.MonthNames 属性,我们可以获取特定于区域性的月份全名数组。同样,我们使用 CultureInfo.DateTimeFormat.AbbreviatedMonthNames 获取特定于区域性的月份缩写名称。

Program.cs
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);
}

该示例打印匈牙利语中的月份名称。我们打印完整和缩写的月份名称。

$ 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 日期时间格式

区域性使用不同的日期时间格式。

Program.cs
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));

该示例以不同的格式打印斯洛伐克文化中今天的日期。

$ 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

来源

CultureInfo 类 - 语言参考

在本文中,我们使用了 C# CultureInfo,它用于全球化 C# 应用程序。

作者

我叫 Jan Bodnar,我是一位充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直撰写编程文章。到目前为止,我已经撰写了 1,400 多篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有 C# 教程