mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-06 14:39:22 +00:00
committed by
claude[bot]
parent
8273af59ca
commit
372d838ec2
@@ -65,7 +65,7 @@ export function markerAreaSnapshotOf(value: unknown): MarkerAreaSnapshot {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
|
||||
const result: MarkerAreaSnapshot = {};
|
||||
for (const [id, raw] of Object.entries(value as Record<string, unknown>)
|
||||
.slice(0, MARKER_AREA_SNAPSHOT_LIMIT)) {
|
||||
.slice(-MARKER_AREA_SNAPSHOT_LIMIT)) {
|
||||
if (!validText(id) || !raw || typeof raw !== 'object' || Array.isArray(raw)) continue;
|
||||
const binding = (raw as { binding?: unknown }).binding;
|
||||
const area = (raw as { area?: unknown }).area;
|
||||
@@ -142,6 +142,22 @@ export function resolveDeviceAreaRelocations(
|
||||
if (!options.authoritative) return { decisions, relocateIds };
|
||||
|
||||
const snapshot = markerAreaSnapshotOf(options.snapshot);
|
||||
const liveIds = new Set<string>();
|
||||
const liveBindings = new Set<MarkerAreaBinding>();
|
||||
for (const device of options.devices) {
|
||||
if (validText(device.id)) liveIds.add(device.id);
|
||||
if (validText(device.marker?.id)) liveIds.add(device.marker.id);
|
||||
if ((device.bindingKind === 'device' || device.bindingKind === 'entity')
|
||||
&& validText(device.bindingRef)) {
|
||||
liveBindings.add(`${device.bindingKind}:${device.bindingRef}`);
|
||||
}
|
||||
if (validBinding(device.marker?.binding)) liveBindings.add(device.marker.binding);
|
||||
}
|
||||
for (const [id, entry] of Object.entries(snapshot)) {
|
||||
if (!liveIds.has(id) && !liveBindings.has(entry.binding)) decisions.push({
|
||||
...unresolved(id, 'registry-unverified'), removeSnapshot: true,
|
||||
});
|
||||
}
|
||||
const scale = Number.isFinite(options.coordinateScale) && Number(options.coordinateScale) > 0
|
||||
? Number(options.coordinateScale) : 1000;
|
||||
const targets = new Map<string, Array<{ space: SpaceModel; room: RoomCfg }>>();
|
||||
|
||||
+4
-1
@@ -33,14 +33,17 @@ export class HpConfirm extends LitElement {
|
||||
const request = this.request;
|
||||
if (!request) return null;
|
||||
const destructive = request.kind === 'destructive';
|
||||
const descriptionId = `hp-confirm-description-${this.token}`;
|
||||
return html`<hp-dialog class="danger-confirm-dialog"
|
||||
.hass=${this.hass}
|
||||
.title=${request.title}
|
||||
.alert=${true}
|
||||
.describedBy=${descriptionId}
|
||||
.icon=${request.icon || (destructive
|
||||
? 'mdi:alert-outline' : 'mdi:lock-open-alert-outline')}
|
||||
dismiss-on-scrim
|
||||
@hp-close=${() => this._decide(false)}>
|
||||
<div class="body danger-confirm-body" data-confirm-key=${request.key}>
|
||||
<div id=${descriptionId} class="body danger-confirm-body" data-confirm-key=${request.key}>
|
||||
${request.objectName
|
||||
? html`<strong class="danger-confirm-object">${request.objectName}</strong>`
|
||||
: null}
|
||||
|
||||
+19
-8
@@ -24,9 +24,10 @@ let dialogSequence = 0;
|
||||
/**
|
||||
* Shared modal shell for Houseplan.
|
||||
*
|
||||
* Home Assistant provides the visual surface and focus trap through ha-dialog.
|
||||
* The native dialog branch keeps the standalone demo usable without mocking HA
|
||||
* frontend internals. Both branches expose the same `hp-close` contract and
|
||||
* Home Assistant provides the visual surface and focus trap through ha-dialog
|
||||
* for ordinary dialogs. Alert confirmations deliberately use the native branch:
|
||||
* the pinned HA component exposes an alert type but does not forward its role
|
||||
* to the actual dialog. Both branches expose the same `hp-close` contract and
|
||||
* restore focus to the control that opened the dialog.
|
||||
*/
|
||||
export class HpDialog extends LitElement {
|
||||
@@ -34,6 +35,8 @@ export class HpDialog extends LitElement {
|
||||
title: { type: String },
|
||||
icon: { type: String },
|
||||
wide: { type: Boolean, reflect: true },
|
||||
alert: { type: Boolean, reflect: true },
|
||||
describedBy: { type: String, attribute: 'described-by' },
|
||||
dismissOnScrim: { type: Boolean, attribute: 'dismiss-on-scrim' },
|
||||
hass: { attribute: false },
|
||||
};
|
||||
@@ -218,6 +221,8 @@ export class HpDialog extends LitElement {
|
||||
title = '';
|
||||
icon = '';
|
||||
wide = false;
|
||||
alert = false;
|
||||
describedBy = '';
|
||||
dismissOnScrim = false;
|
||||
hass: any = null;
|
||||
|
||||
@@ -228,6 +233,10 @@ export class HpDialog extends LitElement {
|
||||
private _overlays: OverlayEntry[] = [];
|
||||
private readonly _titleId = `hp-dialog-title-${++dialogSequence}`;
|
||||
|
||||
private _usesHaDialog(): boolean {
|
||||
return this._useHaDialog && !this.alert;
|
||||
}
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this._opener = this._deepActiveElement();
|
||||
@@ -274,7 +283,7 @@ export class HpDialog extends LitElement {
|
||||
|
||||
protected firstUpdated(changed: PropertyValues): void {
|
||||
super.firstUpdated(changed);
|
||||
if (!this._useHaDialog) {
|
||||
if (!this._usesHaDialog()) {
|
||||
const dialog = this.renderRoot.querySelector('dialog');
|
||||
if (dialog && !dialog.open) dialog.showModal();
|
||||
}
|
||||
@@ -340,7 +349,7 @@ export class HpDialog extends LitElement {
|
||||
const focusable = this._focusableElements();
|
||||
const autofocus = focusable.find((el) => el.hasAttribute('autofocus'));
|
||||
const target = autofocus || focusable[0]
|
||||
|| (!this._useHaDialog ? this.renderRoot.querySelector<HTMLElement>('.close') : null)
|
||||
|| (!this._usesHaDialog() ? this.renderRoot.querySelector<HTMLElement>('.close') : null)
|
||||
|| this.renderRoot.querySelector<HTMLElement>('.surface')
|
||||
|| this.renderRoot.querySelector<HTMLElement>('ha-dialog');
|
||||
target?.focus({ preventScroll: true });
|
||||
@@ -405,7 +414,7 @@ export class HpDialog extends LitElement {
|
||||
this._requestClose();
|
||||
return;
|
||||
}
|
||||
if (event.key !== 'Tab' || this._useHaDialog) return;
|
||||
if (event.key !== 'Tab' || this._usesHaDialog()) return;
|
||||
const close = this.renderRoot.querySelector<HTMLElement>('.close');
|
||||
const focusable = close ? [close, ...this._focusableElements()] : this._focusableElements();
|
||||
if (!focusable.length) {
|
||||
@@ -440,13 +449,14 @@ export class HpDialog extends LitElement {
|
||||
<span class="title-text">${this.title}</span>
|
||||
</span>`;
|
||||
|
||||
if (this._useHaDialog) {
|
||||
if (this._usesHaDialog()) {
|
||||
return html`<ha-dialog
|
||||
.hass=${this.hass}
|
||||
.open=${true}
|
||||
width=${this.wide ? 'medium' : 'small'}
|
||||
.preventScrimClose=${!this.dismissOnScrim}
|
||||
.ariaLabelledBy=${this._titleId}
|
||||
.ariaDescribedBy=${this.describedBy || undefined}
|
||||
@opened=${this._focusInitial}
|
||||
@closed=${this._requestClose}
|
||||
>
|
||||
@@ -457,9 +467,10 @@ export class HpDialog extends LitElement {
|
||||
}
|
||||
|
||||
return html`<dialog
|
||||
role="dialog"
|
||||
role=${this.alert ? 'alertdialog' : 'dialog'}
|
||||
aria-modal="true"
|
||||
aria-labelledby=${this._titleId}
|
||||
aria-describedby=${this.describedBy || nothing}
|
||||
@cancel=${this._onFallbackCancel}
|
||||
@click=${this._onFallbackClick}
|
||||
>
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"history.draft_segment": "Raum-Entwurfsegment hinzufügen",
|
||||
"history.draft_merge": "Unvollständige Raumumrisse verbinden",
|
||||
"history.draft_segment_delete": "Raum-Entwurfssegment entfernen",
|
||||
"history.partition_add": "Trennwand hinzufügen",
|
||||
"history.column_add": "Säule hinzufügen",
|
||||
"history.physical_edit": "Physisches Objekt ändern",
|
||||
"history.physical_delete": "Physisches Objekt löschen",
|
||||
@@ -37,8 +36,6 @@
|
||||
"history.wall_chain_finish": "Wandkette fertigstellen",
|
||||
"history.wall_face_batch": "Räume aus Wänden erstellen",
|
||||
"toast.column_duplicate": "Eine Säule mit demselben Zentrum und äußerer Größe existiert bereits",
|
||||
"confirm.delete_draft": "Sofort den gesamten unvollständigen Raumumriss löschen?",
|
||||
"confirm.delete_draft_segment": "Dieses Entwurfssegment löschen? Der verbleibende Umriss könnte sich in zwei teilen.",
|
||||
"confirm.delete_draft_title": "Unvollständigen Umriss löschen?",
|
||||
"confirm.delete_draft_body": "Der gesamte unvollständige Raumumriss wird gelöscht. Beim Abbrechen wird nichts geändert.",
|
||||
"confirm.delete_draft_segment_title": "Umrisssegment löschen?",
|
||||
@@ -76,7 +73,6 @@
|
||||
"title.zoom_in": "Zoomen",
|
||||
"title.zoom_out": "Herauszoomen",
|
||||
"title.zoom_fit": "Alles anpassen",
|
||||
"title.markup": "Raum-Markierung: Gitter, Linien, Konturen",
|
||||
"title.configure_space": "Bereich konfigurieren",
|
||||
"title.add_space": "Bereich hinzufügen",
|
||||
"title.markup_add": "Wände: eine durchgehende Kette zeichnen; Shift sperrt auf 45°. Werkzeugwechsel oder Verlassen des Editors beendet die Kette und wandelt sie in unabhängige Wände",
|
||||
@@ -121,7 +117,6 @@
|
||||
"history.edit_opening": "Öffnung bearbeiten",
|
||||
"history.move_opening": "Öffnung verschieben",
|
||||
"history.delete_opening": "Öffnung löschen",
|
||||
"history.delete_room": "Raum löschen",
|
||||
"history.delete_room_keep_walls": "Raum löschen, Wände behalten",
|
||||
"history.delete_room_with_walls": "Raum und Wände löschen",
|
||||
"history.decor_add": "Dekorobjekt hinzufügen",
|
||||
@@ -163,7 +158,6 @@
|
||||
"confirm.delete_partition_openings_title": "Wand und Öffnungen löschen?",
|
||||
"confirm.delete_partition_openings_body": "Diese Wand enthält {count} Öffnung(en). Sie werden zusammen gelöscht.",
|
||||
"confirm.delete_partition_openings_item": "• {type}, {length}",
|
||||
"markup.delete": "Löschen",
|
||||
"markup.hint_points": "Punkte: {n} · Shift — 45° Schritte · Esc — Kette beenden · Ctrl+Z — Punkt rückgängig machen · Schließen eines Bereichs erstellt einen Raum",
|
||||
"markup.hint_start": "Klicken Sie auf einen Rasterpunkt, um eine Wandkette zu starten",
|
||||
"tip.lqi": "durchschnittliches Zigbee-Signal:",
|
||||
@@ -192,9 +186,7 @@
|
||||
"display.badge": "Symbol + Zustand",
|
||||
"display.icon_ripple": "Symbol + Zustand und Aktivität",
|
||||
"display.static_icon": "Immer statisches Symbol",
|
||||
"marker.display_hint": "Symbol + Zustand ändert die Platte für die Zustände Arbeit, geöffnet, Alarm und nicht verfügbar. Symbol + Zustand und Aktivität zeigt zusätzlich einen kurzen Impuls für Ereignisse und einen kontinuierlichen Impuls für laufende Arbeit, Bewegung oder Präsenz. Wert + Zustand ersetzt das Symbol durch einen eindeutigen HA-Wert. Ein statisches Symbol reagiert niemals auf Gerätezustände.",
|
||||
"marker.display_hint_badge": "Das Symbol und die dynamische Platte zeigen den Gerätezustand ohne den üblichen Aktivitätspuls. Rote Alarme bleiben sichtbar.",
|
||||
"marker.display_hint_icon": "Das Symbol und die dynamische Platte zeigen den Gerätezustand ohne den üblichen Aktivitätspuls. Rote Alarme bleiben sichtbar.",
|
||||
"marker.display_hint_icon_ripple": "Das Symbol, die dynamische Platte und der Puls zeigen einen kurzen Puls für Ereignisse und einen kontinuierlichen Puls für Arbeit, Bewegung oder Anwesenheit. Rote Alarme haben eine separate Priorität.",
|
||||
"marker.display_hint_value": "Ein ausgewählter oder automatisch ermittelter Home Assistant-Wert ersetzt das Symbol, während die Platte weiterhin den Zustand anzeigt. Rote Alarme bleiben sichtbar.",
|
||||
"marker.display_hint_static_icon": "Die themenabhängige Hülle und das Symbol bleiben immer gleich. Zustand, Aktivität, Nichtverfügbarkeit und Alarme verändern nicht das Erscheinungsbild.",
|
||||
@@ -293,14 +285,11 @@
|
||||
"device.light_group": "Lichtgruppe",
|
||||
"device.fallback": "Gerät",
|
||||
"device.virtual": "Virtuelles Gerät",
|
||||
"confirm.delete_room": "Raum \"{name}\" löschen?",
|
||||
"confirm.delete_room_title": "Raum \"{name}\" löschen?",
|
||||
"confirm.delete_room_body": "Festlegen, ob die ausschließlich zu diesem Raum gehörenden physischen Wände erhalten bleiben. Mit einem anderen Raum geteilte Wände bleiben immer erhalten.",
|
||||
"confirm.remove_marker": "„{name}“ aus dem Plan löschen? Das Gerät verschwindet vollständig und trägt nicht mehr zu den Plandaten bei. Es kann später erneut hinzugefügt werden.",
|
||||
"confirm.remove_marker_title": "Gerät aus dem Plan löschen?",
|
||||
"confirm.remove_marker_body": "Das Gerät verschwindet vollständig und trägt nicht mehr zu den Plandaten bei. Es kann später erneut hinzugefügt werden.",
|
||||
"confirm.erase_decor": "Das Objekt „{kind}“ löschen? Diese Aktion kann im Editor rückgängig gemacht werden.",
|
||||
"confirm.delete_space": "Bereich „{title}“ mit allen Räumen und Markierungen löschen?",
|
||||
"confirm.delete_space_title": "Bereich löschen?",
|
||||
"confirm.delete_space_body": "Der Bereich, alle seine Räume und die gesamte Planmarkierung werden gelöscht.",
|
||||
"space.delete_blocked": "Dieser Bereich wird noch von {n} Gerät(en) verwendet. Die Geräte zuerst in einen anderen Bereich verschieben oder löschen.",
|
||||
@@ -737,7 +726,6 @@
|
||||
"marker.control_passive": "passive Quelle",
|
||||
"toast.marker_control_cycle": "Dieser Link würde eine kreisförmige Kette von Lichtsteuerungen erzeugen.",
|
||||
"toast.marker_binding_required": "Wählen Sie ein Home Assistant-Gerät, bevor Sie eine andere Lichtquelle verlinken.",
|
||||
"confirm.unlock": "„{name}“ entsperren?",
|
||||
"confirm.unlock_title": "Schloss öffnen?",
|
||||
"confirm.unlock_body": "House Plan sendet einen Befehl zum Öffnen an dieses Schloss.",
|
||||
"toast.files_migrate_failed": "Anhänge konnten nicht zur neuen Bindung verschoben werden, Links zeigen weiterhin auf die alten Dateien: {err}",
|
||||
@@ -748,7 +736,6 @@
|
||||
"space.used_by": "in Benutzung: {list}",
|
||||
"space.in_use": "Ein Bereich verwendet diesen Plan noch — zuerst die Verknüpfung lösen",
|
||||
"btn.use": "Verwenden",
|
||||
"confirm.delete_plan": "Plandatei „{name}“ vom Server löschen? Dies kann nicht rückgängig gemacht werden.",
|
||||
"confirm.delete_plan_title": "Plandatei löschen?",
|
||||
"confirm.delete_plan_body": "Die Datei wird vom Server gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden.",
|
||||
"toast.plans_list_failed": "Konnte die gespeicherten Pläne nicht auflisten: {err}",
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"history.draft_segment": "Add room-draft segment",
|
||||
"history.draft_merge": "Join unfinished room outlines",
|
||||
"history.draft_segment_delete": "Remove room-draft segment",
|
||||
"history.partition_add": "Add partition",
|
||||
"history.column_add": "Add column",
|
||||
"history.physical_edit": "Change physical object",
|
||||
"history.physical_delete": "Delete physical object",
|
||||
@@ -37,8 +36,6 @@
|
||||
"history.wall_chain_finish": "Finish wall chain",
|
||||
"history.wall_face_batch": "Create rooms from walls",
|
||||
"toast.column_duplicate": "A column with the same centre and outer size already exists",
|
||||
"confirm.delete_draft": "Delete the whole unfinished room contour?",
|
||||
"confirm.delete_draft_segment": "Delete this draft segment? The remaining contour may split in two.",
|
||||
"confirm.delete_draft_title": "Delete unfinished contour?",
|
||||
"confirm.delete_draft_body": "The entire unfinished room contour will be deleted. Cancelling makes no changes.",
|
||||
"confirm.delete_draft_segment_title": "Delete contour segment?",
|
||||
@@ -76,7 +73,6 @@
|
||||
"title.zoom_in": "Zoom in",
|
||||
"title.zoom_out": "Zoom out",
|
||||
"title.zoom_fit": "Fit all",
|
||||
"title.markup": "Room markup: grid, lines, outlines",
|
||||
"title.configure_space": "Configure space",
|
||||
"title.add_space": "Add space",
|
||||
"title.markup_add": "Walls: draw a continuous chain; Shift locks to 45°. Changing tool or leaving the editor finishes it as independent walls",
|
||||
@@ -121,7 +117,6 @@
|
||||
"history.edit_opening": "Edit opening",
|
||||
"history.move_opening": "Move opening",
|
||||
"history.delete_opening": "Delete opening",
|
||||
"history.delete_room": "Delete room",
|
||||
"history.delete_room_keep_walls": "Delete room, keep walls",
|
||||
"history.delete_room_with_walls": "Delete room and walls",
|
||||
"history.decor_add": "Add decor object",
|
||||
@@ -163,7 +158,6 @@
|
||||
"confirm.delete_partition_openings_title": "Delete wall and openings?",
|
||||
"confirm.delete_partition_openings_body": "This wall contains {count} opening(s). They will be deleted together.",
|
||||
"confirm.delete_partition_openings_item": "• {type}, {length}",
|
||||
"markup.delete": "Delete",
|
||||
"markup.hint_points": "points: {n} · Shift — 45° steps · Esc — finish chain · Ctrl+Z — undo a point · closing an area offers a room",
|
||||
"markup.hint_start": "click a grid dot to start a wall chain",
|
||||
"tip.lqi": "average zigbee signal:",
|
||||
@@ -192,9 +186,7 @@
|
||||
"display.badge": "Icon + state",
|
||||
"display.icon_ripple": "Icon + state and activity",
|
||||
"display.static_icon": "Always static icon",
|
||||
"marker.display_hint": "Icon + state changes the plate for work, open, alarm and unavailable states. Icon + state and activity additionally shows a short pulse for events and a continuous pulse for ongoing work, movement or presence. Value + state replaces the icon with one unambiguous HA value. A static icon never reacts to device states.",
|
||||
"marker.display_hint_badge": "The icon and dynamic plate show device state without the ordinary activity pulse. Red alarms remain visible.",
|
||||
"marker.display_hint_icon": "The icon and dynamic plate show device state without the ordinary activity pulse. Red alarms remain visible.",
|
||||
"marker.display_hint_icon_ripple": "The icon, dynamic plate and pulse show a short pulse for events and a continuous pulse for work, motion or presence. Red alarms have separate priority.",
|
||||
"marker.display_hint_value": "A selected or automatically resolved Home Assistant value replaces the icon while the plate continues to show state. Red alarms remain visible.",
|
||||
"marker.display_hint_static_icon": "The theme-aware shell and icon always stay the same. State, activity, unavailability and alarms do not change the face.",
|
||||
@@ -293,14 +285,11 @@
|
||||
"device.light_group": "light group",
|
||||
"device.fallback": "device",
|
||||
"device.virtual": "virtual device",
|
||||
"confirm.delete_room": "Delete room \"{name}\"?",
|
||||
"confirm.delete_room_title": "Delete room \"{name}\"?",
|
||||
"confirm.delete_room_body": "Choose whether the room's exclusive physical walls should remain. Walls shared with another room are always kept.",
|
||||
"confirm.remove_marker": "Delete \"{name}\" from the plan? The device will disappear completely and stop contributing to plan data. You can add it again later.",
|
||||
"confirm.remove_marker_title": "Delete device from the plan?",
|
||||
"confirm.remove_marker_body": "The device will disappear completely and stop contributing to plan data. You can add it again later.",
|
||||
"confirm.erase_decor": "Erase the {kind} object? You can undo this action from the editor history.",
|
||||
"confirm.delete_space": "Delete space \"{title}\" with all its rooms and markup?",
|
||||
"confirm.delete_space_title": "Delete space?",
|
||||
"confirm.delete_space_body": "The space, all its rooms and all its plan markup will be deleted.",
|
||||
"space.delete_blocked": "This space is still used by {n} device(s). Move them to another space or delete them first.",
|
||||
@@ -737,7 +726,6 @@
|
||||
"marker.control_passive": "passive source",
|
||||
"toast.marker_control_cycle": "This link would create a circular chain of light controls.",
|
||||
"toast.marker_binding_required": "Choose a Home Assistant device before linking another light source.",
|
||||
"confirm.unlock": "Unlock “{name}”?",
|
||||
"confirm.unlock_title": "Unlock?",
|
||||
"confirm.unlock_body": "House Plan will send an unlock command to this lock.",
|
||||
"toast.files_migrate_failed": "Attachments could not be moved to the new binding, links keep pointing at the old files: {err}",
|
||||
@@ -748,7 +736,6 @@
|
||||
"space.used_by": "in use: {list}",
|
||||
"space.in_use": "A space still uses this plan — detach it first",
|
||||
"btn.use": "Use",
|
||||
"confirm.delete_plan": "Delete the plan file \"{name}\" from the server? This cannot be undone.",
|
||||
"confirm.delete_plan_title": "Delete plan file?",
|
||||
"confirm.delete_plan_body": "The file will be deleted from the server. This action cannot be undone.",
|
||||
"toast.plans_list_failed": "Could not list the stored plans: {err}",
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"history.draft_segment": "Ajouter un segment de brouillon de pièce",
|
||||
"history.draft_merge": "Relier des contours de pièce inachevés",
|
||||
"history.draft_segment_delete": "Supprimer un segment de brouillon de pièce",
|
||||
"history.partition_add": "Ajouter une cloison",
|
||||
"history.column_add": "Ajouter une colonne",
|
||||
"history.physical_edit": "Modifier l’objet physique",
|
||||
"history.physical_delete": "Supprimer l’objet physique",
|
||||
@@ -37,8 +36,6 @@
|
||||
"history.wall_chain_finish": "Terminer la chaîne de murs",
|
||||
"history.wall_face_batch": "Créer des pièces à partir des murs",
|
||||
"toast.column_duplicate": "Une colonne avec le même centre et la même dimension extérieure existe déjà",
|
||||
"confirm.delete_draft": "Supprimer tout le contour de pièce inachevé ?",
|
||||
"confirm.delete_draft_segment": "Supprimer ce segment de brouillon ? Le contour restant peut se scinder en deux.",
|
||||
"confirm.delete_draft_title": "Supprimer le contour inachevé ?",
|
||||
"confirm.delete_draft_body": "Tout le contour de pièce inachevé sera supprimé. L’annulation ne modifie rien.",
|
||||
"confirm.delete_draft_segment_title": "Supprimer le segment de contour ?",
|
||||
@@ -76,7 +73,6 @@
|
||||
"title.zoom_in": "Zoomer",
|
||||
"title.zoom_out": "Dézoomer",
|
||||
"title.zoom_fit": "Tout ajuster",
|
||||
"title.markup": "Traçage des pièces : grille, lignes, contours",
|
||||
"title.configure_space": "Configurer l’espace",
|
||||
"title.add_space": "Ajouter un espace",
|
||||
"title.markup_add": "Murs : tracez une chaîne continue ; Maj verrouille à 45°. Changer d’outil ou quitter l’éditeur termine la chaîne en murs indépendants",
|
||||
@@ -121,7 +117,6 @@
|
||||
"history.edit_opening": "Modifier l’ouverture",
|
||||
"history.move_opening": "Déplacer l’ouverture",
|
||||
"history.delete_opening": "Supprimer l’ouverture",
|
||||
"history.delete_room": "Supprimer la pièce",
|
||||
"history.delete_room_keep_walls": "Supprimer la pièce, conserver les murs",
|
||||
"history.delete_room_with_walls": "Supprimer la pièce et les murs",
|
||||
"history.decor_add": "Ajouter un objet décoratif",
|
||||
@@ -163,7 +158,6 @@
|
||||
"confirm.delete_partition_openings_title": "Supprimer le mur et les ouvertures ?",
|
||||
"confirm.delete_partition_openings_body": "Ce mur contient {count} ouverture(s). Elles seront supprimées avec lui.",
|
||||
"confirm.delete_partition_openings_item": "• {type}, {length}",
|
||||
"markup.delete": "Supprimer",
|
||||
"markup.hint_points": "points : {n} · Maj — pas de 45° · Échap — terminer la chaîne · Ctrl+Z — annuler un point · fermer une zone propose de créer une pièce",
|
||||
"markup.hint_start": "cliquez sur un point de la grille pour commencer une chaîne de murs",
|
||||
"tip.lqi": "signal Zigbee moyen :",
|
||||
@@ -192,9 +186,7 @@
|
||||
"display.badge": "Icône + état",
|
||||
"display.icon_ripple": "Icône + état et activité",
|
||||
"display.static_icon": "Icône toujours statique",
|
||||
"marker.display_hint": "Icône + état modifie le fond pour les états en fonctionnement, ouvert, alarme et indisponible. Icône + état et activité ajoute une brève pulsation pour les événements et une pulsation continue pour une activité, un mouvement ou une présence en cours. Valeur + état remplace l’icône par une valeur HA non ambiguë. Une icône statique ne réagit jamais aux états de l’appareil.",
|
||||
"marker.display_hint_badge": "L’icône et le fond dynamique affichent l’état de l’appareil sans la pulsation d’activité habituelle. Les alarmes rouges restent visibles.",
|
||||
"marker.display_hint_icon": "L’icône et le fond dynamique affichent l’état de l’appareil sans la pulsation d’activité habituelle. Les alarmes rouges restent visibles.",
|
||||
"marker.display_hint_icon_ripple": "L’icône, le fond dynamique et la pulsation affichent une brève animation pour les événements et une animation continue pour le fonctionnement, le mouvement ou la présence. Les alarmes rouges restent prioritaires.",
|
||||
"marker.display_hint_value": "Une valeur Home Assistant sélectionnée ou résolue automatiquement remplace l’icône tandis que le fond continue d’indiquer l’état. Les alarmes rouges restent visibles.",
|
||||
"marker.display_hint_static_icon": "Le contour adapté au thème et l’icône restent toujours identiques. L’état, l’activité, l’indisponibilité et les alarmes ne modifient pas l’apparence.",
|
||||
@@ -293,14 +285,11 @@
|
||||
"device.light_group": "groupe de lumières",
|
||||
"device.fallback": "appareil",
|
||||
"device.virtual": "appareil virtuel",
|
||||
"confirm.delete_room": "Supprimer la pièce « {name} » ?",
|
||||
"confirm.delete_room_title": "Supprimer la pièce « {name} » ?",
|
||||
"confirm.delete_room_body": "Choisissez si les murs physiques propres à la pièce doivent être conservés. Les murs partagés avec une autre pièce sont toujours conservés.",
|
||||
"confirm.remove_marker": "Supprimer « {name} » du plan ? L’appareil disparaîtra complètement et ne contribuera plus aux données du plan. Vous pourrez l’ajouter de nouveau plus tard.",
|
||||
"confirm.remove_marker_title": "Supprimer l’appareil du plan ?",
|
||||
"confirm.remove_marker_body": "L’appareil disparaîtra complètement et ne contribuera plus aux données du plan. Vous pourrez l’ajouter de nouveau plus tard.",
|
||||
"confirm.erase_decor": "Effacer l’objet {kind} ? Vous pouvez annuler cette action depuis l’historique de l’éditeur.",
|
||||
"confirm.delete_space": "Supprimer l’espace « {title} » avec toutes ses pièces et son tracé ?",
|
||||
"confirm.delete_space_title": "Supprimer l’espace ?",
|
||||
"confirm.delete_space_body": "L’espace, toutes ses pièces et tout le tracé du plan seront supprimés.",
|
||||
"space.delete_blocked": "Cet espace est encore utilisé par {n} appareil(s). Déplacez-les vers un autre espace ou supprimez-les d’abord.",
|
||||
@@ -737,7 +726,6 @@
|
||||
"marker.control_passive": "source passive",
|
||||
"toast.marker_control_cycle": "Ce lien créerait une chaîne circulaire de contrôles de lumière.",
|
||||
"toast.marker_binding_required": "Choisissez un appareil Home Assistant avant de lier une autre source lumineuse.",
|
||||
"confirm.unlock": "Déverrouiller « {name} » ?",
|
||||
"confirm.unlock_title": "Déverrouiller ?",
|
||||
"confirm.unlock_body": "House Plan enverra une commande de déverrouillage à cette serrure.",
|
||||
"toast.files_migrate_failed": "Les pièces jointes n’ont pas pu être déplacées vers la nouvelle association ; les liens continuent de pointer vers les anciens fichiers : {err}",
|
||||
@@ -748,7 +736,6 @@
|
||||
"space.used_by": "utilisé par : {list}",
|
||||
"space.in_use": "Un espace utilise encore ce plan — dissociez-le d’abord",
|
||||
"btn.use": "Utiliser",
|
||||
"confirm.delete_plan": "Supprimer le fichier de plan « {name} » du serveur ? Cette action est irréversible.",
|
||||
"confirm.delete_plan_title": "Supprimer le fichier du plan ?",
|
||||
"confirm.delete_plan_body": "Le fichier sera supprimé du serveur. Cette action est irréversible.",
|
||||
"toast.plans_list_failed": "Impossible de lister les plans stockés : {err}",
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"history.draft_segment": "Добавление сегмента черновика комнаты",
|
||||
"history.draft_merge": "Соединение незавершённых контуров комнаты",
|
||||
"history.draft_segment_delete": "Удаление сегмента черновика комнаты",
|
||||
"history.partition_add": "Добавление перегородки",
|
||||
"history.column_add": "Добавление колонны",
|
||||
"history.physical_edit": "Изменение физического объекта",
|
||||
"history.physical_delete": "Удаление физического объекта",
|
||||
@@ -37,8 +36,6 @@
|
||||
"history.wall_chain_finish": "Завершение цепочки стен",
|
||||
"history.wall_face_batch": "Создание комнат из стен",
|
||||
"toast.column_duplicate": "Колонна с тем же центром и внешним размером уже существует",
|
||||
"confirm.delete_draft": "Удалить весь незавершённый контур комнаты?",
|
||||
"confirm.delete_draft_segment": "Удалить этот сегмент черновика? Оставшийся контур может разделиться на два.",
|
||||
"confirm.delete_draft_title": "Удалить незавершённый контур?",
|
||||
"confirm.delete_draft_body": "Весь незавершённый контур комнаты будет удалён. При отмене ничего не изменится.",
|
||||
"confirm.delete_draft_segment_title": "Удалить сегмент контура?",
|
||||
@@ -76,7 +73,6 @@
|
||||
"title.zoom_in": "Приблизить",
|
||||
"title.zoom_out": "Отдалить",
|
||||
"title.zoom_fit": "Вписать всё",
|
||||
"title.markup": "Разметка комнат: сетка, линии, контуры",
|
||||
"title.configure_space": "Настроить пространство",
|
||||
"title.add_space": "Добавить пространство",
|
||||
"title.markup_add": "Стены: рисуйте непрерывную цепочку; Shift фиксирует 45°. Смена инструмента или выход завершает её как независимые стены",
|
||||
@@ -121,7 +117,6 @@
|
||||
"history.edit_opening": "Изменение проёма",
|
||||
"history.move_opening": "Перемещение проёма",
|
||||
"history.delete_opening": "Удаление проёма",
|
||||
"history.delete_room": "Удаление комнаты",
|
||||
"history.delete_room_keep_walls": "Удаление комнаты с сохранением стен",
|
||||
"history.delete_room_with_walls": "Удаление комнаты и её стен",
|
||||
"history.decor_add": "Добавление объекта декора",
|
||||
@@ -163,7 +158,6 @@
|
||||
"confirm.delete_partition_openings_title": "Удалить стену и проёмы?",
|
||||
"confirm.delete_partition_openings_body": "В стене есть проёмы: {count}. Они будут удалены вместе со стеной.",
|
||||
"confirm.delete_partition_openings_item": "• {type}, {length}",
|
||||
"markup.delete": "Удалить",
|
||||
"markup.hint_points": "точек: {n} · Shift — шаг 45° · Esc — завершить цепочку · Ctrl+Z — убрать точку · при замыкании будет предложена комната",
|
||||
"markup.hint_start": "кликните точку сетки, чтобы начать цепочку стен",
|
||||
"tip.lqi": "средний сигнал zigbee:",
|
||||
@@ -192,9 +186,7 @@
|
||||
"display.badge": "Значок + состояние",
|
||||
"display.icon_ripple": "Значок + состояние и активность",
|
||||
"display.static_icon": "Всегда статичный значок",
|
||||
"marker.display_hint": "Значок + состояние меняет подложку при работе, открытии, тревоге и недоступности. Значок + состояние и активность дополнительно показывает короткую пульсацию для событий и постоянную — для работы, движения или присутствия. Значение + состояние заменяет значок одним однозначным значением HA. Статичный значок не реагирует на состояния устройства.",
|
||||
"marker.display_hint_badge": "Значок и динамическая подложка показывают состояние устройства без обычной пульсации активности. Красная тревога сохраняется.",
|
||||
"marker.display_hint_icon": "Значок и динамическая подложка показывают состояние устройства без обычной пульсации активности. Красная тревога сохраняется.",
|
||||
"marker.display_hint_icon_ripple": "Значок, динамическая подложка и пульсация: короткая — для событий, постоянная — для работы, движения или присутствия. Красная тревога имеет отдельный приоритет.",
|
||||
"marker.display_hint_value": "Значок заменяется выбранным или автоматически найденным значением Home Assistant; подложка продолжает показывать состояние. Красная тревога сохраняется.",
|
||||
"marker.display_hint_static_icon": "Подложка в цветах темы и значок всегда остаются одинаковыми. Состояния, активность, недоступность и тревоги не меняют отображение.",
|
||||
@@ -293,14 +285,11 @@
|
||||
"device.light_group": "группа света",
|
||||
"device.fallback": "устройство",
|
||||
"device.virtual": "виртуальное устройство",
|
||||
"confirm.delete_room": "Удалить комнату «{name}»?",
|
||||
"confirm.delete_room_title": "Удалить комнату «{name}»?",
|
||||
"confirm.delete_room_body": "Выберите, нужно ли оставить физические стены, принадлежащие только этой комнате. Общие с другой комнатой стены сохраняются всегда.",
|
||||
"confirm.remove_marker": "Удалить «{name}» с плана? Устройство исчезнет полностью и перестанет участвовать в данных плана. Позже его можно будет добавить заново.",
|
||||
"confirm.remove_marker_title": "Удалить устройство с плана?",
|
||||
"confirm.remove_marker_body": "Устройство исчезнет полностью и перестанет участвовать в данных плана. Позже его можно будет добавить заново.",
|
||||
"confirm.erase_decor": "Стереть объект «{kind}»? Действие можно отменить из истории редактора.",
|
||||
"confirm.delete_space": "Удалить пространство «{title}» со всеми комнатами и разметкой?",
|
||||
"confirm.delete_space_title": "Удалить пространство?",
|
||||
"confirm.delete_space_body": "Пространство, все его комнаты и вся разметка плана будут удалены.",
|
||||
"space.delete_blocked": "Это пространство всё ещё используется устройствами: {n}. Сначала перенесите их в другое пространство или удалите.",
|
||||
@@ -737,7 +726,6 @@
|
||||
"marker.control_passive": "пассивный источник",
|
||||
"toast.marker_control_cycle": "Такая связь создаст циклическую цепочку управления светом.",
|
||||
"toast.marker_binding_required": "Сначала выберите устройство Home Assistant, затем добавьте управляемый источник света.",
|
||||
"confirm.unlock": "Открыть замок «{name}»?",
|
||||
"confirm.unlock_title": "Открыть замок?",
|
||||
"confirm.unlock_body": "House Plan отправит этому замку команду открытия.",
|
||||
"toast.files_migrate_failed": "Не удалось перенести вложения к новой привязке, ссылки остались на старые файлы: {err}",
|
||||
@@ -748,7 +736,6 @@
|
||||
"space.used_by": "используется: {list}",
|
||||
"space.in_use": "План используется пространством — сначала отцепите его",
|
||||
"btn.use": "Выбрать",
|
||||
"confirm.delete_plan": "Удалить файл плана «{name}» с сервера? Действие необратимо.",
|
||||
"confirm.delete_plan_title": "Удалить файл плана?",
|
||||
"confirm.delete_plan_body": "Файл будет удалён с сервера. Это действие нельзя отменить.",
|
||||
"toast.plans_list_failed": "Не удалось получить список планов: {err}",
|
||||
|
||||
Reference in New Issue
Block a user