Библиотека Globalize предоставляет мощный механизм интернационализации приложений, включая форматирование дат, чисел, валют и сообщений. Одной из наиболее гибких возможностей являются пользовательские шаблоны, позволяющие полностью контролировать отображение локализованных данных.
Пользовательские шаблоны применяются при:
В основе системы лежат данные стандарта CLDR (Common Locale Data Repository). Библиотека использует готовые локализационные шаблоны, но также позволяет создавать собственные.
Основные компоненты:
| Компонент | Назначение |
|---|---|
| CLDR | Источник локализационных данных |
| Globalize | API для интернационализации |
| Formatter | Функция форматирования |
| Message formatter | Обработчик сообщений |
| Custom pattern | Пользовательский шаблон |
const dateFormatter = Globalize.dateFormatter({
datetime: "medium"
});
console.log(dateFormatter(new Date()));
Результат зависит от текущей локали.
Параметр raw позволяет задавать формат вручную.
const formatter = Globalize.dateFormatter({
raw: "dd MMMM yyyy"
});
console.log(formatter(new Date()));
| Шаблон | Значение |
|---|---|
| dd | День |
| MM | Месяц |
| MMMM | Полное название месяца |
| yy | Короткий год |
| yyyy | Полный год |
| HH | Часы 24h |
| mm | Минуты |
| ss | Секунды |
const formatter = Globalize.dateFormatter({
raw: "EEEE, d MMMM yyyy HH:mm:ss"
});
console.log(formatter(new Date()));
Пример вывода:
понедельник, 12 мая 2026 14:35:10
Один и тот же шаблон автоматически адаптируется под локаль.
Globalize.locale("en");
const enFormatter = Globalize.dateFormatter({
raw: "EEEE, MMMM d"
});
console.log(enFormatter(new Date()));
Globalize.locale("ru");
const ruFormatter = Globalize.dateFormatter({
raw: "EEEE, MMMM d"
});
console.log(ruFormatter(new Date()));
Результаты:
Monday, May 12
понедельник, май 12
const formatter = Globalize.numberFormatter();
console.log(formatter(12345.678));
const formatter = Globalize.numberFormatter({
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(formatter(12345.6));
Результат:
12 345,60
const formatter = Globalize.numberFormatter({
style: "percent",
minimumFractionDigits: 1
});
console.log(formatter(0.756));
Результат:
75,6 %
const formatter = Globalize.currencyFormatter("USD");
console.log(formatter(1500));
const formatter = Globalize.currencyFormatter("EUR", {
minimumFractionDigits: 0
});
console.log(formatter(5000));
Иногда требуется полностью изменить стандартное представление.
const formatter = Globalize.numberFormatter({
style: "decimal"
});
const value = formatter(1000);
console.log(`${value} EUR`);
Результат:
1 000 EUR
Для локализации интерфейсов используется модуль сообщений.
Globalize.loadMessages({
ru: {
greeting: "Привет, {name}!"
}
});
Globalize.locale("ru");
const formatter = Globalize.messageFormatter("greeting");
console.log(formatter({
name: "Анна"
}));
Globalize.loadMessages({
ru: {
order: "Заказ №{id} оформлен на сумму {sum}"
}
});
const formatter = Globalize.messageFormatter("order");
console.log(formatter({
id: 105,
sum: "15 000 ₽"
}));
Globalize.loadMessages({
ru: {
user: {
profile: {
title: "Профиль пользователя {name}"
}
}
}
});
const formatter =
Globalize.messageFormatter("user/profile/title");
console.log(formatter({
name: "Иван"
}));
Globalize поддерживает ICU MessageFormat.
Globalize.loadMessages({
ru: {
photos:
"{count, plural," +
" one {# фотография}" +
" few {# фотографии}" +
" many {# фотографий}" +
" other {# фотографии}" +
"}"
}
});
const formatter =
Globalize.messageFormatter("photos");
console.log(formatter({ count: 1 }));
console.log(formatter({ count: 3 }));
console.log(formatter({ count: 10 }));
Результат:
1 фотография
3 фотографии
10 фотографий
Globalize.loadMessages({
ru: {
genderMessage:
"{gender, select," +
" male {Он вошёл}" +
" female {Она вошла}" +
" other {Пользователь вошёл}" +
"}"
}
});
const formatter =
Globalize.messageFormatter("genderMessage");
console.log(formatter({
gender: "female"
}));
Globalize.loadMessages({
ru: {
notification:
"{name} отправил {count, plural," +
" one {# сообщение}" +
" few {# сообщения}" +
" many {# сообщений}" +
" other {# сообщения}" +
"}"
}
});
const formatter =
Globalize.messageFormatter("notification");
console.log(formatter({
name: "Алексей",
count: 5
}));
Часто возникает необходимость централизовать работу с шаблонами.
class TemplateManager {
constructor(locale) {
this.globalize = new Globalize(locale);
}
message(path, data) {
const formatter =
this.globalize.messageFormatter(path);
return formatter(data);
}
date(pattern, value) {
const formatter =
this.globalize.dateFormatter({
raw: pattern
});
return formatter(value);
}
number(options, value) {
const formatter =
this.globalize.numberFormatter(options);
return formatter(value);
}
}
Использование:
const manager = new TemplateManager("ru");
console.log(
manager.date(
"dd.MM.yyyy",
new Date()
)
);
Шаблон может формироваться во время выполнения.
function createDatePattern(showTime) {
return showTime
? "dd.MM.yyyy HH:mm"
: "dd.MM.yyyy";
}
const formatter =
Globalize.dateFormatter({
raw: createDatePattern(true)
});
console.log(formatter(new Date()));
const adminDateFormatter =
Globalize.dateFormatter({
raw: "yyyy-MM-dd HH:mm:ss"
});
console.log(
adminDateFormatter(new Date())
);
Подобный формат удобен:
const uiFormatter =
Globalize.dateFormatter({
raw: "d MMM yyyy"
});
console.log(
uiFormatter(new Date())
);
Компактные шаблоны улучшают читаемость интерфейса.
const templates = {
shortDate: "dd.MM.yyyy",
longDate: "EEEE, d MMMM yyyy",
time: "HH:mm:ss"
};
Использование:
const formatter =
Globalize.dateFormatter({
raw: templates.longDate
});
Создание formatter-объектов является затратной операцией.
function formatDate(date) {
return Globalize.dateFormatter({
raw: "dd.MM.yyyy"
})(date);
}
const formatter =
Globalize.dateFormatter({
raw: "dd.MM.yyyy"
});
function formatDate(date) {
return formatter(date);
}
Globalize.dateFormatter({
raw: "INVALID_PATTERN"
});
Подобная конструкция может привести к некорректному выводу.
Globalize.locale("xx");
Если локаль не загружена, форматирование завершится ошибкой.
const formatter =
Globalize.messageFormatter("unknown.path");
При отсутствии шаблона сообщение не будет найдено.
function safeMessageFormatter(path) {
try {
return Globalize.messageFormatter(path);
} catch (e) {
return () => "Ошибка локализации";
}
}
Крупные приложения обычно разделяют шаблоны по модулям.
Globalize.loadMessages({
ru: {
auth: {
login: {
title: "Вход"
}
},
profile: {
title: "Профиль"
},
dashboard: {
stats: {
users: "Пользователи"
}
}
}
});
Пример интеграции с React:
function UserCard({ user }) {
const formatter =
Globalize.messageFormatter(
"profile.title"
);
return (
<h1>
{formatter({
name: user.name
})}
</h1>
);
}
Пример интеграции с Vue.js:
export default {
methods: {
formatDate(date) {
return Globalize
.dateFormatter({
raw: "dd.MM.yyyy"
})(date);
}
}
};
const formatters = {
shortDate:
Globalize.dateFormatter({
raw: "dd.MM.yyyy"
}),
money:
Globalize.currencyFormatter(
"RUB"
)
};
Использование:
console.log(
formatters.shortDate(new Date())
);
console.log(
formatters.money(5000)
);
Globalize использует синтаксис ICU.
Основные конструкции:
| Конструкция | Назначение |
|---|---|
{name} |
Подстановка |
plural |
Множественное число |
select |
Выбор варианта |
# |
Текущее значение |
Globalize.loadMessages({
ru: {
cart:
"{count, plural," +
" =0 {Корзина пуста}" +
" one {В корзине # товар}" +
" few {В корзине # товара}" +
" many {В корзине # товаров}" +
" other {В корзине # товара}" +
"}"
}
});
Шаблоны позволяют переносить текстовую бизнес-логику из кода в локализационные файлы.
if (count === 1) {
text = "1 товар";
}
formatter({ count });
Подобный подход:
На производительность влияют:
const authMessages = {
login: "Вход",
logout: "Выход"
};
const profileMessages = {
title: "Профиль"
};
Globalize.loadMessages({
ru: {
auth: authMessages,
profile: profileMessages
}
});
Сервер может передавать шаблоны клиенту:
{
"invoiceDate": "dd.MM.yyyy",
"currencyFormat": "RUB"
}
Клиент использует их динамически:
const formatter =
Globalize.dateFormatter({
raw: config.invoiceDate
});
Структура локализаций:
locales/
ru/
common.json
auth.json
en/
common.json
auth.json
Такой подход: