Форматирование с учетом локали

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


Базовый механизм локалей

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

Установка локали глобально:

moment.locale('ru');

Установка локали для конкретного объекта:

moment().locale('ru').format('LLLL');

Приоритет локали определяется в следующем порядке:

  1. Локаль конкретного объекта moment().locale()
  2. Глобальная локаль moment.locale()
  3. Локаль по умолчанию (обычно en)

Стандартные локализованные форматы

Moment.js предоставляет набор предопределённых токенов, зависящих от локали. Эти форматы автоматически адаптируются под язык.

Основные шаблоны:

  • L — короткая дата
  • LL — расширенная дата
  • LLL — дата и время (расширенно)
  • LLLL — полное текстовое представление даты и времени
  • LT — локализованное время

Пример:

moment().locale('ru').format('L');   // 21.05.2026
moment().locale('ru').format('LL');  // 21 мая 2026 г.
moment().locale('ru').format('LLLL'); // четверг, 21 мая 2026 г., 14:30

В английской локали результат будет отличаться:

moment().locale('en').format('LLLL');
// Thursday, May 21, 2026 2:30 PM

Локализованные названия месяцев и дней недели

Каждая локаль содержит массивы:

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

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

  • MMMM — полное название месяца
  • MMM — сокращённое название месяца
  • dddd — полное название дня недели
  • ddd — сокращённое название дня недели

Пример:

moment().locale('ru').format('dddd, D MMMM');
// четверг, 21 мая
moment().locale('en').format('dddd, D MMMM');
// Thursday, 21 May

Токены форматирования и влияние локали

Форматирование в Moment.js основано на токенах, однако их отображение зависит от локали.

Примеры ключевых токенов

  • D — день месяца
  • Do — день месяца с порядковым суффиксом (1st, 2nd, 3rd)
  • M — месяц числом
  • MMM, MMMM — текстовое название месяца
  • YY, YYYY — год
  • H, HH — часы (24-часовой формат)
  • h, hh — часы (12-часовой формат)
  • a, A — am/pm или локализованный аналог

Пример различий:

moment().locale('en').format('Do MMMM YYYY');
// 21st May 2026

moment().locale('ru').format('Do MMMM YYYY');
// 21 мая 2026

В русском языке порядковые суффиксы не используются, и токен Do фактически сводится к обычному числу.


Локализованное время суток и обозначения AM/PM

В разных локалях обозначения времени суток могут различаться. В английском используется стандартная система AM/PM:

moment().locale('en').format('h:mm A');
// 2:30 PM

В других локалях может применяться 24-часовой формат или локализованные обозначения времени суток:

moment().locale('ru').format('HH:mm');
// 14:30

Настройка и переопределение локали

Локали могут быть изменены или дополнены через moment.defineLocale.

Пример переопределения части локали:

moment.defineLocale('custom', {
  months: 'Янв_Фев_Мар_Апр_Май_Июн_Июл_Авг_Сен_Окт_Ноя_Дек'.split('_'),
  monthsShort: 'Янв_Фев_Мар_Апр_Май_Июн_Июл_Авг_Сен_Окт_Ноя_Дек'.split('_'),
  weekdays: 'Воскресенье_Понедельник_Вторник_Среда_Четверг_Пятница_Суббота'.split('_'),
  weekdaysShort: 'Вс_Пн_Вт_Ср_Чт_Пт_Сб'.split('_'),
  weekdaysMin: 'Вс_Пн_Вт_Ср_Чт_Пт_Сб'.split('_'),
  longDateFormat: {
    L: 'DD.MM.YYYY',
    LL: 'D MMMM YYYY',
    LLL: 'D MMMM YYYY HH:mm'
  }
});

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

moment().locale('custom').format('LL');

Данные локали через localeData

Moment.js позволяет извлекать информацию о текущей локали без форматирования:

const localeData = moment.localeData();

localeData.months();        // массив месяцев
localeData.weekdays();      // массив дней недели
localeData.longDateFormat('LL');

Смена локали влияет на возвращаемые данные:

moment.locale('ru');
moment.localeData().months()[0]; // "январь"

moment.locale('en');
moment.localeData().months()[0]; // "January"

Календарные выражения и локаль

Функция calendar() также зависит от локали и возвращает относительные даты в текстовом виде:

moment().calendar();

Примеры:

  • Сегодня
  • Завтра
  • Вчера
  • На прошлой неделе

В английской локали:

  • Today at 2:30 PM
  • Tomorrow at 2:30 PM
  • Yesterday at 2:30 PM

В русской локали:

  • Сегодня в 14:30
  • Завтра в 14:30
  • Вчера в 14:30

Относительное время и локализация

Функция fromNow() также использует локализацию:

moment().add(5, 'days').fromNow();

Результаты:

  • English: in 5 days
  • Russian: через 5 дней

Локаль определяет грамматические формы чисел и предлоги.


Локаль и парсинг строк

Хотя основное назначение локали — форматирование, она также влияет на парсинг:

moment('21 мая 2026', 'D MMMM YYYY', 'ru');

Без указания локали строка с русскими месяцами может быть интерпретирована некорректно.


Глобальная смена локали и побочные эффекты

Глобальная установка локали влияет на все последующие операции:

moment.locale('ru');

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

Более безопасный подход:

moment().locale(userLocale).format('LLL');

Поведение при отсутствии локали

Если локаль не загружена, Moment.js возвращается к en. Это может приводить к несоответствию языков в интерфейсе:

moment.locale('unknown-locale');
moment().format('LL');
// вывод будет на английском

Сравнение локалей в одном приложении

Одновременное использование разных локалей возможно через изоляцию объектов:

const ruDate = moment().locale('ru').format('LLLL');
const enDate = moment().locale('en').format('LLLL');

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


Особенности работы с многоязычными интерфейсами

В интерфейсах с динамическим переключением языка важно учитывать:

  • необходимость загрузки локалей заранее
  • синхронизацию форматов между клиентом и сервером
  • единообразие временных зон и локалей
  • влияние локали на относительное время и календарные строки

Форматирование через локаль становится частью бизнес-логики отображения, а не только визуального слоя.