Общая проблема строк, дат, чисел в JavaScript – они «не в курсе» языка и особенностей стран, где находится посетитель.
В частности:
- Строки
- При сравнении сравниваются коды символов, а это неправильно, к примеру, в русском языке оказывается, что
"ё" > "я"и"а" > "Я", хотя всем известно, чтоя– последняя буква алфавита и это она должна быть больше любой другой. - Даты
- В разных странах принята разная запись дат. Где-то пишут 31.12.2014 (Россия), а где-то 12/31/2014 (США), где-то иначе.
- Числа
- В одних странах выводятся цифрами, в других – иероглифами, длинные числа разделяются где-то пробелом, где-то запятой.
Все современные браузеры, кроме IE10 (но есть библиотеки и для него) поддерживают стандарт ECMA 402, предназначенный решить эти проблемы навсегда.
Основные объекты
Intl.Collator- Умеет правильно сравнивать и сортировать строки.
Intl.DateTimeFormat- Умеет форматировать дату и время в соответствии с нужным языком.
Intl.NumberFormat- Умеет форматировать числа в соответствии с нужным языком.
Локаль
Локаль – первый и самый важный аргумент всех методов, связанных с интернационализацией.
Локаль описывается строкой из трёх компонентов, которые разделяются дефисом:
- Код языка.
- Код способа записи.
- Код страны.
На практике не всегда указаны три, обычно меньше:
ru– русский язык, без уточнений.en-GB– английский язык, используемый в Англии (GB).en-US– английский язык, используемый в США (US).zh-Hans-CN– китайский язык (zh), записываемый упрощённой иероглифической письменностью (Hans), используемый в Китае.
Также через суффикс -u-* можно указать расширения локалей, например "th-TH-u-nu-thai" – тайский язык (th), используемый в Таиланде (TH), с записью чисел тайскими буквами (๐, ๑, ๒, ๓, ๔, ๕, ๖, ๗, ๘, ๙) .
Стандарт, который описывает локали – RFC 5646, языки описаны в IANA language registry.
Все методы принимают локаль в виде строки или массива, содержащего несколько локалей в порядке предпочтения.
Если локаль не указана или undefined – берётся локаль по умолчанию, установленная в окружении (браузере).
Подбор локали localeMatcher
localeMatcher – вспомогательная настройка, которую тоже можно везде указать, она определяет способ подбора локали, если желаемая недоступна.
У него два значения:
"lookup"– означает простейший порядок поиска путём обрезания суффикса, напримерzh-Hans-CN→zh-Hans→zh→ локаль по умолчанию."best fit"– использует встроенные алгоритмы и предпочтения браузера (или другого окружения) для выбора подходящей локали.
По умолчанию стоит "best fit".
Если локалей несколько, например ["zh-Hans-CN", "ru-RU"] то localeMatcher пытается подобрать наиболее подходящую локаль для первой из списка (китайская), если не получается – переходит ко второй (русской) и так далее. Если ни одной не нашёл, например на компьютере не совсем поддерживается ни китайский ни русский, то используется локаль по умолчанию.
Как правило, "best fit" является здесь наилучшим выбором.
Строки, Intl.Collator
Синтаксис:
// создание
let collator = new Intl.Collator([locales, [options]])
Параметры:
locales-
Локаль, одна или массив в порядке предпочтения.
options-
Объект с дополнительными настройками:
-
localeMatcher– алгоритм выбора подходящей локали. -
usage– цель сравнения: сортировка"sort"или поиск"search", по умолчанию"sort". -
sensitivity– чувствительность: какие различия в символах учитывать, а какие – нет, варианты:base– учитывать только разные символы, без диакритических знаков и регистра, например:а ≠ б,е = ё,а = А.accent– учитывать символы и диакритические знаки, например:а ≠ б,е ≠ ё,а = А.case– учитывать символы и регистр, например:а ≠ б,е = ё,а ≠ А.variant– учитывать всё: символ, диакритические знаки, регистр, например:а ≠ б,е ≠ ё,а ≠ А, используется по умолчанию.
-
ignorePunctuation– игнорировать знаки пунктуации:true/false, по умолчаниюfalse. -
numeric– использовать ли численное сравнение:true/false, еслиtrue, то будет12 > 2, иначе12 < 2. -
caseFirst– в сортировке должны идти первыми прописные или строчные буквы, варианты:"upper"(прописные),"lower"(строчные) или"false"(стандартное для локали, также является значением по умолчанию). Не поддерживается IE11.
-
В подавляющем большинстве случаев подходят стандартные параметры, то есть options указывать не нужно.
Использование:
let result = collator.compare(str1, str2);
Результат compare имеет значение 1 (больше), 0 (равно) или -1 (меньше).
Например:
Выше были использованы полностью стандартные настройки. Они различают регистр символа, но это различие можно убрать, если настроить чувствительность sensitivity:
Даты, Intl.DateTimeFormat
Синтаксис:
// создание
let formatter = new Intl.DateTimeFormat([locales, [options]])
Первый аргумент – такой же, как и в Collator, а в объекте options мы можем определить, какие именно части даты показывать (часы, месяц, год...) и в каком формате.
Полный список свойств options:
| Свойство | Описание | Возможные значения | По умолчанию |
|---|---|---|---|
localeMatcher |
Алгоритм подбора локали |
lookup, best fit
|
best fit
|
formatMatcher |
Алгоритм подбора формата | basic, best fit |
best fit |
hour12 |
Включать ли время в 12-часовом формате | true -- 12-часовой формат, false -- 24-часовой |
|
timeZone |
Временная зона | Временная зона, например Europe/Moscow |
UTC |
weekday |
День недели | narrow, short, long |
|
era |
Эра | narrow, short, long |
|
year |
Год | 2-digit, numeric |
undefined или numeric |
month |
Месяц | 2-digit, numeric, narrow, short, long |
undefined или numeric |
day |
День | 2-digit, numeric |
undefined или numeric |
hour |
Час | 2-digit, numeric |
|
minute |
Минуты | 2-digit, numeric |
|
second |
Секунды | 2-digit, numeric |
|
timeZoneName |
Название таймзоны (нет в IE11) | short, long |
Все локали обязаны поддерживать следующие наборы настроек:
- weekday, year, month, day, hour, minute, second
- weekday, year, month, day
- year, month, day
- year, month
- month, day
- hour, minute, second
Если указанный формат не поддерживается, то настройка formatMatcher задаёт алгоритм подбора наиболее близкого формата: basic – по стандартным правилам и best fit – по умолчанию, на усмотрение окружения (браузера).
Использование:
let dateString = formatter.format(date);
Например:
Длинная дата, с настройками:
Только время:
Числа, Intl.NumberFormat
Форматтер Intl.NumberFormat умеет красиво форматировать не только числа, но и валюту, а также проценты.
Синтаксис:
let formatter = new Intl.NumberFormat([locales[, options]]);
formatter.format(number); // форматирование
Параметры, как и раньше – локаль и опции.
Список опций:
| Свойство | Описание | Возможные значения | По умолчанию |
|---|---|---|---|
localeMatcher |
Алгоритм подбора локали | lookup, best fit |
best fit |
style |
Стиль форматирования | decimal, percent, currency |
decimal |
currency |
Алфавитный код валюты | См. Список кодов валюты, например USD |
|
currencyDisplay |
Показывать валюту в виде кода, локализованного символа или локализованного названия | code, symbol, name |
symbol |
useGrouping |
Разделять ли цифры на группы | true, false |
true |
minimumIntegerDigits |
Минимальное количество цифр целой части | от 1 до 21
|
21 |
minimumFractionDigits |
Минимальное количество десятичных цифр | от 0 до 20 |
для чисел и процентов 0, для валюты зависит от кода. |
maximumFractionDigits |
Максимальное количество десятичных цифр | от minimumFractionDigits до 20. |
для чисел max(minimumFractionDigits, 3), для процентов 0, для валюты зависит от кода. |
minimumSignificantDigits |
Минимальное количество значимых цифр | от 1 до 21 |
1 |
maximumSignificantDigits |
Максимальное количество значимых цифр | от minimumSignificantDigits до 21 |
21 |
Пример без опций:
С ограничением значимых цифр (важны только первые 3):
С опциями для валюты:
С двумя цифрами после запятой:
Методы в Date, String, Number
Методы форматирования также поддерживаются в обычных строках, датах, числах:
String.prototype.localeCompare(that [, locales [, options]])-
Сравнивает строку с другой, с учётом локали, например:
Date.prototype.toLocaleString([locales [, options]])-
Форматирует дату в соответствии с локалью, например:
Date.prototype.toLocaleDateString([locales [, options]])-
То же, что и выше, но опции по умолчанию включают в себя год, месяц, день
Date.prototype.toLocaleTimeString([locales [, options]])-
То же, что и выше, но опции по умолчанию включают в себя часы, минуты, секунды
Number.prototype.toLocaleString([locales [, options]])-
Форматирует число, используя опции
Intl.NumberFormat.
Все эти методы при запуске создают соответствующий объект Intl.* и передают ему опции, можно рассматривать их как укороченные варианты вызова.
Старые IE
В IE10 рекомендуется использовать полифил, например библиотеку https://github.com/andyearnshaw/Intl.js.
Комментарии
<code>, для нескольких строк кода — тег<pre>, если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen...)