mirror of
https://github.com/home-assistant/frontend.git
synced 2026-11-11 07:24:44 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aec4b70eab |
No files matched your search
@@ -0,0 +1,33 @@
|
||||
import type { LocalizeFunc } from "./localize";
|
||||
|
||||
const YAML_ERROR_REASON_KEYS = new Map(
|
||||
Object.entries({
|
||||
"duplicated mapping key": "duplicated_mapping_key",
|
||||
"bad indentation of a mapping entry": "bad_mapping_indentation",
|
||||
"bad indentation of a sequence entry": "bad_sequence_indentation",
|
||||
"deficient indentation": "deficient_indentation",
|
||||
"tab characters must not be used in indentation": "tab_indentation",
|
||||
"can not read a block mapping entry; a multiline key may not be an implicit key":
|
||||
"multiline_implicit_key",
|
||||
"a whitespace character is expected after the key-value separator within a block mapping":
|
||||
"missing_key_value_space",
|
||||
"expected ':' after a mapping key": "missing_colon",
|
||||
"missed comma between flow collection entries": "missing_comma",
|
||||
"unexpected end of the stream within a flow collection":
|
||||
"unterminated_flow_collection",
|
||||
"unexpected end of the stream within a single quoted scalar":
|
||||
"unterminated_single_quote",
|
||||
"unexpected end of the stream within a double quoted scalar":
|
||||
"unterminated_double_quote",
|
||||
"end of the stream or a document separator is expected":
|
||||
"unexpected_content",
|
||||
} as const)
|
||||
);
|
||||
|
||||
export const localizeYamlErrorReason = (
|
||||
localize: LocalizeFunc,
|
||||
reason: string | undefined
|
||||
): string | undefined => {
|
||||
const key = reason ? YAML_ERROR_REASON_KEYS.get(reason) : undefined;
|
||||
return key ? localize(`ui.components.yaml-editor.reasons.${key}`) : reason;
|
||||
};
|
||||
@@ -6,6 +6,7 @@ import { customElement, property, query, state } from "lit/decorators";
|
||||
import type { ContextType } from "@lit/context";
|
||||
import { consume } from "../common/decorators/consume";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { localizeYamlErrorReason } from "../common/translations/localize-yaml-error";
|
||||
import { copyToClipboard } from "../common/util/copy-clipboard";
|
||||
import { haStyle } from "../resources/styles";
|
||||
import { showToast } from "../util/toast";
|
||||
@@ -180,7 +181,7 @@ export class HaYamlEditor extends LitElement {
|
||||
let errorMsg: string | undefined;
|
||||
let yamlError: {
|
||||
mark?: { position: number; line: number; column: number };
|
||||
message?: string;
|
||||
reason?: string;
|
||||
} | null = null;
|
||||
|
||||
if (this._yaml) {
|
||||
@@ -189,8 +190,12 @@ export class HaYamlEditor extends LitElement {
|
||||
} catch (err: any) {
|
||||
// Invalid YAML
|
||||
isValid = false;
|
||||
yamlError = err;
|
||||
errorMsg = `${this._i18n!.localize("ui.components.yaml-editor.error", { reason: err.reason })}${err.mark ? ` (${this._i18n!.localize("ui.components.yaml-editor.error_location", { line: err.mark.line + 1, column: err.mark.column + 1 })})` : ""}`;
|
||||
const reason = localizeYamlErrorReason(
|
||||
this._i18n!.localize,
|
||||
err.reason
|
||||
);
|
||||
yamlError = { mark: err.mark, reason };
|
||||
errorMsg = `${this._i18n!.localize("ui.components.yaml-editor.error", { reason })}${err.mark ? ` (${this._i18n!.localize("ui.components.yaml-editor.error_location", { line: err.mark.line + 1, column: err.mark.column + 1 })})` : ""}`;
|
||||
}
|
||||
} else {
|
||||
parsed = {};
|
||||
|
||||
@@ -27,7 +27,6 @@ import "../../../components/entity/ha-entity-picker";
|
||||
import "../../../components/ha-alert";
|
||||
import "../../../components/ha-area-picker";
|
||||
import "../../../components/ha-color-picker";
|
||||
import "../../../components/ha-domain-icon";
|
||||
import "../../../components/ha-dropdown-item";
|
||||
import "../../../components/ha-icon";
|
||||
import "../../../components/ha-icon-button";
|
||||
@@ -151,13 +150,6 @@ const SWITCH_AS_DOMAINS_INVERT = ["cover", "lock", "valve"];
|
||||
|
||||
const PRECISIONS = [0, 1, 2, 3, 4, 5, 6];
|
||||
|
||||
const DEFAULT_DEVICE_CLASS = "default";
|
||||
|
||||
const DEVICE_CLASS_ICON_STATES: Record<string, string> = {
|
||||
cover: "open",
|
||||
binary_sensor: "on",
|
||||
};
|
||||
|
||||
const SCANNER_SOURCE_TYPES = ["router", "bluetooth", "bluetooth_le"];
|
||||
|
||||
const ZONE_DOMAINS = ["zone"];
|
||||
@@ -168,7 +160,7 @@ export interface EntitySettingsState {
|
||||
entityId: string;
|
||||
areaId: string | null;
|
||||
labels: string[];
|
||||
deviceClass: string | null;
|
||||
deviceClass: string | undefined;
|
||||
disabledBy: EntityRegistryEntry["disabled_by"];
|
||||
hiddenBy: EntityRegistryEntry["hidden_by"];
|
||||
unitOfMeasurement: string | null | undefined;
|
||||
@@ -184,68 +176,6 @@ export interface EntitySettingsState {
|
||||
switchAsInvert: boolean;
|
||||
}
|
||||
|
||||
interface DeviceClassOption {
|
||||
value: string;
|
||||
deviceClass?: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface DeviceClassOptions {
|
||||
defaultOption: DeviceClassOption;
|
||||
related: DeviceClassOption[];
|
||||
others: DeviceClassOption[];
|
||||
}
|
||||
|
||||
const computeDeviceClassOptions = (
|
||||
domain: string,
|
||||
originalDeviceClass: string | undefined,
|
||||
localize: LocalizeFunc,
|
||||
language: string
|
||||
): DeviceClassOptions => {
|
||||
const deviceClassLabel = (deviceClass: string) =>
|
||||
localize(
|
||||
`ui.dialogs.entity_registry.editor.device_classes.${domain}.${deviceClass}`
|
||||
);
|
||||
|
||||
const toSortedOptions = (deviceClasses: string[]): DeviceClassOption[] =>
|
||||
deviceClasses
|
||||
.map((deviceClass) => ({
|
||||
value: deviceClass,
|
||||
deviceClass,
|
||||
label: deviceClassLabel(deviceClass),
|
||||
}))
|
||||
.sort((a, b) => stringCompare(a.label, b.label, language));
|
||||
|
||||
const related: string[] = [];
|
||||
const others: string[] = [];
|
||||
const groups: string[][] = OVERRIDE_DEVICE_CLASSES[domain];
|
||||
for (const group of groups) {
|
||||
if (originalDeviceClass && group.includes(originalDeviceClass)) {
|
||||
related.push(
|
||||
...group.filter((deviceClass) => deviceClass !== originalDeviceClass)
|
||||
);
|
||||
} else {
|
||||
others.push(...group);
|
||||
}
|
||||
}
|
||||
|
||||
const defaultType = originalDeviceClass
|
||||
? deviceClassLabel(originalDeviceClass)
|
||||
: domainToName(localize, domain);
|
||||
|
||||
return {
|
||||
defaultOption: {
|
||||
value: DEFAULT_DEVICE_CLASS,
|
||||
deviceClass: originalDeviceClass,
|
||||
label: localize("ui.dialogs.entity_registry.editor.type_default", {
|
||||
type: defaultType,
|
||||
}),
|
||||
},
|
||||
related: toSortedOptions(related),
|
||||
others: toSortedOptions(others),
|
||||
};
|
||||
};
|
||||
|
||||
@customElement("entity-registry-settings-editor")
|
||||
export class EntityRegistrySettingsEditor extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@@ -275,7 +205,7 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
|
||||
@state() private _entityId!: EntitySettingsState["entityId"];
|
||||
|
||||
@state() private _deviceClass: EntitySettingsState["deviceClass"] = null;
|
||||
@state() private _deviceClass?: EntitySettingsState["deviceClass"];
|
||||
|
||||
@state() private _switchAsDomain: EntitySettingsState["switchAsDomain"] =
|
||||
"switch";
|
||||
@@ -330,6 +260,8 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
|
||||
private _origEntityId!: string;
|
||||
|
||||
private _deviceClassOptions?: string[][];
|
||||
|
||||
protected willUpdate(changedProperties: PropertyValues<this>) {
|
||||
super.willUpdate(changedProperties);
|
||||
this._device = this.entry.device_id
|
||||
@@ -346,9 +278,7 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
this._isMainEntity = !!this._device && !this._entryName;
|
||||
this._icon = this.entry.icon || "";
|
||||
this._deviceClass =
|
||||
this.entry.device_class === this._originalDeviceClass
|
||||
? null
|
||||
: (this.entry.device_class ?? null);
|
||||
this.entry.device_class || this.entry.original_device_class;
|
||||
this._origEntityId = this.entry.entity_id;
|
||||
this._areaId = this.entry.area_id;
|
||||
this._mainEntityWithOwnArea = this._isMainEntity && !!this.entry.area_id;
|
||||
@@ -404,19 +334,32 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
this._visibility_unit = stateObj?.attributes?.visibility_unit;
|
||||
this._wind_speed_unit = stateObj?.attributes?.wind_speed_unit;
|
||||
}
|
||||
|
||||
const deviceClasses: string[][] = OVERRIDE_DEVICE_CLASSES[domain];
|
||||
|
||||
if (!deviceClasses || this._hideDeviceClassOverride(domain)) {
|
||||
this._deviceClassOptions = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
this._deviceClassOptions = [[], []];
|
||||
for (const deviceClass of deviceClasses) {
|
||||
if (deviceClass.includes(this.entry.original_device_class!)) {
|
||||
this._deviceClassOptions[0] = deviceClass;
|
||||
} else {
|
||||
this._deviceClassOptions[1].push(...deviceClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _showDeviceClassSelect(domain: string): boolean {
|
||||
if (!(domain in OVERRIDE_DEVICE_CLASSES)) {
|
||||
return false;
|
||||
}
|
||||
private _hideDeviceClassOverride(domain: string): boolean {
|
||||
// Template binary sensor device_class should be edited via template options,
|
||||
// not the entity registry override UI used by other binary sensors.
|
||||
const isTemplateBinarySensor =
|
||||
return (
|
||||
domain === "binary_sensor" &&
|
||||
this.entry.platform === "template" &&
|
||||
!!this.entry.config_entry_id;
|
||||
return !isTemplateBinarySensor;
|
||||
!!this.entry.config_entry_id
|
||||
);
|
||||
}
|
||||
|
||||
private _precisionLabel(precision?: number, stateValue?: string) {
|
||||
@@ -481,19 +424,19 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
if (changedProps.has("_deviceClass")) {
|
||||
const domain = computeDomain(this.entry.entity_id);
|
||||
|
||||
if (domain === "number" && this._effectiveDeviceClass) {
|
||||
if (domain === "number" && this._deviceClass) {
|
||||
const { units } = await getNumberDeviceClassConvertibleUnits(
|
||||
this.hass,
|
||||
this._effectiveDeviceClass
|
||||
this._deviceClass
|
||||
);
|
||||
this._numberDeviceClassConvertibleUnits = units;
|
||||
} else {
|
||||
this._numberDeviceClassConvertibleUnits = [];
|
||||
}
|
||||
if (domain === "sensor" && this._effectiveDeviceClass) {
|
||||
if (domain === "sensor" && this._deviceClass) {
|
||||
const { units } = await getSensorDeviceClassConvertibleUnits(
|
||||
this.hass,
|
||||
this._effectiveDeviceClass
|
||||
this._deviceClass
|
||||
);
|
||||
this._sensorDeviceClassConvertibleUnits = units;
|
||||
} else {
|
||||
@@ -534,10 +477,6 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
const defaultPrecision =
|
||||
this.entry.options?.sensor?.suggested_display_precision ?? undefined;
|
||||
const defaultName = this._originalName;
|
||||
const previewStateObj = this._previewStateObj(
|
||||
stateObj,
|
||||
this._effectiveDeviceClass
|
||||
);
|
||||
|
||||
return html`
|
||||
${
|
||||
@@ -626,13 +565,13 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
.placeholder=${
|
||||
this.entry.original_icon ||
|
||||
stateObj?.attributes.icon ||
|
||||
(previewStateObj &&
|
||||
(stateObj &&
|
||||
until(
|
||||
entityIcon(
|
||||
this.hass.entities,
|
||||
this.hass.config,
|
||||
this.hass.connection,
|
||||
previewStateObj
|
||||
stateObj
|
||||
)
|
||||
)) ||
|
||||
until(entryIcon(this.hass, this.entry))
|
||||
@@ -640,11 +579,11 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
.disabled=${this.disabled}
|
||||
>
|
||||
${
|
||||
!this._icon && !stateObj?.attributes.icon && previewStateObj
|
||||
!this._icon && !stateObj?.attributes.icon && stateObj
|
||||
? html`
|
||||
<ha-state-icon
|
||||
slot="start"
|
||||
.stateObj=${previewStateObj}
|
||||
.stateObj=${stateObj}
|
||||
></ha-state-icon>
|
||||
`
|
||||
: nothing
|
||||
@@ -661,15 +600,14 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
@selected=${this._switchAsDomainChanged}
|
||||
value=${this._switchAsLabel(
|
||||
this._switchAsDomain,
|
||||
this._effectiveDeviceClass
|
||||
this._deviceClass
|
||||
)}
|
||||
>
|
||||
<ha-dropdown-item
|
||||
value="switch"
|
||||
.selected=${
|
||||
this._switchAsDomain === "switch" &&
|
||||
(!this._effectiveDeviceClass ||
|
||||
this._effectiveDeviceClass === "switch")
|
||||
(!this._deviceClass || this._deviceClass === "switch")
|
||||
}
|
||||
>
|
||||
${domainToName(this.hass.localize, "switch")}
|
||||
@@ -678,7 +616,7 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
value="outlet"
|
||||
.selected=${
|
||||
this._switchAsDomain === "switch" &&
|
||||
this._effectiveDeviceClass === "outlet"
|
||||
this._deviceClass === "outlet"
|
||||
}
|
||||
>
|
||||
${this.hass.localize(
|
||||
@@ -762,10 +700,64 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
} `
|
||||
: nothing
|
||||
}
|
||||
${this._renderDeviceClassSelect(domain)}
|
||||
${
|
||||
this._deviceClassOptions && !this._hideDeviceClassOverride(domain)
|
||||
? html`
|
||||
<ha-select
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.entity_registry.editor.device_class"
|
||||
)}
|
||||
.value=${
|
||||
this._deviceClass
|
||||
? this.hass.localize(
|
||||
`ui.dialogs.entity_registry.editor.device_classes.${domain}.${this._deviceClass}`
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
clearable
|
||||
@selected=${this._deviceClassChanged}
|
||||
>
|
||||
${this._deviceClassesSorted(
|
||||
domain,
|
||||
this._deviceClassOptions[0],
|
||||
this.hass.localize
|
||||
).map(
|
||||
(entry) => html`
|
||||
<ha-dropdown-item
|
||||
.value=${entry.deviceClass}
|
||||
.selected=${entry.deviceClass === this._deviceClass}
|
||||
>
|
||||
${entry.label}
|
||||
</ha-dropdown-item>
|
||||
`
|
||||
)}
|
||||
${
|
||||
this._deviceClassOptions[0].length &&
|
||||
this._deviceClassOptions[1].length
|
||||
? html`<wa-divider></wa-divider>`
|
||||
: nothing
|
||||
}
|
||||
${this._deviceClassesSorted(
|
||||
domain,
|
||||
this._deviceClassOptions[1],
|
||||
this.hass.localize
|
||||
).map(
|
||||
(entry) => html`
|
||||
<ha-dropdown-item
|
||||
.value=${entry.deviceClass}
|
||||
.selected=${entry.deviceClass === this._deviceClass}
|
||||
>
|
||||
${entry.label}
|
||||
</ha-dropdown-item>
|
||||
`
|
||||
)}
|
||||
</ha-select>
|
||||
`
|
||||
: nothing
|
||||
}
|
||||
${
|
||||
domain === "number" &&
|
||||
this._effectiveDeviceClass &&
|
||||
this._deviceClass &&
|
||||
stateObj?.attributes.unit_of_measurement &&
|
||||
this._numberDeviceClassConvertibleUnits?.includes(
|
||||
stateObj?.attributes.unit_of_measurement
|
||||
@@ -854,7 +846,7 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
}
|
||||
${
|
||||
domain === "sensor" &&
|
||||
this._effectiveDeviceClass &&
|
||||
this._deviceClass &&
|
||||
stateObj?.attributes.unit_of_measurement &&
|
||||
this._sensorDeviceClassConvertibleUnits?.includes(
|
||||
stateObj?.attributes.unit_of_measurement
|
||||
@@ -879,7 +871,7 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
domain === "sensor" &&
|
||||
// Allow customizing the precision for a sensor with numerical device class,
|
||||
// a unit of measurement or state class
|
||||
(isNumericSensorDeviceClass(this._effectiveDeviceClass) ||
|
||||
(isNumericSensorDeviceClass(this._deviceClass) ||
|
||||
stateObj?.attributes.unit_of_measurement ||
|
||||
stateObj?.attributes.state_class)
|
||||
? html`
|
||||
@@ -1325,8 +1317,12 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
new_entity_id: this._entityId.trim(),
|
||||
};
|
||||
|
||||
if (this._deviceClass !== (this.entry.device_class ?? null)) {
|
||||
params.device_class = this._deviceClass;
|
||||
// Only update device class if changed by user
|
||||
if (
|
||||
this._deviceClass !==
|
||||
(this.entry.device_class || this.entry.original_device_class)
|
||||
) {
|
||||
params.device_class = this._deviceClass ?? null;
|
||||
}
|
||||
|
||||
const stateObj: HassEntity | undefined =
|
||||
@@ -1620,9 +1616,8 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
this._entityId = `${computeDomain(this._origEntityId)}.${(ev.target as HTMLInputElement).value}`;
|
||||
}
|
||||
|
||||
private _deviceClassChanged(ev: HaSelectSelectEvent): void {
|
||||
const value = ev.detail.value;
|
||||
this._deviceClass = value === DEFAULT_DEVICE_CLASS ? null : value;
|
||||
private _deviceClassChanged(ev: HaSelectSelectEvent<string, true>): void {
|
||||
this._deviceClass = ev.detail.value;
|
||||
}
|
||||
|
||||
private _unitChanged(ev: HaSelectSelectEvent): void {
|
||||
@@ -1684,7 +1679,7 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
value === "outlet") ||
|
||||
value === "switch"
|
||||
) {
|
||||
this._deviceClass = value === this._originalDeviceClass ? null : value;
|
||||
this._deviceClass = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1794,88 +1789,6 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
return String(this.entry.original_name ?? "");
|
||||
}
|
||||
|
||||
private get _originalDeviceClass(): string | undefined {
|
||||
return this.entry.original_device_class || undefined;
|
||||
}
|
||||
|
||||
private get _effectiveDeviceClass(): string | undefined {
|
||||
return this._deviceClass || this._originalDeviceClass;
|
||||
}
|
||||
|
||||
private _renderDeviceClassSelect(domain: string) {
|
||||
if (!this._showDeviceClassSelect(domain)) {
|
||||
return nothing;
|
||||
}
|
||||
const options = this._deviceClassOptions(
|
||||
domain,
|
||||
this._originalDeviceClass,
|
||||
this.hass.localize,
|
||||
this.hass.locale.language
|
||||
);
|
||||
const selectedValue = this._deviceClass || DEFAULT_DEVICE_CLASS;
|
||||
const selectedOption = [
|
||||
options.defaultOption,
|
||||
...options.related,
|
||||
...options.others,
|
||||
].find((option) => option.value === selectedValue);
|
||||
|
||||
return html`
|
||||
<ha-select
|
||||
.label=${this.hass.localize("ui.dialogs.entity_registry.editor.type")}
|
||||
.value=${selectedOption?.label}
|
||||
@selected=${this._deviceClassChanged}
|
||||
>
|
||||
${this._renderDeviceClassItem(domain, options.defaultOption)}
|
||||
<wa-divider></wa-divider>
|
||||
${options.related.map((option) =>
|
||||
this._renderDeviceClassItem(domain, option)
|
||||
)}
|
||||
${
|
||||
options.related.length && options.others.length
|
||||
? html`<wa-divider></wa-divider>`
|
||||
: nothing
|
||||
}
|
||||
${options.others.map((option) =>
|
||||
this._renderDeviceClassItem(domain, option)
|
||||
)}
|
||||
</ha-select>
|
||||
`;
|
||||
}
|
||||
|
||||
private _renderDeviceClassItem(domain: string, option: DeviceClassOption) {
|
||||
return html`
|
||||
<ha-dropdown-item
|
||||
.value=${option.value}
|
||||
.selected=${option.value === (this._deviceClass || DEFAULT_DEVICE_CLASS)}
|
||||
>
|
||||
<ha-domain-icon
|
||||
slot="icon"
|
||||
.domain=${domain}
|
||||
.deviceClass=${option.deviceClass}
|
||||
.state=${DEVICE_CLASS_ICON_STATES[domain]}
|
||||
></ha-domain-icon>
|
||||
${option.label}
|
||||
</ha-dropdown-item>
|
||||
`;
|
||||
}
|
||||
|
||||
private _deviceClassOptions = memoizeOne(computeDeviceClassOptions);
|
||||
|
||||
private _previewStateObj = memoizeOne(
|
||||
(
|
||||
stateObj: HassEntity | undefined,
|
||||
deviceClass: string | undefined
|
||||
): HassEntity | undefined => {
|
||||
if (!stateObj || stateObj.attributes.device_class === deviceClass) {
|
||||
return stateObj;
|
||||
}
|
||||
return {
|
||||
...stateObj,
|
||||
attributes: { ...stateObj.attributes, device_class: deviceClass },
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
private _restoreName(): void {
|
||||
this._name = this._originalName;
|
||||
if (this._device && !this._originalName) {
|
||||
@@ -1953,6 +1866,20 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
||||
)
|
||||
);
|
||||
|
||||
private _deviceClassesSorted = memoizeOne(
|
||||
(domain: string, deviceClasses: string[], localize: LocalizeFunc) =>
|
||||
deviceClasses
|
||||
.map((entry) => ({
|
||||
deviceClass: entry,
|
||||
label: localize(
|
||||
`ui.dialogs.entity_registry.editor.device_classes.${domain}.${entry}`
|
||||
),
|
||||
}))
|
||||
.sort((a, b) =>
|
||||
stringCompare(a.label, b.label, this.hass.locale.language)
|
||||
)
|
||||
);
|
||||
|
||||
private _switchAsLabel = memoizeOne(
|
||||
(switchAsDomain: string, deviceClass?: string) => {
|
||||
if (switchAsDomain !== "switch") {
|
||||
|
||||
@@ -1610,6 +1610,21 @@
|
||||
"syntax_error": "YAML syntax error",
|
||||
"error": "Error in parsing YAML: {reason}",
|
||||
"error_location": "line: {line}, column: {column}",
|
||||
"reasons": {
|
||||
"duplicated_mapping_key": "Duplicated mapping key",
|
||||
"bad_mapping_indentation": "Bad indentation of a mapping entry",
|
||||
"bad_sequence_indentation": "Bad indentation of a sequence entry",
|
||||
"deficient_indentation": "Deficient indentation",
|
||||
"tab_indentation": "Tab characters must not be used in indentation",
|
||||
"multiline_implicit_key": "Can not read a block mapping entry; a multiline key may not be an implicit key",
|
||||
"missing_key_value_space": "A whitespace character is expected after the key-value separator within a block mapping",
|
||||
"missing_colon": "Expected ':' after a mapping key",
|
||||
"missing_comma": "Missed comma between flow collection entries",
|
||||
"unterminated_flow_collection": "Unexpected end of the stream within a flow collection",
|
||||
"unterminated_single_quote": "Unexpected end of the stream within a single quoted scalar",
|
||||
"unterminated_double_quote": "Unexpected end of the stream within a double quoted scalar",
|
||||
"unexpected_content": "End of the stream or a document separator is expected"
|
||||
},
|
||||
"enter_fullscreen": "Enter fullscreen",
|
||||
"exit_fullscreen": "Exit fullscreen",
|
||||
"find_and_replace": "Find and replace",
|
||||
@@ -2192,8 +2207,6 @@
|
||||
"visibility_unit": "Visibility unit",
|
||||
"wind_speed_unit": "Wind speed unit",
|
||||
"device_class": "Show as",
|
||||
"type": "Type",
|
||||
"type_default": "Default ({type})",
|
||||
"switch_as_x": "Show switch as",
|
||||
"invert": {
|
||||
"label": "Invert state",
|
||||
|
||||
Reference in new issue
Block a user