mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-01 13:37:47 +00:00
Merge pull request #6411 from home-assistant/dev
This commit is contained in:
commit
e8254f9aae
@ -108,7 +108,6 @@
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"roboto-fontface": "^0.10.0",
|
||||
"superstruct": "^0.6.1",
|
||||
"svg-gauge": "^1.0.6",
|
||||
"unfetch": "^4.1.0",
|
||||
"vue": "^2.6.11",
|
||||
"vue2-daterange-picker": "^0.5.1",
|
||||
|
2
setup.py
2
setup.py
@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="home-assistant-frontend",
|
||||
version="20200715.1",
|
||||
version="20200716.0",
|
||||
description="The Home Assistant frontend",
|
||||
url="https://github.com/home-assistant/home-assistant-polymer",
|
||||
author="The Home Assistant Authors",
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from "lit-element";
|
||||
|
||||
@customElement("ha-card")
|
||||
class HaCard extends LitElement {
|
||||
export class HaCard extends LitElement {
|
||||
@property() public header?: string;
|
||||
|
||||
@property({ type: Boolean, reflect: true }) public outlined = false;
|
||||
|
130
src/components/ha-gauge.ts
Normal file
130
src/components/ha-gauge.ts
Normal file
@ -0,0 +1,130 @@
|
||||
import {
|
||||
LitElement,
|
||||
svg,
|
||||
customElement,
|
||||
css,
|
||||
property,
|
||||
internalProperty,
|
||||
PropertyValues,
|
||||
} from "lit-element";
|
||||
import { styleMap } from "lit-html/directives/style-map";
|
||||
import { afterNextRender } from "../common/util/render-status";
|
||||
|
||||
const getAngle = (value: number, min: number, max: number) => {
|
||||
const percentage = getValueInPercentage(normalize(value, min, max), min, max);
|
||||
return (percentage * 180) / 100;
|
||||
};
|
||||
|
||||
const normalize = (value: number, min: number, max: number) => {
|
||||
if (value > max) return max;
|
||||
if (value < min) return min;
|
||||
return value;
|
||||
};
|
||||
|
||||
const getValueInPercentage = (value: number, min: number, max: number) => {
|
||||
const newMax = max - min;
|
||||
const newVal = value - min;
|
||||
return (100 * newVal) / newMax;
|
||||
};
|
||||
|
||||
@customElement("ha-gauge")
|
||||
export class Gauge extends LitElement {
|
||||
@property({ type: Number }) public min = 0;
|
||||
|
||||
@property({ type: Number }) public max = 100;
|
||||
|
||||
@property({ type: Number }) public value = 0;
|
||||
|
||||
@property() public label = "";
|
||||
|
||||
@internalProperty() private _angle = 0;
|
||||
|
||||
@internalProperty() private _updated = false;
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues) {
|
||||
super.firstUpdated(changedProperties);
|
||||
// Wait for the first render for the initial animation to work
|
||||
afterNextRender(() => {
|
||||
this._updated = true;
|
||||
this._angle = getAngle(this.value, this.min, this.max);
|
||||
this._rescale_svg();
|
||||
});
|
||||
}
|
||||
|
||||
protected updated(changedProperties: PropertyValues) {
|
||||
super.updated(changedProperties);
|
||||
if (!this._updated || !changedProperties.has("value")) {
|
||||
return;
|
||||
}
|
||||
this._angle = getAngle(this.value, this.min, this.max);
|
||||
this._rescale_svg();
|
||||
}
|
||||
|
||||
protected render() {
|
||||
return svg`
|
||||
<svg viewBox="0 0 100 50" class="gauge">
|
||||
<path
|
||||
class="dial"
|
||||
d="M 10 50 A 40 40 0 0 1 90 50"
|
||||
></path>
|
||||
<path
|
||||
class="value"
|
||||
style=${styleMap({ transform: `rotate(${this._angle}deg)` })}
|
||||
d="M 90 50.001 A 40 40 0 0 1 10 50"
|
||||
></path>
|
||||
</svg>
|
||||
<svg class="text">
|
||||
<text class="value-text">
|
||||
${this.value} ${this.label}
|
||||
</text>
|
||||
</svg>`;
|
||||
}
|
||||
|
||||
private _rescale_svg() {
|
||||
// Set the viewbox of the SVG containing the value to perfectly
|
||||
// fit the text
|
||||
// That way it will auto-scale correctly
|
||||
const svgRoot = this.shadowRoot!.querySelector(".text")!;
|
||||
const box = svgRoot.querySelector("text")!.getBBox()!;
|
||||
svgRoot.setAttribute(
|
||||
"viewBox",
|
||||
`${box.x} ${box!.y} ${box.width} ${box.height}`
|
||||
);
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
:host {
|
||||
position: relative;
|
||||
}
|
||||
.dial {
|
||||
fill: none;
|
||||
stroke: var(--primary-background-color);
|
||||
stroke-width: 15;
|
||||
}
|
||||
.value {
|
||||
fill: none;
|
||||
stroke-width: 15;
|
||||
stroke: var(--gauge-color);
|
||||
transition: all 1000ms ease 0s;
|
||||
transform-origin: 50% 100%;
|
||||
}
|
||||
.gauge {
|
||||
display: block;
|
||||
}
|
||||
.text {
|
||||
position: absolute;
|
||||
max-height: 40%;
|
||||
max-width: 55%;
|
||||
left: 50%;
|
||||
bottom: -6%;
|
||||
transform: translate(-50%, 0%);
|
||||
}
|
||||
.value-text {
|
||||
font-size: 50px;
|
||||
fill: var(--primary-text-color);
|
||||
text-anchor: middle;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
@ -89,7 +89,7 @@ const mdiRenameMapping = {
|
||||
"library-movie": "filmstrip-box-multiple",
|
||||
"library-music": "music-box-multiple",
|
||||
"library-music-outline": "music-box-multiple-outline",
|
||||
"library-video": "play-box-mutiple",
|
||||
"library-video": "play-box-multiple",
|
||||
markdown: "language-markdown",
|
||||
"markdown-outline": "language-markdown-outline",
|
||||
"message-settings-variant": "message-cog",
|
||||
@ -151,6 +151,8 @@ const mdiRenameMapping = {
|
||||
"textbox-lock": "form-textbox-lock",
|
||||
"textbox-password": "form-textbox-password",
|
||||
"syllabary-katakana-half-width": "syllabary-katakana-halfwidth",
|
||||
"visual-studio-code": "microsoft-visual-studio-code",
|
||||
"visual-studio": "microsoft-visual-studio",
|
||||
};
|
||||
|
||||
const mdiRemovedIcons = new Set([
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket/dist/types";
|
||||
import Gauge from "svg-gauge";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@ -10,7 +9,6 @@ import {
|
||||
internalProperty,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
query,
|
||||
} from "lit-element";
|
||||
|
||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||
@ -24,6 +22,8 @@ import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import { createEntityNotFoundWarning } from "../components/hui-warning";
|
||||
import type { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import type { GaugeCardConfig } from "./types";
|
||||
import "../../../components/ha-gauge";
|
||||
import { styleMap } from "lit-html/directives/style-map";
|
||||
|
||||
export const severityMap = {
|
||||
red: "var(--label-badge-red)",
|
||||
@ -68,10 +68,6 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
|
||||
@internalProperty() private _config?: GaugeCardConfig;
|
||||
|
||||
@internalProperty() private _gauge?: any;
|
||||
|
||||
@query("#gauge") private _gaugeElement!: HTMLDivElement;
|
||||
|
||||
public getCardSize(): number {
|
||||
return 2;
|
||||
}
|
||||
@ -84,7 +80,6 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
throw new Error("Invalid Entity");
|
||||
}
|
||||
this._config = { min: 0, max: 100, ...config };
|
||||
this._initGauge();
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
@ -118,7 +113,18 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
|
||||
return html`
|
||||
<ha-card @click=${this._handleClick} tabindex="0">
|
||||
<div id="gauge"></div>
|
||||
<ha-gauge
|
||||
.min=${this._config.min!}
|
||||
.max=${this._config.max!}
|
||||
.value=${state}
|
||||
.label=${this._config!.unit ||
|
||||
this.hass?.states[this._config!.entity].attributes
|
||||
.unit_of_measurement ||
|
||||
""}
|
||||
style=${styleMap({
|
||||
"--gauge-color": this._computeSeverity(state),
|
||||
})}
|
||||
></ha-gauge>
|
||||
<div class="name">
|
||||
${this._config.name || computeStateName(stateObj)}
|
||||
</div>
|
||||
@ -130,13 +136,6 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
return hasConfigOrEntityChanged(this, changedProps);
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues): void {
|
||||
super.firstUpdated(changedProps);
|
||||
if (!this._gauge) {
|
||||
this._initGauge();
|
||||
}
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues): void {
|
||||
super.updated(changedProps);
|
||||
if (!this._config || !this.hass) {
|
||||
@ -156,66 +155,38 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
) {
|
||||
applyThemesOnElement(this, this.hass.themes, this._config.theme);
|
||||
}
|
||||
const oldState = oldHass?.states[this._config.entity];
|
||||
const stateObj = this.hass.states[this._config.entity];
|
||||
if (oldState?.state !== stateObj.state) {
|
||||
this._gauge.setValueAnimated(stateObj.state, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private _initGauge() {
|
||||
if (!this._gaugeElement || !this._config || !this.hass) {
|
||||
return;
|
||||
private _computeSeverity(numberValue: number): string {
|
||||
const sections = this._config!.severity;
|
||||
|
||||
if (!sections) {
|
||||
return severityMap.normal;
|
||||
}
|
||||
if (this._gauge) {
|
||||
this._gaugeElement.removeChild(this._gaugeElement.lastChild!);
|
||||
this._gauge = undefined;
|
||||
}
|
||||
this._gauge = Gauge(this._gaugeElement, {
|
||||
min: this._config.min,
|
||||
max: this._config.max,
|
||||
dialStartAngle: 180,
|
||||
dialEndAngle: 0,
|
||||
viewBox: "0 0 100 55",
|
||||
label: (value) => `${Math.round(value)}
|
||||
${
|
||||
this._config!.unit ||
|
||||
this.hass?.states[this._config!.entity].attributes
|
||||
.unit_of_measurement ||
|
||||
""
|
||||
}`,
|
||||
color: (value) => {
|
||||
const sections = this._config!.severity;
|
||||
|
||||
if (!sections) {
|
||||
return severityMap.normal;
|
||||
}
|
||||
const sectionsArray = Object.keys(sections);
|
||||
const sortable = sectionsArray.map((severity) => [
|
||||
severity,
|
||||
sections[severity],
|
||||
]);
|
||||
|
||||
const sectionsArray = Object.keys(sections);
|
||||
const sortable = sectionsArray.map((severity) => [
|
||||
severity,
|
||||
sections[severity],
|
||||
]);
|
||||
|
||||
for (const severity of sortable) {
|
||||
if (severityMap[severity[0]] == null || isNaN(severity[1])) {
|
||||
return severityMap.normal;
|
||||
}
|
||||
}
|
||||
sortable.sort((a, b) => a[1] - b[1]);
|
||||
|
||||
if (value >= sortable[0][1] && value < sortable[1][1]) {
|
||||
return severityMap[sortable[0][0]];
|
||||
}
|
||||
if (value >= sortable[1][1] && value < sortable[2][1]) {
|
||||
return severityMap[sortable[1][0]];
|
||||
}
|
||||
if (value >= sortable[2][1]) {
|
||||
return severityMap[sortable[2][0]];
|
||||
}
|
||||
for (const severity of sortable) {
|
||||
if (severityMap[severity[0]] == null || isNaN(severity[1])) {
|
||||
return severityMap.normal;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
sortable.sort((a, b) => a[1] - b[1]);
|
||||
|
||||
if (numberValue >= sortable[0][1] && numberValue < sortable[1][1]) {
|
||||
return severityMap[sortable[0][0]];
|
||||
}
|
||||
if (numberValue >= sortable[1][1] && numberValue < sortable[2][1]) {
|
||||
return severityMap[sortable[1][0]];
|
||||
}
|
||||
if (numberValue >= sortable[2][1]) {
|
||||
return severityMap[sortable[2][0]];
|
||||
}
|
||||
return severityMap.normal;
|
||||
}
|
||||
|
||||
private _handleClick(): void {
|
||||
@ -244,31 +215,20 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
outline: none;
|
||||
background: var(--divider-color);
|
||||
}
|
||||
#gauge {
|
||||
|
||||
ha-gauge {
|
||||
--gauge-color: var(--label-badge-blue);
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
}
|
||||
.dial {
|
||||
stroke: #ccc;
|
||||
stroke-width: 15;
|
||||
}
|
||||
.value {
|
||||
stroke-width: 15;
|
||||
}
|
||||
.value-text {
|
||||
fill: var(--primary-text-color);
|
||||
font-size: var(--gauge-value-font-size, 1.1em);
|
||||
transform: translate(0, -5px);
|
||||
font-family: inherit;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
.name {
|
||||
text-align: center;
|
||||
line-height: initial;
|
||||
color: var(--primary-text-color);
|
||||
width: 100%;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
margin-top: 8px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ export class HuiHumidifierCard extends LitElement implements LovelaceCard {
|
||||
.min=${stateObj.attributes.min_humidity}
|
||||
.max=${stateObj.attributes.max_humidity}
|
||||
.rtl=${rtlDirection === "rtl"}
|
||||
.step="1"
|
||||
step="1"
|
||||
@value-changing=${this._dragEvent}
|
||||
@value-changed=${this._setHumidity}
|
||||
></round-slider>
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
PropertyValues,
|
||||
svg,
|
||||
TemplateResult,
|
||||
query,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { UNIT_F } from "../../../common/const";
|
||||
@ -33,6 +34,7 @@ import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import { createEntityNotFoundWarning } from "../components/hui-warning";
|
||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import { ThermostatCardConfig } from "./types";
|
||||
import type { HaCard } from "../../../components/ha-card";
|
||||
|
||||
const modeIcons: { [mode in HvacMode]: string } = {
|
||||
auto: "hass:calendar-sync",
|
||||
@ -77,6 +79,8 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
|
||||
@internalProperty() private _setTemp?: number | number[];
|
||||
|
||||
@query("ha-card") private _card?: HaCard;
|
||||
|
||||
public getCardSize(): number {
|
||||
return 5;
|
||||
}
|
||||
@ -290,18 +294,17 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
// That way it will auto-scale correctly
|
||||
// This is not done to the SVG containing the current temperature, because
|
||||
// it should not be centered on the text, but only on the value
|
||||
if (this.shadowRoot && this.shadowRoot.querySelector("ha-card")) {
|
||||
(this.shadowRoot.querySelector(
|
||||
"ha-card"
|
||||
) as LitElement).updateComplete.then(() => {
|
||||
const svgRoot = this.shadowRoot!.querySelector("#set-values");
|
||||
const box = svgRoot!.querySelector("g")!.getBBox();
|
||||
svgRoot!.setAttribute(
|
||||
const card = this._card;
|
||||
if (card) {
|
||||
card.updateComplete.then(() => {
|
||||
const svgRoot = this.shadowRoot!.querySelector("#set-values")!;
|
||||
const box = svgRoot.querySelector("g")!.getBBox()!;
|
||||
svgRoot.setAttribute(
|
||||
"viewBox",
|
||||
`${box!.x} ${box!.y} ${box!.width} ${box!.height}`
|
||||
`${box.x} ${box!.y} ${box.width} ${box.height}`
|
||||
);
|
||||
svgRoot!.setAttribute("width", `${box!.width}`);
|
||||
svgRoot!.setAttribute("height", `${box!.height}`);
|
||||
svgRoot.setAttribute("width", `${box.width}`);
|
||||
svgRoot.setAttribute("height", `${box.height}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||
import deepFreeze from "deep-freeze";
|
||||
import {
|
||||
css,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||
import deepFreeze from "deep-freeze";
|
||||
import {
|
||||
css,
|
||||
|
@ -98,7 +98,7 @@ class HuiInputNumberEntityRow extends LitElement implements LovelaceRow {
|
||||
no-label-float
|
||||
auto-validate
|
||||
.disabled=${UNAVAILABLE_STATES.includes(stateObj.state)}
|
||||
.pattern="[0-9]+([\\.][0-9]+)?"
|
||||
pattern="[0-9]+([\\.][0-9]+)?"
|
||||
.step="${Number(stateObj.attributes.step)}"
|
||||
.min="${Number(stateObj.attributes.min)}"
|
||||
.max="${Number(stateObj.attributes.max)}"
|
||||
|
@ -9,7 +9,7 @@ import { Constructor } from "../types";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import { HASSDomEvent } from "../common/dom/fire_event";
|
||||
|
||||
const DEBUG = true;
|
||||
const DEBUG = false;
|
||||
|
||||
export const urlSyncMixin = <T extends Constructor<HassBaseEl>>(
|
||||
superClass: T
|
||||
|
@ -70,9 +70,9 @@
|
||||
"armed_custom_bypass": "Zabezpečeno",
|
||||
"armed_home": "Zabezpečeno",
|
||||
"armed_night": "Zabezpečeno",
|
||||
"arming": "Aktivace",
|
||||
"arming": "Zabezpečování",
|
||||
"disarmed": "Nezabezpečeno",
|
||||
"disarming": "Deaktivace",
|
||||
"disarming": "Odbezpečování",
|
||||
"pending": "Čeká",
|
||||
"triggered": "Spuštěn"
|
||||
},
|
||||
@ -95,7 +95,7 @@
|
||||
"alarm_control_panel": {
|
||||
"armed": "Zabezpečeno",
|
||||
"armed_away": "Režim nepřítomnost",
|
||||
"armed_custom_bypass": "Aktivní uživatelským obejitím",
|
||||
"armed_custom_bypass": "Zabezpečeno uživatelským obejitím",
|
||||
"armed_home": "Režim domov",
|
||||
"armed_night": "Noční režim",
|
||||
"arming": "Zabezpečování",
|
||||
@ -430,6 +430,8 @@
|
||||
"activate": "Aktivovat"
|
||||
},
|
||||
"script": {
|
||||
"cancel": "Zrušit",
|
||||
"cancel_multiple": "Zrušit {number}",
|
||||
"execute": "Vykonat"
|
||||
},
|
||||
"service": {
|
||||
@ -525,6 +527,9 @@
|
||||
"clear": "Vymazat",
|
||||
"show_areas": "Zobrazit oblasti"
|
||||
},
|
||||
"data-table": {
|
||||
"search": "Hledat"
|
||||
},
|
||||
"date-range-picker": {
|
||||
"end_date": "Koncové datum",
|
||||
"select": "Vybrat",
|
||||
@ -938,6 +943,19 @@
|
||||
"introduction": "Použijte automatizace k oživení svého domova",
|
||||
"load_error_not_editable": "Lze upravovat pouze automatizace v automations.yaml.",
|
||||
"load_error_unknown": "Chyba při načítání automatizace ({err_no}).",
|
||||
"max": {
|
||||
"parallel": "Maximální počet paralelních spuštění",
|
||||
"queued": "Délka fronty"
|
||||
},
|
||||
"modes": {
|
||||
"description": "Režim určuje, co se stane, když je automatizace spuštěna a zároveň stále ještě běží akce na základě předchozího spuštění. Další informace naleznete na {documentation_link}.",
|
||||
"documentation": "Dokumentace automatizací",
|
||||
"label": "Režim",
|
||||
"parallel": "Paralelní (výchozí)",
|
||||
"queued": "Fronta",
|
||||
"restart": "Restart",
|
||||
"single": "Jediný"
|
||||
},
|
||||
"move_down": "Posunout dolů",
|
||||
"move_up": "Posunout nahoru",
|
||||
"save": "Uložit",
|
||||
@ -1356,6 +1374,7 @@
|
||||
"confirm_text": "Entity lze odebrat pouze v případě, že integrace již entity neposkytuje.",
|
||||
"confirm_title": "Chcete odstranit {number} entit?"
|
||||
},
|
||||
"search": "Hledat entitu",
|
||||
"selected": "{number} vybraných",
|
||||
"status": {
|
||||
"disabled": "Zakázáno",
|
||||
@ -1386,7 +1405,8 @@
|
||||
"entity_id": "ID entity",
|
||||
"name": "Název",
|
||||
"type": "Typ"
|
||||
}
|
||||
},
|
||||
"no_helpers": "Vypadá to, že ještě nemáte žádné pomocníky!"
|
||||
},
|
||||
"types": {
|
||||
"input_boolean": "Přepnout",
|
||||
@ -1490,7 +1510,8 @@
|
||||
"note_about_integrations": "Ne všechny integrace lze prozatím konfigurovat prostřednictvím uživatelského rozhraní.",
|
||||
"note_about_website_reference": "Další jsou k dispozici na ",
|
||||
"rename_dialog": "Upravit název této položky nastavení",
|
||||
"rename_input_label": "Název položky"
|
||||
"rename_input_label": "Název položky",
|
||||
"search": "Hledat integraci"
|
||||
},
|
||||
"introduction": "Zde je možné konfigurovat vaše komponenty a Home Assistant.\nZ uživatelského rozhraní sice zatím není možné konfigurovat vše, ale pracujeme na tom.",
|
||||
"logs": {
|
||||
@ -1643,6 +1664,7 @@
|
||||
"introduction": "Zde lze nastavit entity, které nepatří k zařízení.",
|
||||
"without_device": "Entity bez zařízení"
|
||||
},
|
||||
"icon": "Ikona",
|
||||
"introduction": "Pomocí scén oživte svůj domov.",
|
||||
"load_error_not_editable": "Lze upravovat pouze scény v souboru scenes.yaml.",
|
||||
"load_error_unknown": "Chyba při načítání scény ({err_no}).",
|
||||
@ -1676,9 +1698,26 @@
|
||||
"delete_confirm": "Opravdu chcete tento skript smazat?",
|
||||
"delete_script": "Smazat skript",
|
||||
"header": "Skript: {name}",
|
||||
"icon": "Ikona",
|
||||
"id": "ID entity",
|
||||
"id_already_exists": "Toto ID již existuje",
|
||||
"id_already_exists_save_error": "Tento skript nelze uložit, protože ID není jedinečné, vyberte jiné ID nebo jej nechte prázdné a bude automaticky vygenerováno.",
|
||||
"introduction": "K provedení posloupnosti akcí použijte skripty.",
|
||||
"link_available_actions": "Další informace o dostupných akcích.",
|
||||
"load_error_not_editable": "Upravovat lze pouze skripty uvnitř scripts.yaml.",
|
||||
"max": {
|
||||
"parallel": "Maximální počet paralelních spuštění",
|
||||
"queued": "Délka fronty"
|
||||
},
|
||||
"modes": {
|
||||
"description": "Režim určuje, co se stane, když je skript spuštěn a zároveň stále ještě běží na základě předchozího spuštění. Další informace naleznete na {documentation_link}.",
|
||||
"documentation": "Dokumentace skriptů",
|
||||
"label": "Režim",
|
||||
"parallel": "Paralelní (výchozí)",
|
||||
"queued": "Fronta",
|
||||
"restart": "Restart",
|
||||
"single": "Jediný (výchozí)"
|
||||
},
|
||||
"sequence": "Sekvence",
|
||||
"sequence_sentence": "Posloupnost akcí tohoto skriptu."
|
||||
},
|
||||
@ -2194,6 +2233,7 @@
|
||||
"name": "Název",
|
||||
"no_theme": "Žádný motiv",
|
||||
"refresh_interval": "Interval obnovení",
|
||||
"search": "Hledat",
|
||||
"secondary_info_attribute": "Sekundární informační atribut",
|
||||
"show_icon": "Zobrazit ikonu?",
|
||||
"show_name": "Zobrazit název?",
|
||||
@ -2314,7 +2354,8 @@
|
||||
"edit_lovelace": {
|
||||
"edit_title": "Upravit titulek",
|
||||
"explanation": "Tento název je zobrazen nad všemi vašimi zobrazeními v Lovelace.",
|
||||
"header": "Název vašeho uživatelského rozhraní Lovelace"
|
||||
"header": "Název vašeho uživatelského rozhraní Lovelace",
|
||||
"title": "Název"
|
||||
},
|
||||
"edit_view": {
|
||||
"add": "Přidat pohled",
|
||||
@ -2503,6 +2544,7 @@
|
||||
},
|
||||
"trusted_networks": {
|
||||
"abort": {
|
||||
"not_allowed": "Váš počítač není povolen.",
|
||||
"not_whitelisted": "Váš počítač není na seznamu povolených."
|
||||
},
|
||||
"step": {
|
||||
@ -2678,6 +2720,10 @@
|
||||
"not_used": "Nikdy nebylo použito",
|
||||
"token_title": "Obnovovací token pro {clientId}"
|
||||
},
|
||||
"suspend": {
|
||||
"description": "Měli bychom ukončit spojení se serverem, pokud není Home Assistant viditelný po dobu delší než 5 minut?",
|
||||
"header": "Automaticky ukončovat spojení"
|
||||
},
|
||||
"themes": {
|
||||
"dropdown_label": "Motiv",
|
||||
"error_no_theme": "Žádné motivy nejsou k dispozici.",
|
||||
|
@ -951,10 +951,10 @@
|
||||
"description": "The mode controls what happens when the automation is triggered while the actions are still running from a previous trigger. Check the {documentation_link} for more info.",
|
||||
"documentation": "automation documentation",
|
||||
"label": "Mode",
|
||||
"parallel": "Parallel (default)",
|
||||
"parallel": "Parallel",
|
||||
"queued": "Queued",
|
||||
"restart": "Restart",
|
||||
"single": "Single"
|
||||
"single": "Single (default)"
|
||||
},
|
||||
"move_down": "Move down",
|
||||
"move_up": "Move up",
|
||||
|
@ -430,6 +430,8 @@
|
||||
"activate": "Activar"
|
||||
},
|
||||
"script": {
|
||||
"cancel": "Cancelar",
|
||||
"cancel_multiple": "Cancelar {number}",
|
||||
"execute": "Ejecutar"
|
||||
},
|
||||
"service": {
|
||||
@ -941,6 +943,19 @@
|
||||
"introduction": "Utiliza automatizaciones para darle vida a tu hogar.",
|
||||
"load_error_not_editable": "Solo las automatizaciones en automations.yaml son editables.",
|
||||
"load_error_unknown": "Error al cargar la automatización ({err_no}).",
|
||||
"max": {
|
||||
"parallel": "Número máximo de ejecuciones paralelas",
|
||||
"queued": "Longitud de la cola"
|
||||
},
|
||||
"modes": {
|
||||
"description": "El modo controla lo que sucede cuando se activa la automatización mientras las acciones aún se ejecutan desde una activación anterior. Consulta la {documentation_link} para obtener más información.",
|
||||
"documentation": "documentación de automatización",
|
||||
"label": "Modo",
|
||||
"parallel": "Paralelo (predeterminado)",
|
||||
"queued": "En cola",
|
||||
"restart": "Reiniciar",
|
||||
"single": "Único"
|
||||
},
|
||||
"move_down": "Mover hacia abajo",
|
||||
"move_up": "Mover hacia arriba",
|
||||
"save": "Guardar",
|
||||
@ -1649,6 +1664,7 @@
|
||||
"introduction": "Las entidades que no pertenecen a un dispositivo se pueden configurar aquí.",
|
||||
"without_device": "Entidades sin dispositivo"
|
||||
},
|
||||
"icon": "Icono",
|
||||
"introduction": "Usa escenas para dar vida a tu hogar.",
|
||||
"load_error_not_editable": "Solo las escenas de scenes.yaml son editables.",
|
||||
"load_error_unknown": "Error al cargar la escena ({err_no}).",
|
||||
@ -1682,9 +1698,26 @@
|
||||
"delete_confirm": "¿Seguro que quieres eliminar este script?",
|
||||
"delete_script": "Eliminar script",
|
||||
"header": "Script: {name}",
|
||||
"icon": "Icono",
|
||||
"id": "ID de la entidad",
|
||||
"id_already_exists": "Este ID ya existe",
|
||||
"id_already_exists_save_error": "No puedes guardar este script porque el ID no es único, elije otro ID o déjalo en blanco para generar uno automáticamente.",
|
||||
"introduction": "Utiliza scripts para ejecutar una secuencia de acciones.",
|
||||
"link_available_actions": "Saber más sobre las acciones disponibles.",
|
||||
"load_error_not_editable": "Solo los scripts dentro de scripts.yaml son editables.",
|
||||
"max": {
|
||||
"parallel": "Número máximo de ejecuciones paralelas",
|
||||
"queued": "Longitud de la cola"
|
||||
},
|
||||
"modes": {
|
||||
"description": "El modo controla lo que sucede cuando se invoca el script mientras aún se ejecuta desde una o más invocaciones anteriores. Consulta la {documentation_link} para obtener más información.",
|
||||
"documentation": "documentación de script",
|
||||
"label": "Modo",
|
||||
"parallel": "Paralelo",
|
||||
"queued": "En cola",
|
||||
"restart": "Reiniciar",
|
||||
"single": "Único (predeterminado)"
|
||||
},
|
||||
"sequence": "Secuencia",
|
||||
"sequence_sentence": "La secuencia de acciones de este script."
|
||||
},
|
||||
@ -2511,6 +2544,7 @@
|
||||
},
|
||||
"trusted_networks": {
|
||||
"abort": {
|
||||
"not_allowed": "Tu equipo no está permitido.",
|
||||
"not_whitelisted": "Tu equipo no está en la lista de autorizados."
|
||||
},
|
||||
"step": {
|
||||
|
@ -430,6 +430,8 @@
|
||||
"activate": "Activer"
|
||||
},
|
||||
"script": {
|
||||
"cancel": "Annuler",
|
||||
"cancel_multiple": "Annuler {number}",
|
||||
"execute": "Exécuter"
|
||||
},
|
||||
"service": {
|
||||
@ -941,6 +943,18 @@
|
||||
"introduction": "Utilisez les automatisations pour donner vie à votre maison",
|
||||
"load_error_not_editable": "Seules les automatisations dans automations.yaml sont modifiables.",
|
||||
"load_error_unknown": "Erreur lors du chargement de l'automatisation ( {err_no} ).",
|
||||
"max": {
|
||||
"parallel": "Nombre maximal de parcours parallèles",
|
||||
"queued": "Longueur de la file d'attente"
|
||||
},
|
||||
"modes": {
|
||||
"description": "Le mode contrôle ce qui se passe lorsque l’automatisation est déclenchée alors que les actions sont toujours en cours d’exécution à partir d’un déclencheur précédent. Consultez le {documentation_link} pour plus d’informations.",
|
||||
"documentation": "documentation d'automatisation",
|
||||
"label": "Mode",
|
||||
"parallel": "Parallèle (par défaut)",
|
||||
"queued": "En attente",
|
||||
"restart": "Redémarrer"
|
||||
},
|
||||
"move_down": "Déplacer vers le bas",
|
||||
"move_up": "Déplacer vers le haut",
|
||||
"save": "Sauvegarder",
|
||||
@ -1649,6 +1663,7 @@
|
||||
"introduction": "Les entités n'appartenant pas à un périphérique peuvent être définies ici.",
|
||||
"without_device": "Entités sans appareil"
|
||||
},
|
||||
"icon": "Icône",
|
||||
"introduction": "Utilisez des scènes pour donner vie à votre maison.",
|
||||
"load_error_not_editable": "Seules les scènes de scenes.yaml sont modifiables.",
|
||||
"load_error_unknown": "Erreur de chargement de la scène ({err_no})",
|
||||
@ -1682,9 +1697,26 @@
|
||||
"delete_confirm": "Êtes-vous sûr de vouloir supprimer ce script?",
|
||||
"delete_script": "Supprimer le script",
|
||||
"header": "Script: {name}",
|
||||
"icon": "Icône",
|
||||
"id": "ID de l'entité",
|
||||
"id_already_exists": "Cet ID existe déjà",
|
||||
"id_already_exists_save_error": "Vous ne pouvez pas enregistrer ce script car l'ID n'est pas unique, choisissez un autre ID ou laissez-le vide pour en générer automatiquement un.",
|
||||
"introduction": "Utiliser des scripts pour exécuter une séquence d'actions.",
|
||||
"link_available_actions": "En savoir plus sur les actions disponibles.",
|
||||
"load_error_not_editable": "Seuls les scripts dans scripts.yaml sont modifiables.",
|
||||
"max": {
|
||||
"parallel": "Nombre maximal de parcours parallèles",
|
||||
"queued": "Longueur de la file d'attente"
|
||||
},
|
||||
"modes": {
|
||||
"description": "Le mode contrôle ce qui se passe lorsque le script est appelé alors qu’il est toujours en cours d’exécution à partir d’une ou plusieurs invocations précédentes. Consultez le {documentation_link} pour plus d’informations.",
|
||||
"documentation": "documentation script",
|
||||
"label": "Mode",
|
||||
"parallel": "Parallèle",
|
||||
"queued": "En attente",
|
||||
"restart": "Redémarrer",
|
||||
"single": "Unique (par défaut)"
|
||||
},
|
||||
"sequence": "Séquence",
|
||||
"sequence_sentence": "La séquence d'actions de ce script."
|
||||
},
|
||||
@ -2511,6 +2543,7 @@
|
||||
},
|
||||
"trusted_networks": {
|
||||
"abort": {
|
||||
"not_allowed": "Votre ordinateur n'est pas autorisé.",
|
||||
"not_whitelisted": "Votre ordinateur n'est pas en liste blanche."
|
||||
},
|
||||
"step": {
|
||||
|
@ -430,6 +430,8 @@
|
||||
"activate": "Активировать"
|
||||
},
|
||||
"script": {
|
||||
"cancel": "Отменить",
|
||||
"cancel_multiple": "Отменить {number}",
|
||||
"execute": "Выполнить"
|
||||
},
|
||||
"service": {
|
||||
@ -1654,6 +1656,7 @@
|
||||
"introduction": "Объекты, которые не связаны с каким-либо устройством, могут быть указаны здесь.",
|
||||
"without_device": "Объекты без устройств"
|
||||
},
|
||||
"icon": "Значок",
|
||||
"introduction": "Используйте сцены, чтобы оживить Ваш дом.",
|
||||
"load_error_not_editable": "Доступны для редактирования только сцены из scenes.yaml.",
|
||||
"load_error_unknown": "Ошибка загрузки сцены ({err_no}).",
|
||||
@ -1687,6 +1690,9 @@
|
||||
"delete_confirm": "Вы уверены, что хотите удалить этот сценарий?",
|
||||
"delete_script": "Удалить сценарий",
|
||||
"header": "Сценарий: {name}",
|
||||
"icon": "Значок",
|
||||
"id": "ID объекта",
|
||||
"id_already_exists": "Этот ID уже существует",
|
||||
"introduction": "Используйте сценарии для выполнения последовательности действий.",
|
||||
"link_available_actions": "Узнайте больше о действиях",
|
||||
"load_error_not_editable": "Доступны для редактирования только сценарии из scripts.yaml.",
|
||||
|
@ -430,6 +430,8 @@
|
||||
"activate": "啟用"
|
||||
},
|
||||
"script": {
|
||||
"cancel": "取消",
|
||||
"cancel_multiple": "取消 {number}",
|
||||
"execute": "執行"
|
||||
},
|
||||
"service": {
|
||||
@ -1662,6 +1664,7 @@
|
||||
"introduction": "不屬於設備的物件可以於此設置。",
|
||||
"without_device": "無設備物件"
|
||||
},
|
||||
"icon": "圖示",
|
||||
"introduction": "使用場景來讓你的智能家居更有魅力吧。",
|
||||
"load_error_not_editable": "僅有於 scenes.yaml 檔案內的場景、方能進行編輯。",
|
||||
"load_error_unknown": "載入場景錯誤({err_no})。",
|
||||
@ -1695,6 +1698,10 @@
|
||||
"delete_confirm": "確定要刪除此腳本?",
|
||||
"delete_script": "刪除腳本",
|
||||
"header": "腳本:{name}",
|
||||
"icon": "圖示",
|
||||
"id": "物件 ID",
|
||||
"id_already_exists": "該 ID 已存在",
|
||||
"id_already_exists_save_error": "由於該 ID 非獨一 ID,因此無法儲存此腳本。請選擇其他 ID 或者保留空白以自動產生。",
|
||||
"introduction": "使用腳本以執行一連串的動作。",
|
||||
"link_available_actions": "詳細了解可使用動作",
|
||||
"load_error_not_editable": "僅有於 scripts.yaml 檔案內的腳本,方能進行編輯。",
|
||||
|
@ -11305,11 +11305,6 @@ sver-compat@^1.5.0:
|
||||
es6-iterator "^2.0.1"
|
||||
es6-symbol "^3.1.1"
|
||||
|
||||
svg-gauge@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/svg-gauge/-/svg-gauge-1.0.6.tgz#1e84a366b1cce5b95dab3e33f41fdde867692d28"
|
||||
integrity sha512-gRkznVhtS18eOM/GMPDXAvrLZOpqzNVDg4bFAPAEjiDKd1tZHFIe8Bwt3G6TFg/H+pFboetPPI+zoV+bOL26QQ==
|
||||
|
||||
symbol-observable@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
|
||||
|
Loading…
x
Reference in New Issue
Block a user