mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Make automation editor card headers translateable (actions) (#17027)
This commit is contained in:
parent
a477120f13
commit
7dbb419c30
27
src/common/string/format-list.ts
Normal file
27
src/common/string/format-list.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
import "../../resources/intl-polyfill";
|
||||||
|
import { FrontendLocaleData } from "../../data/translation";
|
||||||
|
|
||||||
|
export const formatListWithAnds = (
|
||||||
|
locale: FrontendLocaleData,
|
||||||
|
list: string[]
|
||||||
|
) => formatConjunctionList(locale).format(list);
|
||||||
|
|
||||||
|
export const formatListWithOrs = (locale: FrontendLocaleData, list: string[]) =>
|
||||||
|
formatDisjunctionList(locale).format(list);
|
||||||
|
|
||||||
|
const formatConjunctionList = memoizeOne(
|
||||||
|
(locale: FrontendLocaleData) =>
|
||||||
|
new Intl.ListFormat(locale.language, {
|
||||||
|
style: "long",
|
||||||
|
type: "conjunction",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const formatDisjunctionList = memoizeOne(
|
||||||
|
(locale: FrontendLocaleData) =>
|
||||||
|
new Intl.ListFormat(locale.language, {
|
||||||
|
style: "long",
|
||||||
|
type: "disjunction",
|
||||||
|
})
|
||||||
|
);
|
@ -31,6 +31,10 @@ import {
|
|||||||
VariablesAction,
|
VariablesAction,
|
||||||
WaitForTriggerAction,
|
WaitForTriggerAction,
|
||||||
} from "./script";
|
} from "./script";
|
||||||
|
import { formatListWithAnds } from "../common/string/format-list";
|
||||||
|
|
||||||
|
const actionTranslationBaseKey =
|
||||||
|
"ui.panel.config.automation.editor.actions.type";
|
||||||
|
|
||||||
export const describeAction = <T extends ActionType>(
|
export const describeAction = <T extends ActionType>(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -75,25 +79,8 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
if (actionType === "service") {
|
if (actionType === "service") {
|
||||||
const config = action as ActionTypes["service"];
|
const config = action as ActionTypes["service"];
|
||||||
|
|
||||||
let base: string | undefined;
|
const targets: string[] = [];
|
||||||
|
|
||||||
if (
|
|
||||||
config.service_template ||
|
|
||||||
(config.service && isTemplate(config.service))
|
|
||||||
) {
|
|
||||||
base = "Call a service based on a template";
|
|
||||||
} else if (config.service) {
|
|
||||||
const [domain, serviceName] = config.service.split(".", 2);
|
|
||||||
const service = hass.services[domain][serviceName];
|
|
||||||
base = service
|
|
||||||
? `${domainToName(hass.localize, domain)}: ${service.name}`
|
|
||||||
: `Call service: ${config.service}`;
|
|
||||||
} else {
|
|
||||||
return "Call a service";
|
|
||||||
}
|
|
||||||
if (config.target) {
|
if (config.target) {
|
||||||
const targets: string[] = [];
|
|
||||||
|
|
||||||
for (const [key, label] of Object.entries({
|
for (const [key, label] of Object.entries({
|
||||||
area_id: "areas",
|
area_id: "areas",
|
||||||
device_id: "devices",
|
device_id: "devices",
|
||||||
@ -108,7 +95,12 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
|
|
||||||
for (const targetThing of keyConf) {
|
for (const targetThing of keyConf) {
|
||||||
if (isTemplate(targetThing)) {
|
if (isTemplate(targetThing)) {
|
||||||
targets.push(`templated ${label}`);
|
targets.push(
|
||||||
|
hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.service.description.target_template`,
|
||||||
|
{ name: label }
|
||||||
|
)
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
} else if (key === "entity_id") {
|
} else if (key === "entity_id") {
|
||||||
if (targetThing.includes(".")) {
|
if (targetThing.includes(".")) {
|
||||||
@ -125,7 +117,11 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
computeEntityRegistryName(hass, entityReg) || targetThing
|
computeEntityRegistryName(hass, entityReg) || targetThing
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
targets.push("unknown entity");
|
targets.push(
|
||||||
|
hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.service.description.target_unknown_entity`
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (key === "device_id") {
|
} else if (key === "device_id") {
|
||||||
@ -133,46 +129,105 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
if (device) {
|
if (device) {
|
||||||
targets.push(computeDeviceName(device, hass));
|
targets.push(computeDeviceName(device, hass));
|
||||||
} else {
|
} else {
|
||||||
targets.push("unknown device");
|
targets.push(
|
||||||
|
hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.service.description.target_unknown_device`
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (key === "area_id") {
|
} else if (key === "area_id") {
|
||||||
const area = hass.areas[targetThing];
|
const area = hass.areas[targetThing];
|
||||||
if (area?.name) {
|
if (area?.name) {
|
||||||
targets.push(area.name);
|
targets.push(area.name);
|
||||||
} else {
|
} else {
|
||||||
targets.push("unknown area");
|
targets.push(
|
||||||
|
hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.service.description.target_unknown_area`
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
targets.push(targetThing);
|
targets.push(targetThing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (targets.length > 0) {
|
|
||||||
base += ` ${targets.join(", ")}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return base;
|
if (
|
||||||
|
config.service_template ||
|
||||||
|
(config.service && isTemplate(config.service))
|
||||||
|
) {
|
||||||
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.service.description.service_based_on_template`,
|
||||||
|
{ targets: formatListWithAnds(hass.locale, targets) }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.service) {
|
||||||
|
const [domain, serviceName] = config.service.split(".", 2);
|
||||||
|
const service = hass.services[domain][serviceName];
|
||||||
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.service.description.service_based_on_name`,
|
||||||
|
{
|
||||||
|
name: service
|
||||||
|
? `${domainToName(hass.localize, domain)}: ${service.name}`
|
||||||
|
: config.service,
|
||||||
|
targets: formatListWithAnds(hass.locale, targets),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.service.description.service`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "delay") {
|
if (actionType === "delay") {
|
||||||
const config = action as DelayAction;
|
const config = action as DelayAction;
|
||||||
|
|
||||||
let duration: string;
|
let duration: string;
|
||||||
|
|
||||||
if (typeof config.delay === "number") {
|
if (typeof config.delay === "number") {
|
||||||
duration = `for ${secondsToDuration(config.delay)!}`;
|
duration = hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.delay.description.duration_string`,
|
||||||
|
{
|
||||||
|
duration: secondsToDuration(config.delay)!,
|
||||||
|
}
|
||||||
|
);
|
||||||
} else if (typeof config.delay === "string") {
|
} else if (typeof config.delay === "string") {
|
||||||
duration = isTemplate(config.delay)
|
duration = isTemplate(config.delay)
|
||||||
? "based on a template"
|
? hass.localize(
|
||||||
: `for ${config.delay || "a duration"}`;
|
`${actionTranslationBaseKey}.delay.description.duration_template`
|
||||||
|
)
|
||||||
|
: hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.delay.description.duration_string`,
|
||||||
|
{
|
||||||
|
duration:
|
||||||
|
config.delay ||
|
||||||
|
hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.delay.description.duration_unknown`
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
} else if (config.delay) {
|
} else if (config.delay) {
|
||||||
duration = `for ${formatDuration(config.delay)}`;
|
duration = hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.delay.description.duration_string`,
|
||||||
|
{
|
||||||
|
duration: formatDuration(config.delay),
|
||||||
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
duration = "for a duration";
|
duration = hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.delay.description.duration_string`,
|
||||||
|
{
|
||||||
|
duration: hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.delay.description.duration_unknown`
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `Delay ${duration}`;
|
return hass.localize(`${actionTranslationBaseKey}.delay.description.full`, {
|
||||||
|
duration: duration,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "activate_scene") {
|
if (actionType === "activate_scene") {
|
||||||
@ -184,77 +239,139 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
entityId = config.target?.entity_id || config.entity_id;
|
entityId = config.target?.entity_id || config.entity_id;
|
||||||
}
|
}
|
||||||
if (!entityId) {
|
if (!entityId) {
|
||||||
return "Activate a scene";
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.activate_scene.description.activate_scene`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const sceneStateObj = entityId ? hass.states[entityId] : undefined;
|
const sceneStateObj = entityId ? hass.states[entityId] : undefined;
|
||||||
return `Activate scene ${
|
return hass.localize(
|
||||||
sceneStateObj ? computeStateName(sceneStateObj) : entityId
|
`${actionTranslationBaseKey}.activate_scene.description.activate_scene_with_name`,
|
||||||
}`;
|
{ name: sceneStateObj ? computeStateName(sceneStateObj) : entityId }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "play_media") {
|
if (actionType === "play_media") {
|
||||||
const config = action as PlayMediaAction;
|
const config = action as PlayMediaAction;
|
||||||
const entityId = config.target?.entity_id || config.entity_id;
|
const entityId = config.target?.entity_id || config.entity_id;
|
||||||
const mediaStateObj = entityId ? hass.states[entityId] : undefined;
|
const mediaStateObj = entityId ? hass.states[entityId] : undefined;
|
||||||
return `Play ${
|
return hass.localize(
|
||||||
config.metadata.title || config.data.media_content_id || "media"
|
`${actionTranslationBaseKey}.play_media.description.full`,
|
||||||
} on ${
|
{
|
||||||
mediaStateObj
|
hasMedia: config.metadata.title || config.data.media_content_id,
|
||||||
? computeStateName(mediaStateObj)
|
media: config.metadata.title || config.data.media_content_id,
|
||||||
: entityId || "a media player"
|
hasMediaPlayer: mediaStateObj ? true : entityId !== undefined,
|
||||||
}`;
|
mediaPlayer: mediaStateObj ? computeStateName(mediaStateObj) : entityId,
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "wait_for_trigger") {
|
if (actionType === "wait_for_trigger") {
|
||||||
const config = action as WaitForTriggerAction;
|
const config = action as WaitForTriggerAction;
|
||||||
const triggers = ensureArray(config.wait_for_trigger);
|
const triggers = ensureArray(config.wait_for_trigger);
|
||||||
if (!triggers || triggers.length === 0) {
|
if (!triggers || triggers.length === 0) {
|
||||||
return "Wait for a trigger";
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.wait_for_trigger.description.wait_for_a_trigger`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return `Wait for ${triggers
|
const triggerNames = triggers.map((trigger) =>
|
||||||
.map((trigger) => describeTrigger(trigger, hass, entityRegistry))
|
describeTrigger(trigger, hass, entityRegistry)
|
||||||
.join(", ")}`;
|
);
|
||||||
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.wait_for_trigger.description.wait_for_triggers_with_name`,
|
||||||
|
{ triggers: formatListWithAnds(hass.locale, triggerNames) }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "variables") {
|
if (actionType === "variables") {
|
||||||
const config = action as VariablesAction;
|
const config = action as VariablesAction;
|
||||||
return `Define variables ${Object.keys(config.variables).join(", ")}`;
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.variables.description.full`,
|
||||||
|
{
|
||||||
|
names: formatListWithAnds(hass.locale, Object.keys(config.variables)),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "fire_event") {
|
if (actionType === "fire_event") {
|
||||||
const config = action as EventAction;
|
const config = action as EventAction;
|
||||||
if (isTemplate(config.event)) {
|
if (isTemplate(config.event)) {
|
||||||
return "Fire event based on a template";
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.event.description.full`,
|
||||||
|
{
|
||||||
|
name: hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.event.description.template`
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return `Fire event ${config.event}`;
|
return hass.localize(`${actionTranslationBaseKey}.event.description.full`, {
|
||||||
|
name: config.event,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "wait_template") {
|
if (actionType === "wait_template") {
|
||||||
return "Wait for a template to render true";
|
return hass.localize(
|
||||||
}
|
`${actionTranslationBaseKey}.wait_template.description.full`
|
||||||
|
);
|
||||||
if (actionType === "check_condition") {
|
|
||||||
return describeCondition(action as Condition, hass, entityRegistry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "stop") {
|
if (actionType === "stop") {
|
||||||
const config = action as StopAction;
|
const config = action as StopAction;
|
||||||
return `Stop${config.stop ? ` because: ${config.stop}` : ""}`;
|
return hass.localize(`${actionTranslationBaseKey}.stop.description.full`, {
|
||||||
|
hasReason: config.stop !== undefined,
|
||||||
|
reason: config.stop,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "if") {
|
if (actionType === "if") {
|
||||||
const config = action as IfAction;
|
const config = action as IfAction;
|
||||||
return `Perform an action if: ${
|
|
||||||
!config.if
|
let ifConditions: string[] = [];
|
||||||
? ""
|
if (Array.isArray(config.if)) {
|
||||||
: typeof config.if === "string"
|
const conditions = ensureArray(config.if);
|
||||||
? config.if
|
conditions.forEach((condition) => {
|
||||||
: ensureArray(config.if).length > 1
|
ifConditions.push(describeCondition(condition, hass, entityRegistry));
|
||||||
? `${ensureArray(config.if).length} conditions`
|
});
|
||||||
: ensureArray(config.if).length
|
} else {
|
||||||
? describeCondition(ensureArray(config.if)[0], hass, entityRegistry)
|
ifConditions = [config.if];
|
||||||
: ""
|
}
|
||||||
}${config.else ? " (or else!)" : ""}`;
|
|
||||||
|
let elseActions: string[] = [];
|
||||||
|
if (config.else) {
|
||||||
|
if (Array.isArray(config.else)) {
|
||||||
|
const actions = ensureArray(config.else);
|
||||||
|
actions.forEach((currentAction) => {
|
||||||
|
elseActions.push(
|
||||||
|
describeAction(hass, entityRegistry, currentAction, undefined)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
elseActions = [
|
||||||
|
describeAction(hass, entityRegistry, config.else, undefined),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let thenActions: string[] = [];
|
||||||
|
if (Array.isArray(config.then)) {
|
||||||
|
const actions = ensureArray(config.then);
|
||||||
|
actions.forEach((currentAction) => {
|
||||||
|
thenActions.push(
|
||||||
|
describeAction(hass, entityRegistry, currentAction, undefined)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
thenActions = [
|
||||||
|
describeAction(hass, entityRegistry, config.then, undefined),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return hass.localize(`${actionTranslationBaseKey}.if.description.full`, {
|
||||||
|
hasElse: config.else !== undefined,
|
||||||
|
action: formatListWithAnds(hass.locale, thenActions),
|
||||||
|
conditions: formatListWithAnds(hass.locale, ifConditions),
|
||||||
|
elseAction: formatListWithAnds(hass.locale, elseActions),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "choose") {
|
if (actionType === "choose") {
|
||||||
@ -262,42 +379,64 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
if (config.choose) {
|
if (config.choose) {
|
||||||
const numActions =
|
const numActions =
|
||||||
ensureArray(config.choose).length + (config.default ? 1 : 0);
|
ensureArray(config.choose).length + (config.default ? 1 : 0);
|
||||||
return `Choose between ${numActions} action${
|
return hass.localize(
|
||||||
numActions === 1 ? "" : "s"
|
`${actionTranslationBaseKey}.choose.description.full`,
|
||||||
}`;
|
{ number: numActions }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return "Choose an action";
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.choose.description.no_action`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "repeat") {
|
if (actionType === "repeat") {
|
||||||
const config = action as RepeatAction;
|
const config = action as RepeatAction;
|
||||||
|
|
||||||
let base = "Repeat an action";
|
let chosenAction = "";
|
||||||
if ("count" in config.repeat) {
|
if ("count" in config.repeat) {
|
||||||
const count = config.repeat.count;
|
const count = config.repeat.count;
|
||||||
base += ` ${count} time${Number(count) === 1 ? "" : "s"}`;
|
chosenAction = hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.repeat.description.count`,
|
||||||
|
{ count: count }
|
||||||
|
);
|
||||||
} else if ("while" in config.repeat) {
|
} else if ("while" in config.repeat) {
|
||||||
base += ` while ${ensureArray(config.repeat.while)
|
const conditions = ensureArray(config.repeat.while).map((condition) =>
|
||||||
.map((condition) => describeCondition(condition, hass, entityRegistry))
|
describeCondition(condition, hass, entityRegistry)
|
||||||
.join(", ")} is true`;
|
);
|
||||||
|
chosenAction = hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.repeat.description.while`,
|
||||||
|
{ conditions: formatListWithAnds(hass.locale, conditions) }
|
||||||
|
);
|
||||||
} else if ("until" in config.repeat) {
|
} else if ("until" in config.repeat) {
|
||||||
base += ` until ${ensureArray(config.repeat.until)
|
const conditions = ensureArray(config.repeat.until).map((condition) =>
|
||||||
.map((condition) => describeCondition(condition, hass, entityRegistry))
|
describeCondition(condition, hass, entityRegistry)
|
||||||
.join(", ")} is true`;
|
);
|
||||||
|
chosenAction = hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.repeat.description.until`,
|
||||||
|
{ conditions: formatListWithAnds(hass.locale, conditions) }
|
||||||
|
);
|
||||||
} else if ("for_each" in config.repeat) {
|
} else if ("for_each" in config.repeat) {
|
||||||
base += ` for every item: ${ensureArray(config.repeat.for_each)
|
const items = ensureArray(config.repeat.for_each).map((item) =>
|
||||||
.map((item) => JSON.stringify(item))
|
JSON.stringify(item)
|
||||||
.join(", ")}`;
|
);
|
||||||
|
chosenAction = hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.repeat.description.for_each`,
|
||||||
|
{ items: formatListWithAnds(hass.locale, items) }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return base;
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.repeat.description.full`,
|
||||||
|
{ chosenAction: chosenAction }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "check_condition") {
|
if (actionType === "check_condition") {
|
||||||
return `Test ${describeCondition(
|
return hass.localize(
|
||||||
action as Condition,
|
`${actionTranslationBaseKey}.check_condition.description.full`,
|
||||||
hass,
|
{
|
||||||
entityRegistry
|
condition: describeCondition(action as Condition, hass, entityRegistry),
|
||||||
)}`;
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "device_action") {
|
if (actionType === "device_action") {
|
||||||
@ -313,7 +452,7 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
if (localized) {
|
if (localized) {
|
||||||
return localized;
|
return localized;
|
||||||
}
|
}
|
||||||
const stateObj = hass.states[config.entity_id as string];
|
const stateObj = hass.states[config.entity_id];
|
||||||
return `${config.type || "Perform action with"} ${
|
return `${config.type || "Perform action with"} ${
|
||||||
stateObj ? computeStateName(stateObj) : config.entity_id
|
stateObj ? computeStateName(stateObj) : config.entity_id
|
||||||
}`;
|
}`;
|
||||||
@ -322,7 +461,10 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
if (actionType === "parallel") {
|
if (actionType === "parallel") {
|
||||||
const config = action as ParallelAction;
|
const config = action as ParallelAction;
|
||||||
const numActions = ensureArray(config.parallel).length;
|
const numActions = ensureArray(config.parallel).length;
|
||||||
return `Run ${numActions} action${numActions === 1 ? "" : "s"} in parallel`;
|
return hass.localize(
|
||||||
|
`${actionTranslationBaseKey}.parallel.description.full`,
|
||||||
|
{ number: numActions }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return actionType;
|
return actionType;
|
||||||
|
@ -2573,25 +2573,50 @@
|
|||||||
"label": "Call service",
|
"label": "Call service",
|
||||||
"response_variable": "Response variable",
|
"response_variable": "Response variable",
|
||||||
"has_optional_response": "This service can return a response, if you want to use the response, enter the name of a variable the response will be saved in",
|
"has_optional_response": "This service can return a response, if you want to use the response, enter the name of a variable the response will be saved in",
|
||||||
"has_response": "This service returns a response, enter the name of a variable the response will be saved in"
|
"has_response": "This service returns a response, enter the name of a variable the response will be saved in",
|
||||||
|
"description": {
|
||||||
|
"service_based_on_template": "Call a service based on a template on {targets}",
|
||||||
|
"service_based_on_name": "Call a service ''{name}'' on {targets}",
|
||||||
|
"service": "Call a service",
|
||||||
|
"target_template": "templated {name}",
|
||||||
|
"target_unknown_entity": "unknown entity",
|
||||||
|
"target_unknown_device": "unknown device",
|
||||||
|
"target_unknown_area": "unknown area"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"play_media": {
|
"play_media": {
|
||||||
"label": "Play media"
|
"label": "Play media",
|
||||||
|
"description": {
|
||||||
|
"full": "Play {hasMedia, select, \n true {{media}} \n other {media}\n } on {hasMediaPlayer, select, \n true {{mediaPlayer}} \n other {a media player}\n }"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"delay": {
|
"delay": {
|
||||||
"label": "Wait for time to pass (delay)",
|
"label": "Wait for time to pass (delay)",
|
||||||
"delay": "Duration"
|
"delay": "Duration",
|
||||||
|
"description": {
|
||||||
|
"full": "Delay {duration}",
|
||||||
|
"duration_string": "for {string}",
|
||||||
|
"duration_template": "based on a template",
|
||||||
|
"duration_unknown": "a duration"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"wait_template": {
|
"wait_template": {
|
||||||
"label": "Wait for a template",
|
"label": "Wait for a template",
|
||||||
"wait_template": "Wait Template",
|
"wait_template": "Wait Template",
|
||||||
"timeout": "Timeout (optional)",
|
"timeout": "Timeout (optional)",
|
||||||
"continue_timeout": "Continue on timeout"
|
"continue_timeout": "Continue on timeout",
|
||||||
|
"description": {
|
||||||
|
"full": "Wait for a template to evaluate to true"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"wait_for_trigger": {
|
"wait_for_trigger": {
|
||||||
"label": "Wait for a trigger",
|
"label": "Wait for a trigger",
|
||||||
"timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::timeout%]",
|
"timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::timeout%]",
|
||||||
"continue_timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::continue_timeout%]"
|
"continue_timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::continue_timeout%]",
|
||||||
|
"description": {
|
||||||
|
"wait_for_a_trigger": "Wait for a trigger",
|
||||||
|
"wait_for_triggers_with_name": "Wait for ''{triggers}''"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"condition": {
|
"condition": {
|
||||||
"label": "Condition"
|
"label": "Condition"
|
||||||
@ -2599,7 +2624,11 @@
|
|||||||
"event": {
|
"event": {
|
||||||
"label": "Event",
|
"label": "Event",
|
||||||
"event": "[%key:ui::panel::config::automation::editor::triggers::type::event::label%]",
|
"event": "[%key:ui::panel::config::automation::editor::triggers::type::event::label%]",
|
||||||
"event_data": "[%key:ui::panel::config::automation::editor::triggers::type::event::event_data%]"
|
"event_data": "[%key:ui::panel::config::automation::editor::triggers::type::event::event_data%]",
|
||||||
|
"description": {
|
||||||
|
"full": "Fire event {name}",
|
||||||
|
"template": "based on a template"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"device_id": {
|
"device_id": {
|
||||||
"label": "Device",
|
"label": "Device",
|
||||||
@ -2618,7 +2647,11 @@
|
|||||||
},
|
},
|
||||||
"activate_scene": {
|
"activate_scene": {
|
||||||
"label": "Scene",
|
"label": "Scene",
|
||||||
"scene": "Scene"
|
"scene": "Scene",
|
||||||
|
"description": {
|
||||||
|
"activate_scene": "Activate a scene",
|
||||||
|
"activate_scene_with_name": "Activate scene {name}"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"repeat": {
|
"repeat": {
|
||||||
"label": "Repeat",
|
"label": "Repeat",
|
||||||
@ -2636,7 +2669,14 @@
|
|||||||
"conditions": "Until conditions"
|
"conditions": "Until conditions"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sequence": "Actions"
|
"sequence": "Actions",
|
||||||
|
"description": {
|
||||||
|
"full": "Repeat an action {chosenAction}",
|
||||||
|
"count": "{count} {count, plural,\n one {time}\n other {times}\n}",
|
||||||
|
"while": "while ''{conditions}'' is true",
|
||||||
|
"until": "until ''{conditions}'' is true",
|
||||||
|
"for_each": "for every item: {items}"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"choose": {
|
"choose": {
|
||||||
"label": "Choose",
|
"label": "Choose",
|
||||||
@ -2646,26 +2686,47 @@
|
|||||||
"add_option": "Add option",
|
"add_option": "Add option",
|
||||||
"remove_option": "Remove option",
|
"remove_option": "Remove option",
|
||||||
"conditions": "Conditions",
|
"conditions": "Conditions",
|
||||||
"sequence": "Actions"
|
"sequence": "Actions",
|
||||||
|
"description": {
|
||||||
|
"full": "Choose between {number} {number, plural,\n one {action}\n other{actions}\n}",
|
||||||
|
"no_action": "Choose an action"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"if": {
|
"if": {
|
||||||
"label": "If-then",
|
"label": "If-then",
|
||||||
"if": "If",
|
"if": "If",
|
||||||
"then": "Then",
|
"then": "Then",
|
||||||
"else": "Else",
|
"else": "Else",
|
||||||
"add_else": "Add else"
|
"add_else": "Add else",
|
||||||
|
"description": {
|
||||||
|
"full": "Perform ''{action}'' if ''{conditions}''{hasElse, select, \n true { otherwise ''{elseAction}''} \n other {}\n } "
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"stop": {
|
"stop": {
|
||||||
"label": "Stop",
|
"label": "Stop",
|
||||||
"stop": "Reason for stopping",
|
"stop": "Reason for stopping",
|
||||||
"response_variable": "The name of the variable to use as response",
|
"response_variable": "The name of the variable to use as response",
|
||||||
"error": "Stop because of an unexpected error"
|
"error": "Stop because of an unexpected error",
|
||||||
|
"description": {
|
||||||
|
"full": "Stop {hasReason, select, \n true { because: {reason}} \n other {}\n }"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"parallel": {
|
"parallel": {
|
||||||
"label": "Run in parallel"
|
"label": "Run in parallel",
|
||||||
|
"description": {
|
||||||
|
"full": "Run {number} {number, plural,\n one {action}\n other {actions}\n} in parallel"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"variables": {
|
"variables": {
|
||||||
"label": "Define variables"
|
"label": "Define variables",
|
||||||
|
"description": {
|
||||||
|
"full": "Define variables {names}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"check_condition": {
|
||||||
|
"description": {
|
||||||
|
"full": "Test {condition}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2782,7 +2843,6 @@
|
|||||||
},
|
},
|
||||||
"discover_blueprint_tip": "[%key:ui::panel::config::automation::dialog_new::discover_blueprint_tip%]"
|
"discover_blueprint_tip": "[%key:ui::panel::config::automation::dialog_new::discover_blueprint_tip%]"
|
||||||
},
|
},
|
||||||
|
|
||||||
"editor": {
|
"editor": {
|
||||||
"alias": "Name",
|
"alias": "Name",
|
||||||
"icon": "Icon",
|
"icon": "Icon",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user