Форматирование чисел, валют, процентов и дат в разных странах существенно отличается. Одной из наиболее заметных особенностей локализации являются разделители:
В англоязычных странах число может выглядеть так:
1,234,567.89
Во многих европейских локалях используется другой формат:
1 234 567,89
В некоторых странах применяются нестандартные схемы группировки:
12,34,56,789
Библиотека Globalize позволяет корректно обрабатывать подобные различия на основе данных CLDR (Common Locale Data Repository), автоматически подставляя нужные символы и правила форматирования.
Для работы с локалями необходимы:
cldr-data.Установка:
npm install globalize cldr-data
Подключение:
const Globalize = require("globalize");
Globalize.load(
require("cldr-data/main/en/numbers.json"),
require("cldr-data/main/fr/numbers.json"),
require("cldr-data/main/de/numbers.json"),
require("cldr-data/supplemental/likelySubtags.json"),
require("cldr-data/supplemental/numberingSystems.json")
);
В локали en дробная часть отделяется точкой.
const en = new Globalize("en");
console.log(en.formatNumber(1234.56));
Результат:
1,234.56
Здесь:
, — разделитель тысяч;. — десятичный разделитель.Во французском формате десятичным разделителем является запятая.
const fr = new Globalize("fr");
console.log(fr.formatNumber(1234.56));
Результат:
1 234,56
Особенности:
В немецком языке также применяется запятая для дробной части.
const de = new Globalize("de");
console.log(de.formatNumber(1234.56));
Результат:
1.234,56
Здесь:
. используется как разделитель тысяч;, — десятичный разделитель.Globalize извлекает правила из CLDR автоматически. Разработчику не требуется вручную задавать символы.
Пример:
function formatPrice(locale, value) {
const g = new Globalize(locale);
return g.formatNumber(value);
}
console.log(formatPrice("en", 12345.67));
console.log(formatPrice("fr", 12345.67));
console.log(formatPrice("de", 12345.67));
Результат:
12,345.67
12 345,67
12.345,67
Наиболее распространённая схема:
1 000 000
Globalize автоматически вставляет нужный символ.
const en = new Globalize("en");
console.log(en.formatNumber(1000000));
Результат:
1,000,000
В Индии применяется особая схема:
12,34,56,789
Подключение локали:
Globalize.load(
require("cldr-data/main/en-IN/numbers.json")
);
const india = new Globalize("en-IN");
console.log(india.formatNumber(123456789));
Результат:
12,34,56,789
Особенность:
Разделители особенно важны при отображении денежных значений.
Подключение данных:
Globalize.load(
require("cldr-data/main/en/currencies.json"),
require("cldr-data/main/fr/currencies.json"),
require("cldr-data/main/de/currencies.json")
);
const en = new Globalize("en");
console.log(
en.formatCurrency(1234567.89, "USD")
);
Результат:
$1,234,567.89
const fr = new Globalize("fr");
console.log(
fr.formatCurrency(1234567.89, "EUR")
);
Результат:
1 234 567,89 €
Особенности:
const de = new Globalize("de");
console.log(
de.formatCurrency(1234567.89, "EUR")
);
Результат:
1.234.567,89 €
Форматирование — только часть задачи. Важно также правильно интерпретировать пользовательский ввод.
parseFloatparseFloat("1,234.56");
Результат:
1
Метод останавливается на запятой.
Для европейского формата ситуация ещё хуже:
parseFloat("1.234,56");
Результат:
1.234
numberParserGlobalize предоставляет локализованный парсер.
const en = new Globalize("en");
const parser = en.numberParser();
console.log(parser("1,234.56"));
Результат:
1234.56
const de = new Globalize("de");
const parser = de.numberParser();
console.log(parser("1.234,56"));
Результат:
1234.56
Globalize автоматически:
Парсер может работать и с денежными значениями.
const fr = new Globalize("fr");
const parser = fr.numberParser({
style: "currency",
currency: "EUR"
});
console.log(
parser("1 234,56 €")
);
Результат:
1234.56
Некоторые локали используют:
Пример французского разделителя:
1 234 567
Здесь используется символ:
U+202F
Это узкий неразрывный пробел.
Globalize корректно работает с такими символами благодаря данным CLDR.
Разделители также влияют на формат процентов.
const en = new Globalize("en");
console.log(
en.formatNumber(0.256, {
style: "percent"
})
);
Результат:
26%
const fr = new Globalize("fr");
console.log(
fr.formatNumber(0.256, {
style: "percent"
})
);
Результат:
26 %
Во французском формате между числом и знаком процента добавляется пробел.
Типичная ошибка — ожидание только одного формата числа.
Неправильно:
const value = parseFloat(userInput);
Проблемы:
Корректный подход:
function parseLocalizedNumber(locale, value) {
const g = new Globalize(locale);
const parser = g.numberParser();
return parser(value);
}
Использование:
console.log(
parseLocalizedNumber("fr", "1 234,56")
);
console.log(
parseLocalizedNumber("de", "1.234,56")
);
Globalize поддерживает компактное представление:
const en = new Globalize("en");
const formatter = en.numberFormatter({
compact: "short"
});
console.log(formatter(1200));
Результат:
1.2K
Во французской локали формат будет другим:
const fr = new Globalize("fr");
const formatter = fr.numberFormatter({
compact: "short"
});
console.log(formatter(1200));
Результат:
1,2 k
Различия:
Разделители сохраняются независимо от количества знаков после запятой.
const de = new Globalize("de");
const formatter = de.numberFormatter({
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(formatter(1234));
Результат:
1.234,00
Globalize позволяет создавать повторно используемые форматтеры.
const locale = new Globalize("fr");
const moneyFormatter =
locale.currencyFormatter("EUR");
const percentFormatter =
locale.numberFormatter({
style: "percent"
});
console.log(
moneyFormatter(1234.5)
);
console.log(
percentFormatter(0.45)
);
Результат:
1 234,50 €
45 %
Часто встречается попытка заменить символы вручную:
value.replace(",", ".");
Такой подход приводит к ошибкам.
Пример:
"1.234,56".replace(",", ".");
Результат:
1.234.56
Полученная строка уже не является корректным числом.
Дополнительные проблемы:
Globalize устраняет необходимость ручной обработки.
В приложении может использоваться несколько языков одновременно.
const locales = ["en", "fr", "de"];
const value = 1234567.89;
locales.forEach(locale => {
const g = new Globalize(locale);
console.log(
locale,
g.formatNumber(value)
);
});
Результат:
en 1,234,567.89
fr 1 234 567,89
de 1.234.567,89
Локаль часто определяется:
Пример:
const locale =
navigator.language;
const g =
new Globalize(locale);
console.log(
g.formatNumber(12345.67)
);
После парсинга рекомендуется проверять результат.
const parser =
new Globalize("fr")
.numberParser();
const result =
parser("1 234,56");
if (isNaN(result)) {
console.log("Ошибка формата");
} else {
console.log(result);
}
Создание форматтера — относительно дорогая операция.
Неэффективно:
function format(value) {
return new Globalize("en")
.formatNumber(value);
}
Лучше:
const formatter =
new Globalize("en")
.numberFormatter();
function format(value) {
return formatter(value);
}
Особенно важно при:
Корректная локализация критична для:
Неправильные разделители могут приводить к:
Globalize обеспечивает единообразную и стандартизированную обработку числовых форматов независимо от региона пользователя.