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 file]()
![Finnish formatting]()
Как только я удалю пустой файл ресурсов, форматы вернутся обратно в США:
![Resource file removed]()
![US formatting winrt]()
Очень странно.
Это приводит к нескольким вопросам, но главное, что я думаю: намерено ли WinRT-приложения не следовать региональным настройкам пользователя, например, приложениям WPF?
Ответы
Ответ 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). Поведение, которое вы видите, - это то, что вы играете с языками пользователей и языками манифеста, и вы получите разные языки приложений.
Ответ 3
Возможно, нам нужно запросить другие классы? Как приведенный здесь пример: http://code.msdn.microsoft.com/windowsapps/Globalization-preferences-6654eb36/sourcecode?fileId=52104&pathId=236099476
Ответ 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;
}