Поделиться через


Глобализируйте форматы даты, времени и чисел

Создайте приложение, чтобы оно было готово к глобальной аудитории, правильно отформатировав даты, время, числа, телефонные номера и валюты. Затем вы сможете адаптировать приложение для дополнительных культур, регионов и языков на глобальном рынке.

Введение

При создании приложения, если вы думаете более широко, чем только о языке и культуре, вы будете иметь меньше (если они вообще возникнут) непредвиденных проблем по мере выхода вашего приложения на новые рынки. Например, даты, время, числа, календари, валюта, номера телефонов, единицы измерения и размеры бумаги — это все элементы, которые могут отображаться по-разному в разных культурах или языках.

Разные регионы и культуры используют разные форматы даты и времени. К ним относятся соглашения о порядке дня и месяца в дате, для разделения часов и минут во времени, а также для того, какие знаки препинания используются в качестве разделителя. Кроме того, даты могут формироваться в разных форматах: длинных ("среда, 28 марта 2012 г.") или коротких ("3/28/12"), которые зависят от культурных различий. И, конечно, имена и аббревиаты для дней недели и месяцев года отличаются между языками.

Вы можете просмотреть форматы, используемые для разных языков. Перейдите в раздел Параметры>Время и язык>Регион и язык, и щелкните Дополнительные параметры даты, времени и региона>Изменить формат даты, времени или чисел. На вкладке Форматы выберите язык из раскрывающегося списка Формат и просмотрите форматы в примерах.

В этом разделе используются термины "список языков профиля пользователя", "список языков манифеста приложения" и "список языков среды выполнения приложения". Дополнительные сведения о том, какие термины означают и как получить доступ к их значениям, см. в разделе "Общие сведения о языках профилей пользователей" и языках манифеста приложения.

Форматирование дат и времени для списка языков среды выполнения приложения

Если необходимо разрешить пользователям выбирать дату или время, используйте стандартные элементы управления календаря, датой и временем. Они автоматически используют лучший формат даты и времени для списка языков среды выполнения приложения.

Если вам нужно отобразить даты или время самостоятельно, можно использовать класс DateTimeFormatter . По умолчанию DateTimeFormatter автоматически использует лучший формат даты и времени для списка языков среды выполнения приложения. Таким образом, приведенный ниже код форматирует заданный dateTime лучшим способом для этого списка. Например, предположим, что список языков манифеста приложения включает английский (США), который также является вашим значением по умолчанию и немецким (Германия). Если текущая дата — 6 ноября 2017 г., а список языков профиля пользователя содержит немецкий (Германия), то средство форматирования дает "06.11.2017". Если в списке языков профиля пользователя английский (США) стоит первым (или если он не содержит ни английского, ни немецкого), то форматтер выводит "11/6/2017" (поскольку "en-US" совпадает или используется по умолчанию).

    // Use the DateTimeFormatter class to display dates and times using basic formatters.

    var shortDateFormatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("shortdate");
    var shortTimeFormatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("shorttime");

    var dateTimeToFormat = DateTime.Now;

    var shortDate = shortDateFormatter.Format(dateTimeToFormat);
    var shortTime = shortTimeFormatter.Format(dateTimeToFormat);

    var results = "Short Date: " + shortDate + "\n" +
                  "Short Time: " + shortTime;

Вы можете протестировать приведенный выше код на своем компьютере, как показано ниже.

Форматирование дат и времени для списка языков профиля пользователя

Помните, что по умолчанию DateTimeFormatter соответствует списку языков среды выполнения приложения. Таким образом, если вы отображаете строки, такие как "Дата: <дата>", то язык будет соответствовать формату даты.

Если по какой-либо причине вы хотите отформатировать даты и (или) время только в соответствии со списком языков профиля пользователя, вы можете сделать это с помощью кода, как показано ниже. Но если вы сделаете это, учтите, что пользователь может выбрать язык, на который в вашем приложении нет переведённых строк. Например, если ваше приложение не локализовано на немецком языке (Германия), но пользователь выбирает это в качестве предпочтительного языка, то это может привести к отображению, возможно, нечетных строк, таких как "Дата 06.11.2017".

    // Use the DateTimeFormatter class to display dates and times using basic formatters.

    var userLanguages = Windows.System.UserProfile.GlobalizationPreferences.Languages;

    var shortDateFormatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("shortdate", userLanguages);

    var results = "Short Date: " + shortDateFormatter.Format(DateTime.Now);

