mirror of
https://github.com/home-assistant/frontend.git
synced 2025-06-08 03:06:34 +00:00
Use explicit duration format for state formatting (#23017)
This commit is contained in:
parent
dd7987e199
commit
a532b4461d
@ -147,6 +147,7 @@ const polyfillMap = {
|
|||||||
...Object.fromEntries(
|
...Object.fromEntries(
|
||||||
[
|
[
|
||||||
"DateTimeFormat",
|
"DateTimeFormat",
|
||||||
|
"DurationFormat",
|
||||||
"DisplayNames",
|
"DisplayNames",
|
||||||
"ListFormat",
|
"ListFormat",
|
||||||
"NumberFormat",
|
"NumberFormat",
|
||||||
|
@ -9,6 +9,7 @@ const outDir = join(paths.build_dir, "locale-data");
|
|||||||
|
|
||||||
const INTL_POLYFILLS = {
|
const INTL_POLYFILLS = {
|
||||||
"intl-datetimeformat": "DateTimeFormat",
|
"intl-datetimeformat": "DateTimeFormat",
|
||||||
|
"intl-durationFormat": "DurationFormat",
|
||||||
"intl-displaynames": "DisplayNames",
|
"intl-displaynames": "DisplayNames",
|
||||||
"intl-listformat": "ListFormat",
|
"intl-listformat": "ListFormat",
|
||||||
"intl-numberformat": "NumberFormat",
|
"intl-numberformat": "NumberFormat",
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
"@egjs/hammerjs": "2.0.17",
|
"@egjs/hammerjs": "2.0.17",
|
||||||
"@formatjs/intl-datetimeformat": "6.16.5",
|
"@formatjs/intl-datetimeformat": "6.16.5",
|
||||||
"@formatjs/intl-displaynames": "6.8.5",
|
"@formatjs/intl-displaynames": "6.8.5",
|
||||||
|
"@formatjs/intl-durationformat": "0.6.4",
|
||||||
"@formatjs/intl-getcanonicallocales": "2.5.3",
|
"@formatjs/intl-getcanonicallocales": "2.5.3",
|
||||||
"@formatjs/intl-listformat": "7.7.5",
|
"@formatjs/intl-listformat": "7.7.5",
|
||||||
"@formatjs/intl-locale": "4.2.5",
|
"@formatjs/intl-locale": "4.2.5",
|
||||||
|
@ -1,19 +1,109 @@
|
|||||||
import millisecondsToDuration from "./milliseconds_to_duration";
|
import { DurationFormat } from "@formatjs/intl-durationformat";
|
||||||
|
import type { DurationInput } from "@formatjs/intl-durationformat/src/types";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
import type { FrontendLocaleData } from "../../data/translation";
|
||||||
|
import { round } from "../number/round";
|
||||||
|
|
||||||
const DAY_IN_MILLISECONDS = 86400000;
|
export const DURATION_UNITS = ["ms", "s", "min", "h", "d"] as const;
|
||||||
const HOUR_IN_MILLISECONDS = 3600000;
|
|
||||||
const MINUTE_IN_MILLISECONDS = 60000;
|
|
||||||
const SECOND_IN_MILLISECONDS = 1000;
|
|
||||||
|
|
||||||
export const UNIT_TO_MILLISECOND_CONVERT = {
|
type DurationUnit = (typeof DURATION_UNITS)[number];
|
||||||
ms: 1,
|
|
||||||
s: SECOND_IN_MILLISECONDS,
|
const formatDurationDayMem = memoizeOne(
|
||||||
min: MINUTE_IN_MILLISECONDS,
|
(locale: FrontendLocaleData) =>
|
||||||
h: HOUR_IN_MILLISECONDS,
|
new DurationFormat(locale.language, {
|
||||||
d: DAY_IN_MILLISECONDS,
|
style: "narrow",
|
||||||
|
daysDisplay: "always",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const formatDurationHourMem = memoizeOne(
|
||||||
|
(locale: FrontendLocaleData) =>
|
||||||
|
new DurationFormat(locale.language, {
|
||||||
|
style: "narrow",
|
||||||
|
hoursDisplay: "always",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const formatDurationMinuteMem = memoizeOne(
|
||||||
|
(locale: FrontendLocaleData) =>
|
||||||
|
new DurationFormat(locale.language, {
|
||||||
|
style: "narrow",
|
||||||
|
minutesDisplay: "always",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const formatDurationSecondMem = memoizeOne(
|
||||||
|
(locale: FrontendLocaleData) =>
|
||||||
|
new DurationFormat(locale.language, {
|
||||||
|
style: "narrow",
|
||||||
|
secondsDisplay: "always",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const formatDurationMillisecondMem = memoizeOne(
|
||||||
|
(locale: FrontendLocaleData) =>
|
||||||
|
new DurationFormat(locale.language, {
|
||||||
|
style: "narrow",
|
||||||
|
millisecondsDisplay: "always",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
export const formatDuration = (
|
||||||
|
duration: string,
|
||||||
|
unit: DurationUnit,
|
||||||
|
precision: number | undefined,
|
||||||
|
locale: FrontendLocaleData
|
||||||
|
): string => {
|
||||||
|
const value =
|
||||||
|
precision !== undefined
|
||||||
|
? round(parseFloat(duration), precision)
|
||||||
|
: parseFloat(duration);
|
||||||
|
|
||||||
|
switch (unit) {
|
||||||
|
case "d": {
|
||||||
|
const days = Math.floor(value);
|
||||||
|
const hours = Math.floor((value - days) * 24);
|
||||||
|
const input: DurationInput = {
|
||||||
|
days,
|
||||||
|
hours,
|
||||||
|
};
|
||||||
|
return formatDurationDayMem(locale).format(input);
|
||||||
|
}
|
||||||
|
case "h": {
|
||||||
|
const hours = Math.floor(value);
|
||||||
|
const minutes = Math.floor((value - hours) * 60);
|
||||||
|
const input: DurationInput = {
|
||||||
|
hours,
|
||||||
|
minutes,
|
||||||
|
};
|
||||||
|
return formatDurationHourMem(locale).format(input);
|
||||||
|
}
|
||||||
|
case "min": {
|
||||||
|
const minutes = Math.floor(value);
|
||||||
|
const seconds = Math.floor((value - minutes) * 60);
|
||||||
|
const input: DurationInput = {
|
||||||
|
minutes,
|
||||||
|
seconds,
|
||||||
|
};
|
||||||
|
return formatDurationMinuteMem(locale).format(input);
|
||||||
|
}
|
||||||
|
case "s": {
|
||||||
|
const seconds = Math.floor(value);
|
||||||
|
const milliseconds = Math.floor((value - seconds) * 1000);
|
||||||
|
const input: DurationInput = {
|
||||||
|
seconds,
|
||||||
|
milliseconds,
|
||||||
|
};
|
||||||
|
return formatDurationSecondMem(locale).format(input);
|
||||||
|
}
|
||||||
|
case "ms": {
|
||||||
|
const milliseconds = Math.floor(value);
|
||||||
|
const input: DurationInput = {
|
||||||
|
milliseconds,
|
||||||
|
};
|
||||||
|
return formatDurationMillisecondMem(locale).format(input);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error("Invalid duration unit");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const formatDuration = (duration: string, units: string): string =>
|
|
||||||
millisecondsToDuration(
|
|
||||||
parseFloat(duration) * UNIT_TO_MILLISECOND_CONVERT[units]
|
|
||||||
) || "0";
|
|
||||||
|
@ -4,7 +4,7 @@ import { formatListWithAnds } from "../string/format-list";
|
|||||||
|
|
||||||
const leftPad = (num: number) => (num < 10 ? `0${num}` : num);
|
const leftPad = (num: number) => (num < 10 ? `0${num}` : num);
|
||||||
|
|
||||||
export const formatDuration = (
|
export const formatNumericDuration = (
|
||||||
locale: FrontendLocaleData,
|
locale: FrontendLocaleData,
|
||||||
duration: HaDurationData
|
duration: HaDurationData
|
||||||
) => {
|
) => {
|
||||||
|
@ -4,10 +4,7 @@ import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
|
|||||||
import type { FrontendLocaleData } from "../../data/translation";
|
import type { FrontendLocaleData } from "../../data/translation";
|
||||||
import { TimeZone } from "../../data/translation";
|
import { TimeZone } from "../../data/translation";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import {
|
import { DURATION_UNITS, formatDuration } from "../datetime/duration";
|
||||||
UNIT_TO_MILLISECOND_CONVERT,
|
|
||||||
formatDuration,
|
|
||||||
} from "../datetime/duration";
|
|
||||||
import { formatDate } from "../datetime/format_date";
|
import { formatDate } from "../datetime/format_date";
|
||||||
import { formatDateTime } from "../datetime/format_date_time";
|
import { formatDateTime } from "../datetime/format_date_time";
|
||||||
import { formatTime } from "../datetime/format_time";
|
import { formatTime } from "../datetime/format_time";
|
||||||
@ -32,7 +29,6 @@ export const computeStateDisplay = (
|
|||||||
const entity = entities?.[stateObj.entity_id] as
|
const entity = entities?.[stateObj.entity_id] as
|
||||||
| EntityRegistryDisplayEntry
|
| EntityRegistryDisplayEntry
|
||||||
| undefined;
|
| undefined;
|
||||||
|
|
||||||
return computeStateDisplayFromEntityAttributes(
|
return computeStateDisplayFromEntityAttributes(
|
||||||
localize,
|
localize,
|
||||||
locale,
|
locale,
|
||||||
@ -72,10 +68,15 @@ export const computeStateDisplayFromEntityAttributes = (
|
|||||||
if (
|
if (
|
||||||
attributes.device_class === "duration" &&
|
attributes.device_class === "duration" &&
|
||||||
attributes.unit_of_measurement &&
|
attributes.unit_of_measurement &&
|
||||||
UNIT_TO_MILLISECOND_CONVERT[attributes.unit_of_measurement]
|
DURATION_UNITS.includes(attributes.unit_of_measurement)
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
return formatDuration(state, attributes.unit_of_measurement);
|
return formatDuration(
|
||||||
|
state,
|
||||||
|
attributes.unit_of_measurement,
|
||||||
|
entity?.display_precision,
|
||||||
|
locale
|
||||||
|
);
|
||||||
} catch (_err) {
|
} catch (_err) {
|
||||||
// fallback to default
|
// fallback to default
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { HassConfig } from "home-assistant-js-websocket";
|
import type { HassConfig } from "home-assistant-js-websocket";
|
||||||
import { ensureArray } from "../common/array/ensure-array";
|
import { ensureArray } from "../common/array/ensure-array";
|
||||||
import {
|
import {
|
||||||
formatDuration,
|
formatNumericDuration,
|
||||||
formatDurationLong,
|
formatDurationLong,
|
||||||
} from "../common/datetime/format_duration";
|
} from "../common/datetime/format_duration";
|
||||||
import {
|
import {
|
||||||
@ -42,7 +42,7 @@ const describeDuration = (
|
|||||||
} else if (typeof forTime === "string") {
|
} else if (typeof forTime === "string") {
|
||||||
duration = forTime;
|
duration = forTime;
|
||||||
} else {
|
} else {
|
||||||
duration = formatDuration(locale, forTime);
|
duration = formatNumericDuration(locale, forTime);
|
||||||
}
|
}
|
||||||
return duration;
|
return duration;
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { formatDuration } from "../common/datetime/duration";
|
import { formatNumericDuration } from "../common/datetime/format_duration";
|
||||||
import type { FrontendLocaleData } from "./translation";
|
import type { FrontendLocaleData } from "./translation";
|
||||||
|
|
||||||
export const STATE_ATTRIBUTES = [
|
export const STATE_ATTRIBUTES = [
|
||||||
@ -99,6 +99,7 @@ export const DOMAIN_ATTRIBUTES_FORMATERS: Record<
|
|||||||
},
|
},
|
||||||
media_player: {
|
media_player: {
|
||||||
volume_level: (value) => Math.round(value * 100).toString(),
|
volume_level: (value) => Math.round(value * 100).toString(),
|
||||||
media_duration: (value) => formatDuration(value.toString(), "s"),
|
media_duration: (value, locale) =>
|
||||||
|
formatNumericDuration(locale, { seconds: value })!,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ensureArray } from "../common/array/ensure-array";
|
import { ensureArray } from "../common/array/ensure-array";
|
||||||
import { formatDuration } from "../common/datetime/format_duration";
|
import { formatNumericDuration } from "../common/datetime/format_duration";
|
||||||
import secondsToDuration from "../common/datetime/seconds_to_duration";
|
import secondsToDuration from "../common/datetime/seconds_to_duration";
|
||||||
import { computeStateName } from "../common/entity/compute_state_name";
|
import { computeStateName } from "../common/entity/compute_state_name";
|
||||||
import { formatListWithAnds } from "../common/string/format-list";
|
import { formatListWithAnds } from "../common/string/format-list";
|
||||||
@ -277,7 +277,7 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
duration = hass.localize(
|
duration = hass.localize(
|
||||||
`${actionTranslationBaseKey}.delay.description.duration_string`,
|
`${actionTranslationBaseKey}.delay.description.duration_string`,
|
||||||
{
|
{
|
||||||
string: formatDuration(hass.locale, config.delay),
|
string: formatNumericDuration(hass.locale, config.delay),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -6,6 +6,8 @@ import { shouldPolyfill as shouldPolyfillLocale } from "@formatjs/intl-locale/sh
|
|||||||
import { shouldPolyfill as shouldPolyfillNumberFormat } from "@formatjs/intl-numberformat/should-polyfill";
|
import { shouldPolyfill as shouldPolyfillNumberFormat } from "@formatjs/intl-numberformat/should-polyfill";
|
||||||
import { shouldPolyfill as shouldPolyfillPluralRules } from "@formatjs/intl-pluralrules/should-polyfill";
|
import { shouldPolyfill as shouldPolyfillPluralRules } from "@formatjs/intl-pluralrules/should-polyfill";
|
||||||
import { shouldPolyfill as shouldPolyfillRelativeTimeFormat } from "@formatjs/intl-relativetimeformat/should-polyfill";
|
import { shouldPolyfill as shouldPolyfillRelativeTimeFormat } from "@formatjs/intl-relativetimeformat/should-polyfill";
|
||||||
|
import { shouldPolyfill as shouldPolyfillDurationFormat } from "@formatjs/intl-durationformat/should-polyfill";
|
||||||
|
|
||||||
import { getLocalLanguage } from "../../util/common-translation";
|
import { getLocalLanguage } from "../../util/common-translation";
|
||||||
import {
|
import {
|
||||||
polyfillLocaleData,
|
polyfillLocaleData,
|
||||||
@ -28,6 +30,9 @@ const polyfillIntl = async () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (shouldPolyfillDurationFormat()) {
|
||||||
|
polyfills.push(import("@formatjs/intl-durationformat/polyfill-force"));
|
||||||
|
}
|
||||||
if (shouldPolyfillDisplayNames(locale)) {
|
if (shouldPolyfillDisplayNames(locale)) {
|
||||||
polyfills.push(import("@formatjs/intl-displaynames/polyfill-force"));
|
polyfills.push(import("@formatjs/intl-displaynames/polyfill-force"));
|
||||||
}
|
}
|
||||||
|
@ -1,47 +1,90 @@
|
|||||||
import { assert, describe, it } from "vitest";
|
import { assert, describe, it } from "vitest";
|
||||||
|
|
||||||
import { formatDuration } from "../../../src/common/datetime/duration";
|
import { formatDuration } from "../../../src/common/datetime/duration";
|
||||||
|
import type { FrontendLocaleData } from "../../../src/data/translation";
|
||||||
|
import {
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
|
NumberFormat,
|
||||||
|
TimeFormat,
|
||||||
|
TimeZone,
|
||||||
|
} from "../../../src/data/translation";
|
||||||
|
|
||||||
|
const LOCALE: FrontendLocaleData = {
|
||||||
|
language: "en",
|
||||||
|
number_format: NumberFormat.language,
|
||||||
|
time_format: TimeFormat.am_pm,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
time_zone: TimeZone.local,
|
||||||
|
first_weekday: FirstWeekday.language,
|
||||||
|
};
|
||||||
|
|
||||||
describe("formatDuration", () => {
|
describe("formatDuration", () => {
|
||||||
it("works", () => {
|
it("works", () => {
|
||||||
assert.strictEqual(formatDuration("0", "ms"), "0");
|
assert.strictEqual(formatDuration("0", "ms", undefined, LOCALE), "0ms");
|
||||||
assert.strictEqual(formatDuration("1", "ms"), "0.001");
|
assert.strictEqual(formatDuration("1", "ms", undefined, LOCALE), "1ms");
|
||||||
assert.strictEqual(formatDuration("10", "ms"), "0.010");
|
assert.strictEqual(formatDuration("10", "ms", undefined, LOCALE), "10ms");
|
||||||
assert.strictEqual(formatDuration("100", "ms"), "0.100");
|
assert.strictEqual(formatDuration("100", "ms", undefined, LOCALE), "100ms");
|
||||||
assert.strictEqual(formatDuration("1000", "ms"), "1");
|
assert.strictEqual(
|
||||||
assert.strictEqual(formatDuration("1001", "ms"), "1.001");
|
formatDuration("1000", "ms", undefined, LOCALE),
|
||||||
assert.strictEqual(formatDuration("65000", "ms"), "1:05");
|
"1,000ms"
|
||||||
assert.strictEqual(formatDuration("3665000", "ms"), "1:01:05");
|
);
|
||||||
assert.strictEqual(formatDuration("39665050", "ms"), "11:01:05");
|
assert.strictEqual(
|
||||||
assert.strictEqual(formatDuration("932093000", "ms"), "258:54:53");
|
formatDuration("1001", "ms", undefined, LOCALE),
|
||||||
|
"1,001ms"
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
formatDuration("65000", "ms", undefined, LOCALE),
|
||||||
|
"65,000ms"
|
||||||
|
);
|
||||||
|
|
||||||
assert.strictEqual(formatDuration("0", "s"), "0");
|
assert.strictEqual(
|
||||||
assert.strictEqual(formatDuration("1", "s"), "1");
|
formatDuration("0.5", "s", undefined, LOCALE),
|
||||||
assert.strictEqual(formatDuration("1.1", "s"), "1.100");
|
"0s 500ms"
|
||||||
assert.strictEqual(formatDuration("65", "s"), "1:05");
|
);
|
||||||
assert.strictEqual(formatDuration("3665", "s"), "1:01:05");
|
assert.strictEqual(formatDuration("1", "s", undefined, LOCALE), "1s");
|
||||||
assert.strictEqual(formatDuration("39665", "s"), "11:01:05");
|
assert.strictEqual(
|
||||||
assert.strictEqual(formatDuration("932093", "s"), "258:54:53");
|
formatDuration("1.1", "s", undefined, LOCALE),
|
||||||
|
"1s 100ms"
|
||||||
|
);
|
||||||
|
assert.strictEqual(formatDuration("65", "s", undefined, LOCALE), "65s");
|
||||||
|
|
||||||
assert.strictEqual(formatDuration("0", "min"), "0");
|
assert.strictEqual(
|
||||||
assert.strictEqual(formatDuration("65", "min"), "1:05:00");
|
formatDuration("0.25", "min", undefined, LOCALE),
|
||||||
assert.strictEqual(formatDuration("3665", "min"), "61:05:00");
|
"0m 15s"
|
||||||
assert.strictEqual(formatDuration("39665", "min"), "661:05:00");
|
);
|
||||||
assert.strictEqual(formatDuration("932093", "min"), "15534:53:00");
|
assert.strictEqual(
|
||||||
assert.strictEqual(formatDuration("12.4", "min"), "12:24");
|
formatDuration("0.5", "min", undefined, LOCALE),
|
||||||
|
"0m 30s"
|
||||||
|
);
|
||||||
|
assert.strictEqual(formatDuration("1", "min", undefined, LOCALE), "1m");
|
||||||
|
assert.strictEqual(formatDuration("20", "min", undefined, LOCALE), "20m");
|
||||||
|
assert.strictEqual(
|
||||||
|
formatDuration("95.5", "min", undefined, LOCALE),
|
||||||
|
"95m 30s"
|
||||||
|
);
|
||||||
|
|
||||||
assert.strictEqual(formatDuration("0", "h"), "0");
|
assert.strictEqual(
|
||||||
assert.strictEqual(formatDuration("65", "h"), "65:00:00");
|
formatDuration("0.25", "h", undefined, LOCALE),
|
||||||
assert.strictEqual(formatDuration("3665", "h"), "3665:00:00");
|
"0h 15m"
|
||||||
assert.strictEqual(formatDuration("39665", "h"), "39665:00:00");
|
);
|
||||||
assert.strictEqual(formatDuration("932093", "h"), "932093:00:00");
|
assert.strictEqual(formatDuration("0.5", "h", undefined, LOCALE), "0h 30m");
|
||||||
assert.strictEqual(formatDuration("24.3", "h"), "24:18:00");
|
assert.strictEqual(formatDuration("1", "h", undefined, LOCALE), "1h");
|
||||||
assert.strictEqual(formatDuration("24.32423", "h"), "24:19:27");
|
assert.strictEqual(formatDuration("20", "h", undefined, LOCALE), "20h");
|
||||||
|
assert.strictEqual(
|
||||||
|
formatDuration("95.5", "h", undefined, LOCALE),
|
||||||
|
"95h 30m"
|
||||||
|
);
|
||||||
|
|
||||||
assert.strictEqual(formatDuration("0", "d"), "0");
|
assert.strictEqual(formatDuration("0", "d", undefined, LOCALE), "0d");
|
||||||
assert.strictEqual(formatDuration("65", "d"), "1560:00:00");
|
assert.strictEqual(formatDuration("0.4", "d", undefined, LOCALE), "0d 9h");
|
||||||
assert.strictEqual(formatDuration("3665", "d"), "87960:00:00");
|
assert.strictEqual(formatDuration("1", "d", undefined, LOCALE), "1d");
|
||||||
assert.strictEqual(formatDuration("39665", "d"), "951960:00:00");
|
assert.strictEqual(formatDuration("20", "d", undefined, LOCALE), "20d");
|
||||||
assert.strictEqual(formatDuration("932093", "d"), "22370232:00:00");
|
assert.strictEqual(
|
||||||
|
formatDuration("95.5", "d", undefined, LOCALE),
|
||||||
|
"95d 12h"
|
||||||
|
);
|
||||||
|
assert.strictEqual(formatDuration("95.75", "d", 0, LOCALE), "96d");
|
||||||
|
assert.strictEqual(formatDuration("95.75", "d", 2, LOCALE), "95d 18h");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
12
yarn.lock
12
yarn.lock
@ -1691,6 +1691,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@formatjs/intl-durationformat@npm:0.6.4":
|
||||||
|
version: 0.6.4
|
||||||
|
resolution: "@formatjs/intl-durationformat@npm:0.6.4"
|
||||||
|
dependencies:
|
||||||
|
"@formatjs/ecma402-abstract": "npm:2.2.4"
|
||||||
|
"@formatjs/intl-localematcher": "npm:0.5.8"
|
||||||
|
tslib: "npm:2"
|
||||||
|
checksum: 10/aa7c045e94322f0a5723584e79dd1395b3c08e5d1d79432748ae98c0b0c1727059bd1aa5c04090df916ff1aea768336184a2d09ecfd2ece2fb090c472bbd8250
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-enumerator@npm:1.8.4":
|
"@formatjs/intl-enumerator@npm:1.8.4":
|
||||||
version: 1.8.4
|
version: 1.8.4
|
||||||
resolution: "@formatjs/intl-enumerator@npm:1.8.4"
|
resolution: "@formatjs/intl-enumerator@npm:1.8.4"
|
||||||
@ -9487,6 +9498,7 @@ __metadata:
|
|||||||
"@egjs/hammerjs": "npm:2.0.17"
|
"@egjs/hammerjs": "npm:2.0.17"
|
||||||
"@formatjs/intl-datetimeformat": "npm:6.16.5"
|
"@formatjs/intl-datetimeformat": "npm:6.16.5"
|
||||||
"@formatjs/intl-displaynames": "npm:6.8.5"
|
"@formatjs/intl-displaynames": "npm:6.8.5"
|
||||||
|
"@formatjs/intl-durationformat": "npm:0.6.4"
|
||||||
"@formatjs/intl-getcanonicallocales": "npm:2.5.3"
|
"@formatjs/intl-getcanonicallocales": "npm:2.5.3"
|
||||||
"@formatjs/intl-listformat": "npm:7.7.5"
|
"@formatjs/intl-listformat": "npm:7.7.5"
|
||||||
"@formatjs/intl-locale": "npm:4.2.5"
|
"@formatjs/intl-locale": "npm:4.2.5"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user