mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-22 08:46:35 +00:00
Merge pull request #6291 from home-assistant/dev
This commit is contained in:
commit
9ac8d70152
2
setup.py
2
setup.py
@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="home-assistant-frontend",
|
||||
version="20200629.0",
|
||||
version="20200701.0",
|
||||
description="The Home Assistant frontend",
|
||||
url="https://github.com/home-assistant/home-assistant-polymer",
|
||||
author="The Home Assistant Authors",
|
||||
|
33
src/common/decorators/restore-scroll.ts
Normal file
33
src/common/decorators/restore-scroll.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import type { LitElement } from "lit-element";
|
||||
import type { ClassElement } from "../../types";
|
||||
|
||||
export const restoreScroll = (selector: string): any => {
|
||||
return (element: ClassElement) => ({
|
||||
kind: "method",
|
||||
placement: "prototype",
|
||||
key: element.key,
|
||||
descriptor: {
|
||||
set(this: LitElement, value: number) {
|
||||
this[`__${String(element.key)}`] = value;
|
||||
},
|
||||
get(this: LitElement) {
|
||||
return this[`__${String(element.key)}`];
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
},
|
||||
finisher(cls: typeof LitElement) {
|
||||
const connectedCallback = cls.prototype.connectedCallback;
|
||||
cls.prototype.connectedCallback = function () {
|
||||
connectedCallback.call(this);
|
||||
if (this[element.key]) {
|
||||
const target = this.renderRoot.querySelector(selector);
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
target.scrollTop = this[element.key];
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
};
|
@ -9,6 +9,8 @@ import {
|
||||
PropertyValues,
|
||||
query,
|
||||
TemplateResult,
|
||||
eventOptions,
|
||||
internalProperty,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { ifDefined } from "lit-html/directives/if-defined";
|
||||
@ -23,6 +25,7 @@ import type { HaCheckbox } from "../ha-checkbox";
|
||||
import "../ha-icon";
|
||||
import { filterData, sortData } from "./sort-filter";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { restoreScroll } from "../../common/decorators/restore-scroll";
|
||||
|
||||
declare global {
|
||||
// for fire event
|
||||
@ -96,15 +99,15 @@ export class HaDataTable extends LitElement {
|
||||
|
||||
@property({ type: String }) public filter = "";
|
||||
|
||||
@property({ type: Boolean }) private _filterable = false;
|
||||
@internalProperty() private _filterable = false;
|
||||
|
||||
@property({ type: String }) private _filter = "";
|
||||
@internalProperty() private _filter = "";
|
||||
|
||||
@property({ type: String }) private _sortColumn?: string;
|
||||
@internalProperty() private _sortColumn?: string;
|
||||
|
||||
@property({ type: String }) private _sortDirection: SortingDirection = null;
|
||||
@internalProperty() private _sortDirection: SortingDirection = null;
|
||||
|
||||
@property({ type: Array }) private _filteredData: DataTableRowData[] = [];
|
||||
@internalProperty() private _filteredData: DataTableRowData[] = [];
|
||||
|
||||
@query("slot[name='header']") private _header!: HTMLSlotElement;
|
||||
|
||||
@ -118,6 +121,9 @@ export class HaDataTable extends LitElement {
|
||||
|
||||
private curRequest = 0;
|
||||
|
||||
// @ts-ignore
|
||||
@restoreScroll(".scroller") private _savedScrollPos?: number;
|
||||
|
||||
private _debounceSearch = debounce(
|
||||
(value: string) => {
|
||||
this._filter = value;
|
||||
@ -286,7 +292,10 @@ export class HaDataTable extends LitElement {
|
||||
</div>
|
||||
`
|
||||
: html`
|
||||
<div class="mdc-data-table__content scroller">
|
||||
<div
|
||||
class="mdc-data-table__content scroller"
|
||||
@scroll=${this._saveScrollPos}
|
||||
>
|
||||
${scroll({
|
||||
items: !this.hasFab
|
||||
? this._filteredData
|
||||
@ -499,6 +508,11 @@ export class HaDataTable extends LitElement {
|
||||
this._table.style.height = `calc(100% - ${this._header.clientHeight}px)`;
|
||||
}
|
||||
|
||||
@eventOptions({ passive: true })
|
||||
private _saveScrollPos(e: Event) {
|
||||
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
/* default mdc styles, colors changed, without checkbox styles */
|
||||
|
@ -6,10 +6,12 @@ import {
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
eventOptions,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import "../components/ha-menu-button";
|
||||
import "../components/ha-icon-button-arrow-prev";
|
||||
import { restoreScroll } from "../common/decorators/restore-scroll";
|
||||
|
||||
@customElement("hass-subpage")
|
||||
class HassSubpage extends LitElement {
|
||||
@ -22,6 +24,9 @@ class HassSubpage extends LitElement {
|
||||
@property({ type: Boolean })
|
||||
public hassio = false;
|
||||
|
||||
// @ts-ignore
|
||||
@restoreScroll(".content") private _savedScrollPos?: number;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div class="toolbar">
|
||||
@ -34,10 +39,15 @@ class HassSubpage extends LitElement {
|
||||
<div main-title>${this.header}</div>
|
||||
<slot name="toolbar-icon"></slot>
|
||||
</div>
|
||||
<div class="content"><slot></slot></div>
|
||||
<div class="content" @scroll=${this._saveScrollPos}><slot></slot></div>
|
||||
`;
|
||||
}
|
||||
|
||||
@eventOptions({ passive: true })
|
||||
private _saveScrollPos(e: Event) {
|
||||
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
|
||||
}
|
||||
|
||||
private _backTapped(): void {
|
||||
history.back();
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
property,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
eventOptions,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
@ -19,6 +20,7 @@ import { HomeAssistant, Route } from "../types";
|
||||
import "../components/ha-svg-icon";
|
||||
import "../components/ha-icon";
|
||||
import "../components/ha-tab";
|
||||
import { restoreScroll } from "../common/decorators/restore-scroll";
|
||||
|
||||
export interface PageNavigation {
|
||||
path: string;
|
||||
@ -52,6 +54,9 @@ class HassTabsSubpage extends LitElement {
|
||||
|
||||
@property() private _activeTab?: PageNavigation;
|
||||
|
||||
// @ts-ignore
|
||||
@restoreScroll(".content") private _savedScrollPos?: number;
|
||||
|
||||
private _getTabs = memoizeOne(
|
||||
(
|
||||
tabs: PageNavigation[],
|
||||
@ -143,12 +148,17 @@ class HassTabsSubpage extends LitElement {
|
||||
<slot name="toolbar-icon"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="content" @scroll=${this._saveScrollPos}>
|
||||
<slot></slot>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@eventOptions({ passive: true })
|
||||
private _saveScrollPos(e: Event) {
|
||||
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
|
||||
}
|
||||
|
||||
private _tabTapped(ev: Event): void {
|
||||
navigate(this, (ev.currentTarget as any).path, true);
|
||||
}
|
||||
|
@ -185,8 +185,7 @@ class PartialPanelResolver extends HassRouterPage {
|
||||
curPanel.component_name !== "iframe" &&
|
||||
// Do not disconnect any custom panel that embeds into iframe (ie hassio)
|
||||
(curPanel.component_name !== "custom" ||
|
||||
!(curPanel.config as CustomPanelInfo).config._panel_custom
|
||||
.embed_iframe)
|
||||
!(curPanel as CustomPanelInfo).config._panel_custom.embed_iframe)
|
||||
) {
|
||||
this._disconnectedPanel = this.lastChild as HTMLElement;
|
||||
const activeEl = deepActiveElement(
|
||||
|
@ -62,7 +62,7 @@ class PanelCalendar extends LitElement {
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header-layout>
|
||||
<app-header fixed slot="header">
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
|
@ -127,7 +127,7 @@ class HaConfigDashboard extends LitElement {
|
||||
}
|
||||
|
||||
return html`
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header-layout>
|
||||
<app-header fixed slot="header">
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
|
@ -47,7 +47,11 @@ import {
|
||||
EntityRegistryEntry,
|
||||
subscribeEntityRegistry,
|
||||
} from "../../../data/entity_registry";
|
||||
import { domainToName } from "../../../data/integration";
|
||||
import {
|
||||
domainToName,
|
||||
fetchIntegrationManifests,
|
||||
IntegrationManifest,
|
||||
} from "../../../data/integration";
|
||||
import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-config-flow";
|
||||
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||
import "../../../layouts/hass-loading-screen";
|
||||
@ -106,6 +110,8 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
|
||||
|
||||
@property() private _deviceRegistryEntries: DeviceRegistryEntry[] = [];
|
||||
|
||||
@property() private _manifests!: { [domain: string]: IntegrationManifest };
|
||||
|
||||
@property() private _showIgnored = false;
|
||||
|
||||
@property() private _searchParms = new URLSearchParams(
|
||||
@ -211,6 +217,7 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
|
||||
super.firstUpdated(changed);
|
||||
this._loadConfigEntries();
|
||||
this.hass.loadBackendTranslation("title", undefined, true);
|
||||
this._fetchManifests();
|
||||
}
|
||||
|
||||
protected updated(changed: PropertyValues) {
|
||||
@ -390,6 +397,7 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
|
||||
.hass=${this.hass}
|
||||
.domain=${domain}
|
||||
.items=${items}
|
||||
.manifest=${this._manifests[domain]}
|
||||
.entityRegistryEntries=${this._entityRegistryEntries}
|
||||
.deviceRegistryEntries=${this._deviceRegistryEntries}
|
||||
></ha-integration-card>`
|
||||
@ -470,6 +478,13 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
|
||||
});
|
||||
}
|
||||
|
||||
private async _fetchManifests() {
|
||||
const manifests = {};
|
||||
const fetched = await fetchIntegrationManifests(this.hass);
|
||||
for (const manifest of fetched) manifests[manifest.domain] = manifest;
|
||||
this._manifests = manifests;
|
||||
}
|
||||
|
||||
private _handleRemoved(ev: HASSDomEvent<ConfigEntryRemovedEvent>) {
|
||||
this._configEntries = this._configEntries!.filter(
|
||||
(entry) => entry.entry_id !== ev.detail.entryId
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { ConfigEntryExtended } from "./ha-config-integrations";
|
||||
import { domainToName } from "../../../data/integration";
|
||||
import { domainToName, IntegrationManifest } from "../../../data/integration";
|
||||
import {
|
||||
ConfigEntry,
|
||||
updateConfigEntry,
|
||||
@ -27,7 +27,7 @@ import {
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
import "../../../components/ha-icon-next";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { mdiDotsVertical } from "@mdi/js";
|
||||
import { mdiDotsVertical, mdiOpenInNew } from "@mdi/js";
|
||||
|
||||
export interface ConfigEntryUpdatedEvent {
|
||||
entry: ConfigEntry;
|
||||
@ -68,12 +68,18 @@ export class HaIntegrationCard extends LitElement {
|
||||
|
||||
@property() public items!: ConfigEntryExtended[];
|
||||
|
||||
@property() public manifest!: IntegrationManifest;
|
||||
|
||||
@property() public entityRegistryEntries!: EntityRegistryEntry[];
|
||||
|
||||
@property() public deviceRegistryEntries!: DeviceRegistryEntry[];
|
||||
|
||||
@property() public selectedConfigEntryId?: string;
|
||||
|
||||
firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (this.items.length === 1) {
|
||||
return this._renderSingleEntry(this.items[0]);
|
||||
@ -125,6 +131,7 @@ export class HaIntegrationCard extends LitElement {
|
||||
private _renderSingleEntry(item: ConfigEntryExtended): TemplateResult {
|
||||
const devices = this._getDevices(item);
|
||||
const entities = this._getEntities(item);
|
||||
|
||||
return html`
|
||||
<ha-card
|
||||
outlined
|
||||
@ -229,6 +236,25 @@ export class HaIntegrationCard extends LitElement {
|
||||
"ui.panel.config.integrations.config_entry.system_options"
|
||||
)}
|
||||
</mwc-list-item>
|
||||
${!this.manifest
|
||||
? ""
|
||||
: html`
|
||||
<a
|
||||
class="documentation"
|
||||
href=${this.manifest.documentation}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<mwc-list-item hasMeta>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.integrations.config_entry.documentation"
|
||||
)}<ha-svg-icon
|
||||
slot="meta"
|
||||
.path=${mdiOpenInNew}
|
||||
></ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
</a>
|
||||
`}
|
||||
<mwc-list-item class="warning" @click=${this._removeIntegration}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.integrations.config_entry.delete"
|
||||
@ -360,6 +386,9 @@ export class HaIntegrationCard extends LitElement {
|
||||
align-items: center;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.card-actions .documentation {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.group-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -402,6 +431,7 @@ export class HaIntegrationCard extends LitElement {
|
||||
}
|
||||
ha-button-menu {
|
||||
color: var(--secondary-text-color);
|
||||
--mdc-menu-min-width: 200px;
|
||||
}
|
||||
@media (min-width: 563px) {
|
||||
paper-listbox {
|
||||
|
@ -89,7 +89,7 @@ class HaConfigZwave extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<ha-app-layout>
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<ha-icon-button-arrow-prev
|
||||
|
@ -36,7 +36,7 @@ class PanelDeveloperTools extends LitElement {
|
||||
protected render(): TemplateResult {
|
||||
const page = this._page;
|
||||
return html`
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header-layout>
|
||||
<app-header fixed slot="header">
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
|
@ -50,7 +50,7 @@ class HaPanelHistory extends LitElement {
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header-layout>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
property,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
eventOptions,
|
||||
} from "lit-element";
|
||||
import { scroll } from "lit-virtualizer";
|
||||
import { formatDate } from "../../common/datetime/format_date";
|
||||
@ -17,6 +18,7 @@ import { computeRTL } from "../../common/util/compute_rtl";
|
||||
import "../../components/ha-icon";
|
||||
import { LogbookEntry } from "../../data/logbook";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { restoreScroll } from "../../common/decorators/restore-scroll";
|
||||
|
||||
class HaLogbook extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@ -29,6 +31,9 @@ class HaLogbook extends LitElement {
|
||||
// @ts-ignore
|
||||
private _rtl = false;
|
||||
|
||||
// @ts-ignore
|
||||
@restoreScroll(".container") private _savedScrollPos?: number;
|
||||
|
||||
protected shouldUpdate(changedProps: PropertyValues) {
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
const languageChanged =
|
||||
@ -50,7 +55,7 @@ class HaLogbook extends LitElement {
|
||||
}
|
||||
|
||||
return html`
|
||||
<div class="container">
|
||||
<div class="container" @scroll=${this._saveScrollPos}>
|
||||
${scroll({
|
||||
items: this.entries,
|
||||
renderItem: (item: LogbookEntry, index?: number) =>
|
||||
@ -116,6 +121,11 @@ class HaLogbook extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
@eventOptions({ passive: true })
|
||||
private _saveScrollPos(e: Event) {
|
||||
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
|
||||
}
|
||||
|
||||
private _entityClicked(ev: Event) {
|
||||
ev.preventDefault();
|
||||
fireEvent(this, "hass-more-info", {
|
||||
|
@ -72,7 +72,7 @@ export class HaPanelLogbook extends LitElement {
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header-layout>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
mdiPencil,
|
||||
mdiHelpCircle,
|
||||
} from "@mdi/js";
|
||||
import "@polymer/app-layout/app-header-layout/app-header-layout";
|
||||
import "@polymer/app-layout/app-header/app-header";
|
||||
import "@polymer/app-layout/app-scroll-effects/effects/waterfall";
|
||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||
|
@ -76,7 +76,7 @@ class HaPanelMailbox extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header-layout>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
|
@ -68,7 +68,7 @@ class HaPanelProfile extends LitElement {
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header-layout>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
|
@ -68,7 +68,7 @@ class HaPanelShoppingList extends LocalizeMixin(PolymerElement) {
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header-layout>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
|
@ -1469,6 +1469,7 @@
|
||||
"rename": "Rename",
|
||||
"options": "Options",
|
||||
"system_options": "System options",
|
||||
"documentation": "Documentation",
|
||||
"delete": "Delete",
|
||||
"delete_confirm": "Are you sure you want to delete this integration?",
|
||||
"restart_confirm": "Restart Home Assistant to finish removing this integration",
|
||||
|
10
src/types.ts
10
src/types.ts
@ -47,6 +47,16 @@ declare global {
|
||||
|
||||
export type Constructor<T = {}> = new (...args: any[]) => T;
|
||||
|
||||
export interface ClassElement {
|
||||
kind: "field" | "method";
|
||||
key: PropertyKey;
|
||||
placement: "static" | "prototype" | "own";
|
||||
initializer?: Function;
|
||||
extras?: ClassElement[];
|
||||
finisher?: <T>(cls: Constructor<T>) => undefined | Constructor<T>;
|
||||
descriptor?: PropertyDescriptor;
|
||||
}
|
||||
|
||||
export interface WebhookError {
|
||||
code: number;
|
||||
message: string;
|
||||
|
@ -646,7 +646,7 @@
|
||||
"pattern": "Patró Regex per a la validació de client",
|
||||
"text": "Text"
|
||||
},
|
||||
"platform_not_loaded": "La integració {platform} no està carregada, afegeix-la a la teva configuració mitjançant 'default_config:' o bé ''{platform}:''.",
|
||||
"platform_not_loaded": "La integració {platform} no està carregada. Afegeix-la a la teva configuració afegint 'default_config:' o bé ''{platform}:''.",
|
||||
"required_error_msg": "Aquest camp és obligatori",
|
||||
"yaml_not_editable": "La configuració d'aquesta entitat no es pot editar des de la interfície d'usuari. Només es poden editar des de la interfície aquelles entitats que s'han configurat des d'ella."
|
||||
},
|
||||
|
@ -646,7 +646,7 @@
|
||||
"pattern": "Regex pattern for client-side validation",
|
||||
"text": "Text"
|
||||
},
|
||||
"platform_not_loaded": "The {platform} integration is not loaded. Please add it your configuration either by adding 'default_config:' or ''{platform}:''.",
|
||||
"platform_not_loaded": "The {platform} integration is not loaded. Please add it to your configuration either by adding 'default_config:' or ''{platform}:''.",
|
||||
"required_error_msg": "This field is required",
|
||||
"yaml_not_editable": "The settings of this entity cannot be edited from the UI. Only entities set up from the UI are configurable from the UI."
|
||||
},
|
||||
@ -1431,6 +1431,7 @@
|
||||
"delete_confirm": "Are you sure you want to delete this integration?",
|
||||
"device_unavailable": "device unavailable",
|
||||
"devices": "{count} {count, plural,\n one {device}\n other {devices}\n}",
|
||||
"documentation": "Documentation",
|
||||
"entities": "{count} {count, plural,\n one {entity}\n other {entities}\n}",
|
||||
"entity_unavailable": "entity unavailable",
|
||||
"firmware": "Firmware: {version}",
|
||||
|
@ -48,6 +48,19 @@
|
||||
"none": "Asettamatta",
|
||||
"sleep": "Nukkumassa"
|
||||
}
|
||||
},
|
||||
"humidifier": {
|
||||
"mode": {
|
||||
"auto": "Automaatilla",
|
||||
"away": "Poissa",
|
||||
"baby": "Vauva",
|
||||
"boost": "Tehostus",
|
||||
"comfort": "Mukavuus",
|
||||
"eco": "Ekonominen",
|
||||
"home": "Koti",
|
||||
"normal": "Normaali",
|
||||
"sleep": "Nukkumassa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"state_badge": {
|
||||
@ -388,6 +401,12 @@
|
||||
"reverse": "Taaksepäin",
|
||||
"speed": "Nopeus"
|
||||
},
|
||||
"humidifier": {
|
||||
"humidity": "Tavoitekosteus",
|
||||
"mode": "Tila",
|
||||
"on_entity": "{name} päällä",
|
||||
"target_humidity_entity": "{name} tavoitekosteus"
|
||||
},
|
||||
"light": {
|
||||
"brightness": "Kirkkaus",
|
||||
"color_temperature": "Värilämpötila",
|
||||
@ -627,7 +646,7 @@
|
||||
"pattern": "Regex-malli käyttäjäpuolen validointia varten.",
|
||||
"text": "Teksti"
|
||||
},
|
||||
"platform_not_loaded": "Integrointia {platform} ei ole ladattu. Voit ladata sen llisäämällä \"default_config:\" tai ''{platform}:'' konfiguraatiotiedostoon.",
|
||||
"platform_not_loaded": "Integrointia {platform} ei ole ladattu. Voit ladata sen lisäämällä \"default_config:\" tai ''{platform}:'' konfiguraatiotiedostoon.",
|
||||
"required_error_msg": "Tämä kenttä on pakollinen",
|
||||
"yaml_not_editable": "Tämän kohteen asetuksia ei voi muokata käyttöliittymästä. Vain käyttöliittymästä määritetyt kohteet ovat määritettävissä käyttöliittymästä."
|
||||
},
|
||||
@ -2006,7 +2025,7 @@
|
||||
"column_example": "Esimerkki",
|
||||
"column_parameter": "Parametri",
|
||||
"data": "Palvelutiedot (YAML, valinnainen)",
|
||||
"description": "Service dev -työkalun avulla voit kutsua mitMitä tahansa käytettävissä olevaan palvelua Home Assistant -sovelluksessa.",
|
||||
"description": "Service dev -työkalun avulla voit kutsua mitä tahansa käytettävissä olevaan palvelua Home Assistant -sovelluksessa.",
|
||||
"fill_example_data": "Täytä esimerkkitiedoilla",
|
||||
"no_description": "Kuvausta ei ole saatavilla",
|
||||
"no_parameters": "Tämä palvelu ei ota parametreja.",
|
||||
@ -2198,6 +2217,10 @@
|
||||
"description": "Vaakapinokortin avulla voit pinota yhteen useita kortteja, jolloin ne ovat aina vierekkäin yhden sarakkeen tilassa.",
|
||||
"name": "Vaakapino"
|
||||
},
|
||||
"humidifier": {
|
||||
"description": "Ilmankostutin-kortti antaa hallita ilmankostutin kokonaisuutta. Voit muuttaa kosteus ja tila asetusta.",
|
||||
"name": "Ilmankostutin"
|
||||
},
|
||||
"iframe": {
|
||||
"description": "Verkkosivukortin avulla voit upottaa suosikkiverkkosivusi suoraan Home Assistantiin.",
|
||||
"name": "iFrame"
|
||||
|
@ -502,6 +502,7 @@
|
||||
"menu": "Menu",
|
||||
"next": "Nächst",
|
||||
"no": "Nee",
|
||||
"overflow_menu": "Iwwerlaf menu",
|
||||
"previous": "Virdrun",
|
||||
"refresh": "Aktualiséieren",
|
||||
"save": "Späicheren",
|
||||
@ -1769,6 +1770,8 @@
|
||||
"discovered_text": "Apparater tauchen hei op soubaal se entdeckt sinn.",
|
||||
"discovery_text": "Entdeckten Apparater tauchen op dëser Platz op. Suivéiert d'Instruktiounen fir är Apparater an aktivéiert den Kupplung's Mod.",
|
||||
"header": "Zigbee Home Automation - Apparater dobäisetzen",
|
||||
"no_devices_found": "Keng Apparater fonnt, stell sécher dass sie am Kopplung Modus sinn a vermedi dass sie während der Entdeckung net an de Stand by ginn.",
|
||||
"pairing_mode": "Stell sécher dass deng Apparater sech am Kopplungs Modus befannen. Kuckt d'Instruktioune vun dengen Apparater wéi dat geht.",
|
||||
"search_again": "Nach emol sichen",
|
||||
"spinner": "Sicht no ZHA Zigbee Apparater..."
|
||||
},
|
||||
@ -2210,6 +2213,7 @@
|
||||
"name": "Horizontale Stapel"
|
||||
},
|
||||
"humidifier": {
|
||||
"description": "Loftbefiichter Kaart gëtt dir Kontroll iwwert ee Loftbefiichter. Erlaabt et dir d'Fiichtegkeet a Betriibs Modus anzestellen.",
|
||||
"name": "Loftbefiichter"
|
||||
},
|
||||
"iframe": {
|
||||
|
@ -646,7 +646,7 @@
|
||||
"pattern": "Шаблон регулярного выражения для проверки на стороне клиента",
|
||||
"text": "Текст"
|
||||
},
|
||||
"platform_not_loaded": "Интеграция '{platform}' не загружена. Добавьте в YAML-конфигурацию 'default_config:' или '{platform}:'.",
|
||||
"platform_not_loaded": "Интеграция {platform} не загружена. Добавьте в YAML-конфигурацию 'default_config:' или ''{platform}:''.",
|
||||
"required_error_msg": "Обязательное поле",
|
||||
"yaml_not_editable": "Настройки этого объекта нельзя изменить из пользовательского интерфейса. Настраиваться из пользовательского интерфейса могут только те объекты, которые были созданы в нём."
|
||||
},
|
||||
|
@ -41,6 +41,19 @@
|
||||
"none": "Không",
|
||||
"sleep": "Ngủ"
|
||||
}
|
||||
},
|
||||
"humidifier": {
|
||||
"mode": {
|
||||
"auto": "Tự động",
|
||||
"away": "Đi vắng",
|
||||
"baby": "Trẻ em",
|
||||
"boost": "Tăng cường",
|
||||
"comfort": "Thoải mái",
|
||||
"eco": "Tiết kiệm",
|
||||
"home": "Ở nhà",
|
||||
"normal": "Bình thường",
|
||||
"sleep": "Ngủ"
|
||||
}
|
||||
}
|
||||
},
|
||||
"state_badge": {
|
||||
@ -376,6 +389,12 @@
|
||||
"oscillate": "Dao động",
|
||||
"speed": "Tốc độ"
|
||||
},
|
||||
"humidifier": {
|
||||
"humidity": "Độ ẩm mong muốn",
|
||||
"mode": "Chế độ",
|
||||
"on_entity": "{name} bật",
|
||||
"target_humidity_entity": "{name} độ ẩm mong muốn"
|
||||
},
|
||||
"light": {
|
||||
"brightness": "Độ sáng",
|
||||
"color_temperature": "Nhiệt độ màu",
|
||||
@ -424,6 +443,7 @@
|
||||
"attributes": {
|
||||
"air_pressure": "Áp suất không khí",
|
||||
"humidity": "Độ ẩm",
|
||||
"precipitation": "Lượng mưa",
|
||||
"temperature": "Nhiệt độ",
|
||||
"visibility": "Tầm nhìn",
|
||||
"wind_speed": "Tốc độ gió"
|
||||
@ -484,6 +504,11 @@
|
||||
"clear": "Xoá",
|
||||
"show_areas": "Hiển thị các khu vực"
|
||||
},
|
||||
"date-range-picker": {
|
||||
"end_date": "Ngày kết thúc",
|
||||
"select": "Lựa chọn",
|
||||
"start_date": "Ngày bắt đầu"
|
||||
},
|
||||
"device-picker": {
|
||||
"clear": "Xoá",
|
||||
"device": "Thiết bị",
|
||||
@ -543,6 +568,7 @@
|
||||
"enabled_description": "Các thực thể bị vô hiệu hóa sẽ không được thêm vào Home Assistant.",
|
||||
"enabled_label": "Kích hoạt thực thể",
|
||||
"entity_id": "Mã định danh Thực thể",
|
||||
"icon": "Ghi đè Biểu tượng",
|
||||
"icon_error": "Các biểu tượng phải ở định dạng 'tiền tố:tên biểu tượng', ví dụ như 'mdi:home'",
|
||||
"name": "Ghi đè Tên",
|
||||
"note": "Lưu ý: điều này có thể không hoạt động với tất cả các tích hợp.",
|
||||
@ -594,7 +620,8 @@
|
||||
"text": "Văn bản"
|
||||
},
|
||||
"platform_not_loaded": "Tích hợp {platform} không được nạp. Hãy thêm nó vào cấu hình của bạn bằng cách thêm 'default_config:' hoặc ''{platform}:''.",
|
||||
"required_error_msg": "Trường này là cần thiết"
|
||||
"required_error_msg": "Trường này là cần thiết",
|
||||
"yaml_not_editable": "Không thể sửa cài đặt của thực thể này từ giao diện người dùng. Chỉ các thực thể được thiết lập từ giao diện người dùng mới có thể được sửa chữa từ giao diện người dùng."
|
||||
},
|
||||
"more_info_control": {
|
||||
"edit": "Chỉnh sửa thực thể",
|
||||
@ -650,8 +677,12 @@
|
||||
"zha_device_info": {
|
||||
"buttons": {
|
||||
"add": "Thêm thiết bị",
|
||||
"clusters": "Quản lý các Cluster",
|
||||
"zigbee_information": "Chữ ký thiết bị ZigBee"
|
||||
},
|
||||
"confirmations": {
|
||||
"remove": "Bạn có chắc muốn xoá bỏ thiết bị không?"
|
||||
},
|
||||
"device_signature": "Chữ ký thiết bị ZigBee",
|
||||
"services": {
|
||||
"zigbee_information": "Xem thông tin Zigbee của thiết bị."
|
||||
@ -1057,11 +1088,16 @@
|
||||
},
|
||||
"introduction": "Home Assistant giữ một sổ đăng ký của mọi thực thể mà nó từng thấy có thể được xác định duy nhất. Mỗi thực thể này sẽ có một ID thực thể được gán sẽ chỉ dành riêng cho thực thể này.",
|
||||
"introduction2": "Sử dụng sổ đăng ký thực thể để ghi đè tên, thay đổi ID thực thể hoặc xóa mục nhập khỏi Home Assistant. Lưu ý, xóa mục đăng ký thực thể sẽ không xóa thực thể. Để làm điều đó, hãy theo liên kết dưới đây và xóa nó khỏi trang tích hợp.",
|
||||
"remove_selected": {
|
||||
"button": "Loại bỏ mục đã chọn",
|
||||
"confirm_partly_title": "Chỉ {number} thực thể đã chọn có thể bị xoá."
|
||||
},
|
||||
"selected": "{number} đã chọn",
|
||||
"status": {
|
||||
"disabled": "Bị vô hiệu hoá",
|
||||
"ok": "Đồng ý",
|
||||
"readonly": "Chỉ đọc",
|
||||
"restored": "Đã khôi phục",
|
||||
"unavailable": "Không khả dụng"
|
||||
}
|
||||
}
|
||||
@ -1112,6 +1148,11 @@
|
||||
"source": "Nguồn:",
|
||||
"title": "Thông tin"
|
||||
},
|
||||
"integration_panel_move": {
|
||||
"link_integration_page": "trang các tích hợp",
|
||||
"missing_zha": "Thiếu bảng cấu hình ZHA? Nó đã được chuyển đến mục ZHA trong {integrations_page}.",
|
||||
"missing_zwave": "Thiếu bảng cấu hình Z-Wave? Nó đã được chuyển đến mục Z-Wave trên {integrations_page} ."
|
||||
},
|
||||
"integrations": {
|
||||
"add_integration": "Thêm tích hợp",
|
||||
"caption": "Các bộ tích hợp",
|
||||
@ -1166,7 +1207,9 @@
|
||||
"no_integrations": "Có vẻ như bạn chưa có bất kỳ tích hợp nào được cấu hình. Nhấp vào nút bên dưới để thêm tích hợp đầu tiên của bạn!",
|
||||
"none": "Chưa có cấu hình nào",
|
||||
"none_found": "Không tìm thấy tích hợp nào",
|
||||
"none_found_detail": "Điều chỉnh tiêu chí tìm kiếm của bạn."
|
||||
"none_found_detail": "Điều chỉnh tiêu chí tìm kiếm của bạn.",
|
||||
"rename_dialog": "Chỉnh sửa tên của mục cấu hình này",
|
||||
"rename_input_label": "Tên mục"
|
||||
},
|
||||
"introduction": "Ở đây có thể định cấu hình các thành phần của bạn và Home Assistant. Không phải mọi thứ đều có thể được cấu hình từ giao diện người dùng, nhưng chúng tôi đang cải thiện việc đó.",
|
||||
"logs": {
|
||||
@ -1200,6 +1243,7 @@
|
||||
"edit_dashboard": "Chỉnh sửa bảng điều khiển",
|
||||
"icon": "Biểu tượng",
|
||||
"new_dashboard": "Thêm bảng điều khiển mới",
|
||||
"remove_default": "Không làm mặc định trên thiết bị này",
|
||||
"require_admin": "Chỉ Quản trị viên",
|
||||
"set_default": "Đặt làm mặc định trên thiết bị này",
|
||||
"show_sidebar": "Hiển thị trong thanh bên",
|
||||
@ -1258,6 +1302,7 @@
|
||||
}
|
||||
},
|
||||
"mqtt": {
|
||||
"button": "Cấu hình",
|
||||
"description_listen": "Nghe một chủ đề",
|
||||
"description_publish": "Công bố một gói tin",
|
||||
"listening_to": "Lắng nghe",
|
||||
@ -1414,21 +1459,29 @@
|
||||
"spinner": "Tìm kiếm các thiết bị ZHA Zigbee ..."
|
||||
},
|
||||
"add": {
|
||||
"caption": "Thêm thiết bị"
|
||||
"caption": "Thêm thiết bị",
|
||||
"description": "Thêm thiết bị vào mạng ZigBee"
|
||||
},
|
||||
"button": "Cấu hình",
|
||||
"caption": "ZHA",
|
||||
"clusters": {
|
||||
"header": "Các Cụm"
|
||||
},
|
||||
"common": {
|
||||
"add_devices": "Thêm thiết bị",
|
||||
"devices": "Thiết bị",
|
||||
"value": "Giá trị"
|
||||
},
|
||||
"description": "Quản lý mạng Zigbee Home Automation",
|
||||
"devices": {
|
||||
"header": "ZigBee Home Automation - Thiết Bị"
|
||||
},
|
||||
"group_binding": {
|
||||
"bind_button_help": "Liên kết nhóm đã chọn vào các cụm thiết bị đã chọn.",
|
||||
"bind_button_label": "Liên kết Nhóm",
|
||||
"cluster_selection_help": "Chọn các cụm để liên kết với nhóm đã chọn.",
|
||||
"group_picker_help": "Chọn một nhóm để thi hành một lệnh liên kết.",
|
||||
"header": "Ràng buộc Nhóm",
|
||||
"unbind_button_help": "Hủy liên kết nhóm đã chọn khỏi cụm thiết bị đã chọn.",
|
||||
"unbind_button_label": "Ngừng liên kết Nhóm"
|
||||
},
|
||||
@ -1439,42 +1492,59 @@
|
||||
"create": "Tạo Nhóm",
|
||||
"create_group": "Zigbee Home Automation - Tạo Nhóm",
|
||||
"creating_group": "Đang tạo Nhóm",
|
||||
"description": "Tạo và sửa đổi các nhóm ZigBee",
|
||||
"group_id": "Mã Nhóm",
|
||||
"group_info": "Thông tin Nhóm",
|
||||
"group_name_placeholder": "Tên Nhóm",
|
||||
"group_not_found": "Không tìm thấy nhóm!",
|
||||
"group-header": "ZigBee Home Automation - Chi tiết Nhóm",
|
||||
"groups": "Nhóm",
|
||||
"groups-header": "ZigBee Home Automation - Quản Lý Nhóm",
|
||||
"header": "Zigbee Home Automation - Quản Lý Nhóm",
|
||||
"introduction": "Tạo và sửa đổi các nhóm zigbee",
|
||||
"manage_groups": "Quản Lý Các Nhóm Zigbee",
|
||||
"members": "Thành viên",
|
||||
"remove_groups": "Xoá các Nhóm",
|
||||
"remove_members": "Xóa Thành viên",
|
||||
"removing_groups": "Đang xoá các Nhóm",
|
||||
"removing_members": "Xoá các Thành Viên"
|
||||
"removing_members": "Xoá các Thành Viên",
|
||||
"zha_zigbee_groups": "Các Nhóm Zigbee ZHA"
|
||||
},
|
||||
"header": "Cấu hình ZigBee Home Automation",
|
||||
"network_management": {
|
||||
"header": "Quản lí Mạng"
|
||||
},
|
||||
"network": {
|
||||
"caption": "Mạng"
|
||||
}
|
||||
},
|
||||
"title": "Zigbee Home Automation"
|
||||
},
|
||||
"zone": {
|
||||
"add_zone": "Thêm Vùng địa lý",
|
||||
"caption": "Khu vực",
|
||||
"configured_in_yaml": "Các khu vực được định cấu hình qua file configuration.yaml không thể được chỉnh sửa thông qua giao diện.",
|
||||
"confirm_delete": "Bạn có chắc bạn muốn xoá bỏ Vùng địa lý này không?",
|
||||
"create_zone": "Tạo một Vùng",
|
||||
"description": "Quản lý các khu vực bạn muốn theo dõi mọi người trong đó.",
|
||||
"detail": {
|
||||
"create": "Tạo",
|
||||
"delete": "Xóa",
|
||||
"icon": "Biểu tượng",
|
||||
"icon_error_msg": "Biểu tượng phải ở định dạng \"tiền tố:tên biểu tượng\", ví dụ: mdi:home",
|
||||
"latitude": "Vĩ độ",
|
||||
"longitude": "Kinh độ",
|
||||
"name": "Tên",
|
||||
"new_zone": "Khu vực mới",
|
||||
"passive": "Thụ động",
|
||||
"radius": "Bán kính",
|
||||
"required_error_msg": "Trường này là cần thiết",
|
||||
"update": "Cập nhật"
|
||||
},
|
||||
"edit_home_zone": "Bán kính của vùng Nhà chưa thể chỉnh sửa được từ frontend. Kéo điểm đánh dấu trên bản đồ để di chuyển vùng Nhà.",
|
||||
"edit_home_zone": "Bán kính của vùng quanh Nhà chưa thể chỉnh sửa được từ frontend. Kéo điểm đánh dấu trên bản đồ để di chuyển vùng quanh Nhà.",
|
||||
"edit_home_zone_narrow": "Bán kính của Khu vực nhà chưa thể được chỉnh sửa từ giao diện. Vị trí này có thể được thay đổi từ cấu hình chung.",
|
||||
"go_to_core_config": "Đi đến cấu hình chung?",
|
||||
"home_zone_core_config": "Vị trí của Khu vực nhà của bạn có thể chỉnh sửa từ trang cấu hình chung. Bán kính của Khu vực nhà chưa thể được chỉnh sửa từ giao diện. Bạn có muốn chuyển đến cấu hình chung?",
|
||||
"introduction": "Vùng địa lý cho phép bạn xác định các khu vực nhất định trên trái đất. Khi một người nằm trong một vùng, trạng thái của họ sẽ hiển thị tên vùng này. Vùng cũng có thể được sử dụng như một kích hoạt hoặc điều kiện trong các thiết lập tự động hóa.",
|
||||
"no_zones_created_yet": "Có vẻ như bạn chưa tạo ra bất kỳ khu vực nào."
|
||||
},
|
||||
"zwave": {
|
||||
@ -1494,9 +1564,12 @@
|
||||
},
|
||||
"node_management": {
|
||||
"add_to_group": "Thêm vào Nhóm",
|
||||
"group": "Nhóm"
|
||||
"group": "Nhóm",
|
||||
"node_to_control": "Nút để điều khiển",
|
||||
"remove_from_group": "Xóa Khỏi Nhóm"
|
||||
},
|
||||
"ozw_log": {
|
||||
"last_log_lines": "Số dòng nhật ký gần nhất",
|
||||
"load": "Tải"
|
||||
},
|
||||
"services": {
|
||||
@ -1505,6 +1578,9 @@
|
||||
"node_info": "Thông tin nút",
|
||||
"print_node": "Nút in ấn",
|
||||
"refresh_entity": "Làm mới Thực thể",
|
||||
"refresh_node": "Làm Mới Nút",
|
||||
"remove_failed_node": "Loại Bỏ Nút Bị Lỗi",
|
||||
"replace_failed_node": "Thay Thế Nút Bị Lỗi",
|
||||
"save_config": "Lưu cấu hình",
|
||||
"soft_reset": "Khởi động lại",
|
||||
"test_node": "Nút kiểm tra"
|
||||
@ -1573,11 +1649,23 @@
|
||||
},
|
||||
"history": {
|
||||
"period": "Giai đoạn",
|
||||
"ranges": {
|
||||
"last_week": "Tuần trước",
|
||||
"this_week": "Tuần này",
|
||||
"today": "Hôm nay",
|
||||
"yesterday": "Hôm qua"
|
||||
},
|
||||
"showing_entries": "Hiển thị mục cho"
|
||||
},
|
||||
"logbook": {
|
||||
"entries_not_found": "Không tìm thấy trong sổ nhật ký.",
|
||||
"period": "Giai đoạn",
|
||||
"ranges": {
|
||||
"last_week": "Tuần trước",
|
||||
"this_week": "Tuần này",
|
||||
"today": "Hôm nay",
|
||||
"yesterday": "Hôm qua"
|
||||
},
|
||||
"showing_entries": "Hiển thị mục cho"
|
||||
},
|
||||
"lovelace": {
|
||||
@ -1603,6 +1691,10 @@
|
||||
"tap": "Nhấn:",
|
||||
"toggle": "Chuyển đổi {name}"
|
||||
},
|
||||
"safe-mode": {
|
||||
"description": "Home Assistant gặp sự cố trong khi tải cấu hình của bạn và hiện đang chạy ở chế độ an toàn. Hãy xem nhật ký lỗi để xem phần nào bị sai.",
|
||||
"header": "Chế Độ An Toàn Đã Kích Hoạt"
|
||||
},
|
||||
"shopping-list": {
|
||||
"add_item": "Thêm mục",
|
||||
"checked_items": "Mục đã chọn",
|
||||
@ -1619,11 +1711,16 @@
|
||||
},
|
||||
"editor": {
|
||||
"card": {
|
||||
"alarm-panel": {
|
||||
"description": "Thẻ Bảng điều khiển An ninh cho phép bạn Kích hoạt và Vô hiệu hóa tích hợp bảng điều khiển an ninh."
|
||||
},
|
||||
"button": {
|
||||
"description": "Thẻ Nút cho phép bạn thêm các nút để thực hiện các tác vụ.",
|
||||
"name": "Nút"
|
||||
},
|
||||
"conditional": {
|
||||
"card": "Thẻ",
|
||||
"change_type": "Đổi loại",
|
||||
"condition_explanation": "Thẻ sẽ được hiển thị khi TẤT CẢ các điều kiện dưới đây được đáp ứng.",
|
||||
"conditions": "Điều kiện",
|
||||
"current_state": "hiện tại",
|
||||
@ -1631,13 +1728,20 @@
|
||||
"state_equal": "Trạng thái bằng với",
|
||||
"state_not_equal": "Trạng thái không bằng với"
|
||||
},
|
||||
"entities": {
|
||||
"description": "Thẻ Các Thực thể là loại thẻ phổ biến nhất. Nó nhóm các mục với nhau thành một danh sách."
|
||||
},
|
||||
"entity-filter": {
|
||||
"description": "Thẻ Bộ lọc Thực thể cho phép bạn xác định danh sách các thực thể mà bạn muốn theo dõi chỉ khi chúng ở trạng thái nhất định.",
|
||||
"name": "Bộ lọc Thực thể"
|
||||
},
|
||||
"entity": {
|
||||
"description": "Thẻ Thực thể cung cấp cho bạn thông tin tổng quát về trạng thái của thực thể.",
|
||||
"name": "Thực thể"
|
||||
},
|
||||
"gauge": {
|
||||
"description": "Thẻ Thước đo là một thẻ cơ bản cho phép bạn quan sát trực quan dữ liệu của cảm biến."
|
||||
},
|
||||
"generic": {
|
||||
"attribute": "Thuộc tính",
|
||||
"double_tap_action": "Hành động khi Nhấn Đôi",
|
||||
@ -1646,6 +1750,9 @@
|
||||
"no_theme": "Không có theme.",
|
||||
"state": "Trạng thái"
|
||||
},
|
||||
"glance": {
|
||||
"description": "Thẻ Xem nhanh rất hữu ích để hiển thị nhiều cảm biến trong một không gian nhỏ gọn."
|
||||
},
|
||||
"history-graph": {
|
||||
"description": "Thẻ Biểu đồ Lịch sử cho phép bạn hiển thị biểu đồ cho từng thực thể được liệt kê."
|
||||
},
|
||||
@ -1653,7 +1760,12 @@
|
||||
"description": "Thẻ Xếp Ngang cho phép bạn nhóm nhiều thẻ để các thẻ này luôn nằm cạnh nhau trong cùng một hàng.",
|
||||
"name": "Xếp Ngang"
|
||||
},
|
||||
"humidifier": {
|
||||
"description": "Thẻ Máy bù ẩm dùng để điều khiển thực thể đại diện cho máy bù ẩm. Cho phép bạn thay đổi độ ẩm và các chế độ của máy.",
|
||||
"name": "Máy bù ẩm"
|
||||
},
|
||||
"iframe": {
|
||||
"description": "Thẻ Trang web cho phép bạn nhúng các trang ưa thích vào Home Assistant.",
|
||||
"name": "Trang web"
|
||||
},
|
||||
"light": {
|
||||
@ -1663,10 +1775,24 @@
|
||||
"description": "Thẻ Bản đồ cho phép bạn hiển thị các thực thể trên bản đồ.",
|
||||
"hours_to_show": "Giờ hiển thị"
|
||||
},
|
||||
"markdown": {
|
||||
"description": "Thẻ Markdown được sử dụng để hiển thị Markdown."
|
||||
},
|
||||
"media-control": {
|
||||
"description": "Thẻ Điều khiển Phương tiện được sử dụng để hiển thị các thực thể Media Player trên một giao diện với các điều khiển dễ sử dụng.",
|
||||
"name": "Điều khiển Thiết bị đa phương tiện"
|
||||
},
|
||||
"picture-elements": {
|
||||
"description": "Thẻ Các thành phần trong Ảnh là một trong những loại thẻ linh hoạt nhất. Các thẻ cho phép bạn định vị các biểu tượng hoặc văn bản và thậm chí cả các dịch vụ! Trên một hình ảnh dựa trên tọa độ."
|
||||
},
|
||||
"picture-entity": {
|
||||
"description": "Thẻ Thực thể Hình ảnh hiển thị một thực thể ở dạng hình ảnh. Thay vì sử dụng hình ảnh từ URL, nó cũng có thể hiển thị hình ảnh của các thực thể camera."
|
||||
},
|
||||
"picture-glance": {
|
||||
"description": "Thẻ Hình ảnh Xem nhanh hiển thị hình ảnh và các thực thể tương ứng như một biểu tượng. Các thực thể ở bên phải cho phép các hành động chuyển đổi, những thực thể còn lại hiển thị hộp thoại thông tin bổ sung."
|
||||
},
|
||||
"picture": {
|
||||
"description": "Thẻ ảnh cho phép bạn thiết lập một hình ảnh sử dụng để điều hướng đến các đường dẫn khác nhau trong giao diện của bạn hoặc gọi một dịch vụ.",
|
||||
"name": "Hình ảnh"
|
||||
},
|
||||
"plant-status": {
|
||||
@ -1689,6 +1815,7 @@
|
||||
"name": "Xếp Dọc"
|
||||
},
|
||||
"weather-forecast": {
|
||||
"description": "Thẻ Dự báo Thời tiết hiển thị thông tin thời tiết. Rất hữu ích khi thêm vào các giao diện điều khiển dùng gắn tường.",
|
||||
"name": "Dự báo Thời tiết",
|
||||
"show_forecast": "Hiển thị Dự báo thời tiết"
|
||||
}
|
||||
@ -1720,6 +1847,8 @@
|
||||
"header": "Cấu hình Tầm nhìn",
|
||||
"move_right": "Di chuyển tầm nhìn sang phải",
|
||||
"tab_badges": "Huy hiệu",
|
||||
"tab_settings": "Cài đặt",
|
||||
"tab_visibility": "Hiển thị",
|
||||
"visibility": {
|
||||
"select_users": "Chọn người dùng sẽ thấy chế độ xem này trong thanh điều hướng"
|
||||
}
|
||||
@ -1736,10 +1865,13 @@
|
||||
"para_no_id": "Phần tử này không có ID. Vui lòng thêm ID vào thành phần này trong 'ui-lovelace.yaml'."
|
||||
},
|
||||
"raw_editor": {
|
||||
"confirm_remove_config_text": "Chúng tôi sẽ tự động tạo giao diện người dùng Lovelace với các khu vực và thiết bị của bạn nếu bạn loại bỏ cấu hình giao diện người dùng Lovelace.",
|
||||
"confirm_remove_config_title": "Bạn có chắc muốn loại bỏ cấu hình giao diện người dùng Lovelace? Chúng tôi sẽ tự động tạo ra các giao diện người dùng Lovelace với các khu vực và thiết bị của bạn.",
|
||||
"confirm_unsaved_changes": "Bạn có những thay đổi chưa được lưu, bạn có chắc muốn thoát không?",
|
||||
"confirm_unsaved_comments": "Cấu hình của bạn chứa (các) ghi chú, những ghi chú này sẽ không được lưu. Bạn có muốn tiếp tục?",
|
||||
"error_invalid_config": "Cấu hình của bạn không hợp lệ: {error}",
|
||||
"error_parse_yaml": "Không thể phân tích YAML: {error}",
|
||||
"error_remove": "Không thể loại bỏ cấu hình: {error}",
|
||||
"error_save_yaml": "Không thể lưu YAML: {error}",
|
||||
"header": "Chỉnh sửa cấu hình",
|
||||
"resources_moved": "Các Tài nguyên giờ không nên được thêm vào qua cấu hình Lovelace nhưng có thể thêm vào qua bảng điều khiển cấu hình Lovelace.",
|
||||
@ -1794,7 +1926,10 @@
|
||||
"title": "Thực thể chưa sử dụng"
|
||||
},
|
||||
"views": {
|
||||
"confirm_delete": "Xóa cửa sổ?"
|
||||
"confirm_delete": "Xóa cửa sổ?",
|
||||
"confirm_delete_existing_cards": "Xóa chế độ xem này cũng đồng thời xoá các thẻ bên trong",
|
||||
"confirm_delete_existing_cards_text": "Bạn có chắc chắn muốn xóa chế độ xem ''{name}'' không? Chế độ xem chứa {Number} thẻ sẽ bị xóa. Hành động này không thể hoàn tác được.",
|
||||
"confirm_delete_text": "Bạn có chắc chắn muốn xóa chế độ xem ''{name}'' không?"
|
||||
},
|
||||
"warning": {
|
||||
"attribute_not_found": "Thuộc tính {attribute} không có trong: {entity}",
|
||||
|
@ -646,7 +646,7 @@
|
||||
"pattern": "客戶端驗證模式",
|
||||
"text": "文字"
|
||||
},
|
||||
"platform_not_loaded": "{platform} 整合未載入。請於設定檔進行添加、新增 'default_config:' 或 ''{platform}:''。",
|
||||
"platform_not_loaded": "整合 {platform} 未載入。請於設定檔進行添加、新增 'default_config:' 或 ''{platform}:''。",
|
||||
"required_error_msg": "必填欄位",
|
||||
"yaml_not_editable": "此物件的設定無法藉由 UI 編輯、僅有透過 UI 設定的物件可於 UI 進行設定。"
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user