获取不同语言的系统时区

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_DisplayMUI_StdMUI_Dlt 键,其中 由操作系统区域设置间接控制。 在 Windows XP 和 Windows Server 2003 等下层平台上, 只有DisplayStdDlt 键存在。 DisplayStdDlt 键值仅本地化为操作的默认语言 系统。

那么他们对CurrentUICulture 写了什么?

由于 Windows 时区注册表架构, CurrentUICulture 设置不会影响这些值 TimeZoneInfo 属性

【讨论】:

它确实提出了一个问题,为什么 DisplayName 属性的文档记录如此糟糕...... 老实说,我不知道,但除非您使用不同的语言设置创建自己的虚拟机,否则我会选择英语。【参考方案2】:

如果您的线程的CurrentCulture 是法语(“fr-FR”),并且如果该语言是您的Windows 版本的“本地”语言,那么属性StandardNameDaylightName 将是法语,它好像。

编辑:

更改线程的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,我在丹麦的注册表中看到了 StdDlt。在.NET 对象中,我看到了英文的Id 属性,以及Danish 中的StandardNameDaylightName 属性。 是的,没有内置的方法来获取不同语言的列表真的很奇怪。我的操作系统是英文的,该应用程序将托管在 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());

【讨论】:

以上是关于获取不同语言的系统时区的主要内容,如果未能解决你的问题,请参考以下文章

如何通过颤动中的设备位置获取颤动中的时区、语言和县 ID?

如何在Win10系统内设置多时区时钟

安卓51虚拟机无法修改时间

windows进程启动设置时区限制

Debian 系统修改语言设置成英文

C#开发的计算机时区语言环境模拟器