456 files

This commit is contained in:
Home Assistant Version Control
2026-10-01 05:38:21 +00:00
parent 4192ecbaae
commit 5d6d845ebf
456 changed files with 64951 additions and 3828 deletions
@@ -241,6 +241,26 @@
"sort_task_name": "Název úkolu",
"all_objects": "Všechny objekty",
"all_parts": "Všechny díly",
"all_areas": "Všechny oblasti",
"areas_filter": "Filtrovat oblasti…",
"areas_filter_none": "Filtru neodpovídá žádná oblast.",
"area_cost_year": "Náklady {year}",
"area_object_count": "Objekty: {n}",
"area_object_count_one": "1 objekt",
"area_range_12m": "Posledních 12 měsíců",
"area_range_all": "Celé období",
"area_task_filter": "Filtrovat podle úkolu…",
"area_kpi_completions": "Dokončení",
"area_kpi_total_time": "Celkový čas",
"area_cost_per_month": "Náklady podle měsíců",
"area_cost_per_year": "Náklady podle let",
"area_cost_per_object": "Náklady podle objektů",
"area_cost_share": "Podíl",
"area_history_section": "Historie (všechny objekty)",
"area_report_print": "Přehled oblasti (PDF)",
"area_report_title": "Přehled oblasti",
"area_report_period": "Období",
"area_no_costs": "V tomto období nejsou zaznamenány žádné náklady.",
"no_tasks_yet": "Zatím žádné úkoly",
"add_first_task": "Přidat první úkol",
"trigger_configuration": "Konfigurace spouštěče",
@@ -399,11 +419,70 @@
"qr_download": "Stáhnout SVG",
"qr_action_view": "Zobrazit informace o údržbě",
"qr_action_complete": "Označit údržbu jako dokončenou",
"qr_action_quick_complete": "Rychlé dokončení — bez dialogu",
"qr_print_quick_none": "Kódy rychlého dokončení vyžadují u úkolu výchozí hodnoty rychlého dokončení (dialog úkolu → Výchozí hodnoty rychlého dokončení) — žádný úkol vybraných objektů je zatím nemá.",
"qr_url_mode": "Typ odkazu",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Lokální (mDNS)",
"qr_mode_server": "URL serveru",
"overview": "Přehled",
"strat_this_month": "Tento měsíc",
"strat_later": "Později",
"strat_week": "Týden",
"strat_fortnight": "Dva týdny",
"strat_month": "Měsíc",
"strat_year": "Rok",
"strat_other": "Ostatní",
"strat_status": "Stav",
"strat_empty_title": "Zatím žádné objekty údržby",
"strat_empty_content": "Otevřete panel Údržba a přidejte první objekt — bazénové čerpadlo, filtr vzduchotechniky, vozidlo, cokoli, co potřebuje pravidelnou péči.",
"strat_open_panel": "Otevřít panel Údržba",
"strat_add_object": "Přidat objekt",
"strat_not_loaded": "**Maintenance Supporter** není načten. Nejprve nainstalujte/povolte integraci.",
"strat_group_by": "Seskupit zobrazení podle",
"strat_group_area": "Podle oblasti (výchozí)",
"strat_group_status": "Podle stavu (Po termínu / Spuštěno / Brzy / OK)",
"strat_group_floor": "Podle podlaží (používá podlaží z HA)",
"strat_group_due_date": "Podle termínu (Po termínu / Dnes / Tento týden / Tento měsíc / Později)",
"strat_group_calendar": "Klouzavý kalendář (Týden / Dva týdny / Měsíc / Rok)",
"strat_editor_help": "Zobrazení „Přehled“ je vždy první. Prázdné skupiny se vynechávají.",
"picker_name_calendar": "Maintenance Supporter — Kalendář",
"picker_name_panel": "Maintenance Supporter — Panel jako karta",
"picker_name_budget": "Maintenance Supporter — Rozpočet údržby",
"picker_name_groups": "Maintenance Supporter — Skupiny",
"picker_name_vacation": "Maintenance Supporter — Režim dovolené",
"picker_name_battery_fleet": "Flotila baterií",
"picker_name_section": "Maintenance Supporter — Sekce",
"picker_name_vacation_status": "Maintenance Supporter — Stav dovolené",
"picker_name_budget_status": "Maintenance Supporter — Stav rozpočtu",
"picker_desc_card": "Přehled úkolů údržby s rychlými akcemi.",
"picker_desc_calendar": "Klouzavý kalendář úkolů údržby s okny 7/14/30/365 dní, ikonami zdroje a štítky přesnosti předpovědi.",
"picker_desc_panel": "Celý panel Maintenance Supporter jako karta — pro zobrazení typu panel / podzobrazení dashboardu bez položky v postranním panelu.",
"picker_desc_budget": "Upravte měsíční a roční rozpočet přímo na dashboardu.",
"picker_desc_groups": "Vytvářejte, přejmenovávejte a mažte skupiny úkolů přímo na dashboardu.",
"picker_desc_vacation": "Zapínejte a vypínejte režim dovolené a nastavte jeho termín přímo na dashboardu.",
"picker_desc_battery_fleet": "Všechny sledované baterie: co je teď slabé, co se brzy vybije a co koupit.",
"picker_desc_dashboard": "Automaticky generovaný dashboard. Seskupte zobrazení podle oblasti, stavu, podlaží nebo termínu — volba v editoru strategie nebo v YAML.",
"picker_desc_section": "Vložte úkoly údržby (filtrovatelné podle oblasti, stavu, termínu) jako sekci do libovolného zobrazení dashboardu.",
"picker_desc_vacation_status": "Kompaktní banner se stavem režimu dovolené. Klepnutím otevřete nastavení v panelu.",
"picker_desc_budget_status": "Přehled měsíčního a ročního rozpočtu na údržbu. Klepnutím zobrazíte podrobnosti.",
"picker_desc_groups_status": "Seznam nastavených skupin úkolů s počtem úkolů v každé.",
"hist_note_button": "Dokončeno tlačítkem na dashboardu",
"hist_note_todo": "Dokončeno ze seznamu úkolů",
"hist_note_voice": "Dokončeno hlasem",
"hist_note_notification": "Dokončeno z oznámení",
"hist_note_nfc": "Dokončeno přes NFC tag",
"hist_note_shopping_list": "Dokončeno z nákupního seznamu",
"hist_note_todo_mirror": "Dokončeno ze zrcadleného seznamu úkolů",
"hist_note_skipped_notification": "Přeskočeno z oznámení",
"hist_note_skipped_button": "Přeskočeno tlačítkem na dashboardu",
"hist_note_sensor_triggered": "Spouštěč senzoru aktivován",
"hist_note_initial": "Počáteční hodnota nastavena při vytvoření úkolu",
"hist_note_auto_recovered": "Automaticky dokončeno: senzor se zotavil ({value})",
"hist_note_reset": "Resetováno na {date}",
"hist_note_trigger_replaced": "Entita spouštěče nahrazena: {old} → {new}",
"hist_note_trigger_removed": "Spouštěč senzoru odebrán (entita: {entity}). Plán převeden na {schedule}.",
"hist_note_compound_removed": "Entita {entity} odebrána ze složeného spouštěče; zbývající podmínky: {count}.",
"recent_activities": "Nedávné aktivity",
"search_notes": "Hledat v poznámkách",
"avg_cost": "Prům. náklady",
@@ -716,6 +795,7 @@
"groups_manage_tasks": "Spravovat přiřazení úkolů…",
"groups_open_panel": "Otevřít v panelu",
"on_complete_action_target_hint": "Poznámka: doména entity musí odpovídat službě — např. 'button.press' funguje jen na button.*, 'counter.increment' jen na counter.*, 'input_button.press' jen na input_button.* atd. Při neshodě akce tiše selže (HA zaznamená 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Ne, když se úkol dokončí sám (jeho senzor se zotavil)",
"show_all_objects": "Zobrazit všechny objekty",
"show_all_tasks": "Vymazat filtr — zobrazit všechny úkoly",
"filter_to_overdue": "Filtrovat seznam jen na po termínu",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "„{name}“: úkoly {before} → {after}",
"adopt_problem_adopt": "Převzít vybrané",
"adopt_problem_done": "Převzato {tasks} senzorů problémů",
"adopt_problem_done_one": "Převzat 1 senzor problémů",
"views_label": "Zobrazení",
"views_none": "— Žádné zobrazení —",
"views_manage": "Uložit / spravovat zobrazení",
@@ -1013,6 +1094,7 @@
"setups_none": "Nenalezena žádná podporovaná zařízení s nepropojenými senzory spotřebního materiálu.",
"setups_adopt": "Nastavit vybrané",
"setups_done": "Vytvořeno {tasks} úkolů propojených se senzory.",
"setups_done_one": "Vytvořen 1 úkol propojený se senzory.",
"complete_parts_used": "Tentokrát použité díly",
"part_delete_confirm": "Smazat díl '{name}'? Odstraní se sledování zásob, vazby na úkoly i případná otevřená připomínka nákupu.",
"baseline_start_value": "Počáteční hodnota (volitelné)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "stejný model na jiném zařízení",
"setups_maybe_covered": "Pravděpodobně už existuje jako „{name}“",
"setups_already": "Už existuje: {names}",
"setups_reset_line": "Dokončení také resetuje čítač v integraci („{button}“)",
"setups_reset_enable": "— tlačítko se k tomu zapne",
"reset_offers_title": "Resetovat čítače při dokončení",
"reset_offers_hint": "Tyto úkoly sledují čítač, který si integrace vede sama. Po propojení dokončení úkolu zde stiskne také resetovací tlačítko integrace — jinak čítač běží dál a úkol je hned znovu splatný.",
"reset_offers_before": "Nyní: dokončení nechá čítač v {integration} běžet dál",
"reset_offers_after": "Poté: stiskne také „{button}“",
"reset_offers_renamed": "Od nastavení přejmenováno — ověřte, že úkol patří k tomuto dílu",
"reset_offers_apply": "Propojit resety",
"reset_offers_done": "Úkoly, které nyní při dokončení resetují čítač: {count}",
"reset_offers_done_one": "1 úkol nyní při dokončení resetuje čítač",
"setups_before_after": "Úkoly u objektu: {before} → {after}",
"setups_new_object_count": "Nový objekt „{name}“ · úkoly: {count}",
"schedule_preview_title": "Nejbližší termíny",
@@ -1046,6 +1138,7 @@
"history_auto": "Automaticky",
"battery_fleet_title": "Flotila baterií",
"battery_fleet_none_low": "Všechny baterie OK — není co měnit.",
"battery_fleet_progress": "K výměně: {n}",
"battery_fleet_buy_now": "Koupit nyní",
"battery_fleet_soon": "Brzy potřeba",
"battery_fleet_soon_hint": "Odhad podle poslední výměny — objednejte předem.",
@@ -1099,8 +1192,12 @@
"dismiss": "Skrýt",
"gs_label": "Začínáme — tyto tipy zmizí, jak vaše nastavení poroste",
"gs_setups_chip": "Navrhovaná nastavení: nalezeno {n} zařízení s předpřipravenými spouštěči",
"gs_setups_chip_one": "Navrhovaná nastavení: nalezeno 1 zařízení s předpřipravenými spouštěči",
"gs_adopt_chip": "{n} problémových senzorů se může stát údržbovými úkoly",
"gs_adopt_chip_one": "1 problémový senzor se může stát údržbovým úkolem",
"gs_fleet_chip": "Jedno kliknutí nastaví flotilu baterií",
"gs_reset_chip": "{n} úkolů může resetovat čítač v integraci",
"gs_reset_chip_one": "1 úkol může resetovat čítač v integraci",
"cal_editor_window": "Výchozí okno",
"cal_editor_window_week": "Týden (7 dní)",
"cal_editor_window_fortnight": "Dva týdny (14 dní)",
@@ -243,6 +243,26 @@
"sort_task_name": "Opgavenavn",
"all_objects": "Alle objekter",
"all_parts": "Alle dele",
"all_areas": "Alle områder",
"areas_filter": "Filtrér områder…",
"areas_filter_none": "Intet område matcher filteret.",
"area_cost_year": "Omkostning {year}",
"area_object_count": "{n} objekter",
"area_object_count_one": "1 objekt",
"area_range_12m": "Seneste 12 måneder",
"area_range_all": "Hele perioden",
"area_task_filter": "Filtrér efter opgave…",
"area_kpi_completions": "Udførelser",
"area_kpi_total_time": "Samlet tid",
"area_cost_per_month": "Omkostning pr. måned",
"area_cost_per_year": "Omkostning pr. år",
"area_cost_per_object": "Omkostning pr. objekt",
"area_cost_share": "Andel",
"area_history_section": "Historik (alle objekter)",
"area_report_print": "Områderapport (PDF)",
"area_report_title": "Områderapport",
"area_report_period": "Periode",
"area_no_costs": "Ingen omkostninger registreret i denne periode.",
"no_tasks_yet": "Ingen opgaver endnu",
"add_first_task": "Tilføj første opgave",
"trigger_configuration": "Udløserkonfiguration",
@@ -401,11 +421,70 @@
"qr_download": "Download SVG",
"qr_action_view": "Vis vedligeholdelsesoplysninger",
"qr_action_complete": "Marker vedligeholdelse som fuldført",
"qr_action_quick_complete": "Hurtig-fuldfør — uden dialog",
"qr_print_quick_none": "Hurtig-fuldfør-koder kræver standardværdier for hurtig-fuldfør på en opgave (opgavedialogen → Standardværdier for hurtig-fuldfør) — ingen opgave i de valgte objekter har nogen endnu.",
"qr_url_mode": "Linktype",
"qr_mode_companion": "Companion-app",
"qr_mode_local": "Lokal (mDNS)",
"qr_mode_server": "Server-URL",
"overview": "Oversigt",
"strat_this_month": "Denne måned",
"strat_later": "Senere",
"strat_week": "Uge",
"strat_fortnight": "To uger",
"strat_month": "Måned",
"strat_year": "År",
"strat_other": "Andet",
"strat_status": "Tilstand",
"strat_empty_title": "Ingen vedligeholdelsesobjekter endnu",
"strat_empty_content": "Åbn Vedligeholdelse-panelet for at tilføje dit første objekt — poolpumpe, ventilationsfilter, køretøj, alt der har brug for planlagt pleje.",
"strat_open_panel": "Åbn Vedligeholdelse-panelet",
"strat_add_object": "Tilføj objekt",
"strat_not_loaded": "**Maintenance Supporter** er ikke indlæst. Installer/aktivér integrationen først.",
"strat_group_by": "Gruppér visninger efter",
"strat_group_area": "Efter område (standard)",
"strat_group_status": "Efter status (Forfalden / Udløst / Snart forfalden / OK)",
"strat_group_floor": "Efter etage (bruger HA-etagerne)",
"strat_group_due_date": "Efter forfaldsdato (Forfalden / I dag / Denne uge / Denne måned / Senere)",
"strat_group_calendar": "Rullende kalender (Uge / To uger / Måned / År)",
"strat_editor_help": "Visningen \"Oversigt\" er altid først. Tomme grupper springes over.",
"picker_name_calendar": "Maintenance Supporter — Kalender",
"picker_name_panel": "Maintenance Supporter — Panel som kort",
"picker_name_budget": "Maintenance Supporter — Vedligeholdelsesbudget",
"picker_name_groups": "Maintenance Supporter — Grupper",
"picker_name_vacation": "Maintenance Supporter — Ferietilstand",
"picker_name_battery_fleet": "Batteriflåde",
"picker_name_section": "Maintenance Supporter — Sektion",
"picker_name_vacation_status": "Maintenance Supporter — Feriestatus",
"picker_name_budget_status": "Maintenance Supporter — Budgetstatus",
"picker_desc_card": "Oversigt over dine vedligeholdelsesopgaver med hurtighandlinger.",
"picker_desc_calendar": "Rullende kalender over vedligeholdelsesopgaver med vinduer på 7/14/30/365 dage, kildeikoner og mærker for prognosesikkerhed.",
"picker_desc_panel": "Hele Maintenance Supporter-panelet som kort — til en panelvisning / dashboard-undervisning uden punkt i sidebjælken.",
"picker_desc_budget": "Rediger måneds- og årsbudgettet direkte på dashboardet.",
"picker_desc_groups": "Opret, omdøb og slet opgavegrupper direkte på dashboardet.",
"picker_desc_vacation": "Slå ferietilstand til eller fra, og angiv datoerne direkte på dashboardet.",
"picker_desc_battery_fleet": "Alle overvågede batterier: hvad der er lavt nu, hvad der snart løber tør, og hvad der skal købes.",
"picker_desc_dashboard": "Automatisk genereret dashboard. Gruppér visninger efter område, status, etage eller forfaldsdato — vælges i strategieditoren eller i YAML.",
"picker_desc_section": "Indlejr vedligeholdelsesopgaver (kan filtreres efter område, status, forfaldsdato) som en sektion i enhver dashboardvisning.",
"picker_desc_vacation_status": "Kompakt statusbanner for ferietilstand. Tryk for at åbne indstillingerne i panelet.",
"picker_desc_budget_status": "Oversigt over måneds- og årsbudgettet til vedligeholdelse. Tryk for detaljer.",
"picker_desc_groups_status": "Liste over konfigurerede opgavegrupper med antal opgaver i hver.",
"hist_note_button": "Fuldført via knap på dashboardet",
"hist_note_todo": "Fuldført fra to-do-listen",
"hist_note_voice": "Fuldført med stemmen",
"hist_note_notification": "Fuldført fra notifikationen",
"hist_note_nfc": "Fuldført via NFC-tag",
"hist_note_shopping_list": "Fuldført fra indkøbslisten",
"hist_note_todo_mirror": "Fuldført fra en spejlet to-do-liste",
"hist_note_skipped_notification": "Sprunget over fra notifikationen",
"hist_note_skipped_button": "Sprunget over via knap på dashboardet",
"hist_note_sensor_triggered": "Sensorudløser aktiveret",
"hist_note_initial": "Startværdi angivet ved oprettelse af opgaven",
"hist_note_auto_recovered": "Automatisk fuldført: sensoren er normal igen ({value})",
"hist_note_reset": "Nulstillet til {date}",
"hist_note_trigger_replaced": "Udløserentitet erstattet: {old} → {new}",
"hist_note_trigger_removed": "Sensorudløser fjernet (entitet: {entity}). Tidsplan ændret til {schedule}.",
"hist_note_compound_removed": "Entiteten {entity} fjernet fra den sammensatte udløser; resterende betingelser: {count}.",
"recent_activities": "Seneste aktiviteter",
"search_notes": "Søg i noter",
"avg_cost": "Gns. omkostning",
@@ -703,6 +782,7 @@
"on_complete_action_desc": "Kalder en HA-tjeneste, når opgaven fuldføres — f.eks. nulstil en tæller på enheden.",
"on_complete_action_target": "Målenhed",
"on_complete_action_target_hint": "Bemærk: enhedens domæne skal matche tjenesten — f.eks. virker 'button.press' kun på button.*, 'counter.increment' kun på counter.*, 'input_button.press' kun på input_button.* osv. Ved et misforhold mislykkes handlingen lydløst (HA logger 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Ikke når opgaven fuldføres af sig selv (dens sensor er normal igen)",
"on_complete_action_data": "Data (JSON, valgfrit)",
"on_complete_action_test": "Valider konfiguration",
"on_complete_action_test_success": "✓ Konfiguration gyldig (handlingen udløses kun ved fuldførelse af opgaven)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "\"{name}\": opgaver {before} → {after}",
"adopt_problem_adopt": "Adopter valgte",
"adopt_problem_done": "Adopterede {tasks} problemsensor(er)",
"adopt_problem_done_one": "Adopterede 1 problemsensor",
"views_label": "Visninger",
"views_none": "— Ingen visning —",
"views_manage": "Gem / administrer visninger",
@@ -1013,6 +1094,7 @@
"setups_none": "Ingen understøttede enheder med utilkoblede forbrugsstof-sensorer fundet.",
"setups_adopt": "Opsæt valgte",
"setups_done": "{tasks} sensor-koblede opgaver oprettet.",
"setups_done_one": "1 sensor-koblet opgave oprettet.",
"complete_parts_used": "Dele brugt denne gang",
"part_delete_confirm": "Slet delen '{name}'? Lagersporing, opgavekoblinger og en åben købspåmindelse fjernes.",
"baseline_start_value": "Startværdi (valgfrit)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "samme model på en anden enhed",
"setups_maybe_covered": "Findes sandsynligvis allerede som \"{name}\"",
"setups_already": "Findes allerede: {names}",
"setups_reset_line": "Fuldførelse nulstiller også tælleren i integrationen (“{button}”)",
"setups_reset_enable": "— knappen aktiveres til dette formål",
"reset_offers_title": "Nulstil tællere ved fuldførelse",
"reset_offers_hint": "Disse opgaver overvåger en tæller, som integrationen selv fører. Når de er forbundet, trykker en fuldførelse her også på integrationens nulstillingsknap — ellers kører tælleren videre, og opgaven forfalder straks igen.",
"reset_offers_before": "Nu: fuldførelse lader tælleren i {integration} køre videre",
"reset_offers_after": "Derefter: trykker også på “{button}”",
"reset_offers_renamed": "Omdøbt siden opsætningen — tjek, at opgaven hører til denne del",
"reset_offers_apply": "Forbind nulstillinger",
"reset_offers_done": "{count} opgaver nulstiller nu deres tæller ved fuldførelse",
"reset_offers_done_one": "1 opgave nulstiller nu sin tæller ved fuldførelse",
"setups_before_after": "Opgaver på objektet: {before} → {after}",
"setups_new_object_count": "Nyt objekt \"{name}\" · opgaver: {count}",
"schedule_preview_title": "Kommende datoer",
@@ -1046,6 +1138,7 @@
"history_auto": "Automatisk",
"battery_fleet_title": "Batteriflåde",
"battery_fleet_none_low": "Alle batterier OK — intet at skifte.",
"battery_fleet_progress": "{n} skal skiftes",
"battery_fleet_buy_now": "Køb nu",
"battery_fleet_soon": "Nødvendigt snart",
"battery_fleet_soon_hint": "Estimeret ud fra sidste skift — bestil på forhånd.",
@@ -1099,8 +1192,12 @@
"dismiss": "Afvis",
"gs_label": "Kom godt i gang — disse tips forsvinder, efterhånden som opsætningen vokser",
"gs_setups_chip": "Foreslåede opsætninger fandt {n} enheder med forudindstillede udløsere",
"gs_setups_chip_one": "Foreslåede opsætninger fandt 1 enhed med forudindstillede udløsere",
"gs_adopt_chip": "{n} problemsensorer kan blive vedligeholdelsesopgaver",
"gs_adopt_chip_one": "1 problemsensor kan blive en vedligeholdelsesopgave",
"gs_fleet_chip": "Ét klik opsætter batteriflåden",
"gs_reset_chip": "{n} opgaver kan nulstille deres tæller i integrationen",
"gs_reset_chip_one": "1 opgave kan nulstille sin tæller i integrationen",
"cal_editor_window": "Standardvindue",
"cal_editor_window_week": "Uge (7 dage)",
"cal_editor_window_fortnight": "To uger (14 dage)",
@@ -243,6 +243,26 @@
"sort_task_name": "Aufgaben-Name",
"all_objects": "Alle Objekte",
"all_parts": "Alle Teile",
"all_areas": "Alle Bereiche",
"areas_filter": "Bereiche filtern…",
"areas_filter_none": "Kein Bereich passt zum Filter.",
"area_cost_year": "Kosten {year}",
"area_object_count": "{n} Objekte",
"area_object_count_one": "1 Objekt",
"area_range_12m": "Letzte 12 Monate",
"area_range_all": "Gesamter Zeitraum",
"area_task_filter": "Nach Aufgabe filtern…",
"area_kpi_completions": "Erledigungen",
"area_kpi_total_time": "Gesamtzeit",
"area_cost_per_month": "Kosten pro Monat",
"area_cost_per_year": "Kosten pro Jahr",
"area_cost_per_object": "Kosten pro Objekt",
"area_cost_share": "Anteil",
"area_history_section": "Verlauf (alle Objekte)",
"area_report_print": "Bereichsbericht (PDF)",
"area_report_title": "Bereichsbericht",
"area_report_period": "Zeitraum",
"area_no_costs": "Keine Kosten in diesem Zeitraum erfasst.",
"no_tasks_yet": "Noch keine Aufgaben",
"add_first_task": "Erste Aufgabe hinzufügen",
"trigger_configuration": "Trigger-Konfiguration",
@@ -401,11 +421,70 @@
"qr_download": "SVG herunterladen",
"qr_action_view": "Wartungsinfo anzeigen",
"qr_action_complete": "Wartung als erledigt markieren",
"qr_action_quick_complete": "Schnell-Abschluss — ohne Dialog",
"qr_print_quick_none": "Schnell-Abschluss-Codes brauchen Schnell-Abschluss-Standardwerte an einer Aufgabe (Aufgabendialog → Schnell-Abschluss-Standardwerte) — noch keine Aufgabe der gewählten Objekte hat welche.",
"qr_url_mode": "Link-Typ",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Lokal (mDNS)",
"qr_mode_server": "Server-URL",
"overview": "Übersicht",
"strat_this_month": "Diesen Monat",
"strat_later": "Später",
"strat_week": "Woche",
"strat_fortnight": "Zwei Wochen",
"strat_month": "Monat",
"strat_year": "Jahr",
"strat_other": "Sonstige",
"strat_status": "Aktueller Stand",
"strat_empty_title": "Noch keine Wartungsobjekte",
"strat_empty_content": "Öffne das Wartungspanel und füge dein erstes Objekt hinzu — Poolpumpe, Lüftungsfilter, Fahrzeug, alles, was regelmäßige Pflege braucht.",
"strat_open_panel": "Wartungspanel öffnen",
"strat_add_object": "Objekt hinzufügen",
"strat_not_loaded": "**Maintenance Supporter** ist nicht geladen. Installiere/aktiviere zuerst die Integration.",
"strat_group_by": "Ansichten gruppieren nach",
"strat_group_area": "Nach Bereich (Standard)",
"strat_group_status": "Nach Status (Überfällig / Ausgelöst / Bald fällig / OK)",
"strat_group_floor": "Nach Etage (nutzt die HA-Etagen)",
"strat_group_due_date": "Nach Fälligkeit (Überfällig / Heute / Diese Woche / Diesen Monat / Später)",
"strat_group_calendar": "Rollierender Kalender (Woche / Zwei Wochen / Monat / Jahr)",
"strat_editor_help": "Die Ansicht „Übersicht“ steht immer an erster Stelle. Leere Gruppen werden ausgelassen.",
"picker_name_calendar": "Maintenance Supporter — Kalender",
"picker_name_panel": "Maintenance Supporter — Panel als Karte",
"picker_name_budget": "Maintenance Supporter — Wartungsbudget",
"picker_name_groups": "Maintenance Supporter — Gruppen",
"picker_name_vacation": "Maintenance Supporter — Urlaubsmodus",
"picker_name_battery_fleet": "Batterie-Flotte",
"picker_name_section": "Maintenance Supporter — Abschnitt",
"picker_name_vacation_status": "Maintenance Supporter — Urlaubsstatus",
"picker_name_budget_status": "Maintenance Supporter — Budgetstatus",
"picker_desc_card": "Übersicht deiner Wartungsaufgaben mit Schnellaktionen.",
"picker_desc_calendar": "Rollierender Kalender der Wartungsaufgaben mit 7/14/30/365-Tage-Fenstern, Quellen-Icons und Badges zur Vorhersage-Genauigkeit.",
"picker_desc_panel": "Das komplette Maintenance-Supporter-Panel als Karte — für eine Panel-Ansicht / Dashboard-Unteransicht ohne Eintrag in der Seitenleiste.",
"picker_desc_budget": "Monats- und Jahresbudget direkt im Dashboard bearbeiten.",
"picker_desc_groups": "Aufgabengruppen direkt im Dashboard anlegen, umbenennen und löschen.",
"picker_desc_vacation": "Urlaubsmodus direkt im Dashboard ein- und ausschalten und den Zeitraum festlegen.",
"picker_desc_battery_fleet": "Alle überwachten Batterien: was jetzt schwach ist, was bald leer wird und was du kaufen musst.",
"picker_desc_dashboard": "Automatisch erzeugtes Dashboard. Ansichten nach Bereich, Status, Etage oder Fälligkeit gruppieren — wählbar im Strategie-Editor oder per YAML.",
"picker_desc_section": "Wartungsaufgaben (filterbar nach Bereich, Status, Fälligkeit) als Abschnitt in jede Dashboard-Ansicht einbetten.",
"picker_desc_vacation_status": "Kompaktes Status-Banner für den Urlaubsmodus. Antippen öffnet die Einstellungen im Panel.",
"picker_desc_budget_status": "Übersicht über Monats- und Jahresbudget für die Wartung. Antippen für Details.",
"picker_desc_groups_status": "Liste der eingerichteten Aufgabengruppen mit der Anzahl ihrer Aufgaben.",
"hist_note_button": "Über Dashboard-Button abgeschlossen",
"hist_note_todo": "Über die To-do-Liste abgeschlossen",
"hist_note_voice": "Per Sprachbefehl abgeschlossen",
"hist_note_notification": "Über die Benachrichtigung abgeschlossen",
"hist_note_nfc": "Per NFC-Tag abgeschlossen",
"hist_note_shopping_list": "Über die Einkaufsliste abgeschlossen",
"hist_note_todo_mirror": "Über eine gespiegelte To-do-Liste abgeschlossen",
"hist_note_skipped_notification": "Über die Benachrichtigung übersprungen",
"hist_note_skipped_button": "Über Dashboard-Button übersprungen",
"hist_note_sensor_triggered": "Sensor-Trigger ausgelöst",
"hist_note_initial": "Anfangswert bei der Aufgabenerstellung gesetzt",
"hist_note_auto_recovered": "Automatisch abgeschlossen: Sensor hat sich erholt ({value})",
"hist_note_reset": "Zurückgesetzt auf {date}",
"hist_note_trigger_replaced": "Trigger-Entität ersetzt: {old} → {new}",
"hist_note_trigger_removed": "Sensor-Trigger entfernt (Entität war: {entity}). Zeitplan umgestellt auf {schedule}.",
"hist_note_compound_removed": "Entität {entity} aus dem verknüpften Trigger entfernt; verbleibende Bedingungen: {count}.",
"recent_activities": "Letzte Aktivitäten",
"search_notes": "Notizen durchsuchen",
"avg_cost": "Ø Kosten",
@@ -703,6 +782,7 @@
"on_complete_action_desc": "Ruft beim Erledigen der Aufgabe einen HA-Service auf — z. B. einen Zähler am Gerät zurücksetzen.",
"on_complete_action_target": "Ziel-Entität",
"on_complete_action_target_hint": "Achtung: Domain der Entität muss zum Service passen — z. B. 'button.press' nur für button.*, 'counter.increment' nur für counter.*, 'input_button.press' nur für input_button.* etc. Bei Mismatch fired die Aktion nicht (HA loggt 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Nicht, wenn sich die Aufgabe selbst erledigt (ihr Sensor hat sich erholt)",
"on_complete_action_data": "Daten (JSON, optional)",
"on_complete_action_test": "Konfiguration prüfen",
"on_complete_action_test_success": "✓ Konfiguration gültig (Aktion wird erst beim Abschluss ausgeführt)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "„{name}“: Aufgaben {before} → {after}",
"adopt_problem_adopt": "Auswahl übernehmen",
"adopt_problem_done": "{tasks} Problem-Sensor(en) übernommen",
"adopt_problem_done_one": "1 Problem-Sensor übernommen",
"views_label": "Ansichten",
"views_none": "— Keine Ansicht —",
"views_manage": "Ansichten speichern/verwalten",
@@ -1013,6 +1094,7 @@
"setups_none": "Keine unterstützten Geräte mit unverdrahteten Verbrauchsmaterial-Sensoren gefunden.",
"setups_adopt": "Auswahl einrichten",
"setups_done": "{tasks} sensor-verdrahtete Aufgaben angelegt.",
"setups_done_one": "1 sensor-verdrahtete Aufgabe angelegt.",
"complete_parts_used": "Diesmal verwendete Teile",
"part_delete_confirm": "Ersatzteil '{name}' löschen? Bestandsverfolgung, Aufgaben-Verknüpfungen und eine offene Kauf-Erinnerung werden entfernt.",
"baseline_start_value": "Startwert (optional)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "gleiches Modell an einem anderen Gerät",
"setups_maybe_covered": "Wahrscheinlich schon vorhanden als „{name}“",
"setups_already": "Schon vorhanden: {names}",
"setups_reset_line": "Erledigen setzt auch den Zähler in der Integration zurück („{button}“)",
"setups_reset_enable": "— der Button wird dafür eingeschaltet",
"reset_offers_title": "Zähler beim Erledigen zurücksetzen",
"reset_offers_hint": "Diese Aufgaben beobachten einen Zähler, den die Integration selbst führt. Verbunden drückt das Erledigen hier auch den Reset-Button der Integration — sonst läuft der Zähler weiter und die Aufgabe ist sofort wieder fällig.",
"reset_offers_before": "Jetzt: Erledigen lässt den Zähler in {integration} weiterlaufen",
"reset_offers_after": "Dann: Erledigen drückt auch „{button}“",
"reset_offers_renamed": "Seit der Einrichtung umbenannt — prüfe, ob diese Aufgabe zu diesem Teil gehört",
"reset_offers_apply": "Reset-Buttons verbinden",
"reset_offers_done": "{count} Aufgaben setzen ihren Zähler jetzt beim Erledigen zurück",
"reset_offers_done_one": "1 Aufgabe setzt ihren Zähler jetzt beim Erledigen zurück",
"setups_before_after": "Aufgaben am Objekt: {before} → {after}",
"setups_new_object_count": "Neues Objekt „{name}“ · Aufgaben: {count}",
"schedule_preview_title": "Nächste Termine",
@@ -1046,6 +1138,7 @@
"history_auto": "Automatisch",
"battery_fleet_title": "Batterie-Flotte",
"battery_fleet_none_low": "Alle Batterien OK — nichts zu wechseln.",
"battery_fleet_progress": "{n} zu wechseln",
"battery_fleet_buy_now": "Jetzt kaufen",
"battery_fleet_soon": "Bald nötig",
"battery_fleet_soon_hint": "Aus dem letzten Wechseldatum geschätzt — vorab bestellen.",
@@ -1099,8 +1192,12 @@
"dismiss": "Ausblenden",
"gs_label": "Erste Schritte — diese Hinweise verschwinden, wenn dein Setup wächst",
"gs_setups_chip": "Vorgeschlagene Setups: {n} Geräte mit vorverdrahteten Auslösern gefunden",
"gs_setups_chip_one": "Vorgeschlagene Setups: 1 Gerät mit vorverdrahteten Auslösern gefunden",
"gs_adopt_chip": "{n} Problem-Sensoren können zu Wartungsaufgaben werden",
"gs_adopt_chip_one": "1 Problem-Sensor kann zu einer Wartungsaufgabe werden",
"gs_fleet_chip": "Ein Klick richtet die Batterieflotte ein",
"gs_reset_chip": "{n} Aufgaben können ihren Zähler in der Integration zurücksetzen",
"gs_reset_chip_one": "1 Aufgabe kann ihren Zähler in der Integration zurücksetzen",
"cal_editor_window": "Standard-Zeitfenster",
"cal_editor_window_week": "Woche (7 Tage)",
"cal_editor_window_fortnight": "Zwei Wochen (14 Tage)",
@@ -243,6 +243,26 @@
"sort_task_name": "Task name",
"all_objects": "All objects",
"all_parts": "All parts",
"all_areas": "All areas",
"areas_filter": "Filter areas…",
"areas_filter_none": "No area matches the filter.",
"area_cost_year": "Cost {year}",
"area_object_count": "{n} objects",
"area_object_count_one": "1 object",
"area_range_12m": "Last 12 months",
"area_range_all": "All time",
"area_task_filter": "Filter by task…",
"area_kpi_completions": "Completions",
"area_kpi_total_time": "Total time",
"area_cost_per_month": "Cost per month",
"area_cost_per_year": "Cost per year",
"area_cost_per_object": "Cost per object",
"area_cost_share": "Share",
"area_history_section": "History (all objects)",
"area_report_print": "Area report (PDF)",
"area_report_title": "Area report",
"area_report_period": "Period",
"area_no_costs": "No costs recorded in this period.",
"no_tasks_yet": "No tasks yet",
"add_first_task": "Add first task",
"trigger_configuration": "Trigger Configuration",
@@ -401,11 +421,70 @@
"qr_download": "Download SVG",
"qr_action_view": "View maintenance info",
"qr_action_complete": "Mark maintenance as complete",
"qr_action_quick_complete": "Quick-complete — no dialog",
"qr_print_quick_none": "Quick-complete codes need quick-complete defaults on a task (task dialog → Quick-complete defaults) — none of the chosen objects' tasks has them yet.",
"qr_url_mode": "Link type",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Local (mDNS)",
"qr_mode_server": "Server URL",
"overview": "Overview",
"strat_this_month": "This Month",
"strat_later": "Later",
"strat_week": "Week",
"strat_fortnight": "Fortnight",
"strat_month": "Month",
"strat_year": "Year",
"strat_other": "Other",
"strat_status": "Status",
"strat_empty_title": "No maintenance objects yet",
"strat_empty_content": "Open the Maintenance panel to add your first object — pool pump, HVAC filter, vehicle, anything that needs scheduled care.",
"strat_open_panel": "Open Maintenance panel",
"strat_add_object": "Add object",
"strat_not_loaded": "**Maintenance Supporter** is not loaded. Install/enable the integration first.",
"strat_group_by": "Group views by",
"strat_group_area": "By area (default)",
"strat_group_status": "By status (Overdue / Triggered / Due Soon / OK)",
"strat_group_floor": "By floor (uses HA floors)",
"strat_group_due_date": "By due date (Overdue / Today / Week / Month / Later)",
"strat_group_calendar": "Rolling calendar (Week / Fortnight / Month / Year)",
"strat_editor_help": "The \"Overview\" view is always first. Empty groups are skipped.",
"picker_name_calendar": "Maintenance Supporter — Calendar",
"picker_name_panel": "Maintenance Supporter — Panel",
"picker_name_budget": "Maintenance Supporter — Budget",
"picker_name_groups": "Maintenance Supporter — Groups",
"picker_name_vacation": "Maintenance Supporter — Vacation",
"picker_name_battery_fleet": "Battery Fleet",
"picker_name_section": "Maintenance Supporter — Section",
"picker_name_vacation_status": "Maintenance Supporter — Vacation Status",
"picker_name_budget_status": "Maintenance Supporter — Budget Status",
"picker_desc_card": "Overview of your maintenance tasks with quick actions.",
"picker_desc_calendar": "Rolling calendar of maintenance tasks with 7/14/30/365 day windows, source icons, and prediction-confidence pills.",
"picker_desc_panel": "The complete Maintenance Supporter panel as a card — for a panel view / dashboard subview without the sidebar entry.",
"picker_desc_budget": "Edit the monthly and yearly budget right on the dashboard.",
"picker_desc_groups": "Create, rename and delete task groups right on the dashboard.",
"picker_desc_vacation": "Switch vacation mode on or off and set its dates right on the dashboard.",
"picker_desc_battery_fleet": "All tracked batteries: what is low now, what runs out soon, and what to buy.",
"picker_desc_dashboard": "Auto-generated dashboard. Group views by area, status, floor, or due date — picked from the strategy editor or YAML.",
"picker_desc_section": "Embed maintenance tasks (filterable by area, status, due date) as a section in any dashboard view.",
"picker_desc_vacation_status": "Compact vacation-mode status banner. Tap to open settings in the panel.",
"picker_desc_budget_status": "Monthly + yearly maintenance budget overview. Tap for details.",
"picker_desc_groups_status": "List of configured task groups with member counts.",
"hist_note_button": "Completed from dashboard button",
"hist_note_todo": "Completed from the To-do list",
"hist_note_voice": "Completed by voice",
"hist_note_notification": "Completed from the notification",
"hist_note_nfc": "Completed via NFC tag",
"hist_note_shopping_list": "Completed from the shopping list",
"hist_note_todo_mirror": "Completed from a mirrored to-do list",
"hist_note_skipped_notification": "Skipped from notification",
"hist_note_skipped_button": "Skipped from dashboard button",
"hist_note_sensor_triggered": "Sensor trigger activated",
"hist_note_initial": "Initial value set during task creation",
"hist_note_auto_recovered": "Auto-completed: sensor recovered ({value})",
"hist_note_reset": "Reset to {date}",
"hist_note_trigger_replaced": "Trigger entity replaced: {old} → {new}",
"hist_note_trigger_removed": "Sensor trigger removed (entity was: {entity}). Schedule converted to {schedule}.",
"hist_note_compound_removed": "Entity {entity} removed from compound trigger; {count} conditions remain.",
"recent_activities": "Recent Activities",
"search_notes": "Search notes",
"avg_cost": "Avg Cost",
@@ -709,6 +788,7 @@
"on_complete_action_desc": "Calls an HA service when the task is completed — e.g. reset a counter on the device.",
"on_complete_action_target": "Target entity",
"on_complete_action_target_hint": "Note: the entity domain must match the service — e.g. 'button.press' only works on button.*, 'counter.increment' only on counter.*, 'input_button.press' only on input_button.* etc. On a mismatch the action will silently fail (HA logs 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Not when the task completes itself (its sensor recovered)",
"on_complete_action_data": "Data (JSON, optional)",
"on_complete_action_test": "Validate configuration",
"on_complete_action_test_success": "✓ Configuration valid (action will fire only on task completion)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "\"{name}\": tasks {before} → {after}",
"adopt_problem_adopt": "Adopt selected",
"adopt_problem_done": "Adopted {tasks} problem sensor(s)",
"adopt_problem_done_one": "Adopted 1 problem sensor",
"views_label": "Views",
"views_none": "— No view —",
"views_manage": "Save / manage views",
@@ -1013,6 +1094,7 @@
"setups_none": "No supported devices with unwired consumable sensors found.",
"setups_adopt": "Set up selected",
"setups_done": "{tasks} sensor-wired tasks created.",
"setups_done_one": "1 sensor-wired task created.",
"complete_parts_used": "Parts used this time",
"part_delete_confirm": "Delete part '{name}'? Its stock tracking, task links and any open buy reminder will be removed.",
"baseline_start_value": "Start reading (optional)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "same model on another device",
"setups_maybe_covered": "Probably there already as \"{name}\"",
"setups_already": "Already there: {names}",
"setups_reset_line": "Completing it also resets the counter in the integration (“{button}”)",
"setups_reset_enable": "— the button gets switched on for this",
"reset_offers_title": "Reset counters on completion",
"reset_offers_hint": "These tasks watch a counter the integration keeps itself. Connected, completing the task here also presses the integration's reset button — otherwise the counter keeps running and the task falls due again right away.",
"reset_offers_before": "Now: completing it leaves the counter in {integration} running",
"reset_offers_after": "Then: it also presses “{button}”",
"reset_offers_renamed": "Renamed since it was set up — check that this task is for this part",
"reset_offers_apply": "Connect resets",
"reset_offers_done": "{count} tasks now reset their counter on completion",
"reset_offers_done_one": "1 task now resets its counter on completion",
"setups_before_after": "Tasks on the object: {before} → {after}",
"setups_new_object_count": "New object \"{name}\" · tasks: {count}",
"schedule_preview_title": "Next dates",
@@ -1046,6 +1138,7 @@
"history_auto": "Automatic",
"battery_fleet_title": "Battery fleet",
"battery_fleet_none_low": "All batteries OK — nothing to replace.",
"battery_fleet_progress": "{n} to replace",
"battery_fleet_buy_now": "Buy now",
"battery_fleet_soon": "Needed soon",
"battery_fleet_soon_hint": "Predicted from the last replacement date — order ahead.",
@@ -1099,8 +1192,12 @@
"dismiss": "Dismiss",
"gs_label": "Getting started — these hints retire as your setup grows",
"gs_setups_chip": "Suggested setups found {n} devices with pre-wired triggers",
"gs_setups_chip_one": "Suggested setups found 1 device with pre-wired triggers",
"gs_adopt_chip": "{n} problem sensors can become maintenance tasks",
"gs_adopt_chip_one": "1 problem sensor can become a maintenance task",
"gs_fleet_chip": "One click sets up the battery fleet",
"gs_reset_chip": "{n} tasks can reset their counter in the integration",
"gs_reset_chip_one": "1 task can reset its counter in the integration",
"cal_editor_window": "Default window",
"cal_editor_window_week": "Week (7 days)",
"cal_editor_window_fortnight": "Fortnight (14 days)",
@@ -241,6 +241,26 @@
"sort_task_name": "Nombre de la tarea",
"all_objects": "Todos los objetos",
"all_parts": "Todas las piezas",
"all_areas": "Todas las áreas",
"areas_filter": "Filtrar áreas…",
"areas_filter_none": "Ningún área coincide con el filtro.",
"area_cost_year": "Coste {year}",
"area_object_count": "{n} objetos",
"area_object_count_one": "1 objeto",
"area_range_12m": "Últimos 12 meses",
"area_range_all": "Todo el periodo",
"area_task_filter": "Filtrar por tarea…",
"area_kpi_completions": "Realizaciones",
"area_kpi_total_time": "Tiempo total",
"area_cost_per_month": "Coste por mes",
"area_cost_per_year": "Coste por año",
"area_cost_per_object": "Coste por objeto",
"area_cost_share": "Proporción",
"area_history_section": "Historial (todos los objetos)",
"area_report_print": "Informe del área (PDF)",
"area_report_title": "Informe del área",
"area_report_period": "Periodo",
"area_no_costs": "No hay costes registrados en este periodo.",
"no_tasks_yet": "Aún no hay tareas",
"add_first_task": "Agregar primera tarea",
"trigger_configuration": "Configuración del disparador",
@@ -399,11 +419,70 @@
"qr_download": "Descargar SVG",
"qr_action_view": "Ver info de mantenimiento",
"qr_action_complete": "Marcar mantenimiento como completado",
"qr_action_quick_complete": "Finalización rápida — sin diálogo",
"qr_print_quick_none": "Los códigos de finalización rápida necesitan valores predeterminados de finalización rápida en una tarea (diálogo de la tarea → Valores predeterminados de finalización rápida); ninguna tarea de los objetos elegidos los tiene todavía.",
"qr_url_mode": "Tipo de enlace",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Local (mDNS)",
"qr_mode_server": "URL del servidor",
"overview": "Resumen",
"strat_this_month": "Este mes",
"strat_later": "Más adelante",
"strat_week": "Semana",
"strat_fortnight": "Quincena",
"strat_month": "Mes",
"strat_year": "Año",
"strat_other": "Otros",
"strat_status": "Estado",
"strat_empty_title": "Aún no hay objetos de mantenimiento",
"strat_empty_content": "Abre el panel de Mantenimiento para añadir tu primer objeto — bomba de piscina, filtro de climatización, vehículo, cualquier cosa que necesite un cuidado programado.",
"strat_open_panel": "Abrir el panel de Mantenimiento",
"strat_add_object": "Añadir objeto",
"strat_not_loaded": "**Maintenance Supporter** no está cargado. Instala/activa primero la integración.",
"strat_group_by": "Agrupar vistas por",
"strat_group_area": "Por área (predeterminado)",
"strat_group_status": "Por estado (Vencida / Activada / Próxima / OK)",
"strat_group_floor": "Por planta (usa las plantas de HA)",
"strat_group_due_date": "Por vencimiento (Vencida / Hoy / Esta semana / Este mes / Más adelante)",
"strat_group_calendar": "Calendario móvil (Semana / Quincena / Mes / Año)",
"strat_editor_help": "La vista «Resumen» siempre va primero. Los grupos vacíos se omiten.",
"picker_name_calendar": "Maintenance Supporter — Calendario",
"picker_name_panel": "Maintenance Supporter — Panel como tarjeta",
"picker_name_budget": "Maintenance Supporter — Presupuesto de mantenimiento",
"picker_name_groups": "Maintenance Supporter — Grupos",
"picker_name_vacation": "Maintenance Supporter — Modo vacaciones",
"picker_name_battery_fleet": "Flota de baterías",
"picker_name_section": "Maintenance Supporter — Sección",
"picker_name_vacation_status": "Maintenance Supporter — Estado de vacaciones",
"picker_name_budget_status": "Maintenance Supporter — Estado del presupuesto",
"picker_desc_card": "Resumen de tus tareas de mantenimiento con acciones rápidas.",
"picker_desc_calendar": "Calendario móvil de tareas de mantenimiento con ventanas de 7/14/30/365 días, iconos de origen y etiquetas de confianza de la predicción.",
"picker_desc_panel": "El panel completo de Maintenance Supporter como tarjeta — para una vista de tipo panel o una subvista, sin entrada en la barra lateral.",
"picker_desc_budget": "Edita el presupuesto mensual y anual directamente en el panel.",
"picker_desc_groups": "Crea, renombra y elimina grupos de tareas directamente en el panel.",
"picker_desc_vacation": "Activa o desactiva el modo vacaciones y define sus fechas directamente en el panel.",
"picker_desc_battery_fleet": "Todas las pilas monitorizadas: cuáles están bajas ahora, cuáles se agotarán pronto y qué comprar.",
"picker_desc_dashboard": "Panel generado automáticamente. Agrupa las vistas por área, estado, planta o vencimiento — se elige en el editor de la estrategia o en YAML.",
"picker_desc_section": "Inserta las tareas de mantenimiento (filtrables por área, estado y vencimiento) como sección en cualquier vista del panel.",
"picker_desc_vacation_status": "Banner compacto con el estado del modo vacaciones. Toca para abrir los ajustes en el panel.",
"picker_desc_budget_status": "Resumen del presupuesto de mantenimiento mensual y anual. Toca para ver detalles.",
"picker_desc_groups_status": "Lista de los grupos de tareas configurados con el número de tareas de cada uno.",
"hist_note_button": "Completada desde un botón del panel",
"hist_note_todo": "Completada desde la lista de tareas",
"hist_note_voice": "Completada por voz",
"hist_note_notification": "Completada desde la notificación",
"hist_note_nfc": "Completada con una etiqueta NFC",
"hist_note_shopping_list": "Completada desde la lista de la compra",
"hist_note_todo_mirror": "Completada desde una lista de tareas reflejada",
"hist_note_skipped_notification": "Omitida desde la notificación",
"hist_note_skipped_button": "Omitida desde un botón del panel",
"hist_note_sensor_triggered": "Disparador de sensor activado",
"hist_note_initial": "Valor inicial establecido al crear la tarea",
"hist_note_auto_recovered": "Completada automáticamente: el sensor se recuperó ({value})",
"hist_note_reset": "Restablecida al {date}",
"hist_note_trigger_replaced": "Entidad disparadora reemplazada: {old} → {new}",
"hist_note_trigger_removed": "Disparador de sensor eliminado (entidad: {entity}). Programación convertida a {schedule}.",
"hist_note_compound_removed": "Entidad {entity} eliminada del disparador compuesto; condiciones restantes: {count}.",
"recent_activities": "Actividades recientes",
"search_notes": "Buscar en notas",
"avg_cost": "Ø Coste",
@@ -716,6 +795,7 @@
"groups_manage_tasks": "Gestionar asignaciones de tareas…",
"groups_open_panel": "Abrir en el panel",
"on_complete_action_target_hint": "Nota: el dominio de la entidad debe coincidir con el servicio — p. ej. 'button.press' solo funciona en button.*, 'counter.increment' solo en counter.*, 'input_button.press' solo en input_button.* etc. Si no coinciden, la acción falla silenciosamente (HA registra 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "No cuando la tarea se completa sola (su sensor se recuperó)",
"show_all_objects": "Mostrar todos los objetos",
"show_all_tasks": "Quitar filtro — mostrar todas las tareas",
"filter_to_overdue": "Filtrar la lista solo a vencidas",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "«{name}»: tareas {before} → {after}",
"adopt_problem_adopt": "Adoptar seleccionados",
"adopt_problem_done": "{tasks} sensor(es) de problema adoptado(s)",
"adopt_problem_done_one": "1 sensor de problema adoptado",
"views_label": "Vistas",
"views_none": "— Sin vista —",
"views_manage": "Guardar / gestionar vistas",
@@ -1013,6 +1094,7 @@
"setups_none": "No se encontraron dispositivos compatibles con sensores de consumibles sin conectar.",
"setups_adopt": "Configurar selección",
"setups_done": "{tasks} tareas conectadas a sensores creadas.",
"setups_done_one": "1 tarea conectada a sensores creada.",
"complete_parts_used": "Piezas usadas esta vez",
"part_delete_confirm": "¿Eliminar la pieza '{name}'? Se eliminarán su control de stock, los vínculos con tareas y cualquier recordatorio de compra abierto.",
"baseline_start_value": "Valor inicial (opcional)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "mismo modelo en otro dispositivo",
"setups_maybe_covered": "Probablemente ya existe como «{name}»",
"setups_already": "Ya existe: {names}",
"setups_reset_line": "Completarla también reinicia el contador en la integración («{button}»)",
"setups_reset_enable": "— para ello se activará el botón",
"reset_offers_title": "Reiniciar contadores al completar",
"reset_offers_hint": "Estas tareas vigilan un contador que lleva la propia integración. Una vez conectadas, completar la tarea aquí también pulsa el botón de reinicio de la integración — si no, el contador sigue corriendo y la tarea vuelve a vencer enseguida.",
"reset_offers_before": "Ahora: completarla deja en marcha el contador de {integration}",
"reset_offers_after": "Después: también pulsa «{button}»",
"reset_offers_renamed": "Renombrada desde su configuración — comprueba que esta tarea corresponde a esta pieza",
"reset_offers_apply": "Conectar reinicios",
"reset_offers_done": "{count} tareas reinician ahora su contador al completarse",
"reset_offers_done_one": "1 tarea reinicia ahora su contador al completarse",
"setups_before_after": "Tareas del objeto: {before} → {after}",
"setups_new_object_count": "Objeto nuevo «{name}» · tareas: {count}",
"schedule_preview_title": "Próximas fechas",
@@ -1046,6 +1138,7 @@
"history_auto": "Automático",
"battery_fleet_title": "Flota de baterías",
"battery_fleet_none_low": "Todas las baterías OK — nada que reemplazar.",
"battery_fleet_progress": "{n} por cambiar",
"battery_fleet_buy_now": "Comprar ahora",
"battery_fleet_soon": "Pronto necesario",
"battery_fleet_soon_hint": "Estimado según el último reemplazo — pide con antelación.",
@@ -1099,8 +1192,12 @@
"dismiss": "Descartar",
"gs_label": "Primeros pasos: estas sugerencias desaparecen a medida que crece tu configuración",
"gs_setups_chip": "Configuraciones sugeridas: {n} dispositivos con disparadores preconfigurados",
"gs_setups_chip_one": "Configuraciones sugeridas: 1 dispositivo con disparadores preconfigurados",
"gs_adopt_chip": "{n} sensores de problemas pueden convertirse en tareas de mantenimiento",
"gs_adopt_chip_one": "1 sensor de problemas puede convertirse en una tarea de mantenimiento",
"gs_fleet_chip": "Un clic configura la flota de baterías",
"gs_reset_chip": "{n} tareas pueden reiniciar su contador en la integración",
"gs_reset_chip_one": "1 tarea puede reiniciar su contador en la integración",
"cal_editor_window": "Ventana predeterminada",
"cal_editor_window_week": "Semana (7 días)",
"cal_editor_window_fortnight": "Quincena (14 días)",
@@ -243,6 +243,26 @@
"sort_task_name": "Tehtävän nimi",
"all_objects": "Kaikki kohteet",
"all_parts": "Kaikki osat",
"all_areas": "Kaikki alueet",
"areas_filter": "Suodata alueita…",
"areas_filter_none": "Mikään alue ei vastaa suodatinta.",
"area_cost_year": "Kustannus {year}",
"area_object_count": "{n} kohdetta",
"area_object_count_one": "1 kohde",
"area_range_12m": "Viimeiset 12 kuukautta",
"area_range_all": "Koko ajalta",
"area_task_filter": "Suodata tehtävän mukaan…",
"area_kpi_completions": "Suoritukset",
"area_kpi_total_time": "Kokonaisaika",
"area_cost_per_month": "Kustannus kuukausittain",
"area_cost_per_year": "Kustannus vuosittain",
"area_cost_per_object": "Kustannus kohteittain",
"area_cost_share": "Osuus",
"area_history_section": "Historia (kaikki kohteet)",
"area_report_print": "Alueraportti (PDF)",
"area_report_title": "Alueraportti",
"area_report_period": "Ajanjakso",
"area_no_costs": "Tällä aikavälillä ei ole kirjattu kustannuksia.",
"no_tasks_yet": "Ei vielä tehtäviä",
"add_first_task": "Lisää ensimmäinen tehtävä",
"trigger_configuration": "Laukaisimen asetukset",
@@ -401,11 +421,70 @@
"qr_download": "Lataa SVG",
"qr_action_view": "Näytä huoltotiedot",
"qr_action_complete": "Merkitse huolto valmiiksi",
"qr_action_quick_complete": "Pikasuoritus — ilman valintaikkunaa",
"qr_print_quick_none": "Pikasuorituskoodit vaativat tehtävälle pikasuorituksen oletukset (tehtävän valintaikkuna → Pikasuorituksen oletukset) — minkään valitun kohteen tehtävällä ei ole niitä vielä.",
"qr_url_mode": "Linkin tyyppi",
"qr_mode_companion": "Companion-sovellus",
"qr_mode_local": "Paikallinen (mDNS)",
"qr_mode_server": "Palvelimen URL",
"overview": "Yleiskatsaus",
"strat_this_month": "Tässä kuussa",
"strat_later": "Myöhemmin",
"strat_week": "Viikko",
"strat_fortnight": "Kaksi viikkoa",
"strat_month": "Kuukausi",
"strat_year": "Vuosi",
"strat_other": "Muut",
"strat_status": "Tila",
"strat_empty_title": "Ei vielä huoltokohteita",
"strat_empty_content": "Avaa Huolto-paneeli ja lisää ensimmäinen kohde — uima-altaan pumppu, ilmanvaihdon suodatin, ajoneuvo, mikä tahansa, joka tarvitsee säännöllistä huoltoa.",
"strat_open_panel": "Avaa Huolto-paneeli",
"strat_add_object": "Lisää kohde",
"strat_not_loaded": "**Maintenance Supporter** ei ole ladattuna. Asenna integraatio tai ota se ensin käyttöön.",
"strat_group_by": "Ryhmittele näkymät",
"strat_group_area": "Alueen mukaan (oletus)",
"strat_group_status": "Tilan mukaan (Myöhässä / Laukaistu / Pian erääntyy / OK)",
"strat_group_floor": "Kerroksen mukaan (käyttää HA:n kerroksia)",
"strat_group_due_date": "Eräpäivän mukaan (Myöhässä / Tänään / Tällä viikolla / Tässä kuussa / Myöhemmin)",
"strat_group_calendar": "Liukuva kalenteri (Viikko / Kaksi viikkoa / Kuukausi / Vuosi)",
"strat_editor_help": "”Yleiskatsaus”-näkymä on aina ensimmäisenä. Tyhjät ryhmät ohitetaan.",
"picker_name_calendar": "Maintenance Supporter — Kalenteri",
"picker_name_panel": "Maintenance Supporter — Paneeli korttina",
"picker_name_budget": "Maintenance Supporter — Huoltobudjetti",
"picker_name_groups": "Maintenance Supporter — Ryhmät",
"picker_name_vacation": "Maintenance Supporter — Lomatila",
"picker_name_battery_fleet": "Paristokanta",
"picker_name_section": "Maintenance Supporter — Osio",
"picker_name_vacation_status": "Maintenance Supporter — Loman tila",
"picker_name_budget_status": "Maintenance Supporter — Budjetin tila",
"picker_desc_card": "Yleiskatsaus huoltotehtäviisi pikatoiminnoilla.",
"picker_desc_calendar": "Huoltotehtävien liukuva kalenteri 7/14/30/365 päivän jaksoilla, lähdekuvakkeilla ja ennusteen luotettavuusmerkeillä.",
"picker_desc_panel": "Koko Maintenance Supporter -paneeli korttina — paneelinäkymään tai kojelaudan alinäkymään ilman sivupalkin kohtaa.",
"picker_desc_budget": "Muokkaa kuukausi- ja vuosibudjettia suoraan kojelaudalla.",
"picker_desc_groups": "Luo, nimeä uudelleen ja poista tehtäväryhmiä suoraan kojelaudalla.",
"picker_desc_vacation": "Ota lomatila käyttöön tai poista se käytöstä ja aseta sen päivät suoraan kojelaudalla.",
"picker_desc_battery_fleet": "Kaikki seuratut paristot: mitkä ovat nyt vähissä, mitkä loppuvat pian ja mitä pitää ostaa.",
"picker_desc_dashboard": "Automaattisesti luotu kojelauta. Ryhmittele näkymät alueen, tilan, kerroksen tai eräpäivän mukaan — valitaan strategiaeditorissa tai YAML:ssä.",
"picker_desc_section": "Upota huoltotehtävät (suodatettavissa alueen, tilan ja eräpäivän mukaan) osioksi mihin tahansa kojelaudan näkymään.",
"picker_desc_vacation_status": "Kompakti lomatilan tilabanneri. Napauta avataksesi asetukset paneelissa.",
"picker_desc_budget_status": "Kuukausi- ja vuosibudjetin yleiskatsaus huollolle. Napauta nähdäksesi tiedot.",
"picker_desc_groups_status": "Luettelo määritetyistä tehtäväryhmistä ja niiden tehtävien määrästä.",
"hist_note_button": "Suoritettu kojelaudan painikkeella",
"hist_note_todo": "Suoritettu tehtävälistasta",
"hist_note_voice": "Suoritettu puheella",
"hist_note_notification": "Suoritettu ilmoituksesta",
"hist_note_nfc": "Suoritettu NFC-tunnisteella",
"hist_note_shopping_list": "Suoritettu ostoslistasta",
"hist_note_todo_mirror": "Suoritettu peilatusta tehtävälistasta",
"hist_note_skipped_notification": "Ohitettu ilmoituksesta",
"hist_note_skipped_button": "Ohitettu kojelaudan painikkeella",
"hist_note_sensor_triggered": "Anturin laukaisin aktivoitui",
"hist_note_initial": "Alkuarvo asetettu tehtävän luonnissa",
"hist_note_auto_recovered": "Suoritettu automaattisesti: anturi palautui ({value})",
"hist_note_reset": "Nollattu päivään {date}",
"hist_note_trigger_replaced": "Laukaisimen entiteetti korvattu: {old} → {new}",
"hist_note_trigger_removed": "Anturin laukaisin poistettu (entiteetti: {entity}). Aikataulu muutettu: {schedule}.",
"hist_note_compound_removed": "Entiteetti {entity} poistettu yhdistetystä laukaisimesta; ehtoja jäljellä: {count}.",
"recent_activities": "Viimeaikaiset toimet",
"search_notes": "Hae muistiinpanoja",
"avg_cost": "Keskim. kustannus",
@@ -703,6 +782,7 @@
"on_complete_action_desc": "Kutsuu HA-palvelua, kun tehtävä suoritetaan — esim. nollaa laitteen laskuri.",
"on_complete_action_target": "Kohde-entiteetti",
"on_complete_action_target_hint": "Huom: entiteetin toimialueen on vastattava palvelua — esim. 'button.press' toimii vain button.*-entiteeteillä, 'counter.increment' vain counter.*-entiteeteillä, 'input_button.press' vain input_button.*-entiteeteillä jne. Epäsopivuuden sattuessa toiminto epäonnistuu hiljaisesti (HA kirjaa 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Ei, kun tehtävä suorittuu itsestään (sen anturi palautui)",
"on_complete_action_data": "Tiedot (JSON, valinnainen)",
"on_complete_action_test": "Tarkista asetukset",
"on_complete_action_test_success": "✓ Asetukset kelvolliset (toiminto laukeaa vain tehtävän suorituksen yhteydessä)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "\"{name}\": tehtävät {before} → {after}",
"adopt_problem_adopt": "Ota valitut käyttöön",
"adopt_problem_done": "Otettiin käyttöön {tasks} ongelma-anturia",
"adopt_problem_done_one": "Otettiin käyttöön 1 ongelma-anturi",
"views_label": "Näkymät",
"views_none": "— Ei näkymää —",
"views_manage": "Tallenna / hallitse näkymiä",
@@ -1013,6 +1094,7 @@
"setups_none": "Tuettuja laitteita, joissa on kytkemättömiä kulutusosa-antureita, ei löytynyt.",
"setups_adopt": "Ota valitut käyttöön",
"setups_done": "{tasks} anturiin kytkettyä tehtävää luotu.",
"setups_done_one": "1 anturiin kytketty tehtävä luotu.",
"complete_parts_used": "Tällä kertaa käytetyt osat",
"part_delete_confirm": "Poistetaanko osa '{name}'? Varastoseuranta, tehtäväkytkennät ja avoin ostomuistutus poistetaan.",
"baseline_start_value": "Aloitusarvo (valinnainen)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "sama malli toisessa laitteessa",
"setups_maybe_covered": "Todennäköisesti jo olemassa nimellä \"{name}\"",
"setups_already": "Jo olemassa: {names}",
"setups_reset_line": "Suoritus nollaa myös integraation laskurin (”{button}”)",
"setups_reset_enable": "— painike otetaan tätä varten käyttöön",
"reset_offers_title": "Nollaa laskurit suorituksen yhteydessä",
"reset_offers_hint": "Nämä tehtävät seuraavat laskuria, jota integraatio ylläpitää itse. Yhdistettynä tehtävän suorittaminen täällä painaa myös integraation nollauspainiketta — muuten laskuri jatkaa kulkuaan ja tehtävä erääntyy heti uudelleen.",
"reset_offers_before": "Nyt: suorituksen jälkeen {integration}-integraation laskuri jatkaa kulkuaan",
"reset_offers_after": "Sitten: painaa myös painiketta ”{button}”",
"reset_offers_renamed": "Nimetty uudelleen määrityksen jälkeen — tarkista, että tehtävä koskee tätä osaa",
"reset_offers_apply": "Yhdistä nollaukset",
"reset_offers_done": "{count} tehtävää nollaa nyt laskurinsa suorituksen yhteydessä",
"reset_offers_done_one": "1 tehtävä nollaa nyt laskurinsa suorituksen yhteydessä",
"setups_before_after": "Kohteen tehtävät: {before} → {after}",
"setups_new_object_count": "Uusi kohde \"{name}\" · tehtäviä: {count}",
"schedule_preview_title": "Seuraavat päivämäärät",
@@ -1046,6 +1138,7 @@
"history_auto": "Automaattinen",
"battery_fleet_title": "Paristokanta",
"battery_fleet_none_low": "Kaikki paristot OK — ei vaihdettavaa.",
"battery_fleet_progress": "Vaihdettavia: {n}",
"battery_fleet_buy_now": "Osta nyt",
"battery_fleet_soon": "Pian tarpeen",
"battery_fleet_soon_hint": "Arvioitu viime vaihdosta — tilaa etukäteen.",
@@ -1099,8 +1192,12 @@
"dismiss": "Hylkää",
"gs_label": "Aloitus — nämä vihjeet poistuvat asennuksen kasvaessa",
"gs_setups_chip": "Ehdotetut asetukset löysivät {n} laitetta valmiilla laukaisimilla",
"gs_setups_chip_one": "Ehdotetut asetukset löysivät 1 laitteen valmiilla laukaisimilla",
"gs_adopt_chip": "{n} ongelma-anturia voi muuttua huoltotehtäviksi",
"gs_adopt_chip_one": "1 ongelma-anturi voi muuttua huoltotehtäväksi",
"gs_fleet_chip": "Yksi napsautus määrittää akkukannan",
"gs_reset_chip": "{n} tehtävää voi nollata laskurinsa integraatiossa",
"gs_reset_chip_one": "1 tehtävä voi nollata laskurinsa integraatiossa",
"cal_editor_window": "Oletusikkuna",
"cal_editor_window_week": "Viikko (7 päivää)",
"cal_editor_window_fortnight": "Kaksi viikkoa (14 päivää)",
@@ -241,6 +241,26 @@
"sort_task_name": "Nom de la tâche",
"all_objects": "Tous les objets",
"all_parts": "Toutes les pièces",
"all_areas": "Toutes les zones",
"areas_filter": "Filtrer les zones…",
"areas_filter_none": "Aucune zone ne correspond au filtre.",
"area_cost_year": "Coût {year}",
"area_object_count": "{n} objets",
"area_object_count_one": "1 objet",
"area_range_12m": "12 derniers mois",
"area_range_all": "Toute la période",
"area_task_filter": "Filtrer par tâche…",
"area_kpi_completions": "Réalisations",
"area_kpi_total_time": "Temps total",
"area_cost_per_month": "Coût par mois",
"area_cost_per_year": "Coût par an",
"area_cost_per_object": "Coût par objet",
"area_cost_share": "Part",
"area_history_section": "Historique (tous les objets)",
"area_report_print": "Rapport de zone (PDF)",
"area_report_title": "Rapport de zone",
"area_report_period": "Période",
"area_no_costs": "Aucun coût enregistré sur cette période.",
"no_tasks_yet": "Pas encore de tâches",
"add_first_task": "Ajouter la première tâche",
"trigger_configuration": "Configuration du déclencheur",
@@ -399,11 +419,70 @@
"qr_download": "Télécharger SVG",
"qr_action_view": "Afficher les infos de maintenance",
"qr_action_complete": "Marquer la maintenance comme terminée",
"qr_action_quick_complete": "Finalisation rapide — sans fenêtre",
"qr_print_quick_none": "Les codes de finalisation rapide nécessitent des valeurs par défaut de finalisation rapide sur une tâche (fenêtre de la tâche → Valeurs par défaut pour finalisation rapide) — aucune tâche des objets choisis n'en a encore.",
"qr_url_mode": "Type de lien",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Local (mDNS)",
"qr_mode_server": "URL serveur",
"overview": "Aperçu",
"strat_this_month": "Ce mois-ci",
"strat_later": "Plus tard",
"strat_week": "Semaine",
"strat_fortnight": "Quinzaine",
"strat_month": "Mois",
"strat_year": "Année",
"strat_other": "Autres",
"strat_status": "Statut",
"strat_empty_title": "Aucun objet de maintenance pour l'instant",
"strat_empty_content": "Ouvrez le panneau Maintenance pour ajouter votre premier objet — pompe de piscine, filtre de climatisation, véhicule, tout ce qui demande un entretien planifié.",
"strat_open_panel": "Ouvrir le panneau Maintenance",
"strat_add_object": "Ajouter un objet",
"strat_not_loaded": "**Maintenance Supporter** n'est pas chargé. Installez/activez d'abord l'intégration.",
"strat_group_by": "Regrouper les vues par",
"strat_group_area": "Par zone (par défaut)",
"strat_group_status": "Par statut (En retard / Déclenché / Bientôt dû / OK)",
"strat_group_floor": "Par étage (utilise les étages de HA)",
"strat_group_due_date": "Par échéance (En retard / Aujourd'hui / Cette semaine / Ce mois-ci / Plus tard)",
"strat_group_calendar": "Calendrier glissant (Semaine / Quinzaine / Mois / Année)",
"strat_editor_help": "La vue « Aperçu » est toujours la première. Les groupes vides sont ignorés.",
"picker_name_calendar": "Maintenance Supporter — Calendrier",
"picker_name_panel": "Maintenance Supporter — Panneau en carte",
"picker_name_budget": "Maintenance Supporter — Budget de maintenance",
"picker_name_groups": "Maintenance Supporter — Groupes",
"picker_name_vacation": "Maintenance Supporter — Mode vacances",
"picker_name_battery_fleet": "Parc de piles",
"picker_name_section": "Maintenance Supporter — Section de tâches",
"picker_name_vacation_status": "Maintenance Supporter — État du mode vacances",
"picker_name_budget_status": "Maintenance Supporter — État du budget",
"picker_desc_card": "Aperçu de vos tâches de maintenance avec actions rapides.",
"picker_desc_calendar": "Calendrier glissant des tâches de maintenance avec fenêtres de 7/14/30/365 jours, icônes de source et pastilles de confiance des prévisions.",
"picker_desc_panel": "Le panneau Maintenance Supporter complet sous forme de carte — pour une vue panneau / sous-vue de tableau de bord sans entrée dans la barre latérale.",
"picker_desc_budget": "Modifiez le budget mensuel et annuel directement sur le tableau de bord.",
"picker_desc_groups": "Créez, renommez et supprimez des groupes de tâches directement sur le tableau de bord.",
"picker_desc_vacation": "Activez ou désactivez le mode vacances et définissez ses dates directement sur le tableau de bord.",
"picker_desc_battery_fleet": "Toutes les piles suivies : ce qui est faible maintenant, ce qui sera bientôt vide et ce qu'il faut acheter.",
"picker_desc_dashboard": "Tableau de bord généré automatiquement. Regroupez les vues par zone, statut, étage ou échéance — au choix dans l'éditeur de stratégie ou en YAML.",
"picker_desc_section": "Intégrez les tâches de maintenance (filtrables par zone, statut, échéance) comme section dans n'importe quelle vue du tableau de bord.",
"picker_desc_vacation_status": "Bannière compacte d'état du mode vacances. Touchez pour ouvrir les réglages dans le panneau.",
"picker_desc_budget_status": "Aperçu du budget de maintenance mensuel et annuel. Touchez pour les détails.",
"picker_desc_groups_status": "Liste des groupes de tâches configurés avec le nombre de tâches de chacun.",
"hist_note_button": "Terminé via un bouton du tableau de bord",
"hist_note_todo": "Terminé depuis la liste de tâches",
"hist_note_voice": "Terminé par la voix",
"hist_note_notification": "Terminé depuis la notification",
"hist_note_nfc": "Terminé via un tag NFC",
"hist_note_shopping_list": "Terminé depuis la liste de courses",
"hist_note_todo_mirror": "Terminé depuis une liste de tâches reflétée",
"hist_note_skipped_notification": "Ignoré depuis la notification",
"hist_note_skipped_button": "Ignoré via un bouton du tableau de bord",
"hist_note_sensor_triggered": "Déclencheur de capteur activé",
"hist_note_initial": "Valeur initiale définie lors de la création de la tâche",
"hist_note_auto_recovered": "Terminé automatiquement : capteur rétabli ({value})",
"hist_note_reset": "Réinitialisé au {date}",
"hist_note_trigger_replaced": "Entité déclencheuse remplacée : {old} → {new}",
"hist_note_trigger_removed": "Déclencheur de capteur supprimé (entité : {entity}). Planning converti en {schedule}.",
"hist_note_compound_removed": "Entité {entity} retirée du déclencheur composé ; conditions restantes : {count}.",
"recent_activities": "Activités récentes",
"search_notes": "Rechercher dans les notes",
"avg_cost": "Ø Coût",
@@ -716,6 +795,7 @@
"groups_manage_tasks": "Gérer les affectations de tâches…",
"groups_open_panel": "Ouvrir dans le panneau",
"on_complete_action_target_hint": "Note : le domaine de l'entité doit correspondre au service — p. ex. 'button.press' ne fonctionne que sur button.*, 'counter.increment' seulement sur counter.*, 'input_button.press' seulement sur input_button.* etc. En cas de non-correspondance, l'action échoue silencieusement (HA journalise 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Pas quand la tâche se termine d'elle-même (son capteur s'est rétabli)",
"show_all_objects": "Afficher tous les objets",
"show_all_tasks": "Effacer le filtre — afficher toutes les tâches",
"filter_to_overdue": "Filtrer la liste sur les tâches en retard uniquement",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "« {name} » : tâches {before} → {after}",
"adopt_problem_adopt": "Adopter la sélection",
"adopt_problem_done": "{tasks} capteur(s) de problème adopté(s)",
"adopt_problem_done_one": "1 capteur de problème adopté",
"views_label": "Vues",
"views_none": "— Aucune vue —",
"views_manage": "Enregistrer / gérer les vues",
@@ -1013,6 +1094,7 @@
"setups_none": "Aucun appareil pris en charge avec des capteurs de consommables non reliés.",
"setups_adopt": "Configurer la sélection",
"setups_done": "{tasks} tâches reliées aux capteurs créées.",
"setups_done_one": "1 tâche reliée aux capteurs créée.",
"complete_parts_used": "Pièces utilisées cette fois",
"part_delete_confirm": "Supprimer la pièce '{name}' ? Son suivi de stock, ses liens aux tâches et tout rappel d'achat ouvert seront supprimés.",
"baseline_start_value": "Valeur de départ (facultatif)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "même modèle sur un autre appareil",
"setups_maybe_covered": "Existe probablement déjà sous « {name} »",
"setups_already": "Déjà présent : {names}",
"setups_reset_line": "La terminer réinitialise aussi le compteur dans l'intégration (« {button} »)",
"setups_reset_enable": "— le bouton sera activé pour cela",
"reset_offers_title": "Réinitialiser les compteurs à la finalisation",
"reset_offers_hint": "Ces tâches surveillent un compteur que l'intégration tient elle-même. Une fois la liaison faite, terminer la tâche ici appuie aussi sur le bouton de réinitialisation de l'intégration — sinon le compteur continue de tourner et la tâche redevient aussitôt due.",
"reset_offers_before": "Maintenant : la terminer laisse tourner le compteur dans {integration}",
"reset_offers_after": "Ensuite : appuie aussi sur « {button} »",
"reset_offers_renamed": "Renommée depuis sa configuration — vérifiez que cette tâche concerne bien cette pièce",
"reset_offers_apply": "Relier les réinitialisations",
"reset_offers_done": "{count} tâches réinitialisent désormais leur compteur à la finalisation",
"reset_offers_done_one": "1 tâche réinitialise désormais son compteur à la finalisation",
"setups_before_after": "Tâches de l'objet : {before} → {after}",
"setups_new_object_count": "Nouvel objet « {name} » · tâches : {count}",
"schedule_preview_title": "Prochaines échéances",
@@ -1046,6 +1138,7 @@
"history_auto": "Automatique",
"battery_fleet_title": "Parc de piles",
"battery_fleet_none_low": "Toutes les piles OK — rien à remplacer.",
"battery_fleet_progress": "{n} à remplacer",
"battery_fleet_buy_now": "Acheter",
"battery_fleet_soon": "Bientôt nécessaire",
"battery_fleet_soon_hint": "Estimé d'après le dernier remplacement — commandez à l'avance.",
@@ -1099,8 +1192,12 @@
"dismiss": "Ignorer",
"gs_label": "Premiers pas — ces conseils disparaissent à mesure que votre configuration grandit",
"gs_setups_chip": "Configurations suggérées : {n} appareils avec déclencheurs pré-câblés trouvés",
"gs_setups_chip_one": "Configurations suggérées : 1 appareil avec déclencheurs pré-câblés trouvé",
"gs_adopt_chip": "{n} capteurs de problème peuvent devenir des tâches de maintenance",
"gs_adopt_chip_one": "1 capteur de problème peut devenir une tâche de maintenance",
"gs_fleet_chip": "Un clic configure le parc de piles",
"gs_reset_chip": "{n} tâches peuvent réinitialiser leur compteur dans l'intégration",
"gs_reset_chip_one": "1 tâche peut réinitialiser son compteur dans l'intégration",
"cal_editor_window": "Fenêtre par défaut",
"cal_editor_window_week": "Semaine (7 jours)",
"cal_editor_window_fortnight": "Quinzaine (14 jours)",
@@ -243,6 +243,26 @@
"sort_task_name": "कार्य का नाम",
"all_objects": "सभी वस्तुएँ",
"all_parts": "सभी पुर्ज़े",
"all_areas": "सभी क्षेत्र",
"areas_filter": "क्षेत्र फ़िल्टर करें…",
"areas_filter_none": "फ़िल्टर से कोई क्षेत्र मेल नहीं खाता।",
"area_cost_year": "{year} की लागत",
"area_object_count": "{n} वस्तुएँ",
"area_object_count_one": "1 वस्तु",
"area_range_12m": "पिछले 12 महीने",
"area_range_all": "पूरी अवधि",
"area_task_filter": "कार्य के अनुसार फ़िल्टर करें…",
"area_kpi_completions": "पूर्णताएँ",
"area_kpi_total_time": "कुल समय",
"area_cost_per_month": "प्रति माह लागत",
"area_cost_per_year": "प्रति वर्ष लागत",
"area_cost_per_object": "प्रति वस्तु लागत",
"area_cost_share": "हिस्सा",
"area_history_section": "इतिहास (सभी वस्तुएँ)",
"area_report_print": "क्षेत्र रिपोर्ट (PDF)",
"area_report_title": "क्षेत्र रिपोर्ट",
"area_report_period": "अवधि",
"area_no_costs": "इस अवधि में कोई लागत दर्ज नहीं है।",
"no_tasks_yet": "अभी कोई कार्य नहीं",
"add_first_task": "पहला कार्य जोड़ें",
"trigger_configuration": "ट्रिगर कॉन्फ़िगरेशन",
@@ -401,11 +421,70 @@
"qr_download": "SVG डाउनलोड करें",
"qr_action_view": "रखरखाव जानकारी देखें",
"qr_action_complete": "रखरखाव को पूर्ण के रूप में चिह्नित करें",
"qr_action_quick_complete": "त्वरित-पूर्ण — बिना संवाद के",
"qr_print_quick_none": "त्वरित-पूर्ण कोड के लिए किसी कार्य पर त्वरित-पूर्ण डिफ़ॉल्ट चाहिए (कार्य संवाद → त्वरित-पूर्ण डिफ़ॉल्ट) — चुनी गई वस्तुओं के किसी कार्य पर अभी ये नहीं हैं।",
"qr_url_mode": "लिंक प्रकार",
"qr_mode_companion": "Companion ऐप",
"qr_mode_local": "लोकल (mDNS)",
"qr_mode_server": "सर्वर URL",
"overview": "अवलोकन",
"strat_this_month": "इस महीने",
"strat_later": "बाद में",
"strat_week": "सप्ताह",
"strat_fortnight": "पखवाड़ा",
"strat_month": "महीना",
"strat_year": "वर्ष",
"strat_other": "अन्य",
"strat_status": "स्थिति",
"strat_empty_title": "अभी कोई रखरखाव वस्तु नहीं",
"strat_empty_content": "अपनी पहली वस्तु जोड़ने के लिए रखरखाव पैनल खोलें — पूल पंप, HVAC फ़िल्टर, वाहन, कुछ भी जिसे नियमित देखभाल की ज़रूरत हो।",
"strat_open_panel": "रखरखाव पैनल खोलें",
"strat_add_object": "वस्तु जोड़ें",
"strat_not_loaded": "**Maintenance Supporter** लोड नहीं है। पहले इंटीग्रेशन इंस्टॉल/सक्षम करें।",
"strat_group_by": "व्यू को इसके अनुसार समूहित करें",
"strat_group_area": "क्षेत्र के अनुसार (डिफ़ॉल्ट)",
"strat_group_status": "स्थिति के अनुसार (अतिदेय / ट्रिगर हुआ / जल्द देय / ठीक)",
"strat_group_floor": "मंज़िल के अनुसार (HA की मंज़िलों का उपयोग)",
"strat_group_due_date": "देय तिथि के अनुसार (अतिदेय / आज / इस सप्ताह / इस महीने / बाद में)",
"strat_group_calendar": "रोलिंग कैलेंडर (सप्ताह / पखवाड़ा / महीना / वर्ष)",
"strat_editor_help": "\"अवलोकन\" व्यू हमेशा पहले आता है। खाली समूह छोड़ दिए जाते हैं।",
"picker_name_calendar": "Maintenance Supporter — कैलेंडर",
"picker_name_panel": "Maintenance Supporter — पैनल कार्ड",
"picker_name_budget": "Maintenance Supporter — रखरखाव बजट",
"picker_name_groups": "Maintenance Supporter — समूह",
"picker_name_vacation": "Maintenance Supporter — अवकाश मोड",
"picker_name_battery_fleet": "बैटरी फ्लीट",
"picker_name_section": "Maintenance Supporter — सेक्शन",
"picker_name_vacation_status": "Maintenance Supporter — अवकाश स्थिति",
"picker_name_budget_status": "Maintenance Supporter — बजट स्थिति",
"picker_desc_card": "त्वरित क्रियाओं के साथ आपके रखरखाव कार्यों का अवलोकन।",
"picker_desc_calendar": "7/14/30/365 दिन की विंडो, स्रोत आइकन और पूर्वानुमान-विश्वास बैज के साथ रखरखाव कार्यों का रोलिंग कैलेंडर।",
"picker_desc_panel": "पूरा Maintenance Supporter पैनल एक कार्ड के रूप में — साइडबार प्रविष्टि के बिना पैनल व्यू / डैशबोर्ड सबव्यू के लिए।",
"picker_desc_budget": "मासिक और वार्षिक बजट सीधे डैशबोर्ड पर संपादित करें।",
"picker_desc_groups": "डैशबोर्ड पर ही कार्य समूह बनाएँ, नाम बदलें और हटाएँ।",
"picker_desc_vacation": "डैशबोर्ड पर ही अवकाश मोड चालू या बंद करें और उसकी तिथियाँ सेट करें।",
"picker_desc_battery_fleet": "सभी ट्रैक की गई बैटरियाँ: अभी कौन-सी कम हैं, कौन-सी जल्द खत्म होंगी और क्या खरीदना है।",
"picker_desc_dashboard": "स्वतः बनाया गया डैशबोर्ड। व्यू को क्षेत्र, स्थिति, मंज़िल या देय तिथि के अनुसार समूहित करें — स्ट्रैटेजी एडिटर या YAML से चुनें।",
"picker_desc_section": "रखरखाव कार्यों (क्षेत्र, स्थिति, देय तिथि से फ़िल्टर योग्य) को किसी भी डैशबोर्ड व्यू में सेक्शन के रूप में जोड़ें।",
"picker_desc_vacation_status": "अवकाश मोड की स्थिति का संक्षिप्त बैनर। पैनल में सेटिंग्स खोलने के लिए टैप करें।",
"picker_desc_budget_status": "मासिक और वार्षिक रखरखाव बजट का अवलोकन। विवरण के लिए टैप करें।",
"picker_desc_groups_status": "कॉन्फ़िगर किए गए कार्य समूहों की सूची, प्रत्येक में कार्यों की संख्या के साथ।",
"hist_note_button": "डैशबोर्ड बटन से पूर्ण किया गया",
"hist_note_todo": "टू-डू सूची से पूर्ण किया गया",
"hist_note_voice": "आवाज़ से पूर्ण किया गया",
"hist_note_notification": "सूचना से पूर्ण किया गया",
"hist_note_nfc": "NFC टैग से पूर्ण किया गया",
"hist_note_shopping_list": "शॉपिंग सूची से पूर्ण किया गया",
"hist_note_todo_mirror": "मिरर की गई टू-डू सूची से पूर्ण किया गया",
"hist_note_skipped_notification": "सूचना से छोड़ा गया",
"hist_note_skipped_button": "डैशबोर्ड बटन से छोड़ा गया",
"hist_note_sensor_triggered": "सेंसर ट्रिगर सक्रिय हुआ",
"hist_note_initial": "कार्य बनाते समय प्रारंभिक मान सेट किया गया",
"hist_note_auto_recovered": "स्वतः पूर्ण: सेंसर ठीक हुआ ({value})",
"hist_note_reset": "{date} पर रीसेट किया गया",
"hist_note_trigger_replaced": "ट्रिगर एंटिटी बदली गई: {old} → {new}",
"hist_note_trigger_removed": "सेंसर ट्रिगर हटाया गया (एंटिटी थी: {entity})। शेड्यूल {schedule} में बदला गया।",
"hist_note_compound_removed": "एंटिटी {entity} को संयुक्त ट्रिगर से हटाया गया; शेष शर्तें: {count}।",
"recent_activities": "हाल की गतिविधियाँ",
"search_notes": "टिप्पणियाँ खोजें",
"avg_cost": "औसत लागत",
@@ -703,6 +782,7 @@
"on_complete_action_desc": "कार्य पूर्ण होने पर एक HA सेवा कॉल करता है — उदा. डिवाइस पर काउंटर रीसेट करना।",
"on_complete_action_target": "लक्ष्य एंटिटी",
"on_complete_action_target_hint": "ध्यान दें: एंटिटी डोमेन सेवा से मेल खाना चाहिए — उदा. 'button.press' केवल button.* पर काम करता है, 'counter.increment' केवल counter.* पर, 'input_button.press' केवल input_button.* पर आदि। मेल न खाने पर क्रिया चुपचाप विफल हो जाएगी (HA लॉग करता है 'Referenced entities ... missing or not currently available')।",
"on_complete_action_skip_auto": "तब नहीं जब कार्य स्वयं पूर्ण हो (उसका सेंसर ठीक हो गया)",
"on_complete_action_data": "डेटा (JSON, वैकल्पिक)",
"on_complete_action_test": "कॉन्फ़िगरेशन सत्यापित करें",
"on_complete_action_test_success": "✓ कॉन्फ़िगरेशन वैध (क्रिया केवल कार्य पूर्ण होने पर चलेगी)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "\"{name}\": कार्य {before} → {after}",
"adopt_problem_adopt": "चयनित अपनाएँ",
"adopt_problem_done": "{tasks} समस्या सेंसर अपनाए गए",
"adopt_problem_done_one": "1 समस्या सेंसर अपनाया गया",
"views_label": "व्यू",
"views_none": "— कोई व्यू नहीं —",
"views_manage": "व्यू सहेजें / प्रबंधित करें",
@@ -1013,6 +1094,7 @@
"setups_none": "बिना जुड़े उपभोग्य-सामग्री सेंसर वाले समर्थित उपकरण नहीं मिले।",
"setups_adopt": "चयनित सेट करें",
"setups_done": "{tasks} सेंसर-जुड़े कार्य बनाए गए।",
"setups_done_one": "1 सेंसर-जुड़ा कार्य बनाया गया।",
"complete_parts_used": "इस बार उपयोग किए गए पुर्ज़े",
"part_delete_confirm": "पुर्ज़ा '{name}' हटाएँ? इसका स्टॉक ट्रैकिंग, कार्य लिंक और कोई खुला खरीद-अनुस्मारक हट जाएगा।",
"baseline_start_value": "प्रारंभिक मान (वैकल्पिक)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "दूसरे डिवाइस पर वही मॉडल",
"setups_maybe_covered": "शायद पहले से \"{name}\" के रूप में मौजूद है",
"setups_already": "पहले से मौजूद: {names}",
"setups_reset_line": "पूर्ण करने पर इंटीग्रेशन में काउंटर भी रीसेट होता है (“{button}”)",
"setups_reset_enable": "— इसके लिए बटन चालू किया जाएगा",
"reset_offers_title": "पूर्ण होने पर काउंटर रीसेट करें",
"reset_offers_hint": "ये कार्य एक ऐसे काउंटर पर नज़र रखते हैं जिसे इंटीग्रेशन खुद रखता है। जोड़ने पर, यहाँ कार्य पूर्ण करने से इंटीग्रेशन का रीसेट बटन भी दबता है — वरना काउंटर चलता रहता है और कार्य तुरंत फिर से देय हो जाता है।",
"reset_offers_before": "अभी: पूर्ण करने पर {integration} में काउंटर चलता रहता है",
"reset_offers_after": "फिर: “{button}” भी दबाया जाएगा",
"reset_offers_renamed": "सेटअप के बाद नाम बदला गया — जाँचें कि यह कार्य इसी पुर्ज़े के लिए है",
"reset_offers_apply": "रीसेट जोड़ें",
"reset_offers_done": "{count} कार्य अब पूर्ण होने पर अपना काउंटर रीसेट करते हैं",
"reset_offers_done_one": "1 कार्य अब पूर्ण होने पर अपना काउंटर रीसेट करता है",
"setups_before_after": "ऑब्जेक्ट के कार्य: {before} → {after}",
"setups_new_object_count": "नया ऑब्जेक्ट \"{name}\" · कार्य: {count}",
"schedule_preview_title": "अगली तिथियाँ",
@@ -1046,6 +1138,7 @@
"history_auto": "स्वचालित",
"battery_fleet_title": "बैटरी फ्लीट",
"battery_fleet_none_low": "सभी बैटरियाँ ठीक — बदलने को कुछ नहीं।",
"battery_fleet_progress": "बदलने हेतु: {n}",
"battery_fleet_buy_now": "अभी खरीदें",
"battery_fleet_soon": "जल्द आवश्यक",
"battery_fleet_soon_hint": "पिछले प्रतिस्थापन से अनुमानित — पहले ऑर्डर करें।",
@@ -1099,8 +1192,12 @@
"dismiss": "हटाएँ",
"gs_label": "शुरुआत — सेटअप बढ़ने पर ये संकेत हट जाते हैं",
"gs_setups_chip": "सुझाए गए सेटअप: पूर्व-निर्धारित ट्रिगर वाले {n} उपकरण मिले",
"gs_setups_chip_one": "सुझाए गए सेटअप: पूर्व-निर्धारित ट्रिगर वाला 1 उपकरण मिला",
"gs_adopt_chip": "{n} समस्या सेंसर रखरखाव कार्य बन सकते हैं",
"gs_adopt_chip_one": "1 समस्या सेंसर रखरखाव कार्य बन सकता है",
"gs_fleet_chip": "एक क्लिक में बैटरी बेड़ा सेट करें",
"gs_reset_chip": "{n} कार्य इंटीग्रेशन में अपना काउंटर रीसेट कर सकते हैं",
"gs_reset_chip_one": "1 कार्य इंटीग्रेशन में अपना काउंटर रीसेट कर सकता है",
"cal_editor_window": "डिफ़ॉल्ट विंडो",
"cal_editor_window_week": "सप्ताह (7 दिन)",
"cal_editor_window_fortnight": "पखवाड़ा (14 दिन)",
@@ -243,6 +243,26 @@
"sort_task_name": "Feladat neve",
"all_objects": "Minden objektum",
"all_parts": "Összes alkatrész",
"all_areas": "Összes terület",
"areas_filter": "Területek szűrése…",
"areas_filter_none": "Egy terület sem felel meg a szűrőnek.",
"area_cost_year": "Költség {year}",
"area_object_count": "{n} objektum",
"area_object_count_one": "1 objektum",
"area_range_12m": "Elmúlt 12 hónap",
"area_range_all": "Teljes időszak",
"area_task_filter": "Szűrés feladat szerint…",
"area_kpi_completions": "Elvégzések",
"area_kpi_total_time": "Teljes idő",
"area_cost_per_month": "Költség havonta",
"area_cost_per_year": "Költség évente",
"area_cost_per_object": "Költség objektumonként",
"area_cost_share": "Arány",
"area_history_section": "Előzmények (összes objektum)",
"area_report_print": "Területi jelentés (PDF)",
"area_report_title": "Területi jelentés",
"area_report_period": "Időszak",
"area_no_costs": "Ebben az időszakban nincs rögzített költség.",
"no_tasks_yet": "Még nincs feladat",
"add_first_task": "Első feladat hozzáadása",
"trigger_configuration": "Kiváltó beállítása",
@@ -401,11 +421,70 @@
"qr_download": "SVG letöltése",
"qr_action_view": "Karbantartási adatok megtekintése",
"qr_action_complete": "Karbantartás elvégzettként jelölése",
"qr_action_quick_complete": "Gyorselvégzés — párbeszédablak nélkül",
"qr_print_quick_none": "A gyorselvégzés-kódokhoz a feladaton gyorselvégzés-alapértékek kellenek (feladat párbeszédablaka → Gyorselvégzés alapértékei) — a kiválasztott objektumok egyik feladatán sincsenek még.",
"qr_url_mode": "Hivatkozás típusa",
"qr_mode_companion": "Companion alkalmazás",
"qr_mode_local": "Helyi (mDNS)",
"qr_mode_server": "Szerver URL",
"overview": "Áttekintés",
"strat_this_month": "Ebben a hónapban",
"strat_later": "Később",
"strat_week": "Hét",
"strat_fortnight": "Két hét",
"strat_month": "Hónap",
"strat_year": "Év",
"strat_other": "Egyéb",
"strat_status": "Állapot",
"strat_empty_title": "Még nincsenek karbantartási objektumok",
"strat_empty_content": "Nyissa meg a Karbantartás panelt az első objektum hozzáadásához — medenceszivattyú, légtechnikai szűrő, jármű, bármi, ami ütemezett gondozást igényel.",
"strat_open_panel": "Karbantartás panel megnyitása",
"strat_add_object": "Objektum hozzáadása",
"strat_not_loaded": "A **Maintenance Supporter** nincs betöltve. Először telepítse/engedélyezze az integrációt.",
"strat_group_by": "Nézetek csoportosítása",
"strat_group_area": "Terület szerint (alapértelmezett)",
"strat_group_status": "Állapot szerint (Lejárt / Aktiválva / Hamarosan esedékes / OK)",
"strat_group_floor": "Szint szerint (a HA szintjeit használja)",
"strat_group_due_date": "Határidő szerint (Lejárt / Ma / Ezen a héten / Ebben a hónapban / Később)",
"strat_group_calendar": "Gördülő naptár (Hét / Két hét / Hónap / Év)",
"strat_editor_help": "Az „Áttekintés” nézet mindig az első. Az üres csoportok kimaradnak.",
"picker_name_calendar": "Maintenance Supporter — Naptár",
"picker_name_panel": "Maintenance Supporter — Panel kártyaként",
"picker_name_budget": "Maintenance Supporter — Karbantartási költségkeret",
"picker_name_groups": "Maintenance Supporter — Csoportok",
"picker_name_vacation": "Maintenance Supporter — Nyaralási mód",
"picker_name_battery_fleet": "Elemflotta",
"picker_name_section": "Maintenance Supporter — Szakasz",
"picker_name_vacation_status": "Maintenance Supporter — Nyaralás állapota",
"picker_name_budget_status": "Maintenance Supporter — Költségkeret állapota",
"picker_desc_card": "Karbantartási feladatainak áttekintése gyorsműveletekkel.",
"picker_desc_calendar": "A karbantartási feladatok gördülő naptára 7/14/30/365 napos időablakokkal, forrásikonokkal és előrejelzési megbízhatósági címkékkel.",
"picker_desc_panel": "A teljes Maintenance Supporter panel kártyaként — panelnézethez / irányítópult-alnézethez oldalsáv-bejegyzés nélkül.",
"picker_desc_budget": "A havi és éves költségkeret szerkesztése közvetlenül az irányítópulton.",
"picker_desc_groups": "Feladatcsoportok létrehozása, átnevezése és törlése közvetlenül az irányítópulton.",
"picker_desc_vacation": "A nyaralási mód be- és kikapcsolása, valamint dátumainak beállítása közvetlenül az irányítópulton.",
"picker_desc_battery_fleet": "Minden nyomon követett elem: mi merült le most, mi fogy ki hamarosan, és mit kell venni.",
"picker_desc_dashboard": "Automatikusan létrehozott irányítópult. A nézetek terület, állapot, szint vagy határidő szerint csoportosíthatók — a stratégiaszerkesztőben vagy YAML-ben választható.",
"picker_desc_section": "Karbantartási feladatok (terület, állapot, határidő szerint szűrhetők) beágyazása szakaszként bármely irányítópult-nézetbe.",
"picker_desc_vacation_status": "Kompakt állapotsáv a nyaralási módhoz. Koppintson a beállítások megnyitásához a panelen.",
"picker_desc_budget_status": "A havi és éves karbantartási költségkeret áttekintése. Koppintson a részletekért.",
"picker_desc_groups_status": "A beállított feladatcsoportok listája a bennük lévő feladatok számával.",
"hist_note_button": "Elvégezve az irányítópult gombjával",
"hist_note_todo": "Elvégezve a teendőlistából",
"hist_note_voice": "Elvégezve hangvezérléssel",
"hist_note_notification": "Elvégezve az értesítésből",
"hist_note_nfc": "Elvégezve NFC címkével",
"hist_note_shopping_list": "Elvégezve a bevásárlólistából",
"hist_note_todo_mirror": "Elvégezve egy tükrözött teendőlistából",
"hist_note_skipped_notification": "Kihagyva az értesítésből",
"hist_note_skipped_button": "Kihagyva az irányítópult gombjával",
"hist_note_sensor_triggered": "Érzékelős kiváltó aktiválva",
"hist_note_initial": "Kezdőérték a feladat létrehozásakor beállítva",
"hist_note_auto_recovered": "Automatikusan elvégezve: az érzékelő helyreállt ({value})",
"hist_note_reset": "Visszaállítva erre: {date}",
"hist_note_trigger_replaced": "Kiváltó entitás lecserélve: {old} → {new}",
"hist_note_trigger_removed": "Érzékelős kiváltó eltávolítva (entitás: {entity}). Ütemezés átállítva: {schedule}.",
"hist_note_compound_removed": "{entity} entitás eltávolítva az összetett kiváltóból; hátralévő feltételek: {count}.",
"recent_activities": "Legutóbbi tevékenységek",
"search_notes": "Keresés a megjegyzésekben",
"avg_cost": "Átl. költség",
@@ -709,6 +788,7 @@
"on_complete_action_desc": "HA szolgáltatást hív meg a feladat elvégzésekor — pl. számláló nullázása az eszközön.",
"on_complete_action_target": "Cél entitás",
"on_complete_action_target_hint": "Megjegyzés: az entitás doménjének egyeznie kell a szolgáltatással — pl. a „button.press” csak button.* entitáson működik, a „counter.increment” csak counter.* entitáson, az „input_button.press” csak input_button.* entitáson stb. Eltérés esetén a művelet csendben meghiúsul (a HA naplóban: „Referenced entities ... missing or not currently available”).",
"on_complete_action_skip_auto": "Nem, ha a feladat magától elvégződik (az érzékelője helyreállt)",
"on_complete_action_data": "Adatok (JSON, opcionális)",
"on_complete_action_test": "Konfiguráció ellenőrzése",
"on_complete_action_test_success": "✓ A konfiguráció érvényes (a művelet csak a feladat elvégzésekor fut le)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "„{name}”: feladatok {before} → {after}",
"adopt_problem_adopt": "Kijelöltek átvétele",
"adopt_problem_done": "{tasks} problémaérzékelő átvéve",
"adopt_problem_done_one": "1 problémaérzékelő átvéve",
"views_label": "Nézetek",
"views_none": "— Nincs nézet —",
"views_manage": "Nézetek mentése / kezelése",
@@ -1013,6 +1094,7 @@
"setups_none": "Nem található támogatott eszköz bekötetlen fogyóeszköz-érzékelővel.",
"setups_adopt": "Kijelöltek beállítása",
"setups_done": "{tasks} érzékelőhöz kötött feladat létrehozva.",
"setups_done_one": "1 érzékelőhöz kötött feladat létrehozva.",
"complete_parts_used": "Most felhasznált alkatrészek",
"part_delete_confirm": "Törli a(z) „{name}” alkatrészt? A készletkövetése, a feladatkapcsolatai és minden nyitott vásárlási emlékeztetője is törlődik.",
"baseline_start_value": "Kezdő leolvasás (opcionális)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "ugyanaz a típus egy másik eszközön",
"setups_maybe_covered": "Valószínűleg már megvan „{name}” néven",
"setups_already": "Már megvan: {names}",
"setups_reset_line": "Az elvégzés az integráció számlálóját is nullázza („{button}”)",
"setups_reset_enable": "— ehhez a gomb be lesz kapcsolva",
"reset_offers_title": "Számlálók nullázása elvégzéskor",
"reset_offers_hint": "Ezek a feladatok egy olyan számlálót figyelnek, amelyet maga az integráció vezet. Összekapcsolva a feladat itteni elvégzése az integráció nullázó gombját is megnyomja — különben a számláló tovább fut, és a feladat azonnal újra esedékessé válik.",
"reset_offers_before": "Most: elvégzéskor a(z) {integration} számlálója tovább fut",
"reset_offers_after": "Utána: ezt is megnyomja: „{button}”",
"reset_offers_renamed": "A beállítás óta átnevezték — ellenőrizze, hogy a feladat ehhez az alkatrészhez tartozik-e",
"reset_offers_apply": "Nullázások összekapcsolása",
"reset_offers_done": "{count} feladat mostantól elvégzéskor nullázza a számlálóját",
"reset_offers_done_one": "1 feladat mostantól elvégzéskor nullázza a számlálóját",
"setups_before_after": "Az objektum feladatai: {before} → {after}",
"setups_new_object_count": "Új objektum „{name}” · feladatok: {count}",
"schedule_preview_title": "Következő dátumok",
@@ -1046,6 +1138,7 @@
"history_auto": "Automatikus",
"battery_fleet_title": "Elemflotta",
"battery_fleet_none_low": "Minden elem rendben — nincs mit cserélni.",
"battery_fleet_progress": "Cserélendő: {n}",
"battery_fleet_buy_now": "Vásárlás most",
"battery_fleet_soon": "Hamarosan szükséges",
"battery_fleet_soon_hint": "Az utolsó cseredátumból előrejelezve — rendeljen előre.",
@@ -1099,8 +1192,12 @@
"dismiss": "Elrejtés",
"gs_label": "Első lépések — a tippek eltűnnek, ahogy a beállítás bővül",
"gs_setups_chip": "Javasolt beállítások: {n} eszköz előre bekötött triggerekkel",
"gs_setups_chip_one": "Javasolt beállítások: 1 eszköz előre bekötött triggerekkel",
"gs_adopt_chip": "{n} problémaérzékelő karbantartási feladattá válhat",
"gs_adopt_chip_one": "1 problémaérzékelő karbantartási feladattá válhat",
"gs_fleet_chip": "Egy kattintás beállítja az elemflottát",
"gs_reset_chip": "{n} feladat nullázhatja a számlálóját az integrációban",
"gs_reset_chip_one": "1 feladat nullázhatja a számlálóját az integrációban",
"cal_editor_window": "Alapértelmezett időablak",
"cal_editor_window_week": "Hét (7 nap)",
"cal_editor_window_fortnight": "Két hét (14 nap)",
@@ -241,6 +241,26 @@
"sort_task_name": "Nome attività",
"all_objects": "Tutti gli oggetti",
"all_parts": "Tutti i ricambi",
"all_areas": "Tutte le aree",
"areas_filter": "Filtra aree…",
"areas_filter_none": "Nessuna area corrisponde al filtro.",
"area_cost_year": "Costo {year}",
"area_object_count": "{n} oggetti",
"area_object_count_one": "1 oggetto",
"area_range_12m": "Ultimi 12 mesi",
"area_range_all": "Tutto il periodo",
"area_task_filter": "Filtra per attività…",
"area_kpi_completions": "Completamenti",
"area_kpi_total_time": "Tempo totale",
"area_cost_per_month": "Costo per mese",
"area_cost_per_year": "Costo per anno",
"area_cost_per_object": "Costo per oggetto",
"area_cost_share": "Quota",
"area_history_section": "Cronologia (tutti gli oggetti)",
"area_report_print": "Rapporto dell'area (PDF)",
"area_report_title": "Rapporto dell'area",
"area_report_period": "Periodo",
"area_no_costs": "Nessun costo registrato in questo periodo.",
"no_tasks_yet": "Nessuna attività",
"add_first_task": "Aggiungi prima attività",
"trigger_configuration": "Configurazione trigger",
@@ -399,11 +419,70 @@
"qr_download": "Scarica SVG",
"qr_action_view": "Visualizza info manutenzione",
"qr_action_complete": "Segna manutenzione come completata",
"qr_action_quick_complete": "Completamento rapido — senza finestra",
"qr_print_quick_none": "I codici di completamento rapido richiedono valori predefiniti di completamento rapido su un'attività (finestra dell'attività → Valori predefiniti completamento rapido) — nessuna attività degli oggetti scelti li ha ancora.",
"qr_url_mode": "Tipo di link",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Locale (mDNS)",
"qr_mode_server": "URL server",
"overview": "Panoramica",
"strat_this_month": "Questo mese",
"strat_later": "Più avanti",
"strat_week": "Settimana",
"strat_fortnight": "Due settimane",
"strat_month": "Mese",
"strat_year": "Anno",
"strat_other": "Altro",
"strat_status": "Stato",
"strat_empty_title": "Nessun oggetto di manutenzione",
"strat_empty_content": "Apri il pannello Manutenzione per aggiungere il tuo primo oggetto — pompa della piscina, filtro del climatizzatore, veicolo, qualsiasi cosa richieda una manutenzione programmata.",
"strat_open_panel": "Apri il pannello Manutenzione",
"strat_add_object": "Aggiungi oggetto",
"strat_not_loaded": "**Maintenance Supporter** non è caricato. Installa/attiva prima l'integrazione.",
"strat_group_by": "Raggruppa le viste per",
"strat_group_area": "Per area (predefinito)",
"strat_group_status": "Per stato (Scaduto / Attivato / In scadenza / OK)",
"strat_group_floor": "Per piano (usa i piani di HA)",
"strat_group_due_date": "Per scadenza (Scaduto / Oggi / Questa settimana / Questo mese / Più avanti)",
"strat_group_calendar": "Calendario mobile (Settimana / Due settimane / Mese / Anno)",
"strat_editor_help": "La vista \"Panoramica\" è sempre la prima. I gruppi vuoti vengono saltati.",
"picker_name_calendar": "Maintenance Supporter — Calendario",
"picker_name_panel": "Maintenance Supporter — Pannello come scheda",
"picker_name_budget": "Maintenance Supporter — Budget di manutenzione",
"picker_name_groups": "Maintenance Supporter — Gruppi",
"picker_name_vacation": "Maintenance Supporter — Modalità vacanza",
"picker_name_battery_fleet": "Parco batterie",
"picker_name_section": "Maintenance Supporter — Sezione",
"picker_name_vacation_status": "Maintenance Supporter — Stato vacanza",
"picker_name_budget_status": "Maintenance Supporter — Stato del budget",
"picker_desc_card": "Panoramica delle tue attività di manutenzione con azioni rapide.",
"picker_desc_calendar": "Calendario mobile delle attività di manutenzione con finestre di 7/14/30/365 giorni, icone della fonte ed etichette di confidenza della previsione.",
"picker_desc_panel": "L'intero pannello di Maintenance Supporter come scheda — per una vista pannello / sottovista della dashboard senza voce nella barra laterale.",
"picker_desc_budget": "Modifica il budget mensile e annuale direttamente nella dashboard.",
"picker_desc_groups": "Crea, rinomina ed elimina gruppi di attività direttamente nella dashboard.",
"picker_desc_vacation": "Attiva o disattiva la modalità vacanza e impostane le date direttamente nella dashboard.",
"picker_desc_battery_fleet": "Tutte le batterie monitorate: quali sono scariche ora, quali si esauriranno presto e cosa comprare.",
"picker_desc_dashboard": "Dashboard generata automaticamente. Raggruppa le viste per area, stato, piano o scadenza — da scegliere nell'editor della strategia o in YAML.",
"picker_desc_section": "Incorpora le attività di manutenzione (filtrabili per area, stato, scadenza) come sezione in qualsiasi vista della dashboard.",
"picker_desc_vacation_status": "Banner compatto dello stato della modalità vacanza. Tocca per aprire le impostazioni nel pannello.",
"picker_desc_budget_status": "Panoramica del budget di manutenzione mensile e annuale. Tocca per i dettagli.",
"picker_desc_groups_status": "Elenco dei gruppi di attività configurati con il numero di attività di ciascuno.",
"hist_note_button": "Completato dal pulsante della dashboard",
"hist_note_todo": "Completato dalla lista di cose da fare",
"hist_note_voice": "Completato con la voce",
"hist_note_notification": "Completato dalla notifica",
"hist_note_nfc": "Completato tramite tag NFC",
"hist_note_shopping_list": "Completato dalla lista della spesa",
"hist_note_todo_mirror": "Completato da una lista di cose da fare rispecchiata",
"hist_note_skipped_notification": "Saltato dalla notifica",
"hist_note_skipped_button": "Saltato dal pulsante della dashboard",
"hist_note_sensor_triggered": "Trigger del sensore attivato",
"hist_note_initial": "Valore iniziale impostato alla creazione dell'attività",
"hist_note_auto_recovered": "Completato automaticamente: sensore ripristinato ({value})",
"hist_note_reset": "Reimpostato al {date}",
"hist_note_trigger_replaced": "Entità trigger sostituita: {old} → {new}",
"hist_note_trigger_removed": "Trigger del sensore rimosso (entità: {entity}). Pianificazione convertita in {schedule}.",
"hist_note_compound_removed": "Entità {entity} rimossa dal trigger composto; condizioni rimanenti: {count}.",
"recent_activities": "Attività recenti",
"search_notes": "Cerca nelle note",
"avg_cost": "Ø Costo",
@@ -716,6 +795,7 @@
"groups_manage_tasks": "Gestisci assegnazioni attività…",
"groups_open_panel": "Apri nel pannello",
"on_complete_action_target_hint": "Nota: il dominio dell'entità deve corrispondere al servizio — es. 'button.press' funziona solo su button.*, 'counter.increment' solo su counter.*, 'input_button.press' solo su input_button.* ecc. In caso di mancata corrispondenza l'azione fallisce silenziosamente (HA registra 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Non quando l'attività si completa da sola (il suo sensore si è ripristinato)",
"show_all_objects": "Mostra tutti gli oggetti",
"show_all_tasks": "Azzera filtro — mostra tutte le attività",
"filter_to_overdue": "Filtra l'elenco solo sulle attività in ritardo",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "«{name}»: attività {before} → {after}",
"adopt_problem_adopt": "Adotta selezionati",
"adopt_problem_done": "{tasks} sensore/i di problema adottato/i",
"adopt_problem_done_one": "1 sensore di problema adottato",
"views_label": "Viste",
"views_none": "— Nessuna vista —",
"views_manage": "Salva / gestisci viste",
@@ -1013,6 +1094,7 @@
"setups_none": "Nessun dispositivo supportato con sensori di consumabili non collegati.",
"setups_adopt": "Configura selezione",
"setups_done": "{tasks} attività collegate ai sensori create.",
"setups_done_one": "1 attività collegata ai sensori creata.",
"complete_parts_used": "Ricambi usati questa volta",
"part_delete_confirm": "Eliminare il ricambio '{name}'? Verranno rimossi il monitoraggio delle scorte, i collegamenti alle attività e ogni promemoria d'acquisto aperto.",
"baseline_start_value": "Valore iniziale (facoltativo)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "stesso modello su un altro dispositivo",
"setups_maybe_covered": "Probabilmente esiste già come «{name}»",
"setups_already": "Già presente: {names}",
"setups_reset_line": "Completarla azzera anche il contatore nell'integrazione («{button}»)",
"setups_reset_enable": "— il pulsante verrà attivato a questo scopo",
"reset_offers_title": "Azzera i contatori al completamento",
"reset_offers_hint": "Queste attività osservano un contatore gestito dall'integrazione stessa. Una volta collegate, completare l'attività qui preme anche il pulsante di azzeramento dell'integrazione — altrimenti il contatore continua a correre e l'attività torna subito in scadenza.",
"reset_offers_before": "Ora: completarla lascia correre il contatore in {integration}",
"reset_offers_after": "Poi: preme anche «{button}»",
"reset_offers_renamed": "Rinominata dopo la configurazione — verifica che questa attività riguardi questo componente",
"reset_offers_apply": "Collega gli azzeramenti",
"reset_offers_done": "{count} attività ora azzerano il contatore al completamento",
"reset_offers_done_one": "1 attività ora azzera il contatore al completamento",
"setups_before_after": "Attività dell'oggetto: {before} → {after}",
"setups_new_object_count": "Nuovo oggetto «{name}» · attività: {count}",
"schedule_preview_title": "Prossime date",
@@ -1046,6 +1138,7 @@
"history_auto": "Automatico",
"battery_fleet_title": "Parco batterie",
"battery_fleet_none_low": "Tutte le batterie OK — niente da sostituire.",
"battery_fleet_progress": "{n} da sostituire",
"battery_fleet_buy_now": "Da comprare",
"battery_fleet_soon": "Presto necessario",
"battery_fleet_soon_hint": "Stimato dall'ultima sostituzione — ordina in anticipo.",
@@ -1099,8 +1192,12 @@
"dismiss": "Ignora",
"gs_label": "Primi passi — questi suggerimenti scompaiono man mano che la configurazione cresce",
"gs_setups_chip": "Configurazioni suggerite: trovati {n} dispositivi con trigger preconfigurati",
"gs_setups_chip_one": "Configurazioni suggerite: trovato 1 dispositivo con trigger preconfigurati",
"gs_adopt_chip": "{n} sensori di problemi possono diventare attività di manutenzione",
"gs_adopt_chip_one": "1 sensore di problemi può diventare un'attività di manutenzione",
"gs_fleet_chip": "Un clic configura la flotta di batterie",
"gs_reset_chip": "{n} attività possono azzerare il contatore nell'integrazione",
"gs_reset_chip_one": "1 attività può azzerare il contatore nell'integrazione",
"cal_editor_window": "Finestra predefinita",
"cal_editor_window_week": "Settimana (7 giorni)",
"cal_editor_window_fortnight": "Due settimane (14 giorni)",
@@ -243,6 +243,26 @@
"sort_task_name": "タスク名",
"all_objects": "すべての対象",
"all_parts": "すべての部品",
"all_areas": "すべてのエリア",
"areas_filter": "エリアを絞り込む…",
"areas_filter_none": "条件に一致するエリアはありません。",
"area_cost_year": "{year}年の費用",
"area_object_count": "{n} 件の対象",
"area_object_count_one": "1 件の対象",
"area_range_12m": "過去12か月",
"area_range_all": "全期間",
"area_task_filter": "タスクで絞り込む…",
"area_kpi_completions": "完了回数",
"area_kpi_total_time": "合計所要時間",
"area_cost_per_month": "月別費用",
"area_cost_per_year": "年別費用",
"area_cost_per_object": "対象別費用",
"area_cost_share": "割合",
"area_history_section": "履歴(全対象)",
"area_report_print": "エリアレポート(PDF)",
"area_report_title": "エリアレポート",
"area_report_period": "期間",
"area_no_costs": "この期間に記録された費用はありません。",
"no_tasks_yet": "タスクがまだありません",
"add_first_task": "最初のタスクを追加",
"trigger_configuration": "トリガー設定",
@@ -401,11 +421,70 @@
"qr_download": "SVGをダウンロード",
"qr_action_view": "メンテナンス情報を表示",
"qr_action_complete": "メンテナンスを完了にする",
"qr_action_quick_complete": "クイック完了 — ダイアログなし",
"qr_print_quick_none": "クイック完了コードには、タスクのクイック完了の既定値が必要です(タスクのダイアログ → クイック完了の既定値)。選択したオブジェクトのタスクにはまだ設定されていません。",
"qr_url_mode": "リンク種別",
"qr_mode_companion": "コンパニオンアプリ",
"qr_mode_local": "ローカル(mDNS)",
"qr_mode_server": "サーバーURL",
"overview": "概要",
"strat_this_month": "今月",
"strat_later": "それ以降",
"strat_week": "1週間",
"strat_fortnight": "2週間",
"strat_month": "1か月",
"strat_year": "1年",
"strat_other": "その他",
"strat_status": "状態",
"strat_empty_title": "メンテナンス対象がまだありません",
"strat_empty_content": "メンテナンスパネルを開いて最初の対象を追加しましょう — プールポンプ、空調フィルター、車両など、定期的な手入れが必要なものなら何でも。",
"strat_open_panel": "メンテナンスパネルを開く",
"strat_add_object": "対象を追加",
"strat_not_loaded": "**Maintenance Supporter** が読み込まれていません。先にインテグレーションをインストール/有効化してください。",
"strat_group_by": "ビューのグループ化",
"strat_group_area": "エリア別(既定)",
"strat_group_status": "状態別(期限超過 / トリガー発生 / 期限間近 / OK)",
"strat_group_floor": "フロア別(HA のフロアを使用)",
"strat_group_due_date": "期限別(期限超過 / 今日 / 今週 / 今月 / それ以降)",
"strat_group_calendar": "ローリングカレンダー(1週間 / 2週間 / 1か月 / 1年)",
"strat_editor_help": "「概要」ビューは常に最初に表示されます。空のグループはスキップされます。",
"picker_name_calendar": "Maintenance Supporter — カレンダー",
"picker_name_panel": "Maintenance Supporter — パネルカード",
"picker_name_budget": "Maintenance Supporter — メンテナンス予算",
"picker_name_groups": "Maintenance Supporter — グループ",
"picker_name_vacation": "Maintenance Supporter — 休暇モード",
"picker_name_battery_fleet": "電池フリート",
"picker_name_section": "Maintenance Supporter — セクション",
"picker_name_vacation_status": "Maintenance Supporter — 休暇ステータス",
"picker_name_budget_status": "Maintenance Supporter — 予算ステータス",
"picker_desc_card": "クイック操作付きのメンテナンスタスク概要。",
"picker_desc_calendar": "7/14/30/365 日の期間、ソースアイコン、予測信頼度バッジを備えたメンテナンスタスクのローリングカレンダー。",
"picker_desc_panel": "Maintenance Supporter パネル全体をカードとして表示 — サイドバー項目なしでパネルビューやダッシュボードのサブビューに。",
"picker_desc_budget": "月間・年間予算をダッシュボード上で直接編集します。",
"picker_desc_groups": "ダッシュボード上でタスクグループを直接作成・名前変更・削除します。",
"picker_desc_vacation": "ダッシュボード上で休暇モードのオン/オフと期間を直接設定します。",
"picker_desc_battery_fleet": "追跡中のすべての電池:今残量が少ないもの、まもなく切れるもの、購入が必要なもの。",
"picker_desc_dashboard": "自動生成されるダッシュボード。ビューをエリア・状態・フロア・期限でグループ化できます(ストラテジーエディターまたは YAML で選択)。",
"picker_desc_section": "メンテナンスタスク(エリア・状態・期限で絞り込み可)を任意のダッシュボードビューにセクションとして埋め込みます。",
"picker_desc_vacation_status": "休暇モードの状態を示すコンパクトなバナー。タップするとパネルで設定を開きます。",
"picker_desc_budget_status": "月間・年間のメンテナンス予算の概要。タップで詳細を表示します。",
"picker_desc_groups_status": "設定済みのタスクグループとそれぞれのタスク数の一覧。",
"hist_note_button": "ダッシュボードのボタンで完了",
"hist_note_todo": "ToDoリストから完了",
"hist_note_voice": "音声で完了",
"hist_note_notification": "通知から完了",
"hist_note_nfc": "NFCタグで完了",
"hist_note_shopping_list": "買い物リストから完了",
"hist_note_todo_mirror": "ミラーしたToDoリストから完了",
"hist_note_skipped_notification": "通知からスキップ",
"hist_note_skipped_button": "ダッシュボードのボタンでスキップ",
"hist_note_sensor_triggered": "センサートリガーが発生",
"hist_note_initial": "タスク作成時に設定された初期値",
"hist_note_auto_recovered": "自動完了:センサーが回復({value})",
"hist_note_reset": "{date} にリセット",
"hist_note_trigger_replaced": "トリガーエンティティを置換: {old} → {new}",
"hist_note_trigger_removed": "センサートリガーを削除しました(エンティティ: {entity})。スケジュールを{schedule}に変更しました。",
"hist_note_compound_removed": "複合トリガーからエンティティ {entity} を削除しました。残りの条件: {count}。",
"recent_activities": "最近のアクティビティ",
"search_notes": "メモを検索",
"avg_cost": "平均費用",
@@ -703,6 +782,7 @@
"on_complete_action_desc": "タスク完了時にHAサービスを呼び出します — 例: デバイスのカウンターをリセット。",
"on_complete_action_target": "対象エンティティ",
"on_complete_action_target_hint": "注意: エンティティのドメインはサービスと一致する必要があります — 例: 'button.press'はbutton.*のみ、'counter.increment'はcounter.*のみ、'input_button.press'はinput_button.*のみで動作します。不一致の場合、アクションは何も表示せずに失敗します(HAのログに「Referenced entities ... missing or not currently available」と記録されます)。",
"on_complete_action_skip_auto": "タスクが自動で完了したとき(センサーが回復したとき)は実行しない",
"on_complete_action_data": "データ(JSON、任意)",
"on_complete_action_test": "設定を検証",
"on_complete_action_test_success": "✓ 設定は有効です(アクションはタスク完了時のみ実行されます)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "「{name}」: タスク {before} → {after}",
"adopt_problem_adopt": "選択を取り込む",
"adopt_problem_done": "{tasks} 件の問題センサーを取り込みました",
"adopt_problem_done_one": "1 件の問題センサーを取り込みました",
"views_label": "ビュー",
"views_none": "— ビューなし —",
"views_manage": "ビューを保存/管理",
@@ -1013,6 +1094,7 @@
"setups_none": "未接続の消耗品センサーを持つ対応デバイスは見つかりませんでした。",
"setups_adopt": "選択項目をセットアップ",
"setups_done": "センサー接続タスクを{tasks}件作成しました。",
"setups_done_one": "センサー接続タスクを1件作成しました。",
"complete_parts_used": "今回使用した部品",
"part_delete_confirm": "部品「{name}」を削除しますか?在庫管理、タスクとのリンク、未完了の購入リマインダーが削除されます。",
"baseline_start_value": "開始値(任意)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "別のデバイスで同じ機種",
"setups_maybe_covered": "「{name}」としてすでにある可能性",
"setups_already": "すでにあり: {names}",
"setups_reset_line": "完了するとインテグレーションのカウンターもリセットします(「{button}」)",
"setups_reset_enable": "— そのためにボタンを有効にします",
"reset_offers_title": "完了時にカウンターをリセット",
"reset_offers_hint": "これらのタスクは、インテグレーション自体が管理するカウンターを監視しています。連携すると、ここでタスクを完了したときにインテグレーションのリセットボタンも押します — そうしないとカウンターが進み続け、タスクがすぐにまた期限になります。",
"reset_offers_before": "現在: 完了しても {integration} のカウンターは進み続けます",
"reset_offers_after": "変更後: 「{button}」も押します",
"reset_offers_renamed": "設定後に名前が変更されています — このタスクがこの部品用か確認してください",
"reset_offers_apply": "リセットを連携",
"reset_offers_done": "{count}件のタスクが完了時にカウンターをリセットするようになりました",
"reset_offers_done_one": "1件のタスクが完了時にカウンターをリセットするようになりました",
"setups_before_after": "オブジェクトのタスク: {before} → {after}",
"setups_new_object_count": "新しいオブジェクト「{name}」· タスク: {count}",
"schedule_preview_title": "次回の予定日",
@@ -1046,6 +1138,7 @@
"history_auto": "自動",
"battery_fleet_title": "電池フリート",
"battery_fleet_none_low": "すべての電池は正常 — 交換不要。",
"battery_fleet_progress": "交換対象:{n}",
"battery_fleet_buy_now": "今すぐ購入",
"battery_fleet_soon": "まもなく必要",
"battery_fleet_soon_hint": "前回交換日からの予測 — 早めに注文を。",
@@ -1099,8 +1192,12 @@
"dismiss": "閉じる",
"gs_label": "はじめに — セットアップが進むとこれらのヒントは消えます",
"gs_setups_chip": "推奨セットアップ:トリガー設定済みのデバイスを{n}台検出",
"gs_setups_chip_one": "推奨セットアップ:トリガー設定済みのデバイスを1台検出",
"gs_adopt_chip": "{n}個の問題センサーをメンテナンスタスクにできます",
"gs_adopt_chip_one": "1個の問題センサーをメンテナンスタスクにできます",
"gs_fleet_chip": "ワンクリックで電池フリートを設定",
"gs_reset_chip": "{n}件のタスクがインテグレーションのカウンターをリセットできます",
"gs_reset_chip_one": "1件のタスクがインテグレーションのカウンターをリセットできます",
"cal_editor_window": "既定の期間",
"cal_editor_window_week": "1週間(7日)",
"cal_editor_window_fortnight": "2週間(14日)",
@@ -243,6 +243,26 @@
"sort_task_name": "작업 이름",
"all_objects": "모든 객체",
"all_parts": "모든 부품",
"all_areas": "모든 구역",
"areas_filter": "구역 필터…",
"areas_filter_none": "필터와 일치하는 구역이 없습니다.",
"area_cost_year": "{year}년 비용",
"area_object_count": "객체 {n}개",
"area_object_count_one": "객체 1개",
"area_range_12m": "최근 12개월",
"area_range_all": "전체 기간",
"area_task_filter": "작업으로 필터…",
"area_kpi_completions": "완료 횟수",
"area_kpi_total_time": "총 소요 시간",
"area_cost_per_month": "월별 비용",
"area_cost_per_year": "연도별 비용",
"area_cost_per_object": "객체별 비용",
"area_cost_share": "비율",
"area_history_section": "기록(전체 객체)",
"area_report_print": "구역 보고서(PDF)",
"area_report_title": "구역 보고서",
"area_report_period": "기간",
"area_no_costs": "이 기간에 기록된 비용이 없습니다.",
"no_tasks_yet": "아직 작업 없음",
"add_first_task": "첫 작업 추가",
"trigger_configuration": "트리거 설정",
@@ -401,11 +421,70 @@
"qr_download": "SVG 다운로드",
"qr_action_view": "유지보수 정보 보기",
"qr_action_complete": "유지보수 완료로 표시",
"qr_action_quick_complete": "빠른 완료 — 대화 상자 없이",
"qr_print_quick_none": "빠른 완료 코드에는 작업의 빠른 완료 기본값이 필요합니다(작업 대화 상자 → 빠른 완료 기본값). 선택한 개체의 작업에는 아직 없습니다.",
"qr_url_mode": "링크 유형",
"qr_mode_companion": "Companion 앱",
"qr_mode_local": "로컬 (mDNS)",
"qr_mode_server": "서버 URL",
"overview": "개요",
"strat_this_month": "이번 달",
"strat_later": "이후",
"strat_week": "1주",
"strat_fortnight": "2주",
"strat_month": "1개월",
"strat_year": "1년",
"strat_other": "기타",
"strat_status": "상태",
"strat_empty_title": "아직 유지보수 객체가 없습니다",
"strat_empty_content": "유지보수 패널을 열어 첫 객체를 추가하세요 — 수영장 펌프, 공조 필터, 차량 등 정기 관리가 필요한 모든 것.",
"strat_open_panel": "유지보수 패널 열기",
"strat_add_object": "객체 추가",
"strat_not_loaded": "**Maintenance Supporter**가 로드되지 않았습니다. 먼저 통합구성요소를 설치/활성화하세요.",
"strat_group_by": "뷰 그룹화 기준",
"strat_group_area": "구역별 (기본)",
"strat_group_status": "상태별 (기한 초과 / 트리거됨 / 기한 임박 / 정상)",
"strat_group_floor": "층별 (HA 층 사용)",
"strat_group_due_date": "예정일별 (기한 초과 / 오늘 / 이번 주 / 이번 달 / 이후)",
"strat_group_calendar": "롤링 캘린더 (1주 / 2주 / 1개월 / 1년)",
"strat_editor_help": "'개요' 뷰는 항상 맨 처음에 표시됩니다. 빈 그룹은 건너뜁니다.",
"picker_name_calendar": "Maintenance Supporter — 캘린더",
"picker_name_panel": "Maintenance Supporter — 패널 카드",
"picker_name_budget": "Maintenance Supporter — 유지보수 예산",
"picker_name_groups": "Maintenance Supporter — 그룹",
"picker_name_vacation": "Maintenance Supporter — 휴가 모드",
"picker_name_battery_fleet": "배터리 플릿",
"picker_name_section": "Maintenance Supporter — 섹션",
"picker_name_vacation_status": "Maintenance Supporter — 휴가 상태",
"picker_name_budget_status": "Maintenance Supporter — 예산 상태",
"picker_desc_card": "빠른 작업이 포함된 유지보수 작업 개요.",
"picker_desc_calendar": "7/14/30/365일 기간, 출처 아이콘, 예측 신뢰도 배지를 갖춘 유지보수 작업 롤링 캘린더.",
"picker_desc_panel": "전체 Maintenance Supporter 패널을 카드로 — 사이드바 항목 없이 패널 뷰 / 대시보드 하위 뷰에 사용.",
"picker_desc_budget": "대시보드에서 바로 월 예산과 연 예산을 편집합니다.",
"picker_desc_groups": "대시보드에서 바로 작업 그룹을 만들고, 이름을 바꾸고, 삭제합니다.",
"picker_desc_vacation": "대시보드에서 바로 휴가 모드를 켜거나 끄고 기간을 설정합니다.",
"picker_desc_battery_fleet": "추적 중인 모든 배터리: 지금 부족한 것, 곧 떨어질 것, 구매할 것.",
"picker_desc_dashboard": "자동 생성 대시보드. 뷰를 구역, 상태, 층 또는 예정일별로 그룹화하며, 전략 편집기나 YAML에서 선택합니다.",
"picker_desc_section": "유지보수 작업(구역, 상태, 예정일로 필터 가능)을 모든 대시보드 뷰에 섹션으로 삽입합니다.",
"picker_desc_vacation_status": "휴가 모드 상태를 보여 주는 간결한 배너. 탭하면 패널에서 설정이 열립니다.",
"picker_desc_budget_status": "월별·연별 유지보수 예산 개요. 탭하면 자세한 내용을 볼 수 있습니다.",
"picker_desc_groups_status": "구성된 작업 그룹 목록과 그룹별 작업 수.",
"hist_note_button": "대시보드 버튼으로 완료됨",
"hist_note_todo": "할 일 목록에서 완료됨",
"hist_note_voice": "음성으로 완료됨",
"hist_note_notification": "알림에서 완료됨",
"hist_note_nfc": "NFC 태그로 완료됨",
"hist_note_shopping_list": "쇼핑 목록에서 완료됨",
"hist_note_todo_mirror": "미러링된 할 일 목록에서 완료됨",
"hist_note_skipped_notification": "알림에서 건너뜀",
"hist_note_skipped_button": "대시보드 버튼으로 건너뜀",
"hist_note_sensor_triggered": "센서 트리거 활성화됨",
"hist_note_initial": "작업 생성 시 설정된 초기값",
"hist_note_auto_recovered": "자동 완료: 센서가 정상으로 돌아옴 ({value})",
"hist_note_reset": "{date}(으)로 초기화됨",
"hist_note_trigger_replaced": "트리거 엔티티 교체됨: {old} → {new}",
"hist_note_trigger_removed": "센서 트리거 제거됨 (엔티티: {entity}). 일정이 {schedule}(으)로 변경됨.",
"hist_note_compound_removed": "복합 트리거에서 엔티티 {entity} 제거됨. 남은 조건: {count}개.",
"recent_activities": "최근 활동",
"search_notes": "메모 검색",
"avg_cost": "평균 비용",
@@ -709,6 +788,7 @@
"on_complete_action_desc": "작업이 완료되면 HA 서비스를 호출합니다 — 예: 기기의 카운터 초기화.",
"on_complete_action_target": "대상 엔티티",
"on_complete_action_target_hint": "참고: 엔티티 도메인이 서비스와 일치해야 합니다 — 예: 'button.press'는 button.*에서만, 'counter.increment'는 counter.*에서만, 'input_button.press'는 input_button.*에서만 동작합니다. 불일치 시 동작이 조용히 실패합니다 (HA 로그에 'Referenced entities ... missing or not currently available' 기록).",
"on_complete_action_skip_auto": "작업이 스스로 완료될 때는 제외 (센서가 정상으로 돌아옴)",
"on_complete_action_data": "데이터 (JSON, 선택)",
"on_complete_action_test": "설정 검증",
"on_complete_action_test_success": "✓ 설정이 유효합니다 (동작은 작업 완료 시에만 실행됩니다)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "\"{name}\": 작업 {before} → {after}",
"adopt_problem_adopt": "선택 항목 가져오기",
"adopt_problem_done": "문제 센서 {tasks}개를 가져왔습니다",
"adopt_problem_done_one": "문제 센서 1개를 가져왔습니다",
"views_label": "보기",
"views_none": "— 보기 없음 —",
"views_manage": "보기 저장 / 관리",
@@ -1013,6 +1094,7 @@
"setups_none": "연결되지 않은 소모품 센서를 가진 지원 기기를 찾지 못했습니다.",
"setups_adopt": "선택 항목 설정",
"setups_done": "센서 연결 작업 {tasks}개가 생성되었습니다.",
"setups_done_one": "센서 연결 작업 1개가 생성되었습니다.",
"complete_parts_used": "이번에 사용한 부품",
"part_delete_confirm": "'{name}' 부품을 삭제할까요? 재고 추적, 작업 연결, 진행 중인 구매 알림이 모두 제거됩니다.",
"baseline_start_value": "시작 값 (선택)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "다른 기기의 같은 모델",
"setups_maybe_covered": "이미 \"{name}\"(으)로 있을 수 있음",
"setups_already": "이미 있음: {names}",
"setups_reset_line": "완료하면 통합구성요소의 카운터도 초기화합니다 (“{button}”)",
"setups_reset_enable": "— 이를 위해 버튼이 활성화됩니다",
"reset_offers_title": "완료 시 카운터 초기화",
"reset_offers_hint": "이 작업들은 통합구성요소가 직접 관리하는 카운터를 감시합니다. 연결하면 여기서 작업을 완료할 때 통합구성요소의 초기화 버튼도 누릅니다 — 그렇지 않으면 카운터가 계속 올라가 작업이 곧바로 다시 기한이 됩니다.",
"reset_offers_before": "현재: 완료해도 {integration}의 카운터는 계속 올라갑니다",
"reset_offers_after": "변경 후: “{button}”도 누릅니다",
"reset_offers_renamed": "설정 후 이름이 변경됨 — 이 작업이 이 부품에 해당하는지 확인하세요",
"reset_offers_apply": "초기화 연결",
"reset_offers_done": "작업 {count}개가 이제 완료 시 카운터를 초기화합니다",
"reset_offers_done_one": "작업 1개가 이제 완료 시 카운터를 초기화합니다",
"setups_before_after": "객체의 작업: {before} → {after}",
"setups_new_object_count": "새 객체 \"{name}\" · 작업: {count}",
"schedule_preview_title": "다음 예정일",
@@ -1046,6 +1138,7 @@
"history_auto": "자동",
"battery_fleet_title": "배터리 플릿",
"battery_fleet_none_low": "모든 배터리 정상 — 교체할 것이 없습니다.",
"battery_fleet_progress": "교체 대상: {n}",
"battery_fleet_buy_now": "지금 구매",
"battery_fleet_soon": "곧 필요",
"battery_fleet_soon_hint": "마지막 교체일로부터 예측한 값입니다 — 미리 주문해 두세요.",
@@ -1099,8 +1192,12 @@
"dismiss": "닫기",
"gs_label": "시작하기 — 설정이 늘어나면 이 힌트는 사라집니다",
"gs_setups_chip": "추천 설정: 트리거가 준비된 기기 {n}대 발견",
"gs_setups_chip_one": "추천 설정: 트리거가 준비된 기기 1대 발견",
"gs_adopt_chip": "문제 센서 {n}개를 유지보수 작업으로 만들 수 있습니다",
"gs_adopt_chip_one": "문제 센서 1개를 유지보수 작업으로 만들 수 있습니다",
"gs_fleet_chip": "클릭 한 번으로 배터리 플릿 설정",
"gs_reset_chip": "작업 {n}개가 통합구성요소의 카운터를 초기화할 수 있습니다",
"gs_reset_chip_one": "작업 1개가 통합구성요소의 카운터를 초기화할 수 있습니다",
"cal_editor_window": "기본 기간",
"cal_editor_window_week": "1주 (7일)",
"cal_editor_window_fortnight": "2주 (14일)",
@@ -243,6 +243,26 @@
"sort_task_name": "Oppgavenavn",
"all_objects": "Alle objekter",
"all_parts": "Alle deler",
"all_areas": "Alle områder",
"areas_filter": "Filtrer områder…",
"areas_filter_none": "Ingen områder samsvarer med filteret.",
"area_cost_year": "Kostnad {year}",
"area_object_count": "{n} objekter",
"area_object_count_one": "1 objekt",
"area_range_12m": "Siste 12 måneder",
"area_range_all": "Hele perioden",
"area_task_filter": "Filtrer etter oppgave…",
"area_kpi_completions": "Utførelser",
"area_kpi_total_time": "Total tid",
"area_cost_per_month": "Kostnad per måned",
"area_cost_per_year": "Kostnad per år",
"area_cost_per_object": "Kostnad per objekt",
"area_cost_share": "Andel",
"area_history_section": "Historikk (alle objekter)",
"area_report_print": "Områderapport (PDF)",
"area_report_title": "Områderapport",
"area_report_period": "Periode",
"area_no_costs": "Ingen kostnader registrert i denne perioden.",
"no_tasks_yet": "Ingen oppgaver ennå",
"add_first_task": "Legg til første oppgave",
"trigger_configuration": "Utløserkonfigurasjon",
@@ -401,11 +421,70 @@
"qr_download": "Last ned SVG",
"qr_action_view": "Vis vedlikeholdsinfo",
"qr_action_complete": "Merk vedlikehold som fullført",
"qr_action_quick_complete": "Hurtigfullføring — uten dialog",
"qr_print_quick_none": "Hurtigfullføringskoder krever standardverdier for hurtigfullføring på en oppgave (oppgavedialogen → Standardverdier for hurtigfullføring) — ingen oppgave i de valgte objektene har noen ennå.",
"qr_url_mode": "Lenketype",
"qr_mode_companion": "Companion-app",
"qr_mode_local": "Lokal (mDNS)",
"qr_mode_server": "Server-URL",
"overview": "Oversikt",
"strat_this_month": "Denne måneden",
"strat_later": "Senere",
"strat_week": "Uke",
"strat_fortnight": "To uker",
"strat_month": "Måned",
"strat_year": "År",
"strat_other": "Annet",
"strat_status": "Tilstand",
"strat_empty_title": "Ingen vedlikeholdsobjekter ennå",
"strat_empty_content": "Åpne vedlikeholdspanelet for å legge til ditt første objekt — bassengpumpe, ventilasjonsfilter, kjøretøy, alt som trenger planlagt stell.",
"strat_open_panel": "Åpne vedlikeholdspanelet",
"strat_add_object": "Legg til objekt",
"strat_not_loaded": "**Maintenance Supporter** er ikke lastet inn. Installer/aktiver integrasjonen først.",
"strat_group_by": "Grupper visninger etter",
"strat_group_area": "Etter område (standard)",
"strat_group_status": "Etter status (Forfalt / Utløst / Forfaller snart / OK)",
"strat_group_floor": "Etter etasje (bruker HA-etasjene)",
"strat_group_due_date": "Etter forfallsdato (Forfalt / I dag / Denne uken / Denne måneden / Senere)",
"strat_group_calendar": "Rullerende kalender (Uke / To uker / Måned / År)",
"strat_editor_help": "Visningen «Oversikt» kommer alltid først. Tomme grupper hoppes over.",
"picker_name_calendar": "Maintenance Supporter — Kalender",
"picker_name_panel": "Maintenance Supporter — Panel som kort",
"picker_name_budget": "Maintenance Supporter — Vedlikeholdsbudsjett",
"picker_name_groups": "Maintenance Supporter — Grupper",
"picker_name_vacation": "Maintenance Supporter — Feriemodus",
"picker_name_battery_fleet": "Batteriflåte",
"picker_name_section": "Maintenance Supporter — Seksjon",
"picker_name_vacation_status": "Maintenance Supporter — Feriestatus",
"picker_name_budget_status": "Maintenance Supporter — Budsjettstatus",
"picker_desc_card": "Oversikt over vedlikeholdsoppgavene dine med hurtighandlinger.",
"picker_desc_calendar": "Rullerende kalender over vedlikeholdsoppgaver med vinduer på 7/14/30/365 dager, kildeikoner og merker for prognosesikkerhet.",
"picker_desc_panel": "Hele Maintenance Supporter-panelet som kort — for en panelvisning / undervisning i et dashbord uten oppføring i sidefeltet.",
"picker_desc_budget": "Rediger måneds- og årsbudsjettet rett på dashbordet.",
"picker_desc_groups": "Opprett, gi nytt navn til og slett oppgavegrupper rett på dashbordet.",
"picker_desc_vacation": "Slå feriemodus av eller på og angi datoene rett på dashbordet.",
"picker_desc_battery_fleet": "Alle overvåkede batterier: hva som er lavt nå, hva som snart går tomt, og hva du må kjøpe.",
"picker_desc_dashboard": "Automatisk generert dashbord. Grupper visninger etter område, status, etasje eller forfallsdato — velges i strategiredigeringen eller i YAML.",
"picker_desc_section": "Bygg inn vedlikeholdsoppgaver (kan filtreres etter område, status, forfallsdato) som en seksjon i hvilken som helst dashbordvisning.",
"picker_desc_vacation_status": "Kompakt statusbanner for feriemodus. Trykk for å åpne innstillingene i panelet.",
"picker_desc_budget_status": "Oversikt over måneds- og årsbudsjettet for vedlikehold. Trykk for detaljer.",
"picker_desc_groups_status": "Liste over konfigurerte oppgavegrupper med antall oppgaver i hver.",
"hist_note_button": "Fullført via knapp på dashbordet",
"hist_note_todo": "Fullført fra gjøremålslisten",
"hist_note_voice": "Fullført med tale",
"hist_note_notification": "Fullført fra varselet",
"hist_note_nfc": "Fullført via NFC-brikke",
"hist_note_shopping_list": "Fullført fra handlelisten",
"hist_note_todo_mirror": "Fullført fra en speilet gjøremålsliste",
"hist_note_skipped_notification": "Hoppet over fra varselet",
"hist_note_skipped_button": "Hoppet over via knapp på dashbordet",
"hist_note_sensor_triggered": "Sensorutløser aktivert",
"hist_note_initial": "Startverdi satt da oppgaven ble opprettet",
"hist_note_auto_recovered": "Automatisk fullført: sensoren er normal igjen ({value})",
"hist_note_reset": "Tilbakestilt til {date}",
"hist_note_trigger_replaced": "Utløserentitet erstattet: {old} → {new}",
"hist_note_trigger_removed": "Sensorutløser fjernet (entitet: {entity}). Tidsplan endret til {schedule}.",
"hist_note_compound_removed": "Entiteten {entity} fjernet fra den sammensatte utløseren; gjenværende betingelser: {count}.",
"recent_activities": "Nylige aktiviteter",
"search_notes": "Søk i notater",
"avg_cost": "Gj.snittlig kostnad",
@@ -703,6 +782,7 @@
"on_complete_action_desc": "Kaller en HA-tjeneste når oppgaven fullføres — f.eks. tilbakestille en teller på enheten.",
"on_complete_action_target": "Målentitet",
"on_complete_action_target_hint": "Merk: entitetsdomenet må samsvare med tjenesten — f.eks. fungerer 'button.press' kun på button.*, 'counter.increment' kun på counter.*, 'input_button.press' kun på input_button.* osv. Ved manglende samsvar mislykkes handlingen i det stille (HA logger 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Ikke når oppgaven fullføres av seg selv (sensoren er normal igjen)",
"on_complete_action_data": "Data (JSON, valgfritt)",
"on_complete_action_test": "Valider konfigurasjon",
"on_complete_action_test_success": "✓ Konfigurasjon gyldig (handlingen utløses kun ved fullføring av oppgaven)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "«{name}»: oppgaver {before} → {after}",
"adopt_problem_adopt": "Ta i bruk valgte",
"adopt_problem_done": "Tok i bruk {tasks} problemsensor(er)",
"adopt_problem_done_one": "Tok i bruk 1 problemsensor",
"views_label": "Visninger",
"views_none": "— Ingen visning —",
"views_manage": "Lagre / administrer visninger",
@@ -1013,6 +1094,7 @@
"setups_none": "Ingen støttede enheter med ukoblede forbrukssensorer funnet.",
"setups_adopt": "Sett opp valgte",
"setups_done": "{tasks} sensor-koblede oppgaver opprettet.",
"setups_done_one": "1 sensor-koblet oppgave opprettet.",
"complete_parts_used": "Deler brukt denne gangen",
"part_delete_confirm": "Slette delen '{name}'? Lagersporing, oppgavekoblinger og en åpen kjøpspåminnelse fjernes.",
"baseline_start_value": "Startverdi (valgfritt)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "samme modell på en annen enhet",
"setups_maybe_covered": "Finnes sannsynligvis allerede som «{name}»",
"setups_already": "Finnes allerede: {names}",
"setups_reset_line": "Fullføring tilbakestiller også telleren i integrasjonen («{button}»)",
"setups_reset_enable": "— knappen slås på for dette",
"reset_offers_title": "Tilbakestill tellere ved fullføring",
"reset_offers_hint": "Disse oppgavene følger med på en teller som integrasjonen fører selv. Når de er koblet, trykker en fullføring her også på integrasjonens tilbakestillingsknapp — ellers fortsetter telleren å gå, og oppgaven forfaller straks igjen.",
"reset_offers_before": "Nå: fullføring lar telleren i {integration} gå videre",
"reset_offers_after": "Deretter: trykker også på «{button}»",
"reset_offers_renamed": "Omdøpt siden oppsettet — sjekk at oppgaven gjelder denne delen",
"reset_offers_apply": "Koble tilbakestillinger",
"reset_offers_done": "{count} oppgaver tilbakestiller nå telleren ved fullføring",
"reset_offers_done_one": "1 oppgave tilbakestiller nå telleren ved fullføring",
"setups_before_after": "Oppgaver på objektet: {before} → {after}",
"setups_new_object_count": "Nytt objekt «{name}» · oppgaver: {count}",
"schedule_preview_title": "Kommende datoer",
@@ -1046,6 +1138,7 @@
"history_auto": "Automatisk",
"battery_fleet_title": "Batteriflåte",
"battery_fleet_none_low": "Alle batterier OK — ingenting å bytte.",
"battery_fleet_progress": "{n} må byttes",
"battery_fleet_buy_now": "Kjøp nå",
"battery_fleet_soon": "Trengs snart",
"battery_fleet_soon_hint": "Estimert fra siste bytte — bestill i forkant.",
@@ -1099,8 +1192,12 @@
"dismiss": "Avvis",
"gs_label": "Kom i gang — tipsene forsvinner etter hvert som oppsettet vokser",
"gs_setups_chip": "Foreslåtte oppsett fant {n} enheter med ferdigkoblede utløsere",
"gs_setups_chip_one": "Foreslåtte oppsett fant 1 enhet med ferdigkoblede utløsere",
"gs_adopt_chip": "{n} problemsensorer kan bli vedlikeholdsoppgaver",
"gs_adopt_chip_one": "1 problemsensor kan bli en vedlikeholdsoppgave",
"gs_fleet_chip": "Ett klikk setter opp batteriflåten",
"gs_reset_chip": "{n} oppgaver kan tilbakestille telleren i integrasjonen",
"gs_reset_chip_one": "1 oppgave kan tilbakestille telleren i integrasjonen",
"cal_editor_window": "Standardvindu",
"cal_editor_window_week": "Uke (7 dager)",
"cal_editor_window_fortnight": "To uker (14 dager)",
@@ -241,6 +241,26 @@
"sort_task_name": "Taaknaam",
"all_objects": "Alle objecten",
"all_parts": "Alle onderdelen",
"all_areas": "Alle gebieden",
"areas_filter": "Gebieden filteren…",
"areas_filter_none": "Geen gebied komt overeen met het filter.",
"area_cost_year": "Kosten {year}",
"area_object_count": "{n} objecten",
"area_object_count_one": "Eén object",
"area_range_12m": "Afgelopen 12 maanden",
"area_range_all": "Volledige periode",
"area_task_filter": "Filteren op taak…",
"area_kpi_completions": "Voltooiingen",
"area_kpi_total_time": "Totale tijd",
"area_cost_per_month": "Kosten per maand",
"area_cost_per_year": "Kosten per jaar",
"area_cost_per_object": "Kosten per object",
"area_cost_share": "Aandeel",
"area_history_section": "Geschiedenis (alle objecten)",
"area_report_print": "Gebiedsrapport (PDF)",
"area_report_title": "Gebiedsrapport",
"area_report_period": "Periode",
"area_no_costs": "Geen kosten geregistreerd in deze periode.",
"no_tasks_yet": "Nog geen taken",
"add_first_task": "Eerste taak toevoegen",
"trigger_configuration": "Triggerconfiguratie",
@@ -399,11 +419,70 @@
"qr_download": "SVG downloaden",
"qr_action_view": "Onderhoudsinfo bekijken",
"qr_action_complete": "Onderhoud als voltooid markeren",
"qr_action_quick_complete": "Snel voltooien — zonder dialoogvenster",
"qr_print_quick_none": "Snel-voltooien-codes hebben snel-voltooien-standaardwaarden bij een taak nodig (taakdialoog → Snel-voltooien-standaardwaarden) — nog geen taak van de gekozen objecten heeft ze.",
"qr_url_mode": "Linktype",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Lokaal (mDNS)",
"qr_mode_server": "Server-URL",
"overview": "Overzicht",
"strat_this_month": "Deze maand",
"strat_later": "Daarna",
"strat_week": "Komende week",
"strat_fortnight": "Komende twee weken",
"strat_month": "Komende maand",
"strat_year": "Komend jaar",
"strat_other": "Overig",
"strat_status": "Stand van zaken",
"strat_empty_title": "Nog geen onderhoudsobjecten",
"strat_empty_content": "Open het Onderhoudspaneel om je eerste object toe te voegen — zwembadpomp, ventilatiefilter, voertuig, alles wat gepland onderhoud nodig heeft.",
"strat_open_panel": "Onderhoudspaneel openen",
"strat_add_object": "Object toevoegen",
"strat_not_loaded": "**Maintenance Supporter** is niet geladen. Installeer/activeer eerst de integratie.",
"strat_group_by": "Weergaven groeperen op",
"strat_group_area": "Per gebied (standaard)",
"strat_group_status": "Op status (Achterstallig / Geactiveerd / Binnenkort / OK)",
"strat_group_floor": "Per verdieping (gebruikt de HA-verdiepingen)",
"strat_group_due_date": "Op vervaldatum (Achterstallig / Vandaag / Deze week / Deze maand / Daarna)",
"strat_group_calendar": "Doorlopende kalender (komende week / twee weken / maand / jaar)",
"strat_editor_help": "De weergave \"Overzicht\" staat altijd vooraan. Lege groepen worden overgeslagen.",
"picker_name_calendar": "Maintenance Supporter — Kalender",
"picker_name_panel": "Maintenance Supporter — Paneel als kaart",
"picker_name_budget": "Maintenance Supporter — Onderhoudsbudget",
"picker_name_groups": "Maintenance Supporter — Groepen",
"picker_name_vacation": "Maintenance Supporter — Vakantiemodus",
"picker_name_battery_fleet": "Batterijvloot",
"picker_name_section": "Maintenance Supporter — Sectie",
"picker_name_vacation_status": "Maintenance Supporter — Vakantiestatus",
"picker_name_budget_status": "Maintenance Supporter — Budgetstatus",
"picker_desc_card": "Overzicht van je onderhoudstaken met snelle acties.",
"picker_desc_calendar": "Doorlopende kalender van onderhoudstaken met vensters van 7/14/30/365 dagen, bronpictogrammen en labels voor de voorspellingszekerheid.",
"picker_desc_panel": "Het volledige Maintenance Supporter-paneel als kaart — voor een paneelweergave / dashboard-subweergave zonder item in de zijbalk.",
"picker_desc_budget": "Bewerk het maand- en jaarbudget direct op het dashboard.",
"picker_desc_groups": "Maak, hernoem en verwijder taakgroepen direct op het dashboard.",
"picker_desc_vacation": "Zet de vakantiemodus aan of uit en stel de data in, direct op het dashboard.",
"picker_desc_battery_fleet": "Alle gevolgde batterijen: wat nu bijna leeg is, wat binnenkort opraakt en wat je moet kopen.",
"picker_desc_dashboard": "Automatisch gegenereerd dashboard. Groepeer weergaven op gebied, status, verdieping of vervaldatum — te kiezen in de strategie-editor of via YAML.",
"picker_desc_section": "Sluit onderhoudstaken (filterbaar op gebied, status, vervaldatum) in als sectie in elke dashboardweergave.",
"picker_desc_vacation_status": "Compacte statusbalk voor de vakantiemodus. Tik om de instellingen in het paneel te openen.",
"picker_desc_budget_status": "Overzicht van het maand- en jaarbudget voor onderhoud. Tik voor details.",
"picker_desc_groups_status": "Lijst van ingestelde taakgroepen met het aantal taken per groep.",
"hist_note_button": "Voltooid via dashboardknop",
"hist_note_todo": "Voltooid via de takenlijst",
"hist_note_voice": "Voltooid via spraak",
"hist_note_notification": "Voltooid via de melding",
"hist_note_nfc": "Voltooid via NFC-tag",
"hist_note_shopping_list": "Voltooid via de boodschappenlijst",
"hist_note_todo_mirror": "Voltooid via een gespiegelde takenlijst",
"hist_note_skipped_notification": "Overgeslagen via de melding",
"hist_note_skipped_button": "Overgeslagen via dashboardknop",
"hist_note_sensor_triggered": "Sensortrigger geactiveerd",
"hist_note_initial": "Beginwaarde ingesteld bij het aanmaken van de taak",
"hist_note_auto_recovered": "Automatisch voltooid: sensor hersteld ({value})",
"hist_note_reset": "Teruggezet naar {date}",
"hist_note_trigger_replaced": "Trigger-entiteit vervangen: {old} → {new}",
"hist_note_trigger_removed": "Sensortrigger verwijderd (entiteit was: {entity}). Schema omgezet naar {schedule}.",
"hist_note_compound_removed": "Entiteit {entity} verwijderd uit samengestelde trigger; resterende voorwaarden: {count}.",
"recent_activities": "Recente activiteiten",
"search_notes": "Notities doorzoeken",
"avg_cost": "Ø Kosten",
@@ -716,6 +795,7 @@
"groups_manage_tasks": "Taaktoewijzingen beheren…",
"groups_open_panel": "Openen in paneel",
"on_complete_action_target_hint": "Let op: het domein van de entiteit moet bij de service passen — bijv. 'button.press' werkt alleen op button.*, 'counter.increment' alleen op counter.*, 'input_button.press' alleen op input_button.* enz. Bij een mismatch mislukt de actie stil (HA logt 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Niet wanneer de taak zichzelf voltooit (de sensor is hersteld)",
"show_all_objects": "Alle objecten tonen",
"show_all_tasks": "Filter wissen — alle taken tonen",
"filter_to_overdue": "Takenlijst filteren op alleen achterstallig",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "\"{name}\": taken {before} → {after}",
"adopt_problem_adopt": "Selectie overnemen",
"adopt_problem_done": "{tasks} probleemsensor(en) overgenomen",
"adopt_problem_done_one": "1 probleemsensor overgenomen",
"views_label": "Weergaven",
"views_none": "— Geen weergave —",
"views_manage": "Weergaven opslaan/beheren",
@@ -1013,6 +1094,7 @@
"setups_none": "Geen ondersteunde apparaten met ongekoppelde verbruikssensoren gevonden.",
"setups_adopt": "Selectie instellen",
"setups_done": "{tasks} sensor-gekoppelde taken aangemaakt.",
"setups_done_one": "1 sensor-gekoppelde taak aangemaakt.",
"complete_parts_used": "Deze keer gebruikte onderdelen",
"part_delete_confirm": "Onderdeel '{name}' verwijderen? De voorraadregistratie, taakkoppelingen en een openstaande koopherinnering worden verwijderd.",
"baseline_start_value": "Startwaarde (optioneel)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "zelfde model op een ander apparaat",
"setups_maybe_covered": "Waarschijnlijk al aanwezig als \"{name}\"",
"setups_already": "Al aanwezig: {names}",
"setups_reset_line": "Voltooien reset ook de teller in de integratie (“{button}”)",
"setups_reset_enable": "— de knop wordt hiervoor ingeschakeld",
"reset_offers_title": "Tellers resetten bij voltooien",
"reset_offers_hint": "Deze taken volgen een teller die de integratie zelf bijhoudt. Gekoppeld drukt het voltooien van de taak hier ook op de resetknop van de integratie — anders loopt de teller door en is de taak meteen weer aan de beurt.",
"reset_offers_before": "Nu: voltooien laat de teller in {integration} doorlopen",
"reset_offers_after": "Daarna: drukt ook op “{button}”",
"reset_offers_renamed": "Hernoemd sinds het instellen — controleer of deze taak bij dit onderdeel hoort",
"reset_offers_apply": "Resets koppelen",
"reset_offers_done": "{count} taken resetten hun teller nu bij voltooien",
"reset_offers_done_one": "1 taak reset haar teller nu bij voltooien",
"setups_before_after": "Taken van het object: {before} → {after}",
"setups_new_object_count": "Nieuw object \"{name}\" · taken: {count}",
"schedule_preview_title": "Volgende data",
@@ -1046,6 +1138,7 @@
"history_auto": "Automatisch",
"battery_fleet_title": "Batterijvloot",
"battery_fleet_none_low": "Alle batterijen OK — niets te vervangen.",
"battery_fleet_progress": "{n} te vervangen",
"battery_fleet_buy_now": "Nu kopen",
"battery_fleet_soon": "Binnenkort nodig",
"battery_fleet_soon_hint": "Geschat op basis van de laatste vervanging — bestel vooruit.",
@@ -1099,8 +1192,12 @@
"dismiss": "Verbergen",
"gs_label": "Aan de slag — deze tips verdwijnen naarmate je installatie groeit",
"gs_setups_chip": "Voorgestelde setups: {n} apparaten met vooraf ingestelde triggers gevonden",
"gs_setups_chip_one": "Voorgestelde setups: 1 apparaat met vooraf ingestelde triggers gevonden",
"gs_adopt_chip": "{n} probleemsensoren kunnen onderhoudstaken worden",
"gs_adopt_chip_one": "1 probleemsensor kan een onderhoudstaak worden",
"gs_fleet_chip": "Eén klik stelt het batterijpark in",
"gs_reset_chip": "{n} taken kunnen hun teller in de integratie resetten",
"gs_reset_chip_one": "1 taak kan haar teller in de integratie resetten",
"cal_editor_window": "Standaardvenster",
"cal_editor_window_week": "Week (7 dagen)",
"cal_editor_window_fortnight": "Twee weken (14 dagen)",
@@ -241,6 +241,26 @@
"sort_task_name": "Nazwa zadania",
"all_objects": "Wszystkie obiekty",
"all_parts": "Wszystkie części",
"all_areas": "Wszystkie obszary",
"areas_filter": "Filtruj obszary…",
"areas_filter_none": "Żaden obszar nie pasuje do filtra.",
"area_cost_year": "Koszt {year}",
"area_object_count": "Obiekty: {n}",
"area_object_count_one": "1 obiekt",
"area_range_12m": "Ostatnie 12 miesięcy",
"area_range_all": "Cały okres",
"area_task_filter": "Filtruj według zadania…",
"area_kpi_completions": "Wykonania",
"area_kpi_total_time": "Łączny czas",
"area_cost_per_month": "Koszt według miesięcy",
"area_cost_per_year": "Koszt według lat",
"area_cost_per_object": "Koszt według obiektów",
"area_cost_share": "Udział",
"area_history_section": "Historia (wszystkie obiekty)",
"area_report_print": "Raport obszaru (PDF)",
"area_report_title": "Raport obszaru",
"area_report_period": "Okres",
"area_no_costs": "Brak zarejestrowanych kosztów w tym okresie.",
"no_tasks_yet": "Jeszcze brak zadań",
"add_first_task": "Dodaj pierwsze zadanie",
"trigger_configuration": "Konfiguracja wyzwalacza",
@@ -399,11 +419,70 @@
"qr_download": "Pobierz SVG",
"qr_action_view": "Wyświetl informacje o konserwacji",
"qr_action_complete": "Oznacz konserwację jako wykonaną",
"qr_action_quick_complete": "Szybkie zakończenie — bez okna dialogowego",
"qr_print_quick_none": "Kody szybkiego zakończenia wymagają wartości domyślnych szybkiego zakończenia w zadaniu (okno zadania → Wartości domyślne szybkiego zakończenia) — żadne zadanie wybranych obiektów ich jeszcze nie ma.",
"qr_url_mode": "Typ linku",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Lokalny (mDNS)",
"qr_mode_server": "URL serwera",
"overview": "Przegląd",
"strat_this_month": "W tym miesiącu",
"strat_later": "Później",
"strat_week": "Tydzień",
"strat_fortnight": "Dwa tygodnie",
"strat_month": "Miesiąc",
"strat_year": "Rok",
"strat_other": "Inne",
"strat_status": "Stan",
"strat_empty_title": "Brak obiektów konserwacji",
"strat_empty_content": "Otwórz panel Konserwacja, aby dodać pierwszy obiekt — pompę basenową, filtr wentylacji, pojazd, wszystko, co wymaga regularnej obsługi.",
"strat_open_panel": "Otwórz panel Konserwacja",
"strat_add_object": "Dodaj obiekt",
"strat_not_loaded": "**Maintenance Supporter** nie jest załadowany. Najpierw zainstaluj/włącz integrację.",
"strat_group_by": "Grupuj widoki wg",
"strat_group_area": "Wg obszaru (domyślnie)",
"strat_group_status": "Wg statusu (Zaległe / Wyzwolone / Wkrótce / OK)",
"strat_group_floor": "Wg piętra (używa pięter HA)",
"strat_group_due_date": "Wg terminu (Zaległe / Dzisiaj / W tym tygodniu / W tym miesiącu / Później)",
"strat_group_calendar": "Kalendarz kroczący (Tydzień / Dwa tygodnie / Miesiąc / Rok)",
"strat_editor_help": "Widok „Przegląd” jest zawsze pierwszy. Puste grupy są pomijane.",
"picker_name_calendar": "Maintenance Supporter — Kalendarz",
"picker_name_panel": "Maintenance Supporter — Panel jako karta",
"picker_name_budget": "Maintenance Supporter — Budżet konserwacji",
"picker_name_groups": "Maintenance Supporter — Grupy",
"picker_name_vacation": "Maintenance Supporter — Tryb urlopowy",
"picker_name_battery_fleet": "Flota baterii",
"picker_name_section": "Maintenance Supporter — Sekcja",
"picker_name_vacation_status": "Maintenance Supporter — Status urlopu",
"picker_name_budget_status": "Maintenance Supporter — Status budżetu",
"picker_desc_card": "Przegląd zadań konserwacyjnych z szybkimi akcjami.",
"picker_desc_calendar": "Kalendarz kroczący zadań konserwacyjnych z oknami 7/14/30/365 dni, ikonami źródła i znacznikami pewności prognozy.",
"picker_desc_panel": "Pełny panel Maintenance Supporter jako karta — do widoku panelu / podwidoku pulpitu bez wpisu na pasku bocznym.",
"picker_desc_budget": "Edytuj budżet miesięczny i roczny bezpośrednio na pulpicie.",
"picker_desc_groups": "Twórz, zmieniaj nazwy i usuwaj grupy zadań bezpośrednio na pulpicie.",
"picker_desc_vacation": "Włączaj i wyłączaj tryb urlopowy oraz ustawiaj jego daty bezpośrednio na pulpicie.",
"picker_desc_battery_fleet": "Wszystkie śledzone baterie: co jest teraz słabe, co wkrótce się wyczerpie i co kupić.",
"picker_desc_dashboard": "Automatycznie generowany pulpit. Grupuj widoki wg obszaru, statusu, piętra lub terminu — wybór w edytorze strategii lub w YAML.",
"picker_desc_section": "Osadź zadania konserwacyjne (z filtrem wg obszaru, statusu, terminu) jako sekcję w dowolnym widoku pulpitu.",
"picker_desc_vacation_status": "Kompaktowy baner stanu trybu urlopowego. Dotknij, aby otworzyć ustawienia w panelu.",
"picker_desc_budget_status": "Przegląd miesięcznego i rocznego budżetu konserwacji. Dotknij, aby zobaczyć szczegóły.",
"picker_desc_groups_status": "Lista skonfigurowanych grup zadań z liczbą zadań w każdej.",
"hist_note_button": "Wykonano przyciskiem na pulpicie",
"hist_note_todo": "Wykonano z listy zadań",
"hist_note_voice": "Wykonano głosowo",
"hist_note_notification": "Wykonano z powiadomienia",
"hist_note_nfc": "Wykonano tagiem NFC",
"hist_note_shopping_list": "Wykonano z listy zakupów",
"hist_note_todo_mirror": "Wykonano z odzwierciedlonej listy zadań",
"hist_note_skipped_notification": "Pominięto z powiadomienia",
"hist_note_skipped_button": "Pominięto przyciskiem na pulpicie",
"hist_note_sensor_triggered": "Wyzwalacz czujnika aktywowany",
"hist_note_initial": "Wartość początkowa ustawiona przy tworzeniu zadania",
"hist_note_auto_recovered": "Wykonano automatycznie: czujnik wrócił do normy ({value})",
"hist_note_reset": "Zresetowano na {date}",
"hist_note_trigger_replaced": "Zastąpiono encję wyzwalacza: {old} → {new}",
"hist_note_trigger_removed": "Usunięto wyzwalacz czujnika (encja: {entity}). Harmonogram zmieniono na {schedule}.",
"hist_note_compound_removed": "Usunięto encję {entity} z wyzwalacza złożonego; pozostałe warunki: {count}.",
"recent_activities": "Ostatnie aktywności",
"search_notes": "Szukaj w notatkach",
"avg_cost": "Śr. koszt",
@@ -716,6 +795,7 @@
"groups_manage_tasks": "Zarządzaj przypisaniami zadań…",
"groups_open_panel": "Otwórz w panelu",
"on_complete_action_target_hint": "Uwaga: domena encji musi pasować do usługi — np. 'button.press' działa tylko na button.*, 'counter.increment' tylko na counter.*, 'input_button.press' tylko na input_button.* itd. W przypadku niezgodności akcja po cichu się nie wykona (HA zapisze w dzienniku 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Nie, gdy zadanie wykona się samo (jego czujnik wrócił do normy)",
"show_all_objects": "Pokaż wszystkie obiekty",
"show_all_tasks": "Wyczyść filtr — pokaż wszystkie zadania",
"filter_to_overdue": "Filtruj listę tylko do zaległych",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "„{name}”: zadania {before} → {after}",
"adopt_problem_adopt": "Przejmij zaznaczone",
"adopt_problem_done": "Przejęto {tasks} czujnik(ów) problemów",
"adopt_problem_done_one": "Przejęto 1 czujnik problemów",
"views_label": "Widoki",
"views_none": "— Brak widoku —",
"views_manage": "Zapisz / zarządzaj widokami",
@@ -1013,6 +1094,7 @@
"setups_none": "Nie znaleziono obsługiwanych urządzeń z niepodłączonymi czujnikami materiałów.",
"setups_adopt": "Skonfiguruj wybrane",
"setups_done": "Utworzono {tasks} zadań powiązanych z czujnikami.",
"setups_done_one": "Utworzono 1 zadanie powiązane z czujnikami.",
"complete_parts_used": "Części użyte tym razem",
"part_delete_confirm": "Usunąć część '{name}'? Zostaną usunięte śledzenie stanu, powiązania z zadaniami i otwarte przypomnienie o zakupie.",
"baseline_start_value": "Wartość początkowa (opcjonalnie)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "ten sam model na innym urządzeniu",
"setups_maybe_covered": "Prawdopodobnie już istnieje jako „{name}”",
"setups_already": "Już istnieje: {names}",
"setups_reset_line": "Wykonanie resetuje też licznik w integracji („{button}”)",
"setups_reset_enable": "— przycisk zostanie w tym celu włączony",
"reset_offers_title": "Resetuj liczniki po wykonaniu",
"reset_offers_hint": "Te zadania obserwują licznik, który integracja prowadzi sama. Po połączeniu wykonanie zadania tutaj naciska też przycisk resetu integracji — w przeciwnym razie licznik biegnie dalej, a zadanie od razu znów jest do zrobienia.",
"reset_offers_before": "Teraz: po wykonaniu licznik w {integration} liczy dalej",
"reset_offers_after": "Potem: naciska też „{button}”",
"reset_offers_renamed": "Nazwa zmieniona od konfiguracji — sprawdź, czy to zadanie dotyczy tej części",
"reset_offers_apply": "Połącz resety",
"reset_offers_done": "Zadania resetujące licznik po wykonaniu: {count}",
"reset_offers_done_one": "1 zadanie resetuje teraz licznik po wykonaniu",
"setups_before_after": "Zadania obiektu: {before} → {after}",
"setups_new_object_count": "Nowy obiekt „{name}” · zadania: {count}",
"schedule_preview_title": "Najbliższe terminy",
@@ -1046,6 +1138,7 @@
"history_auto": "Automatycznie",
"battery_fleet_title": "Flota baterii",
"battery_fleet_none_low": "Wszystkie baterie OK — nic do wymiany.",
"battery_fleet_progress": "Do wymiany: {n}",
"battery_fleet_buy_now": "Kup teraz",
"battery_fleet_soon": "Wkrótce potrzebne",
"battery_fleet_soon_hint": "Szacowane wg ostatniej wymiany — zamów z wyprzedzeniem.",
@@ -1099,8 +1192,12 @@
"dismiss": "Odrzuć",
"gs_label": "Pierwsze kroki — te wskazówki znikają wraz z rozwojem konfiguracji",
"gs_setups_chip": "Sugerowane konfiguracje: znaleziono {n} urządzeń z gotowymi wyzwalaczami",
"gs_setups_chip_one": "Sugerowane konfiguracje: znaleziono 1 urządzenie z gotowymi wyzwalaczami",
"gs_adopt_chip": "{n} czujników problemów może stać się zadaniami konserwacji",
"gs_adopt_chip_one": "1 czujnik problemów może stać się zadaniem konserwacji",
"gs_fleet_chip": "Jedno kliknięcie konfiguruje flotę baterii",
"gs_reset_chip": "{n} zadań może resetować licznik w integracji",
"gs_reset_chip_one": "1 zadanie może resetować licznik w integracji",
"cal_editor_window": "Okno domyślne",
"cal_editor_window_week": "Tydzień (7 dni)",
"cal_editor_window_fortnight": "Dwa tygodnie (14 dni)",
@@ -243,6 +243,26 @@
"sort_task_name": "Nome da tarefa",
"all_objects": "Todos os objetos",
"all_parts": "Todas as peças",
"all_areas": "Todas as áreas",
"areas_filter": "Filtrar áreas…",
"areas_filter_none": "Nenhuma área corresponde ao filtro.",
"area_cost_year": "Custo {year}",
"area_object_count": "{n} objetos",
"area_object_count_one": "1 objeto",
"area_range_12m": "Últimos 12 meses",
"area_range_all": "Todo o período",
"area_task_filter": "Filtrar por tarefa…",
"area_kpi_completions": "Conclusões",
"area_kpi_total_time": "Tempo total",
"area_cost_per_month": "Custo por mês",
"area_cost_per_year": "Custo por ano",
"area_cost_per_object": "Custo por objeto",
"area_cost_share": "Participação",
"area_history_section": "Histórico (todos os objetos)",
"area_report_print": "Relatório da área (PDF)",
"area_report_title": "Relatório da área",
"area_report_period": "Período",
"area_no_costs": "Nenhum custo registrado neste período.",
"no_tasks_yet": "Ainda sem tarefas",
"add_first_task": "Adicionar a primeira tarefa",
"trigger_configuration": "Configuração do gatilho",
@@ -401,11 +421,70 @@
"qr_download": "Baixar SVG",
"qr_action_view": "Ver informações de manutenção",
"qr_action_complete": "Marcar a manutenção como concluída",
"qr_action_quick_complete": "Conclusão rápida — sem janela",
"qr_print_quick_none": "Os códigos de conclusão rápida precisam de padrões de conclusão rápida em uma tarefa (janela da tarefa → Padrões de conclusão rápida) — nenhuma tarefa dos objetos escolhidos os tem ainda.",
"qr_url_mode": "Tipo de link",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Local (mDNS)",
"qr_mode_server": "URL do servidor",
"overview": "Visão geral",
"strat_this_month": "Este mês",
"strat_later": "Mais tarde",
"strat_week": "Semana",
"strat_fortnight": "Quinzena",
"strat_month": "Mês",
"strat_year": "Ano",
"strat_other": "Outros",
"strat_status": "Situação",
"strat_empty_title": "Ainda não há objetos de manutenção",
"strat_empty_content": "Abra o painel de Manutenção para adicionar seu primeiro objeto — bomba da piscina, filtro do ar-condicionado, veículo, qualquer coisa que precise de cuidados programados.",
"strat_open_panel": "Abrir o painel de Manutenção",
"strat_add_object": "Adicionar objeto",
"strat_not_loaded": "O **Maintenance Supporter** não está carregado. Instale/ative a integração primeiro.",
"strat_group_by": "Agrupar visualizações por",
"strat_group_area": "Por área (padrão)",
"strat_group_status": "Por status (Atrasada / Acionada / Vence em breve / OK)",
"strat_group_floor": "Por andar (usa os andares do HA)",
"strat_group_due_date": "Por vencimento (Atrasada / Hoje / Esta semana / Este mês / Mais tarde)",
"strat_group_calendar": "Calendário contínuo (Semana / Quinzena / Mês / Ano)",
"strat_editor_help": "A visualização \"Visão geral\" é sempre a primeira. Grupos vazios são ignorados.",
"picker_name_calendar": "Maintenance Supporter — Calendário",
"picker_name_panel": "Maintenance Supporter — Painel como cartão",
"picker_name_budget": "Maintenance Supporter — Orçamento de manutenção",
"picker_name_groups": "Maintenance Supporter — Grupos",
"picker_name_vacation": "Maintenance Supporter — Modo férias",
"picker_name_battery_fleet": "Frota de baterias",
"picker_name_section": "Maintenance Supporter — Seção",
"picker_name_vacation_status": "Maintenance Supporter — Status de férias",
"picker_name_budget_status": "Maintenance Supporter — Status do orçamento",
"picker_desc_card": "Visão geral das suas tarefas de manutenção com ações rápidas.",
"picker_desc_calendar": "Calendário contínuo das tarefas de manutenção com janelas de 7/14/30/365 dias, ícones de origem e selos de confiança da previsão.",
"picker_desc_panel": "O painel completo do Maintenance Supporter como cartão — para uma visualização do tipo painel ou uma subvisualização, sem a entrada na barra lateral.",
"picker_desc_budget": "Edite o orçamento mensal e anual direto no painel.",
"picker_desc_groups": "Crie, renomeie e exclua grupos de tarefas direto no painel.",
"picker_desc_vacation": "Ative ou desative o modo férias e defina as datas direto no painel.",
"picker_desc_battery_fleet": "Todas as baterias monitoradas: o que está fraco agora, o que acaba em breve e o que comprar.",
"picker_desc_dashboard": "Painel gerado automaticamente. Agrupe as visualizações por área, status, andar ou vencimento — escolhido no editor da estratégia ou em YAML.",
"picker_desc_section": "Incorpore as tarefas de manutenção (filtráveis por área, status, vencimento) como seção em qualquer visualização do painel.",
"picker_desc_vacation_status": "Banner compacto com o status do modo férias. Toque para abrir as configurações no painel.",
"picker_desc_budget_status": "Visão geral do orçamento de manutenção mensal e anual. Toque para ver os detalhes.",
"picker_desc_groups_status": "Lista dos grupos de tarefas configurados com a quantidade de tarefas de cada um.",
"hist_note_button": "Concluída por um botão do painel",
"hist_note_todo": "Concluída pela lista de tarefas",
"hist_note_voice": "Concluída por voz",
"hist_note_notification": "Concluída pela notificação",
"hist_note_nfc": "Concluída por tag NFC",
"hist_note_shopping_list": "Concluída pela lista de compras",
"hist_note_todo_mirror": "Concluída por uma lista de tarefas espelhada",
"hist_note_skipped_notification": "Pulada pela notificação",
"hist_note_skipped_button": "Pulada por um botão do painel",
"hist_note_sensor_triggered": "Gatilho do sensor acionado",
"hist_note_initial": "Valor inicial definido na criação da tarefa",
"hist_note_auto_recovered": "Concluída automaticamente: o sensor se recuperou ({value})",
"hist_note_reset": "Redefinida para {date}",
"hist_note_trigger_replaced": "Entidade do gatilho substituída: {old} → {new}",
"hist_note_trigger_removed": "Gatilho do sensor removido (entidade era: {entity}). Agendamento convertido para {schedule}.",
"hist_note_compound_removed": "Entidade {entity} removida do gatilho composto; condições restantes: {count}.",
"recent_activities": "Atividades recentes",
"search_notes": "Pesquisar observações",
"avg_cost": "Custo médio",
@@ -709,6 +788,7 @@
"on_complete_action_desc": "Chama um serviço do HA quando a tarefa é concluída — ex.: zerar um contador no dispositivo.",
"on_complete_action_target": "Entidade alvo",
"on_complete_action_target_hint": "Atenção: o domínio da entidade deve corresponder ao serviço — ex.: 'button.press' só funciona em button.*, 'counter.increment' só em counter.*, 'input_button.press' só em input_button.* etc. Em caso de divergência, a ação falhará silenciosamente (o HA registra 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Não quando a tarefa se conclui sozinha (o sensor se recuperou)",
"on_complete_action_data": "Dados (JSON, opcional)",
"on_complete_action_test": "Validar configuração",
"on_complete_action_test_success": "✓ Configuração válida (a ação só disparará na conclusão da tarefa)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "\"{name}\": tarefas {before} → {after}",
"adopt_problem_adopt": "Adotar selecionados",
"adopt_problem_done": "{tasks} sensor(es) de problema adotado(s)",
"adopt_problem_done_one": "1 sensor de problema adotado",
"views_label": "Visualizações",
"views_none": "— Nenhuma visualização —",
"views_manage": "Salvar / gerenciar visualizações",
@@ -1013,6 +1094,7 @@
"setups_none": "Nenhum dispositivo compatível com sensores de consumíveis ainda não conectados foi encontrado.",
"setups_adopt": "Configurar selecionados",
"setups_done": "{tasks} tarefas conectadas a sensores foram criadas.",
"setups_done_one": "1 tarefa conectada a sensores foi criada.",
"complete_parts_used": "Peças usadas desta vez",
"part_delete_confirm": "Excluir a peça '{name}'? O controle de estoque, os vínculos com tarefas e qualquer lembrete de compra aberto serão removidos.",
"baseline_start_value": "Leitura inicial (opcional)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "mesmo modelo em outro dispositivo",
"setups_maybe_covered": "Provavelmente já existe como \"{name}\"",
"setups_already": "Já existe: {names}",
"setups_reset_line": "Concluí-la também zera o contador na integração (“{button}”)",
"setups_reset_enable": "— para isso, o botão será ativado",
"reset_offers_title": "Zerar contadores ao concluir",
"reset_offers_hint": "Estas tarefas acompanham um contador que a própria integração mantém. Depois de conectadas, concluir a tarefa aqui também pressiona o botão de zerar da integração — senão o contador continua correndo e a tarefa vence de novo logo em seguida.",
"reset_offers_before": "Agora: concluí-la deixa o contador em {integration} correndo",
"reset_offers_after": "Depois: também pressiona “{button}”",
"reset_offers_renamed": "Renomeada desde a configuração — confira se esta tarefa é desta peça",
"reset_offers_apply": "Conectar zeragem",
"reset_offers_done": "{count} tarefas agora zeram o contador ao concluir",
"reset_offers_done_one": "1 tarefa agora zera o contador ao concluir",
"setups_before_after": "Tarefas do objeto: {before} → {after}",
"setups_new_object_count": "Novo objeto \"{name}\" · tarefas: {count}",
"schedule_preview_title": "Próximas datas",
@@ -1046,6 +1138,7 @@
"history_auto": "Automática",
"battery_fleet_title": "Frota de baterias",
"battery_fleet_none_low": "Todas as baterias OK — nada a substituir.",
"battery_fleet_progress": "{n} para trocar",
"battery_fleet_buy_now": "Comprar agora",
"battery_fleet_soon": "Necessárias em breve",
"battery_fleet_soon_hint": "Previsto a partir da data da última troca — compre com antecedência.",
@@ -1099,8 +1192,12 @@
"dismiss": "Dispensar",
"gs_label": "Primeiros passos — estas dicas somem conforme a configuração cresce",
"gs_setups_chip": "Configurações sugeridas: {n} dispositivos com gatilhos pré-configurados",
"gs_setups_chip_one": "Configurações sugeridas: 1 dispositivo com gatilhos pré-configurados",
"gs_adopt_chip": "{n} sensores de problema podem virar tarefas de manutenção",
"gs_adopt_chip_one": "1 sensor de problema pode virar uma tarefa de manutenção",
"gs_fleet_chip": "Um clique configura a frota de pilhas",
"gs_reset_chip": "{n} tarefas podem zerar o contador na integração",
"gs_reset_chip_one": "1 tarefa pode zerar o contador na integração",
"cal_editor_window": "Janela padrão",
"cal_editor_window_week": "Semana (7 dias)",
"cal_editor_window_fortnight": "Quinzena (14 dias)",
@@ -241,6 +241,26 @@
"sort_task_name": "Nome da tarefa",
"all_objects": "Todos os objetos",
"all_parts": "Todas as peças",
"all_areas": "Todas as áreas",
"areas_filter": "Filtrar áreas…",
"areas_filter_none": "Nenhuma área corresponde ao filtro.",
"area_cost_year": "Custo {year}",
"area_object_count": "{n} objetos",
"area_object_count_one": "1 objeto",
"area_range_12m": "Últimos 12 meses",
"area_range_all": "Todo o período",
"area_task_filter": "Filtrar por tarefa…",
"area_kpi_completions": "Conclusões",
"area_kpi_total_time": "Tempo total",
"area_cost_per_month": "Custo por mês",
"area_cost_per_year": "Custo por ano",
"area_cost_per_object": "Custo por objeto",
"area_cost_share": "Proporção",
"area_history_section": "Histórico (todos os objetos)",
"area_report_print": "Relatório da área (PDF)",
"area_report_title": "Relatório da área",
"area_report_period": "Período",
"area_no_costs": "Sem custos registados neste período.",
"no_tasks_yet": "Ainda sem tarefas",
"add_first_task": "Adicionar primeira tarefa",
"trigger_configuration": "Configuração do acionador",
@@ -399,11 +419,70 @@
"qr_download": "Transferir SVG",
"qr_action_view": "Ver informações de manutenção",
"qr_action_complete": "Marcar manutenção como concluída",
"qr_action_quick_complete": "Conclusão rápida — sem janela",
"qr_print_quick_none": "Os códigos de conclusão rápida precisam de valores predefinidos de conclusão rápida numa tarefa (janela da tarefa → Valores predefinidos de conclusão rápida) — nenhuma tarefa dos objetos escolhidos os tem ainda.",
"qr_url_mode": "Tipo de ligação",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Local (mDNS)",
"qr_mode_server": "URL do servidor",
"overview": "Visão geral",
"strat_this_month": "Este mês",
"strat_later": "Mais tarde",
"strat_week": "Semana",
"strat_fortnight": "Quinzena",
"strat_month": "Mês",
"strat_year": "Ano",
"strat_other": "Outros",
"strat_status": "Estado",
"strat_empty_title": "Ainda sem objetos de manutenção",
"strat_empty_content": "Abra o painel Manutenção para adicionar o seu primeiro objeto — bomba da piscina, filtro de climatização, veículo, tudo o que precise de cuidados programados.",
"strat_open_panel": "Abrir o painel Manutenção",
"strat_add_object": "Adicionar objeto",
"strat_not_loaded": "O **Maintenance Supporter** não está carregado. Instale/ative primeiro a integração.",
"strat_group_by": "Agrupar vistas por",
"strat_group_area": "Por área (predefinido)",
"strat_group_status": "Por estado (Atrasada / Acionada / Próxima / OK)",
"strat_group_floor": "Por piso (usa os pisos do HA)",
"strat_group_due_date": "Por vencimento (Atrasada / Hoje / Esta semana / Este mês / Mais tarde)",
"strat_group_calendar": "Calendário deslizante (Semana / Quinzena / Mês / Ano)",
"strat_editor_help": "A vista «Visão geral» é sempre a primeira. Os grupos vazios são ignorados.",
"picker_name_calendar": "Maintenance Supporter — Calendário",
"picker_name_panel": "Maintenance Supporter — Painel como cartão",
"picker_name_budget": "Maintenance Supporter — Orçamento de manutenção",
"picker_name_groups": "Maintenance Supporter — Grupos",
"picker_name_vacation": "Maintenance Supporter — Modo de férias",
"picker_name_battery_fleet": "Frota de baterias",
"picker_name_section": "Maintenance Supporter — Secção",
"picker_name_vacation_status": "Maintenance Supporter — Estado das férias",
"picker_name_budget_status": "Maintenance Supporter — Estado do orçamento",
"picker_desc_card": "Visão geral das suas tarefas de manutenção com ações rápidas.",
"picker_desc_calendar": "Calendário deslizante das tarefas de manutenção com janelas de 7/14/30/365 dias, ícones de origem e etiquetas de confiança da previsão.",
"picker_desc_panel": "O painel completo do Maintenance Supporter como cartão — para uma vista do tipo painel ou uma subvista, sem entrada na barra lateral.",
"picker_desc_budget": "Edite o orçamento mensal e anual diretamente no painel.",
"picker_desc_groups": "Crie, mude o nome e elimine grupos de tarefas diretamente no painel.",
"picker_desc_vacation": "Ative ou desative o modo de férias e defina as datas diretamente no painel.",
"picker_desc_battery_fleet": "Todas as pilhas monitorizadas: o que está fraco agora, o que vai acabar em breve e o que comprar.",
"picker_desc_dashboard": "Painel gerado automaticamente. Agrupe as vistas por área, estado, piso ou vencimento — a escolher no editor da estratégia ou em YAML.",
"picker_desc_section": "Incorpore as tarefas de manutenção (filtráveis por área, estado, vencimento) como secção em qualquer vista do painel.",
"picker_desc_vacation_status": "Faixa compacta com o estado do modo de férias. Toque para abrir as definições no painel.",
"picker_desc_budget_status": "Visão geral do orçamento de manutenção mensal e anual. Toque para ver detalhes.",
"picker_desc_groups_status": "Lista dos grupos de tarefas configurados com o número de tarefas de cada um.",
"hist_note_button": "Concluída através de um botão do painel",
"hist_note_todo": "Concluída a partir da lista de tarefas",
"hist_note_voice": "Concluída por voz",
"hist_note_notification": "Concluída a partir da notificação",
"hist_note_nfc": "Concluída com uma etiqueta NFC",
"hist_note_shopping_list": "Concluída a partir da lista de compras",
"hist_note_todo_mirror": "Concluída a partir de uma lista de tarefas espelhada",
"hist_note_skipped_notification": "Saltada a partir da notificação",
"hist_note_skipped_button": "Saltada através de um botão do painel",
"hist_note_sensor_triggered": "Gatilho do sensor acionado",
"hist_note_initial": "Valor inicial definido ao criar a tarefa",
"hist_note_auto_recovered": "Concluída automaticamente: sensor recuperado ({value})",
"hist_note_reset": "Reposta para {date}",
"hist_note_trigger_replaced": "Entidade do gatilho substituída: {old} → {new}",
"hist_note_trigger_removed": "Gatilho de sensor removido (entidade: {entity}). Agenda convertida para {schedule}.",
"hist_note_compound_removed": "Entidade {entity} removida do gatilho composto; condições restantes: {count}.",
"recent_activities": "Atividades recentes",
"search_notes": "Pesquisar notas",
"avg_cost": "Ø Custo",
@@ -716,6 +795,7 @@
"groups_manage_tasks": "Gerir atribuições de tarefas…",
"groups_open_panel": "Abrir no painel",
"on_complete_action_target_hint": "Nota: o domínio da entidade tem de corresponder ao serviço — p. ex. 'button.press' só funciona em button.*, 'counter.increment' só em counter.*, 'input_button.press' só em input_button.* etc. Em caso de incompatibilidade, a ação falha silenciosamente (o HA regista 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Não quando a tarefa se conclui sozinha (o sensor recuperou)",
"show_all_objects": "Mostrar todos os objetos",
"show_all_tasks": "Limpar filtro — mostrar todas as tarefas",
"filter_to_overdue": "Filtrar a lista apenas para em atraso",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "«{name}»: tarefas {before} → {after}",
"adopt_problem_adopt": "Adotar selecionados",
"adopt_problem_done": "{tasks} sensor(es) de problema adotado(s)",
"adopt_problem_done_one": "1 sensor de problema adotado",
"views_label": "Vistas",
"views_none": "— Sem vista —",
"views_manage": "Guardar / gerir vistas",
@@ -1013,6 +1094,7 @@
"setups_none": "Nenhum dispositivo suportado com sensores de consumíveis por ligar.",
"setups_adopt": "Configurar seleção",
"setups_done": "{tasks} tarefas ligadas a sensores criadas.",
"setups_done_one": "1 tarefa ligada a sensores criada.",
"complete_parts_used": "Peças usadas desta vez",
"part_delete_confirm": "Eliminar a peça '{name}'? O controlo de stock, as ligações a tarefas e qualquer lembrete de compra aberto serão removidos.",
"baseline_start_value": "Valor inicial (opcional)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "mesmo modelo noutro dispositivo",
"setups_maybe_covered": "Provavelmente já existe como «{name}»",
"setups_already": "Já existe: {names}",
"setups_reset_line": "Concluí-la também reinicia o contador na integração («{button}»)",
"setups_reset_enable": "— para isso, o botão será ativado",
"reset_offers_title": "Reiniciar contadores na conclusão",
"reset_offers_hint": "Estas tarefas acompanham um contador que a própria integração mantém. Uma vez ligadas, concluir a tarefa aqui também prime o botão de reinício da integração — caso contrário, o contador continua a contar e a tarefa volta logo a vencer.",
"reset_offers_before": "Agora: concluí-la deixa o contador em {integration} a contar",
"reset_offers_after": "Depois: também prime «{button}»",
"reset_offers_renamed": "Renomeada desde a configuração — confirme que esta tarefa corresponde a esta peça",
"reset_offers_apply": "Ligar reinícios",
"reset_offers_done": "{count} tarefas passam a reiniciar o contador na conclusão",
"reset_offers_done_one": "1 tarefa passa a reiniciar o contador na conclusão",
"setups_before_after": "Tarefas do objeto: {before} → {after}",
"setups_new_object_count": "Novo objeto «{name}» · tarefas: {count}",
"schedule_preview_title": "Próximas datas",
@@ -1046,6 +1138,7 @@
"history_auto": "Automático",
"battery_fleet_title": "Frota de baterias",
"battery_fleet_none_low": "Todas as baterias OK — nada a substituir.",
"battery_fleet_progress": "{n} a substituir",
"battery_fleet_buy_now": "Comprar agora",
"battery_fleet_soon": "Necessário em breve",
"battery_fleet_soon_hint": "Estimado pela última substituição — encomende com antecedência.",
@@ -1099,8 +1192,12 @@
"dismiss": "Dispensar",
"gs_label": "Primeiros passos — estas dicas desaparecem à medida que a configuração cresce",
"gs_setups_chip": "Configurações sugeridas: {n} dispositivos com gatilhos pré-configurados",
"gs_setups_chip_one": "Configurações sugeridas: 1 dispositivo com gatilhos pré-configurados",
"gs_adopt_chip": "{n} sensores de problema podem tornar-se tarefas de manutenção",
"gs_adopt_chip_one": "1 sensor de problema pode tornar-se uma tarefa de manutenção",
"gs_fleet_chip": "Um clique configura a frota de pilhas",
"gs_reset_chip": "{n} tarefas podem reiniciar o contador na integração",
"gs_reset_chip_one": "1 tarefa pode reiniciar o contador na integração",
"cal_editor_window": "Janela predefinida",
"cal_editor_window_week": "Semana (7 dias)",
"cal_editor_window_fortnight": "Quinzena (14 dias)",
@@ -240,6 +240,26 @@
"sort_task_name": "Имя задачи",
"all_objects": "Все объекты",
"all_parts": "Все детали",
"all_areas": "Все зоны",
"areas_filter": "Фильтр зон…",
"areas_filter_none": "Нет зон, соответствующих фильтру.",
"area_cost_year": "Стоимость за {year}",
"area_object_count": "Объектов: {n}",
"area_object_count_one": "1 объект",
"area_range_12m": "Последние 12 месяцев",
"area_range_all": "За всё время",
"area_task_filter": "Фильтр по задаче…",
"area_kpi_completions": "Выполнения",
"area_kpi_total_time": "Общее время",
"area_cost_per_month": "Стоимость по месяцам",
"area_cost_per_year": "Стоимость по годам",
"area_cost_per_object": "Стоимость по объектам",
"area_cost_share": "Доля",
"area_history_section": "История (все объекты)",
"area_report_print": "Отчёт по зоне (PDF)",
"area_report_title": "Отчёт по зоне",
"area_report_period": "Период",
"area_no_costs": "За этот период затраты не записаны.",
"no_tasks_yet": "Пока нет задач",
"add_first_task": "Добавить первую задачу",
"last_performed_optional": "Последнее выполнение (опционально)",
@@ -399,11 +419,70 @@
"qr_download": "Скачать SVG",
"qr_action_view": "Просмотр",
"qr_action_complete": "Отметить обслуживание как выполненное",
"qr_action_quick_complete": "Быстрое завершение — без диалога",
"qr_print_quick_none": "Для кодов быстрого завершения у задачи должны быть значения по умолчанию для быстрого завершения (окно задачи → Значения по умолчанию для быстрого завершения) — ни у одной задачи выбранных объектов их пока нет.",
"qr_url_mode": "Тип ссылки",
"qr_mode_companion": "Приложение-компаньон",
"qr_mode_local": "Локальный (mDNS)",
"qr_mode_server": "URL сервера",
"overview": "Обзор",
"strat_this_month": "В этом месяце",
"strat_later": "Позже",
"strat_week": "Неделя",
"strat_fortnight": "Две недели",
"strat_month": "Месяц",
"strat_year": "Год",
"strat_other": "Прочее",
"strat_status": "Статус",
"strat_empty_title": "Пока нет объектов обслуживания",
"strat_empty_content": "Откройте панель обслуживания, чтобы добавить первый объект — насос бассейна, фильтр вентиляции, автомобиль, всё, что требует планового ухода.",
"strat_open_panel": "Открыть панель обслуживания",
"strat_add_object": "Добавить объект",
"strat_not_loaded": "**Maintenance Supporter** не загружен. Сначала установите/включите интеграцию.",
"strat_group_by": "Группировать вкладки по",
"strat_group_area": "По зонам (по умолчанию)",
"strat_group_status": "По статусу (Просрочено / Сработало / Скоро / OK)",
"strat_group_floor": "По этажам (этажи из HA)",
"strat_group_due_date": "По сроку (Просрочено / Сегодня / На этой неделе / В этом месяце / Позже)",
"strat_group_calendar": "Скользящий календарь (Неделя / Две недели / Месяц / Год)",
"strat_editor_help": "Вкладка «Обзор» всегда первая. Пустые группы пропускаются.",
"picker_name_calendar": "Maintenance Supporter — Календарь",
"picker_name_panel": "Maintenance Supporter — Панель в карточке",
"picker_name_budget": "Maintenance Supporter — Бюджет обслуживания",
"picker_name_groups": "Maintenance Supporter — Группы",
"picker_name_vacation": "Maintenance Supporter — Режим отпуска",
"picker_name_battery_fleet": "Парк батарей",
"picker_name_section": "Maintenance Supporter — Раздел",
"picker_name_vacation_status": "Maintenance Supporter — Статус отпуска",
"picker_name_budget_status": "Maintenance Supporter — Статус бюджета",
"picker_desc_card": "Обзор задач обслуживания с быстрыми действиями.",
"picker_desc_calendar": "Скользящий календарь задач обслуживания с окнами 7/14/30/365 дней, значками источника и метками надёжности прогноза.",
"picker_desc_panel": "Вся панель Maintenance Supporter в виде карточки — для вкладки в режиме «Панель» или подвкладки без пункта в боковом меню.",
"picker_desc_budget": "Редактируйте месячный и годовой бюджет прямо на панели.",
"picker_desc_groups": "Создавайте, переименовывайте и удаляйте группы задач прямо на панели.",
"picker_desc_vacation": "Включайте и выключайте режим отпуска и задавайте его даты прямо на панели.",
"picker_desc_battery_fleet": "Все отслеживаемые батареи: какие разряжены сейчас, какие скоро сядут и что купить.",
"picker_desc_dashboard": "Автоматически создаваемая панель. Группировка вкладок по зоне, статусу, этажу или сроку — выбор в редакторе стратегии или в YAML.",
"picker_desc_section": "Встраивайте задачи обслуживания (с фильтром по зоне, статусу, сроку) как раздел в любую вкладку панели.",
"picker_desc_vacation_status": "Компактный баннер статуса режима отпуска. Нажмите, чтобы открыть настройки на панели.",
"picker_desc_budget_status": "Обзор месячного и годового бюджета на обслуживание. Нажмите для подробностей.",
"picker_desc_groups_status": "Список настроенных групп задач с числом задач в каждой.",
"hist_note_button": "Выполнено кнопкой на панели",
"hist_note_todo": "Выполнено из списка дел",
"hist_note_voice": "Выполнено голосом",
"hist_note_notification": "Выполнено из уведомления",
"hist_note_nfc": "Выполнено через NFC-метку",
"hist_note_shopping_list": "Выполнено из списка покупок",
"hist_note_todo_mirror": "Выполнено из отражённого списка дел",
"hist_note_skipped_notification": "Пропущено из уведомления",
"hist_note_skipped_button": "Пропущено кнопкой на панели",
"hist_note_sensor_triggered": "Сработал триггер датчика",
"hist_note_initial": "Начальное значение задано при создании задачи",
"hist_note_auto_recovered": "Автоматически выполнено: датчик восстановился ({value})",
"hist_note_reset": "Сброшено на {date}",
"hist_note_trigger_replaced": "Сущность триггера заменена: {old} → {new}",
"hist_note_trigger_removed": "Триггер датчика удалён (сущность: {entity}). Расписание изменено на «{schedule}».",
"hist_note_compound_removed": "Сущность {entity} удалена из составного триггера; осталось условий: {count}.",
"recent_activities": "Недавние действия",
"search_notes": "Поиск по заметкам",
"avg_cost": "Ср. стоимость",
@@ -716,6 +795,7 @@
"groups_manage_tasks": "Управление назначениями задач…",
"groups_open_panel": "Открыть на панели",
"on_complete_action_target_hint": "Примечание: домен сущности должен соответствовать сервису — напр. 'button.press' работает только с button.*, 'counter.increment' только с counter.*, 'input_button.press' только с input_button.* и т. д. При несоответствии действие молча не выполнится (HA запишет в журнал 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Не когда задача выполняется сама (датчик восстановился)",
"show_all_objects": "Показать все объекты",
"show_all_tasks": "Сбросить фильтр — показать все задачи",
"filter_to_overdue": "Фильтровать список только по просроченным",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "«{name}»: задачи {before} → {after}",
"adopt_problem_adopt": "Принять выбранные",
"adopt_problem_done": "Принято сенсоров проблем: {tasks}",
"adopt_problem_done_one": "Принят 1 сенсор проблем",
"views_label": "Представления",
"views_none": "— Без представления —",
"views_manage": "Сохранить / управлять представлениями",
@@ -1013,6 +1094,7 @@
"setups_none": "Поддерживаемых устройств с непривязанными датчиками расходников не найдено.",
"setups_adopt": "Настроить выбранное",
"setups_done": "Создано задач с привязкой к датчикам: {tasks}.",
"setups_done_one": "Создана 1 задача с привязкой к датчикам.",
"complete_parts_used": "Использованные в этот раз запчасти",
"part_delete_confirm": "Удалить запчасть '{name}'? Будут удалены учёт остатков, связи с задачами и открытое напоминание о покупке.",
"baseline_start_value": "Начальное значение (необязательно)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "та же модель на другом устройстве",
"setups_maybe_covered": "Вероятно, уже есть как «{name}»",
"setups_already": "Уже есть: {names}",
"setups_reset_line": "Выполнение также сбрасывает счётчик в интеграции («{button}»)",
"setups_reset_enable": "— для этого кнопка будет включена",
"reset_offers_title": "Сбрасывать счётчики при выполнении",
"reset_offers_hint": "Эти задачи следят за счётчиком, который интеграция ведёт сама. После привязки выполнение задачи здесь также нажимает кнопку сброса интеграции — иначе счётчик продолжает идти и срок задачи сразу наступает снова.",
"reset_offers_before": "Сейчас: при выполнении счётчик в {integration} продолжает идти",
"reset_offers_after": "Потом: также нажимается «{button}»",
"reset_offers_renamed": "Переименована после настройки — проверьте, что задача относится к этой детали",
"reset_offers_apply": "Привязать сброс",
"reset_offers_done": "Задач со сбросом счётчика при выполнении: {count}",
"reset_offers_done_one": "1 задача теперь сбрасывает счётчик при выполнении",
"setups_before_after": "Задачи объекта: {before} → {after}",
"setups_new_object_count": "Новый объект «{name}» · задачи: {count}",
"schedule_preview_title": "Ближайшие даты",
@@ -1046,6 +1138,7 @@
"history_auto": "Автоматически",
"battery_fleet_title": "Парк батарей",
"battery_fleet_none_low": "Все батареи в порядке — менять нечего.",
"battery_fleet_progress": "К замене: {n}",
"battery_fleet_buy_now": "Купить сейчас",
"battery_fleet_soon": "Скоро понадобится",
"battery_fleet_soon_hint": "Оценка по дате последней замены — закажите заранее.",
@@ -1099,8 +1192,12 @@
"dismiss": "Скрыть",
"gs_label": "Первые шаги — эти подсказки исчезнут по мере роста настройки",
"gs_setups_chip": "Рекомендуемые настройки: найдено {n} устройств с готовыми триггерами",
"gs_setups_chip_one": "Рекомендуемые настройки: найдено 1 устройство с готовыми триггерами",
"gs_adopt_chip": "{n} датчиков проблем могут стать задачами обслуживания",
"gs_adopt_chip_one": "1 датчик проблем может стать задачей обслуживания",
"gs_fleet_chip": "Один клик настроит парк батарей",
"gs_reset_chip": "Сброс счётчика в интеграции доступен для задач: {n}",
"gs_reset_chip_one": "Сброс счётчика в интеграции доступен для 1 задачи",
"cal_editor_window": "Окно по умолчанию",
"cal_editor_window_week": "Неделя (7 дней)",
"cal_editor_window_fortnight": "Две недели (14 дней)",
@@ -241,6 +241,26 @@
"sort_task_name": "Uppgiftsnamn",
"all_objects": "Alla objekt",
"all_parts": "Alla delar",
"all_areas": "Alla områden",
"areas_filter": "Filtrera områden…",
"areas_filter_none": "Inget område matchar filtret.",
"area_cost_year": "Kostnad {year}",
"area_object_count": "{n} objekt",
"area_object_count_one": "1 objekt",
"area_range_12m": "Senaste 12 månaderna",
"area_range_all": "Hela perioden",
"area_task_filter": "Filtrera på uppgift…",
"area_kpi_completions": "Utföranden",
"area_kpi_total_time": "Total tid",
"area_cost_per_month": "Kostnad per månad",
"area_cost_per_year": "Kostnad per år",
"area_cost_per_object": "Kostnad per objekt",
"area_cost_share": "Andel",
"area_history_section": "Historik (alla objekt)",
"area_report_print": "Områdesrapport (PDF)",
"area_report_title": "Områdesrapport",
"area_report_period": "Tidsperiod",
"area_no_costs": "Inga kostnader registrerade under denna period.",
"no_tasks_yet": "Inga uppgifter ännu",
"add_first_task": "Lägg till första uppgift",
"trigger_configuration": "Utlösarkonfiguration",
@@ -399,11 +419,70 @@
"qr_download": "Ladda ner SVG",
"qr_action_view": "Visa underhållsinformation",
"qr_action_complete": "Markera underhåll som slutfört",
"qr_action_quick_complete": "Snabb-slutför — utan dialogruta",
"qr_print_quick_none": "Snabb-slutför-koder kräver snabb-slutför standardvärden på en uppgift (uppgiftsdialogen → Snabb-slutför standardvärden) — ingen uppgift i de valda objekten har några ännu.",
"qr_url_mode": "Länktyp",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Lokal (mDNS)",
"qr_mode_server": "Server-URL",
"overview": "Översikt",
"strat_this_month": "Den här månaden",
"strat_later": "Senare",
"strat_week": "Vecka",
"strat_fortnight": "Två veckor",
"strat_month": "Månad",
"strat_year": "År",
"strat_other": "Övrigt",
"strat_status": "Aktuellt läge",
"strat_empty_title": "Inga underhållsobjekt än",
"strat_empty_content": "Öppna Underhållspanelen för att lägga till ditt första objekt — poolpump, ventilationsfilter, fordon, allt som behöver schemalagd skötsel.",
"strat_open_panel": "Öppna Underhållspanelen",
"strat_add_object": "Lägg till objekt",
"strat_not_loaded": "**Maintenance Supporter** är inte laddad. Installera/aktivera integrationen först.",
"strat_group_by": "Gruppera vyer efter",
"strat_group_area": "Per område (standard)",
"strat_group_status": "Efter status (Försenad / Utlöst / Snart / OK)",
"strat_group_floor": "Per våning (använder HA-våningarna)",
"strat_group_due_date": "Efter förfallodatum (Försenad / Idag / Den här veckan / Den här månaden / Senare)",
"strat_group_calendar": "Rullande kalender (Vecka / Två veckor / Månad / År)",
"strat_editor_help": "Vyn ”Översikt” visas alltid först. Tomma grupper hoppas över.",
"picker_name_calendar": "Maintenance Supporter — Kalender",
"picker_name_panel": "Maintenance Supporter — Panel som kort",
"picker_name_budget": "Maintenance Supporter — Underhållsbudget",
"picker_name_groups": "Maintenance Supporter — Grupper",
"picker_name_vacation": "Maintenance Supporter — Semesterläge",
"picker_name_battery_fleet": "Batteriflotta",
"picker_name_section": "Maintenance Supporter — Sektion",
"picker_name_vacation_status": "Maintenance Supporter — Semesterstatus",
"picker_name_budget_status": "Maintenance Supporter — Budgetstatus",
"picker_desc_card": "Översikt över dina underhållsuppgifter med snabbåtgärder.",
"picker_desc_calendar": "Rullande kalender över underhållsuppgifter med fönster på 7/14/30/365 dagar, källikoner och etiketter för prognossäkerhet.",
"picker_desc_panel": "Hela Maintenance Supporter-panelen som kort — för en panelvy / undervy på en instrumentpanel utan post i sidofältet.",
"picker_desc_budget": "Redigera månads- och årsbudgeten direkt på instrumentpanelen.",
"picker_desc_groups": "Skapa, byt namn på och ta bort uppgiftsgrupper direkt på instrumentpanelen.",
"picker_desc_vacation": "Slå på eller av semesterläget och ange datum direkt på instrumentpanelen.",
"picker_desc_battery_fleet": "Alla bevakade batterier: vad som är svagt nu, vad som snart tar slut och vad du behöver köpa.",
"picker_desc_dashboard": "Automatiskt genererad instrumentpanel. Gruppera vyer efter område, status, våning eller förfallodatum — väljs i strategiredigeraren eller i YAML.",
"picker_desc_section": "Bädda in underhållsuppgifter (filtrerbara efter område, status, förfallodatum) som en sektion i valfri vy på instrumentpanelen.",
"picker_desc_vacation_status": "Kompakt statusbanner för semesterläget. Tryck för att öppna inställningarna i panelen.",
"picker_desc_budget_status": "Översikt över månads- och årsbudgeten för underhåll. Tryck för detaljer.",
"picker_desc_groups_status": "Lista över konfigurerade uppgiftsgrupper med antal uppgifter i varje.",
"hist_note_button": "Slutförd via knapp på instrumentpanelen",
"hist_note_todo": "Slutförd från att-göra-listan",
"hist_note_voice": "Slutförd med rösten",
"hist_note_notification": "Slutförd från notifikationen",
"hist_note_nfc": "Slutförd via NFC-tagg",
"hist_note_shopping_list": "Slutförd från inköpslistan",
"hist_note_todo_mirror": "Slutförd från en speglad att-göra-lista",
"hist_note_skipped_notification": "Hoppades över från notifikationen",
"hist_note_skipped_button": "Hoppades över via knapp på instrumentpanelen",
"hist_note_sensor_triggered": "Sensorutlösare aktiverad",
"hist_note_initial": "Startvärde angavs när uppgiften skapades",
"hist_note_auto_recovered": "Automatiskt slutförd: sensorn återhämtade sig ({value})",
"hist_note_reset": "Återställd till {date}",
"hist_note_trigger_replaced": "Utlösarentitet ersatt: {old} → {new}",
"hist_note_trigger_removed": "Sensorutlösare borttagen (entitet: {entity}). Schemat ändrat till {schedule}.",
"hist_note_compound_removed": "Entiteten {entity} togs bort från den sammansatta utlösaren; återstående villkor: {count}.",
"recent_activities": "Senaste aktiviteter",
"search_notes": "Sök i anteckningar",
"avg_cost": "Snittlig kostnad",
@@ -716,6 +795,7 @@
"groups_manage_tasks": "Hantera uppgiftstilldelningar…",
"groups_open_panel": "Öppna i panelen",
"on_complete_action_target_hint": "Obs: entitetens domän måste matcha tjänsten — t.ex. 'button.press' fungerar bara på button.*, 'counter.increment' bara på counter.*, 'input_button.press' bara på input_button.* osv. Vid en avvikelse misslyckas åtgärden tyst (HA loggar 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Inte när uppgiften slutförs av sig själv (sensorn har återhämtat sig)",
"show_all_objects": "Visa alla objekt",
"show_all_tasks": "Rensa filter — visa alla uppgifter",
"filter_to_overdue": "Filtrera listan till endast försenade",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "”{name}”: uppgifter {before} → {after}",
"adopt_problem_adopt": "Anta valda",
"adopt_problem_done": "Antog {tasks} problemsensor(er)",
"adopt_problem_done_one": "Antog 1 problemsensor",
"views_label": "Vyer",
"views_none": "— Ingen vy —",
"views_manage": "Spara / hantera vyer",
@@ -1013,6 +1094,7 @@
"setups_none": "Inga enheter med okopplade förbrukningssensorer hittades.",
"setups_adopt": "Konfigurera valda",
"setups_done": "{tasks} sensorkopplade uppgifter skapade.",
"setups_done_one": "1 sensorkopplad uppgift skapad.",
"complete_parts_used": "Delar använda denna gång",
"part_delete_confirm": "Ta bort delen '{name}'? Lagerspårning, uppgiftskopplingar och en öppen köppåminnelse tas bort.",
"baseline_start_value": "Startvärde (valfritt)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "samma modell på en annan enhet",
"setups_maybe_covered": "Finns troligen redan som ”{name}”",
"setups_already": "Finns redan: {names}",
"setups_reset_line": "Att slutföra den återställer också räknaren i integrationen (”{button}”)",
"setups_reset_enable": "— knappen slås på för detta",
"reset_offers_title": "Återställ räknare vid slutförande",
"reset_offers_hint": "Dessa uppgifter bevakar en räknare som integrationen själv håller. När de är kopplade trycker ett slutförande här också på integrationens återställningsknapp — annars fortsätter räknaren att gå och uppgiften förfaller direkt igen.",
"reset_offers_before": "Nu: att slutföra den låter räknaren i {integration} fortsätta",
"reset_offers_after": "Sedan: trycker också på ”{button}”",
"reset_offers_renamed": "Omdöpt sedan konfigurationen — kontrollera att uppgiften gäller den här delen",
"reset_offers_apply": "Koppla återställningar",
"reset_offers_done": "{count} uppgifter återställer nu sin räknare vid slutförande",
"reset_offers_done_one": "1 uppgift återställer nu sin räknare vid slutförande",
"setups_before_after": "Uppgifter på objektet: {before} → {after}",
"setups_new_object_count": "Nytt objekt ”{name}” · uppgifter: {count}",
"schedule_preview_title": "Kommande datum",
@@ -1046,6 +1138,7 @@
"history_auto": "Automatiskt",
"battery_fleet_title": "Batteriflotta",
"battery_fleet_none_low": "Alla batterier OK — inget att byta.",
"battery_fleet_progress": "{n} att byta",
"battery_fleet_buy_now": "Köp nu",
"battery_fleet_soon": "Behövs snart",
"battery_fleet_soon_hint": "Uppskattat från senaste bytet — beställ i förväg.",
@@ -1099,8 +1192,12 @@
"dismiss": "Avfärda",
"gs_label": "Kom igång — tipsen försvinner när din installation växer",
"gs_setups_chip": "Föreslagna uppsättningar hittade {n} enheter med förkopplade utlösare",
"gs_setups_chip_one": "Föreslagna uppsättningar hittade 1 enhet med förkopplade utlösare",
"gs_adopt_chip": "{n} problemsensorer kan bli underhållsuppgifter",
"gs_adopt_chip_one": "1 problemsensor kan bli en underhållsuppgift",
"gs_fleet_chip": "Ett klick konfigurerar batteriflottan",
"gs_reset_chip": "{n} uppgifter kan återställa sin räknare i integrationen",
"gs_reset_chip_one": "1 uppgift kan återställa sin räknare i integrationen",
"cal_editor_window": "Standardfönster",
"cal_editor_window_week": "Vecka (7 dagar)",
"cal_editor_window_fortnight": "Två veckor (14 dagar)",
@@ -243,6 +243,26 @@
"sort_task_name": "Görev adı",
"all_objects": "Tüm nesneler",
"all_parts": "Tüm parçalar",
"all_areas": "Tüm alanlar",
"areas_filter": "Alanları filtrele…",
"areas_filter_none": "Filtreyle eşleşen alan yok.",
"area_cost_year": "{year} maliyeti",
"area_object_count": "{n} nesne",
"area_object_count_one": "1 nesne",
"area_range_12m": "Son 12 ay",
"area_range_all": "Tüm zamanlar",
"area_task_filter": "Göreve göre filtrele…",
"area_kpi_completions": "Tamamlamalar",
"area_kpi_total_time": "Toplam süre",
"area_cost_per_month": "Aylık maliyet",
"area_cost_per_year": "Yıllık maliyet",
"area_cost_per_object": "Nesne başına maliyet",
"area_cost_share": "Pay",
"area_history_section": "Geçmiş (tüm nesneler)",
"area_report_print": "Alan raporu (PDF)",
"area_report_title": "Alan raporu",
"area_report_period": "Dönem",
"area_no_costs": "Bu dönemde kaydedilmiş maliyet yok.",
"no_tasks_yet": "Henüz görev yok",
"add_first_task": "İlk görevi ekle",
"trigger_configuration": "Tetikleyici Yapılandırması",
@@ -401,11 +421,70 @@
"qr_download": "SVG indir",
"qr_action_view": "Bakım bilgisini görüntüle",
"qr_action_complete": "Bakımı tamamlandı olarak işaretle",
"qr_action_quick_complete": "Hızlı tamamlama — iletişim kutusu olmadan",
"qr_print_quick_none": "Hızlı tamamlama kodları için bir görevde hızlı tamamlama varsayılanları gerekir (görev penceresi → Hızlı tamamlama varsayılanları) — seçilen nesnelerin hiçbir görevinde henüz yok.",
"qr_url_mode": "Bağlantı türü",
"qr_mode_companion": "Companion uygulaması",
"qr_mode_local": "Yerel (mDNS)",
"qr_mode_server": "Sunucu URL'si",
"overview": "Genel Bakış",
"strat_this_month": "Bu ay",
"strat_later": "Daha sonra",
"strat_week": "Hafta",
"strat_fortnight": "İki hafta",
"strat_month": "Ay",
"strat_year": "Yıl",
"strat_other": "Diğer",
"strat_status": "Durum",
"strat_empty_title": "Henüz bakım nesnesi yok",
"strat_empty_content": "İlk nesnenizi eklemek için Bakım panelini açın — havuz pompası, klima filtresi, araç, düzenli bakım gerektiren her şey.",
"strat_open_panel": "Bakım panelini aç",
"strat_add_object": "Nesne ekle",
"strat_not_loaded": "**Maintenance Supporter** yüklenmedi. Önce entegrasyonu kurun/etkinleştirin.",
"strat_group_by": "Görünümleri grupla",
"strat_group_area": "Alana göre (varsayılan)",
"strat_group_status": "Duruma göre (Gecikmiş / Tetiklendi / Yaklaşan / Tamam)",
"strat_group_floor": "Kata göre (HA katlarını kullanır)",
"strat_group_due_date": "Vadeye göre (Gecikmiş / Bugün / Bu hafta / Bu ay / Daha sonra)",
"strat_group_calendar": "Kayan takvim (Hafta / İki hafta / Ay / Yıl)",
"strat_editor_help": "\"Genel Bakış\" görünümü her zaman ilk sıradadır. Boş gruplar atlanır.",
"picker_name_calendar": "Maintenance Supporter — Takvim",
"picker_name_panel": "Maintenance Supporter — Panel kartı",
"picker_name_budget": "Maintenance Supporter — Bakım bütçesi",
"picker_name_groups": "Maintenance Supporter — Gruplar",
"picker_name_vacation": "Maintenance Supporter — Tatil modu",
"picker_name_battery_fleet": "Pil filosu",
"picker_name_section": "Maintenance Supporter — Bölüm",
"picker_name_vacation_status": "Maintenance Supporter — Tatil durumu",
"picker_name_budget_status": "Maintenance Supporter — Bütçe durumu",
"picker_desc_card": "Hızlı eylemlerle bakım görevlerinize genel bakış.",
"picker_desc_calendar": "7/14/30/365 günlük pencereler, kaynak simgeleri ve tahmin güveni etiketleriyle bakım görevlerinin kayan takvimi.",
"picker_desc_panel": "Maintenance Supporter panelinin tamamı kart olarak — kenar çubuğu girişi olmadan bir panel görünümü / pano alt görünümü için.",
"picker_desc_budget": "Aylık ve yıllık bütçeyi doğrudan panoda düzenleyin.",
"picker_desc_groups": "Görev gruplarını doğrudan panoda oluşturun, yeniden adlandırın ve silin.",
"picker_desc_vacation": "Tatil modunu doğrudan panoda açıp kapatın ve tarihlerini ayarlayın.",
"picker_desc_battery_fleet": "İzlenen tüm piller: şu anda hangileri zayıf, hangileri yakında bitecek ve ne satın alınmalı.",
"picker_desc_dashboard": "Otomatik oluşturulan pano. Görünümleri alana, duruma, kata veya vadeye göre gruplayın — strateji düzenleyicisinden veya YAML ile seçilir.",
"picker_desc_section": "Bakım görevlerini (alana, duruma, vadeye göre filtrelenebilir) herhangi bir pano görünümüne bölüm olarak yerleştirin.",
"picker_desc_vacation_status": "Kompakt tatil modu durum bandı. Paneldeki ayarları açmak için dokunun.",
"picker_desc_budget_status": "Aylık ve yıllık bakım bütçesine genel bakış. Ayrıntılar için dokunun.",
"picker_desc_groups_status": "Yapılandırılmış görev gruplarının, her birindeki görev sayısıyla listesi.",
"hist_note_button": "Pano düğmesiyle tamamlandı",
"hist_note_todo": "Yapılacaklar listesinden tamamlandı",
"hist_note_voice": "Sesle tamamlandı",
"hist_note_notification": "Bildirimden tamamlandı",
"hist_note_nfc": "NFC etiketiyle tamamlandı",
"hist_note_shopping_list": "Alışveriş listesinden tamamlandı",
"hist_note_todo_mirror": "Yansıtılan bir yapılacaklar listesinden tamamlandı",
"hist_note_skipped_notification": "Bildirimden atlandı",
"hist_note_skipped_button": "Pano düğmesiyle atlandı",
"hist_note_sensor_triggered": "Sensör tetikleyicisi etkinleşti",
"hist_note_initial": "Görev oluşturulurken ayarlanan başlangıç değeri",
"hist_note_auto_recovered": "Otomatik tamamlandı: sensör düzeldi ({value})",
"hist_note_reset": "{date} tarihine sıfırlandı",
"hist_note_trigger_replaced": "Tetikleyici varlık değiştirildi: {old} → {new}",
"hist_note_trigger_removed": "Sensör tetikleyicisi kaldırıldı (varlık: {entity}). Zamanlama {schedule} olarak değiştirildi.",
"hist_note_compound_removed": "{entity} varlığı bileşik tetikleyiciden kaldırıldı; kalan koşul sayısı: {count}.",
"recent_activities": "Son Etkinlikler",
"search_notes": "Notlarda ara",
"avg_cost": "Ort. Maliyet",
@@ -709,6 +788,7 @@
"on_complete_action_desc": "Görev tamamlandığında bir HA servisi çağırır — örn. cihazdaki bir sayacı sıfırlar.",
"on_complete_action_target": "Hedef varlık",
"on_complete_action_target_hint": "Not: varlık alan adı servisle eşleşmelidir — örn. 'button.press' yalnızca button.* üzerinde, 'counter.increment' yalnızca counter.* üzerinde, 'input_button.press' yalnızca input_button.* üzerinde çalışır. Eşleşmezse eylem sessizce başarısız olur (HA günlüğü: 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Görev kendiliğinden tamamlandığında değil (sensörü düzeldi)",
"on_complete_action_data": "Veri (JSON, isteğe bağlı)",
"on_complete_action_test": "Yapılandırmayı doğrula",
"on_complete_action_test_success": "✓ Yapılandırma geçerli (eylem yalnızca görev tamamlandığında çalışır)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "\"{name}\": görevler {before} → {after}",
"adopt_problem_adopt": "Seçilenleri devral",
"adopt_problem_done": "{tasks} sorun sensörü devralındı",
"adopt_problem_done_one": "1 sorun sensörü devralındı",
"views_label": "Görünümler",
"views_none": "— Görünüm yok —",
"views_manage": "Görünümleri kaydet / yönet",
@@ -1013,6 +1094,7 @@
"setups_none": "Bağlanmamış sarf malzemesi sensörü olan desteklenen cihaz bulunamadı.",
"setups_adopt": "Seçilenleri kur",
"setups_done": "{tasks} sensöre bağlı görev oluşturuldu.",
"setups_done_one": "1 sensöre bağlı görev oluşturuldu.",
"complete_parts_used": "Bu sefer kullanılan parçalar",
"part_delete_confirm": "'{name}' parçası silinsin mi? Stok takibi, görev bağlantıları ve açık satın alma hatırlatmaları kaldırılacak.",
"baseline_start_value": "Başlangıç okuması (isteğe bağlı)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "başka bir cihazda aynı model",
"setups_maybe_covered": "Muhtemelen \"{name}\" olarak zaten var",
"setups_already": "Zaten var: {names}",
"setups_reset_line": "Tamamlamak entegrasyondaki sayacı da sıfırlar (“{button}”)",
"setups_reset_enable": "— bunun için düğme etkinleştirilir",
"reset_offers_title": "Tamamlamada sayaçları sıfırla",
"reset_offers_hint": "Bu görevler, entegrasyonun kendi tuttuğu bir sayacı izler. Bağlandığında, görevi burada tamamlamak entegrasyonun sıfırlama düğmesine de basar — aksi halde sayaç işlemeye devam eder ve görevin vadesi hemen yeniden gelir.",
"reset_offers_before": "Şimdi: tamamlamak {integration} içindeki sayacı çalışır halde bırakır",
"reset_offers_after": "Sonra: “{button}” düğmesine de basar",
"reset_offers_renamed": "Kurulumdan sonra yeniden adlandırıldı — bu görevin bu parçaya ait olduğunu kontrol edin",
"reset_offers_apply": "Sıfırlamaları bağla",
"reset_offers_done": "{count} görev artık tamamlandığında sayacını sıfırlıyor",
"reset_offers_done_one": "1 görev artık tamamlandığında sayacını sıfırlıyor",
"setups_before_after": "Nesnenin görevleri: {before} → {after}",
"setups_new_object_count": "Yeni nesne \"{name}\" · görevler: {count}",
"schedule_preview_title": "Sonraki tarihler",
@@ -1046,6 +1138,7 @@
"history_auto": "Otomatik",
"battery_fleet_title": "Pil filosu",
"battery_fleet_none_low": "Tüm piller iyi durumda — değiştirilecek bir şey yok.",
"battery_fleet_progress": "Değiştirilecek: {n}",
"battery_fleet_buy_now": "Şimdi satın al",
"battery_fleet_soon": "Yakında gerekli",
"battery_fleet_soon_hint": "Son değişim tarihinden tahmin edildi — önceden sipariş verin.",
@@ -1099,8 +1192,12 @@
"dismiss": "Kapat",
"gs_label": "Başlarken — kurulumunuz büyüdükçe bu ipuçları kaybolur",
"gs_setups_chip": "Önerilen kurulumlar {n} cihaz buldu (hazır tetikleyicilerle)",
"gs_setups_chip_one": "Önerilen kurulumlar 1 cihaz buldu (hazır tetikleyicilerle)",
"gs_adopt_chip": "{n} sorun sensörü bakım görevine dönüşebilir",
"gs_adopt_chip_one": "1 sorun sensörü bakım görevine dönüşebilir",
"gs_fleet_chip": "Tek tıkla pil filosunu kurun",
"gs_reset_chip": "{n} görev entegrasyondaki sayacını sıfırlayabilir",
"gs_reset_chip_one": "1 görev entegrasyondaki sayacını sıfırlayabilir",
"cal_editor_window": "Varsayılan pencere",
"cal_editor_window_week": "Hafta (7 gün)",
"cal_editor_window_fortnight": "İki hafta (14 gün)",
@@ -241,6 +241,26 @@
"sort_task_name": "Назва завдання",
"all_objects": "Всі об'єкти",
"all_parts": "Усі деталі",
"all_areas": "Усі зони",
"areas_filter": "Фільтр зон…",
"areas_filter_none": "Немає зон, що відповідають фільтру.",
"area_cost_year": "Вартість за {year}",
"area_object_count": "Об'єктів: {n}",
"area_object_count_one": "1 об'єкт",
"area_range_12m": "Останні 12 місяців",
"area_range_all": "За весь час",
"area_task_filter": "Фільтр за завданням…",
"area_kpi_completions": "Виконання",
"area_kpi_total_time": "Загальний час",
"area_cost_per_month": "Вартість за місяцями",
"area_cost_per_year": "Вартість за роками",
"area_cost_per_object": "Вартість за об'єктами",
"area_cost_share": "Частка",
"area_history_section": "Історія (усі об'єкти)",
"area_report_print": "Звіт по зоні (PDF)",
"area_report_title": "Звіт по зоні",
"area_report_period": "Період",
"area_no_costs": "За цей період витрати не записані.",
"no_tasks_yet": "Завдань ще немає",
"add_first_task": "Додати перше завдання",
"trigger_configuration": "Налаштування тригера",
@@ -399,11 +419,70 @@
"qr_download": "Завантажити SVG",
"qr_action_view": "Переглянути",
"qr_action_complete": "Позначити обслуговування виконаним",
"qr_action_quick_complete": "Швидке завершення — без діалогу",
"qr_print_quick_none": "Для кодів швидкого завершення завдання має мати стандартні значення швидкого завершення (вікно завдання → Стандартні значення швидкого завершення) — жодне завдання вибраних об'єктів їх ще не має.",
"qr_url_mode": "Тип посилання",
"qr_mode_companion": "Companion App",
"qr_mode_local": "Локальний (mDNS)",
"qr_mode_server": "URL сервера",
"overview": "Огляд",
"strat_this_month": "Цього місяця",
"strat_later": "Пізніше",
"strat_week": "Тиждень",
"strat_fortnight": "Два тижні",
"strat_month": "Місяць",
"strat_year": "Рік",
"strat_other": "Інше",
"strat_status": "Статус",
"strat_empty_title": "Поки немає об'єктів обслуговування",
"strat_empty_content": "Відкрийте панель обслуговування, щоб додати перший об'єкт — насос басейну, фільтр вентиляції, автомобіль, усе, що потребує планового догляду.",
"strat_open_panel": "Відкрити панель обслуговування",
"strat_add_object": "Додати об'єкт",
"strat_not_loaded": "**Maintenance Supporter** не завантажено. Спершу встановіть/увімкніть інтеграцію.",
"strat_group_by": "Групувати вкладки за",
"strat_group_area": "За зонами (типово)",
"strat_group_status": "За статусом (Прострочено / Спрацювало / Незабаром / Норма)",
"strat_group_floor": "За поверхами (поверхи з HA)",
"strat_group_due_date": "За терміном (Прострочено / Сьогодні / Цього тижня / Цього місяця / Пізніше)",
"strat_group_calendar": "Ковзний календар (Тиждень / Два тижні / Місяць / Рік)",
"strat_editor_help": "Вкладка «Огляд» завжди перша. Порожні групи пропускаються.",
"picker_name_calendar": "Maintenance Supporter — Календар",
"picker_name_panel": "Maintenance Supporter — Панель у картці",
"picker_name_budget": "Maintenance Supporter — Бюджет обслуговування",
"picker_name_groups": "Maintenance Supporter — Групи",
"picker_name_vacation": "Maintenance Supporter — Режим відпустки",
"picker_name_battery_fleet": "Парк батарей",
"picker_name_section": "Maintenance Supporter — Розділ",
"picker_name_vacation_status": "Maintenance Supporter — Статус відпустки",
"picker_name_budget_status": "Maintenance Supporter — Статус бюджету",
"picker_desc_card": "Огляд завдань обслуговування зі швидкими діями.",
"picker_desc_calendar": "Ковзний календар завдань обслуговування з вікнами 7/14/30/365 днів, значками джерела та мітками надійності прогнозу.",
"picker_desc_panel": "Уся панель Maintenance Supporter у вигляді картки — для вкладки в режимі «Панель» або підвкладки дашборду без пункту в бічному меню.",
"picker_desc_budget": "Редагуйте щомісячний і щорічний бюджет прямо на дашборді.",
"picker_desc_groups": "Створюйте, перейменовуйте та видаляйте групи завдань прямо на дашборді.",
"picker_desc_vacation": "Вмикайте й вимикайте режим відпустки та задавайте його дати прямо на дашборді.",
"picker_desc_battery_fleet": "Усі відстежувані батареї: які розряджені зараз, які скоро сядуть і що купити.",
"picker_desc_dashboard": "Автоматично згенерований дашборд. Групування вкладок за зоною, статусом, поверхом або терміном — вибір у редакторі стратегії чи в YAML.",
"picker_desc_section": "Вбудовуйте завдання обслуговування (з фільтром за зоною, статусом, терміном) як розділ у будь-яку вкладку дашборду.",
"picker_desc_vacation_status": "Компактний банер стану режиму відпустки. Торкніться, щоб відкрити налаштування на панелі.",
"picker_desc_budget_status": "Огляд щомісячного та щорічного бюджету на обслуговування. Торкніться, щоб побачити деталі.",
"picker_desc_groups_status": "Список налаштованих груп завдань із кількістю завдань у кожній.",
"hist_note_button": "Виконано кнопкою на дашборді",
"hist_note_todo": "Виконано зі списку справ",
"hist_note_voice": "Виконано голосом",
"hist_note_notification": "Виконано зі сповіщення",
"hist_note_nfc": "Виконано через NFC-тег",
"hist_note_shopping_list": "Виконано зі списку покупок",
"hist_note_todo_mirror": "Виконано з віддзеркаленого списку справ",
"hist_note_skipped_notification": "Пропущено зі сповіщення",
"hist_note_skipped_button": "Пропущено кнопкою на дашборді",
"hist_note_sensor_triggered": "Спрацював тригер датчика",
"hist_note_initial": "Початкове значення задано під час створення завдання",
"hist_note_auto_recovered": "Автоматично виконано: датчик відновився ({value})",
"hist_note_reset": "Скинуто на {date}",
"hist_note_trigger_replaced": "Сутність тригера замінено: {old} → {new}",
"hist_note_trigger_removed": "Тригер датчика видалено (сутність: {entity}). Розклад змінено на «{schedule}».",
"hist_note_compound_removed": "Сутність {entity} видалено зі складеного тригера; залишилось умов: {count}.",
"recent_activities": "Остання активність",
"search_notes": "Пошук у примітках",
"avg_cost": "Сер. вартість",
@@ -716,6 +795,7 @@
"groups_manage_tasks": "Керування призначеннями завдань…",
"groups_open_panel": "Відкрити на панелі",
"on_complete_action_target_hint": "Примітка: домен сутності має відповідати сервісу — напр. 'button.press' працює лише з button.*, 'counter.increment' лише з counter.*, 'input_button.press' лише з input_button.* тощо. У разі невідповідності дія мовчки не виконається (HA запише в журнал 'Referenced entities ... missing or not currently available').",
"on_complete_action_skip_auto": "Не коли завдання виконується саме (датчик відновився)",
"show_all_objects": "Показати всі об'єкти",
"show_all_tasks": "Скинути фільтр — показати всі завдання",
"filter_to_overdue": "Фільтрувати список лише за простроченими",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "«{name}»: завдання {before} → {after}",
"adopt_problem_adopt": "Прийняти вибрані",
"adopt_problem_done": "Прийнято сенсорів проблем: {tasks}",
"adopt_problem_done_one": "Прийнято 1 сенсор проблем",
"views_label": "Подання",
"views_none": "— Без подання —",
"views_manage": "Зберегти / керувати поданнями",
@@ -1013,6 +1094,7 @@
"setups_none": "Підтримуваних пристроїв із неприв'язаними датчиками витратних матеріалів не знайдено.",
"setups_adopt": "Налаштувати вибране",
"setups_done": "Створено завдань із прив'язкою до датчиків: {tasks}.",
"setups_done_one": "Створено 1 завдання з прив'язкою до датчиків.",
"complete_parts_used": "Використані цього разу запчастини",
"part_delete_confirm": "Видалити запчастину '{name}'? Буде видалено облік залишків, зв'язки із завданнями та відкрите нагадування про купівлю.",
"baseline_start_value": "Початкове значення (необов'язково)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "та сама модель на іншому пристрої",
"setups_maybe_covered": "Імовірно, вже є як «{name}»",
"setups_already": "Уже є: {names}",
"setups_reset_line": "Виконання також скидає лічильник в інтеграції («{button}»)",
"setups_reset_enable": "— для цього кнопку буде увімкнено",
"reset_offers_title": "Скидати лічильники під час виконання",
"reset_offers_hint": "Ці завдання стежать за лічильником, який інтеграція веде сама. Після прив'язки виконання завдання тут також натискає кнопку скидання інтеграції — інакше лічильник продовжує йти і термін завдання одразу настає знову.",
"reset_offers_before": "Зараз: під час виконання лічильник у {integration} продовжує йти",
"reset_offers_after": "Потім: також натискається «{button}»",
"reset_offers_renamed": "Перейменовано після налаштування — перевірте, що завдання стосується цієї деталі",
"reset_offers_apply": "Прив'язати скидання",
"reset_offers_done": "Завдань зі скиданням лічильника під час виконання: {count}",
"reset_offers_done_one": "1 завдання тепер скидає лічильник під час виконання",
"setups_before_after": "Завдання об'єкта: {before} → {after}",
"setups_new_object_count": "Новий об'єкт «{name}» · завдання: {count}",
"schedule_preview_title": "Найближчі дати",
@@ -1046,6 +1138,7 @@
"history_auto": "Автоматично",
"battery_fleet_title": "Парк батарей",
"battery_fleet_none_low": "Усі батареї в нормі — нічого міняти.",
"battery_fleet_progress": "До заміни: {n}",
"battery_fleet_buy_now": "Купити зараз",
"battery_fleet_soon": "Скоро знадобиться",
"battery_fleet_soon_hint": "Оцінка за датою останньої заміни — замовте заздалегідь.",
@@ -1099,8 +1192,12 @@
"dismiss": "Приховати",
"gs_label": "Перші кроки — ці підказки зникнуть у міру зростання налаштування",
"gs_setups_chip": "Рекомендовані налаштування: знайдено {n} пристроїв із готовими тригерами",
"gs_setups_chip_one": "Рекомендовані налаштування: знайдено 1 пристрій із готовими тригерами",
"gs_adopt_chip": "{n} датчиків проблем можуть стати завданнями обслуговування",
"gs_adopt_chip_one": "1 датчик проблем може стати завданням обслуговування",
"gs_fleet_chip": "Один клік налаштує парк батарей",
"gs_reset_chip": "Скидання лічильника в інтеграції доступне для завдань: {n}",
"gs_reset_chip_one": "Скидання лічильника в інтеграції доступне для 1 завдання",
"cal_editor_window": "Вікно за замовчуванням",
"cal_editor_window_week": "Тиждень (7 днів)",
"cal_editor_window_fortnight": "Два тижні (14 днів)",
@@ -243,6 +243,26 @@
"sort_task_name": "任务名称",
"all_objects": "所有维护项",
"all_parts": "所有配件",
"all_areas": "所有区域",
"areas_filter": "筛选区域…",
"areas_filter_none": "没有符合筛选条件的区域。",
"area_cost_year": "{year} 年费用",
"area_object_count": "{n} 个维护项",
"area_object_count_one": "1 个维护项",
"area_range_12m": "最近 12 个月",
"area_range_all": "全部时间",
"area_task_filter": "按任务筛选…",
"area_kpi_completions": "完成次数",
"area_kpi_total_time": "总耗时",
"area_cost_per_month": "每月费用",
"area_cost_per_year": "每年费用",
"area_cost_per_object": "各维护项费用",
"area_cost_share": "占比",
"area_history_section": "历史(全部维护项)",
"area_report_print": "区域报告(PDF)",
"area_report_title": "区域报告",
"area_report_period": "期间",
"area_no_costs": "此期间没有记录费用。",
"no_tasks_yet": "尚无任务",
"add_first_task": "添加首个任务",
"trigger_configuration": "触发器配置",
@@ -401,11 +421,70 @@
"qr_download": "下载 SVG",
"qr_action_view": "查看维护信息",
"qr_action_complete": "标记维护为已完成",
"qr_action_quick_complete": "快速完成 — 无对话框",
"qr_print_quick_none": "快速完成二维码需要任务设置快速完成默认值(任务对话框 → 快速完成默认值)— 所选对象的任务尚未设置。",
"qr_url_mode": "链接类型",
"qr_mode_companion": "Companion App",
"qr_mode_local": "本地 (mDNS)",
"qr_mode_server": "服务器 URL",
"overview": "概览",
"strat_this_month": "本月",
"strat_later": "以后",
"strat_week": "一周",
"strat_fortnight": "两周",
"strat_month": "一个月",
"strat_year": "一年",
"strat_other": "其他",
"strat_status": "状态",
"strat_empty_title": "暂无维护项",
"strat_empty_content": "打开维护面板添加你的第一个维护项——泳池泵、空调滤网、车辆,任何需要定期保养的东西。",
"strat_open_panel": "打开维护面板",
"strat_add_object": "添加维护项",
"strat_not_loaded": "**Maintenance Supporter** 未加载。请先安装/启用该集成。",
"strat_group_by": "视图分组方式",
"strat_group_area": "按区域(默认)",
"strat_group_status": "按状态(逾期 / 已触发 / 即将到期 / 正常)",
"strat_group_floor": "按楼层(使用 HA 楼层)",
"strat_group_due_date": "按到期时间(逾期 / 今天 / 本周 / 本月 / 以后)",
"strat_group_calendar": "滚动日历(一周 / 两周 / 一个月 / 一年)",
"strat_editor_help": "“概览”视图始终排在第一位。空分组会被跳过。",
"picker_name_calendar": "Maintenance Supporter — 日历",
"picker_name_panel": "Maintenance Supporter — 面板卡片",
"picker_name_budget": "Maintenance Supporter — 维护预算",
"picker_name_groups": "Maintenance Supporter — 分组",
"picker_name_vacation": "Maintenance Supporter — 度假模式",
"picker_name_battery_fleet": "电池群",
"picker_name_section": "Maintenance Supporter — 分区",
"picker_name_vacation_status": "Maintenance Supporter — 度假状态",
"picker_name_budget_status": "Maintenance Supporter — 预算状态",
"picker_desc_card": "维护任务概览,附带快捷操作。",
"picker_desc_calendar": "维护任务滚动日历,提供 7/14/30/365 天时间窗、来源图标和预测置信度标签。",
"picker_desc_panel": "将完整的 Maintenance Supporter 面板作为卡片——用于面板视图或仪表盘子视图,无需侧边栏入口。",
"picker_desc_budget": "直接在仪表盘上编辑月度和年度预算。",
"picker_desc_groups": "直接在仪表盘上创建、重命名和删除任务组。",
"picker_desc_vacation": "直接在仪表盘上开启或关闭度假模式并设置日期。",
"picker_desc_battery_fleet": "所有跟踪的电池:当前电量低的、即将耗尽的,以及需要购买的。",
"picker_desc_dashboard": "自动生成的仪表盘。可按区域、状态、楼层或到期时间对视图分组——在策略编辑器或 YAML 中选择。",
"picker_desc_section": "将维护任务(可按区域、状态、到期时间过滤)作为分区嵌入任意仪表盘视图。",
"picker_desc_vacation_status": "紧凑的度假模式状态横幅。点按可在面板中打开设置。",
"picker_desc_budget_status": "月度和年度维护预算概览。点按查看详情。",
"picker_desc_groups_status": "已配置的任务组列表,显示每组的任务数。",
"hist_note_button": "通过仪表盘按钮完成",
"hist_note_todo": "通过待办清单完成",
"hist_note_voice": "通过语音完成",
"hist_note_notification": "通过通知完成",
"hist_note_nfc": "通过 NFC 标签完成",
"hist_note_shopping_list": "通过购物清单完成",
"hist_note_todo_mirror": "通过镜像的待办清单完成",
"hist_note_skipped_notification": "通过通知跳过",
"hist_note_skipped_button": "通过仪表盘按钮跳过",
"hist_note_sensor_triggered": "传感器触发器已触发",
"hist_note_initial": "创建任务时设置的初始值",
"hist_note_auto_recovered": "自动完成:传感器已恢复({value})",
"hist_note_reset": "重置为 {date}",
"hist_note_trigger_replaced": "触发实体已替换:{old} → {new}",
"hist_note_trigger_removed": "传感器触发器已移除(原实体:{entity})。计划已转换为{schedule}。",
"hist_note_compound_removed": "已从组合触发器中移除实体 {entity};剩余 {count} 个条件。",
"recent_activities": "近期活动",
"search_notes": "搜索备注",
"avg_cost": "平均成本",
@@ -703,6 +782,7 @@
"on_complete_action_desc": "任务完成时调用 HA 服务 — 例如重置设备上的物理计数器。",
"on_complete_action_target": "目标实体",
"on_complete_action_target_hint": "注意:实体的域必须与服务匹配 — 例如 'button.press' 仅适用于 button.* 实体,'counter.increment' 仅适用于 counter.* 实体等。如果不匹配,动作将静默失败。",
"on_complete_action_skip_auto": "任务自行完成时(其传感器已恢复)不触发",
"on_complete_action_data": "数据(JSON, 可选)",
"on_complete_action_test": "验证配置",
"on_complete_action_test_success": "✓ 配置有效(动作将在任务完成时触发)",
@@ -958,6 +1038,7 @@
"adopt_summary_existing": "“{name}”:任务 {before} → {after}",
"adopt_problem_adopt": "采用所选",
"adopt_problem_done": "已采用 {tasks} 个问题传感器",
"adopt_problem_done_one": "已采用 1 个问题传感器",
"views_label": "视图",
"views_none": "— 无视图 —",
"views_manage": "保存/管理视图",
@@ -1013,6 +1094,7 @@
"setups_none": "未找到具有未连接耗材传感器的受支持设备。",
"setups_adopt": "配置所选项",
"setups_done": "已创建 {tasks} 个传感器联动任务。",
"setups_done_one": "已创建 1 个传感器联动任务。",
"complete_parts_used": "本次使用的部件",
"part_delete_confirm": "删除部件“{name}”?其库存跟踪、任务关联及未完成的购买提醒将被移除。",
"baseline_start_value": "起始读数(可选)",
@@ -1035,6 +1117,16 @@
"setups_reason_sibling": "另一台设备上的相同型号",
"setups_maybe_covered": "可能已存在为“{name}”",
"setups_already": "已存在:{names}",
"setups_reset_line": "完成时也会重置集成中的计数器(“{button}”)",
"setups_reset_enable": "— 为此将启用该按钮",
"reset_offers_title": "完成时重置计数器",
"reset_offers_hint": "这些任务监视由集成自行维护的计数器。关联后,在此完成任务时也会按下集成的重置按钮 — 否则计数器会继续累计,任务会立即再次到期。",
"reset_offers_before": "现在:完成后 {integration} 中的计数器继续累计",
"reset_offers_after": "之后:还会按下“{button}”",
"reset_offers_renamed": "设置后已重命名 — 请确认此任务对应该部件",
"reset_offers_apply": "关联重置",
"reset_offers_done": "{count} 个任务现在会在完成时重置计数器",
"reset_offers_done_one": "1 个任务现在会在完成时重置计数器",
"setups_before_after": "对象的任务:{before} → {after}",
"setups_new_object_count": "新对象“{name}” · 任务:{count}",
"schedule_preview_title": "下次日期",
@@ -1046,6 +1138,7 @@
"history_auto": "自动",
"battery_fleet_title": "电池群",
"battery_fleet_none_low": "所有电池正常 — 无需更换。",
"battery_fleet_progress": "待更换:{n}",
"battery_fleet_buy_now": "现在购买",
"battery_fleet_soon": "即将需要",
"battery_fleet_soon_hint": "根据上次更换日期预测 — 提前订购。",
@@ -1099,8 +1192,12 @@
"dismiss": "忽略",
"gs_label": "入门提示——随着配置的完善,这些提示会自动消失",
"gs_setups_chip": "推荐配置发现 {n} 台设备(含预设触发器)",
"gs_setups_chip_one": "推荐配置发现 1 台设备(含预设触发器)",
"gs_adopt_chip": "{n} 个问题传感器可转换为维护任务",
"gs_adopt_chip_one": "1 个问题传感器可转换为维护任务",
"gs_fleet_chip": "一键设置电池车队",
"gs_reset_chip": "{n} 个任务可以重置集成中的计数器",
"gs_reset_chip_one": "1 个任务可以重置集成中的计数器",
"cal_editor_window": "默认时间窗",
"cal_editor_window_week": "一周(7天)",
"cal_editor_window_fortnight": "两周(14天)",
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,301 @@
/*! maintenance_supporter frontend 2.95.0 */
import{e as y}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-UJICOAU3.js";import{d as m}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-LEWJHPDY.js";import{a as h}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-GGJ6YWZO.js";import{a as o,b as u,c as n,f as l,h as v,l as g,m as d,s as r,u as f,y as b}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";var a=class extends v{constructor(){super(...arguments);this._open=!1;this._loading=!1;this._adopting=!1;this._error="";this._sensors=[];this._selected=new Set;this._objectNames={};this._objects=[];this._covered={};this._users=[];this._responsible="";this._forMinutes="0";this._localeReady=!1;this._userService=null;this._toggle=t=>{let i=new Set(this._selected);i.has(t)?i.delete(t):i.add(t),this._selected=i};this._toggleAll=()=>{this._selected.size===this._sensors.length?this._selected=new Set:this._selected=new Set(this._sensors.map(t=>t.entity_id))};this._adopt=async()=>{if(this._selected.size===0||this._adopting)return;this._error="";let t=this._sensors.filter(e=>this._selected.has(e.entity_id)).map(e=>({entity_id:e.entity_id,name:e.name,entry_id:this._existingEntryFor(e)??void 0,object_name:this._effectiveName(e),device_id:e.device_id??void 0,part_id:e.suggested_part_id??void 0,responsible_user_id:this._responsible||void 0,for_minutes:parseInt(this._forMinutes,10)>0?parseInt(this._forMinutes,10):void 0})),i=await h(this,{type:"maintenance_supporter/problem_sensors/adopt",selections:t},{busy:e=>{this._adopting=e},onError:e=>{this._error=e}});i!==void 0&&(this.dispatchEvent(new CustomEvent("problem-sensors-adopted",{bubbles:!0,composed:!0,detail:i})),this._open=!1)}}get _lang(){return b(this.hass)}updated(t){t.has("hass")&&this.hass&&!this._localeReady&&(this._localeReady=!0,f(this._lang).then(()=>this.requestUpdate()))}async open(){this._open=!0,this._loading=!0,this._error="",this._sensors=[],this._selected=new Set,this._objectNames={},this._responsible="",this._forMinutes="0",this._userService?this._userService.updateHass(this.hass):this._userService=new y(this.hass);let[t,i,e]=await Promise.all([h(this,{type:"maintenance_supporter/problem_sensors/discover"},{onError:s=>{this._error=s}}),this._userService.getUsers().catch(()=>[]),this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects"}).catch(()=>({objects:[]}))]);this._loading=!1,t!==void 0&&(this._objects=(e?.objects||[]).filter(s=>!s.object.archived_at).map(s=>({entry_id:s.entry_id,name:s.object.name,tasks:(s.tasks||[]).length})),this._sensors=t?.sensors||[],this._covered=Object.fromEntries(this._sensors.map(s=>[s.entity_id,s.covered_by??null])),this._selected=new Set(this._sensors.filter(s=>!s.covered_by).map(s=>s.entity_id)),this._users=i)}_defaultName(t){return t.suggested_entry_id?t.suggested_object_name:t.candidate?.name??t.suggested_object_name}_effectiveName(t){return(this._objectNames[t.entity_id]??"").trim()||this._defaultName(t)}_existingEntryFor(t){let i=this._effectiveName(t),e=t.suggested_entry_id||t.target_entry_id||null;if(i===this._defaultName(t)&&e)return e;let s=this._objects.find(c=>c.name.trim().toLowerCase()===i.toLowerCase());return s?s.entry_id:null}_schedulePreview(){clearTimeout(this._previewTimer),this._previewTimer=setTimeout(()=>{this._preview()},350)}async _preview(){let t=this._sensors.map(e=>({entity_id:e.entity_id,name:e.name,entry_id:this._existingEntryFor(e)})),i=await h(this,{type:"maintenance_supporter/problem_sensors/preview",selections:t},{onError:()=>{}});i?.covered&&(this._covered={...this._covered,...i.covered})}_summary(t){let i=new Map;for(let e of this._sensors){if(!this._selected.has(e.entity_id))continue;let s=this._existingEntryFor(e),c=this._effectiveName(e),_=s??`new:${c.toLowerCase()}`,p=i.get(_)??{name:c,entry:s,adding:0};p.adding+=1,i.set(_,p)}return i.size===0?l:n`
<div class="summary">
<div class="summary-title">${r("adopt_summary_title",t)}</div>
${[...i.values()].map(e=>{if(!e.entry)return n`<div class="summary-line new">
${r("setups_new_object_count",t).replace("{name}",e.name).replace("{count}",String(e.adding))}
</div>`;let s=this._objects.find(c=>c.entry_id===e.entry)?.tasks??0;return n`<div class="summary-line">
${r("adopt_summary_existing",t).replace("{name}",e.name).replace("{before}",String(s)).replace("{after}",String(s+e.adding))}
</div>`})}
</div>
`}_close(){clearTimeout(this._previewTimer),this._open=!1}_targetLabel(t,i){if(t.candidate&&this._existingEntryFor(t)===t.candidate.entry_id){let e=t.candidate.reasons.map(s=>r(`setups_reason_${s}`,i)).join(", ");return r("setups_target_match",i).replace("{name}",t.candidate.name).replace("{reasons}",e)}return this._effectiveName(t)}render(){if(!this._open)return n``;let t=this._lang,i=this._sensors.length>0&&this._selected.size===this._sensors.length;return n`
<div class="overlay" @click=${this._close}>
<div class="card" @click=${e=>e.stopPropagation()}>
<div class="title">${r("adopt_problem_title",t)}</div>
<div class="hint">${r("adopt_problem_hint",t)}</div>
${this._error?n`<div class="error">${this._error}</div>`:l}
${this._loading?n`<div class="loading">…</div>`:this._sensors.length===0?n`<div class="empty">${r("adopt_problem_none",t)}</div>`:n`
<label class="select-all">
<input
type="checkbox"
.checked=${i}
@change=${this._toggleAll}
/>
<span>${r("selected",t)}: ${this._selected.size} / ${this._sensors.length}</span>
</label>
<div class="row-sub adopt-object-hint">${r("adopt_object_hint",t)}</div>
<datalist id="adopt-object-names">
${this._objects.map(e=>n`<option value=${e.name}></option>`)}
</datalist>
<div class="list">
${this._sensors.map(e=>{let s=this._selected.has(e.entity_id),c=e.state==="on",_=[e.device_name,e.area_name].filter(Boolean).join(" \xB7 ");return n`
<label class="row">
<input
type="checkbox"
.checked=${s}
@change=${()=>this._toggle(e.entity_id)}
/>
<div class="row-main">
<div class="row-top">
<span class="row-name">${e.name}</span>
<span class="chip ${c?"chip-active":"chip-ok"}">
${c?r("adopt_problem_active",t):r("adopt_problem_ok",t)}
</span>
</div>
${_?n`<div class="row-sub">${_}</div>`:l}
${s?n`<div class="row-object" @click=${p=>p.stopPropagation()}>
<input
class="adopt-object"
list="adopt-object-names"
aria-label=${r("object",t)}
placeholder=${this._defaultName(e)}
.value=${this._objectNames[e.entity_id]??this._defaultName(e)}
@input=${p=>{this._objectNames={...this._objectNames,[e.entity_id]:p.target.value},this._schedulePreview()}}
/>
</div>`:l}
<div class="row-target">
→ ${this._targetLabel(e,t)}${this._existingEntryFor(e)?l:n` <span class="new-tag">${r("adopt_problem_new_object",t)}</span>`}
</div>
${this._covered[e.entity_id]?n`<div class="maybe">
${r("setups_maybe_covered",t).replace("{name}",this._covered[e.entity_id].name)}
</div>`:l}
${e.suggested_part_name?n`<div class="row-part">
<ha-icon icon="mdi:package-variant-closed"></ha-icon>
${r("adopt_problem_part",t).replace("{name}",e.suggested_part_name)}
</div>`:l}
</div>
</label>
`})}
</div>
`}
${!this._loading&&this._sensors.length>0?this._summary(t):l}
${!this._loading&&this._sensors.length>0?n`
<label class="responsible">
<span>${r("for_at_least_minutes",t)}</span>
<input
class="for-input"
type="number"
min=${m[0]}
max=${m[1]}
.value=${this._forMinutes}
@input=${e=>this._forMinutes=e.target.value}
/>
</label>
<div class="for-hint">${r("adopt_for_minutes_hint",t)}</div>
`:l}
${!this._loading&&this._sensors.length>0&&this._users.length>0?n`
<label class="responsible">
<span>${r("adopt_problem_responsible",t)}</span>
<select
.value=${this._responsible}
@change=${e=>{this._responsible=e.target.value}}
>
<option value="" ?selected=${!this._responsible}>${r("no_user_assigned",t)}</option>
${this._users.map(e=>n`<option value=${e.id} ?selected=${e.id===this._responsible}>${e.name}</option>`)}
</select>
</label>
`:l}
<div class="actions">
<ha-button appearance="plain" @click=${this._close}>
${r("cancel",t)}
</ha-button>
<ha-button
@click=${this._adopt}
.disabled=${this._selected.size===0||this._adopting}
>
${r("adopt_problem_adopt",t)}
</ha-button>
</div>
</div>
</div>
`}};a.styles=u`
.overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.card {
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
border-radius: 12px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
min-width: min(360px, calc(100vw - 24px));
max-width: 560px;
width: 90vw;
max-height: 80vh;
overflow: hidden;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}
.title {
font-size: 18px;
font-weight: 500;
}
.hint {
color: var(--secondary-text-color);
font-size: 13px;
}
.error {
color: var(--error-color, #f44336);
font-size: 13px;
}
.loading,
.empty {
color: var(--secondary-text-color);
font-size: 14px;
padding: 12px 0;
}
.select-all {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: var(--secondary-text-color);
cursor: pointer;
}
.select-all input {
cursor: pointer;
}
.list {
display: flex;
flex-direction: column;
gap: 6px;
overflow-y: auto;
max-height: 50vh;
}
.row {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 8px;
border: 1px solid var(--divider-color);
border-radius: 6px;
cursor: pointer;
}
.row input {
margin-top: 2px;
cursor: pointer;
}
.row-main {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
flex: 1;
}
.row-top {
display: flex;
align-items: center;
gap: 8px;
}
.row-name {
font-weight: 500;
font-size: 13px;
}
.row-sub {
color: var(--secondary-text-color);
font-size: 12px;
}
.row-object { margin-top: 6px; }
.row-object input {
width: 100%; box-sizing: border-box; padding: 6px 8px; font: inherit;
border: 1px solid var(--divider-color); border-radius: 6px;
background: var(--card-background-color); color: var(--primary-text-color);
}
.adopt-object-hint { margin: 0 0 8px; }
.row-target {
color: var(--secondary-text-color);
font-size: 12px;
}
.row-part {
color: var(--secondary-text-color);
font-size: 12px;
display: flex;
align-items: center;
gap: 4px;
}
.row-part ha-icon {
--mdc-icon-size: 14px;
}
.new-tag {
font-style: italic;
}
.maybe {
font-size: 11px;
color: var(--warning-color, #ff9800);
}
.summary {
font-size: 12px;
border-top: 1px dashed var(--divider-color);
padding-top: 6px;
}
.summary-title {
font-weight: 500;
margin-bottom: 2px;
}
.summary-line {
color: var(--primary-color);
}
.chip {
font-size: 11px;
padding: 1px 8px;
border-radius: 10px;
white-space: nowrap;
}
.chip-active {
background: var(--error-color, #f44336);
color: #fff;
}
.chip-ok {
background: var(--divider-color);
color: var(--secondary-text-color);
}
.responsible {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: var(--secondary-text-color);
flex-wrap: wrap;
}
.for-input {
width: 70px;
background: var(--card-background-color);
color: var(--primary-text-color);
border: 1px solid var(--divider-color);
border-radius: 4px;
padding: 4px 6px;
}
.for-hint {
font-size: 11px;
color: var(--secondary-text-color);
margin: -4px 0 2px;
}
.responsible select {
flex: 1;
min-width: 140px;
padding: 4px 6px;
border-radius: 4px;
border: 1px solid var(--divider-color);
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
font-size: 13px;
}
.actions {
display: flex;
justify-content: flex-end;
gap: 8px;
padding-top: 8px;
}
`,o([g({attribute:!1})],a.prototype,"hass",2),o([d()],a.prototype,"_open",2),o([d()],a.prototype,"_loading",2),o([d()],a.prototype,"_adopting",2),o([d()],a.prototype,"_error",2),o([d()],a.prototype,"_sensors",2),o([d()],a.prototype,"_selected",2),o([d()],a.prototype,"_objectNames",2),o([d()],a.prototype,"_objects",2),o([d()],a.prototype,"_covered",2),o([d()],a.prototype,"_users",2),o([d()],a.prototype,"_responsible",2),o([d()],a.prototype,"_forMinutes",2);customElements.get("maintenance-adopt-problem-sensors-dialog")||customElements.define("maintenance-adopt-problem-sensors-dialog",a);export{a as MaintenanceAdoptProblemSensorsDialog};
@@ -0,0 +1,277 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as W}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-APJICCRG.js";import{a as o}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-XSFV5MUM.js";import{f as T,g as K,h as z,i as M,j as Y,k as Q,l as U,m as q,n as R,o as E,p as G}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YKVD2DJ5.js";import{a as A}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-E7KPGZZO.js";import{e as F,f as I}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-S7ZP4PVX.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-ODPGZXCU.js";import{b as P}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-JEWIFUZC.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-UVBHIULM.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-WUMSAU4G.js";import{B as $,C as g,F as O,G as S,J as w,L as N,a as b,c as p,f as y,h as B,l as v,m as k,n as C,q as D,s as a,u as H,y as L}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";function X(_,r,t,s){let d=_.entries.filter(e=>e.type==="completed").sort((e,i)=>e.ts-i.ts),l=`${_.from?t.date(_.from):"\u2026"} \u2013 ${_.to?t.date(_.to):"\u2026"}`,n=_.totals,h=[[r.completions,t.number(n.completions)],[r.totalCost,t.cost(n.totalCost)],[r.avgCost,n.avgCost!=null?t.cost(n.avgCost):r.none],[r.totalTime,n.totalDuration?t.duration(n.totalDuration):r.none]].map(([e,i])=>`<div class="kpi"><div class="k">${o(e)}</div><div class="v">${o(i)}</div></div>`).join(""),c=_.byObject.map(e=>`<tr>
<td>${o(e.objectName)}</td>
<td class="num">${o(t.number(e.completions))}</td>
<td class="num">${o(t.cost(e.cost))}</td>
<td class="num">${o(t.share(e.share))}</td>
</tr>`).join(""),m=_.buckets.buckets.reduce((e,i)=>Math.max(e,i.cost),0),f=_.buckets.buckets.map(e=>{let i=m>0?Math.round(e.cost/m*100):0;return`<tr>
<td class="nowrap">${o(t.bucket(e))}</td>
<td class="num">${o(t.number(e.completions))}</td>
<td class="bar-cell">${i>0?`<span class="bar" style="width:${i}%"></span>`:""}</td>
<td class="num">${o(t.cost(e.cost))}</td>
</tr>`}).join(""),j=d.map(e=>{let i=[e.notes,e.completedBy?`${r.completedBy}: ${e.completedBy}`:null].filter(Boolean).join(" \xB7 "),x=e.phaseName?`${e.taskName} \xB7 ${e.phaseName}`:e.taskName;return`<tr>
<td class="nowrap">${o(t.date(e.timestamp))}</td>
<td>${o(e.objectName)}</td>
<td>${o(x)}</td>
<td class="num">${e.cost!=null?o(t.cost(e.cost)):o(r.none)}</td>
<td class="num">${e.duration!=null?o(t.duration(e.duration)):o(r.none)}</td>
<td class="notes">${o(i)||o(r.none)}</td>
</tr>`}).join(`
`);return`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light">
<title>${o(r.title)} \u2014 ${o(_.areaName)}</title>
<style>
/* Printable sheet: it opens as a blob in whatever viewer the OS supplies
(Companion = WebView, dark phones paint a dark default canvas), so the
document states its own light scheme and paints its background. */
:root { color-scheme: light; }
* { box-sizing: border-box; }
body { font: 13px/1.5 -apple-system, Segoe UI, Roboto, sans-serif; color: #1a1a1a; background: #fff; margin: 32px; }
h1 { font-size: 22px; margin: 0 0 2px; }
h2 { font-size: 15px; margin: 24px 0 8px; }
.sub { color: #666; margin: 0 0 16px; }
.kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 0 0 8px; }
.kpi { border: 1px solid #ddd; border-radius: 6px; padding: 8px 10px; }
.kpi .k { color: #777; font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; }
.kpi .v { font-size: 16px; font-weight: 600; }
table { border-collapse: collapse; width: 100%; }
th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: #666; border-bottom: 2px solid #ccc; padding: 6px 8px; }
td { border-bottom: 1px solid #e5e5e5; padding: 6px 8px; vertical-align: top; }
td.num, th.num { text-align: right; white-space: nowrap; }
td.nowrap { white-space: nowrap; }
td.notes { color: #444; }
td.bar-cell { width: 40%; vertical-align: middle; }
.bar { display: block; height: 10px; background: #9aa7b8; border-radius: 0 3px 3px 0;
-webkit-print-color-adjust: exact; print-color-adjust: exact; }
tfoot td { border-bottom: none; border-top: 2px solid #ccc; font-weight: 600; }
tr { break-inside: avoid; }
.cap-note { margin-top: 14px; color: #888; font-size: 11px; }
@media print { body { margin: 12mm; } }
</style>
</head>
<body>
<h1>${o(r.title)} \u2014 ${o(_.areaName)}</h1>
<p class="sub">${o(r.period)}: ${o(l)} \xB7 ${o(r.generated)} ${o(t.date(s))}</p>
<div class="kpis">${h}</div>
<h2>${o(r.costPerObject)}</h2>
<table>
<thead><tr>
<th>${o(r.colObject)}</th><th class="num">${o(r.completions)}</th>
<th class="num">${o(r.colCost)}</th><th class="num">${o(r.share)}</th>
</tr></thead>
<tbody>${c||`<tr><td colspan="4">${o(r.none)}</td></tr>`}</tbody>
<tfoot><tr>
<td>${o(r.totalCost)}</td><td class="num">${o(t.number(n.completions))}</td>
<td class="num">${o(t.cost(n.totalCost))}</td><td></td>
</tr></tfoot>
</table>
<h2>${o(r.costPerBucket)}</h2>
<table>
<thead><tr>
<th>${o(r.period)}</th><th class="num">${o(r.completions)}</th>
<th></th><th class="num">${o(r.colCost)}</th>
</tr></thead>
<tbody>${f||`<tr><td colspan="4">${o(r.none)}</td></tr>`}</tbody>
</table>
<h2>${o(r.historyHeading)} (${o(t.number(d.length))})</h2>
<table>
<thead><tr>
<th>${o(r.colDate)}</th><th>${o(r.colObject)}</th><th>${o(r.colTask)}</th>
<th class="num">${o(r.colCost)}</th><th class="num">${o(r.colDuration)}</th><th>${o(r.colNotes)}</th>
</tr></thead>
<tbody>
${j||`<tr><td colspan="6">${o(r.none)}</td></tr>`}
</tbody>
<tfoot><tr>
<td colspan="3">${o(r.totalCost)}</td>
<td class="num">${o(t.cost(n.totalCost))}</td>
<td class="num">${n.totalDuration?o(t.duration(n.totalDuration)):""}</td><td></td>
</tr></tfoot>
</table>
${_.capped?`<p class="cap-note">${o(r.capNote)}</p>`:""}
</body>
</html>`}var J=25,Z=5,V={completed:C.ok,missed:C.overdue,reset:C.paused,skipped:"var(--secondary-text-color)"},u=class extends B{constructor(){super(...arguments);this.areaKey="";this.objects=[];this.showArchived=!1;this.currencySymbol="";this.userName=()=>null;this._from="";this._to="";this._entryFilter="";this._taskQuery="";this._expanded=!1;this._printing=!1;this._histories=new W(this);this._localeReady=!1;this._filtersFor=null;this._memo=null}createRenderRoot(){return this}get _lang(){return L(this.hass)}willUpdate(t){if(super.willUpdate(t),t.has("areaKey")&&this._filtersFor!==this.areaKey){this._filtersFor=this.areaKey;let s=R();this._from=s.from,this._to=s.to,this._entryFilter="",this._taskQuery="",this._expanded=!1}if(t.has("objects")||t.has("areaKey")||t.has("showArchived")||t.has("hass")&&t.get("hass")===void 0){let s=this._areaObjects().flatMap(d=>d.tasks.map(l=>({entryId:d.entry_id,task:l})));this._histories.sync(this.hass,s)}}updated(t){super.updated(t),!this._localeReady&&this.hass&&(this._localeReady=!0,H(this._lang).then(()=>this.requestUpdate()))}_areaObjects(){return z(this.objects,this.areaKey,this.showArchived).sort((t,s)=>t.object.name.localeCompare(s.object.name))}_entries(t){let s=[this.objects,this.areaKey,this.showArchived,this._histories.version];if(this._memo&&this._memo.deps.every((l,n)=>l===s[n]))return this._memo.entries;let d=M(t,(l,n)=>this._histories.historyOf(l,n));return this._memo={deps:s,entries:d},d}_figures(){let t=this._areaObjects(),s=this._entries(t),d={from:this._from||null,to:this._to||null},l=Y(s,{...d,entryId:this._entryFilter||null,taskQuery:this._taskQuery}),n=this._entryFilter?t.filter(h=>h.entry_id===this._entryFilter):t;return{objects:t,entries:s,filtered:l,totals:Q(l),buckets:q(l,d),byObject:U(l,n)}}_setRange(t){this._from=t.from,this._to=t.to,this._expanded=!1}_openObject(t){this.dispatchEvent(new CustomEvent("open-object",{detail:{entryId:t},bubbles:!0,composed:!0}))}_openTask(t,s){this.dispatchEvent(new CustomEvent("open-task",{detail:{entryId:t,taskId:s},bubbles:!0,composed:!0}))}_bucketLabel(t,s){return t.month==null?String(t.year):`${N(t.month,this._lang,s)} ${t.year}`}_countText(t,s,d){let l=this._lang;return d===1?a(s,l):a(t,l).replace("{n}",$(d,l))}async _print(){if(this._printing)return;let t=I();this._printing=!0;try{await this._histories.settled()}finally{this._printing=!1}let s=this._lang,d=this.currencySymbol,{filtered:l,totals:n,buckets:h,byObject:c}=this._figures(),m={title:a("area_report_title",s),generated:a("report_generated",s),period:a("area_report_period",s),completions:a("area_kpi_completions",s),totalCost:a("total_cost",s),avgCost:a("avg_cost",s),totalTime:a("area_kpi_total_time",s),costPerObject:a("area_cost_per_object",s),costPerBucket:h.unit==="month"?a("area_cost_per_month",s):a("area_cost_per_year",s),share:a("area_cost_share",s),historyHeading:a("area_history_section",s),colDate:a("date",s),colObject:a("object",s),colTask:a("task_name",s),colCost:a("cost",s),colDuration:a("duration",s),colNotes:a("notes_label",s),completedBy:a("completed_by",s),capNote:a("object_history_cap_note",s),none:"\u2014"},f=l.filter(i=>i.type==="completed"),j=l.map(i=>({...i,completedBy:i.completedBy?this.userName(i.completedBy):null,notes:i.notes?A(i.notes,s):null})),e=X({areaName:T(this.areaKey,this.hass?.areas,a("no_area",s)),from:this._from||f[f.length-1]?.timestamp||null,to:this._to||P(new Date),totals:n,byObject:c,buckets:h,entries:j,capped:this._histories.capped},m,{date:i=>O(i,s),cost:i=>g(i,d,s),duration:i=>w(i,s),bucket:i=>this._bucketLabel(i,"long"),share:i=>`${$(i*100,s,0)} %`,number:i=>$(i,s)},new Date().toISOString());F(e,t)}_renderRangeChips(t){let s=this._lang,d=new Date,l=R(d),n=c=>this._from===c.from&&this._to===c.to,h=G(t,d.getFullYear()).slice(0,Z);return p`
<div class="filter-chips area-range-chips">
<button class="filter-chip ${n(l)?"active":""}" @click=${()=>this._setRange(R())}>
${a("area_range_12m",s)}
</button>
${h.map(c=>p`
<button class="filter-chip ${n(E(c))?"active":""}" @click=${()=>this._setRange(E(c))}>${c}</button>
`)}
<button class="filter-chip ${!this._from&&!this._to?"active":""}" @click=${()=>this._setRange({from:"",to:""})}>
${a("area_range_all",s)}
</button>
</div>
`}_renderChart(t){let s=this._lang,d=this.currencySymbol,l=t.reduce((c,m)=>Math.max(c,m.cost),0);if(l<=0)return p`<p class="area-empty">${a("area_no_costs",s)}</p>`;let n=Math.max(1,Math.ceil(t.length/12)),h=t.map((c,m)=>({b:c,i:m})).filter(({i:c})=>c%n===0);return p`
<div class="area-chart">
<div class="area-chart-max">${g(l,d,s)}</div>
<div class="area-chart-bars">
${t.map(c=>{let m=`${this._bucketLabel(c,"long")}: ${g(c.cost,d,s)} \xB7 ${a("area_kpi_completions",s)}: ${$(c.completions,s)}`;return p`<div class="area-bar" title=${m} aria-label=${m}>
${c.cost>0?p`<div class="area-bar-fill" style="height: ${Math.round(c.cost/l*1e3)/10}%"></div>`:y}
</div>`})}
</div>
<div class="area-chart-axis ${n>1?"grouped":""}">
${h.map(({b:c,i:m})=>p`<span class="area-bar-label" style="flex-grow: ${Math.min(n,t.length-m)}">${c.month==null?String(c.year):p`${N(c.month,s,"short")}${c.month===0||m===0?p`<br />${c.year}`:y}`}</span>`)}
</div>
</div>
`}render(){if(!this.hass||!this.areaKey)return y;let t=this._lang,s=this.currencySymbol,{objects:d,entries:l,filtered:n,totals:h,buckets:c,byObject:m}=this._figures(),f=d.reduce((e,i)=>e+i.tasks.filter(x=>this.showArchived||!x.archived).length,0),j=this._expanded?n:n.slice(0,J);return p`
<div class="detail-section area-view">
<div class="detail-header">
<h2 class="area-title">
<ha-icon .icon=${K(this.areaKey,this.hass.areas)}></ha-icon>
${T(this.areaKey,this.hass.areas,a("no_area",t))}
</h2>
<div class="action-buttons">
<ha-button appearance="plain" class="area-print" .disabled=${this._printing} @click=${()=>this._print()}>
<ha-icon icon="mdi:printer-outline"></ha-icon>
${this._printing?a("loading",t):a("area_report_print",t)}
</ha-button>
</div>
</div>
<p class="meta">
${this._countText("area_object_count","area_object_count_one",d.length)} ·
${this._countText("templates_task_count","templates_task_count_one",f)}
${this._histories.loading?p` · <span class="area-loading">${a("loading",t)}</span>`:y}
</p>
${this._renderRangeChips(l)}
<div class="filter-bar area-filters">
<ms-date-field
kind="date"
clearable
.hass=${this.hass}
.lang=${t}
.label=${a("date_from",t)}
.value=${this._from}
@value-changed=${e=>{this._from=e.detail.value}}
></ms-date-field>
<ms-date-field
kind="date"
clearable
.hass=${this.hass}
.lang=${t}
.label=${a("date_to",t)}
.value=${this._to}
@value-changed=${e=>{this._to=e.detail.value}}
></ms-date-field>
<label class="filter-field">
<span class="filter-label">${a("object",t)}</span>
<select class="area-object-filter" .value=${this._entryFilter}
@change=${e=>{this._entryFilter=e.target.value}}>
<option value="" ?selected=${!this._entryFilter}>${a("all_objects",t)}</option>
${d.map(e=>p`<option value=${e.entry_id} ?selected=${e.entry_id===this._entryFilter}>${e.object.name}</option>`)}
</select>
</label>
<input
type="search"
class="search-input area-task-filter"
aria-label=${a("area_task_filter",t)}
placeholder=${a("area_task_filter",t)}
.value=${this._taskQuery}
@input=${e=>{this._taskQuery=e.target.value}}
/>
</div>
<div class="kpi-bar area-kpis">
<div class="kpi-card">
<div class="kpi-label">${a("area_kpi_completions",t)}</div>
<div class="kpi-value-large area-kpi-completions">${$(h.completions,t)}</div>
</div>
<div class="kpi-card">
<div class="kpi-label">${a("total_cost",t)}</div>
<div class="kpi-value-large area-kpi-cost">${g(h.totalCost,s,t)}</div>
</div>
<div class="kpi-card">
<div class="kpi-label">${a("avg_cost",t)}</div>
<div class="kpi-value-large">${h.avgCost!=null?g(h.avgCost,s,t):"\u2014"}</div>
</div>
<div class="kpi-card">
<div class="kpi-label">${a("area_kpi_total_time",t)}</div>
<div class="kpi-value-large">${h.totalDuration?w(h.totalDuration,t):"\u2014"}</div>
</div>
</div>
<h3>${c.unit==="month"?a("area_cost_per_month",t):a("area_cost_per_year",t)}</h3>
${this._renderChart(c.buckets)}
<h3>${a("area_cost_per_object",t)}</h3>
<div class="objects-table-wrap">
<table class="objects-table area-object-table">
<thead>
<tr>
<th>${a("object",t)}</th>
<th class="num">${a("area_kpi_completions",t)}</th>
<th class="num">${a("cost",t)}</th>
<th class="num">${a("area_cost_share",t)}</th>
</tr>
</thead>
<tbody>
${m.map(e=>p`
<tr class="objects-table-row" @click=${()=>this._openObject(e.entryId)}>
<td><span class="objects-table-name">${e.objectName}</span></td>
<td class="num">${$(e.completions,t)}</td>
<td class="num">${g(e.cost,s,t)}</td>
<td class="num">
<span class="area-share"><span class="area-share-fill" style="width: ${Math.round(e.share*100)}%"></span></span>
${$(e.share*100,t,0)} %
</td>
</tr>
`)}
</tbody>
</table>
</div>
<h3>
${a("area_history_section",t)}
<span class="area-count">${$(n.length,t)}</span>
</h3>
${n.length===0?p`<p class="area-empty">${a("object_history_empty",t)}</p>`:p`
<div class="objects-table-wrap">
<table class="objects-table area-history-table">
<thead>
<tr>
<th>${a("date",t)}</th>
<th></th>
<th>${a("object",t)}</th>
<th>${a("task_name",t)}</th>
<th class="num">${a("cost",t)}</th>
<th class="num">${a("duration",t)}</th>
<th>${a("notes_label",t)}</th>
</tr>
</thead>
<tbody>
${j.map(e=>{let i=e.notes?A(e.notes,t):"";return p`
<tr class="objects-table-row area-history-row" @click=${()=>this._openTask(e.entryId,e.taskId)}>
<td title=${S(e.timestamp,t)}>${O(e.timestamp,t)}</td>
<td>
<span class="area-entry-type" style="color: ${V[e.type]??"inherit"}">
<ha-icon .icon=${D[e.type]||"mdi:circle"}></ha-icon>${a(e.type,t)}
</span>
</td>
<td>
<button class="area-object-link" @click=${x=>{x.stopPropagation(),this._openObject(e.entryId)}}>
${e.objectName}
</button>
</td>
<td><button class="area-task-link">${e.taskName}${e.phaseName?` \xB7 ${e.phaseName}`:""}</button></td>
<td class="num">${e.cost!=null?g(e.cost,s,t):"\u2014"}</td>
<td class="num">${e.duration!=null?w(e.duration,t):"\u2014"}</td>
<td class="oc-notes" title=${i}>${i||"\u2014"}</td>
</tr>
`})}
</tbody>
</table>
</div>
${n.length>j.length?p`<ha-button appearance="plain" class="area-more" @click=${()=>{this._expanded=!0}}>
${a("show_all",t)} (${$(n.length,t)})
</ha-button>`:y}
`}
${this._histories.capped?p`<p class="area-cap-note">${a("object_history_cap_note",t)}</p>`:y}
</div>
`}};b([v({attribute:!1})],u.prototype,"hass",2),b([v()],u.prototype,"areaKey",2),b([v({attribute:!1})],u.prototype,"objects",2),b([v({type:Boolean})],u.prototype,"showArchived",2),b([v()],u.prototype,"currencySymbol",2),b([v({attribute:!1})],u.prototype,"userName",2),b([k()],u.prototype,"_from",2),b([k()],u.prototype,"_to",2),b([k()],u.prototype,"_entryFilter",2),b([k()],u.prototype,"_taskQuery",2),b([k()],u.prototype,"_expanded",2),b([k()],u.prototype,"_printing",2);customElements.get("maintenance-area-view")||customElements.define("maintenance-area-view",u);export{u as MaintenanceAreaView};
@@ -0,0 +1,54 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as C}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-APJICCRG.js";import{q as A,r as j,s as E,t as L,u as R}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YKVD2DJ5.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-ODPGZXCU.js";import{a as _,b as w,c as S}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YQT7IJJB.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-JEWIFUZC.js";import{B as g,C as v,F as k,a as l,c as a,f as m,h as y,l as p,m as b,s as r,u as $,y as f}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";var O=[{key:"name",label:"area",num:!1},{key:"objects",label:"objects",num:!0},{key:"tasks",label:"tasks",num:!0},{key:"overdue",label:"overdue",num:!0},{key:"due_soon",label:"due_soon",num:!0},{key:"cost_year",label:"area_cost_year",num:!0},{key:"cost_total",label:"total_cost",num:!0},{key:"last",label:"last_performed",num:!1}],i=class extends y{constructor(){super(...arguments);this.objects=[];this.showArchived=!1;this.currencySymbol="";this._query="";this._sort=j(w(_.areaSort));this._histories=new C(this);this._localeReady=!1;this._memo=null}createRenderRoot(){return this}get _lang(){return f(this.hass)}willUpdate(e){if(super.willUpdate(e),e.has("objects")||e.has("showArchived")||e.has("hass")&&e.get("hass")===void 0){let o=this.objects.filter(s=>this.showArchived||!s.object.archived).flatMap(s=>s.tasks.map(n=>({entryId:s.entry_id,task:n})));this._histories.sync(this.hass,o)}}updated(e){super.updated(e),!this._localeReady&&this.hass&&(this._localeReady=!0,$(this._lang).then(()=>this.requestUpdate()))}_rows(e){let o=this._lang,s=[this.objects,this.showArchived,this._histories.version,this.hass?.areas,o,e];if(this._memo&&this._memo.deps.every((c,h)=>c===s[h]))return this._memo.rows;let n=A(this.objects,{showArchived:this.showArchived,areas:this.hass?.areas,noAreaLabel:r("no_area",o),year:e,historyOf:(c,h)=>this._histories.historyOf(c,h)});return this._memo={deps:s,rows:n},n}_setSort(e){this._sort=E(this._sort,e),S(_.areaSort,`${this._sort.key}:${this._sort.dir}`)}_open(e){this.dispatchEvent(new CustomEvent("open-area",{detail:{areaKey:e},bubbles:!0,composed:!0}))}_toggleArchived(){this.dispatchEvent(new CustomEvent("archived-toggle",{bubbles:!0,composed:!0}))}_headerLabel(e,o,s){return e==="area_cost_year"?r("area_cost_year",s).replace("{year}",String(o)):r(e,s)}render(){if(!this.hass)return m;let e=this._lang,o=new Date().getFullYear(),s=this.currencySymbol,n=this._rows(o),c=L(R(n,this._query),this._sort),h=this.objects.filter(t=>t.object.archived).length,d=t=>g(t,e);return a`
<div class="filter-bar area-filter-bar">
<input
type="search"
class="search-input"
aria-label=${r("areas_filter",e)}
placeholder=${r("areas_filter",e)}
.value=${this._query}
@input=${t=>{this._query=t.target.value}}
/>
${this._histories.loading?a`<span class="area-loading">${r("loading",e)}</span>`:m}
${h>0?a`<ha-button class="archived-toggle ${this.showArchived?"active":""}" @click=${()=>this._toggleArchived()}>
<ha-icon icon="mdi:archive-outline"></ha-icon>
${this.showArchived?r("hide_archived",e):`${r("show_archived",e)} (${h})`}
</ha-button>`:m}
</div>
${n.length===0?a`<div class="empty-state">${r("no_objects",e)}</div>`:c.length===0?a`<div class="empty-state">${r("areas_filter_none",e)}</div>`:a`
<div class="objects-table-wrap">
<table class="objects-table areas-table">
<thead>
<tr>
${O.map(t=>{let u=this._sort.key===t.key;return a`<th class=${t.num?"num":""}
aria-sort=${u?this._sort.dir==="asc"?"ascending":"descending":"none"}>
<button class="area-sort ${u?"active":""}" title=${r("sort_label",e)} @click=${()=>this._setSort(t.key)}>
${this._headerLabel(t.label,o,e)}
${u?a`<ha-icon icon=${this._sort.dir==="asc"?"mdi:arrow-up":"mdi:arrow-down"}></ha-icon>`:m}
</button>
</th>`})}
</tr>
</thead>
<tbody>
${c.map(t=>a`
<tr class="objects-table-row" tabindex="0"
@click=${()=>this._open(t.key)}
@keydown=${u=>{u.key==="Enter"&&this._open(t.key)}}>
<td>
<ha-icon class="area-row-icon" .icon=${t.icon}></ha-icon>
<span class="objects-table-name">${t.name}</span>
</td>
<td class="num">${d(t.objects)}</td>
<td class="num">${d(t.tasks)}</td>
<td class="num">${t.overdue?a`<span class="area-count overdue">${d(t.overdue)}</span>`:d(0)}</td>
<td class="num">${t.dueSoon?a`<span class="area-count due-soon">${d(t.dueSoon)}</span>`:d(0)}</td>
<td class="num">${v(t.costYear,s,e)}</td>
<td class="num">${v(t.costTotal,s,e)}</td>
<td>${t.lastCompletion?k(t.lastCompletion,e):"\u2014"}</td>
</tr>
`)}
</tbody>
</table>
</div>
`}
`}};l([p({attribute:!1})],i.prototype,"hass",2),l([p({attribute:!1})],i.prototype,"objects",2),l([p({type:Boolean})],i.prototype,"showArchived",2),l([p()],i.prototype,"currencySymbol",2),l([b()],i.prototype,"_query",2),l([b()],i.prototype,"_sort",2);customElements.get("maintenance-areas-view")||customElements.define("maintenance-areas-view",i);export{i as MaintenanceAreasView};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,153 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as u}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-GGJ6YWZO.js";import{a as r,b as _,c as l,f as o,h as p,l as d,m as s,s as i,y as h}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";var a=class extends p{constructor(){super(...arguments);this.objects=[];this._open=!1;this._loading=!1;this._error="";this._name="";this._manufacturer="";this._model="";this._serialNumber="";this._areaId="";this._installationDate="";this._warrantyExpiry="";this._documentationUrl="";this._notes="";this._haDeviceId="";this._parentEntryId="";this._entryId=null}get _lang(){return h(this.hass)}openCreate(){this._entryId=null,this._name="",this._manufacturer="",this._model="",this._serialNumber="",this._areaId="",this._installationDate="",this._warrantyExpiry="",this._documentationUrl="",this._notes="",this._haDeviceId="",this._parentEntryId="",this._error="",this._open=!0}openEdit(e,n){this._entryId=e,this._name=n.name||"",this._manufacturer=n.manufacturer||"",this._model=n.model||"",this._serialNumber=n.serial_number||"",this._areaId=n.area_id||"",this._installationDate=n.installation_date||"",this._warrantyExpiry=n.warranty_expiry||"",this._documentationUrl=n.documentation_url||"",this._notes=n.notes||"",this._haDeviceId=n.ha_device_id||"",this._parentEntryId=n.parent_entry_id||"",this._error="",this._open=!0}async _save(){if(this._loading||!this._name.trim())return;this._error="";let e={name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null};await u(this,this._entryId?{type:"maintenance_supporter/object/update",entry_id:this._entryId,...e}:{type:"maintenance_supporter/object/create",...e},{busy:t=>{this._loading=t},fallbackKey:"save_error",onError:t=>{this._error=t}})!==void 0&&(this._open=!1,this.dispatchEvent(new CustomEvent("object-saved")))}_parentChoices(){return(this.objects||[]).filter(e=>e.entry_id!==this._entryId)}_close(){this._open=!1}render(){if(!this._open)return l``;let e=this._lang,n=this._entryId?i("edit_object",e):i("new_object",e);return l`
<ha-dialog open @closed=${this._close}>
<div class="dialog-title">${n}</div>
<div class="content">
${this._error?l`<div class="error">${this._error}</div>`:o}
<ms-textfield
label="${i("name",e)}"
required
.value=${this._name}
@input=${t=>this._name=t.target.value}
></ms-textfield>
<ms-textfield
label="${i("manufacturer_optional",e)}"
.value=${this._manufacturer}
@input=${t=>this._manufacturer=t.target.value}
></ms-textfield>
<ms-textfield
label="${i("model_optional",e)}"
.value=${this._model}
@input=${t=>this._model=t.target.value}
></ms-textfield>
<ms-textfield
label="${i("serial_number_optional",e)}"
.value=${this._serialNumber}
@input=${t=>this._serialNumber=t.target.value}
></ms-textfield>
<ms-textfield
label="${i("documentation_url_optional",e)}"
type="url"
.value=${this._documentationUrl}
@input=${t=>this._documentationUrl=t.target.value}
></ms-textfield>
<ha-area-picker
.hass=${this.hass}
label="${i("area_id_optional",e)}"
.value=${this._areaId}
@value-changed=${t=>this._areaId=t.detail.value||""}
></ha-area-picker>
<ms-date-field
kind="date"
clearable
.hass=${this.hass}
.lang=${e}
label="${i("installation_date_optional",e)}"
.value=${this._installationDate}
@value-changed=${t=>this._installationDate=t.detail.value}
></ms-date-field>
<ms-date-field
kind="date"
clearable
.hass=${this.hass}
.lang=${e}
label="${i("warranty_expiry_optional",e)}"
.value=${this._warrantyExpiry}
@value-changed=${t=>this._warrantyExpiry=t.detail.value}
></ms-date-field>
<ha-form
.hass=${this.hass}
.data=${{device:this._haDeviceId||void 0}}
.schema=${[{name:"device",selector:{device:{}}}]}
.computeLabel=${()=>i("link_device_optional",e)}
@value-changed=${t=>this._haDeviceId=t.detail.value?.device||""}
></ha-form>
${this._parentChoices().length?l`<label class="textarea-field">
<span class="textarea-label">${i("parent_object_optional",e)}</span>
<select
class="parent-select"
.value=${this._parentEntryId}
@change=${t=>this._parentEntryId=t.target.value}
>
<option value="" ?selected=${!this._parentEntryId}>
${i("parent_none",e)}
</option>
${this._parentChoices().map(t=>l`<option
value=${t.entry_id}
?selected=${this._parentEntryId===t.entry_id}
>${t.object.name}</option>`)}
</select>
</label>`:o}
<label class="textarea-field">
<span class="textarea-label">${i("object_notes_optional",e)}</span>
<textarea
rows="3"
.value=${this._notes}
@input=${t=>this._notes=t.target.value}
></textarea>
<span class="md-hint">${i("notes_markdown_hint",e)}</span>
</label>
</div>
<div class="dialog-actions">
<ha-button appearance="plain" @click=${this._close}>
${i("cancel",this._lang)}
</ha-button>
<ha-button
@click=${this._save}
.disabled=${this._loading||!this._name.trim()}
>
${this._loading?i("saving",this._lang):i("save",this._lang)}
</ha-button>
</div>
</ha-dialog>
`}};a.styles=_`
.dialog-title {
font-size: 18px;
font-weight: 500;
padding-bottom: 12px;
}
.content {
display: flex;
flex-direction: column;
gap: 16px;
min-width: 300px;
}
.dialog-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
padding-top: 16px;
}
ms-textfield {
display: block;
}
.textarea-field {
display: flex; flex-direction: column; gap: 4px;
}
.textarea-label {
font-size: 12px; color: var(--secondary-text-color, #888); font-weight: 500;
}
.textarea-field textarea {
padding: 8px 10px; font-size: 14px; font-family: inherit;
background: var(--secondary-background-color, rgba(0,0,0,0.06));
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
resize: vertical;
}
.textarea-field textarea:focus {
outline: none; border-color: var(--primary-color);
}
.md-hint {
font-size: 11px; color: var(--secondary-text-color); font-style: italic;
}
.parent-select {
padding: 8px 10px; font-size: 14px; font-family: inherit;
background: var(--secondary-background-color, rgba(0,0,0,0.06));
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
}
.error {
color: var(--error-color, #f44336);
font-size: 13px;
}
`,r([d({attribute:!1})],a.prototype,"hass",2),r([d({attribute:!1})],a.prototype,"objects",2),r([s()],a.prototype,"_open",2),r([s()],a.prototype,"_loading",2),r([s()],a.prototype,"_error",2),r([s()],a.prototype,"_name",2),r([s()],a.prototype,"_manufacturer",2),r([s()],a.prototype,"_model",2),r([s()],a.prototype,"_serialNumber",2),r([s()],a.prototype,"_areaId",2),r([s()],a.prototype,"_installationDate",2),r([s()],a.prototype,"_warrantyExpiry",2),r([s()],a.prototype,"_documentationUrl",2),r([s()],a.prototype,"_notes",2),r([s()],a.prototype,"_haDeviceId",2),r([s()],a.prototype,"_parentEntryId",2),r([s()],a.prototype,"_entryId",2);customElements.get("maintenance-object-dialog")||customElements.define("maintenance-object-dialog",a);export{a};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as r}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-LEWJHPDY.js";var a={operatorWriteEnabled:!1,operatorIds:[]};function p(e,t=a){return e?e.is_admin?!0:t.operatorWriteEnabled&&t.operatorIds.includes(e.id):!1}var d=["buttons_compact","buttons","icons"];function _(e){let[t,n]=r.default_warning_days,s=e?.general?.default_warning_days,i=e?.general?.row_action_style;return{features:{...o.features,...e?.features??{}},defaultWarningDays:typeof s=="number"&&Number.isFinite(s)&&s>=t&&s<=n?s:o.defaultWarningDays,rowActionStyle:d.includes(i??"")?i:o.rowActionStyle,access:{operatorWriteEnabled:e?.operator_write_enabled===!0,operatorIds:Array.isArray(e?.admin_panel_user_ids)?e.admin_panel_user_ids.filter(u=>typeof u=="string"):[]},budget:e?.budget??null,rowActionNoticePending:e?.general?.row_action_notice_pending===!0,refsInLists:e?.general?.ref_numbers_in_lists===!0,objectsTableColumns:Array.isArray(e?.objects_table_columns)?e.objects_table_columns:void 0}}var o={features:{adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1},defaultWarningDays:7,rowActionStyle:"buttons_compact",access:a,budget:null,rowActionNoticePending:!1,refsInLists:!1,objectsTableColumns:void 0};function l(){let e=window;return e.__msSettingsCache??={promise:null}}function b(e){let t=l();if(t.promise)return t.promise;let n=e.connection.sendMessagePromise({type:"maintenance_supporter/settings"}).then(s=>_(s)).catch(()=>(t.promise===n&&(t.promise=null),o));return t.promise=n,n}function h(){l().promise=null}var c=class{constructor(){this._handle=null}schedule(t,n=4e3){this.clear(),this._handle=setTimeout(()=>{this._handle=null,t()},n)}clear(){this._handle!==null&&(clearTimeout(this._handle),this._handle=null)}get pending(){return this._handle!==null}};export{a,p as b,d as c,_ as d,b as e,h as f,c as g};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,234 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as k}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-WUMSAU4G.js";import{a as r,b as f,c as n,f as u,h as x,l as h,m as c,s as e}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";function d(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function _(a){return!a.startsWith("data:image/svg+xml,")&&!a.startsWith("data:image/png;base64,")?"":d(a)}function R(a){return a.replace(/[/\\:*?"<>|#%]+/g,"").replace(/\s+/g,"-").toLowerCase().substring(0,100)}var l=class extends x{constructor(){super(...arguments);this.lang="en";this._open=!1;this._loading=!1;this._error="";this._viewResult=null;this._completeResult=null;this._quickResult=null;this._urlMode="companion";this._entryId="";this._taskId=null;this._objectName="";this._taskName="";this._generateSeq=0}openForObject(t,i){this._entryId=t,this._taskId=null,this._objectName=i,this._taskName="",this._urlMode="companion",this._error="",this._viewResult=null,this._completeResult=null,this._quickResult=null,this._open=!0,this._generate()}openForTask(t,i,s,o){this._entryId=t,this._taskId=i,this._objectName=s,this._taskName=o,this._urlMode="companion",this._error="",this._viewResult=null,this._completeResult=null,this._quickResult=null,this._open=!0,this._generate()}async _generate(){let t=++this._generateSeq;this._loading=!0,this._error="",this._viewResult=null,this._completeResult=null,this._quickResult=null;try{let i={type:"maintenance_supporter/qr/generate",entry_id:this._entryId,url_mode:this._urlMode};this._taskId&&(i.task_id=this._taskId);let s=[this.hass.connection.sendMessagePromise({...i,action:"view"})];this._taskId&&(s.push(this.hass.connection.sendMessagePromise({...i,action:"complete"})),await this._hasQuickCompleteDefaults()&&s.push(this.hass.connection.sendMessagePromise({...i,action:"quick_complete"})));let o=await Promise.all(s);if(t!==this._generateSeq)return;this._viewResult=o[0],o.length>1&&(this._completeResult=o[1]),o.length>2&&(this._quickResult=o[2])}catch(i){if(t!==this._generateSeq)return;let s=i?.code,o=i?.message;this._error=s==="no_url"||typeof o=="string"&&o.includes("No Home Assistant URL")?e("qr_error_no_url",this.lang):e("qr_error",this.lang)}finally{t===this._generateSeq&&(this._loading=!1)}}async _hasQuickCompleteDefaults(){try{let i=((await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId})).tasks||[]).find(s=>s.id===this._taskId);return!!i?.quick_complete_defaults&&Object.keys(i.quick_complete_defaults).length>0}catch{return!1}}_setUrlMode(t){this._urlMode!==t&&(this._urlMode=t,this._generate())}_print(){if(!this._viewResult)return;let t=this._viewResult,i=t.label.task_name?`${t.label.object_name} \u2014 ${t.label.task_name}`:t.label.object_name,s=[t.label.manufacturer,t.label.model].filter(Boolean).join(" "),o=window.open("","_blank","width=600,height=500");if(!o)return;let p=this.lang||"en",m=d(i),g=d(s),v=!!this._completeResult,b=!!this._quickResult,q=d(e("qr_action_view",p)),w=d(e("qr_action_complete",p)),$=d(e("qr_action_quick_complete",p));o.document.write(`<!DOCTYPE html><html><head><meta charset="utf-8">
<meta name="color-scheme" content="light">
<title>${m}</title>
<style>
/* Printable sheet \u2014 must not inherit the phone's dark theme. The QR images
carry their own white quiet zone and stay scannable either way, but the
labels below are explicit dark greys and would vanish on a WebView's dark
canvas. Same reasoning as helpers/report.ts. */
:root{color-scheme:light}
body{font-family:sans-serif;text-align:center;padding:20px;background:#fff;color:#1a1a1a}
h2{margin:0 0 4px}
.sub{color:#666;font-size:14px;margin-bottom:16px}
.qr-row{display:flex;justify-content:center;gap:24px;margin:12px 0}
.qr-col{display:flex;flex-direction:column;align-items:center;gap:6px}
.qr-col img{width:${b?"170px":v?"200px":"280px"}}
.qr-label{font-size:13px;font-weight:500;color:#333}
.url{font-size:10px;color:#999;word-break:break-all;margin-top:8px;max-width:480px}
</style></head><body>
<h2>${m}</h2>
${g?`<div class="sub">${g}</div>`:""}
<div class="qr-row">
<div class="qr-col">
<img src="${_(this._viewResult.svg_data_uri)}" alt="QR Info" />
<div class="qr-label">${q}</div>
</div>
${v?`<div class="qr-col">
<img src="${_(this._completeResult.svg_data_uri)}" alt="QR Complete" />
<div class="qr-label">${w}</div>
</div>`:""}
${b?`<div class="qr-col">
<img src="${_(this._quickResult.svg_data_uri)}" alt="QR Quick-complete" />
<div class="qr-label">${$}</div>
</div>`:""}
</div>
<div class="url">${d(this._viewResult.url)}</div>
<script>setTimeout(()=>window.print(),300)<\/script>
</body></html>`),o.document.close()}_downloadSvg(t,i){let s=decodeURIComponent(t.svg_data_uri.replace("data:image/svg+xml,","")),o=this._taskName?`${this._objectName}-${this._taskName}`:this._objectName;k(s,`qr-${R(o)}-${i}.svg`,"image/svg+xml")}_close(){this._open=!1,this._viewResult=null,this._completeResult=null,this._quickResult=null,this._error="",this._loading=!1}render(){if(!this._open)return n``;let t=this.lang||this.hass?.language||"en",i=this._taskName?`${e("qr_code",t)}: ${this._objectName} \u2014 ${this._taskName}`:`${e("qr_code",t)}: ${this._objectName}`,s=!!this._viewResult;return n`
<ha-dialog open @closed=${this._close}>
<div class="dialog-title">${i}</div>
<div class="content">
${this._loading?n`<div class="loading">${e("qr_generating",t)}</div>`:this._error?n`<div class="error">${this._error}</div>`:s?n`
<div class="qr-pair">
<div class="qr-item">
<img
class="qr-image ${this._completeResult?"small":""}"
src="${this._viewResult.svg_data_uri}"
alt="QR Info"
/>
<div class="qr-item-label">${e("qr_action_view",t)}</div>
<button class="dl-btn"
@click=${()=>this._downloadSvg(this._viewResult,"info")}>
<ha-icon icon="mdi:download"></ha-icon>
${e("qr_download",t)}
</button>
</div>
${this._completeResult?n`
<div class="qr-item">
<img
class="qr-image small"
src="${this._completeResult.svg_data_uri}"
alt="QR Complete"
/>
<div class="qr-item-label">${e("qr_action_complete",t)}</div>
<button class="dl-btn"
@click=${()=>this._downloadSvg(this._completeResult,"complete")}>
<ha-icon icon="mdi:download"></ha-icon>
${e("qr_download",t)}
</button>
</div>
`:u}
${this._quickResult?n`
<div class="qr-item quick">
<img
class="qr-image small"
src="${this._quickResult.svg_data_uri}"
alt="QR Quick-complete"
/>
<div class="qr-item-label">${e("qr_action_quick_complete",t)}</div>
<button class="dl-btn"
@click=${()=>this._downloadSvg(this._quickResult,"quick-complete")}>
<ha-icon icon="mdi:download"></ha-icon>
${e("qr_download",t)}
</button>
</div>
`:u}
</div>
<div class="url-display">${this._viewResult.url}</div>
`:u}
<div class="action-row">
<label>${e("qr_url_mode",t)}</label>
<div class="action-toggle">
<button class="toggle-btn ${this._urlMode==="companion"?"active":""}"
@click=${()=>this._setUrlMode("companion")}>${e("qr_mode_companion",t)}</button>
<button class="toggle-btn ${this._urlMode==="local"?"active":""}"
@click=${()=>this._setUrlMode("local")}>${e("qr_mode_local",t)}</button>
<button class="toggle-btn ${this._urlMode==="server"?"active":""}"
@click=${()=>this._setUrlMode("server")}>${e("qr_mode_server",t)}</button>
</div>
</div>
</div>
<div class="dialog-actions">
<ha-button appearance="plain" @click=${this._close}>
${e("cancel",t)}
</ha-button>
<ha-button
@click=${this._print}
.disabled=${!s}
>
${e("qr_print",t)}
</ha-button>
</div>
</ha-dialog>
`}};l.styles=f`
.dialog-title {
font-size: 18px;
font-weight: 500;
padding-bottom: 12px;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
min-width: 300px;
}
.dialog-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
padding-top: 16px;
}
.qr-pair {
display: flex;
flex-wrap: wrap; /* three codes (quick-complete, #192) wrap on a phone */
gap: 20px;
justify-content: center;
width: 100%;
}
.qr-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}
.qr-image {
width: 240px;
height: 240px;
image-rendering: pixelated;
}
.qr-image.small {
width: 180px;
height: 180px;
}
.qr-item-label {
max-width: 180px;
font-size: 12px;
font-weight: 500;
color: var(--secondary-text-color);
text-align: center;
}
.dl-btn {
display: inline-flex;
align-items: center;
gap: 6px;
background: none;
border: 1px solid var(--divider-color, #e0e0e0);
cursor: pointer;
font-size: 13px;
color: var(--primary-text-color);
padding: 6px 14px;
border-radius: 18px;
transition: background 0.2s, border-color 0.2s;
}
.dl-btn:hover {
background: var(--secondary-background-color, #f5f5f5);
border-color: var(--primary-color);
}
.dl-btn ha-icon {
--mdc-icon-size: 18px;
}
.url-display {
font-size: 11px;
color: var(--secondary-text-color);
word-break: break-all;
text-align: center;
max-width: 400px;
}
.loading {
padding: 40px 0;
color: var(--secondary-text-color);
}
.error {
padding: 20px 0;
color: var(--error-color, #f44336);
}
.action-row {
display: flex;
flex-direction: column;
gap: 6px;
width: 100%;
}
.action-row label {
font-size: 13px;
color: var(--secondary-text-color);
}
.action-toggle {
display: flex;
gap: 4px;
background: var(--divider-color, #e0e0e0);
border-radius: 6px;
padding: 3px;
}
.toggle-btn {
flex: 1;
padding: 8px 12px;
border: none;
background: transparent;
color: var(--primary-text-color);
cursor: pointer;
border-radius: 4px;
font-size: 13px;
transition: all 0.2s;
line-height: 1.3;
}
.toggle-btn:hover {
background: rgba(0, 0, 0, 0.05);
}
.toggle-btn.active {
background: var(--primary-color);
color: var(--text-primary-color, #fff);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}
`,r([h({attribute:!1})],l.prototype,"hass",2),r([h()],l.prototype,"lang",2),r([c()],l.prototype,"_open",2),r([c()],l.prototype,"_loading",2),r([c()],l.prototype,"_error",2),r([c()],l.prototype,"_viewResult",2),r([c()],l.prototype,"_completeResult",2),r([c()],l.prototype,"_quickResult",2),r([c()],l.prototype,"_urlMode",2);customElements.get("maintenance-qr-dialog")||customElements.define("maintenance-qr-dialog",l);export{l as a};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as y}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YKVD2DJ5.js";var l=6;async function g(e,i,n){let r=new Array(e.length),a=0,t=async()=>{for(;a<e.length;){let s=a++;r[s]=await n(e[s],s)}},o=Math.min(Math.max(1,i),e.length);return await Promise.all(Array.from({length:o},t)),r}function u(e){let i=e.history?.length??0;return typeof e.history_count!="number"||e.history_count>i}function d(e){return JSON.stringify([e.history_count??null,e.history??[]])}function h(e,i){return`${e}:${i}`}var c=class{constructor(i){this._host=i;this._cache=new Map;this._inFlight=new Map;this._running=0;this._pending=Promise.resolve();this.version=0;i.addController(this)}hostConnected(){}get loading(){return this._running>0}get capped(){for(let i of this._cache.values())if(i.entries.length>=y)return!0;return!1}historyOf(i,n){return this._cache.get(h(i,n.id))?.entries??n.history??[]}sync(i,n){if(!i?.connection)return this._pending;let r=n.filter(t=>u(t.task)).map(t=>({...t,key:h(t.entryId,t.task.id),sig:d(t.task)})).filter(t=>this._cache.get(t.key)?.sig!==t.sig&&this._inFlight.get(t.key)!==t.sig);if(!r.length)return this._pending;for(let t of r)this._inFlight.set(t.key,t.sig);this._running++,this._host.requestUpdate();let a=g(r,l,async t=>{let o;try{let s=await i.connection.sendMessagePromise({type:"maintenance_supporter/task/history",entry_id:t.entryId,task_id:t.task.id});o=Array.isArray(s?.history)?s.history:t.task.history??[]}catch{o=t.task.history??[]}this._inFlight.get(t.key)===t.sig&&(this._inFlight.delete(t.key),this._cache.set(t.key,{sig:t.sig,entries:o}))}).then(()=>{this._running--,this.version++,this._host.requestUpdate()});return this._pending=Promise.all([this._pending,a]).then(()=>{}),this._pending}settled(){return this._pending}};export{c as a};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{F as n,s as o}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";var l={"Completed from dashboard button":"hist_note_button","Completed from the To-do list":"hist_note_todo","Completed by voice":"hist_note_voice","Completed from the notification":"hist_note_notification","Completed via NFC tag":"hist_note_nfc","Completed from the shopping list":"hist_note_shopping_list","Completed from a mirrored to-do list":"hist_note_todo_mirror","Skipped from notification":"hist_note_skipped_notification","Skipped from dashboard button":"hist_note_skipped_button","Sensor trigger activated":"hist_note_sensor_triggered","Initial value set during task creation":"hist_note_initial"},m=[[/^Auto-completed: sensor recovered \((.+)\)$/,"hist_note_auto_recovered",t=>({value:t[1]})],[/^Reset to (\d{4}-\d{2}-\d{2})$/,"hist_note_reset",(t,e)=>({date:n(t[1],e)})],[/^Trigger entity replaced: (.+) → (.+)$/,"hist_note_trigger_replaced",t=>({old:t[1],new:t[2]})],[/^Sensor trigger removed \(entity was: (.+)\)\. Schedule converted to (\w+)\.$/,"hist_note_trigger_removed",(t,e)=>({entity:t[1],schedule:o(t[2],e)})],[/^Entity (.+) removed from compound trigger; (\d+) conditions remain\.$/,"hist_note_compound_removed",t=>({entity:t[1],count:t[2]})]];function h(t,e){if(!t)return"";let i=l[t.trim()];if(i)return o(i,e);for(let[s,d,_]of m){let r=t.trim().match(s);if(r){let c=_(r,e);return o(d,e).replace(/\{(\w+)\}/g,(a,g)=>c[g]??a)}}return t}export{h as a};
@@ -0,0 +1,79 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as r,b as l,c as i,f as o,h as n,l as t}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";var e=class extends n{constructor(){super(...arguments);this.label="";this.value="";this.placeholder="";this.type="text";this.required=!1;this.disabled=!1;this.multiline=!1;this.rows=3}_onInput(s){let a=s.target.value;this.value=a,this.dispatchEvent(new CustomEvent("input",{bubbles:!0,composed:!0,detail:{value:a}}))}render(){return i`
<label class="field">
${this.label?i`<span class="label">${this.label}${this.required?i`<span class="req">*</span>`:o}</span>`:o}
${this.multiline?i`
<textarea
.value=${this.value??""}
rows=${this.rows}
?required=${this.required}
?disabled=${this.disabled}
placeholder=${this.placeholder}
@input=${this._onInput}
@change=${this._onInput}
></textarea>`:i`
<input
.value=${this.value??""}
.type=${this.type}
?required=${this.required}
?disabled=${this.disabled}
placeholder=${this.placeholder}
step=${this.step??o}
min=${this.min??o}
max=${this.max??o}
pattern=${this.pattern??o}
@input=${this._onInput}
@change=${this._onInput}
/>`}
${this.helper?i`<span class="helper">${this.helper}</span>`:o}
</label>
`}};e.styles=l`
:host { display: block; }
.field {
display: flex;
flex-direction: column;
gap: 4px;
}
.label {
font-size: 12px;
color: var(--secondary-text-color, #888);
font-weight: 500;
}
.req { color: var(--error-color, #f44336); margin-left: 2px; }
input {
padding: 8px 10px;
font-size: 14px;
background: var(--secondary-background-color, rgba(0,0,0,0.06));
color: var(--primary-text-color);
border: 1px solid var(--divider-color, rgba(255,255,255,0.12));
border-radius: 6px;
font-family: inherit;
width: 100%;
box-sizing: border-box;
outline: none;
}
input:focus {
border-color: var(--primary-color);
}
input:disabled { opacity: 0.5; cursor: not-allowed; }
textarea {
padding: 8px 10px;
font-size: 14px;
background: var(--secondary-background-color, rgba(0,0,0,0.06));
color: var(--primary-text-color);
border: 1px solid var(--divider-color, rgba(255,255,255,0.12));
border-radius: 6px;
font-family: inherit;
width: 100%;
box-sizing: border-box;
outline: none;
resize: vertical;
}
textarea:focus { border-color: var(--primary-color); }
textarea:disabled { opacity: 0.5; cursor: not-allowed; }
.helper {
font-size: 11px;
color: var(--secondary-text-color);
font-style: italic;
}
`,r([t()],e.prototype,"label",2),r([t()],e.prototype,"value",2),r([t()],e.prototype,"placeholder",2),r([t()],e.prototype,"type",2),r([t({type:Boolean})],e.prototype,"required",2),r([t({type:Boolean})],e.prototype,"disabled",2),r([t()],e.prototype,"step",2),r([t()],e.prototype,"min",2),r([t()],e.prototype,"max",2),r([t()],e.prototype,"pattern",2),r([t()],e.prototype,"helper",2),r([t({type:Boolean})],e.prototype,"multiline",2),r([t({type:Number})],e.prototype,"rows",2);customElements.get("ms-textfield")||customElements.define("ms-textfield",e);
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
var n={default_warning_days:[0,365],default_consumable_threshold:[1,90],battery_low_percent:[1,90],battery_recovered_percent:[20,100],archive_oneoff_days:[0,3650],delete_archived_oneoff_days:[0,3650],notify_due_soon_interval_hours:[0,720],notify_overdue_interval_hours:[0,720],notify_triggered_interval_hours:[0,720],max_notifications_per_day:[0,1e3],notification_bundle_threshold:[2,20],snooze_duration_hours:[1,168],warranty_reminder_days:[1,365],budget_alert_threshold:[10,100],currency_decimals:[0,3]};function o(e){let r=n[e];if(!r)throw new Error(`not an int-ranged setting: ${e}`);return r}var t=[0,14],_=[0,1440],a=[1,1e4],u=15,d=[.1,.9],s=[0,365],i=[.01,999],b=[.01,9999],A=[.1,5];export{n as a,o as b,t as c,_ as d,a as e,u as f,d as g,s as h,i,b as j,A as k};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
var E={\u00DF:"s","\u1E9E":"s",\u00E6:"a",\u0153:"o",\u00F8:"o",\u0111:"d",\u00F0:"d",\u00FE:"t",\u0142:"l",\u0131:"i"},d=10,R=7,g=4,h=2,S=5,x=3,_=/[a-z0-9]+/g;function u(r){let e="";for(let t of r.toLowerCase()){if(t.charCodeAt(0)<128&&t.length===1){e+=t;continue}let n=E[t];if(n){e+=n;continue}let o=t.normalize("NFKD")[0]||t;e+=o.charCodeAt(0)<128?o:t}return e}function m(r){return u(r).match(_)||[]}function C(r){return u(r).replace(/[^a-z0-9]+/g,"")}function b(r){return r.replace(/ue/g,"u").replace(/oe/g,"o").replace(/ae/g,"a").replace(/ss/g,"s")}function F(r){let e=[];for(let t of m(r)){let n=[t],o=b(t);o&&o!==t&&n.push(o),e.push(n)}return e}function p(r,e){if(r===e)return!0;let t=r.length,n=e.length;if(Math.abs(t-n)>1)return!1;if(t===n){let l=[];for(let i=0;i<t;i++)r[i]!==e[i]&&l.push(i);if(l.length===1)return!0;if(l.length===2&&l[1]===l[0]+1){let i=l[0];return r[i]===e[i+1]&&r[i+1]===e[i]}return!1}let[o,s]=t>n?[r,e]:[e,r],c=0,f=0,a=!1;for(;c<o.length&&f<s.length;)if(o[c]===s[f])c++,f++;else{if(a)return!1;a=!0,c++}return!0}function N(r,e){let t=0;for(let n of r)if(n){if(e===n)return d;if(e.startsWith(n)){t=Math.max(t,R);continue}if(n.length>=x&&e.includes(n)){t=Math.max(t,g);continue}n.length>=S&&t<h&&(p(n,e)||e.length>n.length&&p(n,e.slice(0,n.length)))&&(t=h)}return t}function I(r,e){let t=0;for(let n of m(e))if(t=Math.max(t,N(r,n)),t===d)return t;if(t<g){let n=C(e);for(let o of r)if(o.length>=x&&n.includes(o))return g}return t}function O(r,e){if(!r)return!1;let t=F(e);if(!t.length){let n=u(e.trim());return n.length>0&&u(r).includes(n)}return M(t,[{text:r,weight:1}])>0}function M(r,e){if(!r.length)return 0;let t=e.filter(o=>o.text),n=0;for(let o of r){let s=0;for(let c of t){let f=I(o,c.text)*c.weight;f>s&&(s=f)}if(s===0)return 0;n+=s}return n}export{F as a,O as b,M as c};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{b as s}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-WUMSAU4G.js";async function a(o,n,t=300){return(await o.connection.sendMessagePromise({type:"auth/sign_path",path:n,expires:t})).path}async function r(o,n,t=300){return a(o,`/api/maintenance_supporter/document/${n}`,t)}async function p(o,n,t=""){let e=window.open("about:blank","_blank");try{let i=await r(o,n);e&&(e.location.href=new URL(i+t,window.location.origin).href)}catch(i){throw e&&e.close(),i}}async function l(o,n,t){s(await r(o,n,30),t)}function m(o,n=null){let t=URL.createObjectURL(new Blob([o],{type:"text/html"}));n&&!n.closed?n.location.href=t:window.open(t,"_blank"),setTimeout(()=>URL.revokeObjectURL(t),6e4)}function u(){return window.open("about:blank","_blank")}export{a,r as b,p as c,l as d,m as e,u as f};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{s as a}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";var _=[{key:"name",labelKey:"name",required:!0},{key:"ref_no",labelKey:"ref_number"},{key:"manufacturer",labelKey:"manufacturer"},{key:"model",labelKey:"model"},{key:"serial_number",labelKey:"serial_number_label"},{key:"installation_date",labelKey:"installed"},{key:"warranty_expiry",labelKey:"warranty"},{key:"area_id",labelKey:"area"},{key:"documentation_url",labelKey:"documentation_url_label"},{key:"notes",labelKey:"object_notes_label"},{key:"task_count",labelKey:"tasks"},{key:"actions",labelKey:"actions"}],u=_.map(e=>e.key),i=["name","manufacturer","model","serial_number","installation_date","warranty_expiry","area_id","task_count","actions"];function g(e){if(!Array.isArray(e))return[...i];let n=new Set,r=[];for(let t of e)typeof t=="string"&&u.includes(t)&&!n.has(t)&&(n.add(t),r.push(t));return r.length?(r.includes("name")||r.unshift("name"),r):[...i]}function f(e,n){return a(`home_dwelling_${e==="house"||e==="apartment"?e:"unknown"}`,n)}function m(e,n){if(!e)return"";try{return new Intl.DisplayNames([n],{type:"region"}).of(e)||e}catch{return e}}var l={floors:"home_reason_floors",basement_floor:"home_reason_basement",area_basement:"home_reason_basement",area_garden:"home_reason_garden",area_shed:"home_reason_shed",area_driveway:"home_reason_driveway",area_garage:"home_reason_garage",entity_garage:"home_reason_garage",area_attic:"home_reason_attic",entity_lawn_mower:"home_reason_lawn_mower",entity_gate:"home_reason_gate",area_balcony:"home_reason_balcony",small_home:"home_reason_small_home"},c={ups:"home_reason_ups"};function d(e,n){let r=[];for(let t of e){let o=l[t];if(!o)continue;let s=a(o,n);r.includes(s)||r.push(s)}return r.join(", ")}function b(e,n,r){if(e==="starter")return a("home_reason_starter",n);if(e==="country")return a("home_reason_country",n).replace("{country}",m(r,n));if(e.startsWith("feature_")){let t=e.slice(8),o=l[`area_${t}`]??c[t];return a("home_reason_feature",n).replace("{feature}",o?a(o,n):e)}return a(`home_trait_${e}`,n)}export{_ as a,i as b,g as c,f as d,m as e,d as f,b as g};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{c as r,f as i}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";var a=["#c62828","#ad1457","#6a1b9a","#4527a0","#283593","#1565c0","#00838f","#2e7d32","#558b2f","#ef6c00","#6d4c41","#546e7a"];function u(e){let s=(e||"").split(/\s+/).filter(Boolean);return s.length===0?"?":s.length===1?s[0][0].toUpperCase():(s[0][0]+s[s.length-1][0]).toUpperCase()}function c(e){let s=0;for(let n of e)s=s*31+n.charCodeAt(0)>>>0;return a[s%a.length]}function o(e){return e?{id:e.id,name:e.name,initials:e.initials||u(e.name),color:e.color||c(e.id)}:null}function h(e){return e?r`<span class="person-avatar" style="--person-color: ${e.color}" title=${e.name}>${e.initials}</span>`:i}function m(e,s=""){return e?r`<span class="person-chip ${s}" title=${e.name}>${h(e)}<span class="person-name">${e.name}</span></span>`:i}var l=class{constructor(s){this.usersCache=null;this.cacheTimestamp=0;this.CACHE_TTL_MS=6e4;this.hass=s}updateHass(s){this.hass=s}async getUsers(s=!1){let n=Date.now();if(!s&&this.usersCache&&n-this.cacheTimestamp<this.CACHE_TTL_MS)return this.usersCache;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/users/list"});return this.usersCache=t.users,this.cacheTimestamp=n,this.usersCache}catch(t){return console.error("Failed to fetch users:",t),this.usersCache||[]}}async assignUser(s,n,t){await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/assign_user",entry_id:s,task_id:n,user_id:t})}async getTasksByUser(s){return(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/tasks/by_user",user_id:s})).tasks}getUserName(s){return!s||!this.usersCache?null:this.usersCache.find(t=>t.id===s)?.name||null}getPerson(s){return o(this.getUser(s))}getUser(s){return!s||!this.usersCache?null:this.usersCache.find(n=>n.id===s)||null}getCurrentUserId(){return this.hass.user?.id||null}isCurrentUser(s){return s?s===this.getCurrentUserId():!1}clearCache(){this.usersCache=null,this.cacheTimestamp=0}};export{a,o as b,h as c,m as d,l as e};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,88 @@
/*! maintenance_supporter frontend 2.95.0 */
import{F as m,a,b as y,c as s,f as l,h as g,l as o,m as f,s as d}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";function $(n){let t=m("2001-02-03",n).match(/\d+/g)||[],e=v=>t.findIndex(_=>Number(_)===v),h=e(2001),c=e(2),u=e(3);return h===0?"YMD":c>=0&&u>=0&&c<u?"MDY":"DMY"}function p(n,i,t){if(n<1e3||n>9999||i<1||i>12||t<1||t>31)return null;let e=new Date(n,i-1,t);return e.getFullYear()!==n||e.getMonth()!==i-1||e.getDate()!==t?null:`${n}-${String(i).padStart(2,"0")}-${String(t).padStart(2,"0")}`}function b(n,i){let t=n.trim(),e;if(e=t.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/))return p(+e[1],+e[2],+e[3]);if(e=t.match(/^(\d{4})$/))return p(+e[1],1,1);if(e=t.match(/^(\d{1,2})[./](\d{4})$/))return p(+e[2],+e[1],1);if(e=t.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/))return p(+e[3],+e[2],+e[1]);if(e=t.match(/^(\d{1,2})[/-](\d{1,2})[/-](\d{4})$/)){let h=+e[1],c=+e[2],u=+e[3];return $(i)==="MDY"?p(u,h,c):p(u,c,h)}return null}function x(n,i){if(i)switch(n){case"date":return i.split("T")[0];case"time":return i.length===5?`${i}:00`:i;case"datetime":{let[t,e="00:00:00"]=i.split("T");return`${t} ${e.length===5?`${e}:00`:e}`}}}function k(n,i){if(typeof i!="string"||!i)return"";switch(n){case"date":return i.slice(0,10);case"time":return i.slice(0,5);case"datetime":{let[t,e="00:00:00"]=i.split(" ");return`${t}T${e.length===5?`${e}:00`:e}`}}}var r=class extends g{constructor(){super(...arguments);this.kind="date";this.label="";this.value="";this.clearable=!1;this.disabled=!1;this.required=!1;this.lang="en";this._typing=!1;this._typed="";this._typedInvalid=!1}_startTyping(){this._typed=this.value,this._typedInvalid=!1,this._typing=!0,this.updateComplete.then(()=>this.shadowRoot?.querySelector("input.typed")?.focus())}_commitTyped(){if(!this._typed.trim()){this._typing=!1;return}let t=b(this._typed,this.lang);if(!t){this._typedInvalid=!0;return}this._typing=!1,this._typedInvalid=!1,this._emit(t)}_onTypedKey(t){t.key==="Enter"?(t.preventDefault(),this._commitTyped()):t.key==="Escape"&&(t.preventDefault(),this._typing=!1,this._typedInvalid=!1)}_selector(){switch(this.kind){case"date":return{date:{}};case"time":return{time:{no_second:!0}};case"datetime":return{datetime:{}}}}_onSelectorChange(t){t.stopPropagation(),this._emit(k(this.kind,t.detail?.value))}_clear(){this._emit("")}_emit(t){t!==this.value&&(this.value=t,this.dispatchEvent(new CustomEvent("value-changed",{bubbles:!0,composed:!0,detail:{value:t}})))}render(){return s`
<div class="field">
${this.label?s`<span class="label">${this.label}${this.required?s`<span class="req">*</span>`:l}</span>`:l}
<div class="row">
${this._typing?s`<input class="typed" type="text" inputmode="numeric" autocomplete="off"
.value=${this._typed}
placeholder=${m("1978-03-15",this.lang)}
aria-invalid=${this._typedInvalid?"true":"false"}
@input=${t=>{this._typed=t.target.value,this._typedInvalid=!1}}
@keydown=${this._onTypedKey}
@blur=${this._commitTyped} />`:s`<ha-selector
.hass=${this.hass}
.selector=${this._selector()}
.value=${x(this.kind,this.value)}
.required=${this.required}
.disabled=${this.disabled}
@value-changed=${this._onSelectorChange}
></ha-selector>`}
${this.kind==="date"&&!this.disabled&&!this._typing?s`<button type="button" class="type-toggle" title=${d("date_type_toggle",this.lang)} aria-label=${d("date_type_toggle",this.lang)} @click=${this._startTyping}>
<ha-icon icon="mdi:keyboard-outline"></ha-icon>
</button>`:l}
${this.clearable&&this.value&&!this.disabled&&!this._typing?s`<button type="button" class="clear" title=${d("clear",this.lang)} aria-label=${d("clear",this.lang)} @click=${this._clear}>
<ha-icon icon="mdi:close"></ha-icon>
</button>`:l}
</div>
${this._typedInvalid?s`<span class="helper invalid">${d("date_type_invalid",this.lang)}</span>`:this.helper?s`<span class="helper">${this.helper}</span>`:l}
</div>
`}};r.styles=y`
:host { display: block; }
.field {
display: flex;
flex-direction: column;
gap: 4px;
}
.label {
font-size: 12px;
color: var(--secondary-text-color, #888);
font-weight: 500;
}
.req { color: var(--error-color, #f44336); margin-left: 2px; }
.row {
display: flex;
align-items: center;
gap: 4px;
}
ha-selector {
flex: 1;
min-width: 0;
}
.clear, .type-toggle {
flex: none;
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
padding: 0;
border: none;
border-radius: 50%;
background: transparent;
color: var(--secondary-text-color);
cursor: pointer;
--mdc-icon-size: 20px;
}
.clear:hover, .type-toggle:hover { background: rgba(var(--rgb-primary-text-color, 0, 0, 0), 0.08); }
.clear:focus-visible, .type-toggle:focus-visible { outline: 2px solid var(--primary-color); }
.helper {
font-size: 11px;
color: var(--secondary-text-color);
font-style: italic;
}
.helper.invalid { color: var(--error-color, #f44336); font-style: normal; }
input.typed {
flex: 1;
min-width: 0;
height: 40px;
box-sizing: border-box;
padding: 0 12px;
border: 1px solid var(--divider-color, #ccc);
border-radius: 4px;
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
font: inherit;
}
input.typed[aria-invalid="true"] { border-color: var(--error-color, #f44336); }
input.typed:focus { outline: 2px solid var(--primary-color); outline-offset: -1px; }
`,a([o({attribute:!1})],r.prototype,"hass",2),a([o()],r.prototype,"kind",2),a([o()],r.prototype,"label",2),a([o()],r.prototype,"value",2),a([o()],r.prototype,"helper",2),a([o({type:Boolean})],r.prototype,"clearable",2),a([o({type:Boolean})],r.prototype,"disabled",2),a([o({type:Boolean})],r.prototype,"required",2),a([o()],r.prototype,"lang",2),a([f()],r.prototype,"_typing",2),a([f()],r.prototype,"_typed",2),a([f()],r.prototype,"_typedInvalid",2);customElements.get("ms-date-field")||customElements.define("ms-date-field",r);
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
function c(o,t,e){let l=new Blob([o],{type:e}),d=URL.createObjectURL(l),n=document.createElement("a");n.href=d,n.download=t,n.target="_blank",n.rel="noopener",n.style.display="none",document.body.appendChild(n),n.dispatchEvent(new MouseEvent("click")),document.body.removeChild(n),setTimeout(()=>URL.revokeObjectURL(d),6e4)}function r(o,t){let e=document.createElement("a");e.href=o,e.download=t,e.target="_blank",e.rel="noopener",e.style.display="none",document.body.appendChild(e),e.dispatchEvent(new MouseEvent("click")),document.body.removeChild(e)}export{c as a,r as b};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
async function i(o,n,e){let t=o.auth;if(t?.expired&&t.refreshAccessToken)try{await t.refreshAccessToken()}catch{}return fetch(n,{...e,headers:{...e.headers??{},Authorization:`Bearer ${t?.data?.access_token??""}`}})}var u=500*1024*1024;async function d(o,n,e,t="doc_too_large"){let a=await i(o,n,{method:"POST",body:e});if(a.status===413)throw new Error(t);if(!a.ok)throw new Error("doc_upload_failed");return await a.json()}async function c(o,n,e,t){let a=new FormData;a.append("entry_id",n);for(let s of t)a.append("tags",s);a.append("file",e,e.name);let r=await d(o,"/api/maintenance_supporter/document/upload",a);if(!r.id)throw new Error("doc_upload_failed");return{id:r.id,deduped:!!r.deduped,duplicate_in_object:r.duplicate_in_object??null}}async function m(o,n,e){return(await c(o,n,e,["photo"])).id}async function l(o,n,e){await Promise.all(e.map(t=>o.connection.sendMessagePromise({type:"maintenance_supporter/documents/discard_upload",entry_id:n,doc_id:t}).catch(()=>{})))}export{u as a,d as b,c,m as d,l as e};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
function r(t){return String(t??"").replace(/[&<>"']/g,n=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[n])}export{r as a};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
var r={objectSections:"msp-object-sections",printOptions:"msp-print-options",batteryRosterOpen:"msp-bf-roster-open",docSort:"msp-doc-sort",cameraLabel:"msp-camera-label",overviewTab:"msp-overview-tab",collapsedSections:"msp-collapsed-sections",chartRange:"msp-chart-range",chartHideOutliers:"msp-chart-hide-outliers",taskSort:"maintenance_supporter_sort",objectSort:"maintenance_supporter_object_sort",groupBy:"maintenance_supporter_groupby",objectView:"maintenance_supporter_object_view",objectsCache:"msp-objects-cache",gettingStartedDismissed:"msp-gs-dismissed",batteryRosterSort:"ms_bf_roster_sort",areaSort:"msp-area-sort"};function s(t){try{return localStorage.getItem(t)}catch{return null}}function o(t,e){try{localStorage.setItem(t,e)}catch{}}export{r as a,s as b,o as c};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{B as f,D as g,s as p}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";function m(r){return`${r.entry_id??""}\0${r.part_id}`}function y(r,n,i,o){let e=!!r.entry_id&&r.entry_id!==n,t=e?r.entry_id:n,s=i.find(l=>l.entry_id===t),a=(s?.parts||[]).find(l=>l.id===r.part_id)||null,d=e&&s?.object?.name||"",u=a?.name||p("shared_part_unknown",o);return{part:a,foreign:e,ownerName:d,label:d?`${u} (${d})`:u}}function k(r,n,i,o){let{part:e,label:t}=y(r,n,i,o),s=e&&e.stock!==null&&e.stock!==void 0?` (${g(e.stock,e.unit,o)})`:"",a=e?.storage_location?` \u2014 ${e.storage_location}`:"";return`${f(r.quantity,o)}\xD7 ${t}${s}${a}`}function b(r,n,i,o){let t=(i.find(a=>a.entry_id===n)?.parts||[]).map(a=>({...a})),s=new Set(t.map(a=>m({part_id:a.id})));for(let a of r?.consumes_parts||[]){if(!a.entry_id||a.entry_id===n)continue;let d=m(a);if(s.has(d))continue;s.add(d);let{part:u,ownerName:l}=y(a,n,i,o);t.push({id:a.part_id,name:u?.name||p("shared_part_unknown",o),unit:u?.unit,stock:u?.stock??null,storage_location:u?.storage_location,entry_id:a.entry_id,owner_name:l})}return t}function S(){let r=new Uint8Array(4);return(globalThis.crypto??{getRandomValues:n=>n.map(()=>Math.floor(Math.random()*256))}).getRandomValues(r),Array.from(r,n=>n.toString(16).padStart(2,"0")).join("")}function c(r){let n=r?.reading_values;if(!Array.isArray(n))return[];let i=[],o=new Set;for(let e of n){if(!e||typeof e!="object")continue;let t=e;typeof t.id!="string"||!t.id||o.has(t.id)||typeof t.value!="number"||!Number.isFinite(t.value)||(o.add(t.id),i.push({id:t.id,name:typeof t.name=="string"?t.name:t.id,unit:typeof t.unit=="string"?t.unit:null,value:t.value}))}return i}function _(r){return r.filter(n=>n.type==="completed"&&(n.reading_value!=null||c(n).length>0)).sort((n,i)=>n.timestamp.localeCompare(i.timestamp))}function P(r){return _(r??[]).map(n=>({timestamp:n.timestamp,values:c(n)})).filter(n=>n.values.length>0)}function v(r,n,i){let o;for(let e of r){if(i!==void 0){let s=new Date(e.timestamp).getTime();if(!isNaN(s)&&s>=i)break}let t=e.values.find(s=>s.id===n);t&&(o=t)}return o}function x(r,n,i){let o=c(n).find(t=>t.id===i);if(!o)return null;let e=null;for(let t of _(r)){if(t.timestamp>=n.timestamp)break;let s=c(t).find(a=>a.id===i);s&&(e=s.value)}return e==null?null:o.value-e}function E(r){let n=new Set,i=new Set;for(let o of r){let e=(o.name||"").trim().toLowerCase();e&&(n.has(e)?i.add(o.id):n.add(e))}return i}function L(r){let n=[],i=new Set,o=new Set;for(let e of r){let t=(e.name||"").trim();if(!(!t||i.has(e.id)||o.has(t.toLowerCase()))&&(i.add(e.id),o.add(t.toLowerCase()),n.push({id:e.id,name:t,unit:(e.unit||"").trim()||null}),n.length>=20))break}return n}function N(r){let n=(r??"").trim();if(n==="")return null;let i=Number(n.replace(",","."));return!Number.isFinite(i)||i<0?null:Math.round(i)}var M=["notes","cost","duration","photo","user"],H={notes:"notes_label",cost:"cost",duration:"duration",photo:"photo_label",user:"user_label"};export{m as a,k as b,b as c,S as d,c as e,P as f,v as g,x as h,E as i,L as j,N as k,M as l,H as m};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{d as a}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-GTEFDN23.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-XCDM7D5I.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-YQT7IJJB.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-JEWIFUZC.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-ZCC7RQPW.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-UVBHIULM.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-LEWJHPDY.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-GGJ6YWZO.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";export{a as MaintenanceCompleteDialog};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{F as a,G as b,H as c,I as d,J as e,K as f,L as g,M as h,N as i,O as j,P as k}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-UN244A6U.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-45NFFEKB.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-E7KPGZZO.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-S7ZP4PVX.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-ODPGZXCU.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-3WM7WAL2.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-2SARE4MS.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-FQOUX6W2.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-GTEFDN23.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-XCDM7D5I.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-YQT7IJJB.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-JEWIFUZC.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-ZCC7RQPW.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-UVBHIULM.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-AHDRR46D.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-WUMSAU4G.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-UJICOAU3.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-LEWJHPDY.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-GGJ6YWZO.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";export{b as __resetSettingsCacheForTests,a as getRowActionStyle,h as openCompleteDialog,c as openCreateObjectDialog,e as openCreateTaskDialog,d as openEditObjectDialog,f as openEditTaskDialog,g as openHistoryEditDialog,k as openObjectQuickActions,i as openQrDialog,j as openTaskQuickActions};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-3WM7WAL2.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-FQOUX6W2.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-UVBHIULM.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-GGJ6YWZO.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";export{a as MaintenanceObjectDialog};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-AHDRR46D.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-WUMSAU4G.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";export{a as MaintenanceQrDialog};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,184 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as g}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-GGJ6YWZO.js";import{a as d,b,c as n,f as p,h as x,l as y,m as l,s as r,u as w,y as k}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";var m=u=>`${u.entry_id}/${u.task_id}`,_="__new__",o=class extends x{constructor(){super(...arguments);this._open=!1;this._loading=!1;this._adopting=!1;this._error="";this._setups=[];this._selected=new Set;this._baselines=new Map;this._targets=new Map;this._tasks=new Map;this._objects=[];this._offers=[];this._offerTicks=new Set;this._wiring=!1;this._localeReady=!1;this._wire=async()=>{if(this._wiring)return;let e=this._offers.filter(s=>this._offerTicks.has(m(s))).map(s=>({entry_id:s.entry_id,task_id:s.task_id}));if(e.length===0)return;this._error="";let t=await g(this,{type:"maintenance_supporter/integration_setups/wire_resets",items:e},{busy:s=>{this._wiring=s},onError:s=>{this._error=s}});t!==void 0&&(this.dispatchEvent(new CustomEvent("reset-counters-wired",{bubbles:!0,composed:!0,detail:t})),await this._loadOffers())};this._toggle=e=>{let t=new Set(this._selected);t.has(e)?t.delete(e):t.add(e),this._selected=t};this._adopt=async()=>{if(this._adopting)return;this._error="";let e=[...this._selected].map(s=>{let a=[...this._tasks.get(s)??[]],c={device_id:s,task_names:a},i=this._targets.get(s);i&&i!==_&&(c.entry_id=i);for(let f of a){let h=this._baselines.get(`${s} ${f}`),v=h?parseFloat(h):NaN;!isNaN(v)&&v>=0&&((c.baselines??={})[f]=v)}return c}).filter(s=>s.task_names.length>0);if(e.length===0)return;let t=await g(this,{type:"maintenance_supporter/integration_setups/adopt",selections:e},{busy:s=>{this._adopting=s},onError:s=>{this._error=s}});t!==void 0&&(this.dispatchEvent(new CustomEvent("integration-setups-adopted",{bubbles:!0,composed:!0,detail:t})),this._open=!1)}}get _lang(){return k(this.hass)}updated(e){e.has("hass")&&this.hass&&!this._localeReady&&(this._localeReady=!0,w(this._lang).then(()=>this.requestUpdate()))}_defaultTicks(e){return new Set(e.tasks.filter(t=>!t.covered_by).map(t=>t.task_name))}async open(){this._open=!0,this._loading=!0,this._error="",this._setups=[],this._selected=new Set,this._offers=[],this._loadOffers();let e=await g(this,{type:"maintenance_supporter/integration_setups/discover"},{onError:t=>{this._error=t}});if(e!==void 0){this._setups=e?.setups||[],this._selected=new Set(this._setups.map(t=>t.device_id)),this._baselines=new Map,this._targets=new Map(this._setups.map(t=>[t.device_id,t.target_entry_id||_])),this._tasks=new Map(this._setups.map(t=>[t.device_id,this._defaultTicks(t)]));try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects"});this._objects=(t.objects||[]).filter(s=>!s.object?.archived_at).map(s=>({entry_id:s.entry_id,name:s.object?.name||s.entry_id})).sort((s,a)=>s.name.localeCompare(a.name))}catch{this._objects=[]}}this._loading=!1}_close(){this._open=!1}async _loadOffers(){try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/integration_setups/reset_offers"});this._offers=e.offers||[],this._offerTicks=new Set(this._offers.filter(t=>!t.renamed).map(m))}catch{this._offers=[]}}_toggleOffer(e){let t=new Set(this._offerTicks),s=m(e);t.has(s)?t.delete(s):t.add(s),this._offerTicks=t}_renderOffers(e){if(this._offers.length===0)return p;let t=this._offers.filter(s=>this._offerTicks.has(m(s))).length;return n`
<div class="offers">
<div class="offers-title">${r("reset_offers_title",e)}</div>
<div class="hint">${r("reset_offers_hint",e)}</div>
${this._offers.map(s=>n`
<label class="offer" data-task=${s.task_id}>
<input type="checkbox" class="offer-check" .checked=${this._offerTicks.has(m(s))} @change=${()=>this._toggleOffer(s)} />
<span class="task-text">
<span>${s.task_name} · ${s.object_name}</span>
${s.renamed?n`<span class="offer-renamed">${r("reset_offers_renamed",e)}</span>`:p}
<span class="offer-before">${r("reset_offers_before",e).replace("{integration}",s.integration_name)}</span>
<span class="offer-after">
${r("reset_offers_after",e).replace("{button}",s.button_name)}${s.button_disabled?` ${r("setups_reset_enable",e)}`:""}
</span>
</span>
</label>
`)}
<div class="offers-actions">
<ha-button @click=${this._wire} .disabled=${t===0||this._wiring}>${r("reset_offers_apply",e)}</ha-button>
</div>
</div>
`}_toggleTask(e,t){let s=new Set(this._tasks.get(e)??[]);s.has(t)?s.delete(t):s.add(t),this._tasks=new Map(this._tasks).set(e,s)}async _retarget(e,t){this._targets=new Map(this._targets).set(e.device_id,t);let s=await g(this,{type:"maintenance_supporter/integration_setups/preview",device_id:e.device_id,entry_id:t===_?null:t},{onError:a=>{this._error=a}});!s||!Array.isArray(s.tasks)||(this._setups=this._setups.map(a=>a.device_id===e.device_id?{...a,...s}:a),this._tasks=new Map(this._tasks).set(e.device_id,this._defaultTicks(s)))}get _anythingTicked(){return[...this._selected].some(e=>(this._tasks.get(e)?.size??0)>0)}_targetOptions(e,t){let s=this._targets.get(e.device_id)??_,a=[];if(e.suggested_entry_id)a.push({value:e.suggested_entry_id,label:e.suggested_object_name});else{if(e.candidate){let i=e.candidate.reasons.map(f=>r(`setups_reason_${f}`,t)).join(", ");a.push({value:e.candidate.entry_id,label:r("setups_target_match",t).replace("{name}",e.candidate.name).replace("{reasons}",i)})}a.push({value:_,label:r("setups_target_new",t).replace("{name}",e.device_name)})}let c=new Set(a.map(i=>i.value));for(let i of this._objects)c.has(i.entry_id)||a.push({value:i.entry_id,label:i.name});return n`
<select
class="target-select"
@click=${i=>i.stopPropagation()}
@change=${i=>{this._retarget(e,i.target.value)}}
>
${a.map(i=>n`<option value=${i.value} ?selected=${i.value===s}>${i.label}</option>`)}
</select>
`}_beforeAfter(e,t){let s=this._tasks.get(e.device_id)?.size??0;if((this._targets.get(e.device_id)??_)===_)return r("setups_new_object_count",t).replace("{name}",e.device_name).replace("{count}",String(s));let c=e.target_task_count??0;return r("setups_before_after",t).replace("{before}",String(c)).replace("{after}",String(c+s))}render(){if(!this._open)return n``;let e=this._lang;return n`
<div class="overlay" @click=${this._close}>
<div class="card" @click=${t=>t.stopPropagation()}>
<div class="title">${r("setups_title",e)}</div>
<div class="hint">${r("setups_hint",e)}</div>
${this._error?n`<div class="error">${this._error}</div>`:p}
${this._renderOffers(e)}
${this._loading?n`<div class="loading">…</div>`:this._setups.length===0?this._offers.length===0?n`<div class="empty">${r("setups_none",e)}</div>`:p:n`
<div class="list">
${this._setups.map(t=>{let s=this._selected.has(t.device_id),a=[t.integration_name,t.area_name].filter(Boolean).join(" \xB7 "),c=this._tasks.get(t.device_id)??new Set;return n`
<div class="row ${s?"":"off"}" data-device=${t.device_id}>
<input
type="checkbox"
class="device-check"
.checked=${s}
@change=${()=>this._toggle(t.device_id)}
/>
<div class="row-main">
<div class="row-top">
<span class="row-name">${t.device_name}</span>
</div>
<div class="row-sub">${a}</div>
<div class="row-target">→ ${this._targetOptions(t,e)}</div>
${s?n`
<div class="task-list">
${t.tasks.map(i=>n`
<label class="task" title=${i.entity_ids.join(", ")}>
<input
type="checkbox"
class="task-check"
.checked=${c.has(i.task_name)}
@change=${()=>this._toggleTask(t.device_id,i.task_name)}
/>
<span class="task-text">
<span>${i.task_name_localized||i.task_name}</span>
${i.covered_by?n`<span class="maybe">${r("setups_maybe_covered",e).replace("{name}",i.covered_by.name)}</span>`:p}
${i.reset?n`<span class="reset">↻ ${r("setups_reset_line",e).replace("{button}",i.reset.name)}${i.reset.disabled?` ${r("setups_reset_enable",e)}`:""}</span>`:p}
</span>
</label>
${i.direction==="usage_delta"&&c.has(i.task_name)?n`
<div class="baseline-field">
<span class="baseline-label">${r("setups_baseline_hint",e)}</span>
<input
type="number"
step="any"
min="0"
.value=${this._baselines.get(`${t.device_id} ${i.task_name}`)??""}
@input=${f=>{let h=new Map(this._baselines);h.set(`${t.device_id} ${i.task_name}`,f.target.value),this._baselines=h}}
/>
</div>
`:p}
`)}
${t.already?.length?n`<div class="already">
${r("setups_already",e).replace("{names}",t.already.map(i=>i.existing_name).join(", "))}
</div>`:p}
</div>
<div class="before-after">${this._beforeAfter(t,e)}</div>
`:p}
</div>
</div>
`})}
</div>
`}
<div class="actions">
<ha-button appearance="plain" @click=${this._close}>
${r("cancel",e)}
</ha-button>
<ha-button @click=${this._adopt} .disabled=${!this._anythingTicked||this._adopting}>
${r("setups_adopt",e)}
</ha-button>
</div>
</div>
</div>
`}};o.styles=b`
.overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.card {
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
border-radius: 12px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
min-width: min(360px, calc(100vw - 24px));
max-width: 560px;
width: 90vw;
max-height: 80vh;
overflow: hidden;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}
.title { font-size: 18px; font-weight: 500; }
.hint { color: var(--secondary-text-color); font-size: 13px; }
.error { color: var(--error-color, #f44336); font-size: 13px; }
.loading, .empty { color: var(--secondary-text-color); font-size: 14px; padding: 12px 0; }
.list { display: flex; flex-direction: column; gap: 6px; overflow-y: auto; max-height: 55vh; }
.row {
display: flex; align-items: flex-start; gap: 10px; padding: 8px;
border: 1px solid var(--divider-color); border-radius: 6px;
}
.row.off .row-main { opacity: 0.6; }
.row input { margin-top: 2px; cursor: pointer; }
.row-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.row-name { font-weight: 500; font-size: 13px; }
.row-sub, .row-target { color: var(--secondary-text-color); font-size: 12px; }
.row-target { display: flex; align-items: center; gap: 6px; min-width: 0; }
.target-select {
font-size: 12px; padding: 2px 4px; min-width: 0; max-width: 100%; flex: 1 1 auto;
border: 1px solid var(--divider-color); border-radius: 4px;
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
}
.task-list { display: flex; flex-direction: column; gap: 2px; margin-top: 2px; }
.task { display: flex; align-items: flex-start; gap: 6px; font-size: 13px; cursor: pointer; }
.task-text { display: flex; flex-direction: column; min-width: 0; }
.maybe { font-size: 11px; color: var(--warning-color, #ff9800); }
.already { font-size: 11px; color: var(--secondary-text-color); margin-top: 2px; }
.reset { font-size: 11px; color: var(--secondary-text-color); }
.offers {
display: flex; flex-direction: column; gap: 6px; padding: 8px;
border: 1px solid var(--primary-color); border-radius: 6px;
overflow-y: auto; max-height: 40vh; flex-shrink: 0;
}
.offers-title { font-weight: 500; font-size: 14px; }
.offer { display: flex; align-items: flex-start; gap: 6px; font-size: 13px; cursor: pointer; }
.offer-before { font-size: 11px; color: var(--secondary-text-color); }
.offer-after { font-size: 11px; color: var(--primary-color); }
.offer-renamed { font-size: 11px; color: var(--warning-color, #ff9800); }
.offers-actions { display: flex; justify-content: flex-end; }
.before-after {
font-size: 12px; font-weight: 500; color: var(--primary-color);
border-top: 1px dashed var(--divider-color); padding-top: 4px; margin-top: 2px;
}
.baseline-field {
display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
margin: 0 0 2px 24px; font-size: 12px; color: var(--secondary-text-color);
}
.baseline-field input {
width: 110px; padding: 3px 6px; font-size: 12px;
border: 1px solid var(--divider-color); border-radius: 4px;
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
}
.actions { display: flex; justify-content: flex-end; gap: 8px; padding-top: 8px; }
`,d([y({attribute:!1})],o.prototype,"hass",2),d([l()],o.prototype,"_open",2),d([l()],o.prototype,"_loading",2),d([l()],o.prototype,"_adopting",2),d([l()],o.prototype,"_error",2),d([l()],o.prototype,"_setups",2),d([l()],o.prototype,"_selected",2),d([l()],o.prototype,"_baselines",2),d([l()],o.prototype,"_targets",2),d([l()],o.prototype,"_tasks",2),d([l()],o.prototype,"_objects",2),d([l()],o.prototype,"_offers",2),d([l()],o.prototype,"_offerTicks",2),d([l()],o.prototype,"_wiring",2);customElements.get("maintenance-suggested-setups-dialog")||customElements.define("maintenance-suggested-setups-dialog",o);export{o as MaintenanceSuggestedSetupsDialog};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a,b,c}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-2SARE4MS.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-FQOUX6W2.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-ZCC7RQPW.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-UVBHIULM.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-UJICOAU3.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-LEWJHPDY.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-GGJ6YWZO.js";import"/maintenance_supporter_panelfiles/panel-chunks/chunk-4XNVTWGC.js";export{c as MaintenanceTaskDialog,b as applyTypeFields,a as typeFieldsFromConfig};
@@ -0,0 +1,127 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as w,b as $}from"./chunk-IWH6LGYJ.js";import{a as h,b as o,d as m,e as y,f as v,g as l,h as g,i as _,j as f,k as x,n as p,z as u}from"./chunk-2ARNLSF6.js";import{a as n,g as i}from"./chunk-3MSNNIFG.js";var E=80,s=class extends y{constructor(){super(...arguments);this._config={type:""};this._status=null;this._busy=!1;this._error="";this._localMonthly="";this._localYearly="";this._dirty=!1;this._loaded=!1}setConfig(t){this._config=t}getCardSize(){return 2}get _lang(){return f(this.hass)}get _isAdmin(){return this.hass?.user?.is_admin??!0}updated(t){super.updated(t),_(this,t),t.has("hass")&&this.hass&&!this._loaded&&(this._loaded=!0,this._load())}async _load(){let t=await u(this,{type:"maintenance_supporter/budget_status"},{onError:e=>{this._error=e}});t&&(this._status=t,x(t),this._localMonthly=t.monthly_budget?String(t.monthly_budget):"",this._localYearly=t.yearly_budget?String(t.yearly_budget):"",this._dirty=!1)}async _save(){if(!this._isAdmin)return;this._error="";let t=this._localMonthly.trim()===""?0:parseFloat(this._localMonthly),e=this._localYearly.trim()===""?0:parseFloat(this._localYearly),a={};!isNaN(t)&&t>=0&&(a.budget_monthly=t),!isNaN(e)&&e>=0&&(a.budget_yearly=e),await u(this,{type:"maintenance_supporter/global/update",settings:a},{busy:d=>{this._busy=d},reload:()=>this._load(),onError:d=>{this._error=d}})}_onDeepLink(){history.pushState(null,"","/maintenance-supporter?ms_action=open_budget"),window.dispatchEvent(new CustomEvent("location-changed"))}render(){let t=this._lang,e=this._status;if(!e)return o`<ha-card><div class="loading">${i("loading",t)}</div></ha-card>`;let a=g(e),d=e.alert_threshold_pct??E,k=[{label:i("budget_monthly",t),spent:e.monthly_spent||0,budget:e.monthly_budget||0},{label:i("budget_yearly",t),spent:e.yearly_spent||0,budget:e.yearly_budget||0}];return o`
<ha-card>
<div class="card-content">
<div class="header">
<div class="title">
<span class="emoji">💰</span>
<span>${this._config.title||i("settings_budget",t)}</span>
</div>
<span class="currency">${a}</span>
</div>
${this._error?o`<div class="error">${this._error}</div>`:m}
${k.map(r=>{if(!(r.budget>0))return o`
<div class="track spent-only">
<div class="track-label-row">
<label>${r.label}</label>
<span class="track-numbers ok">${p(r.spent,a,t)}</span>
</div>
</div>
`;let c=Math.min(100,Math.max(0,r.spent/r.budget*100)),b=c>=100?"danger":c>=d?"warning":"ok";return o`
<div class="track">
<div class="track-label-row">
<label>${r.label}</label>
<span class="track-numbers ${b}">
${p(r.spent,void 0,t)} / ${p(r.budget,a,t)}
</span>
</div>
<div class="bar"><div class="bar-fill ${b}" style="width:${c}%"></div></div>
</div>
`})}
${this._isAdmin?o`
<div class="inputs-row">
<div class="input-field">
<label>${i("budget_monthly_set",t)}</label>
<div class="input-wrap">
<input type="number" min="0" step="1"
.value=${this._localMonthly}
?disabled=${this._busy}
@input=${r=>{this._localMonthly=r.target.value,this._dirty=!0}} />
<span class="input-suffix">${a}</span>
</div>
</div>
<div class="input-field">
<label>${i("budget_yearly_set",t)}</label>
<div class="input-wrap">
<input type="number" min="0" step="1"
.value=${this._localYearly}
?disabled=${this._busy}
@input=${r=>{this._localYearly=r.target.value,this._dirty=!0}} />
<span class="input-suffix">${a}</span>
</div>
</div>
</div>
<div class="actions">
<button class="btn ${this._dirty?"primary":"muted"}"
@click=${this._save}
?disabled=${this._busy||!this._dirty}>
<ha-icon icon="${this._dirty?"mdi:content-save":"mdi:check"}"></ha-icon>
${this._dirty?i("save",t):i("saved",t)}
</button>
<button class="btn link" @click=${this._onDeepLink}>
${i("budget_advanced",t)}
</button>
</div>
`:o`
<button class="btn link" @click=${this._onDeepLink}>
${i("budget_open_panel",t)}
</button>
`}
</div>
</ha-card>
`}};s.styles=[$,h`
.currency {
font-size: 14px; font-weight: 600;
color: var(--secondary-text-color);
background: var(--secondary-background-color);
padding: 2px 10px; border-radius: 999px;
}
.track { display: flex; flex-direction: column; gap: 4px; }
.track-label-row {
display: flex; align-items: center; justify-content: space-between;
}
.track-label-row label {
font-size: 12px; color: var(--secondary-text-color);
text-transform: uppercase; letter-spacing: 0.5px;
}
.track-numbers { font-size: 13px; font-weight: 600; }
.track-numbers.ok { color: var(--primary-text-color); }
.track-numbers.warning { color: #ff9800; }
.track-numbers.danger { color: var(--error-color, #f44336); }
.bar {
height: 6px; background: var(--secondary-background-color);
border-radius: 3px; overflow: hidden;
}
.bar-fill { height: 100%; transition: width 0.3s; border-radius: 3px; }
.bar-fill.ok { background: var(--primary-color); }
.bar-fill.warning { background: #ff9800; }
.bar-fill.danger { background: var(--error-color, #f44336); }
/* minmax(0, …): a bare 1fr never shrinks below the number inputs'
natural width — the row was 420 px wide on a phone (2026-09-27). */
.inputs-row {
display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px;
padding-top: 4px; border-top: 1px solid var(--divider-color);
}
.input-field { display: flex; flex-direction: column; gap: 4px; }
.input-field label {
font-size: 11px; color: var(--secondary-text-color);
text-transform: uppercase; letter-spacing: 0.3px;
}
.input-wrap { position: relative; display: flex; align-items: center; }
.input-wrap input {
flex: 1; min-width: 0; width: 100%; box-sizing: border-box; padding: 6px 32px 6px 8px; font-size: 13px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
font-family: inherit;
}
.input-suffix {
position: absolute; right: 8px;
color: var(--secondary-text-color); font-size: 13px;
pointer-events: none;
}
.actions { display: flex; gap: 8px; align-items: center; }
`],n([v({attribute:!1})],s.prototype,"hass",2),n([l()],s.prototype,"_config",2),n([l()],s.prototype,"_status",2),n([l()],s.prototype,"_busy",2),n([l()],s.prototype,"_error",2),n([l()],s.prototype,"_localMonthly",2),n([l()],s.prototype,"_localYearly",2),n([l()],s.prototype,"_dirty",2);customElements.get("maintenance-budget-section-card")||customElements.define("maintenance-budget-section-card",s);w({type:"maintenance-budget-section-card",name:"Maintenance Supporter \u2014 Budget",description:"Edit the monthly and yearly budget right on the dashboard.",preview:!1});export{s as MaintenanceBudgetSectionCard};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
var _=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var L=(n,e,t,s)=>{for(var r=s>1?void 0:s?f(e,t):e,c=n.length-1,l;c>=0;c--)(l=n[c])&&(r=(s?l(e,t,r):l(r))||r);return s&&r&&_(e,t,r),r};var v={ok:"var(--success-color, #4caf50)",due_soon:"var(--warning-color, #ff9800)",overdue:"var(--error-color, #f44336)",triggered:"var(--deep-orange-color, #ff5722)",archived:"var(--disabled-color, #9e9e9e)",paused:"var(--info-color, #2196f3)"},p=["overdue","triggered","due_soon","ok"],E=["overdue","triggered","due_soon"],T=Object.fromEntries(p.map((n,e)=>[n,e]));var b={ok:"mdi:check-circle",due_soon:"mdi:alert-circle",overdue:"mdi:alert-octagon",triggered:"mdi:bell-alert",archived:"mdi:archive-outline",paused:"mdi:pause-circle-outline",completed:"mdi:check-circle",skipped:"mdi:skip-next",missed:"mdi:calendar-remove",reset:"mdi:refresh"};var u="2.95.0";var a="en",g=(()=>{let n=window;return n.__msLocales||(n.__msLocales={store:{},inflight:{}}),n.__msLocales})(),o=g.store,i=g.inflight;function N(n){o.en=Object.assign({},n,o.en??{})}var S=new Set(["de","nl","fr","it","es","pt","pt-br","ru","uk","pl","cs","sv","zh","da","fi","nb","ja","hi","hu","ko","tr"]),m="/maintenance_supporter_locales";function d(n){let e=(n||a).toLowerCase();return e.startsWith("pt")&&e.endsWith("br")?"pt-br":e.substring(0,2)}function O(n,e,t){let s=d(e);return o[s]?.[n]??o.en?.[n]??t??n}function U(n){let e=d(n);return e===a||e in o}function k(n){let e=d(n);return e===a||e in o||!S.has(e)?Promise.resolve():(e in i||(i[e]=fetch(`${m}/${e}.json?v=${u}`).then(t=>t.ok?t.json():null).then(t=>{t?o[e]=t:delete i[e]}).catch(()=>{delete i[e]})),i[e])}export{L as a,v as b,E as c,b as d,N as e,d as f,O as g,U as h,k as i};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
function l(r){if(!r)return[];let n=[],i=r.photo_doc_id;typeof i=="string"&&n.push(i);let o=r.photo_doc_ids;Array.isArray(o)&&n.push(...o);let t=[];for(let e of n){if(typeof e!="string")continue;let s=e.trim();if(!(!s||t.includes(s))&&(t.push(s),t.length>=10))break}return t}function f(){let r=new Uint8Array(4);return(globalThis.crypto??{getRandomValues:n=>n.map(()=>Math.floor(Math.random()*256))}).getRandomValues(r),Array.from(r,n=>n.toString(16).padStart(2,"0")).join("")}function d(r){let n=r?.reading_values;if(!Array.isArray(n))return[];let i=[],o=new Set;for(let t of n){if(!t||typeof t!="object")continue;let e=t;typeof e.id!="string"||!e.id||o.has(e.id)||typeof e.value!="number"||!Number.isFinite(e.value)||(o.add(e.id),i.push({id:e.id,name:typeof e.name=="string"?e.name:e.id,unit:typeof e.unit=="string"?e.unit:null,value:e.value}))}return i}function c(r){return r.filter(n=>n.type==="completed"&&(n.reading_value!=null||d(n).length>0)).sort((n,i)=>n.timestamp.localeCompare(i.timestamp))}function p(r){return c(r??[]).map(n=>({timestamp:n.timestamp,values:d(n)})).filter(n=>n.values.length>0)}function m(r,n,i){let o;for(let t of r){if(i!==void 0){let s=new Date(t.timestamp).getTime();if(!isNaN(s)&&s>=i)break}let e=t.values.find(s=>s.id===n);e&&(o=e)}return o}function _(r,n,i){let o=d(n).find(e=>e.id===i);if(!o)return null;let t=null;for(let e of c(r)){if(e.timestamp>=n.timestamp)break;let s=d(e).find(a=>a.id===i);s&&(t=s.value)}return t==null?null:o.value-t}function R(r){let n=new Set,i=new Set;for(let o of r){let t=(o.name||"").trim().toLowerCase();t&&(n.has(t)?i.add(o.id):n.add(t))}return i}function h(r){let n=[],i=new Set,o=new Set;for(let t of r){let e=(t.name||"").trim();if(!(!e||i.has(t.id)||o.has(e.toLowerCase()))&&(i.add(t.id),o.add(e.toLowerCase()),n.push({id:t.id,name:e,unit:(t.unit||"").trim()||null}),n.length>=20))break}return n}function y(r,n,i,o){let t=i,e=u=>typeof u=="string"?u:null,s=u=>typeof u=="number"?u:null,a=e(t.timestamp)??"";return{entry_id:r,task_id:n,original_timestamp:a,type:e(t.type)||"completed",timestamp:a,notes:e(t.notes),cost:s(t.cost),duration:s(t.duration),completed_by:e(t.completed_by),used_parts:Array.isArray(t.used_parts)?t.used_parts:null,photo_doc_ids:l(t),reading_value:s(t.reading_value),reading_values:d(t),readings:o?.readings??[],task_type:o?.type??null,reading_unit:o?.reading_unit??null}}async function E(r,n,i,o){let e=(await r.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:n})).tasks?.find(a=>a.id===i);if(!e)return null;let s=e.history?.find(a=>a.timestamp===o);return s||(s=(await r.connection.sendMessagePromise({type:"maintenance_supporter/task/history",entry_id:n,task_id:i})).history?.find(u=>u.timestamp===o)),s?y(n,i,s,e):null}export{l as a,f as b,d as c,p as d,m as e,_ as f,R as g,h,y as i,E as j};
@@ -0,0 +1,66 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as u,b as s,d as r,e as _,f as m,g as o,j as d,x as c}from"./chunk-2ARNLSF6.js";import{a as n,g as p}from"./chunk-3MSNNIFG.js";var g={default_warning_days:[0,365],default_consumable_threshold:[1,90],battery_low_percent:[1,90],battery_recovered_percent:[20,100],archive_oneoff_days:[0,3650],delete_archived_oneoff_days:[0,3650],notify_due_soon_interval_hours:[0,720],notify_overdue_interval_hours:[0,720],notify_triggered_interval_hours:[0,720],max_notifications_per_day:[0,1e3],notification_bundle_threshold:[2,20],snooze_duration_hours:[1,168],warranty_reminder_days:[1,365],budget_alert_threshold:[10,100],currency_decimals:[0,3]};var b=[0,14],x=[0,1440],y=[1,1e4],R=15,A=[.1,.9],E=[0,365],T=[.01,999],$=[.01,9999];var i=class extends _{constructor(){super(...arguments);this._open=!1;this._title="";this._message="";this._confirmText="";this._danger=!1;this._inputLabel="";this._inputType="";this._options=null;this._inputValue="";this._resolve=null;this._promptResolve=null}confirm(e){return this._title=e.title,this._message=e.message,this._confirmText=e.confirmText||"OK",this._danger=e.danger||!1,this._inputLabel="",this._inputType="",this._options=null,this._inputValue="",this._open=!0,new Promise(t=>{this._resolve=t,this._promptResolve=null})}prompt(e){return this._title=e.title,this._message=e.message,this._confirmText=e.confirmText||"OK",this._danger=e.danger||!1,this._inputLabel=e.inputLabel||"",this._inputType=e.inputType||"text",this._options=e.options&&e.options.length?e.options:null,this._inputValue=e.inputValue||"",this._open=!0,new Promise(t=>{this._promptResolve=t,this._resolve=null})}_cancel(){this._open=!1,this._promptResolve&&(this._promptResolve({confirmed:!1,value:""}),this._promptResolve=null),this._resolve?.(!1),this._resolve=null}_confirmAction(){this._open=!1,this._promptResolve&&(this._promptResolve({confirmed:!0,value:this._inputValue}),this._promptResolve=null),this._resolve?.(!0),this._resolve=null}render(){if(!this._open)return r;let e=d(this.hass);return s`
<ha-dialog open @closed=${this._cancel}>
<div class="dialog-title">${this._title}</div>
<div class="content">
${this._message}
${this._inputLabel?s`
<!-- Native <input> rather than <ha-textfield>: HA loads
ha-textfield lazily for its own panels, so inside this custom
panel it can be unregistered and render with zero height —
the prompt then shows no field at all (caught live testing
the pause/replace prompts; same fix as complete-dialog). -->
<label class="field">
<span class="field-label">${this._inputLabel}</span>
${this._options?s`<select class="field-input field-select"
@change=${t=>this._inputValue=t.target.value}>
${this._options.map(t=>s`<option value=${t.value} ?selected=${t.value===this._inputValue}>${t.label}</option>`)}
</select>`:s`<input class="field-input"
type="${this._inputType||"text"}"
.value=${this._inputValue}
@input=${t=>this._inputValue=t.target.value} />`}
</label>
`:r}
</div>
<div class="dialog-actions">
<ha-button appearance="plain" @click=${this._cancel}>
${p("cancel",e)}
</ha-button>
<ha-button
class="${this._danger?"danger":""}"
@click=${this._confirmAction}
>
${this._confirmText}
</ha-button>
</div>
</ha-dialog>
`}};i.styles=[c,u`
.dialog-title {
font-size: 18px;
font-weight: 500;
padding-bottom: 12px;
}
/* shared native-field scaffold from nativeFieldStyles; the prompt input
follows the message text, hence the extra top margin here */
.field { margin-top: 12px; }
.content {
padding: 8px 0;
min-width: 280px;
line-height: 1.5;
display: flex;
flex-direction: column;
gap: 12px;
}
.dialog-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
padding-top: 16px;
}
ha-textfield {
display: block;
}
ha-button.danger {
--mdc-theme-primary: var(--error-color, #f44336);
}
`],n([m({attribute:!1})],i.prototype,"hass",2),n([o()],i.prototype,"_open",2),n([o()],i.prototype,"_title",2),n([o()],i.prototype,"_message",2),n([o()],i.prototype,"_confirmText",2),n([o()],i.prototype,"_danger",2),n([o()],i.prototype,"_inputLabel",2),n([o()],i.prototype,"_inputType",2),n([o()],i.prototype,"_options",2),n([o()],i.prototype,"_inputValue",2);customElements.get("maintenance-confirm-dialog")||customElements.define("maintenance-confirm-dialog",i);var h="maintenance-confirm-dialog",f="data-ms-lovelace-confirm";function v(){return document.querySelector("home-assistant")?.shadowRoot??document.body}function H(l,a){let e=v(),t=e.querySelector(`${h}[${f}]`);return t||(t=document.createElement(h),t.setAttribute(f,""),e.appendChild(t)),t.hass=l,t.confirm(a)}export{g as a,b,x as c,y as d,R as e,A as f,E as g,T as h,$ as i,H as j};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as i}from"./chunk-6BHUADHJ.js";var a={operatorWriteEnabled:!1,operatorIds:[]};function _(e,t=a){return e?e.is_admin?!0:t.operatorWriteEnabled&&t.operatorIds.includes(e.id):!1}var u=["buttons_compact","buttons","icons"];function d(e){let[t,s]=i.default_warning_days,n=e?.general?.default_warning_days,r=e?.general?.row_action_style;return{features:{...o.features,...e?.features??{}},defaultWarningDays:typeof n=="number"&&Number.isFinite(n)&&n>=t&&n<=s?n:o.defaultWarningDays,rowActionStyle:u.includes(r??"")?r:o.rowActionStyle,access:{operatorWriteEnabled:e?.operator_write_enabled===!0,operatorIds:Array.isArray(e?.admin_panel_user_ids)?e.admin_panel_user_ids.filter(c=>typeof c=="string"):[]},budget:e?.budget??null,rowActionNoticePending:e?.general?.row_action_notice_pending===!0,refsInLists:e?.general?.ref_numbers_in_lists===!0,objectsTableColumns:Array.isArray(e?.objects_table_columns)?e.objects_table_columns:void 0}}var o={features:{adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1},defaultWarningDays:7,rowActionStyle:"buttons_compact",access:a,budget:null,rowActionNoticePending:!1,refsInLists:!1,objectsTableColumns:void 0};function l(){let e=window;return e.__msSettingsCache??={promise:null}}function m(e){let t=l();if(t.promise)return t.promise;let s=e.connection.sendMessagePromise({type:"maintenance_supporter/settings"}).then(n=>d(n)).catch(()=>(t.promise===s&&(t.promise=null),o));return t.promise=s,s}function b(){l().promise=null}export{a,_ as b,m as c,b as d};
@@ -0,0 +1,60 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as t}from"./chunk-2ARNLSF6.js";function e(o){let r=window;r.customCards=r.customCards||[],r.customCards.some(a=>a.type===o.type)||r.customCards.push(o)}var d=t`
ha-card { overflow: hidden; }
.card-content {
padding: 16px;
display: flex; flex-direction: column;
gap: 12px;
}
.header {
display: flex; align-items: center; justify-content: space-between;
gap: 12px;
}
.title {
display: flex; align-items: center; gap: 8px;
font-size: 16px; font-weight: 500;
}
.emoji { font-size: 20px; }
/* Button family — primary action / muted-saved-state / link / icon-with-text */
.btn {
padding: 6px 12px; font-size: 13px;
border-radius: 6px; cursor: pointer;
border: 1px solid var(--divider-color);
background: var(--secondary-background-color, transparent);
color: var(--primary-text-color);
font-weight: 500;
display: inline-flex; align-items: center; gap: 4px;
}
.btn:hover { background: var(--state-icon-color, rgba(255,255,255,0.06)); }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }
.btn.primary {
background: var(--primary-color);
color: var(--text-primary-color, white);
border-color: var(--primary-color);
}
.btn.primary[disabled] { opacity: 0.6; }
.btn.muted {
background: transparent;
color: var(--secondary-text-color);
border-style: dashed;
}
.btn.muted[disabled] { opacity: 1; cursor: default; }
.btn.muted ha-icon, .btn.primary ha-icon { --mdc-icon-size: 14px; }
.btn.link {
background: transparent; border: none; padding: 6px 4px;
color: var(--primary-color); margin-left: auto;
}
.btn.link:hover { background: transparent; text-decoration: underline; }
/* Error + loading states */
.error {
padding: 8px; border-radius: 6px;
background: rgba(211, 47, 47, 0.1);
color: var(--error-color, #d32f2f); font-size: 13px;
}
.loading {
padding: 24px; text-align: center;
color: var(--secondary-text-color);
}
`;export{e as a,d as b};
@@ -0,0 +1,88 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as y,b as s,d,e as g,f as o,g as f,p as m}from"./chunk-2ARNLSF6.js";import{a,g as l}from"./chunk-3MSNNIFG.js";function $(n){let t=m("2001-02-03",n).match(/\d+/g)||[],e=v=>t.findIndex(_=>Number(_)===v),h=e(2001),c=e(2),u=e(3);return h===0?"YMD":c>=0&&u>=0&&c<u?"MDY":"DMY"}function p(n,i,t){if(n<1e3||n>9999||i<1||i>12||t<1||t>31)return null;let e=new Date(n,i-1,t);return e.getFullYear()!==n||e.getMonth()!==i-1||e.getDate()!==t?null:`${n}-${String(i).padStart(2,"0")}-${String(t).padStart(2,"0")}`}function b(n,i){let t=n.trim(),e;if(e=t.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/))return p(+e[1],+e[2],+e[3]);if(e=t.match(/^(\d{4})$/))return p(+e[1],1,1);if(e=t.match(/^(\d{1,2})[./](\d{4})$/))return p(+e[2],+e[1],1);if(e=t.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/))return p(+e[3],+e[2],+e[1]);if(e=t.match(/^(\d{1,2})[/-](\d{1,2})[/-](\d{4})$/)){let h=+e[1],c=+e[2],u=+e[3];return $(i)==="MDY"?p(u,h,c):p(u,c,h)}return null}function x(n,i){if(i)switch(n){case"date":return i.split("T")[0];case"time":return i.length===5?`${i}:00`:i;case"datetime":{let[t,e="00:00:00"]=i.split("T");return`${t} ${e.length===5?`${e}:00`:e}`}}}function k(n,i){if(typeof i!="string"||!i)return"";switch(n){case"date":return i.slice(0,10);case"time":return i.slice(0,5);case"datetime":{let[t,e="00:00:00"]=i.split(" ");return`${t}T${e.length===5?`${e}:00`:e}`}}}var r=class extends g{constructor(){super(...arguments);this.kind="date";this.label="";this.value="";this.clearable=!1;this.disabled=!1;this.required=!1;this.lang="en";this._typing=!1;this._typed="";this._typedInvalid=!1}_startTyping(){this._typed=this.value,this._typedInvalid=!1,this._typing=!0,this.updateComplete.then(()=>this.shadowRoot?.querySelector("input.typed")?.focus())}_commitTyped(){if(!this._typed.trim()){this._typing=!1;return}let t=b(this._typed,this.lang);if(!t){this._typedInvalid=!0;return}this._typing=!1,this._typedInvalid=!1,this._emit(t)}_onTypedKey(t){t.key==="Enter"?(t.preventDefault(),this._commitTyped()):t.key==="Escape"&&(t.preventDefault(),this._typing=!1,this._typedInvalid=!1)}_selector(){switch(this.kind){case"date":return{date:{}};case"time":return{time:{no_second:!0}};case"datetime":return{datetime:{}}}}_onSelectorChange(t){t.stopPropagation(),this._emit(k(this.kind,t.detail?.value))}_clear(){this._emit("")}_emit(t){t!==this.value&&(this.value=t,this.dispatchEvent(new CustomEvent("value-changed",{bubbles:!0,composed:!0,detail:{value:t}})))}render(){return s`
<div class="field">
${this.label?s`<span class="label">${this.label}${this.required?s`<span class="req">*</span>`:d}</span>`:d}
<div class="row">
${this._typing?s`<input class="typed" type="text" inputmode="numeric" autocomplete="off"
.value=${this._typed}
placeholder=${m("1978-03-15",this.lang)}
aria-invalid=${this._typedInvalid?"true":"false"}
@input=${t=>{this._typed=t.target.value,this._typedInvalid=!1}}
@keydown=${this._onTypedKey}
@blur=${this._commitTyped} />`:s`<ha-selector
.hass=${this.hass}
.selector=${this._selector()}
.value=${x(this.kind,this.value)}
.required=${this.required}
.disabled=${this.disabled}
@value-changed=${this._onSelectorChange}
></ha-selector>`}
${this.kind==="date"&&!this.disabled&&!this._typing?s`<button type="button" class="type-toggle" title=${l("date_type_toggle",this.lang)} aria-label=${l("date_type_toggle",this.lang)} @click=${this._startTyping}>
<ha-icon icon="mdi:keyboard-outline"></ha-icon>
</button>`:d}
${this.clearable&&this.value&&!this.disabled&&!this._typing?s`<button type="button" class="clear" title=${l("clear",this.lang)} aria-label=${l("clear",this.lang)} @click=${this._clear}>
<ha-icon icon="mdi:close"></ha-icon>
</button>`:d}
</div>
${this._typedInvalid?s`<span class="helper invalid">${l("date_type_invalid",this.lang)}</span>`:this.helper?s`<span class="helper">${this.helper}</span>`:d}
</div>
`}};r.styles=y`
:host { display: block; }
.field {
display: flex;
flex-direction: column;
gap: 4px;
}
.label {
font-size: 12px;
color: var(--secondary-text-color, #888);
font-weight: 500;
}
.req { color: var(--error-color, #f44336); margin-left: 2px; }
.row {
display: flex;
align-items: center;
gap: 4px;
}
ha-selector {
flex: 1;
min-width: 0;
}
.clear, .type-toggle {
flex: none;
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
padding: 0;
border: none;
border-radius: 50%;
background: transparent;
color: var(--secondary-text-color);
cursor: pointer;
--mdc-icon-size: 20px;
}
.clear:hover, .type-toggle:hover { background: rgba(var(--rgb-primary-text-color, 0, 0, 0), 0.08); }
.clear:focus-visible, .type-toggle:focus-visible { outline: 2px solid var(--primary-color); }
.helper {
font-size: 11px;
color: var(--secondary-text-color);
font-style: italic;
}
.helper.invalid { color: var(--error-color, #f44336); font-style: normal; }
input.typed {
flex: 1;
min-width: 0;
height: 40px;
box-sizing: border-box;
padding: 0 12px;
border: 1px solid var(--divider-color, #ccc);
border-radius: 4px;
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
font: inherit;
}
input.typed[aria-invalid="true"] { border-color: var(--error-color, #f44336); }
input.typed:focus { outline: 2px solid var(--primary-color); outline-offset: -1px; }
`,a([o({attribute:!1})],r.prototype,"hass",2),a([o()],r.prototype,"kind",2),a([o()],r.prototype,"label",2),a([o()],r.prototype,"value",2),a([o()],r.prototype,"helper",2),a([o({type:Boolean})],r.prototype,"clearable",2),a([o({type:Boolean})],r.prototype,"disabled",2),a([o({type:Boolean})],r.prototype,"required",2),a([o()],r.prototype,"lang",2),a([f()],r.prototype,"_typing",2),a([f()],r.prototype,"_typed",2),a([f()],r.prototype,"_typedInvalid",2);customElements.get("ms-date-field")||customElements.define("ms-date-field",r);
File diff suppressed because one or more lines are too long
@@ -0,0 +1,137 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as v,b as y}from"./chunk-IWH6LGYJ.js";import{a as f,b as x,c as k}from"./chunk-C275ZO4V.js";import{j as b}from"./chunk-6BHUADHJ.js";import{a as h,b as a,d as c,e as g,f as _,g as o,j as m,z as l}from"./chunk-2ARNLSF6.js";import{a as n,g as i,i as u}from"./chunk-3MSNNIFG.js";var e=class extends g{constructor(){super(...arguments);this._config={type:""};this._groups={};this._loaded=!1;this._busy=!1;this._error="";this._newName="";this._editingId=null;this._editingName="";this._access=f;this._hasInitiallyLoaded=!1}setConfig(t){this._config=t}getCardSize(){return 2}get _lang(){return m(this.hass)}get _canWrite(){return x(this.hass?.user,this._access)}updated(t){super.updated(t),t.has("hass")&&this.hass&&!this._hasInitiallyLoaded&&(this._hasInitiallyLoaded=!0,this._load(),k(this.hass).then(r=>{this._access=r.access}),u(this._lang).then(()=>this.requestUpdate()))}async _load(){let t=await l(this,{type:"maintenance_supporter/groups"},{onError:r=>{this._error=r}});t!==void 0&&(this._groups=t?.groups||{},this._loaded=!0)}async _act(t,r){this._error="",await l(this,t,{busy:s=>{this._busy=s},reload:async()=>{r?.(),await this._load()},onError:s=>{this._error=s}})}async _addGroup(){if(!this._canWrite)return;let t=this._newName.trim();t&&await this._act({type:"maintenance_supporter/group/create",name:t},()=>{this._newName=""})}_startEdit(t){this._editingId=t,this._editingName=this._groups[t]?.name||""}async _saveEdit(){if(!this._canWrite||!this._editingId)return;let t=this._editingName.trim();t&&await this._act({type:"maintenance_supporter/group/update",group_id:this._editingId,name:t},()=>{this._editingId=null,this._editingName=""})}async _deleteGroup(t,r){!this._canWrite||!await b(this.hass,{title:i("delete",this._lang),message:i("delete_group_confirm",this._lang).replace("{name}",r),confirmText:i("delete",this._lang),danger:!0})||await this._act({type:"maintenance_supporter/group/delete",group_id:t})}_onDeepLink(){history.pushState(null,"","/maintenance-supporter?ms_action=open_groups"),window.dispatchEvent(new CustomEvent("location-changed"))}_onKeyDown(t,r){t.key==="Enter"?(t.preventDefault(),r()):t.key==="Escape"&&(t.preventDefault(),this._editingId=null,this._editingName="")}render(){let t=this._lang;if(!this._loaded)return a`<ha-card><div class="loading">${i("loading",t)}</div></ha-card>`;let r=Object.keys(this._groups);return a`
<ha-card>
<div class="card-content">
<div class="header">
<div class="title">
<span class="emoji">🏷️</span>
<span>${this._config.title||i("groups",t)}</span>
<span class="count">${r.length}</span>
</div>
</div>
${this._error?a`<div class="error">${this._error}</div>`:c}
${r.length===0?a`<div class="empty">${i("groups_empty",t)}</div>`:a`
<div class="group-list">
${r.map(s=>{let d=this._groups[s],$=d.task_refs?.length??0,w=this._editingId===s;return a`
<div class="group-row">
${w?a`
<input class="edit-input" type="text"
.value=${this._editingName}
?disabled=${this._busy}
@input=${p=>{this._editingName=p.target.value}}
@keydown=${p=>this._onKeyDown(p,this._saveEdit.bind(this))} />
<button class="btn small primary"
@click=${this._saveEdit}
?disabled=${this._busy||!this._editingName.trim()}>
${i("save",t)}
</button>
<button class="btn small"
@click=${()=>{this._editingId=null}}>
${i("cancel",t)}
</button>
`:a`
<span class="group-name">${d.name||"Unnamed"}</span>
<span class="task-count">${$}</span>
${this._canWrite?a`
<button class="icon-btn"
title="${i("edit",t)}"
@click=${()=>this._startEdit(s)}
?disabled=${this._busy}>
<ha-icon icon="mdi:pencil"></ha-icon>
</button>
<button class="icon-btn danger"
title="${i("delete",t)}"
@click=${()=>this._deleteGroup(s,d.name||"Unnamed")}
?disabled=${this._busy}>
<ha-icon icon="mdi:delete"></ha-icon>
</button>
`:c}
`}
</div>
`})}
</div>
`}
${this._canWrite?a`
<div class="add-row">
<input type="text"
placeholder="${i("group_new_placeholder",t)}"
.value=${this._newName}
?disabled=${this._busy}
@input=${s=>{this._newName=s.target.value}}
@keydown=${s=>this._onKeyDown(s,this._addGroup.bind(this))} />
<button class="btn primary"
@click=${this._addGroup}
?disabled=${this._busy||!this._newName.trim()}>
<ha-icon icon="mdi:plus"></ha-icon>
${i("add",t)}
</button>
</div>
<button class="btn link" @click=${this._onDeepLink}>
${i("groups_manage_tasks",t)}
</button>
`:a`
<button class="btn link" @click=${this._onDeepLink}>
${i("groups_open_panel",t)}
</button>
`}
</div>
</ha-card>
`}};e.styles=[y,h`
.count {
font-size: 12px; color: var(--secondary-text-color);
background: var(--secondary-background-color);
padding: 2px 8px; border-radius: 999px;
}
.empty {
padding: 16px; text-align: center;
color: var(--secondary-text-color); font-style: italic;
}
.group-list { display: flex; flex-direction: column; gap: 4px; }
.group-row {
display: flex; align-items: center; gap: 8px;
padding: 6px 8px; border-radius: 6px;
background: var(--secondary-background-color, rgba(255,255,255,0.03));
}
.group-name { flex: 1; font-size: 14px; }
.task-count {
font-size: 11px; color: var(--secondary-text-color);
background: var(--card-background-color, rgba(0,0,0,0.2));
padding: 1px 8px; border-radius: 999px;
font-weight: 500;
}
.edit-input {
flex: 1; padding: 4px 8px; font-size: 14px;
background: var(--card-background-color, #1c1c1c);
color: var(--primary-text-color);
border: 1px solid var(--primary-color); border-radius: 4px;
font-family: inherit;
}
.icon-btn {
background: transparent; border: none; cursor: pointer;
color: var(--secondary-text-color); padding: 4px;
border-radius: 4px;
}
.icon-btn:hover {
background: var(--state-icon-color, rgba(255,255,255,0.06));
color: var(--primary-text-color);
}
.icon-btn.danger:hover { color: var(--error-color); }
.icon-btn ha-icon { --mdc-icon-size: 18px; }
.add-row {
display: flex; gap: 6px;
padding-top: 8px; border-top: 1px solid var(--divider-color);
}
.add-row input {
flex: 1; padding: 6px 8px; font-size: 13px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
font-family: inherit;
}
/* Card-specific overrides on the shared .btn */
.btn.small { padding: 4px 8px; font-size: 12px; }
.btn ha-icon { --mdc-icon-size: 16px; }
`],n([_({attribute:!1})],e.prototype,"hass",2),n([o()],e.prototype,"_config",2),n([o()],e.prototype,"_groups",2),n([o()],e.prototype,"_loaded",2),n([o()],e.prototype,"_busy",2),n([o()],e.prototype,"_error",2),n([o()],e.prototype,"_newName",2),n([o()],e.prototype,"_editingId",2),n([o()],e.prototype,"_editingName",2),n([o()],e.prototype,"_access",2);customElements.get("maintenance-groups-section-card")||customElements.define("maintenance-groups-section-card",e);v({type:"maintenance-groups-section-card",name:"Maintenance Supporter \u2014 Groups",description:"Create, rename and delete task groups right on the dashboard.",preview:!1});export{e as MaintenanceGroupsSectionCard};
@@ -0,0 +1,134 @@
/*! maintenance_supporter frontend 2.95.0 */
import{a as y,b as x}from"./chunk-IWH6LGYJ.js";import"./chunk-N5LSMQW7.js";import{b as p,j as $}from"./chunk-6BHUADHJ.js";import{a as v,b as r,d as c,e as f,f as m,g as n,i as b,j as g,z as u}from"./chunk-2ARNLSF6.js";import{a as s,g as a,i as h}from"./chunk-3MSNNIFG.js";var i=class extends f{constructor(){super(...arguments);this._config={type:""};this._state=null;this._busy=!1;this._error="";this._localStart="";this._localEnd="";this._localBuffer="3";this._dirty=!1;this._loaded=!1}setConfig(t){this._config=t}getCardSize(){return 2}get _lang(){return g(this.hass)}get _isAdmin(){return this.hass?.user?.is_admin??!0}updated(t){super.updated(t),b(this,t),t.has("hass")&&this.hass&&!this._loaded&&(this._loaded=!0,this._load(),h(this._lang).then(()=>this.requestUpdate()))}async _load(){let t=await u(this,{type:"maintenance_supporter/vacation/state"},{onError:e=>{this._error=e}});t&&(this._state=t,this._localStart=t.start||"",this._localEnd=t.end||"",this._localBuffer=String(t.buffer_days??3),this._dirty=!1)}_act(t){return this._error="",u(this,t,{busy:e=>{this._busy=e},onError:e=>{this._error=e}})}async _toggleEnabled(t){let e=await this._act({type:"maintenance_supporter/vacation/update",enabled:t});e&&(this._state=e)}async _save(){if(!this._isAdmin)return;let[t,e]=p,o=Number(this._localBuffer);if(this._localBuffer.trim()===""||!Number.isInteger(o)||o<t||o>e){this._error=a("settings_value_out_of_range",this._lang).replace("{min}",String(t)).replace("{max}",String(e));return}let l=await this._act({type:"maintenance_supporter/vacation/update",start:this._localStart||null,end:this._localEnd||null,buffer_days:o});l&&(this._state=l,this._dirty=!1)}async _endNow(){if(!this._isAdmin||!await $(this.hass,{title:a("vacation_end_now",this._lang),message:a("vacation_end_now_confirm",this._lang),confirmText:a("vacation_end_now",this._lang)}))return;let e=await this._act({type:"maintenance_supporter/vacation/end_now"});e&&(this._state=e,this._localStart=e.start||"",this._localEnd=e.end||"")}_onDeepLink(){history.pushState(null,"","/maintenance-supporter?ms_action=open_vacation"),window.dispatchEvent(new CustomEvent("location-changed"))}render(){let t=this._lang,e=this._state;if(!e)return r`<ha-card><div class="loading">${a("loading",t)}</div></ha-card>`;let o=e.is_active===!0,l=e.enabled===!0,_=e.exempt_task_ids?.length??0,w=o?a("vacation_status_active",t):l?a("vacation_status_scheduled",t):a("vacation_status_inactive",t),k=o?"active":l?"scheduled":"inactive";return r`
<ha-card>
<div class="card-content">
<div class="header">
<div class="title">
<span class="emoji">🏖️</span>
<span>${this._config.title||a("vacation_mode",t)}</span>
</div>
<span class="status-pill ${k}">${w}</span>
</div>
${this._error?r`<div class="error">${this._error}</div>`:c}
${this._isAdmin?r`
<div class="row toggle-row">
<label>${a("enable",t)}</label>
<ha-switch
.checked=${l}
.disabled=${this._busy}
@change=${d=>this._toggleEnabled(d.target.checked)}
></ha-switch>
</div>
<div class="dates-row">
<div class="date-field">
<label>${a("vacation_start",t)}</label>
<ms-date-field
kind="date"
clearable
.hass=${this.hass}
.lang=${t}
.value=${this._localStart}
.disabled=${this._busy}
@value-changed=${d=>{this._localStart=d.detail.value,this._dirty=!0}}
></ms-date-field>
</div>
<div class="date-field">
<label>${a("vacation_end",t)}</label>
<ms-date-field
kind="date"
clearable
.hass=${this.hass}
.lang=${t}
.value=${this._localEnd}
.disabled=${this._busy}
@value-changed=${d=>{this._localEnd=d.detail.value,this._dirty=!0}}
></ms-date-field>
</div>
<div class="date-field buffer">
<label>${a("vacation_buffer",t)}</label>
<input type="number" min=${p[0]} max=${p[1]}
.value=${this._localBuffer}
?disabled=${this._busy}
@input=${d=>{this._localBuffer=d.target.value,this._dirty=!0}} />
</div>
</div>
<div class="actions">
<button class="btn ${this._dirty?"primary":"muted"}"
@click=${this._save}
?disabled=${this._busy||!this._dirty}>
<ha-icon icon="${this._dirty?"mdi:content-save":"mdi:check"}"></ha-icon>
${this._dirty?a("save",t):a("saved",t)}
</button>
${o?r`<button class="btn"
@click=${this._endNow}
?disabled=${this._busy}>
${a("vacation_end_now",t)}
</button>`:c}
${_>0?r`<button class="btn link"
@click=${this._onDeepLink}>
${_} ${a("vacation_exempt_count",t)}…
</button>`:r`<button class="btn link"
@click=${this._onDeepLink}>
${a("vacation_advanced",t)}
</button>`}
</div>
`:r`
<div class="readonly">
${l&&e.start&&e.end?r`<div>${e.start} → ${e.end}</div>`:c}
<button class="btn link" @click=${this._onDeepLink}>
${a("vacation_open_panel",t)}
</button>
</div>
`}
</div>
</ha-card>
`}};i.styles=[x,v`
.status-pill {
font-size: 11px; font-weight: 600;
padding: 3px 8px; border-radius: 999px;
text-transform: uppercase; letter-spacing: 0.5px;
}
.status-pill.active {
background: rgba(76, 175, 80, 0.15);
color: #4caf50;
}
.status-pill.scheduled {
background: rgba(255, 152, 0, 0.15);
color: #ff9800;
}
.status-pill.inactive {
background: rgba(158, 158, 158, 0.15);
color: var(--secondary-text-color);
}
.row.toggle-row {
display: flex; align-items: center; justify-content: space-between;
}
.row.toggle-row label {
font-size: 14px; color: var(--primary-text-color);
}
.dates-row {
display: grid; grid-template-columns: 1fr 1fr 100px; gap: 10px;
}
.date-field.buffer label { white-space: nowrap; }
.date-field { display: flex; flex-direction: column; gap: 4px; }
.date-field label {
font-size: 11px; color: var(--secondary-text-color);
text-transform: uppercase; letter-spacing: 0.3px;
}
.date-field input {
padding: 6px 8px; font-size: 13px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
font-family: inherit;
}
.date-field input:disabled { opacity: 0.5; cursor: not-allowed; }
.actions {
display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
}
.readonly { display: flex; flex-direction: column; gap: 8px; }
`],s([m({attribute:!1})],i.prototype,"hass",2),s([n()],i.prototype,"_config",2),s([n()],i.prototype,"_state",2),s([n()],i.prototype,"_busy",2),s([n()],i.prototype,"_error",2),s([n()],i.prototype,"_localStart",2),s([n()],i.prototype,"_localEnd",2),s([n()],i.prototype,"_localBuffer",2),s([n()],i.prototype,"_dirty",2);customElements.get("maintenance-vacation-section-card")||customElements.define("maintenance-vacation-section-card",i);y({type:"maintenance-vacation-section-card",name:"Maintenance Supporter \u2014 Vacation",description:"Switch vacation mode on or off and set its dates right on the dashboard.",preview:!1});export{i as MaintenanceVacationSectionCard};
File diff suppressed because one or more lines are too long