Динамическое переключение языков актуально для многоязычных
приложений, где пользователь может сменить интерфейсный язык в runtime.
timeago.js поддерживает это нативно — функция format
принимает локаль аргументом, а render позволяет пересоздать
обновляемые элементы с новой локалью.
Локаль в timeago.js не хранится глобально как “текущая”. Она передаётся при каждом вызове. Чтобы переключить язык, достаточно передать другой идентификатор:
import { format } from 'timeago.js';
format(date, 'ru'); // русский
format(date, 'en_US'); // английский
format(date, 'de'); // немецкий
import { cancel, render } from 'timeago.js';
let currentLocale = 'ru';
function setLocale(locale) {
currentLocale = locale;
const nodes = document.querySelectorAll('[data-timeago]');
cancel(nodes);
render(nodes, locale);
}
// Пользователь нажимает кнопку смены языка
document.getElementById('btn-en').addEventListener('click', () => setLocale('en_US'));
document.getElementById('btn-ru').addEventListener('click', () => setLocale('ru'));
document.getElementById('btn-de').addEventListener('click', () => setLocale('de'));
import { cancel, render, format } from 'timeago.js';
const state = {
locale: localStorage.getItem('locale') || 'ru',
};
function setLocale(locale) {
state.locale = locale;
localStorage.setItem('locale', locale);
const nodes = document.querySelectorAll('[data-timeago]');
cancel(nodes);
render(nodes, locale);
}
function getLocale() {
return state.locale;
}
import { useState, useCallback } from 'react';
import { format } from 'timeago.js';
type Locale = 'ru' | 'en_US' | 'de';
function useTimeAgoLocale(initialLocale: Locale = 'ru') {
const [locale, setLocale] = useState<Locale>(initialLocale);
const formatDate = useCallback(
(date: Date | string | number) => format(date, locale),
[locale]
);
return { locale, setLocale, formatDate };
}
function App() {
const { locale, setLocale, formatDate } = useTimeAgoLocale();
return (
<div>
<button onCl ick={() => setLocale('ru')}>RU</button>
<button onCl ick={() => setLocale('en_US')}>EN</button>
<time>{formatDate('2025-05-26T08:00:00Z')}</time>
</div>
);
}
<script setup>
import { ref, computed } from 'vue';
import { format } from 'timeago.js';
const locale = ref('ru');
function changeLocale(newLocale) {
locale.value = newLocale;
}
function timeAgo(date) {
return format(date, locale.value);
}
</script>
<template>
<div>
<button @click="changeLocale('ru')">RU</button>
<button @click="changeLocale('en_US')">EN</button>
<time>{{ timeAgo('2025-05-26T08:00:00Z') }}</time>
</div>
</template>
При использовании vue-i18n или
react-i18next локаль timeago.js синхронизируется с
глобальным состоянием:
// Vue i18n
import { useI18n } from 'vue-i18n';
import { format } from 'timeago.js';
const { locale } = useI18n();
function timeAgo(date) {
return format(date, locale.value);
}
// React i18next
import { useTranslation } from 'react-i18next';
import { format } from 'timeago.js';
function useTimeAgo() {
const { i18n } = useTranslation();
return (date) => format(date, i18n.language);
}
Имена локалей в i18n-библиотеках и timeago.js могут отличаться:
const LOCALE_MAP = {
'ru': 'ru',
'en': 'en_US',
'en-US': 'en_US',
'de': 'de',
'zh': 'zh_CN',
'zh-CN': 'zh_CN',
'zh-TW': 'zh_TW',
};
function mapLocale(i18nLocale) {
return LOCALE_MAP[i18nLocale] || 'en_US';
}
format(date, mapLocale(i18n.language));
import { register } from 'timeago.js';
import ru from 'timeago.js/esm/lang/ru';
import en from 'timeago.js/esm/lang/en_US';
import de from 'timeago.js/esm/lang/de';
import fr from 'timeago.js/esm/lang/fr';
const locales = { ru, en_US: en, de, fr };
Object.entries(locales).forEach(([key, fn]) => register(key, fn));
Все языки регистрируются при старте, переключение происходит мгновенно без асинхронных операций.
Для оптимизации бандла локали загружаются только при первом использовании:
import { register, format } from 'timeago.js';
const loaded = new Set(['en_US']);
async function loadAndFormat(date, locale) {
if (!loaded.has(locale)) {
const module = await import(`timeago.js/esm/lang/${locale}.js`);
register(locale, module.default);
loaded.add(locale);
}
return format(date, locale);
}
При использовании render:
import { cancel, render } from 'timeago.js';
function onLocaleChange(newLocale) {
const nodes = document.querySelectorAll('[data-timeago]');
// Обязательно отменить старые таймеры
cancel(nodes);
// Запустить с новой локалью
render(nodes, newLocale);
}
Без cancel старые и новые таймеры будут работать
одновременно.