Получение системных часовых поясов на разных языках

В настоящее время я получаю список всех часовых поясов вроде этого:

var TheListOfAllTimezones = TimeZoneInfo.GetSystemTimeZones();

Так, например, часовой пояс в Париже имеет свойство DisplayName W. Europe Standard Time. Теперь, как мне получить этот список на другом языке? Например, для пользователей во Франции я хотел бы отобразить Heure Europe de l'Ouest.

Спасибо.

enter image description here

Ответ 1

Изменение CurrentCulture не работает, поскольку информация поступает из реестра (XP) или из библиотеки многоязыкового интерфейса пользователя (MUI) (Vista, Windows 7).

В Vista или Windows 7 вы можете установить другие языки и изменить язык отображения (Регион и Язык → Клавиатуры и языки → Язык отображения). Требуется перезагрузка. Это, и только это, фактически изменит язык, используемый в TimeZoneInfo.

В Windows 7 только Ultimate и Enterprise позволяют устанавливать другие языки - путем установки пакетов многоязыкового интерфейса пользователя.

После установки других языков вы сможете найти библиотеки DLL в папке system32 (найдите tzres) и, возможно, экспортируйте ресурсы с помощью Visual Studio.

Что касается достоверных/официальных источников - как насчет статьи о msdn команды BCL:

... отображаемые строки загружаются либо из многоязычного пользователя Интерфейс (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.

Ответ 2

Из документация:

Коллекция, возвращаемая этим методом, сортируется по отображаемому имени, используя текущая культура.

Вы пытались изменить текущую культуру в пользовательской культуре, прежде чем получать список?

Это может не сработать. Возможно, единственными отображаемыми именами являются те, которые установлены для установленной версии Windows. То есть, если у вас есть англо-английская версия Windows, французские отображаемые имена могут отсутствовать. Глядя на мой реестр (HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zones), я вижу только английские имена.

Ответ 3

Если CurrentCulture вашего потока - французский ( "fr-FR" ), и если этот язык "родной" с вашей версией Windows, то свойства StandardName и DaylightName будут на французском языке, это кажется.

Edit:

Не похоже, что изменение CurrentCulture потока поможет. Часовой пояс поступает из реестра (см. Ответ Джима Мишеля для пути), и похоже, что язык установки Windows определяет значения. Идентификаторы (которые являются ключами в пути реестра) всегда находятся на английском языке, а другие свойства зависят от языка 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

Ответ 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());
}