获取不同语言的系统时区
Posted
技术标签:
【中文标题】获取不同语言的系统时区【英文标题】:Getting system Timezones in different languages 【发布时间】:2012-10-21 05:22:17 【问题描述】:我目前正在获取所有时区的列表,如下所示:
var TheListOfAllTimezones = TimeZoneInfo.GetSystemTimeZones();
例如,巴黎时区的DisplayName
属性为W. Europe Standard Time
。现在我如何用另一种语言获得这个列表?例如,对于法国的用户,我想显示Heure Europe de l'Ouest
。
谢谢。
【问题讨论】:
要更好地理解这个问题,请阅读my blog on the subject,并查看this library 以获得解决方案。 【参考方案1】:更改 CurrentCulture
不起作用,因为信息来自注册表 (XP) 或多语言用户界面 (MUI) DLL(Vista、Windows 7)。
在 Vista 或 Windows 7 上,您可以安装其他语言并更改显示语言(区域和语言 -> 键盘和语言 -> 显示语言)。需要重新启动。这个,也只有这个,实际上会改变TimeZoneInfo
中使用的语言。
在 Windows 7 上,只有 Ultimate 和 Enterprise 允许安装其他语言 - 通过安装 多语言用户界面包。
安装其他语言后,您应该能够在 system32 文件夹中找到 DLL(查找 tzres
),并可以使用 Visual Studio 导出资源。
关于可靠/官方来源 - an article on msdn of the BCL Team:
...显示字符串从 Multilingual User 加载 接口 (MUI) DLL、tzres.dll 或直接来自注册表,当 MUI 支持不可用。支持 MUI 的操作系统,例如 Windows Vista 包含
MUI_Display
、MUI_Std
和MUI_Dlt
键,其中 由操作系统区域设置间接控制。 在 Windows XP 和 Windows Server 2003 等下层平台上, 只有Display
、Std
和Dlt
键存在。Display
、Std
和Dlt
键值仅本地化为操作的默认语言 系统。
那么他们对CurrentUICulture
写了什么?
由于 Windows 时区注册表架构, CurrentUICulture 设置不会影响这些值 TimeZoneInfo 属性。
【讨论】:
它确实提出了一个问题,为什么 DisplayName 属性的文档记录如此糟糕...... 老实说,我不知道,但除非您使用不同的语言设置创建自己的虚拟机,否则我会选择英语。【参考方案2】:如果您的线程的CurrentCulture
是法语(“fr-FR”),并且如果该语言是您的Windows 版本的“本地”语言,那么属性StandardName
和DaylightName
将是法语,它好像。
编辑:
更改线程的CurrentCulture
似乎没有帮助。时区都来自注册表(请参阅 Jim Mischel 的路径答案),看起来 Windows 安装的语言决定了这些值。 ID(注册表路径中的键)始终为英文,而其他属性取决于 Windows 语言。
以下代码的输出是什么:
Console.WriteLine(CultureInfo.InstalledUICulture.DisplayName);
var tzi = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
Console.WriteLine(tzi.Id); // always English
Console.WriteLine(tzi.DisplayName); // localized
Console.WriteLine(tzi.StandardName); // localized
Console.WriteLine(tzi.DaylightName); // localized
【讨论】:
@JonSkeet 好的,它似乎只取决于操作系统语言。我正在丹麦语 Windows 机器上尝试这个。对于一个TimeZoneInfo
实例,我有Id
等于"Romance Standard Time"
; DisplayName
是 "(UTC+01:00) København, Stockholm, Oslo, Madrid, Paris"
; StandardName
是 "Rom, normaltid"
;而DaylightName
是"Rom, sommertid"
。
是的,没有内置方法来获取不同语言的列表,这真的很奇怪。
@JonSkeet:你知道怎么做吗?
@frenchie:不幸的是:(通常的方法是给出城市列表而不是时区名称 - Unicode CLDR 给出了要列出的示例城市,但那些是针对 TZDB 时区的......
@JeppeStigNielsen:是的,我认为 CLDR 对不同语言的城市有不同的名称。不过我得检查一下。【参考方案3】:
来自the documentation:
此方法返回的集合使用显示名称排序 当前的文化。
在获取列表之前,您是否尝试过将当前文化更改为用户的文化?
这可能行不通。唯一可用的显示名称可能是已安装的 Windows 版本的显示名称。也就是说,如果您有美国英语版本的 Windows,则可能不存在法语显示名称。查看我的注册表 (HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zones
),我只看到英文名称。
【讨论】:
有趣。我这里有丹麦版本的 Windows,我在丹麦的注册表中看到了Std
和 Dlt
。在.NET
对象中,我看到了英文的Id
属性,以及Danish
中的StandardName
和DaylightName
属性。
是的,没有内置的方法来获取不同语言的列表真的很奇怪。我的操作系统是英文的,该应用程序将托管在 Azure 上,所以我想这也是英文的。【参考方案4】:
如何创建像“TimeZoneInfoExtension”这样的类,该类将具有名为 ToLocolizedString 的静态方法:
public static class TimeZoneInfoExtensions
public static string ToLocalizedString(this TimeZoneInfo timeZone)
switch (timeZone.Id)
case "Dateline Standard Time":
return i18n.DatelineStandardTime;
case "UTC-11":
return i18n.UTC11;
case "Hawaiian Standard Time":
return i18n.HawaiianStandardTime;
case "Alaskan Standard Time":
return i18n.AlaskanStandardTime;
....
default:
throw new NotImplementedException();
其中 i18n 是一个有资源的类。是的,您必须手动填写翻译。但我只是在不同的系统语言中使用了类似的东西来生成翻译:
Regex rgx = new Regex("[ +-]");
foreach (var timeZone in TimeZoneInfo.GetSystemTimeZones())
Console.WriteLine(" <data name=\"0\" xml:space=\"preserve\">", rgx.Replace(timeZone.Id, string.Empty));
Console.WriteLine(" <value>0</value>", timeZone.DisplayName);
Console.WriteLine(" </data>");
然后你可以根据你的 CurrentCulture 来使用它,如下所示:
foreach (var timeZoneInfo in TimeZoneInfo.GetSystemTimeZones())
Console.WriteLine(timeZoneInfo.ToLocalizedString());
【讨论】:
以上是关于获取不同语言的系统时区的主要内容,如果未能解决你的问题,请参考以下文章