From 7837864841dde44da603d1293156ac9949816b9d Mon Sep 17 00:00:00 2001 From: 0phoff <0phoff@users.noreply.github.com> Date: Wed, 17 Jan 2024 18:23:11 +0100 Subject: [PATCH] Enhancement: locale option for date & relativeDate format (#2658) --- docs/widgets/services/customapi.md | 11 ++++++++++- next-i18next.config.js | 14 ++++++++++++++ public/locales/en/common.json | 1 + src/widgets/customapi/component.jsx | 15 ++++++++++++++- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/docs/widgets/services/customapi.md b/docs/widgets/services/customapi.md index f39d8d5ea..d392f0a9c 100644 --- a/docs/widgets/services/customapi.md +++ b/docs/widgets/services/customapi.md @@ -34,11 +34,20 @@ widget: - field: key # needs to be YAML string or object label: Field 4 format: date # optional - defaults to text + locale: nl # optional dateStyle: long # optional - defaults to "long". Allowed values: `["full", "long", "medium", "short"]`. timeStyle: medium # optional - Allowed values: `["full", "long", "medium", "short"]`. + - field: key # needs to be YAML string or object + label: Field 5 + format: relativeDate # optional - defaults to text + locale: nl # optional + style: short # optional - defaults to "long". Allowed values: `["long", "short", "narrow"]`. + numeric: auto # optional - defaults to "always". Allowed values `["always", "auto"]`. ``` -Supported formats for the values are `text`, `number`, `float`, `percent`, `bytes`, `bitrate` and `date`. +Supported formats for the values are `text`, `number`, `float`, `percent`, `bytes`, `bitrate`, `date` and `relativeDate`. + +The `dateStyle` and `timeStyle` options of the `date` format are passed directly to [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) and the `style` and `numeric` options of `relativeDate` are passed to [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat). ## Example diff --git a/next-i18next.config.js b/next-i18next.config.js index 6790e14d9..96483cc3f 100644 --- a/next-i18next.config.js +++ b/next-i18next.config.js @@ -100,6 +100,17 @@ function uptime(uptimeInSeconds, i18next) { return (moDisplay + dDisplay + hDisplay + mDisplay + sDisplay).replace(/,\s*$/, ""); } +function relativeDate(date, formatter) { + const cutoffs = [60, 3600, 86400, 86400 * 7, 86400 * 30, 86400 * 365, Infinity]; + const units = ["second", "minute", "hour", "day", "week", "month", "year"]; + + const delta = Math.round((date.getTime() - Date.now()) / 1000); + const unitIndex = cutoffs.findIndex((cutoff) => cutoff > Math.abs(delta)); + const divisor = unitIndex ? cutoffs[unitIndex - 1] : 1; + + return formatter.format(Math.floor(delta / divisor), units[unitIndex]); +} + module.exports = { i18n: { defaultLocale: "en", @@ -142,6 +153,9 @@ module.exports = { i18next.services.formatter.add("date", (value, lng, options) => new Intl.DateTimeFormat(lng, { ...options }).format(new Date(value)), ); + i18next.services.formatter.add("relativeDate", (value, lng, options) => + relativeDate(new Date(value), new Intl.RelativeTimeFormat(lng, { ...options })), + ); i18next.services.formatter.add("uptime", (value, lng) => uptime(value, i18next)); }, type: "3rdParty", diff --git a/public/locales/en/common.json b/public/locales/en/common.json index bf39f1d98..1c43e5066 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -12,6 +12,7 @@ "number": "{{value, number}}", "ms": "{{value, number}}", "date": "{{value, date}}", + "relativeDate": "{{value, relativeDate}}", "uptime": "{{value, uptime}}", "months": "mo", "days": "d", diff --git a/src/widgets/customapi/component.jsx b/src/widgets/customapi/component.jsx index fcf6e82f9..7e6ad4d73 100644 --- a/src/widgets/customapi/component.jsx +++ b/src/widgets/customapi/component.jsx @@ -70,7 +70,20 @@ function formatValue(t, mapping, rawValue) { value = t("common.bitrate", { value }); break; case "date": - value = t("common.date", { value, dateStyle: mapping?.dateStyle ?? "long", timeStyle: mapping?.timeStyle }); + value = t("common.date", { + value, + lng: mapping?.locale, + dateStyle: mapping?.dateStyle ?? "long", + timeStyle: mapping?.timeStyle, + }); + break; + case "relativeDate": + value = t("common.relativeDate", { + value, + lng: mapping?.locale, + style: mapping?.style, + numeric: mapping?.numeric, + }); break; case "text": default: