当前区域设置、不变区域设置、当前用户界面区域设置和已安装用户界面区域设置之间的区别

76

System.Globalization.CultureInfo中的CurrentCultureInvariantCultureCurrentUICultureInstalledUICulture之间有什么区别?


什么时候应该指定CurrentCulture或InvariantCulture,什么时候应该保持默认? - Tim Schmelter
2个回答

125

我会尝试给出比这个答案更具见解的回答。

CurrentCulture应该用于格式化。也就是说,数字、货币、百分比、日期和时间在显示给用户之前都应该使用这种文化进行格式化。以下是一些示例:

const string CURRENCY_FORMAT = "c";
const string PERCENTAGE_FORMAT = "p";

DateTime now = DateTime.UtcNow; // all dates should be kept in UTC internally
// convert time to local and format appropriately for end user
dateLabel.Text = now.ToLocalTime().ToString(CultureInfo.CurrentCulture);

float someFloat = 12.3456f;
// yields 12,3456 for pl-PL Culture
floatLabel.Text = someFloat.ToString(CultureInfo.CurrentCulture);
// yields 12,35 zł for pl-PL Culture - rounding takes place!
currencyLabel.Text = someFloat.ToString(CURRENCY_FORMAT, CultureInfo.CurrentCulture);
// yields 1234,56% for pl-PL Culture - 1.0f is 100%
percentageLabel.Text = someFloat.ToString(PERCENTAGE_FORMAT, CultureInfo.CurrentCulture);

需要注意的一件重要事情是,你应该永远不要使用floatdouble来存储与货币相关的信息(decimal才是正确的选择)。
另一个常见的用例是区域感知解析。你的应用程序应该始终允许用户以他们的地区格式提供输入:

float parsedFloat;
if (float.TryParse(inputBox.Text, NumberStyles.Float, CultureInfo.CurrentCulture, out parsedFloat))
{
    MessageBox.Show(parsedFloat.ToString(CultureInfo.CurrentCulture), "Success at last!");
}

请注意,我总是提供IFormatProvider参数,尽管它是暗示且默认为CultureInfo.CurrentCulture。原因是,我想与其他开发人员沟通:这是将显示给最终用户的内容。这也是为什么FxCop将省略此参数视为错误之一。
另一方面,InvariantCulture应该用于可靠地将上述类之一转换为其文本表示形式。因此,如果您想通过网络传输DateTimefloatdouble或类似对象,将其存储到数据库或某种文本文件(包括XML),您应该始终使用InvariantCulture
float someFloat = 1234.56f;
// yields 1234.56
string internalFloat = someFloat.ToString(CultureInfo.InvariantCulture);
DateTime now = DateTime.UtcNow;
// yields something like 04/16/2011 19:02:46
string internalDateAndTime = now.ToString(CultureInfo.InvariantCulture);

需要注意的是,InvariantCulture 提供的日期/时间格式实际上与 en-US 完全相同。虽然它是可靠的,但并不完全正确。真正应该使用的是ISO8601可交换日期和时间格式。由于某种原因,Microsoft甚至没有提供这样的模式(最接近的是可排序模式 - “s”和通用模式 - “u”,这只类似于ISO8601格式),您需要自己创建如下:

const string iso8601Pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'";
string iso8601Formatted = now.ToString(iso8601Pattern);

重要提示:在此处实际上需要IFormatProvider,省略此参数可能导致严重错误。我曾经不得不修复法语操作系统上的缺陷。代码如下:

float dbVersion = // some kind of logic that took float from database
string versionString = dbVersion.ToString(); // culture-aware formatting used
Version ver = new Version(versionString); // exception thrown here

原因非常简单:在法语操作系统上格式化的浮点数(使用法语区域格式)被格式化为类似于10.5的东西,而Version类需要文化不变的输入。


CurrentUICulture负责加载应用程序的适当可翻译资源。也就是说,它应该用于显示正确的文本消息、颜色和图像。
在Asp.Net应用程序中,如果您想出于某种原因实现CSS本地化机制(能够按语言覆盖CSS定义),CurrentUICulture是一个好方法(前提是您实际从Web浏览器读取此属性)。
同样,如果您想实现语言切换机制,则应覆盖CurrentUICulture


InstalledUICulture与默认的操作系统UI区域设置相连。正如MSDN所说:

此属性相当于Windows API中的GetSystemDefaultUILanguage。

要真正理解这个属性,我们需要深入一些理论。有不同的Windows产品线:

  • 单一语言(即英语、法语、德语、日语等)
  • MUI(即多语言用户界面-以英语为基础的操作系统和语言包)

对于单一语言产品线,InstalledUICulture将始终返回操作系统语言,而对于MUI,它应该始终返回英语(美国)即en-US。这有用吗?我不知道,我从未需要过这样的信息。就我个人而言,我没有看到过利用此属性的程序。


1
你不再需要使用上述的ISO8601模式字符串了。这个也可以:myDate.ToString("o")oO格式字符串将把日期/时间转换为ISO 8601格式。 - Alan S

3
这个答案中获取:
CurrentCulture是系统默认用户区域设置的.NET表示。这控制默认的数字和日期格式等。
CurrentUICulture是指默认的用户界面语言,这是Windows 2000引入的设置。这主要涉及您应用程序的UI本地化/翻译部分。
无论系统配置了什么区域选项,都将是您的.NET应用程序中的“当前”值。
通常它们都是相同的。但在我的系统上它们会有所不同:我喜欢德国格式的数字和日期,所以CurrentCulture将是德语,但我也喜欢所有应用程序都是英文的,所以CurrentUICulture将是英文。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接