Приложения WinRT и региональные настройки. Как правильно форматировать даты и числа в зависимости от региональных настроек пользователя?

У меня возникают проблемы с региональными настройками пользователя в приложениях Windows 8 Metro (XAML и C #). Кажется, что приложения не соблюдают региональные настройки пользователя, поэтому даже если в вашей Windows 8 настроено отображение даты и времени в финском формате, приложения все равно будут отображать их с использованием форматирования для США. Но это такая большая проблема, что я что-то упускаю?

Чтобы проверить это, я начал с создания WPF-приложения. Приложение просто распечатывает CurrentCulture и форматированный DateTime.Now:

    private void Culture_Loaded_1(object sender, RoutedEventArgs e)
    {
        this.Culture.Text = System.Globalization.CultureInfo.CurrentCulture.DisplayName;
    }

    private void Date_Loaded_1(object sender, RoutedEventArgs e)
    {
        this.Date.Text = DateTime.Now.ToString();
    }

Вот мои региональные настройки по умолчанию: Regional settings

При запуске приложение отображало дату в финском формате:

Финское форматирование

Затем я изменил региональные настройки на США: Региональные настройки США

А когда приложение было запущено снова, культура и форматирование изменились: US wpf formatting

Это как я ожидал, все работает, и именно так я ожидал, что приложения WinRT будут работать.

Итак, в качестве следующего шага я создал приложение WinRT (XAML & C #) с тем же кодом и вернул региональные настройки обратно на финский. Проблема:

Форматирование Winrt

Даже когда я определил в региональных настройках, что форматирование должно быть «финским», приложение WinRT отображает дату и время с американским форматированием. Затем я изменил файл проекта приложения и сделал fi-FI языком по умолчанию:

Язык по умолчанию

Это изменение также изменило культуру приложения:

Финское форматирование winrt

Странный. Я изменил язык по умолчанию на значение по умолчанию, и форматирование было восстановлено до США. Затем я создал в проекте папки «Strings - fi-FI» и добавил в проект пустой «Resources.resw». Кажется, этого пустого файла достаточно, так как я теперь получал финское форматирование:

Файл ресурсовФинское форматирование

Как только я удаляю пустой файл ресурсов, форматирование возвращается к US:

Файл ресурсов удаленWinrt форматирование США

Очень странно.

Это приводит к нескольким вопросам, но я думаю, что главный из них: намеренно ли, что приложения WinRT не следуют региональным настройкам пользователя, как это делают приложения WPF?


person Mikael Koskinen    schedule 24.09.2012    source источник


Ответы (4)


Прошло некоторое время, но на этот вопрос нет полного ответа, поэтому позвольте мне поделиться своим небольшим исследованием. Депечи в основном прав, но он дал только ссылку и не совсем уверен.

Да, это неожиданное изменение сделано намеренно. Нам больше не следует использовать CultureInfo, поскольку он содержит устаревшие коды, а Microsoft хочет, чтобы мы вместо этого использовали API-интерфейсы Windows.Globalization.

Чтобы получить текущий регион, мы можем использовать:

GeographicRegion userRegion = new GeographicRegion();
string regionCode = userRegion.CodeTwoLetter;

Но, как я заметил, он содержит только информацию о регионе, кода языка нет. Для получения языка мы можем использовать:

string langRegionCode = Windows.Globalization.Language.CurrentInputMethodLanguageTag; // depends on keyboard settings
List<string> langs = Windows.System.UserProfile.GlobalizationPreferences.Languages; // all user  languages, like in languages control panel
List<string> applicationlangs = Windows.Globalization.ApplicationLanguages.Languages; // application languages (user languages resolved against languages declared as supported by application)

Они возвращают языковые теги BCP47 в формате language-REGION, например "en-US", если в языке есть диалекты, или просто язык, например, "pl", если в языке нет основных диалектов.

Мы также можем установить один основной язык, который переопределит все остальные:

Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "en-US";

(Это постоянный параметр, который предполагается использовать по запросу пользователя)

Также есть новый API для даты, времени и чисел:

Windows.Globalization.DateTimeFormatting.DateTimeFormatter dtf = new DateTimeFormatter("longdate", new[] { "en-US" }, "US", CalendarIdentifiers.Gregorian, ClockIdentifiers.TwentyFourHour);
string longDate = dtf.Format(DateTime.Now);

Windows.Globalization.NumberFormatting.DecimalFormatter deciamlFormatter = new DecimalFormatter(new string[] { "PL" }, "PL");
double d1 = (double)deciamlFormatter.ParseDouble("2,5"); // ParseDouble returns double?, not double

API-интерфейсы Windows.Globalization действительно намного больше, но я думаю, что это дает нам общее представление. Для дальнейшего чтения:

Вы также можете найти некоторые темы по этой проблеме на форуме центра разработчиков Windows 8 с ответами некоторых сотрудников Microsoft, но в основном они отправляют вас к документации.

person Tom    schedule 29.12.2012
comment
Итак, как на самом деле получить / соблюдать настройки регионального формата пользователей? Я запустил эмулятор Windows Phone 8.1 со следующей конфигурацией для целей тестирования: Язык пользовательского интерфейса: немецкий, регион: США, настройки формата: ирландский. Я не нашел способа получить информацию о том, что пользователь установил свои параметры формата на ирландский. И мое единственное желание - отформатировать DateTime так, как пользователь хочет его видеть. И региональный формат не означает автоматически регион, который я установил для устройства, или язык пользовательского интерфейса, который я выбрал. На своих устройствах я установил пользовательский интерфейс на английский, но хочу видеть все отметки времени и даты в немецком формате ... - person Kornelis; 17.07.2014
comment
спасибо, следующее было здорово, потому что мне нужен ISO 3166-1 alpha2 en.wikipedia.org / wiki / ISO_3166-1_alpha-2 Географический регион userRegion = новый Географический регион (); строка regionCode = userRegion.CodeTwoLetter; - person Quincy; 29.06.2015
comment
Это сработало для меня, но теперь мне нужны большие числа, а CurrencyFormatter не поддерживает десятичные числа, поэтому мне нужно обходное решение ... - person Alberto Rivelli; 17.01.2017

Это сделано намеренно. Microsoft отказывается от принуждения приложений к языку ОС. Вместо этого каждое приложение использует информацию, объявленную приложением (языки манифеста, наблюдаемые в Windows.Globalization.ApplicationLanguages.ManifestLanguages) и объявленные пользователем (языки пользователя, наблюдаемые в Windows.System.UserProfile.GlobalizationPreferences.Languages), чтобы определить, как отображать ресурсы и глобализированные даты и время. Этот набор языков называется языками приложений (можно найти в Windows.Globalization.ApplicationLanguages.Languages). Поведение, которое вы наблюдаете, связано с тем, что вы возитесь с языками пользователя и языками манифеста, и вы получите разные языки приложения.

person Eric MSFT    schedule 07.03.2013
comment
Интересный подход, хотя, как португалец, живущий в Великобритании (и в настоящее время работающий в Microsoft), я не мог не согласиться с ним! Вот мое мнение: на моем телефоне Win10 установлен английский язык (США), язык страны - Великобритания, а региональный формат - португальский (Португалия). Outlook показывает даты в правильном формате pt-PT, но все другие приложения настаивают на использовании en-US, что ИМХО неверно, а не то, что я ожидал !! - person Pedro Lamas; 19.01.2016

Может быть, теперь нам нужно запросить другие классы? Как в примере, приведенном здесь: http://code.msdn.microsoft.com/windowsapps/Globalization-preferences-6654eb36/sourcecode?fileId=52104&pathId=236099476.

person Depechie    schedule 25.09.2012

Этот пост все еще кажется актуальным, хотя его спросили два года назад. Я просто наткнулся на это, когда искал ответ примерно на то же самое. Я также хотел отображать даты в региональном формате в моем приложении WP8.1 WinRT. Информация, размещенная здесь, помогает, но было немного сложно собрать ее воедино.

Это то, что я придумал, и, кажется, мне подходит ответ, который мне нужен:

using Windows.Globalization;
using Windows.Globalization.DateTimeFormatting;

private string FormatDate(int year, int month, int day)
{
    GeographicRegion userRegion = new GeographicRegion();
    string regionCode = userRegion.CodeTwoLetter;
    var formatter = new DateTimeFormatter("year month day", new[] { regionCode });
    DateTime dateToFormat = new DateTime(year, month, day);
    var formattedDate = formatter.Format(dateToFormat);
    return formattedDate;
}
person theMaxx    schedule 07.07.2015