Lokalize automation trace area (#19836)

* Translate automation trace timeline area

* Fix undefined changed_variables

* change naming options in triggered_by

* Split messages for stopped_by

* remove stopped message
This commit is contained in:
Simon Lamon 2024-02-29 13:51:18 +01:00 committed by GitHub
parent a087b4c43e
commit bc445a1e27
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 150 additions and 47 deletions

View File

@ -17,6 +17,7 @@ export const basicTrace: DemoTrace = {
{ {
path: "trigger/0", path: "trigger/0",
timestamp: "2021-03-25T04:36:51.223693+00:00", timestamp: "2021-03-25T04:36:51.223693+00:00",
changed_variables: {},
}, },
], ],
"condition/0": [ "condition/0": [

View File

@ -17,6 +17,7 @@ export const motionLightTrace: DemoTrace = {
{ {
path: "trigger/0", path: "trigger/0",
timestamp: "2021-03-25T04:36:51.223693+00:00", timestamp: "2021-03-25T04:36:51.223693+00:00",
changed_variables: {},
}, },
], ],
"action/0": [ "action/0": [

View File

@ -55,6 +55,7 @@ export class DemoAutomationTraceTimeline extends LitElement {
super.firstUpdated(changedProps); super.firstUpdated(changedProps);
const hass = provideHass(this); const hass = provideHass(this);
hass.updateTranslations(null, "en"); hass.updateTranslations(null, "en");
hass.updateTranslations("config", "en");
} }
static get styles() { static get styles() {

View File

@ -60,6 +60,7 @@ export class DemoAutomationTrace extends LitElement {
super.firstUpdated(changedProps); super.firstUpdated(changedProps);
const hass = provideHass(this); const hass = provideHass(this);
hass.updateTranslations(null, "en"); hass.updateTranslations(null, "en");
hass.updateTranslations("config", "en");
} }
static get styles() { static get styles() {

View File

@ -153,7 +153,7 @@ class LogbookRenderer {
const parts: TemplateResult[] = []; const parts: TemplateResult[] = [];
let i; let i: number;
for ( for (
i = 0; i = 0;
@ -232,7 +232,7 @@ class ActionRenderer {
const value = this._getItem(index); const value = this._getItem(index);
if (renderAllIterations) { if (renderAllIterations) {
let i; let i: number = 0;
value.forEach((item) => { value.forEach((item) => {
i = this._renderIteration(index, item, actionType); i = this._renderIteration(index, item, actionType);
}); });
@ -270,7 +270,12 @@ class ActionRenderer {
} catch (err: any) { } catch (err: any) {
this._renderEntry( this._renderEntry(
path, path,
`Unable to extract path ${path}. Download trace and report as bug` this.hass.localize(
"ui.panel.config.automation.trace.messages.path_error",
{
path: path,
}
)
); );
return index + 1; return index + 1;
} }
@ -324,20 +329,22 @@ class ActionRenderer {
private _handleTrigger(index: number, triggerStep: TriggerTraceStep): number { private _handleTrigger(index: number, triggerStep: TriggerTraceStep): number {
this._renderEntry( this._renderEntry(
triggerStep.path, triggerStep.path,
`${ this.hass.localize(
triggerStep.changed_variables.trigger.alias "ui.panel.config.automation.trace.messages.triggered_by",
? `${triggerStep.changed_variables.trigger.alias} triggered` {
: "Triggered" triggeredBy: triggerStep.changed_variables.trigger?.alias
} ${ ? "alias"
triggerStep.path === "trigger" : "other",
? "manually" alias: triggerStep.changed_variables.trigger?.alias,
: `by the ${this.trace.trigger}` triggeredPath: triggerStep.path === "trigger" ? "manual" : "trigger",
} at trigger: this.trace.trigger,
${formatDateTimeWithSeconds( time: formatDateTimeWithSeconds(
new Date(triggerStep.timestamp), new Date(triggerStep.timestamp),
this.hass.locale, this.hass.locale,
this.hass.config this.hass.config
)}`, ),
}
),
mdiCircle mdiCircle
); );
return index + 1; return index + 1;
@ -367,12 +374,17 @@ class ActionRenderer {
this.keys[index] this.keys[index]
) as ChooseAction; ) as ChooseAction;
const disabled = chooseConfig.enabled === false; const disabled = chooseConfig.enabled === false;
const name = chooseConfig.alias || "Choose"; const name =
chooseConfig.alias ||
this.hass.localize("ui.panel.config.automation.trace.messages.choose");
if (defaultExecuted) { if (defaultExecuted) {
this._renderEntry( this._renderEntry(
choosePath, choosePath,
`${name}: Default action executed`, this.hass.localize(
"ui.panel.config.automation.trace.messages.default_action_executed",
{ name: name }
),
undefined, undefined,
disabled disabled
); );
@ -385,8 +397,17 @@ class ActionRenderer {
`${this.keys[index]}/choose/${chooseTrace.result.choice}` `${this.keys[index]}/choose/${chooseTrace.result.choice}`
) as ChooseActionChoice | undefined; ) as ChooseActionChoice | undefined;
const choiceName = choiceConfig const choiceName = choiceConfig
? `${choiceConfig.alias || `Option ${choiceNumeric}`} executed` ? `${
: `Error: ${chooseTrace.error}`; choiceConfig.alias ||
this.hass.localize(
"ui.panel.config.automation.trace.messages.option_executed",
{ option: choiceNumeric }
)
}`
: this.hass.localize(
"ui.panel.config.automation.trace.messages.error",
{ error: chooseTrace.error }
);
this._renderEntry( this._renderEntry(
choosePath, choosePath,
`${name}: ${choiceName}`, `${name}: ${choiceName}`,
@ -396,13 +417,16 @@ class ActionRenderer {
} else { } else {
this._renderEntry( this._renderEntry(
choosePath, choosePath,
`${name}: No action taken`, this.hass.localize(
"ui.panel.config.automation.trace.messages.no_action_executed",
{ name: name }
),
undefined, undefined,
disabled disabled
); );
} }
let i; let i: number;
// Skip over conditions // Skip over conditions
for (i = index + 1; i < this.keys.length; i++) { for (i = index + 1; i < this.keys.length; i++) {
@ -479,26 +503,38 @@ class ActionRenderer {
const ifTrace = this._getItem(index)[0] as IfActionTraceStep; const ifTrace = this._getItem(index)[0] as IfActionTraceStep;
const ifConfig = this._getDataFromPath(this.keys[index]) as IfAction; const ifConfig = this._getDataFromPath(this.keys[index]) as IfAction;
const disabled = ifConfig.enabled === false; const disabled = ifConfig.enabled === false;
const name = ifConfig.alias || "If"; const name =
ifConfig.alias ||
this.hass.localize("ui.panel.config.automation.trace.messages.if");
if (ifTrace.result?.choice) { if (ifTrace.result?.choice) {
const choiceConfig = this._getDataFromPath( const choiceConfig = this._getDataFromPath(
`${this.keys[index]}/${ifTrace.result.choice}/` `${this.keys[index]}/${ifTrace.result.choice}/`
) as any; ) as any;
const choiceName = choiceConfig const choiceName = choiceConfig
? `${choiceConfig.alias || `${ifTrace.result.choice} action executed`}` ? choiceConfig.alias ||
: `Error: ${ifTrace.error}`; this.hass.localize(
"ui.panel.config.automation.trace.messages.action_executed",
{ action: ifTrace.result.choice }
)
: this.hass.localize(
"ui.panel.config.automation.trace.messages.error",
{ error: ifTrace.error }
);
this._renderEntry(ifPath, `${name}: ${choiceName}`, undefined, disabled); this._renderEntry(ifPath, `${name}: ${choiceName}`, undefined, disabled);
} else { } else {
this._renderEntry( this._renderEntry(
ifPath, ifPath,
`${name}: No action taken`, this.hass.localize(
"ui.panel.config.automation.trace.messages.no_action_executed",
{ name: name }
),
undefined, undefined,
disabled disabled
); );
} }
let i; let i: number;
// Skip over conditions // Skip over conditions
for (i = index + 1; i < this.keys.length; i++) { for (i = index + 1; i < this.keys.length; i++) {
@ -534,7 +570,11 @@ class ActionRenderer {
const disabled = parallelConfig.enabled === false; const disabled = parallelConfig.enabled === false;
const name = parallelConfig.alias || "Execute in parallel"; const name =
parallelConfig.alias ||
this.hass.localize(
"ui.panel.config.automation.trace.messages.execute_in_parallel"
);
this._renderEntry(parallelPath, name, undefined, disabled); this._renderEntry(parallelPath, name, undefined, disabled);
@ -564,7 +604,11 @@ class ActionRenderer {
this.entries.push(html` this.entries.push(html`
<ha-timeline .icon=${icon} data-path=${path} .notEnabled=${disabled}> <ha-timeline .icon=${icon} data-path=${path} .notEnabled=${disabled}>
${description}${disabled ${description}${disabled
? html`<span class="disabled"> (disabled)</span>` ? html`<span class="disabled">
${this.hass.localize(
"ui.panel.config.automation.trace.messages.disabled"
)}</span
>`
: ""} : ""}
</ha-timeline> </ha-timeline>
`); `);
@ -636,13 +680,12 @@ export class HaAutomationTracer extends LitElement {
this.hass.locale, this.hass.locale,
this.hass.config this.hass.config
); );
const renderRuntime = () => `(runtime: const renderRuntime = () =>
${( (
(new Date(this.trace!.timestamp.finish!).getTime() - (new Date(this.trace!.timestamp.finish!).getTime() -
new Date(this.trace!.timestamp.start).getTime()) / new Date(this.trace!.timestamp.start).getTime()) /
1000 1000
).toFixed(2)} ).toFixed(2);
seconds)`;
let entry: { let entry: {
description: TemplateResult | string; description: TemplateResult | string;
@ -652,57 +695,90 @@ export class HaAutomationTracer extends LitElement {
if (this.trace.state === "running") { if (this.trace.state === "running") {
entry = { entry = {
description: "Still running", description: this.hass.localize(
"ui.panel.config.automation.trace.messages.still_running"
),
icon: mdiProgressClock, icon: mdiProgressClock,
}; };
} else if (this.trace.state === "debugged") { } else if (this.trace.state === "debugged") {
entry = { entry = {
description: "Debugged", description: this.hass.localize(
"ui.panel.config.automation.trace.messages.debugged"
),
icon: mdiProgressWrench, icon: mdiProgressWrench,
}; };
} else if (this.trace.script_execution === "finished") { } else if (this.trace.script_execution === "finished") {
entry = { entry = {
description: `Finished at ${renderFinishedAt()} ${renderRuntime()}`, description: this.hass.localize(
"ui.panel.config.automation.trace.messages.finished",
{
time: renderFinishedAt(),
executiontime: renderRuntime(),
}
),
icon: mdiCircle, icon: mdiCircle,
}; };
} else if (this.trace.script_execution === "aborted") { } else if (this.trace.script_execution === "aborted") {
entry = { entry = {
description: `Aborted at ${renderFinishedAt()} ${renderRuntime()}`, description: this.hass.localize(
"ui.panel.config.automation.trace.messages.aborted",
{
time: renderFinishedAt(),
executiontime: renderRuntime(),
}
),
icon: mdiAlertCircle, icon: mdiAlertCircle,
}; };
} else if (this.trace.script_execution === "cancelled") { } else if (this.trace.script_execution === "cancelled") {
entry = { entry = {
description: `Cancelled at ${renderFinishedAt()} ${renderRuntime()}`, description: this.hass.localize(
"ui.panel.config.automation.trace.messages.cancelled",
{
time: renderFinishedAt(),
executiontime: renderRuntime(),
}
),
icon: mdiAlertCircle, icon: mdiAlertCircle,
}; };
} else { } else {
let reason: string; let message:
| "stopped_failed_conditions"
| "stopped_failed_single"
| "stopped_failed_max_runs"
| "stopped_error"
| "stopped_unknown_reason";
let isError = false; let isError = false;
let extra: TemplateResult | undefined; let extra: TemplateResult | undefined;
switch (this.trace.script_execution) { switch (this.trace.script_execution) {
case "failed_conditions": case "failed_conditions":
reason = "a condition failed"; message = "stopped_failed_conditions";
break; break;
case "failed_single": case "failed_single":
reason = "only a single execution is allowed"; message = "stopped_failed_single";
break; break;
case "failed_max_runs": case "failed_max_runs":
reason = "maximum number of parallel runs reached"; message = "stopped_failed_max_runs";
break; break;
case "error": case "error":
reason = "an error was encountered";
isError = true; isError = true;
message = "stopped_error";
extra = html`<br /><br />${this.trace.error!}`; extra = html`<br /><br />${this.trace.error!}`;
break; break;
default: default:
reason = `of unknown reason "${this.trace.script_execution}"`;
isError = true; isError = true;
message = "stopped_unknown_reason";
} }
entry = { entry = {
description: html`Stopped because ${reason} at ${renderFinishedAt()} description: html`${this.hass.localize(
${renderRuntime()}${extra || ""}`, `ui.panel.config.automation.trace.messages.${message}`,
{
time: renderFinishedAt(),
executiontime: renderRuntime(),
}
)}
${extra || ""}`,
icon: mdiAlertCircle, icon: mdiAlertCircle,
className: isError ? "error" : undefined, className: isError ? "error" : undefined,
}; };

View File

@ -3195,6 +3195,29 @@
"no_logbook_entries": "No Logbook entries found for this step.", "no_logbook_entries": "No Logbook entries found for this step.",
"no_variables_changed": "No variables changed", "no_variables_changed": "No variables changed",
"unable_to_find_config": "Unable to find config" "unable_to_find_config": "Unable to find config"
},
"messages": {
"no_action_executed": "{name}: No action executed",
"default_action_executed": "{name}: Default action executed",
"action_executed": "{action} action executed",
"option_executed": "Option {option} executed",
"error": "Error: {error}",
"execute_in_parallel": "Execute in parallel",
"if": "If",
"choose": "Choose",
"still_running": "Still running",
"debugged": "Debugged",
"finished": "Finished at {time} (runtime: {executiontime} seconds)",
"aborted": "Aborted at {time} (runtime: {executiontime} seconds)",
"cancelled": "Cancelled at {time} (runtime: {executiontime} seconds)",
"stopped_failed_conditions": "Stopped because a condition failed at {time} (runtime: {executiontime} seconds)",
"stopped_failed_single": "Stopped because only a single execution is allowed at {time} (runtime: {executiontime} seconds)",
"stopped_failed_max_runs": "Stopped because maximum number of parallel runs reached at {time} (runtime: {executiontime} seconds)",
"stopped_error": "Stopped because an error was encountered at {time} (runtime: {executiontime} seconds)",
"stopped_unknown_reason": "Stopped because of unknown reason {reason} at {time} (runtime: {executiontime} seconds)",
"disabled": "(disabled)",
"triggered_by": "{triggeredBy, select, \n alias {{alias} triggered}\n other {Triggered} \n} {triggeredPath, select, \n trigger {by the {trigger}}\n other {manually} \n} at {time}",
"path_error": "Unable to extract path {path}. Download trace and report as bug."
} }
} }
}, },