Создание собственной локализации

Pikaday реализует механизм локализации через конфигурационный объект i18n, позволяющий полностью переопределять текстовые элементы календаря, названия месяцев, дней недели и навигационные подписи. Такой подход обеспечивает адаптацию интерфейса под любые языковые среды без изменения исходного кода библиотеки.

Базовая локализация в Pikaday задаётся через поле i18n, которое передаётся при инициализации календаря. Объект содержит набор строковых и массивных значений, определяющих все текстовые элементы интерфейса:

const picker = new Pikaday({
  field: document.getElementById('date'),
  i18n: {
    previousMonth: 'Previous Month',
    nextMonth: 'Next Month',
    months: [],
    weekdays: [],
    weekdaysShort: []
  }
});

Каждое поле выполняет строго определённую роль:

  • previousMonth — подпись кнопки перехода к предыдущему месяцу
  • nextMonth — подпись кнопки перехода к следующему месяцу
  • months — массив названий месяцев
  • weekdays — полные названия дней недели
  • weekdaysShort — сокращённые названия дней недели

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

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

Массив months должен содержать 12 элементов, соответствующих календарным месяцам, начиная с января. Внутренний механизм Pikaday использует индекс месяца (0–11), напрямую обращаясь к этому массиву.

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

months: [
  'Январь', 'Февраль', 'Март', 'Апрель',
  'Май', 'Июнь', 'Июль', 'Август',
  'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'
]

Важно учитывать, что строки могут использоваться в заголовке календаря, поэтому допустимы как формы именительного падежа, так и сокращённые варианты, если это соответствует UI-дизайну.

При необходимости динамической локализации массив может формироваться на основе внешних i18n-библиотек или API переводов, однако результат должен строго соответствовать фиксированному порядку месяцев.

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

Поля weekdays и weekdaysShort управляют отображением строк заголовков календарной сетки.

weekdays: [
  'Воскресенье', 'Понедельник', 'Вторник',
  'Среда', 'Четверг', 'Пятница', 'Суббота'
],
weekdaysShort: [
  'Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'
]

Порядок элементов фиксирован и соответствует стандарту JavaScript Date.getDay(), где 0 соответствует воскресенью.

Расхождение порядка приводит к смещению отображения дней недели и некорректному позиционированию дат в сетке календаря.

Навигационные элементы

Поля previousMonth и nextMonth используются в элементах управления календарём. Они не влияют на функциональность, но определяют текстовые подписи кнопок навигации.

previousMonth: 'Предыдущий месяц',
nextMonth: 'Следующий месяц'

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

  • aria-label для доступности
  • tooltip при наведении
  • текст внутри кнопок (в зависимости от темы оформления)

Корректная локализация этих значений критична для поддержки screen reader и общей доступности интерфейса.

Полная кастомизация локализации

Полностью кастомизированный объект i18n может объединять все элементы:

const ruLocale = {
  previousMonth: 'Назад',
  nextMonth: 'Вперёд',
  months: [
    'Январь', 'Февраль', 'Март', 'Апрель',
    'Май', 'Июнь', 'Июль', 'Август',
    'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'
  ],
  weekdays: [
    'Воскресенье', 'Понедельник', 'Вторник',
    'Среда', 'Четверг', 'Пятница', 'Суббота'
  ],
  weekdaysShort: [
    'Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'
  ]
};

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

const picker = new Pikaday({
  field: document.getElementById('date'),
  i18n: ruLocale
});

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

Интеграция с внешними системами локализации

При использовании систем вроде i18next или Intl генерация объекта i18n часто выполняется динамически. В этом случае формируется промежуточный слой адаптации:

function buildPikadayLocale(t) {
  return {
    previousMonth: t('calendar.prev'),
    nextMonth: t('calendar.next'),
    months: t('calendar.months', { returnObjects: true }),
    weekdays: t('calendar.weekdays', { returnObjects: true }),
    weekdaysShort: t('calendar.weekdaysShort', { returnObjects: true })
  };
}

Ключевой момент заключается в том, что Pikaday не интерпретирует локализационные ключи — только готовые строки. Поэтому вся логика перевода должна завершаться до передачи объекта в инициализацию.

Особенности порядка и индексации

Внутренняя логика календаря использует стандартные числовые индексы:

  • месяцы: 0–11
  • дни недели: 0–6

Это означает, что любые пользовательские массивы должны быть строго синхронизированы с этими индексами. Любое смещение (например, начало недели с понедельника) требует дополнительной настройки логики рендеринга, а не только изменения массива weekdays.

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

const picker = new Pikaday({
  firstDay: 1
});

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

Работа с сокращениями и формами слов

Поле weekdaysShort часто используется в ограниченных UI-контейнерах, где полные названия не помещаются. Важно учитывать, что библиотека не выполняет автоматическое сокращение строк.

Пример несоответствия:

  • корректно: Пон, Втр
  • некорректно: автоматическое преобразование из Понедельник

Таким образом, оба массива (weekdays и weekdaysShort) должны поддерживаться параллельно и синхронно обновляться при изменении языка.

Расширенные сценарии локализации

При сложных интерфейсах может потребоваться переключение языка без пересоздания страницы. В этом случае создаётся новый экземпляр календаря с обновлённым i18n:

picker.destroy();

const newPicker = new Pikaday({
  field: document.getElementById('date'),
  i18n: newLocale
});

Такой подход объясняется тем, что Pikaday не предусматривает полноценного реактивного обновления локализационного объекта после инициализации.

Альтернативный вариант — прямое переопределение свойств:

picker._o.i18n = newLocale;
picker.draw();

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

Совместимость локализации с форматированием дат

Локализация интерфейса календаря не влияет на формат вывода даты, который задаётся отдельно через toString или кастомный парсер:

const picker = new Pikaday({
  toString(date) {
    return date.toLocaleDateString('ru-RU');
  }
});

Таким образом разделяются два уровня:

  • визуальная локализация интерфейса (i18n)
  • форматирование значения даты (toString, parse)

Смешивание этих уровней приводит к неоднородному поведению календаря при смене языка.

Использование внешних наборов локализаций

Готовые локализации часто выносятся в отдельные файлы, подключаемые по требованию. Пример структуры модуля:

export const ru = {
  previousMonth: 'Назад',
  nextMonth: 'Вперёд',
  months: [...],
  weekdays: [...],
  weekdaysShort: [...]
};

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

Исходный код библиотеки доступен в репозитории