Используйте шаблоны и модели для расширенного форматирования даты и времени

Классы можно использовать в пространстве имен Windows.Globalization.DateTimeFormatting с пользовательскими шаблонами и паттернами для отображения дат и времени в точном формате, который вы хотите.

Разница между шаблонами форматирования и форматами

Шаблон формата — это строка формата, не зависящая от языка и региональных параметров. Таким образом, если вы создаете DateTimeFormatter с помощью шаблона формата, средство форматирования отображает компоненты формата в правильном порядке для текущего языка. И наоборот, шаблон формата зависит от культурных особенностей. Если вы создаете DateTimeFormatter с помощью шаблона формата, средство форматирования будет использовать шаблон точно так же, как указано. Следовательно, шаблон не обязательно является допустимым в разных культурах.

Проиллюстрируем это различие с примером. Мы передадим простой шаблон формата (а не шаблон) конструктору DateTimeFormatter . Это шаблон формата "день месяца".

var dateFormatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("month day");

При этом создается метод форматирования на основе значения языка и региона текущего контекста. Порядок компонентов в шаблоне формата не имеет значения; Модуль форматирования отображает их в правильном порядке для текущего языка. Таким образом, он отображает "1 января" для английского (США), "1 janvier" для французского (Франция) и "1月1日" для японского языка.

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

IReadOnlyList<string> monthDayPatterns = dateFormatter.Patterns;

Это дает разные результаты в зависимости от языка среды выполнения и региона. Разные регионы могут использовать разные компоненты в разном порядке, с дополнительными символами и интервалами или без них.

En-US: "{month.full} {day.integer}"
Fr-FR: "{day.integer} {month.full}"
Ja-JP: "{month.integer}月{day.integer}日"

В приведенном выше примере мы ввели строку формата, не зависящую от языка и региональных параметров, и она преобразовалась в строку формата, зависящую от языка и региона (которая была в действии при вызове dateFormatter.Patterns). Поэтому, если вы создаете DateTimeFormatter из шаблона формата, зависящего от культурных параметров, то он будет допустим только для определенных языков или регионов.

var dateFormatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("{month.full} {day.integer}");

Форматировщик выше возвращает значения, специфичные для культуры, для отдельных компонентов внутри квадратных скобок {}. Но порядок компонентов в шаблоне формата является инвариантным. Вы получаете именно то, что вы просите, что может или не быть культурно подходящим. Этот форматировщик действителен для английского (США), но не для французского (Франция) или для японского языка.

En-US: January 1
Fr-FR: janvier 1 (inappropriate for France; non-standard order)
Ja-JP: 1月1 (inappropriate for Japan; the day symbol 日 is missing)

Кроме того, шаблон, который является правильным сегодня, может быть неправильно в будущем. Страны или регионы могут изменить свои системы календаря, которые изменяют шаблон формата. Windows обновляет выходные данные средств форматирования на основе шаблонов форматирования для учета таких изменений. Поэтому синтаксис шаблона следует использовать только в одном или нескольких из этих условий.

  • Вы не зависите от конкретного формата выходного результата.
  • Вам не нужно, чтобы формат строго соответствовал культурно-специфическим стандартам.
  • Вы намеренно планируете, чтобы шаблон был инвариантным в разных культурах.
  • Вы планируете локализовать сам шаблон формата.

Ниже приведены общие сведения о различиях между шаблонами форматирования и шаблонами формата.

Шаблоны форматирования, такие как "день месяца"

  • Абстрактное представление формата DateTime , включающее значения для месяца, дня и т. д., в любом порядке.
  • Гарантированно возвращать допустимый стандартный формат во всех значениях языкового региона, поддерживаемых Windows.
  • Гарантируется предоставление форматированной строки, соответствующей культурным нормам данного языка и региона.
  • Не все сочетания компонентов допустимы. Например, "dayofweek day" недопустим.

Формат шаблонов, таких как "{month.full} {day.integer}"

  • Явно упорядоченная строка, которая выражает полное имя месяца, за которым следует пробел, за которым следует целое число дня, в этом порядке или любой заданный шаблон формата.
  • Может не соответствовать допустимому стандартному формату для любой пары языкового региона.
  • Не гарантируется, что он будет культурно подходящим.
  • Любое сочетание компонентов может быть указано в любом порядке.

