-
+
-
+ ${initials}
`;
}
+ protected updated(changedProps) {
+ super.updated(changedProps);
+ this.toggleAttribute(
+ "long",
+ (this.user ? computeInitials(this.user.name) : "?").length > 2
+ );
+ }
+
static get styles(): CSSResult {
return css`
- .profile-badge {
+ :host {
display: inline-block;
box-sizing: border-box;
width: 40px;
@@ -63,7 +61,7 @@ class StateBadge extends LitElement {
overflow: hidden;
}
- .profile-badge.long {
+ :host([long]) {
font-size: 80%;
}
`;
diff --git a/src/data/collection.ts b/src/data/collection.ts
new file mode 100644
index 0000000000..a565d371f0
--- /dev/null
+++ b/src/data/collection.ts
@@ -0,0 +1,74 @@
+import {
+ Collection,
+ Connection,
+ getCollection,
+ UnsubscribeFunc,
+} from "home-assistant-js-websocket";
+import { Store } from "home-assistant-js-websocket/dist/store";
+
+interface OptimisticCollection
extends Collection {
+ save(data: T): Promise;
+}
+
+/**
+ * Create an optimistic collection that includes a save function.
+ * When the collection is saved, the collection is optimistically updated.
+ * The update is reversed when the update failed.
+ */
+
+export const getOptimisticCollection = (
+ saveCollection: (conn: Connection, data: StateType) => Promise,
+ conn: Connection,
+ key: string,
+ fetchCollection: (conn: Connection) => Promise,
+ subscribeUpdates?: (
+ conn: Connection,
+ store: Store
+ ) => Promise
+): OptimisticCollection => {
+ const updateKey = `${key}-optimistic`;
+
+ const collection = getCollection(
+ conn,
+ key,
+ fetchCollection,
+ async (_conn, store) => {
+ // Subscribe to original updates
+ const subUpResult = subscribeUpdates
+ ? subscribeUpdates(conn, store)
+ : undefined;
+ // Store the store
+ conn[updateKey] = store;
+
+ // Unsub function to undo both
+ return () => {
+ if (subUpResult) {
+ subUpResult.then((unsub) => unsub());
+ }
+ conn[updateKey] = undefined;
+ };
+ }
+ );
+ return {
+ ...collection,
+ async save(data: StateType) {
+ const store: Store | undefined = conn[updateKey];
+ let current;
+
+ // Can be undefined if currently no subscribers
+ if (store) {
+ current = store.state;
+ store.setState(data, true);
+ }
+
+ try {
+ return await saveCollection(conn, data);
+ } catch (err) {
+ if (store) {
+ store.setState(current as any, true);
+ }
+ throw err;
+ }
+ },
+ };
+};
diff --git a/src/data/frontend.ts b/src/data/frontend.ts
index 71c60d670f..83a2db1ac7 100644
--- a/src/data/frontend.ts
+++ b/src/data/frontend.ts
@@ -1,8 +1,14 @@
-import { HomeAssistant } from "../types";
+import { Connection } from "home-assistant-js-websocket";
+import { getOptimisticCollection } from "./collection";
+
+export interface CoreFrontendUserData {
+ showAdvanced?: boolean;
+}
declare global {
- // tslint:disable-next-line
- interface FrontendUserData {}
+ interface FrontendUserData {
+ core: CoreFrontendUserData;
+ }
}
export type ValidUserDataKey = keyof FrontendUserData;
@@ -10,10 +16,10 @@ export type ValidUserDataKey = keyof FrontendUserData;
export const fetchFrontendUserData = async <
UserDataKey extends ValidUserDataKey
>(
- hass: HomeAssistant,
+ conn: Connection,
key: UserDataKey
): Promise => {
- const result = await hass.callWS<{
+ const result = await conn.sendMessagePromise<{
value: FrontendUserData[UserDataKey] | null;
}>({
type: "frontend/get_user_data",
@@ -25,12 +31,31 @@ export const fetchFrontendUserData = async <
export const saveFrontendUserData = async <
UserDataKey extends ValidUserDataKey
>(
- hass: HomeAssistant,
+ conn: Connection,
key: UserDataKey,
value: FrontendUserData[UserDataKey]
): Promise =>
- hass.callWS({
+ conn.sendMessagePromise({
type: "frontend/set_user_data",
key,
value,
});
+
+export const getOptimisticFrontendUserDataCollection = <
+ UserDataKey extends ValidUserDataKey
+>(
+ conn: Connection,
+ userDataKey: UserDataKey
+) =>
+ getOptimisticCollection(
+ (_conn, data) =>
+ saveFrontendUserData(
+ conn,
+ userDataKey,
+ // @ts-ignore
+ data
+ ),
+ conn,
+ `_frontendUserData-${userDataKey}`,
+ () => fetchFrontendUserData(conn, userDataKey)
+ );
diff --git a/src/data/translation.ts b/src/data/translation.ts
index 122ce344bd..f2ce1a7c1a 100644
--- a/src/data/translation.ts
+++ b/src/data/translation.ts
@@ -12,12 +12,12 @@ declare global {
}
export const fetchTranslationPreferences = (hass: HomeAssistant) =>
- fetchFrontendUserData(hass, "language");
+ fetchFrontendUserData(hass.connection, "language");
export const saveTranslationPreferences = (
hass: HomeAssistant,
data: FrontendTranslationData
-) => saveFrontendUserData(hass, "language", data);
+) => saveFrontendUserData(hass.connection, "language", data);
export const getHassTranslations = async (
hass: HomeAssistant,
diff --git a/src/layouts/home-assistant-main.ts b/src/layouts/home-assistant-main.ts
index 0472f1069a..d2631cd825 100644
--- a/src/layouts/home-assistant-main.ts
+++ b/src/layouts/home-assistant-main.ts
@@ -18,6 +18,8 @@ import "./partial-panel-resolver";
import { HomeAssistant, Route } from "../types";
import { fireEvent } from "../common/dom/fire_event";
import { PolymerChangedEvent } from "../polymer-types";
+// tslint:disable-next-line: no-duplicate-imports
+import { AppDrawerLayoutElement } from "@polymer/app-layout/app-drawer-layout/app-drawer-layout";
const NON_SWIPABLE_PANELS = ["kiosk", "map"];
@@ -29,9 +31,9 @@ declare global {
}
class HomeAssistantMain extends LitElement {
- @property() public hass?: HomeAssistant;
+ @property() public hass!: HomeAssistant;
@property() public route?: Route;
- @property() private _narrow?: boolean;
+ @property({ type: Boolean }) private narrow?: boolean;
protected render(): TemplateResult | void {
const hass = this.hass;
@@ -40,7 +42,8 @@ class HomeAssistantMain extends LitElement {
return;
}
- const disableSwipe = NON_SWIPABLE_PANELS.indexOf(hass.panelUrl) !== -1;
+ const disableSwipe =
+ !this.narrow || NON_SWIPABLE_PANELS.indexOf(hass.panelUrl) !== -1;
return html`
-
+
@@ -77,19 +83,17 @@ class HomeAssistantMain extends LitElement {
import(/* webpackChunkName: "ha-sidebar" */ "../components/ha-sidebar");
this.addEventListener("hass-toggle-menu", () => {
- const shouldOpen = !this.drawer.opened;
-
- if (shouldOpen) {
- if (this._narrow) {
- this.drawer.open();
+ if (this.narrow) {
+ if (this.drawer.opened) {
+ this.drawer.close();
} else {
- fireEvent(this, "hass-dock-sidebar", { dock: true });
+ this.drawer.open();
}
} else {
- this.drawer.close();
- if (this.hass!.dockedSidebar) {
- fireEvent(this, "hass-dock-sidebar", { dock: false });
- }
+ fireEvent(this, "hass-dock-sidebar", {
+ dock: !this.hass.dockedSidebar,
+ });
+ setTimeout(() => this.appLayout.resetLayout());
}
});
}
@@ -97,7 +101,9 @@ class HomeAssistantMain extends LitElement {
protected updated(changedProps: PropertyValues) {
super.updated(changedProps);
- if (changedProps.has("route") && this._narrow) {
+ this.toggleAttribute("expanded", this.narrow || this.hass.dockedSidebar);
+
+ if (changedProps.has("route") && this.narrow) {
this.drawer.close();
}
@@ -110,19 +116,27 @@ class HomeAssistantMain extends LitElement {
}
private _narrowChanged(ev: PolymerChangedEvent) {
- this._narrow = ev.detail.value;
+ this.narrow = ev.detail.value;
}
private get drawer(): AppDrawerElement {
return this.shadowRoot!.querySelector("app-drawer")!;
}
+ private get appLayout(): AppDrawerLayoutElement {
+ return this.shadowRoot!.querySelector("app-drawer-layout")!;
+ }
+
static get styles(): CSSResult {
return css`
:host {
color: var(--primary-text-color);
/* remove the grey tap highlights in iOS on the fullscreen touch targets */
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+ --app-drawer-width: 64px;
+ }
+ :host([expanded]) {
+ --app-drawer-width: 256px;
}
partial-panel-resolver,
ha-sidebar {
diff --git a/src/panels/config/core/ha-config-core.js b/src/panels/config/core/ha-config-core.js
index c53f7e9b6e..bcc71ca824 100644
--- a/src/panels/config/core/ha-config-core.js
+++ b/src/panels/config/core/ha-config-core.js
@@ -37,6 +37,7 @@ class HaConfigCore extends LocalizeMixin(PolymerElement) {
@@ -48,6 +49,7 @@ class HaConfigCore extends LocalizeMixin(PolymerElement) {
return {
hass: Object,
isWide: Boolean,
+ showAdvanced: Boolean,
};
}
diff --git a/src/panels/config/core/ha-config-section-core.js b/src/panels/config/core/ha-config-section-core.js
index 9b55d253a0..74cb573073 100644
--- a/src/panels/config/core/ha-config-section-core.js
+++ b/src/panels/config/core/ha-config-section-core.js
@@ -63,79 +63,80 @@ class HaConfigSectionCore extends LocalizeMixin(PolymerElement) {
-
-
- [[localize('ui.panel.config.core.section.core.validation.introduction')]]
-
-
-
-
-
- [[localize('ui.panel.config.core.section.core.validation.valid')]]
-
+
+
+
+ [[localize('ui.panel.config.core.section.core.validation.introduction')]]
+
+
+
+
+
+ [[localize('ui.panel.config.core.section.core.validation.valid')]]
+
+
+
+ [[localize('ui.panel.config.core.section.core.validation.check_config')]]
+
+
+
+
+
+
+
+
+
+ [[localize('ui.panel.config.core.section.core.validation.invalid')]]
+
[[localize('ui.panel.config.core.section.core.validation.check_config')]]
-
-
-
-
-
-
-
-
-
- [[localize('ui.panel.config.core.section.core.validation.invalid')]]
-
-
- [[localize('ui.panel.config.core.section.core.validation.check_config')]]
-
-
- [[validateLog]]
-
-
-
-
-
-
- [[localize('ui.panel.config.core.section.core.reloading.introduction')]]
-
-
- [[localize('ui.panel.config.core.section.core.reloading.core')]]
-
- [[localize('ui.panel.config.core.section.core.reloading.group')]]
-
- [[localize('ui.panel.config.core.section.core.reloading.automation')]]
-
- [[localize('ui.panel.config.core.section.core.reloading.script')]]
-
-
-
+
+ [[validateLog]]
+
+
+
+
+
+ [[localize('ui.panel.config.core.section.core.reloading.introduction')]]
+
+
+ [[localize('ui.panel.config.core.section.core.reloading.core')]]
+
+ [[localize('ui.panel.config.core.section.core.reloading.group')]]
+
+ [[localize('ui.panel.config.core.section.core.reloading.automation')]]
+
+ [[localize('ui.panel.config.core.section.core.reloading.script')]]
+
+
+
+
@@ -188,6 +189,8 @@ class HaConfigSectionCore extends LocalizeMixin(PolymerElement) {
type: String,
value: "",
},
+
+ showAdvanced: Boolean,
};
}
diff --git a/src/panels/config/dashboard/ha-config-dashboard.js b/src/panels/config/dashboard/ha-config-dashboard.js
index 8c4a40a721..0e31d22255 100644
--- a/src/panels/config/dashboard/ha-config-dashboard.js
+++ b/src/panels/config/dashboard/ha-config-dashboard.js
@@ -31,10 +31,17 @@ class HaConfigDashboard extends NavigateMixin(LocalizeMixin(PolymerElement)) {
.content {
padding-bottom: 32px;
}
- a {
+ ha-card a {
text-decoration: none;
color: var(--primary-text-color);
}
+ .promo-advanced {
+ text-align: center;
+ color: var(--secondary-text-color);
+ }
+ .promo-advanced a {
+ color: var(--secondary-text-color);
+ }
@@ -99,7 +106,16 @@ class HaConfigDashboard extends NavigateMixin(LocalizeMixin(PolymerElement)) {
-
+
+
+
+
+
@@ -111,6 +127,7 @@ class HaConfigDashboard extends NavigateMixin(LocalizeMixin(PolymerElement)) {
hass: Object,
isWide: Boolean,
cloudStatus: Object,
+ showAdvanced: Boolean,
};
}
diff --git a/src/panels/config/dashboard/ha-config-navigation.js b/src/panels/config/dashboard/ha-config-navigation.js
deleted file mode 100644
index be00ec1e3e..0000000000
--- a/src/panels/config/dashboard/ha-config-navigation.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import "@polymer/iron-icon/iron-icon";
-import "@polymer/paper-item/paper-item-body";
-import "@polymer/paper-item/paper-item";
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-
-import NavigateMixin from "../../../mixins/navigate-mixin";
-import LocalizeMixin from "../../../mixins/localize-mixin";
-
-import isComponentLoaded from "../../../common/config/is_component_loaded";
-
-import "../../../components/ha-card";
-import "../../../components/ha-icon-next";
-
-const CORE_PAGES = ["core", "customize", "entity_registry", "area_registry"];
-/*
- * @appliesMixin LocalizeMixin
- * @appliesMixin NavigateMixin
- */
-class HaConfigNavigation extends LocalizeMixin(NavigateMixin(PolymerElement)) {
- static get template() {
- return html`
-
-
- 
+
+
+
+
Home Assistant
${hass.config.version}
diff --git a/src/panels/lovelace/components/hui-entities-toggle.ts b/src/panels/lovelace/components/hui-entities-toggle.ts
index b135cd854e..2d5feeaa8b 100644
--- a/src/panels/lovelace/components/hui-entities-toggle.ts
+++ b/src/panels/lovelace/components/hui-entities-toggle.ts
@@ -41,6 +41,7 @@ class HuiEntitiesToggle extends LitElement {
return html`
{
const stateObj = this.hass!.states[entityId];
return stateObj && stateObj.state === "on";
diff --git a/src/panels/lovelace/components/notifications/hui-notifications-button.ts b/src/panels/lovelace/components/notifications/hui-notifications-button.ts
index c56d2931a1..023764e8a9 100644
--- a/src/panels/lovelace/components/notifications/hui-notifications-button.ts
+++ b/src/panels/lovelace/components/notifications/hui-notifications-button.ts
@@ -23,6 +23,7 @@ class HuiNotificationsButton extends LitElement {
protected render(): TemplateResult | void {
return html`
diff --git a/src/panels/lovelace/hui-root.ts b/src/panels/lovelace/hui-root.ts
index ab1144e4b5..53c7467b93 100644
--- a/src/panels/lovelace/hui-root.ts
+++ b/src/panels/lovelace/hui-root.ts
@@ -144,6 +144,7 @@ class HUIRoot extends LitElement {
horizontal-offset="-5"
>
diff --git a/src/panels/profile/ha-advanced-mode-card.ts b/src/panels/profile/ha-advanced-mode-card.ts
new file mode 100644
index 0000000000..5e97fb80fe
--- /dev/null
+++ b/src/panels/profile/ha-advanced-mode-card.ts
@@ -0,0 +1,65 @@
+import {
+ LitElement,
+ property,
+ TemplateResult,
+ html,
+ customElement,
+ CSSResult,
+ css,
+} from "lit-element";
+import "../../components/ha-card";
+import { HomeAssistant } from "../../types";
+import {
+ CoreFrontendUserData,
+ getOptimisticFrontendUserDataCollection,
+} from "../../data/frontend";
+
+@customElement("ha-advanced-mode-card")
+class AdvancedModeCard extends LitElement {
+ @property() public hass!: HomeAssistant;
+ @property() public coreUserData?: CoreFrontendUserData;
+
+ protected render(): TemplateResult | void {
+ return html`
+
+
+
+ Home Assistant hides advanced features and options by default. You can
+ make these features accessible by checking this toggle. This is a
+ user-specific setting and does not impact other users using Home
+ Assistant.
+
+
+ `;
+ }
+
+ private async _advancedToggled(ev) {
+ getOptimisticFrontendUserDataCollection(this.hass.connection, "core").save({
+ showAdvanced: ev.currentTarget.checked,
+ });
+ }
+
+ static get styles(): CSSResult {
+ return css`
+ .card-header {
+ display: flex;
+ }
+ .title {
+ flex: 1;
+ }
+ `;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "ha-advanced-mode-card": AdvancedModeCard;
+ }
+}
diff --git a/src/panels/profile/ha-panel-profile.js b/src/panels/profile/ha-panel-profile.js
index 5e60d5ed6f..eb55c2fbc0 100644
--- a/src/panels/profile/ha-panel-profile.js
+++ b/src/panels/profile/ha-panel-profile.js
@@ -11,11 +11,14 @@ import "../../components/ha-card";
import "../../components/ha-menu-button";
import "../../resources/ha-style";
+import { getOptimisticFrontendUserDataCollection } from "../../data/frontend";
+
import { EventsMixin } from "../../mixins/events-mixin";
import LocalizeMixin from "../../mixins/localize-mixin";
import "./ha-change-password-card";
import "./ha-mfa-modules-card";
+import "./ha-advanced-mode-card";
import "./ha-refresh-tokens-card";
import "./ha-long-lived-access-tokens-card";
@@ -98,6 +101,11 @@ class HaPanelProfile extends EventsMixin(LocalizeMixin(PolymerElement)) {
mfa-modules="[[hass.user.mfa_modules]]"
>
+
+
{
+ this._coreUserData = coreUserData;
+ });
+ }
+
+ disconnectedCallback() {
+ super.disconnectedCallback();
+ if (this._unsubCoreData) {
+ this._unsubCoreData();
+ this._unsubCoreData = undefined;
+ }
}
async _refreshRefreshTokens() {
diff --git a/src/state/connection-mixin.ts b/src/state/connection-mixin.ts
index dcf34e1aab..009db79be1 100644
--- a/src/state/connection-mixin.ts
+++ b/src/state/connection-mixin.ts
@@ -44,7 +44,7 @@ export const connectionMixin = (
localize: () => "",
translationMetadata,
- dockedSidebar: false,
+ dockedSidebar: true,
moreInfoEntityId: null,
callService: async (domain, service, serviceData = {}) => {
if (__DEV__) {
diff --git a/src/state/translations-mixin.ts b/src/state/translations-mixin.ts
index cb3113ffdb..edce6341cc 100644
--- a/src/state/translations-mixin.ts
+++ b/src/state/translations-mixin.ts
@@ -9,9 +9,11 @@ import { HassBaseEl } from "./hass-base-mixin";
import { computeLocalize } from "../common/translations/localize";
import { computeRTL } from "../common/util/compute_rtl";
import { HomeAssistant } from "../types";
-import { saveFrontendUserData } from "../data/frontend";
import { storeState } from "../util/ha-pref-storage";
-import { getHassTranslations } from "../data/translation";
+import {
+ getHassTranslations,
+ saveTranslationPreferences,
+} from "../data/translation";
/*
* superClass needs to contain `this.hass` and `this._updateHass`.
@@ -65,7 +67,7 @@ export default (superClass: Constructor) =>
this._updateHass({ language, selectedLanguage: language });
storeState(this.hass);
if (saveToBackend) {
- saveFrontendUserData(this.hass, "language", { language });
+ saveTranslationPreferences(this.hass, { language });
}
this._applyTranslations(this.hass);
diff --git a/src/util/hass-translation.ts b/src/util/hass-translation.ts
index 220c0210a7..c2ee7e434b 100644
--- a/src/util/hass-translation.ts
+++ b/src/util/hass-translation.ts
@@ -1,6 +1,6 @@
import { translationMetadata } from "../resources/translations-metadata";
-import { fetchFrontendUserData } from "../data/frontend";
import { HomeAssistant } from "../types";
+import { fetchTranslationPreferences } from "../data/translation";
const STORAGE = window.localStorage || {};
@@ -43,7 +43,7 @@ function findAvailableLanguage(language: string) {
* Get user selected language from backend
*/
export async function getUserLanguage(hass: HomeAssistant) {
- const result = await fetchFrontendUserData(hass, "language");
+ const result = await fetchTranslationPreferences(hass);
const language = result ? result.language : null;
if (language) {
const availableLanguage = findAvailableLanguage(language);
diff --git a/translations/ca.json b/translations/ca.json
index b8aaa3577c..fbab8e7f6d 100644
--- a/translations/ca.json
+++ b/translations/ca.json
@@ -338,7 +338,7 @@
"validation": {
"heading": "Validació de la configuració",
"introduction": "Valida la configuració si recentment has fet algun canvi a la configuració i vols assegurar-te de que no té problemes.",
- "check_config": "Comprovar la configuració",
+ "check_config": "Comprova la configuració",
"valid": "La configuració és vàlida!",
"invalid": "La configuració és invàlida"
},
@@ -353,8 +353,8 @@
"server_management": {
"heading": "Gestió del servidor",
"introduction": "Controla el servidor de Home Assistant... des de Home Assistant.",
- "restart": "Reiniciar",
- "stop": "Aturar"
+ "restart": "Reinicia",
+ "stop": "Atura"
},
"core_config": {
"edit_requires_storage": "L'editor està desactivat ja que la configuració es troba a configuration.yaml.",
diff --git a/translations/is.json b/translations/is.json
index 5ae86e011a..d2b85024d2 100644
--- a/translations/is.json
+++ b/translations/is.json
@@ -3,13 +3,14 @@
"config": "Stillingar",
"states": "Yfirlit",
"map": "Kort",
- "logbook": "Logbók",
+ "logbook": "Breytingarsaga",
"history": "Saga",
"mailbox": "Pósthólf",
"shopping_list": "Innkaupalisti",
"dev-services": "Þjónustur",
"dev-states": "Stöður",
"dev-events": "Viðburðir",
+ "dev-templates": "Skapalón",
"dev-mqtt": "MQTT",
"dev-info": "Upplýsingar",
"calendar": "Dagatal",
@@ -75,6 +76,10 @@
"off": "Aftengdur",
"on": "Tengdur"
},
+ "cold": {
+ "off": "Venjulegt",
+ "on": "Kalt"
+ },
"door": {
"off": "Lokuð",
"on": "Opin"
@@ -83,6 +88,10 @@
"off": "Lokuð",
"on": "Opin"
},
+ "heat": {
+ "off": "Venjulegt",
+ "on": "Heitt"
+ },
"window": {
"off": "Loka",
"on": "Opna"
@@ -301,6 +310,7 @@
"stop": "Stöðva"
},
"core_config": {
+ "edit_requires_storage": "Ritill er óvirkur af því að stillingar eru vistaðar í configuration.yaml.",
"location_name": "Nafnið á Home Assistant uppsetningunni",
"latitude": "Breiddargráða",
"longitude": "Lengdargráða",
@@ -475,7 +485,9 @@
}
},
"learn_more": "Læra meira um aðgerðir"
- }
+ },
+ "load_error_not_editable": "Eingöngu er hægt að breyta sjálfvirkni í automations.yaml",
+ "load_error_unknown": "Villa kom upp við að hlaða inn sjálfvirkni ({err_no})."
}
},
"script": {
@@ -537,6 +549,7 @@
},
"config_flow": {
"external_step": {
+ "description": "Þetta skref krefst þess að þú heimsækir ytri vefsíðu svo hægt sé að ljúka þessu skrefi.",
"open_site": "Opna vefsíðu"
}
}
@@ -785,6 +798,7 @@
"finish": "Ljúka"
},
"core-config": {
+ "intro": "Hæ {name}, velkomin(n) í Home Assistant. Hvað á heimilið þitt að heita?",
"location_name_default": "Heima",
"button_detect": "Uppgötva",
"finish": "Næsta"
@@ -869,12 +883,14 @@
"cards": {
"demo": {
"demo_by": "eftir {name}",
+ "next_demo": "Næsta sýnidæmi",
"learn_more": "Læra meira um Home Assistant"
}
},
"config": {
"arsaboo": {
"names": {
+ "family_room": "Fjölskyldurými",
"kitchen": "Eldhús",
"left": "Vinstri",
"right": "Hægri",
@@ -885,7 +901,10 @@
"information": "Upplýsingar",
"entertainment": "Skemmtun",
"activity": "Virkni",
+ "hdmi_input": "HDMI inntak",
+ "hdmi_switcher": "HDMI rofi",
"volume": "Hljóðstyrkur",
+ "total_tv_time": "Heildar sjónvarpstími",
"turn_tv_off": "Slökkva á sjónvarpi"
},
"unit": {
@@ -985,6 +1004,7 @@
"currently": "Er núna",
"on_off": "Kveikt \/ slökkt",
"operation": "Aðgerð",
+ "fan_mode": "Viftuhamur",
"swing_mode": "Sveifluhamur"
},
"lock": {
@@ -1104,6 +1124,7 @@
"updater": "Uppfærsluálfur",
"weblink": "Vefslóð",
"zwave": "Z-Wave",
+ "vacuum": "Ryksuga",
"zha": "ZHA",
"hassio": "Hass.io",
"homeassistant": "Home Assistant",
diff --git a/translations/pl.json b/translations/pl.json
index d5eee243f5..31141e0fc6 100644
--- a/translations/pl.json
+++ b/translations/pl.json
@@ -849,7 +849,7 @@
"data": {
"code": "Kod uwierzytelniania dwuskładnikowego"
},
- "description": "Otwórz **{mfa_module_name}** na swoim urządzeniu by zobaczyć kod dwuskładnikowego uwierzytelniania i zweryfikować swoją toższamość:"
+ "description": "Otwórz **{mfa_module_name}** na swoim urządzeniu by zobaczyć kod dwuskładnikowego uwierzytelniania i zweryfikować swoją tożsamość:"
}
},
"error": {