diff --git a/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts b/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts index d6ea47f34c..e934bced92 100755 --- a/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts +++ b/hassio/src/dialogs/snapshot/dialog-hassio-snapshot.ts @@ -4,6 +4,7 @@ import { mdiDotsVertical } from "@mdi/js"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { fireEvent } from "../../../../src/common/dom/fire_event"; +import { slugify } from "../../../../src/common/string/slugify"; import "../../../../src/components/buttons/ha-progress-button"; import "../../../../src/components/ha-button-menu"; import { createCloseHeading } from "../../../../src/components/ha-dialog"; @@ -287,10 +288,9 @@ class HassioSnapshotDialog } } - const name = this._computeName.replace(/[^a-z0-9]+/gi, "_"); const a = document.createElement("a"); a.href = signedPath.path; - a.download = `Hass_io_${name}.tar`; + a.download = `home_assistant_snapshot_${slugify(this._computeName)}.tar`; this.shadowRoot!.appendChild(a); a.click(); this.shadowRoot!.removeChild(a); diff --git a/hassio/src/hassio-main.ts b/hassio/src/hassio-main.ts index 280654bf7d..e4a777c664 100644 --- a/hassio/src/hassio-main.ts +++ b/hassio/src/hassio-main.ts @@ -103,27 +103,25 @@ export class HassioMain extends SupervisorBaseElement { private _applyTheme() { let themeName: string; - let themeSettings: - | Partial - | undefined; + let themeSettings: Partial | undefined; if (atLeastVersion(this.hass.config.version, 0, 114)) { themeName = - this.hass.selectedThemeSettings?.theme || + this.hass.selectedTheme?.theme || (this.hass.themes.darkMode && this.hass.themes.default_dark_theme ? this.hass.themes.default_dark_theme! : this.hass.themes.default_theme); - themeSettings = this.hass.selectedThemeSettings; + themeSettings = this.hass.selectedTheme; if (themeSettings?.dark === undefined) { themeSettings = { - ...this.hass.selectedThemeSettings, + ...this.hass.selectedTheme, dark: this.hass.themes.darkMode, }; } } else { themeName = - ((this.hass.selectedThemeSettings as unknown) as string) || + ((this.hass.selectedTheme as unknown) as string) || this.hass.themes.default_theme; } diff --git a/setup.py b/setup.py index 152002c007..311519d4e2 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20210526.0", + version="20210528.0", description="The Home Assistant frontend", url="https://github.com/home-assistant/home-assistant-polymer", author="The Home Assistant Authors", diff --git a/src/common/dom/apply_themes_on_element.ts b/src/common/dom/apply_themes_on_element.ts index 90143f9bcf..3f647f6a40 100644 --- a/src/common/dom/apply_themes_on_element.ts +++ b/src/common/dom/apply_themes_on_element.ts @@ -31,7 +31,7 @@ export const applyThemesOnElement = ( element, themes: HomeAssistant["themes"], selectedTheme?: string, - themeSettings?: Partial + themeSettings?: Partial ) => { let cacheKey = selectedTheme; let themeRules: Partial = {}; diff --git a/src/common/util/promise-timeout.ts b/src/common/util/promise-timeout.ts new file mode 100644 index 0000000000..b26e8ba4b8 --- /dev/null +++ b/src/common/util/promise-timeout.ts @@ -0,0 +1,10 @@ +export const promiseTimeout = (ms: number, promise: Promise) => { + const timeout = new Promise((_resolve, reject) => { + setTimeout(() => { + reject(`Timed out in ${ms} ms.`); + }, ms); + }); + + // Returns a race between our timeout and the passed in promise + return Promise.race([promise, timeout]); +}; diff --git a/src/components/ha-icon.ts b/src/components/ha-icon.ts index 73563d26f6..7fea1da222 100644 --- a/src/components/ha-icon.ts +++ b/src/components/ha-icon.ts @@ -125,6 +125,7 @@ export class HaIcon extends LitElement { databaseIcon = await getIcon(iconName); } catch (_err) { // Firefox in private mode doesn't support IDB + // iOS Safari sometimes doesn't open the DB databaseIcon = undefined; } diff --git a/src/components/state-history-chart-line.js b/src/components/state-history-chart-line.js index b74f3feebd..412ca18e75 100644 --- a/src/components/state-history-chart-line.js +++ b/src/components/state-history-chart-line.js @@ -377,6 +377,7 @@ class StateHistoryChartLine extends LocalizeMixin(PolymerElement) { major: { fontStyle: "bold", }, + autoSkipPadding: 20, }, }, ], diff --git a/src/components/state-history-chart-timeline.js b/src/components/state-history-chart-timeline.js index 816425aa25..23f0a91e7d 100644 --- a/src/components/state-history-chart-timeline.js +++ b/src/components/state-history-chart-timeline.js @@ -236,10 +236,13 @@ class StateHistoryChartTimeline extends LocalizeMixin(PolymerElement) { major: { fontStyle: "bold", }, + autoSkipPadding: 50, }, categoryPercentage: undefined, barPercentage: undefined, - time: { format: undefined }, + time: { + format: undefined, + }, }, ], yAxes: [ diff --git a/src/data/iconsets.ts b/src/data/iconsets.ts index 8b92ddbfa3..debfcea7e2 100644 --- a/src/data/iconsets.ts +++ b/src/data/iconsets.ts @@ -1,4 +1,5 @@ -import { clear, get, set, createStore } from "idb-keyval"; +import { clear, get, set, createStore, promisifyRequest } from "idb-keyval"; +import { promiseTimeout } from "../common/util/promise-timeout"; import { iconMetadata } from "../resources/icon-metadata"; import { IconMeta } from "../types"; @@ -14,33 +15,34 @@ export const iconStore = createStore("hass-icon-db", "mdi-icon-store"); export const MDI_PREFIXES = ["mdi", "hass", "hassio", "hademo"]; -let toRead: Array<[string, (iconPath: string) => void, () => void]> = []; +let toRead: Array< + [string, (iconPath: string | undefined) => void, (e: any) => void] +> = []; // Queue up as many icon fetches in 1 transaction export const getIcon = (iconName: string) => - new Promise((resolve, reject) => { + new Promise((resolve, reject) => { toRead.push([iconName, resolve, reject]); if (toRead.length > 1) { return; } - const results: Array<[(iconPath: string) => void, IDBRequest]> = []; - - iconStore("readonly", (store) => { - for (const [iconName_, resolve_] of toRead) { - results.push([resolve_, store.get(iconName_)]); - } - }) - .then(() => { - for (const [resolve_, request] of results) { - resolve_(request.result); + promiseTimeout( + 1000, + iconStore("readonly", (store) => { + for (const [iconName_, resolve_, reject_] of toRead) { + promisifyRequest(store.get(iconName_)) + .then((icon) => resolve_(icon)) + .catch((e) => reject_(e)); } }) - .catch(() => { + ) + .catch((e) => { // Firefox in private mode doesn't support IDB + // Safari sometime doesn't open the DB so we time out for (const [, , reject_] of toRead) { - reject_(); + reject_(e); } }) .finally(() => { diff --git a/src/fake_data/provide_hass.ts b/src/fake_data/provide_hass.ts index d074f4c9ab..d537ffa80e 100644 --- a/src/fake_data/provide_hass.ts +++ b/src/fake_data/provide_hass.ts @@ -277,7 +277,7 @@ export const provideHass = ( mockTheme(theme) { invalidateThemeCache(); hass().updateHass({ - selectedThemeSettings: { theme: theme ? "mock" : "default" }, + selectedTheme: { theme: theme ? "mock" : "default" }, themes: { ...hass().themes, themes: { @@ -285,11 +285,11 @@ export const provideHass = ( }, }, }); - const { themes, selectedThemeSettings } = hass(); + const { themes, selectedTheme } = hass(); applyThemesOnElement( document.documentElement, themes, - selectedThemeSettings!.theme + selectedTheme!.theme ); }, diff --git a/src/layouts/supervisor-error-screen.ts b/src/layouts/supervisor-error-screen.ts index 29bafefbc8..0138793b2e 100644 --- a/src/layouts/supervisor-error-screen.ts +++ b/src/layouts/supervisor-error-screen.ts @@ -81,27 +81,25 @@ class SupervisorErrorScreen extends LitElement { private _applyTheme() { let themeName: string; - let themeSettings: - | Partial - | undefined; + let themeSettings: Partial | undefined; if (atLeastVersion(this.hass.config.version, 0, 114)) { themeName = - this.hass.selectedThemeSettings?.theme || + this.hass.selectedTheme?.theme || (this.hass.themes.darkMode && this.hass.themes.default_dark_theme ? this.hass.themes.default_dark_theme! : this.hass.themes.default_theme); - themeSettings = this.hass.selectedThemeSettings; + themeSettings = this.hass.selectedTheme; if (themeName === "default" && themeSettings?.dark === undefined) { themeSettings = { - ...this.hass.selectedThemeSettings, + ...this.hass.selectedTheme, dark: this.hass.themes.darkMode, }; } } else { themeName = - ((this.hass.selectedThemeSettings as unknown) as string) || + ((this.hass.selectedTheme as unknown) as string) || this.hass.themes.default_theme; } diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index e7f0943f3a..53b3394483 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -152,7 +152,7 @@ export class HUIView extends ReactiveElement { changedProperties.has("hass") && (!oldHass || this.hass.themes !== oldHass.themes || - this.hass.selectedThemeSettings !== oldHass.selectedThemeSettings) + this.hass.selectedTheme !== oldHass.selectedTheme) ) { applyThemesOnElement(this, this.hass.themes, this._viewConfigTheme); } diff --git a/src/panels/profile/ha-pick-theme-row.ts b/src/panels/profile/ha-pick-theme-row.ts index 32c89b373d..7043281d87 100644 --- a/src/panels/profile/ha-pick-theme-row.ts +++ b/src/panels/profile/ha-pick-theme-row.ts @@ -41,9 +41,9 @@ export class HaPickThemeRow extends LitElement { const hasThemes = this.hass.themes.themes && Object.keys(this.hass.themes.themes).length; const curTheme = - this.hass.selectedThemeSettings?.theme || this.hass.themes.default_theme; + this.hass.selectedTheme?.theme || this.hass.themes.default_theme; - const themeSettings = this.hass.selectedThemeSettings; + const themeSettings = this.hass.selectedTheme; return html` @@ -162,8 +162,7 @@ export class HaPickThemeRow extends LitElement { (!oldHass || oldHass.themes.themes !== this.hass.themes.themes); const selectedThemeChanged = changedProperties.has("hass") && - (!oldHass || - oldHass.selectedThemeSettings !== this.hass.selectedThemeSettings); + (!oldHass || oldHass.selectedTheme !== this.hass.selectedTheme); if (themesChanged) { this._themeNames = ["Backend-selected", "default"].concat( @@ -173,16 +172,16 @@ export class HaPickThemeRow extends LitElement { if (selectedThemeChanged) { if ( - this.hass.selectedThemeSettings && - this._themeNames.indexOf(this.hass.selectedThemeSettings.theme) > 0 + this.hass.selectedTheme && + this._themeNames.indexOf(this.hass.selectedTheme.theme) > 0 ) { this._selectedThemeIndex = this._themeNames.indexOf( - this.hass.selectedThemeSettings.theme + this.hass.selectedTheme.theme ); this._selectedTheme = this.hass.themes.themes[ - this.hass.selectedThemeSettings.theme + this.hass.selectedTheme.theme ]; - } else if (!this.hass.selectedThemeSettings) { + } else if (!this.hass.selectedTheme) { this._selectedThemeIndex = 0; } } @@ -220,7 +219,7 @@ export class HaPickThemeRow extends LitElement { private _handleThemeSelection(ev: CustomEvent) { const theme = ev.detail.item.theme; if (theme === "Backend-selected") { - if (this.hass.selectedThemeSettings?.theme) { + if (this.hass.selectedTheme?.theme) { fireEvent(this, "settheme", { theme: "", primaryColor: undefined, diff --git a/src/state/connection-mixin.ts b/src/state/connection-mixin.ts index bfe4617020..07e34ad80e 100644 --- a/src/state/connection-mixin.ts +++ b/src/state/connection-mixin.ts @@ -39,7 +39,7 @@ export const connectionMixin = >( states: null as any, config: null as any, themes: null as any, - selectedThemeSettings: null, + selectedTheme: null, panels: null as any, services: null as any, user: null as any, diff --git a/src/state/themes-mixin.ts b/src/state/themes-mixin.ts index 9ef9778014..efce598882 100644 --- a/src/state/themes-mixin.ts +++ b/src/state/themes-mixin.ts @@ -11,10 +11,10 @@ import { HassBaseEl } from "./hass-base-mixin"; declare global { // for add event listener interface HTMLElementEventMap { - settheme: HASSDomEvent>; + settheme: HASSDomEvent>; } interface HASSDomEvents { - settheme: Partial; + settheme: Partial; } } @@ -28,8 +28,8 @@ export default >(superClass: T) => super.firstUpdated(changedProps); this.addEventListener("settheme", (ev) => { this._updateHass({ - selectedThemeSettings: { - ...this.hass!.selectedThemeSettings!, + selectedTheme: { + ...this.hass!.selectedTheme!, ...ev.detail, }, }); @@ -68,8 +68,8 @@ export default >(superClass: T) => return; } - let themeSettings: Partial = this - .hass!.selectedThemeSettings; + let themeSettings: Partial = this.hass! + .selectedTheme; const themeName = themeSettings?.theme || @@ -89,7 +89,7 @@ export default >(superClass: T) => darkMode = false; } - themeSettings = { ...this.hass.selectedThemeSettings, dark: darkMode }; + themeSettings = { ...this.hass.selectedTheme, dark: darkMode }; applyThemesOnElement( document.documentElement, diff --git a/src/types.ts b/src/types.ts index 2cb1af3337..9f10eff84c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -194,7 +194,7 @@ export interface HomeAssistant { services: HassServices; config: HassConfig; themes: Themes; - selectedThemeSettings: ThemeSettings | null; + selectedTheme: ThemeSettings | null; panels: Panels; panelUrl: string; // i18n diff --git a/src/util/ha-pref-storage.ts b/src/util/ha-pref-storage.ts index 086e8f7c46..8c21de00b7 100644 --- a/src/util/ha-pref-storage.ts +++ b/src/util/ha-pref-storage.ts @@ -2,16 +2,13 @@ import { HomeAssistant } from "../types"; const STORED_STATE = [ "dockedSidebar", - "selectedThemeSettings", + "selectedTheme", "selectedLanguage", "vibrate", "suspendWhenHidden", "enableShortcuts", "defaultPanel", ]; -// Deprecated states will be loaded once so that the values can be migrated to other states if required, -// but during the next state storing, the deprecated keys will be removed. -const STORED_STATE_DEPRECATED = ["selectedTheme"]; const STORAGE = window.localStorage || {}; export function storeState(hass: HomeAssistant) { @@ -20,9 +17,6 @@ export function storeState(hass: HomeAssistant) { const value = hass[key]; STORAGE[key] = JSON.stringify(value === undefined ? null : value); }); - STORED_STATE_DEPRECATED.forEach((key) => { - if (key in STORAGE) delete STORAGE[key]; - }); } catch (err) { // Safari throws exception in private mode } @@ -31,17 +25,13 @@ export function storeState(hass: HomeAssistant) { export function getState() { const state = {}; - STORED_STATE.concat(STORED_STATE_DEPRECATED).forEach((key) => { + STORED_STATE.forEach((key) => { if (key in STORAGE) { let value = JSON.parse(STORAGE[key]); // selectedTheme went from string to object on 20200718 if (key === "selectedTheme" && typeof value === "string") { value = { theme: value }; } - // selectedTheme was renamed to selectedThemeSettings on 20210207 - if (key === "selectedTheme") { - key = "selectedThemeSettings"; - } // dockedSidebar went from boolean to enum on 20190720 if (key === "dockedSidebar" && typeof value === "boolean") { value = value ? "docked" : "auto"; diff --git a/src/util/hass-attributes-util.ts b/src/util/hass-attributes-util.ts index 0e991b0fa5..7a9bc9c232 100644 --- a/src/util/hass-attributes-util.ts +++ b/src/util/hass-attributes-util.ts @@ -101,6 +101,7 @@ hassAttributeUtil.LOGIC_STATE_ATTRIBUTES = { supported_features: undefined, attribution: undefined, restored: undefined, + editable: undefined, custom_ui_more_info: { type: "string" }, custom_ui_state_card: { type: "string" }, device_class: { @@ -109,6 +110,13 @@ hassAttributeUtil.LOGIC_STATE_ATTRIBUTES = { description: "Device class", domains: ["binary_sensor", "cover", "humidifier", "sensor", "switch"], }, + state_class: { + type: "array", + options: { sensor: ["measurement"] }, + description: "State class", + domains: ["sensor"], + }, + last_reset: undefined, assumed_state: { type: "boolean", domains: [ diff --git a/translations/frontend/ca.json b/translations/frontend/ca.json index a62762e1bb..9ca6e802d6 100644 --- a/translations/frontend/ca.json +++ b/translations/frontend/ca.json @@ -292,7 +292,7 @@ "save": "Desa", "show_more": "Mostra més informació al respecte", "update": "Actualitza", - "update_available": "{count, plural,\n one {Actualització pendent}\n other {{count} Actualitzacions pendents}\n}", + "update_available": "{count, plural,\n one {Actualització pendent}\n other {{count} actualitzacions pendents}\n}", "version": "Versió", "yes": "Sí" }, @@ -314,7 +314,7 @@ "addon_new_version": "Nova versió disponible", "addon_running": "El complement s'està executant", "addon_stopped": "El complement està aturat", - "addons": "Complements", + "addons": "Complements instal·lats", "no_addons": "Encara no tens cap complement instal·lat. Vés al directori de complements per començar!" }, "dialog": { @@ -396,14 +396,15 @@ }, "folders": "Carpetes", "full_snapshot": "Instantània completa", - "name": "Nom", + "name": "Nom de la instantània", "no_snapshots": "Encara no tens instantànies.", "partial_snapshot": "Instantània parcial", - "password": "Contrasenya", + "password": "Contrasenya de la instantània", "password_protected": "protegit amb contrasenya", "password_protection": "Protecció amb contrasenya", "security": "Seguretat", - "type": "Tipus", + "select_type": "Selecciona què vols restaurar", + "type": "Tipus d'instantània", "upload_snapshot": "Puja instantània" }, "store": { @@ -720,6 +721,9 @@ "no_match": "No s'han trobat àrees coincidents", "show_areas": "Mostra àrees" }, + "attributes": { + "expansion_header": "Atributs" + }, "blueprint-picker": { "add_user": "Afegeix usuari", "remove_user": "Elimina usuari", @@ -1719,6 +1723,7 @@ "title": "Alexa" }, "connected": "Connectat", + "connecting": "Connectant...", "connection_status": "Estat de connexió amb Cloud", "fetching_subscription": "Obtenint subscripció...", "google": { @@ -2959,6 +2964,7 @@ }, "logs": { "log_level": "Nivell dels registres", + "log_level_changed": "Nivell de registre canviat a: {level}", "subscribed_to_logs": "Subscrit a missatges de registre Z-Wave JS...", "title": "Registres de Z-Wave JS" }, diff --git a/translations/frontend/cs.json b/translations/frontend/cs.json index 9278395619..f093bf9861 100644 --- a/translations/frontend/cs.json +++ b/translations/frontend/cs.json @@ -292,7 +292,7 @@ "save": "Uložit", "show_more": "Zobrazit o tom více informací", "update": "Aktualizovat", - "update_available": "{count, plural,\n one {Aktualizace}\n few {{count} aktualizace}\n other {{count} aktualizací}\n}", + "update_available": "{count, plural,\n one {Čekající aktualizace}\n few {{count} čekající aktualizace}\n other {{count} čekajících aktualizací}\n}", "version": "Verze", "yes": "Ano" }, @@ -314,7 +314,7 @@ "addon_new_version": "K dispozici je nová verze", "addon_running": "Doplněk je spuštěn", "addon_stopped": "Doplněk je zastaven", - "addons": "Doplňky", + "addons": "Nainstalované doplňky", "no_addons": "Zatím nemáte nainstalované žádné doplňky. Chcete-li začít, přejděte do obchodu s doplňky." }, "dialog": { @@ -396,14 +396,15 @@ }, "folders": "Složky", "full_snapshot": "Úplná záloha", - "name": "Název", + "name": "Název zálohy", "no_snapshots": "Zatím nemáte žádné zálohy.", "partial_snapshot": "Částečná záloha", - "password": "Heslo", + "password": "Heslo zálohy", "password_protected": "chráněno heslem", "password_protection": "Ochrana heslem", "security": "Zabezpečení", - "type": "Typ", + "select_type": "Vyberte, co chcete obnovit", + "type": "Typ zálohy", "upload_snapshot": "Nahrát zálohu" }, "store": { @@ -720,6 +721,9 @@ "no_match": "Nebyly nalezeny žádné odpovídající oblasti", "show_areas": "Zobrazit oblasti" }, + "attributes": { + "expansion_header": "Atributy" + }, "blueprint-picker": { "add_user": "Přidat uživatele", "remove_user": "Odebrat uživatele", @@ -1719,6 +1723,7 @@ "title": "Alexa" }, "connected": "Připojeno", + "connecting": "Připojování...", "connection_status": "Stav cloudového připojení", "fetching_subscription": "Načítání předplatného ...", "google": { @@ -2956,6 +2961,7 @@ }, "logs": { "log_level": "Úroveň protokolu", + "log_level_changed": "Úroveň protokolu změněna na: {level}", "title": "Z-Wave JS protokoly" }, "navigation": { diff --git a/translations/frontend/fa.json b/translations/frontend/fa.json index d6647a2f35..b2e67f6c47 100644 --- a/translations/frontend/fa.json +++ b/translations/frontend/fa.json @@ -45,6 +45,7 @@ "away": "بیرون", "boost": "افزایش", "comfort": "آسایش", + "eco": "اکو", "home": "خانه", "none": "هیچ کدام", "sleep": "خواب" @@ -100,6 +101,27 @@ } }, "supervisor": { + "addon": { + "configuration": { + "audio": { + "default": "پیش فرض", + "header": "صوتی", + "input": "ورودی", + "output": "خروجی" + }, + "network": { + "disabled": "غیر فعال", + "header": "شبکه", + "host": "میزبان" + }, + "options": { + "edit_in_ui": "ویرایش در رابط کاربری", + "edit_in_yaml": "ویرایش در YAML", + "header": "تنظیمات", + "show_unused_optional": "گزینه های پیکربندی اختیاری استفاده نشده را نشان دهید" + } + } + }, "common": { "close": "بستن" } diff --git a/translations/frontend/ko.json b/translations/frontend/ko.json index a5e21b946d..066fd0a1ea 100644 --- a/translations/frontend/ko.json +++ b/translations/frontend/ko.json @@ -403,6 +403,7 @@ "password_protected": "비밀번호로 보호됨", "password_protection": "비밀번호 보호", "security": "보안", + "select_type": "복원 할 항목 선택", "type": "유형", "upload_snapshot": "스냅숏 올리기" }, @@ -720,6 +721,9 @@ "no_match": "일치하는 영역을 찾을 수 없습니다", "show_areas": "영역 표시하기" }, + "attributes": { + "expansion_header": "속성" + }, "blueprint-picker": { "add_user": "사용자 추가하기", "remove_user": "사용자 제거하기", @@ -1719,6 +1723,7 @@ "title": "Alexa" }, "connected": "연결됨", + "connecting": "연결 중 ...", "connection_status": "클라우드 연결 상태", "fetching_subscription": "구독 정보를 가져오는 중…", "google": { @@ -2959,6 +2964,7 @@ }, "logs": { "log_level": "로그 레벨", + "log_level_changed": "로그 레벨이 변경되었습니다: {level}", "subscribed_to_logs": "Z-Wave JS 로그 메시지 수신 ...", "title": "Z-Wave JS 로그" }, diff --git a/translations/frontend/nl.json b/translations/frontend/nl.json index 6cf8313968..ef4ac76756 100644 --- a/translations/frontend/nl.json +++ b/translations/frontend/nl.json @@ -314,7 +314,7 @@ "addon_new_version": "Nieuwe versie beschikbaar", "addon_running": "Add-on wordt uitgevoerd", "addon_stopped": "Add-on is gestopt", - "addons": "Add-ons", + "addons": "Geïnstalleerde add-ons", "no_addons": "Je hebt nog geen add-ons geïnstalleerd. Ga naar de add-on store om te beginnen!" }, "dialog": { @@ -396,14 +396,15 @@ }, "folders": "Mappen", "full_snapshot": "Volledige snapshot", - "name": "Naam", + "name": "Snapshot naam", "no_snapshots": "Je hebt nog geen snapshots.", "partial_snapshot": "Gedeeltelijke snapshot", - "password": "Wachtwoord", + "password": "Snapshot wachtwoord", "password_protected": "beveiligd met wachtwoord", "password_protection": "Wachtwoord bescherming", "security": "Beveiliging", - "type": "Type", + "select_type": "Selecteer wat u wilt herstellen", + "type": "Snapshot type", "upload_snapshot": "Upload snapshot" }, "store": { @@ -720,6 +721,9 @@ "no_match": "Geen overeenkomende gebieden gevonden", "show_areas": "Toon gebieden" }, + "attributes": { + "expansion_header": "Attributen" + }, "blueprint-picker": { "add_user": "Gebruiker toevoegen", "remove_user": "Gebruiker verwijderen", @@ -1719,6 +1723,7 @@ "title": "Alexa" }, "connected": "Verbonden", + "connecting": "Verbinden...", "connection_status": "Cloud verbindingsstatus", "fetching_subscription": "Abonnement ophalen...", "google": { @@ -2959,6 +2964,7 @@ }, "logs": { "log_level": "Log niveau", + "log_level_changed": "Logboekniveau gewijzigd in: {level}", "subscribed_to_logs": "Geabonneerd op Z-Wave JS log berichten ...", "title": "Z-Wave JS Logs" }, diff --git a/translations/frontend/pl.json b/translations/frontend/pl.json index 13ee90347d..9a208016a5 100644 --- a/translations/frontend/pl.json +++ b/translations/frontend/pl.json @@ -396,14 +396,15 @@ }, "folders": "Foldery", "full_snapshot": "Pełny snapshot", - "name": "Nazwa", + "name": "Nazwa snapshota", "no_snapshots": "Nie masz jeszcze żadnych snapshotów.", "partial_snapshot": "Częściowy snapshot", - "password": "Hasło", + "password": "Hasło snapshota", "password_protected": "chroniony hasłem", "password_protection": "Ochrona hasłem", "security": "Bezpieczeństwo", - "type": "Typ", + "select_type": "Wybierz, co przywrócić", + "type": "Typ snapshota", "upload_snapshot": "Prześlij snapshota" }, "store": { @@ -1722,6 +1723,7 @@ "title": "Alexa" }, "connected": "połączono", + "connecting": "Łączenie...", "connection_status": "Status połączenia z chmurą", "fetching_subscription": "Pobieranie subskrypcji…", "google": { @@ -2962,6 +2964,7 @@ }, "logs": { "log_level": "Poziom loga", + "log_level_changed": "Poziom dziennika zmieniony na: {level}", "subscribed_to_logs": "Zasubskrybowano komunikaty dziennika Z-Wave JS...", "title": "Logi Z-Wave JS" }, diff --git a/translations/frontend/pt.json b/translations/frontend/pt.json index 6ad736bf3f..19b20f966f 100644 --- a/translations/frontend/pt.json +++ b/translations/frontend/pt.json @@ -112,8 +112,10 @@ "output": "Saída" }, "network": { + "container": "Container", "disabled": "Desativado", - "header": "Rede" + "header": "Rede", + "host": "Servidor" }, "options": { "edit_in_ui": "Editar em UI", @@ -148,7 +150,14 @@ "title": "Acesso completo ao hardware" }, "hassio_api": { - "description": "O suplemento tem acesso à API do Supervisor, a pedido do autor do complemento. Por defeito, o complemento pode aceder à informação da versão do seu sistema. Quando o complemento solicita acesso de nível 'gestor' ou 'administrador' à API, obterá acesso para controlar múltiplas partes do seu sistema Home Assistant. Esta permissão é indicada por este crachá e terá um impacto negativo na pontuação de segurança do complemento." + "description": "O suplemento tem acesso à API do Supervisor, a pedido do autor do complemento. Por defeito, o complemento pode aceder à informação da versão do seu sistema. Quando o complemento solicita acesso de nível 'gestor' ou 'administrador' à API, obterá acesso para controlar múltiplas partes do seu sistema Home Assistant. Esta permissão é indicada por este crachá e terá um impacto negativo na pontuação de segurança do complemento.", + "title": "Acesso à API supervisor" + }, + "homeassistant_api": { + "title": "Acesso à API do Home Assistant" + }, + "host_network": { + "title": "Rede do Servidor" }, "ingress": { "title": "Ingress" @@ -179,8 +188,10 @@ }, "changelog": "Changelog", "cpu_usage": "Utilização de CPU do add-on", + "hostname": "Nome do servidor", "install": "Instalar", "new_update_available": "{name} {version} está disponível", + "not_available_arch": "Este add-on não é compatível com o processador ou sistema operativo do seu dispositivo.", "not_available_version": "Está a executar o Home Assistant {core_version_installed}, para actualizar esta versão do add-on necessita pelo menos da versão {core_version_needed} do Home Assistant", "open_web_ui": "Abrir o interface web", "option": { @@ -210,6 +221,7 @@ "title": "Aviso: o modo de proteção está desativado!" }, "ram_usage": "Utilização de RAM do add-on", + "rebuild": "reconstruir", "restart": "Reiniciar", "start": "Iniciar", "stop": "Parar", @@ -334,6 +346,7 @@ }, "my": { "error": "Ocorreu um erro desconhecido", + "error_addon_no_ingress": "O add-on solicitado não suporta Ingress", "error_addon_not_found": "Add-on não encontrado", "not_supported": "Este redirecionamento não é suportado pela sua instância Início Assistant. Verifique o {link} para os redirecionamentos suportados e a versão em que foram introduzidos." }, @@ -369,6 +382,7 @@ "password_protected": "Protegido por Palavra-passe", "password_protection": "Proteção por palavra-passe", "security": "Segurança", + "select_type": "Selecione o que restaurar", "type": "Tipo", "upload_snapshot": "Upload snapshot" }, @@ -529,8 +543,11 @@ }, "light": { "brightness": "Brilho", + "cold_white_value": "Brilho branco frio", + "color_brightness": "Brilho", "color_temperature": "Temperatura de cor", "effect": "Efeito", + "warm_white_value": "Brilho branco quente", "white_value": "Brilho" }, "lock": { @@ -657,6 +674,10 @@ "addon-picker": { "addon": "Add-on", "error": { + "fetch_addons": { + "description": "A busca de add-ons retornou um erro.", + "title": "Erro ao obter add-ons." + }, "no_supervisor": { "title": "Sem Supervisor" } @@ -677,6 +698,9 @@ "no_match": "Nenhuma área correspondente encontrada", "show_areas": "Mostrar áreas" }, + "attributes": { + "expansion_header": "Atributos" + }, "blueprint-picker": { "add_user": "Adicionar um utilizador", "remove_user": "Remover utilizador", @@ -803,6 +827,13 @@ "label": "Imagem", "unsupported_format": "Formato não suportado, por favor escolha uma imagem JPEG, PNG ou GIF." }, + "related-filter-menu": { + "filter_by_area": "Filtrar por área", + "filter_by_device": "Filtrar por dispositivo", + "filter_by_entity": "Filtrar por entidade", + "filtered_by_area": "área: {area_name}", + "filtered_by_device": "dispositivo: {device_name}" + }, "related-items": { "area": "Área", "automation": "Parte das seguintes automações", @@ -840,6 +871,7 @@ } }, "service-control": { + "integration_doc": "Documentação da integração", "required": "Este campo é obrigatório", "service_data": "Dados do serviço", "target": "Alvos", @@ -1150,8 +1182,11 @@ "bind_header": "Associação", "button_hide": "Ocultar detalhes", "button_show": "Mostrar Detalhes", + "cluster_header": "Grupo", + "configuration_complete": "Reconfiguração do dispositivo concluída.", "configuring_alt": "A configurar", "min_max_change": "min/max/alterar", + "reporting_header": "Relatórios", "start_reconfiguration": "Iniciar reconfiguração" } }, @@ -1643,6 +1678,7 @@ "title": "Alexa" }, "connected": "Ligado", + "connecting": "A conectar...", "connection_status": "Estado da ligação na cloud", "fetching_subscription": "A buscar assinatura...", "google": { @@ -2009,6 +2045,9 @@ "filtering_by": "A filtrar por", "show": "Mostrar" }, + "hassio": { + "button": "Configurar" + }, "header": "Configurar o Home Assistant", "helpers": { "caption": "Auxiliares", @@ -2099,10 +2138,12 @@ "entity_unavailable": "Entidade indisponível", "firmware": "Firmware: {version}", "hub": "Conectado via", + "logs": "Logs", "manuf": "por {manufacturer}", "no_area": "Nenhuma Área", "not_loaded": "Não carregado", "options": "Opções", + "provided_by_custom_integration": "Fornecido por uma integração personalizada", "reload": "Recarregar", "reload_confirm": "A integração foi recarregada", "reload_restart_confirm": "Reinicie o Home Assistant para terminar de carregar esta integração", @@ -2113,7 +2154,8 @@ "loaded": "Carregado", "migration_error": "Erro de migração", "not_loaded": "Não carregado", - "setup_error": "Erro ao inicializar" + "setup_error": "Erro ao inicializar", + "setup_retry": "A repetir a configuração" }, "system_options": "Opções do sistema", "unnamed_entry": "Entrada sem nome" @@ -2134,6 +2176,9 @@ "loading_first_time": "Por favor, aguarde enquanto a integração está a ser instalada", "next": "Próximo", "not_all_required_fields": "Nem todos os campos obrigatórios estão preenchidos.", + "pick_flow_step": { + "title": "Descobrimos estes, quer configurá-los?" + }, "submit": "Enviar" }, "configure": "Configurar", @@ -2180,6 +2225,13 @@ "clear": "Limpar", "description": "Ver os registos do Home Assistant", "details": "Detalhes do log ( {level} )", + "level": { + "critical": "CRÍTICO", + "debug": "DEPURAR", + "error": "ERRO", + "info": "INFO", + "warning": "AVISO" + }, "load_full_log": "Carregar log completo do Home Assistant", "loading_log": "A carregar o log de erros...", "multiple_messages": "mensagem ocorreu primeiro em {time} e repetiu-se {counter} vezes", @@ -2691,6 +2743,12 @@ "manufacturer_code_override": "Substituição do código do fabricante", "value": "Valor" }, + "configuration_page": { + "shortcuts_title": "Atalhos", + "zha_options": { + "title": "Opções Globais" + } + }, "device_pairing_card": { "CONFIGURED": "Configuração Completa", "CONFIGURED_status_text": "A inicializar", @@ -2778,6 +2836,7 @@ "follow_device_instructions": "Siga as instruções do seu dispositivo para ativar o modo de emparelhamento", "inclusion_failed": "Não foi possível adicionar o nó. Por favor verifique os logs para mais informações.", "inclusion_finished": "O nó foi adicionado. Poderá demorar alguns minutos para que todas as entidades fiquem disponiveis, enquanto terminamos a configuração do nó em segundo plano.", + "interview_failed": "A consulta do dispositivo falhou. Informações adicionais podem estar disponíveis nos logs.", "introduction": "Este assistente irá guiá-lo para adicionar um nó à sua rede Z-Wave.", "secure_inclusion_warning": "Dispositivos seguros requerem mais largura de banda; demasiados dispositivos seguros podem diminuir a performance da rede Z-Wave. Recomendamos que apenas sejam adicionados dispositivos seguros estritamente necessários, como fechaduras e aberturas de garagem.", "start_inclusion": "Iniciar Inclusão", @@ -2814,6 +2873,8 @@ }, "logs": { "log_level": "Nível de log", + "log_level_changed": "Nível de log alterado para: {level}", + "subscribed_to_logs": "Inscrito em mensagens de log do Z-Wave JS...", "title": "Z-Wave JS Logs" }, "navigation": { @@ -2827,7 +2888,10 @@ }, "node_config": { "error_device_not_found": "Dispositivo não encontrado", - "parameter_is_read_only": "Este parâmetro é apenas de leitura." + "parameter_is_read_only": "Este parâmetro é apenas de leitura.", + "set_param_accepted": "O parâmetro foi atualizado.", + "set_param_error": "Ocorreu um erro.", + "set_param_queued": "A alteração do parâmetro foi colocada na fila e será atualizada quando o dispositivo for ativado." }, "node_status": { "alive": "Ativo", @@ -2836,6 +2900,12 @@ "dead": "Inativo", "unknown": "Desconhecido" }, + "reinterview_node": { + "in_progress": "A consultar dispositivo. Isto pode demorar algum tempo.", + "interview_complete": "Consulta do dispositivo concluída.", + "interview_failed": "A consulta do dispositivo falhou. Informações adicionais podem estar disponíveis nos logs.", + "start_reinterview": "Iniciar nova consulta" + }, "remove_node": { "cancel_exclusion": "Cancelar Exclusão", "controller_in_exclusion_mode": "O seu controlador Z-Wave está agora em modo de exclusão.", @@ -3666,6 +3736,9 @@ } }, "page-onboarding": { + "analytics": { + "finish": "Próximo" + }, "core-config": { "button_detect": "Detetar", "finish": "Próxima", @@ -3675,12 +3748,14 @@ "location_name": "Nome da instalação do Home Assistant", "location_name_default": "Início" }, + "finish": "Terminar", "integration": { "finish": "Terminar", "intro": "Dispositivos e serviços são representados no Home Assistant como integrações. Pode configurá-los agora ou fazê-lo mais tarde no ecrã de configuração.", "more_integrations": "Mais" }, "intro": "Está pronto para despertar a sua casa, reclamar a sua privacidade e juntar-se a uma comunidade mundial de tecnólogos?", + "next": "Próximo", "restore": { "description": "Em alternativa, pode restaurar a partir de um snapshot anterior.", "hide_log": "Ocultar log completo", @@ -3825,6 +3900,17 @@ "primary_color": "Cor primária", "reset": "Redefinir" }, + "time_format": { + "description": "Escolha como os horários são formatados.", + "dropdown_label": "Formato de hora", + "formats": { + "12": "12 horas (AM/PM)", + "24": "24 horas", + "language": "Auto (usar configuração de idioma)", + "system": "Utilizar o formato do sistema" + }, + "header": "Formato de hora" + }, "vibrate": { "description": "Ative ou desative a vibração neste dispositivo ao controlar dispositivos.", "header": "Vibrar" diff --git a/translations/frontend/ru.json b/translations/frontend/ru.json index bf9577846b..c657d7b224 100644 --- a/translations/frontend/ru.json +++ b/translations/frontend/ru.json @@ -383,7 +383,7 @@ "could_not_create": "Не удалось создать снимок", "create": "Создать", "create_blocked_not_running": "Создание снимка сейчас невозможно, потому что система находится в состоянии {state}.", - "create_snapshot": "Снимки файловой системы", + "create_snapshot": "Создать снимок", "created": "Создан", "description": "Снимок файловой системы (snapshot) позволяет легко создавать и восстанавливать резервную копию всех данных Вашего Home Assistant.", "enter_password": "Пожалуйста, введите пароль.", diff --git a/translations/frontend/zh-Hant.json b/translations/frontend/zh-Hant.json index 849d32e790..b5e293dac7 100644 --- a/translations/frontend/zh-Hant.json +++ b/translations/frontend/zh-Hant.json @@ -396,14 +396,15 @@ }, "folders": "資料夾", "full_snapshot": "全系統備份", - "name": "名稱", + "name": "系統備份名稱", "no_snapshots": "目前沒有任何系統備份", "partial_snapshot": "部分系統備份", - "password": "密碼", + "password": "系統備份密碼", "password_protected": "密碼保護未顯示", "password_protection": "密碼保護", "security": "加密", - "type": "類型", + "select_type": "選擇所要回復內容", + "type": "系統備份類型", "upload_snapshot": "上傳系統備份" }, "store": { @@ -720,6 +721,9 @@ "no_match": "找不到相符分區", "show_areas": "顯示分區" }, + "attributes": { + "expansion_header": "屬性" + }, "blueprint-picker": { "add_user": "新增使用者", "remove_user": "移除使用者", @@ -1719,6 +1723,7 @@ "title": "Alexa" }, "connected": "已連接", + "connecting": "連線中...", "connection_status": "雲服務連線狀態", "fetching_subscription": "取得訂閱狀態中...", "google": { @@ -2959,6 +2964,7 @@ }, "logs": { "log_level": "日誌記錄等級", + "log_level_changed": "日誌等級變更為:{level}", "subscribed_to_logs": "訂閱 Z-Wave JS 日誌訊息...", "title": "Z-Wave JS 日誌" }, diff --git a/yarn.lock b/yarn.lock index 0375730fc3..eccbc5fc48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5676,9 +5676,9 @@ dns-equal@^1.0.0: integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= dns-packet@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" - integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg== + version "1.3.4" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" + integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== dependencies: ip "^1.1.0" safe-buffer "^5.0.1"