diff --git a/package.json b/package.json index 7b4ada4548..9f61f7eba7 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/setup.py b/setup.py index 21c1ec8bc5..c068657406 100644 --- a/setup.py +++ b/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", diff --git a/src/components/ha-card.ts b/src/components/ha-card.ts index 8b2cbd8292..1c8fc43c97 100644 --- a/src/components/ha-card.ts +++ b/src/components/ha-card.ts @@ -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; diff --git a/src/components/ha-gauge.ts b/src/components/ha-gauge.ts new file mode 100644 index 0000000000..a33ba30cf2 --- /dev/null +++ b/src/components/ha-gauge.ts @@ -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` + + + + + + + ${this.value} ${this.label} + + `; + } + + 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; + } + `; + } +} diff --git a/src/components/ha-icon.ts b/src/components/ha-icon.ts index 07b802bd40..bd5092a806 100644 --- a/src/components/ha-icon.ts +++ b/src/components/ha-icon.ts @@ -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([ diff --git a/src/panels/lovelace/cards/hui-gauge-card.ts b/src/panels/lovelace/cards/hui-gauge-card.ts index 054ea20010..686f36a480 100644 --- a/src/panels/lovelace/cards/hui-gauge-card.ts +++ b/src/panels/lovelace/cards/hui-gauge-card.ts @@ -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` -
+
${this._config.name || computeStateName(stateObj)}
@@ -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; } `; } diff --git a/src/panels/lovelace/cards/hui-humidifier-card.ts b/src/panels/lovelace/cards/hui-humidifier-card.ts index bb583ad366..2f8ba20d7c 100644 --- a/src/panels/lovelace/cards/hui-humidifier-card.ts +++ b/src/panels/lovelace/cards/hui-humidifier-card.ts @@ -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} > diff --git a/src/panels/lovelace/cards/hui-thermostat-card.ts b/src/panels/lovelace/cards/hui-thermostat-card.ts index ea254bd21f..04a7a8a1ac 100644 --- a/src/panels/lovelace/cards/hui-thermostat-card.ts +++ b/src/panels/lovelace/cards/hui-thermostat-card.ts @@ -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}`); }); } } diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-delete-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-delete-card.ts index 18c8015f3c..08f3678efc 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-delete-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-delete-card.ts @@ -1,3 +1,4 @@ +import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable"; import deepFreeze from "deep-freeze"; import { css, diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts index 5664aafda6..1a3075b86a 100755 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts @@ -1,3 +1,4 @@ +import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable"; import deepFreeze from "deep-freeze"; import { css, diff --git a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts index 775626dede..219fa2c237 100644 --- a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts @@ -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)}" diff --git a/src/state/url-sync-mixin.ts b/src/state/url-sync-mixin.ts index ae5078e5d0..e564963cc1 100644 --- a/src/state/url-sync-mixin.ts +++ b/src/state/url-sync-mixin.ts @@ -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 = >( superClass: T diff --git a/translations/frontend/cs.json b/translations/frontend/cs.json index 6ab2b5b713..db41b222b9 100644 --- a/translations/frontend/cs.json +++ b/translations/frontend/cs.json @@ -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.", diff --git a/translations/frontend/en.json b/translations/frontend/en.json index e41284926c..d3e41b83da 100644 --- a/translations/frontend/en.json +++ b/translations/frontend/en.json @@ -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", diff --git a/translations/frontend/es.json b/translations/frontend/es.json index 0bf1709566..eb77162f88 100644 --- a/translations/frontend/es.json +++ b/translations/frontend/es.json @@ -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": { diff --git a/translations/frontend/fr.json b/translations/frontend/fr.json index 4da2ae549d..39fad0f3e4 100644 --- a/translations/frontend/fr.json +++ b/translations/frontend/fr.json @@ -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": { diff --git a/translations/frontend/ru.json b/translations/frontend/ru.json index ebab530ffd..4829e3fd4b 100644 --- a/translations/frontend/ru.json +++ b/translations/frontend/ru.json @@ -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.", diff --git a/translations/frontend/zh-Hant.json b/translations/frontend/zh-Hant.json index b6d8ba5e07..d42e58a88c 100644 --- a/translations/frontend/zh-Hant.json +++ b/translations/frontend/zh-Hant.json @@ -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 檔案內的腳本,方能進行編輯。", diff --git a/yarn.lock b/yarn.lock index 50621e3fee..9701db610f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"