Загрузка локальных файлов

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

Каждый файл локали представляет собой модуль, экспортирующий объект с набором правил форматирования. Эти правила описывают текстовые шаблоны для различных временных диапазонов:

  • секунды
  • минуты
  • часы
  • дни
  • недели
  • месяцы
  • годы

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

export default {
  locale: 'ru',
  name: 'Russian',
  now: 'только что',
  seconds: '%s секунд назад',
  minute: 'минуту назад',
  minutes: '%s минут назад',
  hour: 'час назад',
  hours: '%s часов назад',
  day: 'вчера',
  days: '%s дней назад',
  month: 'месяц назад',
  months: '%s месяцев назад',
  year: 'год назад',
  years: '%s лет назад'
}

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

Способы подключения локальных файлов

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

Импорт в модульной среде

При использовании ES Modules локаль подключается напрямую из каталога локализаций:

import { format, register } from 'timeago.js'
import ruLocale from 'timeago.js/lib/lang/ru'

register('ru', ruLocale)

После регистрации идентификатор ru становится доступен для форматирования времени.

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

В окружениях Node.js с CommonJS используется require:

const { format, register } = require('timeago.js')
const ruLocale = require('timeago.js/lib/lang/ru')

register('ru', ruLocale)

Регистрация локали выполняется один раз на уровне приложения, после чего она доступна глобально внутри экземпляров форматирования.

Механизм регистрации локали

Регистрация локали происходит через функцию register, которая добавляет языковой пакет в внутренний реестр. Этот реестр представляет собой объект, где ключом выступает идентификатор языка, а значением — объект правил форматирования.

Принцип работы:

  1. Передача идентификатора локали
  2. Привязка объекта правил
  3. Сохранение в глобальном реестре
  4. Использование при вызове форматирования

После регистрации локаль становится доступной для передачи в функцию форматирования времени:

format(date, 'ru')

Подключение локалей через индексные файлы

В некоторых сборках библиотека предоставляет централизованный доступ к локалям через индексный файл, который экспортирует все доступные языки:

import ru from 'timeago.js/lib/lang/ru'
import en from 'timeago.js/lib/lang/en'
import de from 'timeago.js/lib/lang/de'

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

Динамическая загрузка локалей

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

async function loadLocale(locale) {
  const module = await import(`timeago.js/lib/lang/${locale}`)
  register(locale, module.default)
}

Такой подход позволяет:

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

Работа с бандлерами

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

Webpack context

Webpack может ограничивать динамические пути, поэтому используется require.context:

const locales = require.context('timeago.js/lib/lang', false, /\.js$/)

locales.keys().forEach(key => {
  const locale = locales(key)
  register(key.replace('./', '').replace('.js', ''), locale)
})

Vite и ESM

Vite поддерживает нативные динамические импорты без дополнительной конфигурации:

const modules = import.meta.glob('timeago.js/lib/lang/*.js')

for (const path in modules) {
  const locale = await modules[path]()
  const name = path.split('/').pop().replace('.js', '')
  register(name, locale.default)
}

Приоритет локалей и fallback

Если при вызове форматирования указана локаль, которая не зарегистрирована, библиотека использует поведение по умолчанию. Обычно это английская локаль или встроенный fallback.

Логика разрешения:

  1. Проверка наличия локали в реестре
  2. Использование указанной локали
  3. Переход к fallback-локали
  4. Использование базового формата

Такой механизм предотвращает ошибки при отсутствии перевода.

Изоляция локалей в разных окружениях

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

Типовая структура инициализации:

import { register } from 'timeago.js'
import ru from 'timeago.js/lib/lang/ru'
import en from 'timeago.js/lib/lang/en'

register('ru', ru)
register('en', en)

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

Оптимизация загрузки локалей

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

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

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

Взаимодействие локалей с форматированием

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

Например:

  • 45 секунд → “45 секунд назад”
  • 5 минут → “5 минут назад”
  • 1 день → “вчера”

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

Кастомизация локализационных файлов

Локали могут быть изменены или расширены без изменения ядра библиотеки. Это достигается путём создания собственного объекта локали и его регистрации:

const customRu = {
  locale: 'ru',
  seconds: 'только что',
  minute: 'минуту назад',
  minutes: '%s минут назад'
}

register('ru-custom', customRu)

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