Объединение шаблонов даты и времени с пользовательским форматированием

Предположим, что вы хотите отобразить текущий месяц и день вместе с текущим временем в определенном формате. Например, вы хотите, чтобы пользователи английского языка США видели примерно следующее:

June 25 | 1:38 PM

Часть даты соответствует шаблону формата "месяц день", а часть времени соответствует шаблону формата "час минуты". Таким образом, можно создавать форматировщики для соответствующих шаблонов формата даты и времени, а затем объединять их выходные данные вместе с помощью строки локализованного формата.

var dateToFormat = System.DateTime.Now;
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();

var dateFormatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("month day");
var timeFormatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("hour minute");

var date = dateFormatter.Format(dateToFormat);
var time = timeFormatter.Format(dateToFormat);

string output = string.Format(resourceLoader.GetString("CustomDateTimeFormatString"), date, time);

CustomDateTimeFormatString — это идентификатор ресурса, ссылающийся на локализуемый ресурс в файле ресурсов (resw). Для языка английского языка по умолчанию (США) это значение будет иметь значение "{0} | {1}" вместе с комментарием, указывающим, что "{0}" является датой и "{1}" — это время. Таким образом переводчики могут настраивать элементы формата по мере необходимости. Например, они могут изменить порядок элементов, если он кажется более естественным на каком-либо языке или регионе, чтобы время предшествует дате. Кроме того, они могут заменить "|" другим символом разделителя.

Другой способ реализации этого примера заключается в том, чтобы запросить два форматировщика для их форматов, объединить их в одно, а затем создать третий форматировщик из полученного формата.

var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();

var dateFormatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("month day");
var timeFormatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("hour minute");

string dateFormatterPattern = dateFormatter.Patterns[0];
string timeFormatterPattern = timeFormatter.Patterns[0];

string pattern = string.Format(resourceLoader.GetString("CustomDateTimeFormatString"), dateFormatterPattern, timeFormatterPattern);

var patternFormatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter(pattern);

string output = patternFormatter.Format(System.DateTime.Now);

Форматирование чисел и валют соответствующим образом

Разные культуры форматируют числа по-разному. Различия в формате могут включать количество отображаемых десятичных цифр, символов, используемых в качестве десятичных разделителей, и используемых символов валют. Используйте классы в пространстве имен NumberFormatting для отображения десятичных, процентных или многомиллионных чисел и валют. В большинстве случаев эти классы форматирования будут выбирать оптимальный формат для профиля пользователя. Но вы можете использовать средства форматирования для отображения валюты для любого региона или формата.

В этом примере показано, как отображать валюты как для профиля пользователя, так и для конкретной валюты.

    // This scenario uses the CurrencyFormatter class to format a number as a currency.

    var userCurrency = Windows.System.UserProfile.GlobalizationPreferences.Currencies[0];

    var valueToBeFormatted = 12345.67;

    var userCurrencyFormatter = new Windows.Globalization.NumberFormatting.CurrencyFormatter(userCurrency);
    var userCurrencyValue = userCurrencyFormatter.Format(valueToBeFormatted);

    // Create a formatter initialized to a specific currency,
    // in this case US Dollar (specified as an ISO 4217 code) 
    // but with the default number formatting for the current user.
    var currencyFormatUSD = new Windows.Globalization.NumberFormatting.CurrencyFormatter("USD");
    var currencyValueUSD = currencyFormatUSD.Format(valueToBeFormatted);

    // Create a formatter initialized to a specific currency.
    // In this case it's the Euro with the default number formatting for France.
    var currencyFormatEuroFR = new Windows.Globalization.NumberFormatting.CurrencyFormatter("EUR", new[] { "fr-FR" }, "FR");
    var currencyValueEuroFR = currencyFormatEuroFR.Format(valueToBeFormatted);

    // Results for display.
    var results = "Fixed number (" + valueToBeFormatted + ")\n" +
                    "With user's default currency: " + userCurrencyValue + "\n" +
                    "Formatted US Dollar: " + currencyValueUSD + "\n" +
                    "Formatted Euro (fr-FR defaults): " + currencyValueEuroFR;

