UNPKG

humanize-time-tool

Version:

A simple and lightweight Node.js library for human-friendly time formatting and localization.

702 lines (682 loc) 22.4 kB
/** * Collection of translations for multiple languages. * Each language object contains strings for various time intervals. */ const translations = { "sv": { "seconds": "för några sekunder sedan", "minute_one": "för 1 minut sedan", "minutes": "för {n} minuter sedan", "hour_one": "för 1 timme sedan", "hours": "för {n} timmar sedan", "day_one": "för 1 dag sedan", "days": "för {n} dagar sedan", "week_one": "för 1 vecka sedan", "weeks": "för {n} veckor sedan", "month_one": "för 1 månad sedan", "months": "för {n} månader sedan", "year_one": "för 1 år sedan", "years": "för {n} år sedan" }, "en": { "seconds": "a few seconds ago", "minute_one": "1 minute ago", "minutes": "{n} minutes ago", "hour_one": "1 hour ago", "hours": "{n} hours ago", "day_one": "1 day ago", "days": "{n} days ago", "week_one": "1 week ago", "weeks": "{n} weeks ago", "month_one": "1 month ago", "months": "{n} months ago", "year_one": "1 year ago", "years": "{n} years ago" }, "fr": { "seconds": "il y a quelques secondes", "minute_one": "il y a 1 minute", "minutes": "il y a {n} minutes", "hour_one": "il y a 1 heure", "hours": "il y a {n} heures", "day_one": "il y a 1 jour", "days": "il y a {n} jours", "week_one": "il y a 1 semaine", "weeks": "il y a {n} semaines", "month_one": "il y a 1 mois", "months": "il y a {n} mois", "year_one": "il y a 1 an", "years": "il y a {n} ans" }, "de": { "seconds": "vor ein paar Sekunden", "minute_one": "vor 1 Minute", "minutes": "vor {n} Minuten", "hour_one": "vor 1 Stunde", "hours": "vor {n} Stunden", "day_one": "vor 1 Tag", "days": "vor {n} Tagen", "week_one": "vor 1 Woche", "weeks": "vor {n} Wochen", "month_one": "vor 1 Monat", "months": "vor {n} Monaten", "year_one": "vor 1 Jahr", "years": "vor {n} Jahren" }, "es": { "seconds": "hace unos segundos", "minute_one": "hace 1 minuto", "minutes": "hace {n} minutos", "hour_one": "hace 1 hora", "hours": "hace {n} horas", "day_one": "hace 1 día", "days": "hace {n} días", "week_one": "hace 1 semana", "weeks": "hace {n} semanas", "month_one": "hace 1 mes", "months": "hace {n} meses", "year_one": "hace 1 año", "years": "hace {n} años" }, "it": { "seconds": "qualche secondo fa", "minute_one": "1 minuto fa", "minutes": "{n} minuti fa", "hour_one": "1 ora fa", "hours": "{n} ore fa", "day_one": "1 giorno fa", "days": "{n} giorni fa", "week_one": "1 settimana fa", "weeks": "{n} settimane fa", "month_one": "1 mese fa", "months": "{n} mesi fa", "year_one": "1 anno fa", "years": "{n} anni fa" }, "pt": { "seconds": "há poucos segundos", "minute_one": "há 1 minuto", "minutes": "há {n} minutos", "hour_one": "há 1 hora", "hours": "há {n} horas", "day_one": "há 1 dia", "days": "há {n} dias", "week_one": "há 1 semana", "weeks": "há {n} semanas", "month_one": "há 1 mês", "months": "há {n} meses", "year_one": "há 1 ano", "years": "há {n} anos" }, "nl": { "seconds": "een paar seconden geleden", "minute_one": "1 minuut geleden", "minutes": "{n} minuten geleden", "hour_one": "1 uur geleden", "hours": "{n} uur geleden", "day_one": "1 dag geleden", "days": "{n} dagen geleden", "week_one": "1 week geleden", "weeks": "{n} weken geleden", "month_one": "1 maand geleden", "months": "{n} maanden geleden", "year_one": "1 jaar geleden", "years": "{n} jaar geleden" }, "pl": { "seconds": "kilka sekund temu", "minute_one": "1 minuta temu", "minutes": "{n} minut temu", "hour_one": "1 godzina temu", "hours": "{n} godzin temu", "day_one": "1 dzień temu", "days": "{n} dni temu", "week_one": "1 tydzień temu", "weeks": "{n} tygodni temu", "month_one": "1 miesiąc temu", "months": "{n} miesięcy temu", "year_one": "1 rok temu", "years": "{n} lat temu" }, "fi": { "seconds": "muutama sekunti sitten", "minute_one": "1 minuutti sitten", "minutes": "{n} minuuttia sitten", "hour_one": "1 tunti sitten", "hours": "{n} tuntia sitten", "day_one": "1 päivä sitten", "days": "{n} päivää sitten", "week_one": "1 viikko sitten", "weeks": "{n} viikkoa sitten", "month_one": "1 kuukausi sitten", "months": "{n} kuukautta sitten", "year_one": "1 vuosi sitten", "years": "{n} vuotta sitten" }, "no": { "seconds": "for noen sekunder siden", "minute_one": "for 1 minutt siden", "minutes": "for {n} minutter siden", "hour_one": "for 1 time siden", "hours": "for {n} timer siden", "day_one": "for 1 dag siden", "days": "for {n} dager siden", "week_one": "for 1 uke siden", "weeks": "for {n} uker siden", "month_one": "for 1 måned siden", "months": "for {n} måneder siden", "year_one": "for 1 år siden", "years": "for {n} år siden" }, "da": { "seconds": "for få sekunder siden", "minute_one": "for 1 minut siden", "minutes": "for {n} minutter siden", "hour_one": "for 1 time siden", "hours": "for {n} timer siden", "day_one": "for 1 dag siden", "days": "for {n} dage siden", "week_one": "for 1 uge siden", "weeks": "for {n} uger siden", "month_one": "for 1 måned siden", "months": "for {n} måneder siden", "year_one": "for 1 år siden", "years": "for {n} år siden" }, "ru": { "seconds": "несколько секунд назад", "minute_one": "1 минуту назад", "minutes": "{n} минут назад", "hour_one": "1 час назад", "hours": "{n} часов назад", "day_one": "1 день назад", "days": "{n} дней назад", "week_one": "1 неделю назад", "weeks": "{n} недель назад", "month_one": "1 месяц назад", "months": "{n} месяцев назад", "year_one": "1 год назад", "years": "{n} лет назад" }, "zh": { "seconds": "几秒前", "minute_one": "1 分钟前", "minutes": "{n} 分钟前", "hour_one": "1 小时前", "hours": "{n} 小时前", "day_one": "1 天前", "days": "{n} 天前", "week_one": "1 周前", "weeks": "{n} 周前", "month_one": "1 个月前", "months": "{n} 个月前", "year_one": "1 年前", "years": "{n} 年前" }, "ja": { "seconds": "数秒前", "minute_one": "1 分前", "minutes": "{n} 分前", "hour_one": "1 時間前", "hours": "{n} 時間前", "day_one": "1 日前", "days": "{n} 日前", "week_one": "1 週間前", "weeks": "{n} 週間前", "month_one": "1 か月前", "months": "{n} か月前", "year_one": "1 年前", "years": "{n} 年前" }, "ko": { "seconds": "몇 초 전", "minute_one": "1분 전", "minutes": "{n}분 전", "hour_one": "1시간 전", "hours": "{n}시간 전", "day_one": "1일 전", "days": "{n}일 전", "week_one": "1주 전", "weeks": "{n}주 전", "month_one": "1개월 전", "months": "{n}개월 전", "year_one": "1년 전", "years": "{n}년 전" }, "ar": { "seconds": "منذ ثوانٍ قليلة", "minute_one": "منذ دقيقة واحدة", "minutes": "منذ {n} دقائق", "hour_one": "منذ ساعة واحدة", "hours": "منذ {n} ساعات", "day_one": "منذ يوم واحد", "days": "منذ {n} أيام", "week_one": "منذ أسبوع واحد", "weeks": "منذ {n} أسابيع", "month_one": "منذ شهر واحد", "months": "منذ {n} أشهر", "year_one": "منذ سنة واحدة", "years": "منذ {n} سنوات" }, "hi": { "seconds": "कुछ सेकंड पहले", "minute_one": "1 मिनट पहले", "minutes": "{n} मिनट पहले", "hour_one": "1 घंटे पहले", "hours": "{n} घंटे पहले", "day_one": "1 दिन पहले", "days": "{n} दिन पहले", "week_one": "1 सप्ताह पहले", "weeks": "{n} सप्ताह पहले", "month_one": "1 महीने पहले", "months": "{n} महीने पहले", "year_one": "1 साल पहले", "years": "{n} साल पहले" }, "he": { "seconds": "לפני כמה שניות", "minute_one": "לפני דקה אחת", "minutes": "לפני {n} דקות", "hour_one": "לפני שעה אחת", "hours": "לפני {n} שעות", "day_one": "לפני יום אחד", "days": "לפני {n} ימים", "week_one": "לפני שבוע אחד", "weeks": "לפני {n} שבועות", "month_one": "לפני חודש אחד", "months": "לפני {n} חודשים", "year_one": "לפני שנה אחת", "years": "לפני {n} שנים" }, "tr": { "seconds": "birkaç saniye önce", "minute_one": "1 dakika önce", "minutes": "{n} dakika önce", "hour_one": "1 saat önce", "hours": "{n} saat önce", "day_one": "1 gün önce", "days": "{n} gün önce", "week_one": "1 hafta önce", "weeks": "{n} hafta önce", "month_one": "1 ay önce", "months": "{n} ay önce", "year_one": "1 yıl önce", "years": "{n} yıl önce" }, "el": { "seconds": "πριν από μερικά δευτερόλεπτα", "minute_one": "πριν από 1 λεπτό", "minutes": "πριν από {n} λεπτά", "hour_one": "πριν από 1 ώρα", "hours": "πριν από {n} ώρες", "day_one": "πριν από 1 μέρα", "days": "πριν από {n} μέρες", "week_one": "πριν από 1 εβδομάδα", "weeks": "πριν από {n} εβδομάδες", "month_one": "πριν από 1 μήνα", "months": "πριν από {n} μήνες", "year_one": "πριν από 1 χρόνο", "years": "πριν από {n} χρόνια" }, "cs": { "seconds": "před několika sekundami", "minute_one": "před 1 minutou", "minutes": "před {n} minutami", "hour_one": "před 1 hodinou", "hours": "před {n} hodinami", "day_one": "před 1 dnem", "days": "před {n} dny", "week_one": "před 1 týdnem", "weeks": "před {n} týdny", "month_one": "před 1 měsícem", "months": "před {n} měsíci", "year_one": "před 1 rokem", "years": "před {n} lety" }, "vi": { "seconds": "vài giây trước", "minute_one": "1 phút trước", "minutes": "{n} phút trước", "hour_one": "1 giờ trước", "hours": "{n} giờ trước", "day_one": "1 ngày trước", "days": "{n} ngày trước", "week_one": "1 tuần trước", "weeks": "{n} tuần trước", "month_one": "1 tháng trước", "months": "{n} tháng trước", "year_one": "1 năm trước", "years": "{n} năm trước" }, "et": { "seconds": "paar sekundit tagasi", "minute_one": "1 minut tagasi", "minutes": "{n} minutit tagasi", "hour_one": "1 tund tagasi", "hours": "{n} tundi tagasi", "day_one": "1 päev tagasi", "days": "{n} päeva tagasi", "week_one": "1 nädal tagasi", "weeks": "{n} nädalat tagasi", "month_one": "1 kuu tagasi", "months": "{n} kuud tagasi", "year_one": "1 aasta tagasi", "years": "{n} aastat tagasi" }, "lv": { "seconds": "dažas sekundes atpakaļ", "minute_one": "1 minūti atpakaļ", "minutes": "{n} minūtes atpakaļ", "hour_one": "1 stundu atpakaļ", "hours": "{n} stundas atpakaļ", "day_one": "1 dienu atpakaļ", "days": "{n} dienas atpakaļ", "week_one": "1 nedēļu atpakaļ", "weeks": "{n} nedēļas atpakaļ", "month_one": "1 mēnesi atpakaļ", "months": "{n} mēneši atpakaļ", "year_one": "1 gadu atpakaļ", "years": "{n} gadus atpakaļ" }, "lt": { "seconds": "prieš kelias sekundes", "minute_one": "prieš 1 minutę", "minutes": "prieš {n} minutes", "hour_one": "prieš 1 valandą", "hours": "prieš {n} valandas", "day_one": "prieš 1 dieną", "days": "prieš {n} dienas", "week_one": "prieš 1 savaitę", "weeks": "prieš {n} savaites", "month_one": "prieš 1 mėnesį", "months": "prieš {n} mėnesius", "year_one": "prieš 1 metus", "years": "prieš {n} metus" }, "sk": { "seconds": "pred niekoľkými sekundami", "minute_one": "pred 1 minútou", "minutes": "pred {n} minútami", "hour_one": "pred 1 hodinou", "hours": "pred {n} hodinami", "day_one": "pred 1 dňom", "days": "pred {n} dňami", "week_one": "pred 1 týždňom", "weeks": "pred {n} týždňami", "month_one": "pred 1 mesiacom", "months": "pred {n} mesiacmi", "year_one": "pred 1 rokom", "years": "pred {n} rokmi" }, "hu": { "seconds": "néhány másodperce", "minute_one": "1 perce", "minutes": "{n} perce", "hour_one": "1 órája", "hours": "{n} órája", "day_one": "1 napja", "days": "{n} napja", "week_one": "1 hete", "weeks": "{n} hete", "month_one": "1 hónapja", "months": "{n} hónapja", "year_one": "1 éve", "years": "{n} éve" }, "sr": { "seconds": "пре неколико секунди", "minute_one": "пре 1 минут", "minutes": "пре {n} минута", "hour_one": "пре 1 сат", "hours": "пре {n} сати", "day_one": "пре 1 дана", "days": "пре {n} дана", "week_one": "пре 1 недеље", "weeks": "пре {n} недеља", "month_one": "пре 1 месеца", "months": "пре {n} месеци", "year_one": "пре 1 године", "years": "пре {n} година" }, "hr": { "seconds": "prije nekoliko sekundi", "minute_one": "prije 1 minute", "minutes": "prije {n} minuta", "hour_one": "prije 1 sat", "hours": "prije {n} sati", "day_one": "prije 1 dan", "days": "prije {n} dana", "week_one": "prije 1 tjedan", "weeks": "prije {n} tjedana", "month_one": "prije 1 mjesec", "months": "prije {n} mjeseci", "year_one": "prije 1 godinu", "years": "prije {n} godina" }, "uk": { "seconds": "кілька секунд тому", "minute_one": "1 хвилину тому", "minutes": "{n} хвилин тому", "hour_one": "1 годину тому", "hours": "{n} годин тому", "day_one": "1 день тому", "days": "{n} днів тому", "week_one": "1 тиждень тому", "weeks": "{n} тижнів тому", "month_one": "1 місяць тому", "months": "{n} місяців тому", "year_one": "1 рік тому", "years": "{n} років тому" }, "be": { "seconds": "некалькі секунд таму", "minute_one": "1 хвіліну таму", "minutes": "{n} хвілін таму", "hour_one": "1 гадзіну таму", "hours": "{n} гадзін таму", "day_one": "1 дзень таму", "days": "{n} дзён таму", "week_one": "1 тыдзень таму", "weeks": "{n} тыдняў таму", "month_one": "1 месяц таму", "months": "{n} месяцаў таму", "year_one": "1 год таму", "years": "{n} гадоў таму" }, "bg": { "seconds": "преди няколко секунди", "minute_one": "преди 1 минута", "minutes": "преди {n} минути", "hour_one": "преди 1 час", "hours": "преди {n} часа", "day_one": "преди 1 ден", "days": "преди {n} дни", "week_one": "преди 1 седмица", "weeks": "преди {n} седмици", "month_one": "преди 1 месец", "months": "преди {n} месеца", "year_one": "преди 1 година", "years": "преди {n} години" }, "ro": { "seconds": "cu câteva secunde în urmă", "minute_one": "acum 1 minut", "minutes": "acum {n} minute", "hour_one": "acum 1 oră", "hours": "acum {n} ore", "day_one": "acum 1 zi", "days": "acum {n} zile", "week_one": "acum 1 săptămână", "weeks": "acum {n} săptămâni", "month_one": "acum 1 lună", "months": "acum {n} luni", "year_one": "acum 1 an", "years": "acum {n} ani" }, "th": { "seconds": "เมื่อไม่กี่วินาทีที่แล้ว", "minute_one": "1 นาทีที่แล้ว", "minutes": "{n} นาทีที่แล้ว", "hour_one": "1 ชั่วโมงที่แล้ว", "hours": "{n} ชั่วโมงที่แล้ว", "day_one": "1 วันที่แล้ว", "days": "{n} วันที่แล้ว", "week_one": "1 สัปดาห์ที่แล้ว", "weeks": "{n} สัปดาห์ที่แล้ว", "month_one": "1 เดือนที่แล้ว", "months": "{n} เดือนที่แล้ว", "year_one": "1 ปีที่แล้ว", "years": "{n} ปีที่แล้ว" }, "sl": { "seconds": "pred nekaj sekundami", "minute_one": "pred 1 minuto", "minutes": "pred {n} minutami", "hour_one": "pred 1 uro", "hours": "pred {n} urami", "day_one": "pred 1 dnem", "days": "pred {n} dnevi", "week_one": "pred 1 tednom", "weeks": "pred {n} tedni", "month_one": "pred 1 mesecem", "months": "pred {n} meseci", "year_one": "pred 1 letom", "years": "pred {n} leti" }, "bs": { "seconds": "prije nekoliko sekundi", "minute_one": "prije 1 minut", "minutes": "prije {n} minuta", "hour_one": "prije 1 sat", "hours": "prije {n} sati", "day_one": "prije 1 dan", "days": "prije {n} dana", "week_one": "prije 1 sedmicu", "weeks": "prije {n} sedmica", "month_one": "prije 1 mjesec", "months": "prije {n} mjeseci", "year_one": "prije 1 godinu", "years": "prije {n} godina" }, "fa": { "seconds": "چند ثانیه پیش", "minute_one": "1 دقیقه پیش", "minutes": "{n} دقیقه پیش", "hour_one": "1 ساعت پیش", "hours": "{n} ساعت پیش", "day_one": "1 روز پیش", "days": "{n} روز پیش", "week_one": "1 هفته پیش", "weeks": "{n} هفته پیش", "month_one": "1 ماه پیش", "months": "{n} ماه پیش", "year_one": "1 سال پیش", "years": "{n} سال پیش" }, "is": { "seconds": "fyrir nokkrum sekúndum", "minute_one": "fyrir 1 mínútu", "minutes": "fyrir {n} mínútum", "hour_one": "fyrir 1 klukkustund", "hours": "fyrir {n} klukkustundum", "day_one": "fyrir 1 degi", "days": "fyrir {n} dögum", "week_one": "fyrir 1 viku", "weeks": "fyrir {n} vikum", "month_one": "fyrir 1 mánuði", "months": "fyrir {n} mánuðum", "year_one": "fyrir 1 ári", "years": "fyrir {n} árum" } }; // Internal storage for registered languages const registered = new Map(); /** * Register a language (activate it) * @param {string} lang - language code */ function register(lang) { if (translations[lang]) { registered.set(lang, translations[lang]); } else { console.warn(`Language '${lang}' not found in translations`); } } /** * Clear all registered languages */ function clearRegistered() { registered.clear(); } /** * Middleware to "allow" certain languages * @param {'*'|string[]} allowedLanguages - '*' or an array of allowed language codes * @returns middleware function for e.g. Express */ function languageMiddleware(allowedLanguages) { return function (req, res, next) { clearRegistered(); const isWildcard = allowedLanguages === '*' || (Array.isArray(allowedLanguages) && allowedLanguages.length === 1 && allowedLanguages[0] === '*'); if (isWildcard) { Object.keys(translations).forEach(register); } else if (Array.isArray(allowedLanguages)) { allowedLanguages.forEach(register); } else { console.warn('⚠️ allowedLanguages must be "*" or an array of language codes.'); } next(); }; } /** * Get translations for a language if it's registered * @param {string} lang * @returns {object|null} */ function getTranslations(lang) { return registered.get(lang) || null; } /** * Formats a time difference as "time ago" according to selected language * @param {Date|string|number} dateInput * @param {string} lang - language code * @param {object} custom - optional custom translations * @returns {string} */ function timeAgo(dateInput, lang = 'en', custom = {}) { const date = new Date(dateInput); if (isNaN(date)) throw new TypeError('Invalid date'); const diff = Math.floor((Date.now() - date.getTime()) / 1000); const base = translations.en; const locale = getTranslations(lang) || base; const t = { ...base, ...locale, ...custom }; const fmt = (str, n) => (typeof str === 'string' ? str.replace('{n}', n) : ''); if (diff < 60) return t.seconds || 'a few seconds ago'; const min = Math.floor(diff / 60); if (min === 1) return t.minute_one || '1 minute ago'; if (min < 60) return fmt(t.minutes, min); const hr = Math.floor(min / 60); if (hr === 1) return t.hour_one || '1 hour ago'; if (hr < 24) return fmt(t.hours, hr); const day = Math.floor(hr / 24); if (day === 1) return t.day_one || '1 day ago'; if (day < 7) return fmt(t.days, day); const wk = Math.floor(day / 7); if (wk === 1) return t.week_one || '1 week ago'; if (wk < 5) return fmt(t.weeks, wk); const mo = Math.floor(day / 30.44); if (mo === 1) return t.month_one || '1 month ago'; if (mo < 12) return fmt(t.months, mo); const yr = Math.floor(day / 365.25); if (yr === 1) return t.year_one || '1 year ago'; return fmt(t.years, yr) || `${yr} years ago`; } export { languageMiddleware, timeAgo, register, clearRegistered, getTranslations, translations, };