Пользовательские шаблоны

Библиотека Globalize предоставляет мощный механизм интернационализации приложений, включая форматирование дат, чисел, валют и сообщений. Одной из наиболее гибких возможностей являются пользовательские шаблоны, позволяющие полностью контролировать отображение локализованных данных.

Пользовательские шаблоны применяются при:

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

Архитектура шаблонов в 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

MessageFormatter и шаблоны сообщений

Для локализации интерфейсов используется модуль сообщений.

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 фотографий

Пользовательские шаблоны с select

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-функций

Создание 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");

При отсутствии шаблона сообщение не будет найдено.


Валидация шаблонов

Проверка существования formatter

function safeMessageFormatter(path) {
    try {
        return Globalize.messageFormatter(path);
    } catch (e) {
        return () => "Ошибка локализации";
    }
}

Организация структуры шаблонов

Крупные приложения обычно разделяют шаблоны по модулям.

Globalize.loadMessages({
    ru: {
        auth: {
            login: {
                title: "Вход"
            }
        },

        profile: {
            title: "Профиль"
        },

        dashboard: {
            stats: {
                users: "Пользователи"
            }
        }
    }
});

Шаблоны и React

Пример интеграции с React:

function UserCard({ user }) {
    const formatter =
        Globalize.messageFormatter(
            "profile.title"
        );

    return (
        <h1>
            {formatter({
                name: user.name
            })}
        </h1>
    );
}

Шаблоны и Vue

Пример интеграции с Vue.js:

export default {
    methods: {
        formatDate(date) {
            return Globalize
                .dateFormatter({
                    raw: "dd.MM.yyyy"
                })(date);
        }
    }
};

Пользовательские helper-функции

const formatters = {
    shortDate:
        Globalize.dateFormatter({
            raw: "dd.MM.yyyy"
        }),

    money:
        Globalize.currencyFormatter(
            "RUB"
        )
};

Использование:

console.log(
    formatters.shortDate(new Date())
);

console.log(
    formatters.money(5000)
);

ICU MessageFormat как основа шаблонов

Globalize использует синтаксис ICU.

Основные конструкции:

Конструкция Назначение
{name} Подстановка
plural Множественное число
select Выбор варианта
# Текущее значение

Сложные ICU-шаблоны

Globalize.loadMessages({
    ru: {
        cart:
            "{count, plural," +
            " =0 {Корзина пуста}" +
            " one {В корзине # товар}" +
            " few {В корзине # товара}" +
            " many {В корзине # товаров}" +
            " other {В корзине # товара}" +
            "}"
    }
});

Локализация бизнес-логики

Шаблоны позволяют переносить текстовую бизнес-логику из кода в локализационные файлы.

Без шаблонов

if (count === 1) {
    text = "1 товар";
}

С шаблонами

formatter({ count });

Подобный подход:

  • уменьшает количество условий;
  • упрощает перевод;
  • делает код чище;
  • централизует локализацию.

Производительность пользовательских шаблонов

На производительность влияют:

  • создание formatter-функций;
  • загрузка CLDR;
  • объём ICU-шаблонов;
  • количество локалей.

Практики оптимизации

  • кэширование formatter-объектов;
  • ленивое подключение локалей;
  • разделение сообщений по модулям;
  • минимизация повторных вычислений.

Модульная организация шаблонов

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

Такой подход:

  • упрощает поддержку;
  • облегчает масштабирование;
  • уменьшает конфликт локализаций;
  • позволяет разделять зоны ответственности.

Типичные сценарии применения

Электронная коммерция

  • форматирование цен;
  • локализация корзины;
  • шаблоны уведомлений.

CRM-системы

  • даты событий;
  • сообщения пользователей;
  • статусы объектов.

Аналитические панели

  • локализованные числа;
  • валюты;
  • временные диапазоны.

SaaS-платформы

  • мультиязычный интерфейс;
  • локализованные уведомления;
  • шаблоны отчётов.