Вы можете протестировать приведенный выше код на своем компьютере, изменив страну или регион в разделе Параметры>Время и язык>Регион и язык>Страна или регион. Выберите страну или регион (возможно, Исландию) и снова запустите код.

Использование культурно подходящего календаря

Календарь отличается между регионами и языками. Григорианский календарь не является значением по умолчанию для каждого региона. Пользователи в некоторых регионах могут выбирать альтернативные календари, например японский календарь эпохи или арабские лунные календари. Даты и время в календаре также чувствительны к разным часовых поясам и летнему времени.

Для того чтобы гарантировать использование предпочтительного формата календаря, вы можете воспользоваться стандартными элементами управления для календаря, даты и времени. Для более сложных задач, когда требуется работа непосредственно с операциями с календарными датами, Windows.Globalization предоставляет класс Calendar, который обеспечивает соответствующее представление календаря для заданной культуры, региона и типа календаря.

Форматирование номеров телефонов соответствующим образом

Номера телефонов форматируются по-разному в разных регионах. Количество цифр, группирование цифр и значение определенных частей номера телефона зависит от стран или регионов. Начиная с Windows 10 версии 1607, классы можно использовать в пространстве имен PhoneNumberFormatting для форматирования номеров телефонов соответствующим образом для текущего региона.

PhoneNumberInfo анализирует строку цифр и позволяет: определить, являются ли цифры допустимым номером телефона в текущем регионе; сравните два числа для равенства; и для извлечения различных функциональных частей номера телефона, таких как код страны или географический код области.

PhoneNumberFormatter форматирует строку цифр или PhoneNumberInfo для отображения, даже если строка цифр представляет собой частичный номер телефона. Вы можете использовать частичное форматирование числа, чтобы отформатировать его, когда пользователь вводит число.

В приведенном ниже примере показано, как использовать PhoneNumberFormatter для форматирования номера телефона при вводе. Каждый раз, когда текст изменяется в TextBox с именем phoneNumberInputTextBox, содержимое текстового поля форматируется с помощью текущей области по умолчанию и отображается в TextBlock с именем phoneNumberOutputTextBlock. Для демонстрационных целей строка также форматируется с помощью региона для Новой Зеландии и отображается в TextBlock с именем phoneNumberOutputTextBlockNZ.

    using Windows.Globalization.PhoneNumberFormatting;

    PhoneNumberFormatter currentFormatter, NZFormatter;

    public MainPage()
    {
        this.InitializeComponent();

        // Use the default formatter for the current region
        this.currentFormatter = new PhoneNumberFormatter();

        // Create an explicit formatter for New Zealand. 
        PhoneNumberFormatter.TryCreate("NZ", out this.NZFormatter);
    }

    private void phoneNumberInputTextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        // Format for the default region.
        this.phoneNumberOutputTextBlock.Text = currentFormatter.FormatPartialString(this.phoneNumberInputTextBox.Text);

        // If the NZFormatter was created successfully, format the partial string for the NZ TextBlock.
        if(this.NZFormatter != null)
        {
            this.phoneNumberOutputTextBlockNZ.Text = this.NZFormatter.FormatPartialString(this.phoneNumberInputTextBox.Text);
        }
    }

Вы можете протестировать приведенный выше код на своем компьютере, изменив страну или регион в разделе Параметры>Время и язык>Регион и язык>Страна или регион. Выберите страну или регион (возможно, Новую Зеландию, чтобы подтвердить соответствие форматов) и снова запустите код. Для тестовых данных можно выполнить веб-поиск телефонного номера бизнеса в Новой Зеландии.

Языковые и культурные предпочтения пользователя

В сценариях, где вы хотите предоставить различные функциональные возможности, основанные исключительно на языке пользователя, регионе или культурных предпочтениях, Windows предоставляет возможность доступа к этим предпочтениям через Windows.System.UserProfile.GlobalizationPreferences. При необходимости используйте класс GlobalizationPreferences , чтобы получить значение текущего географического региона пользователя, предпочитаемых языков, предпочитаемых валют и т. д. Но помните, что если строки и изображения приложения не локализованы для предпочтительного языка пользователя, то даты и время и другие данные, отформатированные для этого предпочтительного языка, не будут соответствовать отображаемым строкам.

Важные API

Образцы