Метод setLocale

timeago.js не имеет публичного метода setLocale. Это осознанное архитектурное решение: вместо глобальной “текущей локали” библиотека требует явного указания локали в каждом вызове format и render. Тем не менее поведение setLocale можно реализовать самостоятельно через обёртки.


Почему нет встроенного setLocale

Библиотека придерживается принципа явности: каждый вызов format(date, locale) однозначно указывает, какой язык использовать. Глобальное изменение состояния через setLocale могло бы привести к неожиданному поведению в многокомпонентных приложениях, где разные части интерфейса могут использовать разные локали.


Реализация setLocale через модуль

// src/timeago-locale.js

import { format, render, cancel } from 'timeago.js';

let currentLocale = 'ru';

export function setLocale(locale) {
  currentLocale = locale;
}

export function getLocale() {
  return currentLocale;
}

export function timeAgo(date) {
  return format(date, currentLocale);
}

export function renderTime(nodes) {
  cancel(nodes);
  render(nodes, currentLocale);
}

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

import { setLocale, timeAgo, renderTime } from './timeago-locale.js';

setLocale('ru');

console.log(timeAgo(Date.now() - 3600000));
// → "1 час назад"

setLocale('de');

console.log(timeAgo(Date.now() - 3600000));
// → "vor 1 Stunde"

Реализация через React Context

import { createContext, useContext, useState, ReactNode } from 'react';
import { format } from 'timeago.js';

type Locale = 'ru' | 'en_US' | 'de';

interface TimeagoContextValue {
  locale: Locale;
  setLocale: (l: Locale) => void;
  timeAgo: (date: Date | string | number) => string;
}

const TimeagoContext = createContext<TimeagoContextValue>({
  locale: 'ru',
  setLocale: () => {},
  timeAgo: (d) => format(d, 'ru'),
});

export function TimeagoProvider({ children }: { children: ReactNode }) {
  const [locale, setLocale] = useState<Locale>('ru');

  return (
    <TimeagoContext.Provider value={{
      locale,
      setLocale,
      timeAgo: (d) => format(d, locale),
    }}>
      {children}
    </TimeagoContext.Provider>
  );
}

export function useTimeago() {
  return useContext(TimeagoContext);
}

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

function PostTime({ date }: { date: string }) {
  const { timeAgo } = useTimeago();
  return <time>{timeAgo(date)}</time>;
}

Реализация через Vue provide/inject

// composables/useTimeago.ts
import { inject, provide, ref } from 'vue';
import { format } from 'timeago.js';

const LOCALE_KEY = Symbol('timeago-locale');

export function provideTimeago(initialLocale = 'ru') {
  const locale = ref(initialLocale);

  provide(LOCALE_KEY, {
    locale,
    setLocale: (l: string) => { locale.value = l; },
    timeAgo: (d: Date | string | number) => format(d, locale.value),
  });
}

export function useTimeago() {
  return inject(LOCALE_KEY) as {
    locale: Ref<string>;
    setLocale: (l: string) => void;
    timeAgo: (d: Date | string | number) => string;
  };
}

Синхронизация с i18n

При использовании i18next:

import i18n from 'i18next';
import { setLocale } from './timeago-locale.js';

const LOCALE_MAP = {
  ru: 'ru',
  en: 'en_US',
  de: 'de',
};

i18n.on('languageChanged', (lang) => {
  setLocale(LOCALE_MAP[lang] || 'en_US');

  // Обновить все временные метки на странице
  const nodes = document.querySelectorAll('[data-timeago]');
  renderTime(nodes);
});

setLocale с localStorage

import { format } from 'timeago.js';

const LOCALE_KEY = 'app-timeago-locale';

let currentLocale = localStorage.getItem(LOCALE_KEY) || 'ru';

function setLocale(locale) {
  currentLocale = locale;
  localStorage.setItem(LOCALE_KEY, locale);
}

function timeAgo(date) {
  return format(date, currentLocale);
}

Когда setLocale нужен

  • Многоязычные SPA, где пользователь может сменить язык без перезагрузки.
  • Приложения с автоматическим определением языка из navigator.language.
  • Системы с user-specific локалью (например, сайт на нескольких языках с персонализацией).

Когда setLocale не нужен

  • Одноязычные приложения — локаль задаётся при инициализации.
  • SSR-страницы с фиксированным языком.
  • Компоненты с изолированной локалью — передавать явно в каждый format.