diff --git a/ui/__snapshots__/qa.spec.ts.snap b/ui/__snapshots__/qa.spec.ts.snap
index a853551a..a2779860 100644
--- a/ui/__snapshots__/qa.spec.ts.snap
+++ b/ui/__snapshots__/qa.spec.ts.snap
@@ -106,7 +106,7 @@ var closeIconHTML = '';
var closeBtnHTML = \`\`;
// helpers/countdown.ts
-var formatDeadline = (time) => {
+var formatDeadline = (time, locales = [LOCALE, void 0]) => {
let unit = "second";
let timeLeft = (time - Date.now()) / 1e3;
if (timeLeft >= 60) {
@@ -118,14 +118,22 @@ var formatDeadline = (time) => {
unit = "hour";
}
const isLastMinute = unit === "minute" && timeLeft < 2;
- const formattedTimeLeft = new Intl.NumberFormat(LOCALE, {
- style: "unit",
- unitDisplay: "long",
- minimumFractionDigits: isLastMinute ? 1 : 0,
- maximumFractionDigits: isLastMinute ? 1 : 0,
- unit
- }).format(Math.max(0, timeLeft));
- return \`in \${formattedTimeLeft}\`;
+ const nonNegTimeLeft = Math.max(0, timeLeft);
+ for (const locale of locales) {
+ try {
+ const formattedTimeLeft = new Intl.NumberFormat(locale, {
+ style: "unit",
+ unitDisplay: "long",
+ minimumFractionDigits: isLastMinute ? 1 : 0,
+ maximumFractionDigits: isLastMinute ? 1 : 0,
+ unit
+ }).format(nonNegTimeLeft);
+ return \`in \${formattedTimeLeft}\`;
+ } catch (error) {
+ console.warn(\`Failed to format time using \${locale} locale\`, error);
+ }
+ }
+ return \`in \${nonNegTimeLeft} \${unit}\${nonNegTimeLeft === 1 ? "" : "s"}\`;
};
var getCountdownDelay = (deadline) => deadline - Date.now() > 12e4 ? 6e4 : 1e3;
var setCountdown = (selector, deadline) => {
diff --git a/ui/helpers/countdown.spec.ts b/ui/helpers/countdown.spec.ts
index cf0c7dd3..1389793c 100644
--- a/ui/helpers/countdown.spec.ts
+++ b/ui/helpers/countdown.spec.ts
@@ -46,6 +46,31 @@ describe("Countdown helpers", () => {
expect(formatDeadline(Date.now() + offset * 1000)).toMatchSnapshot();
},
);
+
+ test.each([
+ [10000, "10 seconds"],
+ [60000, "1 minute"],
+ [-10000, "0 seconds"],
+ ])(`should handle invalid locales %#`, (offset, label) => {
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+ expect(
+ formatDeadline(Date.now() + offset, [
+ "invalid_locale_id",
+ "another_invalid_one",
+ ]),
+ ).toBe(`in ${label}`);
+ expect(warnSpy).toHaveBeenCalledTimes(2);
+ expect(warnSpy.mock.calls).toEqual([
+ [
+ "Failed to format time using invalid_locale_id locale",
+ expect.any(Error),
+ ],
+ [
+ "Failed to format time using another_invalid_one locale",
+ expect.any(Error),
+ ],
+ ]);
+ });
});
describe("getCountdownDelay() helper", () => {
diff --git a/ui/helpers/countdown.ts b/ui/helpers/countdown.ts
index 62d86f77..1903a6a8 100644
--- a/ui/helpers/countdown.ts
+++ b/ui/helpers/countdown.ts
@@ -1,4 +1,7 @@
-export const formatDeadline = (time: number): string => {
+export const formatDeadline = (
+ time: number,
+ locales = [LOCALE, undefined],
+): string => {
let unit: "second" | "minute" | "hour" = "second";
let timeLeft = (time - Date.now()) / 1000;
if (timeLeft >= 60) {
@@ -10,14 +13,22 @@ export const formatDeadline = (time: number): string => {
unit = "hour";
}
const isLastMinute = unit === "minute" && timeLeft < 2;
- const formattedTimeLeft = new Intl.NumberFormat(LOCALE, {
- style: "unit",
- unitDisplay: "long",
- minimumFractionDigits: isLastMinute ? 1 : 0,
- maximumFractionDigits: isLastMinute ? 1 : 0,
- unit,
- }).format(Math.max(0, timeLeft));
- return `in ${formattedTimeLeft}`;
+ const nonNegTimeLeft = Math.max(0, timeLeft);
+ for (const locale of locales) {
+ try {
+ const formattedTimeLeft = new Intl.NumberFormat(locale, {
+ style: "unit",
+ unitDisplay: "long",
+ minimumFractionDigits: isLastMinute ? 1 : 0,
+ maximumFractionDigits: isLastMinute ? 1 : 0,
+ unit,
+ }).format(nonNegTimeLeft);
+ return `in ${formattedTimeLeft}`;
+ } catch (error) {
+ console.warn(`Failed to format time using ${locale} locale`, error);
+ }
+ }
+ return `in ${nonNegTimeLeft} ${unit}${nonNegTimeLeft === 1 ? "" : "s"}`;
};
export const getCountdownDelay = (deadline: number): number =>