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

date-fns предоставляет мощную систему форматирования дат, ориентированную на локали (locales), где каждая операция вывода даты может быть адаптирована под правила конкретного языка, региона и культурных особенностей. Локализация в библиотеке затрагивает не только названия месяцев и дней недели, но и правила построения предложений, порядок слов, склонения и формат относительного времени.

Локаль в date-fns представляет собой набор правил форматирования, сгруппированных в объект. Каждая локаль включает:

  • названия месяцев и дней недели;
  • правила форматирования относительного времени;
  • предопределённые форматы даты и времени;
  • грамматические правила (pluralization rules);
  • сокращённые и полные формы слов.

Локали не подключаются глобально автоматически — каждая функция получает локаль явно через опции locale.

Подключение локалей

Локали импортируются отдельно, чтобы минимизировать размер бандла и обеспечить tree-shaking.

import { format } from 'date-fns'
import { ru } from 'date-fns/locale'

Использование локали в форматировании:

format(new Date(2026, 0, 24), 'PPPP', { locale: ru })

Результат будет соответствовать русской грамматике и правилам вывода даты.

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

Функция format является центральной для локализованного вывода даты. Она использует токены форматирования, но их интерпретация зависит от локали.

Базовое форматирование

import { format } from 'date-fns'
import { enUS, ru } from 'date-fns/locale'

const date = new Date(2026, 4, 22)

format(date, 'PPPP', { locale: enUS })
format(date, 'PPPP', { locale: ru })

Один и тот же шаблон 'PPPP' даёт разные результаты:

  • английская локаль: Friday, May 22nd, 2026
  • русская локаль: пятница, 22 мая 2026 г.

Токены и их локализация

Форматирование в date-fns основано на токенах:

  • PPP, PPPP — предустановленные форматы;
  • EEEE — день недели;
  • LLLL — месяц;
  • do — порядковый день месяца.

Локаль влияет на то, как интерпретируются эти токены.

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

format(date, 'EEEE', { locale: enUS }) // Friday
format(date, 'EEEE', { locale: ru })   // пятница

Форматирование относительного времени

Функция formatDistance и её расширенные версии используют локали для построения естественного языка.

import { formatDistance } from 'date-fns'
import { ru } from 'date-fns/locale'

formatDistance(
  new Date(2026, 4, 22),
  new Date(2026, 4, 20),
  { locale: ru }
)

Результат: «2 дня назад» или «через 2 дня» в зависимости от порядка дат.

Грамматическая модель

Локали определяют:

  • формы единственного и множественного числа;
  • падежи (для языков, где это применимо);
  • специальные формы для «1 день», «2 дня», «5 дней».

formatRelative и контекст времени

Функция formatRelative формирует строки относительно текущей даты, например «вчера», «сегодня», «завтра».

import { formatRelative } from 'date-fns'
import { ru } from 'date-fns/locale'

formatRelative(new Date(2026, 4, 22), new Date(2026, 4, 21), {
  locale: ru
})

Локаль задаёт не только слова, но и структуру предложения:

  • английский: “yesterday at 12:00”
  • русский: “вчера в 12:00”

Структура локали

Объект локали в date-fns имеет строгую структуру.

Основные поля

  • formatDistance — правила расстояния между датами;
  • formatLong — длинные форматы дат;
  • formatRelative — правила относительного форматирования;
  • localize — локализация месяцев, дней, периодов;
  • match — парсинг строк обратно в даты.

Пример структуры

const locale = {
  formatDistance: { ... },
  formatLong: { ... },
  formatRelative: { ... },
  localize: { ... },
  match: { ... }
}

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

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

  • months — полные названия месяцев;
  • monthsShort — сокращённые формы;
  • weekdays — дни недели;
  • weekdaysShort — короткие формы;
  • weekdaysMin — минимальные формы.

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

localize: {
  month: (n) => ['январь', 'февраль', ...][n],
  day: (n) => ['воскресенье', 'понедельник', ...][n]
}

Пользовательские локали

date-fns позволяет создавать собственные локали для нестандартных языков или бизнес-форматов.

Пример кастомной локали

const customLocale = {
  localize: {
    month: (n) => ['M1', 'M2', 'M3'][n],
    day: (n) => ['D0', 'D1', 'D2'][n]
  },
  formatLong: {
    date: () => 'yyyy-MM-dd'
  }
}

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

format(new Date(), 'PPP', { locale: customLocale })

Комбинация локали и форматов

Форматирование часто комбинируется с несколькими уровнями шаблонов:

  • стандартные (P, PP, PPP);
  • кастомные (yyyy-MM-dd);
  • относительные (formatRelative);
  • расстояния (formatDistance).

Локаль применяется единообразно ко всем уровням.

Подключение нескольких локалей

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

import { enUS, ru, de } from 'date-fns/locale'

const locales = { en: enUS, ru, de }

function formatDate(date, lang) {
  return format(date, 'PPP', { locale: locales[lang] })
}

Особенности работы локалей в production

Tree-shaking

Импортировать следует только нужные локали:

import { ru } from 'date-fns/locale'

Импорт всей библиотеки локалей увеличивает bundle size.

Иммутабельность

Локали в date-fns являются неизменяемыми объектами. Любые модификации приводят к непредсказуемому поведению форматирования.

Совместимость версий

Некоторые локали могут обновляться независимо от функций форматирования, поэтому важно синхронизировать версии date-fns.

Форматирование дат в SSR и браузере

При серверном рендеринге локаль должна передаваться явно, так как отсутствует доступ к navigator.language.

const locale = ru

const result = format(new Date(), 'PPPP', { locale })

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

import { enUS, ru } from 'date-fns/locale'

const browserLocale =
  navigator.language.startsWith('ru') ? ru : enUS

Интернационализация сложных форматов

Некоторые языки требуют:

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

date-fns решает это через функции в formatRelative и formatDistance, а не через простую подстановку строк.

Пример сложной логики

formatDistance: {
  xDays: (count) => {
    if (count === 1) return '1 день'
    if (count < 5) return `${count} дня`
    return `${count} дней`
  }
}

Итоговая модель локализации

Система локалей date-fns строится вокруг трёх принципов:

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

Такой подход позволяет поддерживать широкий спектр языков без жёсткой зависимости от глобальных настроек окружения.