diff --git a/client/src/Components/design-elements/MonitorStatus.tsx b/client/src/Components/design-elements/MonitorStatus.tsx
index cc0f8df5b..76934f2b3 100644
--- a/client/src/Components/design-elements/MonitorStatus.tsx
+++ b/client/src/Components/design-elements/MonitorStatus.tsx
@@ -8,8 +8,11 @@ import { typographyLevels } from "@/Utils/Theme/Palette";
import useMediaQuery from "@mui/material/useMediaQuery";
import { LAYOUT } from "@/Utils/Theme/constants";
import { formatDuration } from "@/Utils/TimeUtils";
+import { useTranslation } from "react-i18next";
+
export const MonitorStatus = ({ monitor }: { monitor: Monitor }) => {
const theme = useTheme();
+ const { t, i18n } = useTranslation();
const isSmall = useMediaQuery(theme.breakpoints.down("md"));
if (!monitor) {
@@ -52,7 +55,12 @@ export const MonitorStatus = ({ monitor }: { monitor: Monitor }) => {
<>
- Checking every {formatDuration(monitor?.interval, true)}
+ {t("pages.common.monitors.statBoxes.checkingEvery", {
+ interval: formatDuration(monitor.interval, {
+ long: true,
+ locale: i18n.resolvedLanguage,
+ }),
+ })}
>
)}
diff --git a/client/src/Components/monitors/MonitorStatBoxes.tsx b/client/src/Components/monitors/MonitorStatBoxes.tsx
index 8b201b474..020eda78a 100644
--- a/client/src/Components/monitors/MonitorStatBoxes.tsx
+++ b/client/src/Components/monitors/MonitorStatBoxes.tsx
@@ -21,7 +21,7 @@ export const MonitorStatBoxes = ({
domainExpiry,
}: MonitorStatBoxesProps) => {
const theme = useTheme();
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
if (!monitorStats || !monitor) {
return null;
}
@@ -29,13 +29,16 @@ export const MonitorStatBoxes = ({
const timeOfLastFailure = monitorStats?.timeOfLastFailure || 0;
const timeSinceLastFailure = timeOfLastFailure > 0 ? Date.now() - timeOfLastFailure : 0;
- // Determine time since last check
const timeOfLastCheck = monitorStats?.lastCheckTimestamp || 0;
- const timeSinceLastCheck = Date.now() - timeOfLastCheck || 0;
const streakTime = formatDuration(timeSinceLastFailure);
-
- const lastCheckTime = formatDuration(timeSinceLastCheck);
+ const lastCheckTime = timeOfLastCheck
+ ? formatDuration(Date.now() - timeOfLastCheck, {
+ long: true,
+ relative: true,
+ locale: i18n.resolvedLanguage,
+ })
+ : t("common.labels.na");
const isActive =
monitor?.status === "up" ||
monitor?.status === "paused" ||
diff --git a/client/src/Utils/TimeUtils.ts b/client/src/Utils/TimeUtils.ts
index 9b809e1da..d82649c81 100644
--- a/client/src/Utils/TimeUtils.ts
+++ b/client/src/Utils/TimeUtils.ts
@@ -104,9 +104,46 @@ export const formatMs = (ms: number, hasSpace: boolean = true): string => {
return formatted;
};
-export const formatDuration = (ms: number, verbose: boolean = false, hasSpace = true) => {
- if (verbose) {
- return prettyMilliseconds(ms, { verbose: true });
+type DurationUnit = "day" | "hour" | "minute" | "second";
+
+interface FormatDurationOptions {
+ long?: boolean;
+ relative?: boolean;
+ hasSpace?: boolean;
+ locale?: string;
+}
+
+const DURATION_UNITS: Array<{ unit: DurationUnit; milliseconds: number }> = [
+ { unit: "day", milliseconds: MS_PER_DAY },
+ { unit: "hour", milliseconds: MS_PER_HOUR },
+ { unit: "minute", milliseconds: MS_PER_MINUTE },
+ { unit: "second", milliseconds: MS_PER_SECOND },
+];
+
+const getDurationUnit = (ms: number) =>
+ DURATION_UNITS.find(({ milliseconds }) => Math.abs(ms) >= milliseconds) ??
+ DURATION_UNITS[DURATION_UNITS.length - 1];
+
+export const formatDuration = (
+ ms: number,
+ { long = false, relative = false, hasSpace = true, locale }: FormatDurationOptions = {}
+): string => {
+ if (long || relative) {
+ const { unit, milliseconds } = getDurationUnit(ms);
+ const value = Math.sign(ms) * Math.floor(Math.abs(ms) / milliseconds);
+
+ if (relative) {
+ return new Intl.RelativeTimeFormat(locale, {
+ numeric: "always",
+ style: long ? "long" : "narrow",
+ }).format(-value, unit);
+ }
+
+ return new Intl.NumberFormat(locale, {
+ style: "unit",
+ unit,
+ unitDisplay: "long",
+ }).format(value);
}
const formatted = prettyMilliseconds(ms, {
diff --git a/client/src/locales/de.json b/client/src/locales/de.json
index 6a39ee1aa..23db1be49 100644
--- a/client/src/locales/de.json
+++ b/client/src/locales/de.json
@@ -448,6 +448,7 @@
},
"statBoxes": {
"activeFor": "Aktiv seit",
+ "checkingEvery": "Check alle {{interval}}",
"certificateExpiry": "Zertifikatablauf",
"lastCheck": "Letzter Check",
"lastResponseTime": "Letzte Antwortzeit",
diff --git a/client/src/locales/en.json b/client/src/locales/en.json
index cbebadded..03b69a3bf 100644
--- a/client/src/locales/en.json
+++ b/client/src/locales/en.json
@@ -545,6 +545,7 @@
},
"statBoxes": {
"activeFor": "Active for",
+ "checkingEvery": "Checking every {{interval}}",
"certificateExpiry": "Certificate expiry",
"domainExpiry": "Domain expiry",
"lastCheck": "Last check",