diff --git a/src/mixins/lang.js b/src/mixins/lang.js index 9061e7d3d..f8a02415e 100644 --- a/src/mixins/lang.js +++ b/src/mixins/lang.js @@ -1,5 +1,5 @@ import { currentLocale } from "../i18n"; -import { setPageLocale } from "../util-frontend"; +import { setPageLocale, rtf } from "../util-frontend"; const langModules = import.meta.glob("../lang/*.json"); export default { @@ -28,11 +28,13 @@ export default { * @returns {Promise} */ async changeLang(lang) { - let message = (await langModules["../lang/" + lang + ".json"]()).default; + let message = (await langModules["../lang/" + lang + ".json"]()) + .default; this.$i18n.setLocaleMessage(lang, message); this.$i18n.locale = lang; localStorage.locale = lang; setPageLocale(); - } - } + rtf.updateLocale(lang); + }, + }, }; diff --git a/src/pages/Details.vue b/src/pages/Details.vue index 17d32365c..3d1f0f4d5 100644 --- a/src/pages/Details.vue +++ b/src/pages/Details.vue @@ -76,7 +76,7 @@
- {{ $t("checkEverySecond", [ monitor.interval ]) }} + {{ $t("checkEverySecond", [ monitor.interval ]) }} ({{ secondsToHumanReadableFormat(monitor.interval) }})
{{ status.text }} @@ -285,7 +285,7 @@ import Tag from "../components/Tag.vue"; import CertificateInfo from "../components/CertificateInfo.vue"; import { getMonitorRelativeURL } from "../util.ts"; import { URL } from "whatwg-url"; -import { getResBaseURL } from "../util-frontend"; +import { getResBaseURL, rtf } from "../util-frontend"; import { highlight, languages } from "prismjs/components/prism-core"; import "prismjs/components/prism-clike"; import "prismjs/components/prism-javascript"; @@ -656,7 +656,12 @@ export default { .replace("https://example.com/api/push/key?status=up&msg=OK&ping=", this.pushURL); this.pushMonitor.code = code; }); + }, + + secondsToHumanReadableFormat(seconds) { + return rtf.secondsToHumanReadableFormat(seconds); } + }, }; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 5d999b597..a26f023e6 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -530,6 +530,9 @@
+
+ {{ monitor.humanReadableInterval }} +
@@ -1073,7 +1076,7 @@ import RemoteBrowserDialog from "../components/RemoteBrowserDialog.vue"; import ProxyDialog from "../components/ProxyDialog.vue"; import TagsManager from "../components/TagsManager.vue"; import { genSecret, isDev, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND, sleep } from "../util.ts"; -import { hostNameRegexPattern } from "../util-frontend"; +import { hostNameRegexPattern, rtf } from "../util-frontend"; import HiddenInput from "../components/HiddenInput.vue"; import EditMonitorConditions from "../components/EditMonitorConditions.vue"; import { version } from "../../package.json"; @@ -1090,6 +1093,7 @@ const monitorDefaults = { url: "https://", method: "GET", interval: 60, + humanReadableInterval: rtf.secondsToHumanReadableFormat(60), retryInterval: 60, resendInterval: 0, maxretries: 0, @@ -1472,6 +1476,8 @@ message HealthCheckResponse { if (this.monitor.retryInterval === oldValue) { this.monitor.retryInterval = value; } + // Converting monitor.interval to human readable format. + this.monitor.humanReadableInterval = rtf.secondsToHumanReadableFormat(value); }, "monitor.timeout"(value, oldValue) { diff --git a/src/util-frontend.js b/src/util-frontend.js index d9bf378e5..b6d758199 100644 --- a/src/util-frontend.js +++ b/src/util-frontend.js @@ -213,3 +213,62 @@ export function getToastErrorTimeout() { return errorTimeout; } + +class RelativeTimeFormatter { + // Default locale and options + constructor() { + this.locale = currentLocale(); + this.options = { numeric: "auto" }; + this.rtf = new Intl.RelativeTimeFormat(this.locale, this.options); + } + + // Method to get the singleton instance + getInstance() { + return this.rtf; + } + + // Method to update the locale and options + updateLocale(locale, options = {}) { + this.locale = locale; + this.options = { ...this.options, ...options }; + this.rtf = new Intl.RelativeTimeFormat(this.locale, this.options); + } + + secondsToHumanReadableFormat(seconds) { + const days = Math.floor(seconds / 86400); + const hours = Math.floor((seconds % 86400) / 3600); + const minutes = Math.floor(((seconds % 86400) % 3600) / 60); + const secs = ((seconds % 86400) % 3600) % 60; + const parts = []; + // Build the formatted string from parts + const toFormattedPart = (value, unitOfTime) => { + const res = this.getInstance().formatToParts(value, unitOfTime); + console.log(res) + let formattedString = res + .map((part, _idx) => { + if ((part.type === "literal" || part.type === "integer") && _idx > 0) { + return part.value; + } + return ""; + }) + .join(""); + formattedString = formattedString.trim(); + parts.push(formattedString); + }; + + if (days > 0) toFormattedPart(days, "days"); + if (hours > 0) toFormattedPart(hours, "hour"); + if (minutes > 0) toFormattedPart(minutes, "minute"); + if (secs > 0) toFormattedPart(secs, "second"); + + const result = + parts.length > 0 + ? `~ ${parts.join(" ")}` + : this.getInstance().format(0, "second"); // Handle case for 0 seconds + + return result; + } +} + +export const rtf = new RelativeTimeFormatter(); +