mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-10 10:56:34 +00:00
Merge pull request #10869 from home-assistant/dev
This commit is contained in:
commit
bdd13db8cf
2
setup.py
2
setup.py
@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="home-assistant-frontend",
|
name="home-assistant-frontend",
|
||||||
version="20211209.0",
|
version="20211211.0",
|
||||||
description="The Home Assistant frontend",
|
description="The Home Assistant frontend",
|
||||||
url="https://github.com/home-assistant/frontend",
|
url="https://github.com/home-assistant/frontend",
|
||||||
author="The Home Assistant Authors",
|
author="The Home Assistant Authors",
|
||||||
|
@ -56,6 +56,7 @@ export class HaRelatedFilterButtonMenu extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
@click=${this._handleClick}
|
@click=${this._handleClick}
|
||||||
|
.label=${this.hass.localize("ui.components.related-filter-menu.filter")}
|
||||||
.path=${mdiFilterVariant}
|
.path=${mdiFilterVariant}
|
||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
<mwc-menu-surface
|
<mwc-menu-surface
|
||||||
|
@ -35,7 +35,7 @@ class HaCoverControls extends LitElement {
|
|||||||
hidden: !supportsOpen(this.stateObj),
|
hidden: !supportsOpen(this.stateObj),
|
||||||
})}
|
})}
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.dialogs.more_info_control.open_cover"
|
"ui.dialogs.more_info_control.cover.open_cover"
|
||||||
)}
|
)}
|
||||||
@click=${this._onOpenTap}
|
@click=${this._onOpenTap}
|
||||||
.disabled=${this._computeOpenDisabled()}
|
.disabled=${this._computeOpenDisabled()}
|
||||||
@ -47,7 +47,7 @@ class HaCoverControls extends LitElement {
|
|||||||
hidden: !supportsStop(this.stateObj),
|
hidden: !supportsStop(this.stateObj),
|
||||||
})}
|
})}
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.dialogs.more_info_control.stop_cover"
|
"ui.dialogs.more_info_control.cover.stop_cover"
|
||||||
)}
|
)}
|
||||||
.path=${mdiStop}
|
.path=${mdiStop}
|
||||||
@click=${this._onStopTap}
|
@click=${this._onStopTap}
|
||||||
@ -58,7 +58,7 @@ class HaCoverControls extends LitElement {
|
|||||||
hidden: !supportsClose(this.stateObj),
|
hidden: !supportsClose(this.stateObj),
|
||||||
})}
|
})}
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.dialogs.more_info_control.close_cover"
|
"ui.dialogs.more_info_control.cover.close_cover"
|
||||||
)}
|
)}
|
||||||
@click=${this._onCloseTap}
|
@click=${this._onCloseTap}
|
||||||
.disabled=${this._computeClosedDisabled()}
|
.disabled=${this._computeClosedDisabled()}
|
||||||
|
@ -30,7 +30,7 @@ class HaCoverTiltControls extends LitElement {
|
|||||||
invisible: !supportsOpenTilt(this.stateObj),
|
invisible: !supportsOpenTilt(this.stateObj),
|
||||||
})}
|
})}
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.dialogs.more_info_control.open_tilt_cover"
|
"ui.dialogs.more_info_control.cover.open_tilt_cover"
|
||||||
)}
|
)}
|
||||||
.path=${mdiArrowTopRight}
|
.path=${mdiArrowTopRight}
|
||||||
@click=${this._onOpenTiltTap}
|
@click=${this._onOpenTiltTap}
|
||||||
@ -40,7 +40,9 @@ class HaCoverTiltControls extends LitElement {
|
|||||||
class=${classMap({
|
class=${classMap({
|
||||||
invisible: !supportsStopTilt(this.stateObj),
|
invisible: !supportsStopTilt(this.stateObj),
|
||||||
})}
|
})}
|
||||||
.label=${this.hass.localize("ui.dialogs.more_info_control.stop_cover")}
|
.label=${this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.cover.stop_cover"
|
||||||
|
)}
|
||||||
.path=${mdiStop}
|
.path=${mdiStop}
|
||||||
@click=${this._onStopTiltTap}
|
@click=${this._onStopTiltTap}
|
||||||
.disabled=${this.stateObj.state === UNAVAILABLE}
|
.disabled=${this.stateObj.state === UNAVAILABLE}
|
||||||
@ -50,7 +52,7 @@ class HaCoverTiltControls extends LitElement {
|
|||||||
invisible: !supportsCloseTilt(this.stateObj),
|
invisible: !supportsCloseTilt(this.stateObj),
|
||||||
})}
|
})}
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.dialogs.more_info_control.close_tilt_cover"
|
"ui.dialogs.more_info_control.cover.close_tilt_cover"
|
||||||
)}
|
)}
|
||||||
.path=${mdiArrowBottomLeft}
|
.path=${mdiArrowBottomLeft}
|
||||||
@click=${this._onCloseTiltTap}
|
@click=${this._onCloseTiltTap}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Formfield } from "@material/mwc-formfield";
|
import { Formfield } from "@material/mwc-formfield";
|
||||||
import { css, CSSResultGroup } from "lit";
|
import { css, CSSResultGroup } from "lit";
|
||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
|
||||||
@customElement("ha-formfield")
|
@customElement("ha-formfield")
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@ -13,6 +14,7 @@ export class HaFormfield extends Formfield {
|
|||||||
case "HA-CHECKBOX":
|
case "HA-CHECKBOX":
|
||||||
case "HA-RADIO":
|
case "HA-RADIO":
|
||||||
(input as any).checked = !(input as any).checked;
|
(input as any).checked = !(input as any).checked;
|
||||||
|
fireEvent(input, "change");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
input.click();
|
input.click();
|
||||||
|
@ -29,7 +29,7 @@ export class HaIconOverflowMenu extends LitElement {
|
|||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
${this.narrow
|
${this.narrow
|
||||||
? html` <!-- Collapsed Representation for Small Screens -->
|
? html` <!-- Collapsed representation for small screens -->
|
||||||
<ha-button-menu
|
<ha-button-menu
|
||||||
@click=${this._handleIconOverflowMenuOpened}
|
@click=${this._handleIconOverflowMenuOpened}
|
||||||
@closed=${this._handleIconOverflowMenuClosed}
|
@closed=${this._handleIconOverflowMenuClosed}
|
||||||
@ -59,8 +59,7 @@ export class HaIconOverflowMenu extends LitElement {
|
|||||||
)}
|
)}
|
||||||
</ha-button-menu>`
|
</ha-button-menu>`
|
||||||
: html`
|
: html`
|
||||||
<!-- Icon Representation for Big Screens -->
|
<!-- Icon representation for big screens -->
|
||||||
|
|
||||||
${this.items.map((item) =>
|
${this.items.map((item) =>
|
||||||
item.narrowOnly
|
item.narrowOnly
|
||||||
? ""
|
? ""
|
||||||
@ -70,13 +69,12 @@ export class HaIconOverflowMenu extends LitElement {
|
|||||||
${item.tooltip}
|
${item.tooltip}
|
||||||
</paper-tooltip>`
|
</paper-tooltip>`
|
||||||
: ""}
|
: ""}
|
||||||
<mwc-icon-button
|
<ha-icon-button
|
||||||
@click=${item.action}
|
@click=${item.action}
|
||||||
.label=${item.label}
|
.label=${item.label}
|
||||||
|
.path=${item.path}
|
||||||
.disabled=${item.disabled}
|
.disabled=${item.disabled}
|
||||||
>
|
></ha-icon-button>
|
||||||
<ha-svg-icon .path=${item.path}></ha-svg-icon>
|
|
||||||
</mwc-icon-button>
|
|
||||||
</div> `
|
</div> `
|
||||||
)}
|
)}
|
||||||
`}
|
`}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import "@material/mwc-list/mwc-list-item";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import "@material/mwc-select/mwc-select";
|
import "@material/mwc-select/mwc-select";
|
||||||
|
import "@material/mwc-textfield/mwc-textfield";
|
||||||
|
import type { TextField } from "@material/mwc-textfield/mwc-textfield";
|
||||||
import { mdiCamera } from "@mdi/js";
|
import { mdiCamera } from "@mdi/js";
|
||||||
import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
@ -9,6 +11,7 @@ import { stopPropagation } from "../common/dom/stop_propagation";
|
|||||||
import { LocalizeFunc } from "../common/translations/localize";
|
import { LocalizeFunc } from "../common/translations/localize";
|
||||||
import "./ha-alert";
|
import "./ha-alert";
|
||||||
import "./ha-button-menu";
|
import "./ha-button-menu";
|
||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
|
||||||
@customElement("ha-qr-scanner")
|
@customElement("ha-qr-scanner")
|
||||||
class HaQrScanner extends LitElement {
|
class HaQrScanner extends LitElement {
|
||||||
@ -26,6 +29,8 @@ class HaQrScanner extends LitElement {
|
|||||||
|
|
||||||
@query("#canvas-container", true) private _canvasContainer!: HTMLDivElement;
|
@query("#canvas-container", true) private _canvasContainer!: HTMLDivElement;
|
||||||
|
|
||||||
|
@query("mwc-textfield") private _manualInput?: TextField;
|
||||||
|
|
||||||
public disconnectedCallback(): void {
|
public disconnectedCallback(): void {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
this._qrNotFoundCount = 0;
|
this._qrNotFoundCount = 0;
|
||||||
@ -74,7 +79,7 @@ class HaQrScanner extends LitElement {
|
|||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
slot="trigger"
|
slot="trigger"
|
||||||
.label=${this.localize(
|
.label=${this.localize(
|
||||||
"ui.panel.config.zwave_js.add_node.select_camera"
|
"ui.components.qr-scanner.select_camera"
|
||||||
)}
|
)}
|
||||||
.path=${mdiCamera}
|
.path=${mdiCamera}
|
||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
@ -90,11 +95,22 @@ class HaQrScanner extends LitElement {
|
|||||||
</ha-button-menu>`
|
</ha-button-menu>`
|
||||||
: ""}
|
: ""}
|
||||||
</div>`
|
</div>`
|
||||||
: html`<ha-alert alert-type="warning"
|
: html`<ha-alert alert-type="warning">
|
||||||
>${!window.isSecureContext
|
${!window.isSecureContext
|
||||||
? "You can only use your camera to scan a QR core when using HTTPS."
|
? this.localize("ui.components.qr-scanner.only_https_supported")
|
||||||
: "Your browser doesn't support QR scanning."}</ha-alert
|
: this.localize("ui.components.qr-scanner.not_supported")}
|
||||||
>`}`;
|
</ha-alert>
|
||||||
|
<p>${this.localize("ui.components.qr-scanner.manual_input")}</p>
|
||||||
|
<div class="row">
|
||||||
|
<mwc-textfield
|
||||||
|
.label=${this.localize("ui.components.qr-scanner.enter_qr_code")}
|
||||||
|
@keyup=${this._manualKeyup}
|
||||||
|
@paste=${this._manualPaste}
|
||||||
|
></mwc-textfield>
|
||||||
|
<mwc-button @click=${this._manualSubmit}
|
||||||
|
>${this.localize("ui.common.submit")}</mwc-button
|
||||||
|
>
|
||||||
|
</div>`}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _loadQrScanner() {
|
private async _loadQrScanner() {
|
||||||
@ -143,6 +159,23 @@ class HaQrScanner extends LitElement {
|
|||||||
fireEvent(this, "qr-code-scanned", { value: qrCodeString });
|
fireEvent(this, "qr-code-scanned", { value: qrCodeString });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private _manualKeyup(ev: KeyboardEvent) {
|
||||||
|
if (ev.key === "Enter") {
|
||||||
|
this._qrCodeScanned((ev.target as TextField).value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _manualPaste(ev: ClipboardEvent) {
|
||||||
|
this._qrCodeScanned(
|
||||||
|
// @ts-ignore
|
||||||
|
(ev.clipboardData || window.clipboardData).getData("text")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _manualSubmit() {
|
||||||
|
this._qrCodeScanned(this._manualInput!.value);
|
||||||
|
}
|
||||||
|
|
||||||
private _cameraChanged(ev: CustomEvent): void {
|
private _cameraChanged(ev: CustomEvent): void {
|
||||||
this._qrScanner?.setCamera((ev.target as any).value);
|
this._qrScanner?.setCamera((ev.target as any).value);
|
||||||
}
|
}
|
||||||
@ -162,6 +195,14 @@ class HaQrScanner extends LitElement {
|
|||||||
color: white;
|
color: white;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
mwc-textfield {
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +99,8 @@ export class QuickBar extends LitElement {
|
|||||||
|
|
||||||
private _focusSet = false;
|
private _focusSet = false;
|
||||||
|
|
||||||
|
private _focusListElement?: ListItem | null;
|
||||||
|
|
||||||
public async showDialog(params: QuickBarParams) {
|
public async showDialog(params: QuickBarParams) {
|
||||||
this._commandMode = params.commandMode || this._toggleIfAlreadyOpened();
|
this._commandMode = params.commandMode || this._toggleIfAlreadyOpened();
|
||||||
this._initializeItemsIfNeeded();
|
this._initializeItemsIfNeeded();
|
||||||
@ -317,7 +319,8 @@ export class QuickBar extends LitElement {
|
|||||||
} else if (ev.code === "ArrowDown") {
|
} else if (ev.code === "ArrowDown") {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this._getItemAtIndex(0)?.focus();
|
this._getItemAtIndex(0)?.focus();
|
||||||
this._getItemAtIndex(1)?.focus();
|
this._focusSet = true;
|
||||||
|
this._focusListElement = this._getItemAtIndex(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,6 +353,11 @@ export class QuickBar extends LitElement {
|
|||||||
this._initializeItemsIfNeeded();
|
this._initializeItemsIfNeeded();
|
||||||
this._filter = this._search;
|
this._filter = this._search;
|
||||||
} else {
|
} else {
|
||||||
|
if (this._focusSet && this._focusListElement) {
|
||||||
|
this._focusSet = false;
|
||||||
|
// @ts-ignore
|
||||||
|
this._focusListElement.rippleHandlers.endFocus();
|
||||||
|
}
|
||||||
this._debouncedSetFilter(this._search);
|
this._debouncedSetFilter(this._search);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,12 +374,14 @@ export class QuickBar extends LitElement {
|
|||||||
private _setFocusFirstListItem() {
|
private _setFocusFirstListItem() {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this._getItemAtIndex(0)?.rippleHandlers.startFocus();
|
this._getItemAtIndex(0)?.rippleHandlers.startFocus();
|
||||||
|
this._focusListElement = this._getItemAtIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleListItemKeyDown(ev: KeyboardEvent) {
|
private _handleListItemKeyDown(ev: KeyboardEvent) {
|
||||||
const isSingleCharacter = ev.key.length === 1;
|
const isSingleCharacter = ev.key.length === 1;
|
||||||
const isFirstListItem =
|
const isFirstListItem =
|
||||||
(ev.target as HTMLElement).getAttribute("index") === "0";
|
(ev.target as HTMLElement).getAttribute("index") === "0";
|
||||||
|
this._focusListElement = ev.target as ListItem;
|
||||||
if (ev.key === "ArrowUp") {
|
if (ev.key === "ArrowUp") {
|
||||||
if (isFirstListItem) {
|
if (isFirstListItem) {
|
||||||
this._filterInputField?.focus();
|
this._filterInputField?.focus();
|
||||||
@ -511,7 +521,13 @@ export class QuickBar extends LitElement {
|
|||||||
if (page.component) {
|
if (page.component) {
|
||||||
const info = this._getNavigationInfoFromConfig(page);
|
const info = this._getNavigationInfoFromConfig(page);
|
||||||
|
|
||||||
if (info) {
|
// Add to list, but only if we do not already have an entry for the same path and component
|
||||||
|
if (
|
||||||
|
info &&
|
||||||
|
!items.some(
|
||||||
|
(e) => e.path === info.path && e.component === info.component
|
||||||
|
)
|
||||||
|
) {
|
||||||
items.push(info);
|
items.push(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { object, optional, number } from "superstruct";
|
import { object, optional, number, string } from "superstruct";
|
||||||
|
|
||||||
|
export const baseTriggerStruct = object({
|
||||||
|
platform: string(),
|
||||||
|
id: optional(string()),
|
||||||
|
});
|
||||||
|
|
||||||
export const forDictStruct = object({
|
export const forDictStruct = object({
|
||||||
days: optional(number()),
|
days: optional(number()),
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import { html, LitElement, PropertyValues } from "lit";
|
import { html, LitElement, PropertyValues } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { assert, literal, object, optional, string, union } from "superstruct";
|
import {
|
||||||
|
assert,
|
||||||
|
assign,
|
||||||
|
literal,
|
||||||
|
object,
|
||||||
|
optional,
|
||||||
|
string,
|
||||||
|
union,
|
||||||
|
} from "superstruct";
|
||||||
import { createDurationData } from "../../../../../common/datetime/create_duration_data";
|
import { createDurationData } from "../../../../../common/datetime/create_duration_data";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
import { hasTemplate } from "../../../../../common/string/has-template";
|
import { hasTemplate } from "../../../../../common/string/has-template";
|
||||||
@ -10,20 +18,23 @@ import "../../../../../components/entity/ha-entity-picker";
|
|||||||
import "../../../../../components/ha-duration-input";
|
import "../../../../../components/ha-duration-input";
|
||||||
import { StateTrigger } from "../../../../../data/automation";
|
import { StateTrigger } from "../../../../../data/automation";
|
||||||
import { HomeAssistant } from "../../../../../types";
|
import { HomeAssistant } from "../../../../../types";
|
||||||
import { forDictStruct } from "../../structs";
|
import { baseTriggerStruct, forDictStruct } from "../../structs";
|
||||||
import {
|
import {
|
||||||
handleChangeEvent,
|
handleChangeEvent,
|
||||||
TriggerElement,
|
TriggerElement,
|
||||||
} from "../ha-automation-trigger-row";
|
} from "../ha-automation-trigger-row";
|
||||||
|
|
||||||
const stateTriggerStruct = object({
|
const stateTriggerStruct = assign(
|
||||||
platform: literal("state"),
|
baseTriggerStruct,
|
||||||
entity_id: string(),
|
object({
|
||||||
attribute: optional(string()),
|
platform: literal("state"),
|
||||||
from: optional(string()),
|
entity_id: string(),
|
||||||
to: optional(string()),
|
attribute: optional(string()),
|
||||||
for: optional(union([string(), forDictStruct])),
|
from: optional(string()),
|
||||||
});
|
to: optional(string()),
|
||||||
|
for: optional(union([string(), forDictStruct])),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
@customElement("ha-automation-trigger-state")
|
@customElement("ha-automation-trigger-state")
|
||||||
export class HaStateTrigger extends LitElement implements TriggerElement {
|
export class HaStateTrigger extends LitElement implements TriggerElement {
|
||||||
|
@ -178,7 +178,10 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
Search device
|
Search device
|
||||||
</mwc-button>`
|
</mwc-button>`
|
||||||
: this._status === "qr_scan"
|
: this._status === "qr_scan"
|
||||||
? html`<ha-qr-scanner
|
? html`${this._error
|
||||||
|
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||||
|
: ""}
|
||||||
|
<ha-qr-scanner
|
||||||
.localize=${this.hass.localize}
|
.localize=${this.hass.localize}
|
||||||
@qr-code-scanned=${this._qrCodeScanned}
|
@qr-code-scanned=${this._qrCodeScanned}
|
||||||
></ha-qr-scanner>
|
></ha-qr-scanner>
|
||||||
@ -194,9 +197,9 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
</p>
|
</p>
|
||||||
${
|
${
|
||||||
this._error
|
this._error
|
||||||
? html`<ha-alert alert-type="error"
|
? html`<ha-alert alert-type="error">
|
||||||
>${this._error}</ha-alert
|
${this._error}
|
||||||
>`
|
</ha-alert>`
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
<div class="flex-container">
|
<div class="flex-container">
|
||||||
@ -614,7 +617,6 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
ZWaveFeature.SmartStart
|
ZWaveFeature.SmartStart
|
||||||
)
|
)
|
||||||
).supported;
|
).supported;
|
||||||
this._supportsSmartStart = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _startOver(_ev: Event) {
|
private _startOver(_ev: Event) {
|
||||||
|
@ -291,12 +291,14 @@
|
|||||||
"undo": "Undo",
|
"undo": "Undo",
|
||||||
"move": "Move",
|
"move": "Move",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
|
"submit": "Submit",
|
||||||
"rename": "Rename",
|
"rename": "Rename",
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
"not_now": "Not now",
|
"not_now": "Not now",
|
||||||
"skip": "Skip",
|
"skip": "Skip",
|
||||||
"menu": "Menu",
|
"menu": "Menu",
|
||||||
|
"overflow_menu": "Overflow menu",
|
||||||
"help": "Help",
|
"help": "Help",
|
||||||
"successfully_saved": "Successfully saved",
|
"successfully_saved": "Successfully saved",
|
||||||
"successfully_deleted": "Successfully deleted",
|
"successfully_deleted": "Successfully deleted",
|
||||||
@ -421,6 +423,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"related-filter-menu": {
|
"related-filter-menu": {
|
||||||
|
"filter": "Filter",
|
||||||
"filter_by_entity": "Filter by entity",
|
"filter_by_entity": "Filter by entity",
|
||||||
"filter_by_device": "Filter by device",
|
"filter_by_device": "Filter by device",
|
||||||
"filter_by_area": "Filter by area",
|
"filter_by_area": "Filter by area",
|
||||||
@ -538,6 +541,13 @@
|
|||||||
},
|
},
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"expansion_header": "Attributes"
|
"expansion_header": "Attributes"
|
||||||
|
},
|
||||||
|
"qr-scanner": {
|
||||||
|
"select_camera": "Select camera",
|
||||||
|
"only_https_supported": "You can only use your camera to scan a QR code when using HTTPS.",
|
||||||
|
"not_supported": "Your browser doesn't support QR scanning.",
|
||||||
|
"manual_input": "You can scan the QR code with another QR scanner and paste the code in the input below",
|
||||||
|
"enter_qr_code": "Enter QR code value"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dialogs": {
|
"dialogs": {
|
||||||
@ -939,7 +949,7 @@
|
|||||||
},
|
},
|
||||||
"blueprints": {
|
"blueprints": {
|
||||||
"title": "Blueprints",
|
"title": "Blueprints",
|
||||||
"description": "Manage blueprints"
|
"description": "Pre-made automations and scripts by the community"
|
||||||
},
|
},
|
||||||
"supervisor": {
|
"supervisor": {
|
||||||
"title": "Add-ons, Backups & Supervisor",
|
"title": "Add-ons, Backups & Supervisor",
|
||||||
@ -1146,7 +1156,7 @@
|
|||||||
"cost_number": "Use a static price",
|
"cost_number": "Use a static price",
|
||||||
"cost_number_input": "Price per {unit}",
|
"cost_number_input": "Price per {unit}",
|
||||||
"gas_usage": "Gas usage",
|
"gas_usage": "Gas usage",
|
||||||
"m3_or_kWh": "m³ or kWh"
|
"m3_or_kWh": "ft³, m³, Wh, kWh or MWh"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"device_consumption": {
|
"device_consumption": {
|
||||||
@ -1187,19 +1197,19 @@
|
|||||||
},
|
},
|
||||||
"entity_unexpected_unit_energy": {
|
"entity_unexpected_unit_energy": {
|
||||||
"title": "Unexpected unit of measurement",
|
"title": "Unexpected unit of measurement",
|
||||||
"description": "The following entities do not have the expected units of measurement 'kWh' or 'Wh':"
|
"description": "The following entities do not have the expected units of measurement 'Wh', 'kWh' or 'MWh':"
|
||||||
},
|
},
|
||||||
"entity_unexpected_unit_gas": {
|
"entity_unexpected_unit_gas": {
|
||||||
"title": "Unexpected unit of measurement",
|
"title": "Unexpected unit of measurement",
|
||||||
"description": "The following entities do not have the expected units of measurement 'kWh', 'm³' or 'ft³':"
|
"description": "The following entities do not have the expected units of measurement 'Wh', 'kWh' or 'MWh' for an energy sensor or 'm³' or 'ft³' for a gas sensor:"
|
||||||
},
|
},
|
||||||
"entity_unexpected_unit_energy_price": {
|
"entity_unexpected_unit_energy_price": {
|
||||||
"title": "Unexpected unit of measurement",
|
"title": "Unexpected unit of measurement",
|
||||||
"description": "The following entities do not have the expected units of measurement ''{currency}/kWh'' or ''{currency}/Wh'':"
|
"description": "The following entities do not have the expected units of measurement ''{currency}/kWh'', ''{currency}/Wh'' or ''{currency}/MWh'':"
|
||||||
},
|
},
|
||||||
"entity_unexpected_unit_gas_price": {
|
"entity_unexpected_unit_gas_price": {
|
||||||
"title": "Unexpected unit of measurement",
|
"title": "Unexpected unit of measurement",
|
||||||
"description": "The following entities do not have the expected units of measurement ''{currency}/kWh'', ''{currency}/Wh'', ''{currency}/m³'' or ''{currency}/ft³'':"
|
"description": "The following entities do not have the expected units of measurement ''{currency}/kWh'', ''{currency}/Wh'', ''{currency}/MWh'', ''{currency}/m³'' or ''{currency}/ft³'':"
|
||||||
},
|
},
|
||||||
"entity_unexpected_state_class": {
|
"entity_unexpected_state_class": {
|
||||||
"title": "Unexpected state class",
|
"title": "Unexpected state class",
|
||||||
@ -2515,7 +2525,7 @@
|
|||||||
"admin": "Administrator",
|
"admin": "Administrator",
|
||||||
"group": "Group",
|
"group": "Group",
|
||||||
"active": "Active",
|
"active": "Active",
|
||||||
"local_only": "Can only login from the local network",
|
"local_only": "Can only log in from the local network",
|
||||||
"system_generated": "System generated",
|
"system_generated": "System generated",
|
||||||
"system_generated_users_not_removable": "Unable to remove system generated users.",
|
"system_generated_users_not_removable": "Unable to remove system generated users.",
|
||||||
"system_generated_users_not_editable": "Unable to update system generated users.",
|
"system_generated_users_not_editable": "Unable to update system generated users.",
|
||||||
@ -2920,8 +2930,6 @@
|
|||||||
"qr_code": "QR Code",
|
"qr_code": "QR Code",
|
||||||
"qr_code_paragraph": "If your device supports SmartStart you can scan the QR code for easy pairing.",
|
"qr_code_paragraph": "If your device supports SmartStart you can scan the QR code for easy pairing.",
|
||||||
"scan_qr_code": "Scan QR code",
|
"scan_qr_code": "Scan QR code",
|
||||||
"enter_qr_code": "Enter QR code value",
|
|
||||||
"select_camera": "Select camera",
|
|
||||||
"inclusion_failed": "The device could not be added.",
|
"inclusion_failed": "The device could not be added.",
|
||||||
"check_logs": "Please check the logs for more information.",
|
"check_logs": "Please check the logs for more information.",
|
||||||
"inclusion_finished": "The device has been added.",
|
"inclusion_finished": "The device has been added.",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user