mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 07:16:39 +00:00
Introduce Intl.ListFormat (#16857)
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com> Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
49fa7ec4ed
commit
5fc4e7a95d
@ -17,6 +17,7 @@ const modules = {
|
|||||||
"intl-datetimeformat": "DateTimeFormat",
|
"intl-datetimeformat": "DateTimeFormat",
|
||||||
"intl-numberformat": "NumberFormat",
|
"intl-numberformat": "NumberFormat",
|
||||||
"intl-displaynames": "DisplayNames",
|
"intl-displaynames": "DisplayNames",
|
||||||
|
"intl-listformat": "ListFormat",
|
||||||
};
|
};
|
||||||
|
|
||||||
gulp.task("create-locale-data", (done) => {
|
gulp.task("create-locale-data", (done) => {
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
"@formatjs/intl-datetimeformat": "6.9.0",
|
"@formatjs/intl-datetimeformat": "6.9.0",
|
||||||
"@formatjs/intl-displaynames": "6.4.0",
|
"@formatjs/intl-displaynames": "6.4.0",
|
||||||
"@formatjs/intl-getcanonicallocales": "2.2.1",
|
"@formatjs/intl-getcanonicallocales": "2.2.1",
|
||||||
|
"@formatjs/intl-listformat": "7.3.0",
|
||||||
"@formatjs/intl-locale": "3.3.1",
|
"@formatjs/intl-locale": "3.3.1",
|
||||||
"@formatjs/intl-numberformat": "8.6.0",
|
"@formatjs/intl-numberformat": "8.6.0",
|
||||||
"@formatjs/intl-pluralrules": "5.2.3",
|
"@formatjs/intl-pluralrules": "5.2.3",
|
||||||
|
@ -21,6 +21,7 @@ import {
|
|||||||
localizeDeviceAutomationTrigger,
|
localizeDeviceAutomationTrigger,
|
||||||
} from "./device_automation";
|
} from "./device_automation";
|
||||||
import { EntityRegistryEntry } from "./entity_registry";
|
import { EntityRegistryEntry } from "./entity_registry";
|
||||||
|
import "../resources/intl-polyfill";
|
||||||
import { FrontendLocaleData } from "./translation";
|
import { FrontendLocaleData } from "./translation";
|
||||||
|
|
||||||
const describeDuration = (forTime: number | string | ForDict) => {
|
const describeDuration = (forTime: number | string | ForDict) => {
|
||||||
@ -82,6 +83,11 @@ export const describeTrigger = (
|
|||||||
return trigger.alias;
|
return trigger.alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const disjunctionFormatter = new Intl.ListFormat("en", {
|
||||||
|
style: "long",
|
||||||
|
type: "disjunction",
|
||||||
|
});
|
||||||
|
|
||||||
// Event Trigger
|
// Event Trigger
|
||||||
if (trigger.platform === "event" && trigger.event_type) {
|
if (trigger.platform === "event" && trigger.event_type) {
|
||||||
let eventTypes = "";
|
let eventTypes = "";
|
||||||
@ -489,51 +495,43 @@ export const describeTrigger = (
|
|||||||
|
|
||||||
// Zone Trigger
|
// Zone Trigger
|
||||||
if (trigger.platform === "zone" && trigger.entity_id && trigger.zone) {
|
if (trigger.platform === "zone" && trigger.entity_id && trigger.zone) {
|
||||||
let entities = "";
|
const entities: string[] = [];
|
||||||
let zones = "";
|
const zones: string[] = [];
|
||||||
let zonesPlural = false;
|
|
||||||
|
|
||||||
const states = hass.states;
|
const states = hass.states;
|
||||||
|
|
||||||
if (Array.isArray(trigger.entity_id)) {
|
if (Array.isArray(trigger.entity_id)) {
|
||||||
for (const [index, entity] of trigger.entity_id.entries()) {
|
for (const [entity] of trigger.entity_id.entries()) {
|
||||||
if (states[entity]) {
|
if (states[entity]) {
|
||||||
entities += `${index > 0 ? "," : ""} ${
|
entities.push(`${computeStateName(states[entity]) || entity}`);
|
||||||
trigger.entity_id.length > 1 &&
|
|
||||||
index === trigger.entity_id.length - 1
|
|
||||||
? "or"
|
|
||||||
: ""
|
|
||||||
} ${computeStateName(states[entity]) || entity}`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
entities = states[trigger.entity_id]
|
entities.push(
|
||||||
? computeStateName(states[trigger.entity_id])
|
states[trigger.entity_id]
|
||||||
: trigger.entity_id;
|
? computeStateName(states[trigger.entity_id])
|
||||||
|
: trigger.entity_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(trigger.zone)) {
|
if (Array.isArray(trigger.zone)) {
|
||||||
if (trigger.zone.length > 1) {
|
for (const [zone] of trigger.zone.entries()) {
|
||||||
zonesPlural = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [index, zone] of trigger.zone.entries()) {
|
|
||||||
if (states[zone]) {
|
if (states[zone]) {
|
||||||
zones += `${index > 0 ? "," : ""} ${
|
zones.push(`${computeStateName(states[zone]) || zone}`);
|
||||||
trigger.zone.length > 1 && index === trigger.zone.length - 1
|
|
||||||
? "or"
|
|
||||||
: ""
|
|
||||||
} ${computeStateName(states[zone]) || zone}`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
zones = states[trigger.zone]
|
zones.push(
|
||||||
? computeStateName(states[trigger.zone])
|
states[trigger.zone]
|
||||||
: trigger.zone;
|
? computeStateName(states[trigger.zone])
|
||||||
|
: trigger.zone
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `When ${entities} ${trigger.event}s ${zones} ${
|
const entitiesString = disjunctionFormatter.format(entities);
|
||||||
zonesPlural ? "zones" : "zone"
|
const zonesString = disjunctionFormatter.format(zones);
|
||||||
|
return `When ${entitiesString} ${trigger.event}s ${zonesString} ${
|
||||||
|
zones.length > 1 ? "zones" : "zone"
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,6 +634,11 @@ export const describeCondition = (
|
|||||||
return condition.alias;
|
return condition.alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const disjunctionFormatter = new Intl.ListFormat("en", {
|
||||||
|
style: "long",
|
||||||
|
type: "disjunction",
|
||||||
|
});
|
||||||
|
|
||||||
if (!condition.condition) {
|
if (!condition.condition) {
|
||||||
const shorthands: Array<"and" | "or" | "not"> = ["and", "or", "not"];
|
const shorthands: Array<"and" | "or" | "not"> = ["and", "or", "not"];
|
||||||
for (const key of shorthands) {
|
for (const key of shorthands) {
|
||||||
@ -938,56 +941,44 @@ export const describeCondition = (
|
|||||||
|
|
||||||
// Zone condition
|
// Zone condition
|
||||||
if (condition.condition === "zone" && condition.entity_id && condition.zone) {
|
if (condition.condition === "zone" && condition.entity_id && condition.zone) {
|
||||||
let entities = "";
|
const entities: string[] = [];
|
||||||
let entitiesPlural = false;
|
const zones: string[] = [];
|
||||||
let zones = "";
|
|
||||||
let zonesPlural = false;
|
|
||||||
|
|
||||||
const states = hass.states;
|
const states = hass.states;
|
||||||
|
|
||||||
if (Array.isArray(condition.entity_id)) {
|
if (Array.isArray(condition.entity_id)) {
|
||||||
if (condition.entity_id.length > 1) {
|
for (const [entity] of condition.entity_id.entries()) {
|
||||||
entitiesPlural = true;
|
|
||||||
}
|
|
||||||
for (const [index, entity] of condition.entity_id.entries()) {
|
|
||||||
if (states[entity]) {
|
if (states[entity]) {
|
||||||
entities += `${index > 0 ? "," : ""} ${
|
entities.push(`${computeStateName(states[entity]) || entity}`);
|
||||||
condition.entity_id.length > 1 &&
|
|
||||||
index === condition.entity_id.length - 1
|
|
||||||
? "or"
|
|
||||||
: ""
|
|
||||||
} ${computeStateName(states[entity]) || entity}`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
entities = states[condition.entity_id]
|
entities.push(
|
||||||
? computeStateName(states[condition.entity_id])
|
states[condition.entity_id]
|
||||||
: condition.entity_id;
|
? computeStateName(states[condition.entity_id])
|
||||||
|
: condition.entity_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(condition.zone)) {
|
if (Array.isArray(condition.zone)) {
|
||||||
if (condition.zone.length > 1) {
|
for (const [zone] of condition.zone.entries()) {
|
||||||
zonesPlural = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [index, zone] of condition.zone.entries()) {
|
|
||||||
if (states[zone]) {
|
if (states[zone]) {
|
||||||
zones += `${index > 0 ? "," : ""} ${
|
zones.push(`${computeStateName(states[zone]) || zone}`);
|
||||||
condition.zone.length > 1 && index === condition.zone.length - 1
|
|
||||||
? "or"
|
|
||||||
: ""
|
|
||||||
} ${computeStateName(states[zone]) || zone}`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
zones = states[condition.zone]
|
zones.push(
|
||||||
? computeStateName(states[condition.zone])
|
states[condition.zone]
|
||||||
: condition.zone;
|
? computeStateName(states[condition.zone])
|
||||||
|
: condition.zone
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `Confirm ${entities} ${entitiesPlural ? "are" : "is"} in ${zones} ${
|
const entitiesString = disjunctionFormatter.format(entities);
|
||||||
zonesPlural ? "zones" : "zone"
|
const zonesString = disjunctionFormatter.format(zones);
|
||||||
}`;
|
return `Confirm ${entitiesString} ${
|
||||||
|
entities.length > 1 ? "are" : "is"
|
||||||
|
} in ${zonesString} ${zones.length > 1 ? "zones" : "zone"}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (condition.condition === "device") {
|
if (condition.condition === "device") {
|
||||||
|
@ -15,3 +15,5 @@ import "@formatjs/intl-datetimeformat/locale-data/en";
|
|||||||
import "@formatjs/intl-datetimeformat/add-all-tz";
|
import "@formatjs/intl-datetimeformat/add-all-tz";
|
||||||
import "@formatjs/intl-displaynames/polyfill";
|
import "@formatjs/intl-displaynames/polyfill";
|
||||||
import "@formatjs/intl-displaynames/locale-data/en";
|
import "@formatjs/intl-displaynames/locale-data/en";
|
||||||
|
import "@formatjs/intl-listformat/polyfill";
|
||||||
|
import "@formatjs/intl-listformat/locale-data/en";
|
||||||
|
@ -3,6 +3,7 @@ import { shouldPolyfill as shouldPolyfillDisplayName } from "@formatjs/intl-disp
|
|||||||
import { shouldPolyfill as shouldPolyfillLocale } from "@formatjs/intl-locale/should-polyfill";
|
import { shouldPolyfill as shouldPolyfillLocale } from "@formatjs/intl-locale/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 shouldPolyfillRelativeTime } from "@formatjs/intl-relativetimeformat/should-polyfill";
|
import { shouldPolyfill as shouldPolyfillRelativeTime } from "@formatjs/intl-relativetimeformat/should-polyfill";
|
||||||
|
import { shouldPolyfill as shouldPolyfillListFormat } from "@formatjs/intl-listformat/should-polyfill";
|
||||||
import { getLocalLanguage } from "../util/common-translation";
|
import { getLocalLanguage } from "../util/common-translation";
|
||||||
import { polyfillLocaleData } from "./locale-data-polyfill";
|
import { polyfillLocaleData } from "./locale-data-polyfill";
|
||||||
|
|
||||||
@ -29,6 +30,9 @@ const polyfillIntl = async () => {
|
|||||||
if (shouldPolyfillDisplayName(locale)) {
|
if (shouldPolyfillDisplayName(locale)) {
|
||||||
polyfills.push(import("@formatjs/intl-displaynames/polyfill-force"));
|
polyfills.push(import("@formatjs/intl-displaynames/polyfill-force"));
|
||||||
}
|
}
|
||||||
|
if (shouldPolyfillListFormat(locale)) {
|
||||||
|
polyfills.push(import("@formatjs/intl-listformat/polyfill-force"));
|
||||||
|
}
|
||||||
if (polyfills.length === 0) {
|
if (polyfills.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,17 @@ export const polyfillLocaleData = async (language: string) => {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
Intl.DisplayNames.__addLocaleData(await result.json());
|
Intl.DisplayNames.__addLocaleData(await result.json());
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
Intl.ListFormat &&
|
||||||
|
// @ts-ignore
|
||||||
|
typeof Intl.ListFormat.__addLocaleData === "function"
|
||||||
|
) {
|
||||||
|
const result = await fetch(
|
||||||
|
`${__STATIC_PATH__}locale-data/intl-listformat/${language}.json`
|
||||||
|
);
|
||||||
|
// @ts-ignore
|
||||||
|
Intl.ListFormat.__addLocaleData(await result.json());
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
// Language Options
|
// Language Options
|
||||||
"target": "ES2017",
|
"target": "ES2021",
|
||||||
"lib": [
|
"lib": ["ES2021", "DOM", "DOM.Iterable", "WebWorker"],
|
||||||
"ES2017",
|
|
||||||
"DOM",
|
|
||||||
"DOM.Iterable",
|
|
||||||
"WebWorker"
|
|
||||||
],
|
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
// Modules
|
// Modules
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
@ -43,4 +38,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
yarn.lock
12
yarn.lock
@ -1669,6 +1669,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@formatjs/intl-listformat@npm:7.3.0":
|
||||||
|
version: 7.3.0
|
||||||
|
resolution: "@formatjs/intl-listformat@npm:7.3.0"
|
||||||
|
dependencies:
|
||||||
|
"@formatjs/ecma402-abstract": 1.16.0
|
||||||
|
"@formatjs/intl-localematcher": 0.3.0
|
||||||
|
tslib: ^2.4.0
|
||||||
|
checksum: 6638e6a3cad750ac5199cf293c549c4048f0de240762dd98c61cece645091f19262ef64c1fb2f7a44b5bb3e5c168a8f53e9aa604b4867290981c30baf8635c0d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-locale@npm:3.3.1":
|
"@formatjs/intl-locale@npm:3.3.1":
|
||||||
version: 3.3.1
|
version: 3.3.1
|
||||||
resolution: "@formatjs/intl-locale@npm:3.3.1"
|
resolution: "@formatjs/intl-locale@npm:3.3.1"
|
||||||
@ -9620,6 +9631,7 @@ __metadata:
|
|||||||
"@formatjs/intl-datetimeformat": 6.9.0
|
"@formatjs/intl-datetimeformat": 6.9.0
|
||||||
"@formatjs/intl-displaynames": 6.4.0
|
"@formatjs/intl-displaynames": 6.4.0
|
||||||
"@formatjs/intl-getcanonicallocales": 2.2.1
|
"@formatjs/intl-getcanonicallocales": 2.2.1
|
||||||
|
"@formatjs/intl-listformat": 7.3.0
|
||||||
"@formatjs/intl-locale": 3.3.1
|
"@formatjs/intl-locale": 3.3.1
|
||||||
"@formatjs/intl-numberformat": 8.6.0
|
"@formatjs/intl-numberformat": 8.6.0
|
||||||
"@formatjs/intl-pluralrules": 5.2.3
|
"@formatjs/intl-pluralrules": 5.2.3
|
||||||
|
Loading…
x
Reference in New Issue
Block a user