diff --git a/hassio/src/hassio-main.js b/hassio/src/hassio-main.js
index a01086d6db..df4d57b985 100644
--- a/hassio/src/hassio-main.js
+++ b/hassio/src/hassio-main.js
@@ -87,7 +87,8 @@ class HassioMain extends EventsMixin(NavigateMixin(PolymerElement)) {
// open and close events. These events are a no-op in newer versions of
// Home Assistant.
this.addEventListener("hass-toggle-menu", () => {
- window.parent.customPanel.fire(
+ fireEvent(
+ window.parent.customPanel,
this.hass.dockedSidebar ? "hass-close-menu" : "hass-open-menu"
);
});
@@ -130,7 +131,7 @@ class HassioMain extends EventsMixin(NavigateMixin(PolymerElement)) {
if (route.path === "" && route.prefix === "/hassio") {
this.navigate("/hassio/dashboard", true);
}
- this.fire("iron-resize");
+ fireEvent(this, "iron-resize");
}
equalsAddon(page) {
diff --git a/setup.py b/setup.py
index 5ef268efa2..772a9ba598 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name="home-assistant-frontend",
- version="20190327.0",
+ version="20190329.0",
description="The Home Assistant frontend",
url="https://github.com/home-assistant/home-assistant-polymer",
author="The Home Assistant Authors",
diff --git a/src/auth/ha-authorize.ts b/src/auth/ha-authorize.ts
index fe17c90bcb..10a190cca8 100644
--- a/src/auth/ha-authorize.ts
+++ b/src/auth/ha-authorize.ts
@@ -1,7 +1,15 @@
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
-import { LitElement, html, PropertyDeclarations } from "lit-element";
+import {
+ LitElement,
+ html,
+ PropertyDeclarations,
+ PropertyValues,
+ CSSResult,
+ css,
+} from "lit-element";
import "./ha-auth-flow";
import { AuthProvider } from "../data/auth";
+import { registerServiceWorker } from "../util/register-service-worker";
import(/* webpackChunkName: "pick-auth-provider" */ "../auth/ha-pick-auth-provider");
@@ -76,7 +84,6 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
);
return html`
- ${this.renderStyle()}
${this.localize(
"ui.panel.page-authorize.authorizing_client",
@@ -108,7 +115,24 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
`;
}
- public async firstUpdated() {
+ protected firstUpdated(changedProps: PropertyValues) {
+ super.firstUpdated(changedProps);
+ this._fetchAuthProviders();
+
+ if (!this.redirectUri) {
+ return;
+ }
+
+ // If we are logging into the instance that is hosting this auth form
+ // we will register the service worker to start preloading.
+ const tempA = document.createElement("a");
+ tempA.href = this.redirectUri!;
+ if (tempA.host === location.host) {
+ registerServiceWorker(false);
+ }
+ }
+
+ private async _fetchAuthProviders() {
// Fetch auth providers
try {
const response = await (window as any).providersPromise;
@@ -136,19 +160,17 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
}
}
- protected renderStyle() {
- return html`
-
- `;
- }
-
private async _handleAuthProviderPick(ev) {
this._authProvider = ev.detail;
}
+
+ static get styles(): CSSResult {
+ return css`
+ ha-pick-auth-provider {
+ display: block;
+ margin-top: 48px;
+ }
+ `;
+ }
}
customElements.define("ha-authorize", HaAuthorize);
diff --git a/src/data/camera.ts b/src/data/camera.ts
index 62f94096e4..62ff707130 100644
--- a/src/data/camera.ts
+++ b/src/data/camera.ts
@@ -1,6 +1,13 @@
import { HomeAssistant, CameraEntity } from "../types";
import { timeCachePromiseFunc } from "../common/util/time-cache-function-promise";
+export const CAMERA_SUPPORT_ON_OFF = 1;
+export const CAMERA_SUPPORT_STREAM = 2;
+
+export interface CameraPreferences {
+ preload_stream: boolean;
+}
+
export interface CameraThumbnail {
content_type: string;
content: string;
@@ -41,3 +48,22 @@ export const fetchStreamUrl = (
}
return hass.callWS(data);
};
+
+export const fetchCameraPrefs = (hass: HomeAssistant, entityId: string) =>
+ hass.callWS({
+ type: "camera/get_prefs",
+ entity_id: entityId,
+ });
+
+export const updateCameraPrefs = (
+ hass: HomeAssistant,
+ entityId: string,
+ prefs: {
+ preload_stream?: boolean;
+ }
+) =>
+ hass.callWS({
+ type: "camera/update_prefs",
+ entity_id: entityId,
+ ...prefs,
+ });
diff --git a/src/data/zha.ts b/src/data/zha.ts
index 87ac9a3a88..454ffaa85a 100644
--- a/src/data/zha.ts
+++ b/src/data/zha.ts
@@ -15,8 +15,8 @@ export interface ZHADevice {
entities: ZHAEntityReference[];
manufacturer_code: number;
device_reg_id: string;
- user_given_name: string;
- area_id: string;
+ user_given_name?: string;
+ area_id?: string;
}
export interface Attribute {
diff --git a/src/dialogs/more-info/controls/more-info-camera.ts b/src/dialogs/more-info/controls/more-info-camera.ts
index 3fbc56a727..bb8ed1e393 100644
--- a/src/dialogs/more-info/controls/more-info-camera.ts
+++ b/src/dialogs/more-info/controls/more-info-camera.ts
@@ -1,15 +1,36 @@
-import { property, UpdatingElement, PropertyValues } from "lit-element";
+import {
+ property,
+ PropertyValues,
+ LitElement,
+ TemplateResult,
+ html,
+ CSSResult,
+ css,
+} from "lit-element";
import computeStateName from "../../../common/entity/compute_state_name";
import { HomeAssistant, CameraEntity } from "../../../types";
import { fireEvent } from "../../../common/dom/fire_event";
-import { fetchStreamUrl, computeMJPEGStreamUrl } from "../../../data/camera";
+import {
+ fetchStreamUrl,
+ computeMJPEGStreamUrl,
+ CAMERA_SUPPORT_STREAM,
+ CameraPreferences,
+ fetchCameraPrefs,
+ updateCameraPrefs,
+} from "../../../data/camera";
+import { supportsFeature } from "../../../common/entity/supports-feature";
+import "@polymer/paper-checkbox/paper-checkbox";
+// Not duplicate import, it's for typing
+// tslint:disable-next-line
+import { PaperCheckboxElement } from "@polymer/paper-checkbox/paper-checkbox";
type HLSModule = typeof import("hls.js");
-class MoreInfoCamera extends UpdatingElement {
+class MoreInfoCamera extends LitElement {
@property() public hass?: HomeAssistant;
@property() public stateObj?: CameraEntity;
+ @property() private _cameraPrefs?: CameraPreferences;
private _hlsPolyfillInstance?: Hls;
public disconnectedCallback() {
@@ -17,6 +38,22 @@ class MoreInfoCamera extends UpdatingElement {
this._teardownPlayback();
}
+ protected render(): TemplateResult | void {
+ return html`
+
+ ${this._cameraPrefs
+ ? html`
+
+ Preload stream
+
+ `
+ : undefined}
+ `;
+ }
+
protected updated(changedProps: PropertyValues) {
if (!changedProps.has("stateObj")) {
return;
@@ -46,7 +83,10 @@ class MoreInfoCamera extends UpdatingElement {
return;
}
- if (!this.hass!.config.components.includes("stream")) {
+ if (
+ !this.hass!.config.components.includes("stream") ||
+ !supportsFeature(this.stateObj, CAMERA_SUPPORT_STREAM)
+ ) {
this._renderMJPEG();
return;
}
@@ -73,6 +113,8 @@ class MoreInfoCamera extends UpdatingElement {
this.hass!,
this.stateObj.entity_id
);
+ // Fetch in background while we set up the video.
+ this._fetchCameraPrefs();
if (Hls.isSupported()) {
this._renderHLSPolyfill(videoEl, Hls, url);
@@ -81,16 +123,20 @@ class MoreInfoCamera extends UpdatingElement {
}
return;
} catch (err) {
- // Fails if entity doesn't support it. In that case we go
- // for mjpeg.
+ // When an error happens, we will do nothing so we render mjpeg.
}
}
this._renderMJPEG();
}
+ private get _videoRoot(): HTMLDivElement {
+ return this.shadowRoot!.getElementById("root")! as HTMLDivElement;
+ }
+
private async _renderHLSNative(videoEl: HTMLVideoElement, url: string) {
videoEl.src = url;
+ this._videoRoot.appendChild(videoEl);
await new Promise((resolve) =>
videoEl.addEventListener("loadedmetadata", resolve)
);
@@ -110,7 +156,7 @@ class MoreInfoCamera extends UpdatingElement {
hls.attachMedia(videoEl);
});
hls.loadSource(url);
- this.appendChild(videoEl);
+ this._videoRoot.appendChild(videoEl);
videoEl.addEventListener("loadeddata", () =>
fireEvent(this, "iron-resize")
);
@@ -124,7 +170,7 @@ class MoreInfoCamera extends UpdatingElement {
? "/demo/webcamp.jpg"
: computeMJPEGStreamUrl(this.stateObj!);
img.alt = computeStateName(this.stateObj!);
- this.appendChild(img);
+ this._videoRoot.appendChild(img);
}
private _teardownPlayback(): any {
@@ -132,11 +178,48 @@ class MoreInfoCamera extends UpdatingElement {
this._hlsPolyfillInstance.destroy();
this._hlsPolyfillInstance = undefined;
}
- while (this.lastChild) {
- this.removeChild(this.lastChild);
+ const root = this._videoRoot;
+ while (root.lastChild) {
+ root.removeChild(root.lastChild);
}
this.stateObj = undefined;
}
+
+ private async _fetchCameraPrefs() {
+ this._cameraPrefs = await fetchCameraPrefs(
+ this.hass!,
+ this.stateObj!.entity_id
+ );
+ }
+
+ private async _handleCheckboxChanged(ev) {
+ const checkbox = ev.currentTarget as PaperCheckboxElement;
+ try {
+ this._cameraPrefs = await updateCameraPrefs(
+ this.hass!,
+ this.stateObj!.entity_id,
+ {
+ preload_stream: checkbox.checked!,
+ }
+ );
+ } catch (err) {
+ alert(err.message);
+ checkbox.checked = !checkbox.checked;
+ }
+ }
+
+ static get styles(): CSSResult {
+ return css`
+ paper-checkbox {
+ position: absolute;
+ top: 0;
+ right: 0;
+ background-color: var(--secondary-background-color);
+ padding: 5px;
+ border-bottom-left-radius: 6px;
+ }
+ `;
+ }
}
customElements.define("more-info-camera", MoreInfoCamera);
diff --git a/src/dialogs/more-info/controls/more-info-content.ts b/src/dialogs/more-info/controls/more-info-content.ts
index e60c03b6e0..2d0f0e4cc7 100644
--- a/src/dialogs/more-info/controls/more-info-content.ts
+++ b/src/dialogs/more-info/controls/more-info-content.ts
@@ -43,6 +43,7 @@ class MoreInfoContent extends UpdatingElement {
}
protected firstUpdated(): void {
+ this.style.position = "relative";
this.style.display = "block";
}
diff --git a/src/entrypoints/custom-panel.ts b/src/entrypoints/custom-panel.ts
index f5c9c463e5..4021b7a8a7 100644
--- a/src/entrypoints/custom-panel.ts
+++ b/src/entrypoints/custom-panel.ts
@@ -72,13 +72,14 @@ function initialize(panel: Panel, properties: {}) {
}
};
panelEl!.addEventListener("hass-toggle-menu", forwardEvent);
- window.addEventListener("location-changed", (ev: any) =>
- navigate(
- window.parent.customPanel,
- window.location.pathname,
- ev.detail ? ev.detail.replace : false
- )
- );
+ window.addEventListener("location-changed", (ev: any) => {
+ if (window.parent.customPanel) {
+ window.parent.customPanel.navigate(
+ window.location.pathname,
+ ev.detail ? ev.detail.replace : false
+ );
+ }
+ });
setProperties({ panel, ...properties });
document.body.appendChild(panelEl!);
},
diff --git a/src/onboarding/ha-onboarding.ts b/src/onboarding/ha-onboarding.ts
index 19a7a91f15..e377ac250d 100644
--- a/src/onboarding/ha-onboarding.ts
+++ b/src/onboarding/ha-onboarding.ts
@@ -14,6 +14,7 @@ import { genClientId } from "home-assistant-js-websocket";
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
import { OnboardingStep, onboardUserStep } from "../data/onboarding";
import { PolymerChangedEvent } from "../polymer-types";
+import { registerServiceWorker } from "../util/register-service-worker";
@customElement("ha-onboarding")
class HaOnboarding extends litLocalizeLiteMixin(LitElement) {
@@ -122,14 +123,18 @@ class HaOnboarding extends litLocalizeLiteMixin(LitElement) {
`;
}
- protected async firstUpdated(changedProps: PropertyValues) {
+ protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);
this.addEventListener("keypress", (ev) => {
if (ev.keyCode === 13) {
this._submitForm();
}
});
+ this._fetchOnboardingSteps();
+ registerServiceWorker(false);
+ }
+ private async _fetchOnboardingSteps() {
try {
const response = await window.stepsPromise;
diff --git a/src/panels/config/zha/zha-device-card.ts b/src/panels/config/zha/zha-device-card.ts
index c37d3902d9..575f29704b 100644
--- a/src/panels/config/zha/zha-device-card.ts
+++ b/src/panels/config/zha/zha-device-card.ts
@@ -55,6 +55,7 @@ class ZHADeviceCard extends LitElement {
@property() private _serviceData?: NodeServiceData;
@property() private _areas: AreaRegistryEntry[] = [];
@property() private _selectedAreaIndex: number = -1;
+ @property() private _userGivenName?: string;
public firstUpdated(changedProperties: PropertyValues): void {
super.firstUpdated(changedProperties);
@@ -71,9 +72,15 @@ class ZHADeviceCard extends LitElement {
protected updated(changedProperties: PropertyValues): void {
if (changedProperties.has("device")) {
- this._selectedAreaIndex =
- this._areas.findIndex((area) => area.area_id === this.device!.area_id) +
- 1;
+ if (!this._areas || !this.device || !this.device.area_id) {
+ this._selectedAreaIndex = 0;
+ } else {
+ this._selectedAreaIndex =
+ this._areas.findIndex(
+ (area) => area.area_id === this.device!.area_id
+ ) + 1;
+ }
+ this._userGivenName = this.device!.user_given_name;
}
super.update(changedProperties);
}
@@ -150,6 +157,7 @@ class ZHADeviceCard extends LitElement {
void | undefined;
+ // Since navigate fires events on `window`, we need to expose this as a function
+ // to allow custom panels to forward their location changes to the main window
+ // instead of their iframe window.
+ public navigate = (path: string, replace?: boolean) =>
+ navigate(this, path, replace);
+
public registerIframe(initialize, setProperties) {
initialize(this.panel, {
hass: this.hass,
diff --git a/src/panels/lovelace/components/notifications/hui-notification-item-template.js b/src/panels/lovelace/components/notifications/hui-notification-item-template.js
deleted file mode 100644
index a7b091849a..0000000000
--- a/src/panels/lovelace/components/notifications/hui-notification-item-template.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import "@material/mwc-button";
-import "@polymer/paper-icon-button/paper-icon-button";
-
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-
-import "../../../../components/ha-card";
-
-export class HuiNotificationItemTemplate extends PolymerElement {
- static get template() {
- return html`
-
-
-
-
-
-
- `;
- }
-}
-customElements.define(
- "hui-notification-item-template",
- HuiNotificationItemTemplate
-);
diff --git a/src/panels/lovelace/components/notifications/hui-notification-item-template.ts b/src/panels/lovelace/components/notifications/hui-notification-item-template.ts
new file mode 100644
index 0000000000..5aa26648b7
--- /dev/null
+++ b/src/panels/lovelace/components/notifications/hui-notification-item-template.ts
@@ -0,0 +1,61 @@
+import {
+ html,
+ LitElement,
+ TemplateResult,
+ customElement,
+ css,
+ CSSResult,
+} from "lit-element";
+
+import "../../../../components/ha-card";
+
+@customElement("hui-notification-item-template")
+export class HuiNotificationItemTemplate extends LitElement {
+ protected render(): TemplateResult | void {
+ return html`
+
+
+
+
+
+ `;
+ }
+
+ static get styles(): CSSResult {
+ return css`
+ .contents {
+ padding: 16px;
+ }
+
+ ha-card .header {
+ /* start paper-font-headline style */
+ font-family: "Roboto", "Noto", sans-serif;
+ -webkit-font-smoothing: antialiased; /* OS X subpixel AA bleed bug */
+ text-rendering: optimizeLegibility;
+ font-size: 24px;
+ font-weight: 400;
+ letter-spacing: -0.012em;
+ line-height: 32px;
+ /* end paper-font-headline style */
+
+ color: var(--primary-text-color);
+ padding: 16px 16px 0;
+ }
+
+ .actions {
+ border-top: 1px solid #e8e8e8;
+ padding: 5px 16px;
+ }
+
+ ::slotted(.primary) {
+ color: var(--primary-color);
+ }
+ `;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-notification-item-template": HuiNotificationItemTemplate;
+ }
+}
diff --git a/src/util/register-service-worker.js b/src/util/register-service-worker.ts
similarity index 77%
rename from src/util/register-service-worker.js
rename to src/util/register-service-worker.ts
index c80eef58b8..9dfcf4b23a 100644
--- a/src/util/register-service-worker.js
+++ b/src/util/register-service-worker.ts
@@ -1,12 +1,20 @@
const serviceWorkerUrl =
__BUILD__ === "latest" ? "/service_worker.js" : "/service_worker_es5.js";
-export const registerServiceWorker = () => {
- if (!("serviceWorker" in navigator)) return;
+export const registerServiceWorker = (notifyUpdate = true) => {
+ if (
+ !("serviceWorker" in navigator) ||
+ (location.protocol !== "https:" && location.hostname !== "localhost")
+ ) {
+ return;
+ }
navigator.serviceWorker.register(serviceWorkerUrl).then((reg) => {
reg.addEventListener("updatefound", () => {
const installingWorker = reg.installing;
+ if (!installingWorker || !notifyUpdate) {
+ return;
+ }
installingWorker.addEventListener("statechange", () => {
if (
installingWorker.state === "installed" &&
diff --git a/translations/da.json b/translations/da.json
index 8a9c0b7b7c..719121aeb0 100644
--- a/translations/da.json
+++ b/translations/da.json
@@ -279,7 +279,8 @@
"state_badge": {
"default": {
"unknown": "Ukendt",
- "unavailable": "Utilgængelig"
+ "unavailable": "Utilgængelig",
+ "error": "Fejl"
},
"alarm_control_panel": {
"armed": "Tilkoblet",
@@ -608,6 +609,12 @@
"services": {
"reconfigure": "Genkonfigurer ZHA-enhed (helbred enhed). Brug dette hvis du har problemer med enheden. Hvis den pågældende enhed er en batteridrevet enhed skal du sørge for at den er vågen og accepterer kommandoer når du bruger denne service.",
"updateDeviceName": "Angiv et brugerdefineret navn til denne enhed i enhedsopsætningen"
+ },
+ "device_card": {
+ "area_picker_label": "Område"
+ },
+ "add_device_page": {
+ "spinner": "Søger efter ZHA Zigbee-enheder..."
}
},
"area_registry": {
@@ -1084,7 +1091,7 @@
"sun": {
"elevation": "Elevation",
"rising": "Solopgang",
- "setting": "Indstilling"
+ "setting": "Solnedgang"
},
"updater": {
"title": "Opdateringsvejledning"
diff --git a/translations/de.json b/translations/de.json
index 07831e73ea..1e38c315ff 100644
--- a/translations/de.json
+++ b/translations/de.json
@@ -279,7 +279,9 @@
"state_badge": {
"default": {
"unknown": "Unbek.",
- "unavailable": "N.v."
+ "unavailable": "N.v.",
+ "error": "Fehler",
+ "entity_not_found": "Entität nicht gefunden!"
},
"alarm_control_panel": {
"armed": "Aktiv",
@@ -608,6 +610,14 @@
"services": {
"reconfigure": "Rekonfiguriere ZHA-Gerät (Gerät heilen). Benutze dies, wenn du Probleme mit dem Gerät hast. Wenn es sich bei dem betroffenden Gerät um ein batteriebetriebenes Gerät handelt, stelle sicher dass es wach ist und Kommandos akzeptiert wenn du diesen Dienst benutzt.",
"updateDeviceName": "Lege einen benutzerdefinierten Namen für dieses Gerät in der Geräteregistrierung fest."
+ },
+ "device_card": {
+ "area_picker_label": "Bereich"
+ },
+ "add_device_page": {
+ "header": "Zigbee Home Automation - Geräte hinzufügen",
+ "spinner": "Suche nach ZHA Zigbee Geräten... ",
+ "discovery_text": "Erkannte Geräte werden hier angezeigt. Befolgen Sie die Anweisungen für Ihr Gerät und versetzen Sie das Gerät in den Pairing-Modus."
}
},
"area_registry": {
diff --git a/translations/en.json b/translations/en.json
index bdbd816093..332d959cdf 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -279,7 +279,9 @@
"state_badge": {
"default": {
"unknown": "Unk",
- "unavailable": "Unavai"
+ "unavailable": "Unavai",
+ "error": "Error",
+ "entity_not_found": "Entity Not Found"
},
"alarm_control_panel": {
"armed": "Armed",
@@ -607,7 +609,18 @@
"description": "Zigbee Home Automation network management",
"services": {
"reconfigure": "Reconfigure ZHA device (heal device). Use this if you are having issues with the device. If the device in question is a battery powered device please ensure it is awake and accepting commands when you use this service.",
- "updateDeviceName": "Set a custom name for this device in the device registry."
+ "updateDeviceName": "Set a custom name for this device in the device registry.",
+ "remove": "Remove a device from the ZigBee network."
+ },
+ "device_card": {
+ "device_name_placeholder": "User given name",
+ "area_picker_label": "Area",
+ "update_name_button": "Update Name"
+ },
+ "add_device_page": {
+ "header": "Zigbee Home Automation - Add Devices",
+ "spinner": "Searching for ZHA Zigbee devices...",
+ "discovery_text": "Discovered devices will show up here. Follow the instructions for your device(s) and place the device(s) in pairing mode."
}
},
"area_registry": {
diff --git a/translations/ko.json b/translations/ko.json
index dc3482770f..6465ec7bcd 100644
--- a/translations/ko.json
+++ b/translations/ko.json
@@ -259,7 +259,7 @@
"vacuum": {
"cleaning": "청소중",
"docked": "충전중",
- "error": "작동 에러",
+ "error": "작동 오류",
"idle": "대기중",
"off": "꺼짐",
"on": "켜짐",
@@ -279,7 +279,9 @@
"state_badge": {
"default": {
"unknown": "알수없음",
- "unavailable": "사용불가"
+ "unavailable": "사용불가",
+ "error": "오류",
+ "entity_not_found": "구성요소를 찾을 수 없음"
},
"alarm_control_panel": {
"armed": "경비중",
@@ -607,7 +609,18 @@
"description": "Zigbee 홈 자동화 네트워크 관리",
"services": {
"reconfigure": "ZHA 장치를 다시 구성 합니다. (장치 복구). 장치에 문제가 있는 경우 사용해주세요. 장치가 배터리로 작동하는 경우, 이 서비스를 사용할 때 장치가 켜져있고 통신이 가능한 상태인지 확인해주세요.",
- "updateDeviceName": "이 장치의 사용자 정의 이름을 장치 레지스트리에 설정합니다."
+ "updateDeviceName": "이 장치의 사용자 정의 이름을 장치 레지스트리에 설정합니다.",
+ "remove": "ZigBee 네트워크에서 기기 제거"
+ },
+ "device_card": {
+ "device_name_placeholder": "사용자 지정 이름",
+ "area_picker_label": "영역",
+ "update_name_button": "이름 업데이트"
+ },
+ "add_device_page": {
+ "header": "Zigbee 홈 자동화 - 기기 추가",
+ "spinner": "ZHA Zigbee 기기를 찾고있습니다...",
+ "discovery_text": "발견된 기기가 여기에 표시됩니다. 기기의 설명서를 참고하여 기기를 페어링 모드로 설정해주세요."
}
},
"area_registry": {
diff --git a/translations/nb.json b/translations/nb.json
index 6a31ca5d9d..9eb06cb052 100644
--- a/translations/nb.json
+++ b/translations/nb.json
@@ -257,14 +257,14 @@
"windy-variant": "Vind"
},
"vacuum": {
- "cleaning": "Rengjøring",
+ "cleaning": "Rengjør",
"docked": "Dokket",
"error": "Feil",
- "idle": "Ledig",
+ "idle": "Inaktiv",
"off": "Av",
"on": "På",
"paused": "Pauset",
- "returning": "Returner til dokken"
+ "returning": "Returner til dokk"
},
"timer": {
"active": "aktiv",
diff --git a/translations/nl.json b/translations/nl.json
index 2ebeb3d665..3727702b03 100644
--- a/translations/nl.json
+++ b/translations/nl.json
@@ -1094,7 +1094,7 @@
"auth_store": {
"ask": "Wilt u de inloggegevens opslaan?",
"decline": "Nee, bedankt",
- "confirm": "Bewaar inloggegevens"
+ "confirm": "Login opslaan"
},
"notification_drawer": {
"click_to_configure": "Klik op de knop om {entity} te configureren",
diff --git a/translations/pl.json b/translations/pl.json
index 74fa7f521d..1aa07b97ab 100644
--- a/translations/pl.json
+++ b/translations/pl.json
@@ -279,7 +279,9 @@
"state_badge": {
"default": {
"unknown": "niezn",
- "unavailable": "niedos"
+ "unavailable": "niedos",
+ "error": "błąd",
+ "entity_not_found": "brak"
},
"alarm_control_panel": {
"armed": "uzbr",
@@ -604,10 +606,21 @@
},
"zha": {
"caption": "ZHA",
- "description": "Zarządzanie siecią automatyki domowej ZigBee",
+ "description": "Zarządzanie siecią automatyki domowej Zigbee",
"services": {
"reconfigure": "Ponowna konfiguracja urządzenia ZHA (uzdrawianie urządzenia). Użyj tej usługi, jeśli masz problemy z urządzeniem. Jeśli urządzenie jest zasilane bateryjnie, upewnij się, że nie jest uśpione i przyjmie polecenie rekonfiguracji.",
- "updateDeviceName": "Ustaw niestandardową nazwę tego urządzenia w rejestrze urządzeń."
+ "updateDeviceName": "Ustaw niestandardową nazwę tego urządzenia w rejestrze urządzeń.",
+ "remove": "Usuń urządzenie z sieci Zigbee."
+ },
+ "device_card": {
+ "device_name_placeholder": "Nazwa użytkownika",
+ "area_picker_label": "Obszar",
+ "update_name_button": "Aktualizuj nazwę"
+ },
+ "add_device_page": {
+ "header": "Zigbee Home Automation - Dodaj urządzenia",
+ "spinner": "Wyszukiwanie urządzeń ZHA Zigbee...",
+ "discovery_text": "Wykryte urządzenia pojawią się tutaj. Postępuj zgodnie z instrukcjami dla urządzeń, by wprowadzić je w tryb parowania."
}
},
"area_registry": {
diff --git a/translations/pt.json b/translations/pt.json
index c804d15f28..054cde24c9 100644
--- a/translations/pt.json
+++ b/translations/pt.json
@@ -461,7 +461,8 @@
"enter": "Entrar",
"leave": "Sair"
}
- }
+ },
+ "learn_more": "Saber mais sobre gatilhos"
},
"conditions": {
"header": "Condições",
@@ -605,7 +606,8 @@
"caption": "ZHA",
"description": "Gestão de rede Zigbee Home Automation",
"services": {
- "reconfigure": "Reconfigure o dispositivo ZHA (curar dispositivo). Use isto se estiver a ter problemas com o dispositivo. Se o dispositivo em questão for um dispositivo alimentado por bateria, certifique-se de que ele está ativo e a aceitar comandos ao usar este serviço."
+ "reconfigure": "Reconfigure o dispositivo ZHA (curar dispositivo). Use isto se estiver a ter problemas com o dispositivo. Se o dispositivo em questão for um dispositivo alimentado por bateria, certifique-se de que ele está ativo e a aceitar comandos ao usar este serviço.",
+ "updateDeviceName": "Definir um nome personalizado para este dispositivo no registo do dispositivo."
}
},
"area_registry": {
@@ -613,7 +615,10 @@
"description": "Visão geral de todas as áreas da sua casa.",
"picker": {
"header": "Registo de áreas",
+ "introduction": "Áreas são usadas para organizar os dispositivos. Essas informações serão usadas no Home Assistant para ajudá-lo a organizar sua interface, permissões e integrações com outros sistemas.",
+ "introduction2": "Para colocar dispositivos em uma área, use o link abaixo para navegar até a página de integrações e, em seguida, clique em uma integração configurada para acessar os cartões de dispositivos.",
"integrations_page": "Página de Integrações",
+ "no_areas": "Parece que ainda não tem áreas!",
"create_area": "CRIAR ÁREA"
},
"no_areas": "Parece que ainda não tem áreas!",
@@ -631,6 +636,8 @@
"picker": {
"header": "Registo de Entidades",
"unavailable": "(indisponível)",
+ "introduction": "O Home Assistant mantém um registro de todas as entidades que já viu e que podem ser identificadas exclusivamente. Cada uma dessas entidades terá um ID de entidade atribuído, que será reservado apenas para essa entidade.",
+ "introduction2": "Use o registo da entidade para substituir o nome, alterar o ID da entidade ou remover a entrada do Assistente Inicial. Observe que a remoção da entrada do registo de entidade não removerá a entidade. Para fazer isso, siga o link abaixo e remova-o da página de integrações.",
"integrations_page": "Página de Integrações"
},
"editor": {
@@ -895,6 +902,10 @@
"unused_entities": "Entidades não utilizadas",
"help": "Ajuda",
"refresh": "Atualizar"
+ },
+ "warning": {
+ "entity_not_found": "Entidade indisponível",
+ "entity_non_numeric": "Entidade é não numérica"
}
}
},
@@ -1153,6 +1164,7 @@
},
"groups": {
"system-admin": "Administradores",
- "system-users": "Utilizadores"
+ "system-users": "Utilizadores",
+ "system-read-only": "Utilizadores somente de leitura"
}
}
\ No newline at end of file
diff --git a/translations/ru.json b/translations/ru.json
index 1fac4cec95..480c2ed2d1 100644
--- a/translations/ru.json
+++ b/translations/ru.json
@@ -279,7 +279,9 @@
"state_badge": {
"default": {
"unknown": "Неизв.",
- "unavailable": "Недоступно"
+ "unavailable": "Недоступно",
+ "error": "Ошибка",
+ "entity_not_found": "Объект не найден"
},
"alarm_control_panel": {
"armed": "Охрана",
@@ -607,7 +609,18 @@
"description": "Управляйте сетью Zigbee Home Automation",
"services": {
"reconfigure": "Перенастройка устройства ZHA. Используйте эту службу, если у Вас есть проблемы с устройством. Если рассматриваемое устройство работает от батареи, пожалуйста, убедитесь, что оно не находится в режиме сна и принимает команды, когда вы запускаете эту службу.",
- "updateDeviceName": "Установите имя для этого устройства в реестре устройств."
+ "updateDeviceName": "Установите имя для этого устройства в реестре устройств.",
+ "remove": "Удалить устройство из сети ZigBee."
+ },
+ "device_card": {
+ "device_name_placeholder": "Название",
+ "area_picker_label": "Помещение",
+ "update_name_button": "Обновить название"
+ },
+ "add_device_page": {
+ "header": "Zigbee Home Automation",
+ "spinner": "Поиск Zigbee устройств...",
+ "discovery_text": "Здесь будут отображаться обнаруженные устройства. Следуйте инструкциям для Вашего устройства, чтобы включить режим сопряжения."
}
},
"area_registry": {