Подтвердить что ты не робот

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

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

Чтобы проверить это, я начал с создания 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

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

Finnish formatting

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

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

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

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

Winrt formatting

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

Default language

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

Finnish winrt formatting

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

Resource fileFinnish formatting

Как только я удалю пустой файл ресурсов, форматы вернутся обратно в США:

Resource file removedUS formatting winrt

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

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

4b9b3361

Ответ 1

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

Да, это неожиданное изменение намеренно. Нам больше не следует использовать 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 в языке формата 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 dev center с некоторыми ответами сотрудников Microsoft, но они в основном отправляют вас в документацию.

Ответ 2

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

Ответ 4

Этот пост по-прежнему кажется актуальным, хотя он был задан два года назад. Я просто наткнулся на это, поскольку я искал ответ примерно на одно и то же. Я также хотел отображать даты в региональном формате в моем приложении 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;
}