iobroker.alias-workbench 0.9.9 → 0.9.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "alias-workbench",
4
- "version": "0.9.9",
4
+ "version": "0.9.11",
5
5
  "news": {
6
+ "0.9.11": {
7
+ "en": "* After saving, the next click in the tree asked **“unsaved changes”** — about an alias that had just been written. The “something unwritten is here” mark was only ever set, never cleared; it went away solely when the draft itself was dropped, i.e. on delete and on move. It now falls after every successful write — and only then: if something went wrong, the change really is not in yet, and the question stays justified. **There is a second effect that had been missing for a long time**: while the mark stood, the workbench deliberately did not rebuild the draft. After a write the old one therefore stayed, instead of rebuilding from the freshly written alias.\n* A second press of **“Suggest free slots”** bent back a row you had set yourself. On the air conditioner: guess nine slots, set the role of the SPEED row to `level.speed` by hand, discard — and the next suggestion put the guessed `level.mode.fan` back. The pattern slot looked free, so the same row was guessed a second time; it then carried **both** marks, “changed” and “guessed”, which exclude each other — what was just guessed cannot have been changed before. Guessing now leaves any row marked “changed” alone. The slot stays free, and the note below says why. Putting a second row next to it was the alternative — the same source point would then hold two slots, and the eighth check would rightly report it.\n* As soon as guesses were pending, the button in the pattern bar renamed itself to **“Discard suggestions”** — and a second one with the same word and the same effect stood in the blue bar below it. Two buttons, one handle. The bar now always says “Suggest free slots”, and only while something is left to guess; once everything is guessed it disappears. Discarding happens where it belongs: in the blue bar, next to “keep all”.\n* Instead of „either every slot is taken, or no remaining datapoint fits\" the note now states the case that actually applies — with the **names** of the slots that stay free: “SPEED, SWING … stays free. Every remaining datapoint already serves as a read or write source in a filled row”, or “… No remaining datapoint fits”. If a hand decision holds a slot open, a sentence is appended: “1 rows were decided by hand and are left untouched.” The “every slot taken” case stays silent unless asked — it says “nothing to do”, and would otherwise appear on nearly every device.\n* Ricardo’s air conditioner is detected as a **thermostat** and fills 3 of 24 slots. **airCondition** fails because its only required slot, MODE, does not carry the role — and that settles it, since “does not fit” has the last word. With automatic suggestions it would reach **9 of 29** against 8 of 24. That now stands next to the pattern field: “· airCondition might fit better” — a single line, both numbers in the tooltip. **One** pattern is named — the best one — and only when it really is better; measured in filled slots, not in ratio. Next to it sits a small **→** button that does both in one go: switch to that pattern and press “Suggest free slots” right away — otherwise the note would be an announcement without an action. In the pattern list every affected row carries “with suggestions: fits” behind its reason. It is computed once when the device is selected and after that only on a row change — suggesting reads names, value lists, units and types, no measured values.\n* In the **template sheet** and in the „save as template\" dialog the device type showed its **pattern key** instead of its name: a blind read „blinds\", a media player „mediaPlayer\", a slider „levelSlider\" — words that appear nowhere else in the interface. The stored value was right all along (the type, since 11.09.2026); only the label came from the wrong field, and since the Admin does not know those three keys, the translated name fell away with them. It now says the same as the pattern picker next to it: „Jalousien · blind\".\n* A **button** can now be created. `STOP` on a blind only writes — a key press has no state to read — and that used to defeat the **whole** alias: the dry run said “STOP: no source chosen”, “create now” stayed greyed out, and not a single blind alias ever got a STOP. The first diagnosis was wrong, and that deserves saying: it was not the write check being too strict. **ioBroker rejects an alias without a read source** — `{ id: { write: … } }` yields “Alias id is invalid: The id is empty!”. The correct shape is the one Ricardo has long been using on his ten hand-built STOPs: `alias.id` as plain text pointing at the command point, plus `common.read: false` on the alias point. That tells vis, Alexa and matter to draw a **button** rather than a toggle stuck at “off” forever. What decides is the **target**, not the role: `read: false` is written by the adapter itself (measured on a real `hm-rpc` STOP). If the target is readable the block stays — then the missing read source really is a defect. The button also survives being read back: all three places that reconstruct an alias now know it, otherwise `read` would quietly flip to `true` on the next update. **The same question grew into a new check**: “target can do what is asked”. The workbench writes to foreign points and reads from foreign points without ever checking whether they can do that. Three ways it silently falls apart — the write formula produces text and the target takes none; the target carries `write: false` (ioBroker stores the value anyway but the adapter passes nothing on: a silent dud); the read source carries `read: false` and never reports anything. All three now appear in the checks panel and as a chip on the ID in the detail view, right where the formula is typed\n* The workbench creates MQTT **send points** itself — a `cmnd` point only comes into existence in ioBroker once something has been published to its topic; before that the alias would have nothing to write to. It took the type from the command knowledge, and `POWER` is listed there as `boolean` — right next to the write formula `val ? \"ON\" : \"OFF\"`. The two do not add up: the js-controller converts the formula result back to the type of the **target** on write, the `\"ON\"` becomes `true` again, and the formula sits in the alias without effect. Switching still works — Tasmota takes `on` as well as `true` — but the point looked different from every point mqtt-client creates, and the formula claimed something it did not do. On the production system it was **one of 196** alias points with an MQTT write target, and it came from us. The rule now is: **where a write formula exists, the point is created as `mixed`** — no exception for `POWER` but a rule that also covers `Fade` and `LedTable`. Without a formula the exact type stays, because the admin derives min, max and unit from `number`. **Plus two places where it becomes visible**: the target point's type now shows as a chip behind its ID in the detail view — right where the formula is typed — in warning colour when the two do not match. And the checks panel has an eighth check, \"write formula takes effect\", that names it instead of keeping quiet\n* A template now counts as fitting only where its **mandatory rows** actually find their source. Until now detection alone decided, and detection asks a different question than application: `pruefeVorlage` checks whether the named **points** exist, the rows need particular **fields inside them**. A hand-built power-meter template whose mandatory row reads `tele.SENSOR · SML.Total_Summe` thus won on **17** ordinary Tasmota devices and delivered exactly one — and unchecked — row there, where the socket template would have built eleven. The device said \"identified as: Tasmota power meter\", and the draft was empty. Now it does not even enter the race there and the next best one takes the place; what was skipped is stated in the \"why\". Optional rows do not count, that is what optional means — measured against the stock, **none** of the fifteen other templates loses any of its 51 wins. **And the try-out in the template sheet**: it now also fetches the values of the points the rows read. Without them it judged fields it could not see, and the same template reported different numbers depending on what had been clicked before. It now shows per device how many rows would really come out, and on \"does not fit\" **which mandatory row is missing** — turning \"22 devices matched, 17 of them won\" into the honest \"22 matched, 1 won · 21× does not fit\". **And the try-out now computes like the creation does**: at first it compared only against the single highest-scoring other template — if that one did not fit the device, the template under test declared itself the winner. \"Plain measuring point\" thus reported a win on a Tasmota although the socket template sits in between and really fits there. It now walks the match list like `vorschlag` does; measured afterwards, all 150 pairs of template and device agree\n* An alias whose source has vanished from the system is now visible without clicking it. Until now it was only said in the expanded detail and in the checks panel — the row in the list stayed quiet because it asked whether a source was **entered**, not whether it **exists**. The row now carries the red `!` with the note \"source does not exist\", the header a chip \"1 point points nowhere\" with the list in its tooltip, and the alias tree a red `!` on the affected channel. This is not cosmetic: the js-controller remembers \"source missing\" permanently and never corrects it — only deleting and recreating helps. It is computed once when the objects load, not on every redraw; on the production system 531 alias points in 5.2 ms. Two were found straight away: a window contact still pointing at the long-replaced `zigbee` adapter, and an NSPanel point with a missing `0_userdata` source for both reading and writing. A row with **no** source at all keeps its own note — it is unfinished, not broken\n* New: **\"Referenced in\"** on an existing alias. The box below the change comparison searches on click for whatever else mentions the ID — the **scripts** of the javascript adapter with folder, name, state and line numbers, the **files** of the instance folders (that is, the vis and vis-2 views), every loaded **object** (where the matter bridges keep their members, for instance), the **enumerations** and the entries on the point itself (`SET → influxdb.0`) — and the same again for the **source**, including further aliases on it. That answers the question of what was left behind when moving to the alias. Measured on the production system with 24,706 objects and 66 files: the first look takes 1.3 seconds, every further alias after that 0.17. The web interfaces of the adapters are not searched — 160 of the 177 MB of text in the file tree, identical on every ioBroker, and they carry examples like `alias.0.Floor.Room.MotionSensor`; without that boundary the workbench would find its own source files as users of itself. Deliberately without a verdict: a source that is still mentioned is not a fault — a script that feeds it belongs exactly there (of 376 aliases with a source, 61 still had the source mentioned directly, a good share of them rightly so). **And the delete dialog now searches the scripts too** — that only existed when moving, although deleting is the irreversible one\n* The field picker on a JSON point now copes with every key. Until now the workbench glued the field name onto the access with dots — which only works as long as every part is a valid JavaScript name. `gpu_usages.amd-vaapi.gpu` turned into an arithmetic expression (`?.amd - vaapi?.gpu`), `service.storage./dev/shm.free` and `cpu_usages.1111740.mem` into a syntax error. Measured on a Frigate telegram: of 233 offered fields **27** were usable, the other 206 ended in the red \"formula broken\" message. `feldFormel` now uses brackets where the key is not a name — `JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null` — and reads them back again, so the picker stays on the chosen field instead of falling back to \"own formula\". For ordinary names **not a single character** changes, so the shipped templates are untouched. A dot inside the key itself (`frigate.full_system`) remains unresolvable and still shows \"own formula\"",
8
+ "de": "* Nach dem Speichern fragte der nächste Klick im Baum **„Ungespeicherte Änderungen\"** — über einen Alias, der gerade geschrieben worden war. Die Marke „hier steht etwas Ungeschriebenes\" wurde im ganzen Programm nur gesetzt und nie gelöscht; weg war sie allein, wenn der Entwurf ganz wegfiel, also beim Löschen und beim Verlegen. Jetzt fällt sie nach jedem gelungenen Schreibvorgang — und nur dann: ging etwas schief, ist die Änderung tatsächlich noch nicht drin, und die Frage bleibt berechtigt. **Dazu kommt eine zweite Wirkung, die lange gefehlt hat**: Solange die Marke stand, baute die Werkbank den Entwurf absichtlich nicht neu auf. Nach dem Schreiben blieb deshalb der alte stehen, statt sich am frisch geschriebenen Alias neu aufzubauen.\n* Der zweite Druck auf **„Freie Plätze vorschlagen\"** bog eine Zeile zurück, die man selbst gesetzt hatte. An der Klimaanlage: neun Plätze raten lassen, in der SPEED-Zeile die Rolle von Hand auf `level.speed` stellen, verwerfen — und beim nächsten Vorschlag stand dort wieder das geratene `level.mode.fan`. Der Musterplatz sah frei aus, also wurde dieselbe Zeile ein zweites Mal geraten; sie trug danach **beide** Marken, „geändert\" und „vermutet\", was sich ausschließt — was frisch geraten ist, kann nicht vorher geändert worden sein. Jetzt fasst das Raten eine Zeile mit der Marke „geändert\" gar nicht erst an. Der Platz bleibt dann frei, und die Meldung darunter sagt, warum. Eine zweite Zeile daneben zu legen war die Alternative — dann hätte derselbe Quellpunkt zwei Plätze, und die achte Prüfung meldete das zu Recht.\n* Sobald Vermutungen offen waren, benannte sich der Knopf in der Musterleiste in **„Vorschläge verwerfen\"** um — und in der blauen Leiste darunter stand ein zweiter mit demselben Wort und derselben Wirkung. Zwei Knöpfe, ein Griff. In der Leiste steht jetzt immer „Freie Plätze vorschlagen\", und nur, solange es noch etwas zu raten gibt; ist alles geraten, fällt er weg. Verworfen wird dort, wo es hingehört: in der blauen Leiste, neben „alle behalten\".\n* Statt „entweder sind alle Plätze besetzt, oder kein übriger Datenpunkt passt\" steht dort der Fall, der wirklich vorliegt — und mit den **Namen** der Plätze, die frei bleiben: „Frei bleibt SPEED, SWING … Jeder übrige Datenpunkt steckt schon als Lese- oder Schreibquelle in einer belegten Zeile\" oder „… Kein übriger Datenpunkt passt dazu\". Hält eine Handentscheidung einen Platz offen, hängt ein Satz an: „1 Zeilen sind von Hand entschieden und bleiben unangetastet.\" Der Fall „alle Plätze besetzt\" bleibt ungefragt stumm — er sagt „nichts zu tun\", und das stünde sonst an fast jedem Gerät.\n* Ricardos Klimaanlage wird als **Thermostat** erkannt und belegt 3 von 24 Plätzen. **Klimaanlage** fällt durch, weil ihr einziger Pflichtplatz MODE die Rolle nicht trägt — und damit ist das Thema erledigt, denn „passt nicht\" behält das letzte Wort. Mit dem automatischen Vorschlag käme sie aber auf **9 von 29** gegenüber 8 von 24. Neben dem Musterfeld steht das jetzt: „· Klimaanlage würde evtl. besser passen\" — eine Zeile, die beiden Zahlen im Tooltip. Genannt wird **ein** Muster — das beste — und nur, wenn es wirklich besser ist; gemessen an den belegten Plätzen, nicht am Anteil. Rechts daneben steht ein kleiner Knopf **→**, der beides in einem Griff macht: auf das Muster wechseln und gleich „Freie Plätze vorschlagen\" drücken — sonst wäre der Hinweis eine Ansage ohne Handlung. In der Musterliste trägt jede betroffene Zeile hinter ihrem Fehlgrund „mit Vorschlag: passt\". Gerechnet wird einmal beim Auswählen des Geräts und danach nur noch bei einer Zeilenänderung — der Vorschlag liest Namen, Werteliste, Einheit und Typ, keine Messwerte.\n* Im **Vorlagenblatt** und im Dialog „Als Vorlage speichern\" stand der Gerätetyp mit seinem **Musterschlüssel** statt mit seinem Namen: Am Rollladen las man „blinds\", beim Mediaplayer „mediaPlayer\", beim Schieberegler „levelSlider\" — Wörter, die sonst nirgends in der Oberfläche vorkommen. Der gespeicherte Wert war die ganze Zeit richtig (der Typ, seit dem 11.09.2026), nur die Beschriftung kam aus dem falschen Feld; und weil der Admin diese drei Schlüssel nicht kennt, fiel mit ihnen auch der deutsche Beiname weg. Jetzt steht dort dasselbe wie in der Musterwahl daneben: „Jalousien · blind\".\n* Ein **Taster** lässt sich jetzt anlegen. `STOP` am Rollladen schreibt nur — ein Tastendruck hat keinen Zustand zum Lesen —, und daran scheiterte bisher der **ganze** Alias: Der Trockenlauf meldete „STOP: keine Quelle gewählt“, „Jetzt anlegen“ blieb grau, und kein einziger Rollladen-Alias hat je einen STOP bekommen. Die erste Diagnose war falsch, und das gehört dazugesagt: Nicht die Schreibprüfung war zu streng. **ioBroker weist einen Alias ohne Lesequelle ab** — ein `{ id: { write: … } }` ergibt „Alias id is invalid: The id is empty!“. Die richtige Form ist die, die Ricardo an seinen zehn handgebauten STOPs längst fährt: `alias.id` als blanker Text auf den Befehlspunkt, dazu `common.read: false` am Alias-Punkt. Der sagt vis, Alexa und matter, dass sie einen **Knopf** zeichnen sollen und keinen Kippschalter, der ewig auf „aus“ steht. Entschieden wird dabei am **Ziel**, nicht an der Rolle: `read: false` schreibt der Adapter selbst hin (nachgemessen an einem echten `hm-rpc`-STOP). Ist das Ziel lesbar, bleibt die Sperre — dann ist die fehlende Lesequelle wirklich ein Mangel. Der Taster überlebt auch das Wiedereinlesen: alle drei Stellen, die einen Alias zurücklesen, kennen ihn jetzt, sonst kippte `read` beim nächsten Aktualisieren still auf `true`. **Aus derselben Frage ist eine neue Prüfung gewachsen**: „Ziel kann, was verlangt wird“. Die Werkbank schreibt auf fremde Punkte und liest aus fremden Punkten, ohne je nachzusehen, ob die das können. Drei Arten, wie es still auseinandergeht — die Schreibformel liefert Text und das Ziel nimmt keinen; das Ziel trägt `write: false` (ioBroker legt den Wert trotzdem ab, der Adapter reicht ihn aber nicht weiter: ein stiller Blindgänger); die Lesequelle trägt `read: false` und meldet nie etwas. Alle drei stehen jetzt in der Prüfungen-Karte und als Marke an der Kennung im Detail, dort, wo man die Formel tippt\n* Die Werkbank legt MQTT-**Sendepunkte** selbst an — ein `cmnd`-Punkt entsteht in ioBroker erst, wenn auf sein Thema gesendet wurde, vorher hätte der Alias nichts zum Schreiben. Dabei nahm sie den Typ aus dem Befehlswissen, und `POWER` steht dort als `boolean` — mit der Schreibformel `val ? \"ON\" : \"OFF\"` daneben. Beides zusammen geht nicht auf: Der js-controller rechnet den Formelwert beim Schreiben auf den Typ des **Ziels** zurück, aus dem `\"ON\"` wird wieder `true`, und die Formel steht wirkungslos im Alias. Geschaltet wird trotzdem — Tasmota nimmt `on` wie `true` —, aber der Punkt sah anders aus als jeder von mqtt-client angelegte, und die Formel behauptete etwas, das sie nicht tat. Am Produktivsystem war es **einer von 196** Alias-Punkten mit MQTT-Schreibziel, und der kam von uns. Jetzt gilt: **wo eine Schreibformel steht, entsteht der Punkt als `mixed`** — keine Ausnahme für `POWER`, sondern eine Regel, die auch `Fade` und `LedTable` erfasst. Ohne Formel bleibt der genaue Typ, weil der Admin aus `number` Min, Max und Einheit zieht. **Dazu zwei Stellen, an denen man es künftig sieht**: der Typ des Zielpunktes steht als Marke hinter seiner Kennung im Detail — dort, wo man die Formel tippt —, in Warnfarbe, wenn beides nicht zusammenpasst. Und die Prüfungen-Karte hat eine achte Prüfung, „Schreibformel wirkt\", die es benennt statt es zu verschweigen\n* Eine Vorlage gilt jetzt nur dort als passend, wo ihre **Pflichtzeilen** ihre Quelle auch finden. Bisher entschied allein die Erkennung, und die stellt eine andere Frage als das Anwenden: `pruefeVorlage` prüft, ob die genannten **Punkte** da sind, die Zeilen brauchen bestimmte **Felder darin**. Eine selbstgebaute Stromzähler-Vorlage, deren Pflichtzeile `tele.SENSOR · SML.Total_Summe` liest, gewann damit an **17** gewöhnlichen Tasmotas und lieferte dort genau eine — obendrein abgewählte — Zeile, wo die Steckdosen-Vorlage elf gebaut hätte. Am Gerät stand „Identifiziert als: Tasmota-Stromzähler\", und der Entwurf war leer. Jetzt tritt sie dort gar nicht erst an, und die nächstbeste bekommt den Platz; was übergangen wurde, steht im „Warum\". Optionale Zeilen zählen nicht mit, dafür sind sie optional — gemessen am Bestand verliert **keine** der fünfzehn übrigen Vorlagen einen ihrer 51 Siege. **Dazu der Probelauf im Vorlagenblatt**: er holt sich jetzt auch die Werte der Punkte, aus denen die Zeilen lesen. Ohne die urteilte er über Felder, die er nicht sehen konnte, und dieselbe Vorlage meldete je nach Vorgeschichte andere Zahlen. Er zeigt jetzt je Gerät, wie viele Zeilen wirklich entstünden, und bei „passt nicht\" **welche Pflichtzeile fehlt** — aus „22 Geräte getroffen, 17 davon gewonnen\" wurde damit das ehrliche „22 getroffen, 1 gewonnen · 21× passt nicht\". **Und der Probelauf rechnet wie das Anlegen**: Er verglich anfangs nur gegen die eine punktbeste andere Vorlage — griff die am Gerät nicht, erklärte sich die geprüfte zur Siegerin. So meldete „Reiner Messpunkt\" an einer Tasmota einen Sieg, obwohl die Steckdosen-Vorlage dazwischenliegt und dort wirklich greift. Jetzt geht er die Trefferliste durch wie `vorschlag`; nachgemessen stimmen alle 150 Paare aus Vorlage und Gerät überein\n* Ein Alias, dessen Quelle aus dem System verschwunden ist, fällt jetzt auf, ohne dass man ihn anklickt. Gesagt wurde es bisher nur im aufgeklappten Detail und im Prüfungen-Kasten — die Zeile in der Liste schwieg, weil sie fragte, ob eine Quelle **eingetragen** ist, nicht ob es sie **gibt**. Jetzt trägt die Zeile das rote `!` mit dem Vermerk „Quelle gibt es nicht\", die Kopfzeile eine Marke „1 Punkt zeigt ins Leere\" samt Liste im Tooltip, und der Aliasbaum ein rotes `!` am betroffenen Kanal. Das ist kein Schönheitsfehler: der js-controller merkt sich „Quelle fehlt\" dauerhaft und korrigiert es nie — hilft nur löschen und neu anlegen. Gerechnet wird einmal beim Objektladen, nicht bei jedem Zeichnen; am Produktivsystem 531 Alias-Punkte in 5,2 ms. Gefunden wurden dabei gleich zwei: ein Fensterkontakt, der noch auf den längst abgelösten `zigbee`-Adapter zeigte, und ein NSPanel-Punkt mit fehlender `0_userdata`-Quelle für Lesen und Schreiben. Eine Zeile ganz **ohne** Quelle behält ihren eigenen Vermerk — sie ist unfertig, nicht kaputt\n* Neu: **„Wird genannt in\"** am vorhandenen Alias. Der Kasten unter dem Änderungsvergleich sucht auf Klick, wer die Kennung sonst noch nennt — die **Skripte** des javascript-Adapters mit Ordner, Name, Zustand und Zeilennummern, die **Dateien** der Instanzordner (also die vis- und vis-2-Ansichten), alle geladenen **Objekte** (dort legen etwa die matter-Bridges ihre Mitglieder ab), die **Aufzählungen** und die Einträge am Punkt selbst (`SET → influxdb.0`) — und dasselbe noch einmal für die **Quelle**, samt weiterer Aliase darauf. Das beantwortet die Frage, was beim Umzug auf den Alias liegen geblieben ist. Gemessen am Produktivsystem mit 24 706 Objekten und 66 Dateien: der erste Blick dauert 1,3 Sekunden, jeder weitere Alias danach 0,17. Nicht durchsucht werden die Oberflächen der Adapter — das sind 160 der 177 MB Text im Dateibaum, auf jedem ioBroker dieselben, und sie führen Beispiele wie `alias.0.Floor.Room.MotionSensor`; ohne diese Grenze fände die Werkbank ihre eigenen Quelldateien als Verwender ihrer selbst. Bewusst ohne Urteil: dass die Quelle noch genannt wird, ist kein Fehler — ein Skript, das sie beschreibt, gehört genau dorthin (von 376 Aliasen mit Quelle wurde bei 61 die Quelle weiter direkt genannt, ein guter Teil davon zu Recht). **Und der Löschdialog sucht jetzt auch** in den Skripten — das gab es nur beim Verlegen, dabei ist die Folge beim Löschen endgültig\n* Die Feldauswahl an einem JSON-Punkt kommt jetzt mit jedem Schlüssel zurecht. Bisher klebte die Werkbank den Feldnamen mit Punkten an den Zugriff — das geht nur auf, solange jeder Teil ein gültiger JavaScript-Name ist. Aus `gpu_usages.amd-vaapi.gpu` wurde dabei eine Rechnung (`?.amd - vaapi?.gpu`), aus `service.storage./dev/shm.free` und `cpu_usages.1111740.mem` ein Syntaxfehler. Gemessen an einem Frigate-Telegramm: von 233 angebotenen Feldern ließen sich **27** benutzen, die übrigen 206 endeten in der roten Meldung „Formel fehlerhaft\". Jetzt setzt `feldFormel` Klammern, wo der Schlüssel kein Name ist — `JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null` —, und liest sie auch wieder zurück, damit das Auswahlfeld auf dem gewählten Feld stehen bleibt statt auf „eigene Formel\". Für gewöhnliche Namen ändert sich **kein Zeichen**, die mitgelieferten Vorlagen bleiben also unberührt. Ein Punkt im Schlüssel selbst (`frigate.full_system`) bleibt unauflösbar und zeigt weiter „eigene Formel\"",
9
+ "ru": "* После сохранения следующий щелчок в дереве спрашивал **«несохранённые изменения»** — про алиас, который только что был записан. Метка «здесь есть незаписанное» во всей программе только выставлялась и никогда не снималась; она исчезала лишь тогда, когда пропадал сам черновик, то есть при удалении и при переносе. Теперь она снимается после каждой удачной записи — и только тогда: если что-то не получилось, изменение действительно ещё не внутри, и вопрос остаётся оправданным. **Есть и второй эффект, которого давно не хватало**: пока метка стояла, верстак намеренно не пересобирал черновик. После записи оставался старый вместо того, чтобы собраться заново по свежезаписанному алиасу.\n* Второе нажатие **«Предложить свободные места»** возвращало назад строку, которую вы задали сами. На кондиционере: угадать девять мест, вручную поставить роль строки SPEED на `level.speed`, отменить — и следующее предложение снова подставляло угаданное `level.mode.fan`. Место шаблона выглядело свободным, поэтому та же строка угадывалась второй раз; после этого она несла **обе** метки, «изменено» и «предположено», которые исключают друг друга — то, что только что угадано, не могло быть изменено раньше. Теперь угадывание не трогает строку с меткой «изменено». Место остаётся свободным, а сообщение под панелью говорит почему. Положить рядом вторую строку было альтернативой — тогда одна и та же исходная точка заняла бы два места, и восьмая проверка справедливо сообщила бы об этом.\n* Как только появлялись предположения, кнопка в панели шаблона переименовывалась в **«Отклонить предложения»** — а вторая с тем же словом и тем же действием стояла в синей полосе под ней. Две кнопки, одна ручка. В панели теперь всегда написано «Предложить свободные места», и только пока есть что угадывать; когда угадано всё, кнопка исчезает. Отклоняют там, где этому место: в синей полосе, рядом с «оставить все».\n* Вместо «либо все места заняты, либо ни одна оставшаяся точка не подходит» сообщение теперь называет случай, который действительно имеет место — с **именами** мест, остающихся свободными: «Свободными остаются SPEED, SWING … Каждая оставшаяся точка уже служит источником чтения или записи в занятой строке» либо «… Ни одна оставшаяся точка сюда не подходит». Если решение, принятое вручную, держит место открытым, добавляется фраза: «1 строк решены вручную и остаются нетронутыми». Случай «все места заняты» без спроса молчит — он говорит «делать нечего», а иначе стоял бы почти у каждого устройства.\n* Кондиционер Рикардо распознаётся как **термостат** и занимает 3 из 24 мест. **airCondition** не проходит, потому что его единственное обязательное место MODE не несёт нужной роли — и на этом всё, ведь «не подходит» остаётся последним словом. С автоматическим предложением он дошёл бы до **9 из 29** против 8 из 24. Теперь это стоит рядом с полем шаблона: «· airCondition, возможно, подошёл бы лучше» — одна строка, оба числа во всплывающей подсказке. Называется **один** шаблон — лучший — и только тогда, когда он действительно лучше; мерится занятыми местами, а не долей. Рядом сидит маленькая кнопка **→**, которая делает оба шага сразу: переключает на этот шаблон и тут же нажимает «Предложить свободные места» — иначе подсказка была бы объявлением без действия. В списке шаблонов каждая затронутая строка несёт «с предложением: подходит» после причины отказа. Считается один раз при выборе устройства и далее только при изменении строки — предложение читает имена, списки значений, единицы и типы, но не измеренные значения.\n* В **листе шаблона** и в диалоге «сохранить как шаблон» тип устройства показывался своим **ключом шаблона**, а не именем: у жалюзи читалось «blinds», у медиаплеера «mediaPlayer», у ползунка «levelSlider» — слова, которых больше нигде в интерфейсе нет. Сохранённое значение всё это время было верным (тип, с 11.09.2026); неверной была только подпись, она приходила из другого поля, а поскольку Admin не знает этих трёх ключей, вместе с ними пропадало и переведённое имя. Теперь там написано то же, что и в выборе шаблона рядом: «Жалюзи · blind».\n* Теперь можно создать **кнопку**. `STOP` у жалюзи только пишет — у нажатия клавиши нет состояния для чтения — и это раньше срывало **весь** алиас: пробный прогон говорил «STOP: источник не выбран», «создать сейчас» оставалась серой, и ни один алиас жалюзи так и не получил STOP. Первый диагноз был неверным, и это стоит сказать: дело было не в слишком строгой проверке записи. **ioBroker отклоняет алиас без источника чтения** — `{ id: { write: … } }` даёт «Alias id is invalid: The id is empty!». Правильная форма — та, которую Рикардо давно использует на своих десяти рукотворных STOP: `alias.id` как простой текст, указывающий на командную точку, плюс `common.read: false` на точке алиаса. Это говорит vis, Alexa и matter рисовать **кнопку**, а не переключатель, навсегда застрявший в «выкл». Решает **цель**, а не роль: `read: false` пишет сам адаптер (измерено на настоящем STOP у `hm-rpc`). Если цель читаема, блокировка остаётся — тогда отсутствующий источник чтения действительно дефект. Кнопка переживает и обратное чтение: все три места, которые восстанавливают алиас, теперь про неё знают, иначе `read` тихо переключился бы на `true` при следующем обновлении. **Из того же вопроса выросла новая проверка**: «цель умеет то, что от неё требуют». Верстак пишет в чужие точки и читает из чужих точек, ни разу не проверив, умеют ли они это. Три способа тихо развалиться — формула записи выдаёт текст, а цель текста не принимает; цель несёт `write: false` (ioBroker всё равно кладёт значение, но адаптер ничего дальше не передаёт: тихий холостой ход); источник чтения несёт `read: false` и никогда ничего не сообщает. Все три теперь появляются в блоке проверок и как значок у идентификатора в подробном виде, ровно там, где набирается формула\n* Верстак сам создаёт **точки отправки** MQTT — точка `cmnd` возникает в ioBroker лишь после того, как в её топик что-то опубликовано; до этого алиасу было бы некуда писать. Тип он брал из знания о командах, а `POWER` записан там как `boolean` — прямо рядом с формулой записи `val ? \"ON\" : \"OFF\"`. Одно с другим не сходится: js-controller при записи преобразует результат формулы обратно к типу **цели**, «ON» снова становится `true`, и формула лежит в алиасе без действия. Переключение всё равно работает — Tasmota принимает и `on`, и `true` — но точка выглядела иначе, чем любая точка, созданная mqtt-client, а формула утверждала то, чего не делала. На продуктивной системе это была **одна из 196** точек алиасов с целью записи MQTT, и пришла она от нас. Правило теперь такое: **где есть формула записи, точка создаётся как `mixed`** — не исключение для `POWER`, а правило, которое покрывает и `Fade`, и `LedTable`. Без формулы точный тип сохраняется, потому что admin выводит min, max и единицу из `number`. **Плюс два места, где это становится видно**: тип целевой точки теперь показан значком после её идентификатора в подробном виде — ровно там, где набирается формула — предупреждающим цветом, когда одно с другим не сходится. А в блоке проверок появилась восьмая проверка «формула записи действует», которая называет это вместо того, чтобы молчать\n* Шаблон теперь считается подходящим только там, где его **обязательные строки** действительно находят свой источник. До сих пор решало одно лишь распознавание, а распознавание задаёт другой вопрос, чем применение: `pruefeVorlage` проверяет, есть ли названные **точки**, строкам же нужны определённые **поля внутри них**. Самодельный шаблон счётчика электроэнергии, чья обязательная строка читает `tele.SENSOR · SML.Total_Summe`, побеждал таким образом на **17** обычных устройствах Tasmota и выдавал там ровно одну — к тому же снятую — строку там, где шаблон розетки построил бы одиннадцать. У устройства стояло «распознано как: счётчик Tasmota», а черновик был пуст. Теперь он там даже не выходит на старт, и место достаётся следующему по силе; что было пропущено, написано в «почему». Необязательные строки не считаются, на то они и необязательные — по замеру на имеющемся фонде **ни один** из пятнадцати остальных шаблонов не теряет ни одной из своих 51 побед. **И пробный прогон в листе шаблона**: он теперь забирает и значения точек, из которых читают строки. Без них он судил о полях, которых не видел, и один и тот же шаблон сообщал разные числа в зависимости от предыстории. Теперь он показывает по каждому устройству, сколько строк вышло бы на самом деле, а при «не подходит» — **какой обязательной строки не хватает**; так «22 устройства затронуто, 17 из них выиграно» превратилось в честное «22 затронуто, 1 выиграно · 21× не подходит». **И пробный прогон считает так же, как создание**: сперва он сравнивал лишь с одним другим шаблоном, набравшим больше всех очков — если тот не подходил устройству, проверяемый объявлял себя победителем. Так «чистая точка измерения» сообщала о победе на Tasmota, хотя между ними стоит шаблон розетки, который там действительно подходит. Теперь он проходит список совпадений так же, как `vorschlag`; при повторном замере все 150 пар «шаблон — устройство» совпадают\n* Алиас, чей источник исчез из системы, теперь заметен без щелчка по нему. До сих пор об этом говорилось лишь в развёрнутой подробности и в блоке проверок — строка в списке молчала, потому что спрашивала, **внесён** ли источник, а не **существует** ли он. Теперь строка несёт красный `!` с пометкой «источника не существует», заголовок — значок «1 точка указывает в пустоту» со списком во всплывающей подсказке, а дерево алиасов — красный `!` у затронутого канала. Это не косметика: js-controller запоминает «источник отсутствует» навсегда и никогда сам этого не исправляет — помогает только удалить и создать заново. Считается один раз при загрузке объектов, а не при каждой отрисовке; на продуктивной системе 531 точка алиасов за 5,2 мс. Сразу нашлись две: оконный контакт, всё ещё указывающий на давно заменённый адаптер `zigbee`, и точка NSPanel с отсутствующим источником `0_userdata` и для чтения, и для записи. Строка **вовсе** без источника сохраняет свою собственную пометку — она недоделана, а не сломана\n* Новое: **«Упоминается в»** у существующего алиаса. Блок под сравнением изменений ищет по щелчку всё, что ещё упоминает идентификатор — **скрипты** адаптера javascript с папкой, именем, состоянием и номерами строк, **файлы** папок экземпляров (то есть виды vis и vis-2), каждый загруженный **объект** (например, там, где мосты matter хранят своих участников), **перечисления** и записи у самой точки (`SET → influxdb.0`) — и то же самое для **источника**, включая другие алиасы на нём. Это отвечает на вопрос, что осталось позади при переходе на алиас. Измерено на продуктивной системе с 24 706 объектами и 66 файлами: первый взгляд занимает 1,3 секунды, каждый следующий алиас после этого 0,17. Веб-интерфейсы адаптеров не обыскиваются — 160 из 177 МБ текста в файловом дереве, одинаковые на каждом ioBroker, и они несут примеры вроде `alias.0.Floor.Room.MotionSensor`; без этой границы верстак нашёл бы собственные исходники как своих же пользователей. Намеренно без приговора: источник, который всё ещё упоминается, не ошибка — скрипт, который его питает, находится ровно там, где надо (из 376 алиасов с источником у 61 источник по-прежнему упоминался напрямую, и у доброй части заслуженно). **А диалог удаления теперь тоже ищет по скриптам** — это было только при переносе, хотя необратимо как раз удаление\n* Выбор поля у точки JSON теперь справляется с любым ключом. До сих пор верстак приклеивал имя поля к обращению через точки — что работает лишь до тех пор, пока каждая часть является допустимым именем JavaScript. `gpu_usages.amd-vaapi.gpu` превращался в арифметическое выражение (`?.amd - vaapi?.gpu`), `service.storage./dev/shm.free` и `cpu_usages.1111740.mem` — в синтаксическую ошибку. Измерено на телеграмме Frigate: из 233 предложенных полей пригодными были **27**, остальные 206 заканчивались красным сообщением «формула сломана». `feldFormel` теперь ставит скобки там, где ключ не является именем — `JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null` — и читает их обратно, так что выбор остаётся на выбранном поле вместо того, чтобы откатываться к «собственной формуле». Для обычных имён не меняется **ни один символ**, так что поставляемые шаблоны не тронуты. Точка внутри самого ключа (`frigate.full_system`) остаётся неразрешимой и по-прежнему показывает «собственная формула»",
10
+ "pt": "* Depois de guardar, o clique seguinte na árvore perguntava **«alterações não guardadas»** — a respeito de um alias que acabara de ser escrito. A marca «há aqui algo por escrever» era apenas colocada e nunca apagada; só desaparecia quando desaparecia o próprio rascunho, ou seja ao eliminar e ao mover. Agora cai após cada escrita bem-sucedida — e só então: se algo correu mal, a alteração realmente ainda não está lá dentro, e a pergunta continua justificada. **Há um segundo efeito que faltava há muito**: enquanto a marca estava posta, a bancada não reconstruía o rascunho de propósito. Depois de uma escrita ficava portanto o antigo, em vez de se reconstruir a partir do alias acabado de escrever.\n* Uma segunda pressão em **«Propor lugares livres»** fazia recuar uma linha que tinhas definido tu. No ar condicionado: mandar adivinhar nove lugares, pôr à mão o papel da linha SPEED em `level.speed`, descartar — e a proposta seguinte voltava a pôr o adivinhado `level.mode.fan`. O lugar do modelo parecia livre, por isso a mesma linha era adivinhada uma segunda vez; passava então a levar **ambas** as marcas, «alterada» e «presumida», que se excluem mutuamente — o que acabou de ser adivinhado não pode ter sido alterado antes. Agora a adivinhação deixa em paz qualquer linha marcada como «alterada». O lugar fica livre, e a mensagem por baixo diz porquê. Pôr uma segunda linha ao lado era a alternativa — o mesmo ponto de origem ocuparia então dois lugares, e a oitava verificação assinalá-lo-ia com razão.\n* Assim que havia suposições pendentes, o botão da barra de modelos mudava de nome para **«Descartar propostas»** — e um segundo com a mesma palavra e o mesmo efeito estava na barra azul por baixo. Dois botões, um só puxador. Na barra está agora sempre «Propor lugares livres», e só enquanto restar algo por adivinhar; uma vez tudo adivinhado, desaparece. Descarta-se onde é o seu lugar: na barra azul, ao lado de «guardar todos».\n* Em vez de «ou todos os lugares estão ocupados, ou nenhum ponto de dados restante serve», a mensagem nomeia agora o caso que realmente ocorre — com os **nomes** dos lugares que ficam livres: «Ficam livres SPEED, SWING … Cada ponto de dados restante já serve de origem de leitura ou de escrita numa linha ocupada», ou «… Nenhum ponto de dados restante serve aqui». Se uma decisão tomada à mão mantém um lugar aberto, acrescenta-se uma frase: «1 linhas foram decididas à mão e ficam intocadas.» O caso «todos os lugares ocupados» cala-se sem que se pergunte — diz «nada a fazer», e de outro modo apareceria em quase todos os dispositivos.\n* O ar condicionado do Ricardo é reconhecido como **termóstato** e ocupa 3 de 24 lugares. **airCondition** falha porque o seu único lugar obrigatório, MODE, não leva o papel — e com isso o assunto fica encerrado, pois «não serve» tem a última palavra. Com a proposta automática chegaria a **9 de 29** contra 8 de 24. Isso está agora ao lado do campo do modelo: «· airCondition talvez servisse melhor» — uma única linha, ambos os números na dica. É nomeado **um** só modelo — o melhor — e apenas quando é realmente melhor; mede-se em lugares ocupados, não em proporção. Ao lado fica um pequeno botão **→** que faz as duas coisas de uma vez: mudar para esse modelo e premir logo «Propor lugares livres» — caso contrário a indicação seria um anúncio sem ação. Na lista de modelos, cada linha afetada leva «com proposta: serve» atrás do seu motivo de recusa. É calculado uma vez ao escolher o dispositivo e depois só numa alteração de linha — a proposta lê nomes, listas de valores, unidades e tipos, não valores medidos.\n* Na **folha de modelo** e na caixa «guardar como modelo», o tipo de dispositivo mostrava a sua **chave de modelo** em vez do nome: num estore lia-se «blinds», num leitor multimédia «mediaPlayer», num cursor «levelSlider» — palavras que não aparecem em mais lado nenhum da interface. O valor guardado esteve certo todo o tempo (o tipo, desde 11.09.2026); só o rótulo vinha do campo errado, e como o Admin não conhece essas três chaves, com elas perdia-se também o nome traduzido. Agora lá está o mesmo que na escolha de modelo ao lado: «Estores · blind».\n* Agora pode criar-se um **botão de impulso**. `STOP` num estore só escreve — uma pressão de tecla não tem estado para ler — e isso deitava antes por terra o alias **inteiro**: o ensaio dizia «STOP: nenhuma origem escolhida», «criar agora» ficava a cinzento, e nenhum alias de estore alguma vez recebeu um STOP. O primeiro diagnóstico estava errado, e vale a pena dizê-lo: não era a verificação de escrita ser demasiado rígida. **O ioBroker recusa um alias sem origem de leitura** — `{ id: { write: … } }` dá «Alias id is invalid: The id is empty!». A forma correta é a que o Ricardo usa há muito nos seus dez STOP feitos à mão: `alias.id` como simples texto a apontar para o ponto de comando, mais `common.read: false` no ponto do alias. Isso diz ao vis, à Alexa e ao matter para desenharem um **botão de impulso** e não um interruptor preso para sempre em «desligado». O que decide é o **destino**, não o papel: `read: false` é escrito pelo próprio adaptador (medido num STOP real de `hm-rpc`). Se o destino for legível, o bloqueio mantém-se — então a origem de leitura em falta é mesmo um defeito. O botão sobrevive também à releitura: os três lugares que reconstroem um alias conhecem-no agora, caso contrário `read` voltaria em silêncio a `true` na atualização seguinte. **Da mesma pergunta nasceu uma nova verificação**: «o destino sabe fazer o que lhe é pedido». A bancada escreve em pontos alheios e lê de pontos alheios sem nunca verificar se eles o conseguem. Três maneiras de desmoronar em silêncio — a fórmula de escrita produz texto e o destino não o aceita; o destino leva `write: false` (o ioBroker guarda o valor na mesma, mas o adaptador não passa nada adiante: um tiro em falso silencioso); a origem de leitura leva `read: false` e nunca comunica nada. As três aparecem agora no painel de verificações e como etiqueta no identificador na vista de detalhe, precisamente onde a fórmula é escrita\n* A bancada cria ela própria os **pontos de envio** MQTT — um ponto `cmnd` só nasce no ioBroker depois de algo ter sido publicado no seu tópico; antes disso o alias não teria onde escrever. Tirava o tipo do conhecimento de comandos, e `POWER` figura lá como `boolean` — mesmo ao lado da fórmula de escrita `val ? \"ON\" : \"OFF\"`. As duas coisas não batem certo: ao escrever, o js-controller reconverte o resultado da fórmula para o tipo do **destino**, o «ON» volta a ser `true`, e a fórmula fica no alias sem efeito. A comutação funciona à mesma — o Tasmota aceita tanto `on` como `true` — mas o ponto parecia diferente de qualquer ponto criado pelo mqtt-client, e a fórmula afirmava algo que não fazia. No sistema produtivo era **um de 196** pontos de alias com destino de escrita MQTT, e vinha de nós. A regra passa a ser: **onde existe uma fórmula de escrita, o ponto é criado como `mixed`** — não uma exceção para `POWER` mas uma regra que abrange também `Fade` e `LedTable`. Sem fórmula mantém-se o tipo exato, porque o admin deriva mín., máx. e unidade de `number`. **Mais dois sítios onde isso fica visível**: o tipo do ponto de destino aparece agora como etiqueta atrás do seu identificador na vista de detalhe — precisamente onde a fórmula é escrita — em cor de aviso quando os dois não coincidem. E o painel de verificações tem uma oitava verificação, «a fórmula de escrita faz efeito», que o nomeia em vez de se calar\n* Um modelo só conta como adequado onde as suas **linhas obrigatórias** encontram realmente a sua origem. Até agora decidia apenas o reconhecimento, e o reconhecimento faz outra pergunta que a aplicação: `pruefeVorlage` verifica se os **pontos** nomeados existem, as linhas precisam de determinados **campos lá dentro**. Um modelo caseiro de contador de energia, cuja linha obrigatória lê `tele.SENSOR · SML.Total_Summe`, vencia assim em **17** Tasmota comuns e entregava lá exatamente uma linha — ainda por cima desmarcada — onde o modelo da tomada teria construído onze. No dispositivo estava «identificado como: contador Tasmota», e o rascunho estava vazio. Agora nem sequer entra em prova ali e o lugar vai para o seguinte melhor; o que foi ultrapassado consta do «porquê». As linhas opcionais não contam, é por isso que são opcionais — medido no parque existente, **nenhum** dos quinze modelos restantes perde uma única das suas 51 vitórias. **E o ensaio na folha de modelo**: passa agora a buscar também os valores dos pontos de onde as linhas leem. Sem eles julgava campos que não conseguia ver, e o mesmo modelo comunicava números diferentes conforme o que tinha sido clicado antes. Mostra agora por dispositivo quantas linhas sairiam realmente, e em caso de «não serve» **qual a linha obrigatória em falta** — transformando «22 dispositivos atingidos, 17 ganhos» no honesto «22 atingidos, 1 ganho · 21× não serve». **E o ensaio calcula como a criação**: ao início comparava apenas com o único outro modelo de pontuação mais alta — se esse não servia ao dispositivo, o modelo em análise declarava-se vencedor. Assim «ponto de medição puro» anunciava uma vitória num Tasmota, embora o modelo da tomada esteja pelo meio e ali sirva mesmo. Percorre agora a lista de correspondências como o `vorschlag`; medidos de novo, todos os 150 pares de modelo e dispositivo coincidem\n* Um alias cuja origem desapareceu do sistema dá agora nas vistas sem se clicar nele. Até agora só era dito no detalhe expandido e no painel de verificações — a linha da lista calava-se, porque perguntava se havia uma origem **introduzida**, não se ela **existe**. A linha leva agora o `!` vermelho com a nota «a origem não existe», o cabeçalho uma etiqueta «1 ponto aponta para o vazio» com a lista na dica, e a árvore de alias um `!` vermelho no canal afetado. Isto não é cosmética: o js-controller guarda «origem em falta» de forma duradoura e nunca o corrige — só ajuda apagar e criar de novo. É calculado uma vez ao carregar os objetos, não a cada desenho; no sistema produtivo, 531 pontos de alias em 5,2 ms. Logo se encontraram dois: um contacto de janela ainda a apontar para o adaptador `zigbee` há muito substituído, e um ponto NSPanel com origem `0_userdata` em falta tanto para ler como para escrever. Uma linha **sem qualquer** origem mantém a sua própria nota — está por acabar, não está partida\n* Novo: **«Referido em»** no alias existente. O painel por baixo da comparação de alterações procura, ao clique, tudo o que ainda refere o identificador — os **scripts** do adaptador javascript com pasta, nome, estado e números de linha, os **ficheiros** das pastas de instância (ou seja, as vistas do vis e do vis-2), cada **objeto** carregado (onde as pontes matter guardam os seus membros, por exemplo), as **enumerações** e as entradas no próprio ponto (`SET → influxdb.0`) — e o mesmo para a **origem**, incluindo outros alias sobre ela. Isso responde à pergunta do que ficou para trás na passagem para o alias. Medido no sistema produtivo com 24 706 objetos e 66 ficheiros: o primeiro olhar leva 1,3 segundos, cada alias seguinte 0,17. As interfaces web dos adaptadores não são vasculhadas — 160 dos 177 MB de texto na árvore de ficheiros, idênticas em cada ioBroker, e trazem exemplos como `alias.0.Floor.Room.MotionSensor`; sem esse limite a bancada encontraria as suas próprias fontes como utilizadoras de si mesma. Deliberadamente sem veredicto: uma origem ainda referida não é uma falha — um script que a alimenta está exatamente onde deve (de 376 alias com origem, 61 tinham ainda a origem referida diretamente, boa parte deles com razão). **E a caixa de eliminação procura agora também nos scripts** — isso só existia ao mover, embora seja a eliminação que é irreversível\n* A escolha de campo num ponto JSON lida agora com qualquer chave. Até agora a bancada colava o nome do campo ao acesso com pontos — o que só funciona enquanto cada parte for um nome JavaScript válido. `gpu_usages.amd-vaapi.gpu` tornava-se uma expressão aritmética (`?.amd - vaapi?.gpu`), `service.storage./dev/shm.free` e `cpu_usages.1111740.mem` um erro de sintaxe. Medido num telegrama do Frigate: dos 233 campos oferecidos **27** eram utilizáveis, os outros 206 acabavam na mensagem vermelha «fórmula partida». O `feldFormel` usa agora parênteses retos onde a chave não é um nome — `JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null` — e volta a lê-los, de modo que a escolha permanece no campo escolhido em vez de recuar para «fórmula própria». Para nomes comuns não muda **um único caractere**, pelo que os modelos fornecidos ficam intocados. Um ponto dentro da própria chave (`frigate.full_system`) continua insolúvel e mostra ainda «fórmula própria»",
11
+ "nl": "* Na het opslaan vroeg de volgende klik in de boom **«niet-opgeslagen wijzigingen»** — over een alias die net was weggeschreven. De markering «hier staat iets ongeschrevens» werd alleen maar gezet en nooit gewist; ze verdween uitsluitend wanneer het concept zelf verdween, dus bij verwijderen en bij verplaatsen. Ze valt nu weg na elke geslaagde schrijfactie — en alleen dan: ging er iets mis, dan zit de wijziging er werkelijk nog niet in, en blijft de vraag terecht. **Er is een tweede gevolg dat lang heeft ontbroken**: zolang de markering stond, bouwde de werkbank het concept met opzet niet opnieuw op. Na een schrijfactie bleef daarom het oude staan, in plaats van zich op de zojuist geschreven alias opnieuw op te bouwen.\n* Een tweede druk op **«Vrije plaatsen voorstellen»** boog een regel terug die je zelf had ingesteld. Op de airco: negen plaatsen laten raden, de rol van de regel SPEED met de hand op `level.speed` zetten, verwerpen — en het volgende voorstel zette het geraden `level.mode.fan` er weer neer. De plaats van het patroon leek vrij, dus werd dezelfde regel een tweede keer geraden; ze droeg toen **beide** markeringen, «gewijzigd» en «vermoed», die elkaar uitsluiten — wat zojuist geraden is, kan niet eerder gewijzigd zijn. Het raden laat nu elke regel met de markering «gewijzigd» met rust. De plaats blijft vrij, en de melding eronder zegt waarom. Een tweede regel ernaast leggen was het alternatief — hetzelfde bronpunt zou dan twee plaatsen bezetten, en de achtste controle zou dat terecht melden.\n* Zodra er vermoedens openstonden, hernoemde de knop in de patroonbalk zichzelf tot **«Voorstellen verwerpen»** — en een tweede met hetzelfde woord en hetzelfde effect stond in de blauwe balk eronder. Twee knoppen, één handgreep. In de balk staat nu altijd «Vrije plaatsen voorstellen», en alleen zolang er nog iets te raden valt; is alles geraden, dan verdwijnt hij. Verwerpen gebeurt waar het hoort: in de blauwe balk, naast «alles behouden».\n* In plaats van «ofwel zijn alle plaatsen bezet, ofwel past geen enkel overgebleven datapunt» noemt de melding nu het geval dat zich werkelijk voordoet — met de **namen** van de plaatsen die vrij blijven: «Vrij blijven SPEED, SWING … Elk overgebleven datapunt dient al als lees- of schrijfbron in een bezette regel», of «… Geen enkel overgebleven datapunt past hierbij». Houdt een met de hand genomen beslissing een plaats open, dan komt er een zin bij: «1 regels zijn met de hand beslist en blijven onaangeroerd.» Het geval «alle plaatsen bezet» zwijgt ongevraagd — het zegt «niets te doen», en zou anders bij bijna elk apparaat staan.\n* Ricardo’s airco wordt herkend als **thermostaat** en vult 3 van de 24 plaatsen. **airCondition** valt af omdat zijn enige verplichte plaats, MODE, de rol niet draagt — en daarmee is de kous af, want «past niet» heeft het laatste woord. Met het automatische voorstel zou hij op **9 van 29** komen tegen 8 van 24. Dat staat nu naast het patroonveld: «· airCondition zou misschien beter passen» — één regel, beide getallen in de tooltip. Er wordt **één** patroon genoemd — het beste — en alleen wanneer het werkelijk beter is; gemeten in bezette plaatsen, niet in verhouding. Ernaast zit een kleine knop **→** die beide in één greep doet: naar dat patroon overschakelen en meteen «Vrije plaatsen voorstellen» indrukken — anders zou de aanwijzing een mededeling zonder handeling zijn. In de patroonlijst draagt elke betrokken regel «met voorstel: past» achter haar reden van afwijzing. Er wordt één keer gerekend bij het kiezen van het apparaat en daarna alleen bij een regelwijziging — het voorstel leest namen, waardelijsten, eenheden en typen, geen meetwaarden.\n* In het **sjabloonblad** en in het venster «als sjabloon opslaan» toonde het apparaattype zijn **patroonsleutel** in plaats van zijn naam: bij een rolluik las je «blinds», bij een mediaspeler «mediaPlayer», bij een schuifregelaar «levelSlider» — woorden die nergens anders in de interface voorkomen. De opgeslagen waarde was al die tijd juist (het type, sinds 11.09.2026); alleen het opschrift kwam uit het verkeerde veld, en omdat de Admin die drie sleutels niet kent, viel daarmee ook de vertaalde naam weg. Er staat nu hetzelfde als in de patroonkeuze ernaast: «Rolluiken · blind».\n* Een **drukknop** kan nu worden aangemaakt. `STOP` op een rolluik schrijft alleen — een toetsdruk heeft geen toestand om te lezen — en dat liet vroeger de **hele** alias stranden: de proefdraai zei «STOP: geen bron gekozen», «nu aanmaken» bleef grijs, en geen enkele rolluikalias heeft ooit een STOP gekregen. De eerste diagnose was fout, en dat mag gezegd: het lag niet aan een te strenge schrijfcontrole. **ioBroker weigert een alias zonder leesbron** — `{ id: { write: … } }` levert «Alias id is invalid: The id is empty!». De juiste vorm is die welke Ricardo al lang gebruikt op zijn tien met de hand gebouwde STOP’s: `alias.id` als gewone tekst die naar het commandopunt wijst, plus `common.read: false` op het aliaspunt. Dat zegt vis, Alexa en matter een **drukknop** te tekenen in plaats van een schakelaar die voor eeuwig op «uit» blijft staan. Wat beslist is het **doel**, niet de rol: `read: false` wordt door de adapter zelf geschreven (gemeten op een echte `hm-rpc`-STOP). Is het doel leesbaar, dan blijft de blokkade — dan is de ontbrekende leesbron werkelijk een gebrek. De knop overleeft ook het teruglezen: alle drie de plaatsen die een alias opnieuw opbouwen kennen hem nu, anders zou `read` bij de volgende update stilletjes op `true` omslaan. **Uit dezelfde vraag groeide een nieuwe controle**: «doel kan wat gevraagd wordt». De werkbank schrijft op vreemde punten en leest uit vreemde punten zonder ooit te controleren of die dat kunnen. Drie manieren om stil uit elkaar te vallen — de schrijfformule levert tekst en het doel neemt er geen; het doel draagt `write: false` (ioBroker legt de waarde toch weg maar de adapter geeft niets door: een stille misser); de leesbron draagt `read: false` en meldt nooit iets. Alle drie verschijnen nu in het controlekader en als chip op de ID in de detailweergave, precies waar de formule wordt ingetikt\n* De werkbank maakt de MQTT-**verzendpunten** zelf aan — een `cmnd`-punt ontstaat in ioBroker pas zodra er iets op zijn topic is gepubliceerd; daarvoor zou de alias nergens naartoe kunnen schrijven. Het type haalde hij uit de commandokennis, en `POWER` staat daar als `boolean` — pal naast de schrijfformule `val ? \"ON\" : \"OFF\"`. Die twee rijmen niet: de js-controller rekent het formuleresultaat bij het schrijven terug naar het type van het **doel**, de «ON» wordt weer `true`, en de formule ligt zonder werking in de alias. Schakelen werkt toch — Tasmota neemt zowel `on` als `true` — maar het punt zag er anders uit dan elk punt dat mqtt-client aanmaakt, en de formule beweerde iets wat ze niet deed. Op het productiesysteem was het **één van de 196** aliaspunten met een MQTT-schrijfdoel, en het kwam van ons. De regel luidt nu: **waar een schrijfformule bestaat, wordt het punt als `mixed` aangemaakt** — geen uitzondering voor `POWER` maar een regel die ook `Fade` en `LedTable` dekt. Zonder formule blijft het exacte type staan, omdat de admin min, max en eenheid uit `number` afleidt. **Plus twee plekken waar het zichtbaar wordt**: het type van het doelpunt staat nu als chip achter de ID in de detailweergave — precies waar de formule wordt ingetikt — in waarschuwingskleur wanneer beide niet bij elkaar passen. En het controlekader heeft een achtste controle, «schrijfformule werkt», die het benoemt in plaats van te zwijgen\n* Een sjabloon geldt nu alleen daar als passend waar zijn **verplichte regels** hun bron werkelijk vinden. Tot nu besliste alleen de herkenning, en de herkenning stelt een andere vraag dan het toepassen: `pruefeVorlage` controleert of de genoemde **punten** er zijn, de regels hebben bepaalde **velden daarbinnen** nodig. Een zelfgebouwd sjabloon voor een energiemeter, waarvan de verplichte regel `tele.SENSOR · SML.Total_Summe` leest, won zo op **17** gewone Tasmota’s en leverde daar precies één — bovendien uitgevinkte — regel, waar het stopcontactsjabloon er elf zou hebben gebouwd. Bij het apparaat stond «geïdentificeerd als: Tasmota-energiemeter», en het concept was leeg. Nu komt het daar niet eens aan de start en gaat de plaats naar het volgende beste; wat werd overgeslagen staat in het «waarom». Optionele regels tellen niet mee, daarvoor zijn ze optioneel — gemeten aan het bestand verliest **geen** van de vijftien overige sjablonen ook maar één van zijn 51 overwinningen. **En de proef in het sjabloonblad**: die haalt nu ook de waarden op van de punten waaruit de regels lezen. Zonder die oordeelde hij over velden die hij niet kon zien, en hetzelfde sjabloon meldde andere getallen naargelang wat er eerder was aangeklikt. Hij toont nu per apparaat hoeveel regels er werkelijk uit zouden komen, en bij «past niet» **welke verplichte regel ontbreekt** — zo werd «22 apparaten geraakt, 17 daarvan gewonnen» het eerlijke «22 geraakt, 1 gewonnen · 21× past niet». **En de proef rekent nu zoals het aanmaken**: eerst vergeleek hij alleen met het ene andere sjabloon met de hoogste score — paste dat niet bij het apparaat, dan riep het beproefde sjabloon zichzelf tot winnaar uit. Zo meldde «zuiver meetpunt» een overwinning op een Tasmota, hoewel het stopcontactsjabloon ertussen zit en daar werkelijk past. Hij loopt de treffers nu af zoals `vorschlag` dat doet; nagemeten kloppen alle 150 paren van sjabloon en apparaat\n* Een alias waarvan de bron uit het systeem verdwenen is, valt nu op zonder dat je erop klikt. Tot nu werd het alleen gezegd in het uitgeklapte detail en in het controlekader — de regel in de lijst zweeg, omdat ze vroeg of er een bron **ingevuld** was, niet of die **bestaat**. De regel draagt nu de rode `!` met de vermelding «bron bestaat niet», de kopregel een chip «1 punt wijst in het niets» met de lijst in de tooltip, en de aliasboom een rode `!` bij het betrokken kanaal. Dat is geen schoonheidsfoutje: de js-controller onthoudt «bron ontbreekt» blijvend en corrigeert het nooit — alleen verwijderen en opnieuw aanmaken helpt. Er wordt één keer gerekend bij het laden van de objecten, niet bij elk tekenen; op het productiesysteem 531 aliaspunten in 5,2 ms. Er werden er meteen twee gevonden: een raamcontact dat nog naar de allang vervangen `zigbee`-adapter wees, en een NSPanel-punt met een ontbrekende `0_userdata`-bron voor zowel lezen als schrijven. Een regel **helemaal zonder** bron houdt haar eigen vermelding — die is onaf, niet stuk\n* Nieuw: **«Wordt genoemd in»** bij de bestaande alias. Het kader onder de wijzigingsvergelijking zoekt op een klik alles wat de ID nog noemt — de **scripts** van de javascript-adapter met map, naam, toestand en regelnummers, de **bestanden** van de instantiemappen (dus de vis- en vis-2-weergaven), elk geladen **object** (waar de matter-bruggen bijvoorbeeld hun leden bewaren), de **opsommingen** en de vermeldingen op het punt zelf (`SET → influxdb.0`) — en hetzelfde voor de **bron**, inclusief verdere aliassen daarop. Dat beantwoordt de vraag wat er is achtergebleven bij de overstap naar de alias. Gemeten op het productiesysteem met 24.706 objecten en 66 bestanden: de eerste blik kost 1,3 seconde, elke volgende alias daarna 0,17. De webinterfaces van de adapters worden niet doorzocht — 160 van de 177 MB tekst in de bestandsboom, op elke ioBroker identiek, en ze bevatten voorbeelden als `alias.0.Floor.Room.MotionSensor`; zonder die grens zou de werkbank haar eigen bronbestanden vinden als gebruikers van zichzelf. Bewust zonder oordeel: een bron die nog genoemd wordt is geen fout — een script dat haar voedt hoort daar precies thuis (van 376 aliassen met bron hadden er 61 de bron nog rechtstreeks genoemd, een goed deel daarvan terecht). **En het verwijderscherm doorzoekt nu ook de scripts** — dat bestond alleen bij het verplaatsen, terwijl juist verwijderen onomkeerbaar is\n* De veldkeuze op een JSON-punt kan nu met elke sleutel overweg. Tot nu plakte de werkbank de veldnaam met punten aan de toegang — wat alleen werkt zolang elk deel een geldige JavaScript-naam is. `gpu_usages.amd-vaapi.gpu` werd een rekenkundige uitdrukking (`?.amd - vaapi?.gpu`), `service.storage./dev/shm.free` en `cpu_usages.1111740.mem` een syntaxisfout. Gemeten aan een Frigate-telegram: van de 233 aangeboden velden waren er **27** bruikbaar, de andere 206 eindigden in de rode melding «formule kapot». `feldFormel` gebruikt nu haken waar de sleutel geen naam is — `JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null` — en leest ze weer terug, zodat de keuze op het gekozen veld blijft in plaats van terug te vallen op «eigen formule». Voor gewone namen verandert er **geen enkel teken**, de meegeleverde sjablonen blijven dus onaangeroerd. Een punt binnen de sleutel zelf (`frigate.full_system`) blijft onoplosbaar en toont nog steeds «eigen formule»",
12
+ "fr": "* Après l’enregistrement, le clic suivant dans l’arbre demandait **« modifications non enregistrées »** — à propos d’un alias qui venait d’être écrit. La marque « il y a ici quelque chose de non écrit » n’était jamais que posée, jamais effacée ; elle ne disparaissait que lorsque le brouillon lui-même disparaissait, c’est-à-dire à la suppression et au déplacement. Elle tombe désormais après chaque écriture réussie — et seulement alors : si quelque chose a échoué, la modification n’est réellement pas encore en place, et la question reste justifiée. **Il y a un second effet qui manquait depuis longtemps** : tant que la marque était posée, l’établi ne reconstruisait délibérément pas le brouillon. Après une écriture, l’ancien restait donc en place au lieu de se reconstruire à partir de l’alias fraîchement écrit.\n* Un second appui sur **« Proposer les places libres »** ramenait en arrière une ligne que vous aviez réglée vous-même. Sur le climatiseur : faire deviner neuf places, mettre à la main le rôle de la ligne SPEED sur `level.speed`, rejeter — et la proposition suivante remettait le `level.mode.fan` deviné. La place du modèle paraissait libre, donc la même ligne était devinée une seconde fois ; elle portait alors **les deux** marques, « modifiée » et « supposée », qui s’excluent l’une l’autre — ce qui vient d’être deviné ne peut pas avoir été modifié auparavant. La proposition laisse désormais tranquille toute ligne marquée « modifiée ». La place reste libre, et le message en dessous dit pourquoi. Poser une seconde ligne à côté était l’autre possibilité — le même point source occuperait alors deux places, et la huitième vérification le signalerait à juste titre.\n* Dès que des suppositions étaient en attente, le bouton de la barre des modèles se renommait en **« Rejeter les propositions »** — et un second, avec le même mot et le même effet, se trouvait dans la barre bleue en dessous. Deux boutons, une seule poignée. La barre indique désormais toujours « Proposer les places libres », et seulement tant qu’il reste quelque chose à deviner ; une fois tout deviné, il disparaît. Le rejet se fait là où il a sa place : dans la barre bleue, à côté de « tout garder ».\n* Au lieu de « soit toutes les places sont occupées, soit aucun point de données restant ne convient », le message nomme désormais le cas qui se présente réellement — avec les **noms** des places qui restent libres : « Restent libres SPEED, SWING … Chaque point de données restant sert déjà de source de lecture ou d’écriture dans une ligne occupée », ou « … Aucun point de données restant ne convient ». Si une décision prise à la main tient une place ouverte, une phrase s’ajoute : « 1 lignes ont été décidées à la main et restent intactes. » Le cas « toutes les places occupées » se tait sans qu’on le demande — il dit « rien à faire », et figurerait sinon sur presque chaque appareil.\n* Le climatiseur de Ricardo est reconnu comme **thermostat** et occupe 3 places sur 24. **airCondition** échoue parce que sa seule place obligatoire, MODE, ne porte pas le rôle — et l’affaire est close, puisque « ne convient pas » a le dernier mot. Avec la proposition automatique, il atteindrait **9 sur 29** contre 8 sur 24. Cela figure désormais à côté du champ du modèle : « · airCondition conviendrait peut-être mieux » — une seule ligne, les deux nombres dans l’infobulle. **Un** seul modèle est nommé — le meilleur — et seulement lorsqu’il est réellement meilleur ; la mesure porte sur les places occupées, non sur la proportion. À côté se trouve un petit bouton **→** qui fait les deux d’un seul geste : basculer sur ce modèle et appuyer aussitôt sur « Proposer les places libres » — sinon l’indication serait une annonce sans action. Dans la liste des modèles, chaque ligne concernée porte « avec proposition : convient » derrière son motif d’échec. Le calcul a lieu une fois au choix de l’appareil, puis seulement lors d’une modification de ligne — la proposition lit les noms, les listes de valeurs, les unités et les types, pas les valeurs mesurées.\n* Dans la **feuille de modèle** et dans la boîte de dialogue « enregistrer comme modèle », le type d’appareil affichait sa **clé de modèle** au lieu de son nom : un volet indiquait « blinds », un lecteur multimédia « mediaPlayer », un curseur « levelSlider » — des mots qui n’apparaissent nulle part ailleurs dans l’interface. La valeur enregistrée était juste depuis le début (le type, depuis le 11.09.2026) ; seule l’étiquette venait du mauvais champ, et comme l’Admin ne connaît pas ces trois clés, le nom traduit disparaissait avec elles. Il y est écrit désormais la même chose que dans le choix de modèle à côté : « Volets · blind ».\n* Un **bouton** peut désormais être créé. `STOP` sur un volet ne fait qu’écrire — une pression de touche n’a pas d’état à lire — et cela mettait autrefois en échec l’alias **entier** : l’essai à blanc disait « STOP : aucune source choisie », « créer maintenant » restait grisé, et aucun alias de volet n’a jamais reçu de STOP. Le premier diagnostic était faux, et cela mérite d’être dit : ce n’était pas la vérification d’écriture qui était trop stricte. **ioBroker refuse un alias sans source de lecture** — `{ id: { write: … } }` donne « Alias id is invalid: The id is empty! ». La forme correcte est celle que Ricardo utilise depuis longtemps sur ses dix STOP construits à la main : `alias.id` comme simple texte pointant vers le point de commande, plus `common.read: false` sur le point d’alias. Cela dit à vis, Alexa et matter de dessiner un **bouton** plutôt qu’un interrupteur bloqué à jamais sur « arrêt ». Ce qui décide, c’est la **cible**, pas le rôle : `read: false` est écrit par l’adaptateur lui-même (mesuré sur un vrai STOP `hm-rpc`). Si la cible est lisible, le blocage demeure — alors la source de lecture manquante est bien un défaut. Le bouton survit aussi à la relecture : les trois endroits qui reconstruisent un alias le connaissent désormais, sinon `read` basculerait discrètement sur `true` à la mise à jour suivante. **La même question a donné naissance à une nouvelle vérification** : « la cible sait faire ce qu’on lui demande ». L’établi écrit sur des points étrangers et lit depuis des points étrangers sans jamais vérifier s’ils en sont capables. Trois manières de s’effondrer en silence — la formule d’écriture produit du texte et la cible n’en accepte pas ; la cible porte `write: false` (ioBroker enregistre quand même la valeur mais l’adaptateur ne transmet rien : un coup dans l’eau silencieux) ; la source de lecture porte `read: false` et ne rapporte jamais rien. Toutes trois apparaissent désormais dans l’encadré des vérifications et comme étiquette sur l’identifiant dans la vue détaillée, exactement là où la formule se saisit\n* L’établi crée lui-même les **points d’envoi** MQTT — un point `cmnd` n’existe dans ioBroker qu’une fois que quelque chose a été publié sur son sujet ; avant cela, l’alias n’aurait nulle part où écrire. Il prenait le type du savoir sur les commandes, et `POWER` y est indiqué comme `boolean` — juste à côté de la formule d’écriture `val ? \"ON\" : \"OFF\"`. Les deux ne concordent pas : le js-controller reconvertit à l’écriture le résultat de la formule vers le type de la **cible**, le « ON » redevient `true`, et la formule reste dans l’alias sans effet. La commutation fonctionne malgré tout — Tasmota accepte `on` comme `true` — mais le point ne ressemblait à aucun point créé par mqtt-client, et la formule prétendait faire ce qu’elle ne faisait pas. Sur le système de production, c’était **l’un des 196** points d’alias avec une cible d’écriture MQTT, et il venait de nous. La règle est désormais : **là où il y a une formule d’écriture, le point est créé en `mixed`** — non pas une exception pour `POWER` mais une règle qui couvre aussi `Fade` et `LedTable`. Sans formule, le type exact est conservé, car l’admin déduit min, max et unité de `number`. **Plus deux endroits où cela devient visible** : le type du point cible s’affiche désormais comme étiquette derrière son identifiant dans la vue détaillée — exactement là où la formule se saisit — en couleur d’avertissement lorsque les deux ne concordent pas. Et l’encadré des vérifications compte une huitième vérification, « la formule d’écriture agit », qui le nomme au lieu de se taire\n* Un modèle n’est désormais considéré comme adapté que là où ses **lignes obligatoires** trouvent réellement leur source. Jusqu’ici, seule la reconnaissance décidait, et la reconnaissance pose une autre question que l’application : `pruefeVorlage` vérifie si les **points** nommés existent, les lignes ont besoin de **champs précis à l’intérieur**. Un modèle de compteur électrique fait maison, dont la ligne obligatoire lit `tele.SENSOR · SML.Total_Summe`, l’emportait ainsi sur **17** Tasmota ordinaires et n’y livrait qu’une seule ligne — décochée de surcroît — là où le modèle de prise en aurait construit onze. L’appareil indiquait « identifié comme : compteur Tasmota », et le brouillon était vide. Désormais il ne prend même pas le départ à cet endroit et le suivant obtient la place ; ce qui a été écarté figure dans le « pourquoi ». Les lignes facultatives ne comptent pas, c’est bien pourquoi elles sont facultatives — mesuré sur le parc, **aucun** des quinze autres modèles ne perd une seule de ses 51 victoires. **Et l’essai dans la feuille de modèle** : il récupère désormais aussi les valeurs des points dont les lignes lisent. Sans elles, il jugeait des champs qu’il ne pouvait pas voir, et le même modèle annonçait des chiffres différents selon ce qui avait été cliqué auparavant. Il montre désormais par appareil combien de lignes sortiraient réellement, et en cas de « ne convient pas » **quelle ligne obligatoire manque** — transformant « 22 appareils touchés, 17 gagnés » en l’honnête « 22 touchés, 1 gagné · 21× ne convient pas ». **Et l’essai calcule maintenant comme la création** : au début il ne comparait qu’au seul autre modèle le mieux noté — si celui-ci n’allait pas à l’appareil, le modèle examiné se déclarait vainqueur. « Point de mesure simple » annonçait ainsi une victoire sur un Tasmota, bien que le modèle de prise s’intercale et convienne réellement là. Il parcourt désormais la liste des correspondances comme `vorschlag` ; à la mesure suivante, les 150 paires modèle/appareil concordent\n* Un alias dont la source a disparu du système se remarque désormais sans qu’on clique dessus. Jusqu’ici, cela n’était dit que dans le détail déplié et dans l’encadré des vérifications — la ligne de la liste se taisait, parce qu’elle demandait si une source était **renseignée**, non si elle **existe**. La ligne porte désormais le `!` rouge avec la mention « la source n’existe pas », l’en-tête une étiquette « 1 point pointe dans le vide » avec la liste dans son infobulle, et l’arbre des alias un `!` rouge sur le canal concerné. Ce n’est pas cosmétique : le js-controller retient « source manquante » de façon durable et ne le corrige jamais — seul supprimer et recréer aide. Le calcul a lieu une fois au chargement des objets, pas à chaque tracé ; sur le système de production, 531 points d’alias en 5,2 ms. Deux ont été trouvés aussitôt : un contact de fenêtre pointant encore vers l’adaptateur `zigbee` remplacé depuis longtemps, et un point NSPanel avec une source `0_userdata` manquante pour la lecture comme pour l’écriture. Une ligne **sans aucune** source conserve sa propre mention — elle est inachevée, pas cassée\n* Nouveau : **« Mentionné dans »** sur un alias existant. L’encadré sous la comparaison des modifications cherche au clic tout ce qui mentionne encore l’identifiant — les **scripts** de l’adaptateur javascript avec dossier, nom, état et numéros de ligne, les **fichiers** des dossiers d’instance (c’est-à-dire les vues vis et vis-2), chaque **objet** chargé (là où les ponts matter gardent leurs membres, par exemple), les **énumérations** et les entrées sur le point lui-même (`SET → influxdb.0`) — et la même chose pour la **source**, y compris d’autres alias dessus. Cela répond à la question de ce qui est resté derrière lors du passage à l’alias. Mesuré sur le système de production avec 24 706 objets et 66 fichiers : le premier coup d’œil prend 1,3 seconde, chaque alias suivant 0,17. Les interfaces web des adaptateurs ne sont pas fouillées — 160 des 177 Mo de texte de l’arborescence, identiques sur chaque ioBroker, et elles contiennent des exemples comme `alias.0.Floor.Room.MotionSensor` ; sans cette limite, l’établi trouverait ses propres sources comme utilisatrices de lui-même. Délibérément sans verdict : une source encore mentionnée n’est pas une faute — un script qui l’alimente est exactement à sa place (sur 376 alias avec source, 61 avaient encore la source mentionnée directement, une bonne part à juste titre). **Et la boîte de dialogue de suppression fouille désormais aussi les scripts** — cela n’existait qu’au déplacement, alors que c’est la suppression qui est irréversible\n* Le sélecteur de champ sur un point JSON s’accommode désormais de chaque clé. Jusqu’ici, l’établi collait le nom du champ à l’accès avec des points — ce qui ne fonctionne que tant que chaque partie est un nom JavaScript valide. `gpu_usages.amd-vaapi.gpu` devenait une expression arithmétique (`?.amd - vaapi?.gpu`), `service.storage./dev/shm.free` et `cpu_usages.1111740.mem` une erreur de syntaxe. Mesuré sur un télégramme Frigate : sur 233 champs proposés, **27** étaient utilisables, les 206 autres finissaient sur le message rouge « formule cassée ». `feldFormel` utilise désormais des crochets là où la clé n’est pas un nom — `JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null` — et les relit, de sorte que le sélecteur reste sur le champ choisi au lieu de retomber sur « formule propre ». Pour les noms ordinaires, **pas un seul caractère** ne change, les modèles livrés restent donc intacts. Un point à l’intérieur de la clé elle-même (`frigate.full_system`) demeure insoluble et affiche toujours « formule propre »",
13
+ "it": "* Dopo il salvataggio il clic successivo nell’albero chiedeva **«modifiche non salvate»** — a proposito di un alias appena scritto. Il segno «qui c’è qualcosa di non scritto» veniva soltanto impostato e mai cancellato; spariva solo quando spariva la bozza stessa, cioè con l’eliminazione e con lo spostamento. Ora cade dopo ogni scrittura riuscita — e soltanto allora: se qualcosa è andato storto la modifica davvero non è ancora dentro, e la domanda resta giustificata. **C’è un secondo effetto che mancava da tempo**: finché il segno restava, il banco di lavoro deliberatamente non ricostruiva la bozza. Dopo una scrittura restava quindi quella vecchia, invece di ricostruirsi sull’alias appena scritto.\n* Una seconda pressione su **«Proponi posti liberi»** riportava indietro una riga che avevi impostato tu. Sul climatizzatore: far indovinare nove posti, impostare a mano il ruolo della riga SPEED su `level.speed`, scartare — e la proposta successiva rimetteva l’indovinato `level.mode.fan`. Il posto del modello sembrava libero, quindi la stessa riga veniva indovinata una seconda volta; portava allora **entrambi** i segni, «modificata» e «presunta», che si escludono a vicenda — ciò che è appena stato indovinato non può essere stato modificato prima. Ora l’indovinare lascia stare ogni riga contrassegnata «modificata». Il posto resta libero, e il messaggio sotto dice perché. Mettere accanto una seconda riga era l’alternativa — lo stesso punto sorgente occuperebbe allora due posti, e l’ottava verifica lo segnalerebbe a ragione.\n* Non appena c’erano supposizioni in sospeso, il pulsante nella barra dei modelli si rinominava in **«Scarta proposte»** — e un secondo con la stessa parola e lo stesso effetto stava nella barra blu sotto. Due pulsanti, una sola maniglia. Nella barra ora c’è sempre «Proponi posti liberi», e solo finché resta qualcosa da indovinare; una volta indovinato tutto, sparisce. Si scarta dove è il suo posto: nella barra blu, accanto a «tieni tutto».\n* Invece di «o tutti i posti sono occupati, oppure nessun punto dati rimanente è adatto», il messaggio nomina ora il caso che si presenta davvero — con i **nomi** dei posti che restano liberi: «Restano liberi SPEED, SWING … Ogni punto dati rimanente serve già da sorgente di lettura o scrittura in una riga occupata», oppure «… Nessun punto dati rimanente è adatto». Se una decisione presa a mano tiene aperto un posto, si aggiunge una frase: «1 righe sono state decise a mano e restano intatte.» Il caso «tutti i posti occupati» tace se non richiesto — dice «niente da fare», e altrimenti comparirebbe su quasi ogni dispositivo.\n* Il climatizzatore di Ricardo viene riconosciuto come **termostato** e occupa 3 posti su 24. **airCondition** non passa perché il suo unico posto obbligatorio, MODE, non porta il ruolo — e con ciò la faccenda è chiusa, dato che «non adatto» ha l’ultima parola. Con la proposta automatica arriverebbe a **9 su 29** contro 8 su 24. Ora questo compare accanto al campo del modello: «· airCondition forse andrebbe meglio» — una sola riga, entrambi i numeri nel suggerimento. Viene nominato **un** solo modello — il migliore — e soltanto quando è davvero migliore; si misura in posti occupati, non in proporzione. Accanto c’è un piccolo pulsante **→** che fa entrambe le cose in un gesto: passa a quel modello e preme subito «Proponi posti liberi» — altrimenti l’indicazione sarebbe un annuncio senza azione. Nell’elenco dei modelli ogni riga interessata porta «con proposta: adatto» dietro il motivo del rifiuto. Il calcolo avviene una volta alla scelta del dispositivo e poi solo a una modifica di riga — la proposta legge nomi, elenchi di valori, unità e tipi, non valori misurati.\n* Nel **foglio del modello** e nella finestra «salva come modello» il tipo di dispositivo mostrava la sua **chiave di modello** invece del nome: su una tapparella si leggeva «blinds», su un lettore multimediale «mediaPlayer», su un cursore «levelSlider» — parole che non compaiono da nessun’altra parte nell’interfaccia. Il valore salvato era giusto da sempre (il tipo, dall’11.09.2026); solo l’etichetta veniva dal campo sbagliato, e poiché l’Admin non conosce quelle tre chiavi, con esse spariva anche il nome tradotto. Ora vi si legge la stessa cosa della scelta del modello accanto: «Tapparelle · blind».\n* Ora si può creare un **pulsante**. `STOP` su una tapparella scrive soltanto — la pressione di un tasto non ha uno stato da leggere — e questo faceva finora fallire l’alias **intero**: la prova a vuoto diceva «STOP: nessuna sorgente scelta», «crea ora» restava grigio, e nessun alias di tapparella ha mai ricevuto uno STOP. La prima diagnosi era sbagliata, e va detto: non era la verifica di scrittura a essere troppo severa. **ioBroker rifiuta un alias senza sorgente di lettura** — `{ id: { write: … } }` dà «Alias id is invalid: The id is empty!». La forma corretta è quella che Ricardo usa da tempo sui suoi dieci STOP costruiti a mano: `alias.id` come semplice testo che punta al punto di comando, più `common.read: false` sul punto alias. Questo dice a vis, Alexa e matter di disegnare un **pulsante** invece di un interruttore bloccato per sempre su «spento». A decidere è il **bersaglio**, non il ruolo: `read: false` lo scrive l’adattatore stesso (misurato su un vero STOP `hm-rpc`). Se il bersaglio è leggibile il blocco resta — allora la sorgente di lettura mancante è davvero un difetto. Il pulsante sopravvive anche alla rilettura: tutti e tre i punti che ricostruiscono un alias ora lo conoscono, altrimenti `read` tornerebbe silenziosamente a `true` al prossimo aggiornamento. **Dalla stessa domanda è nata una nuova verifica**: «il bersaglio sa fare ciò che gli si chiede». Il banco di lavoro scrive su punti altrui e legge da punti altrui senza mai verificare se ne siano capaci. Tre modi di sgretolarsi in silenzio — la formula di scrittura produce testo e il bersaglio non ne accetta; il bersaglio porta `write: false` (ioBroker deposita comunque il valore ma l’adattatore non passa nulla oltre: un colpo a vuoto silenzioso); la sorgente di lettura porta `read: false` e non riferisce mai nulla. Tutti e tre compaiono ora nel riquadro delle verifiche e come etichetta sull’identificativo nella vista di dettaglio, proprio dove si digita la formula\n* Il banco di lavoro crea da sé i **punti di invio** MQTT — un punto `cmnd` nasce in ioBroker solo dopo che qualcosa è stato pubblicato sul suo argomento; prima l’alias non avrebbe dove scrivere. Prendeva il tipo dalla conoscenza dei comandi, e `POWER` vi è indicato come `boolean` — proprio accanto alla formula di scrittura `val ? \"ON\" : \"OFF\"`. Le due cose non tornano: in scrittura il js-controller riconverte il risultato della formula al tipo del **bersaglio**, «ON» torna `true`, e la formula resta nell’alias senza effetto. La commutazione funziona lo stesso — Tasmota accetta sia `on` sia `true` — ma il punto appariva diverso da ogni punto creato da mqtt-client, e la formula affermava qualcosa che non faceva. Sul sistema di produzione era **uno dei 196** punti alias con un bersaglio di scrittura MQTT, e veniva da noi. La regola ora è: **dove esiste una formula di scrittura, il punto viene creato come `mixed`** — non un’eccezione per `POWER` ma una regola che copre anche `Fade` e `LedTable`. Senza formula resta il tipo esatto, perché l’admin ricava min, max e unità da `number`. **In più due punti in cui diventa visibile**: il tipo del punto bersaglio compare ora come etichetta dietro il suo identificativo nella vista di dettaglio — proprio dove si digita la formula — in colore di avviso quando le due cose non coincidono. E il riquadro delle verifiche ha un’ottava verifica, «la formula di scrittura ha effetto», che lo dice invece di tacere\n* Un modello vale come adatto soltanto là dove le sue **righe obbligatorie** trovano davvero la loro sorgente. Finora decideva il solo riconoscimento, e il riconoscimento pone una domanda diversa dall’applicazione: `pruefeVorlage` verifica se i **punti** nominati esistono, le righe hanno bisogno di determinati **campi al loro interno**. Un modello di contatore elettrico fatto in casa, la cui riga obbligatoria legge `tele.SENSOR · SML.Total_Summe`, vinceva così su **17** normali Tasmota e vi forniva esattamente una riga — per giunta deselezionata — là dove il modello della presa ne avrebbe costruite undici. Sul dispositivo c’era scritto «identificato come: contatore Tasmota», e la bozza era vuota. Ora là non si presenta neppure alla partenza e il posto va al migliore successivo; ciò che è stato scavalcato sta nel «perché». Le righe facoltative non contano, è proprio per questo che sono facoltative — misurato sul parco esistente, **nessuno** dei quindici modelli restanti perde una sola delle sue 51 vittorie. **E la prova nel foglio del modello**: ora recupera anche i valori dei punti da cui le righe leggono. Senza di essi giudicava campi che non poteva vedere, e lo stesso modello riferiva numeri diversi a seconda di ciò che era stato cliccato prima. Ora mostra per ogni dispositivo quante righe verrebbero fuori davvero, e in caso di «non adatto» **quale riga obbligatoria manca** — così «22 dispositivi colpiti, 17 vinti» è diventato l’onesto «22 colpiti, 1 vinto · 21× non adatto». **E la prova calcola come fa la creazione**: all’inizio confrontava solo con l’unico altro modello col punteggio più alto — se quello non andava bene al dispositivo, il modello in esame si dichiarava vincitore. Così «punto di misura puro» annunciava una vittoria su un Tasmota, benché in mezzo ci sia il modello della presa che lì davvero si adatta. Ora percorre l’elenco dei riscontri come fa `vorschlag`; rimisurate, tutte le 150 coppie modello/dispositivo coincidono\n* Un alias la cui sorgente è sparita dal sistema si nota ora senza doverci cliccare sopra. Finora lo si diceva solo nel dettaglio aperto e nel riquadro delle verifiche — la riga nell’elenco taceva, perché chiedeva se una sorgente fosse **inserita**, non se **esista**. La riga porta ora il `!` rosso con la nota «la sorgente non esiste», l’intestazione un’etichetta «1 punto punta nel vuoto» con l’elenco nel suggerimento, e l’albero degli alias un `!` rosso sul canale interessato. Non è un difetto estetico: il js-controller ricorda «sorgente mancante» in modo duraturo e non lo corregge mai — aiuta solo cancellare e ricreare. Il calcolo avviene una volta al caricamento degli oggetti, non a ogni disegno; sul sistema di produzione 531 punti alias in 5,2 ms. Se ne sono trovati subito due: un contatto finestra che puntava ancora all’adattatore `zigbee` sostituito da tempo, e un punto NSPanel con sorgente `0_userdata` mancante sia per la lettura sia per la scrittura. Una riga **del tutto** senza sorgente conserva la sua nota propria — è incompiuta, non rotta\n* Novità: **«Citato in»** sull’alias esistente. Il riquadro sotto il confronto delle modifiche cerca al clic tutto ciò che cita ancora l’identificativo — gli **script** dell’adattatore javascript con cartella, nome, stato e numeri di riga, i **file** delle cartelle di istanza (cioè le viste vis e vis-2), ogni **oggetto** caricato (ad esempio dove i ponti matter tengono i loro membri), le **enumerazioni** e le voci sul punto stesso (`SET → influxdb.0`) — e lo stesso per la **sorgente**, inclusi altri alias su di essa. Questo risponde alla domanda su cosa sia rimasto indietro nel passaggio all’alias. Misurato sul sistema di produzione con 24.706 oggetti e 66 file: il primo sguardo richiede 1,3 secondi, ogni alias successivo 0,17. Le interfacce web degli adattatori non vengono frugate — 160 dei 177 MB di testo nell’albero dei file, identiche su ogni ioBroker, e contengono esempi come `alias.0.Floor.Room.MotionSensor`; senza quel confine il banco di lavoro troverebbe i propri sorgenti come utilizzatori di se stesso. Deliberatamente senza verdetto: una sorgente ancora citata non è un errore — uno script che la alimenta sta esattamente dove deve (su 376 alias con sorgente, 61 avevano ancora la sorgente citata direttamente, buona parte a ragione). **E ora anche la finestra di eliminazione cerca negli script** — esisteva solo per lo spostamento, benché sia l’eliminazione a essere irreversibile\n* La scelta del campo su un punto JSON se la cava ora con qualsiasi chiave. Finora il banco di lavoro incollava il nome del campo all’accesso con i punti — cosa che funziona solo finché ogni parte è un nome JavaScript valido. `gpu_usages.amd-vaapi.gpu` diventava un’espressione aritmetica (`?.amd - vaapi?.gpu`), `service.storage./dev/shm.free` e `cpu_usages.1111740.mem` un errore di sintassi. Misurato su un telegramma Frigate: dei 233 campi offerti **27** erano utilizzabili, gli altri 206 finivano nel messaggio rosso «formula rotta». `feldFormel` usa ora le parentesi quadre dove la chiave non è un nome — `JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null` — e le rilegge, così la scelta resta sul campo selezionato invece di ripiegare su «formula propria». Per i nomi ordinari non cambia **un solo carattere**, quindi i modelli forniti restano intatti. Un punto dentro la chiave stessa (`frigate.full_system`) resta irrisolvibile e mostra ancora «formula propria»",
14
+ "es": "* Tras guardar, el siguiente clic en el árbol preguntaba **«cambios sin guardar»** — sobre un alias que acababa de escribirse. La marca «aquí hay algo sin escribir» solo se ponía y nunca se quitaba; desaparecía únicamente cuando desaparecía el propio borrador, es decir al borrar y al mover. Ahora cae tras cada escritura lograda — y solo entonces: si algo falló, el cambio realmente aún no está dentro, y la pregunta sigue siendo justificada. **Hay un segundo efecto que faltaba desde hace mucho**: mientras la marca estaba puesta, el banco de trabajo no reconstruía el borrador a propósito. Tras una escritura quedaba por tanto el antiguo, en lugar de reconstruirse a partir del alias recién escrito.\n* Una segunda pulsación de **«Proponer plazas libres»** devolvía una fila que habías fijado tú mismo. En el aire acondicionado: hacer adivinar nueve plazas, poner a mano el rol de la fila SPEED en `level.speed`, descartar — y la siguiente propuesta volvía a poner el adivinado `level.mode.fan`. La plaza del patrón parecía libre, así que la misma fila se adivinaba por segunda vez; llevaba entonces **ambas** marcas, «modificada» y «supuesta», que se excluyen entre sí — lo que acaba de adivinarse no puede haberse modificado antes. Ahora la adivinación deja en paz toda fila marcada como «modificada». La plaza queda libre, y el mensaje de debajo dice por qué. Poner una segunda fila al lado era la alternativa — el mismo punto de origen ocuparía entonces dos plazas, y la octava comprobación lo señalaría con razón.\n* En cuanto había suposiciones pendientes, el botón de la barra de patrones se renombraba a **«Descartar propuestas»** — y un segundo con la misma palabra y el mismo efecto estaba en la barra azul de debajo. Dos botones, un solo mango. En la barra pone ahora siempre «Proponer plazas libres», y solo mientras quede algo por adivinar; una vez adivinado todo, desaparece. Se descarta donde corresponde: en la barra azul, junto a «conservar todo».\n* En lugar de «o todas las plazas están ocupadas, o ningún punto de datos restante encaja», el mensaje nombra ahora el caso que realmente se da — con los **nombres** de las plazas que quedan libres: «Quedan libres SPEED, SWING … Cada punto de datos restante ya sirve de origen de lectura o escritura en una fila ocupada», o «… Ningún punto de datos restante encaja aquí». Si una decisión tomada a mano mantiene una plaza abierta, se añade una frase: «1 filas se decidieron a mano y quedan intactas.» El caso «todas las plazas ocupadas» calla si no se pregunta — dice «nada que hacer», y de otro modo aparecería en casi cada dispositivo.\n* El aire acondicionado de Ricardo se reconoce como **termostato** y ocupa 3 de 24 plazas. **airCondition** no pasa porque su única plaza obligatoria, MODE, no lleva el rol — y con eso el asunto queda cerrado, pues «no encaja» tiene la última palabra. Con la propuesta automática llegaría a **9 de 29** frente a 8 de 24. Eso figura ahora junto al campo del patrón: «· airCondition quizá encajaría mejor» — una sola línea, ambos números en la ayuda emergente. Se nombra **un** solo patrón — el mejor — y solo cuando es realmente mejor; se mide en plazas ocupadas, no en proporción. Al lado hay un pequeño botón **→** que hace ambas cosas de una vez: cambiar a ese patrón y pulsar acto seguido «Proponer plazas libres» — de lo contrario la indicación sería un anuncio sin acción. En la lista de patrones cada fila afectada lleva «con propuesta: encaja» detrás de su motivo de rechazo. Se calcula una vez al elegir el dispositivo y después solo al cambiar una fila — la propuesta lee nombres, listas de valores, unidades y tipos, no valores medidos.\n* En la **hoja de patrón** y en el diálogo «guardar como plantilla», el tipo de dispositivo mostraba su **clave de patrón** en lugar de su nombre: en una persiana se leía «blinds», en un reproductor «mediaPlayer», en un deslizador «levelSlider» — palabras que no aparecen en ningún otro lugar de la interfaz. El valor guardado fue correcto todo el tiempo (el tipo, desde el 11.09.2026); solo la etiqueta venía del campo equivocado, y como el Admin no conoce esas tres claves, con ellas se perdía también el nombre traducido. Ahora pone ahí lo mismo que en la elección de patrón de al lado: «Persianas · blind».\n* Ahora puede crearse un **pulsador**. `STOP` en una persiana solo escribe — una pulsación de tecla no tiene estado que leer — y eso echaba antes por tierra el alias **entero**: la simulación decía «STOP: ningún origen elegido», «crear ahora» quedaba en gris, y ningún alias de persiana recibió nunca un STOP. El primer diagnóstico fue erróneo, y conviene decirlo: no era que la comprobación de escritura fuera demasiado estricta. **ioBroker rechaza un alias sin origen de lectura** — `{ id: { write: … } }` da «Alias id is invalid: The id is empty!». La forma correcta es la que Ricardo usa desde hace tiempo en sus diez STOP hechos a mano: `alias.id` como simple texto apuntando al punto de mando, más `common.read: false` en el punto del alias. Eso le dice a vis, Alexa y matter que dibujen un **pulsador** y no un interruptor atascado para siempre en «apagado». Lo que decide es el **destino**, no el rol: `read: false` lo escribe el propio adaptador (medido en un STOP real de `hm-rpc`). Si el destino es legible, el bloqueo permanece — entonces el origen de lectura que falta sí es un defecto. El pulsador sobrevive también a la relectura: los tres lugares que reconstruyen un alias lo conocen ahora, de lo contrario `read` volvería en silencio a `true` en la siguiente actualización. **De la misma pregunta nació una nueva comprobación**: «el destino sabe hacer lo que se le pide». El banco de trabajo escribe en puntos ajenos y lee de puntos ajenos sin comprobar nunca si pueden hacerlo. Tres formas de desmoronarse en silencio — la fórmula de escritura produce texto y el destino no lo acepta; el destino lleva `write: false` (ioBroker deposita el valor igualmente, pero el adaptador no pasa nada adelante: un tiro al aire silencioso); el origen de lectura lleva `read: false` y no informa nunca de nada. Las tres aparecen ahora en el recuadro de comprobaciones y como etiqueta en el identificador de la vista de detalle, justo donde se escribe la fórmula\n* El banco de trabajo crea por sí mismo los **puntos de envío** MQTT — un punto `cmnd` solo nace en ioBroker cuando se ha publicado algo en su tema; antes el alias no tendría dónde escribir. Tomaba el tipo del conocimiento de comandos, y `POWER` figura allí como `boolean` — justo al lado de la fórmula de escritura `val ? \"ON\" : \"OFF\"`. Ambas cosas no cuadran: al escribir, el js-controller reconvierte el resultado de la fórmula al tipo del **destino**, el «ON» vuelve a ser `true`, y la fórmula queda en el alias sin efecto. La conmutación funciona igualmente — Tasmota acepta tanto `on` como `true` — pero el punto se veía distinto de cualquier punto creado por mqtt-client, y la fórmula afirmaba algo que no hacía. En el sistema productivo era **uno de 196** puntos de alias con destino de escritura MQTT, y venía de nosotros. La regla es ahora: **donde hay una fórmula de escritura, el punto se crea como `mixed`** — no una excepción para `POWER` sino una regla que cubre también `Fade` y `LedTable`. Sin fórmula se conserva el tipo exacto, porque el admin deduce mín., máx. y unidad de `number`. **Además dos lugares donde se hace visible**: el tipo del punto de destino se muestra ahora como etiqueta detrás de su identificador en la vista de detalle — justo donde se escribe la fórmula — en color de aviso cuando ambos no coinciden. Y el recuadro de comprobaciones tiene una octava comprobación, «la fórmula de escritura surte efecto», que lo nombra en vez de callar\n* Una plantilla solo cuenta como adecuada allí donde sus **filas obligatorias** encuentran realmente su origen. Hasta ahora decidía solo el reconocimiento, y el reconocimiento plantea una pregunta distinta a la aplicación: `pruefeVorlage` comprueba si existen los **puntos** nombrados, las filas necesitan determinados **campos dentro de ellos**. Una plantilla casera de contador eléctrico, cuya fila obligatoria lee `tele.SENSOR · SML.Total_Summe`, ganaba así en **17** Tasmota corrientes y entregaba allí exactamente una fila — además desmarcada — donde la plantilla de enchufe habría construido once. En el dispositivo ponía «identificado como: contador Tasmota», y el borrador estaba vacío. Ahora ni siquiera sale a la salida allí y la plaza va a la siguiente mejor; lo que se omitió figura en el «por qué». Las filas opcionales no cuentan, para eso son opcionales — medido sobre el parque existente, **ninguna** de las quince plantillas restantes pierde ni una de sus 51 victorias. **Y la prueba en la hoja de plantilla**: ahora recoge también los valores de los puntos de los que leen las filas. Sin ellos juzgaba campos que no podía ver, y la misma plantilla informaba de cifras distintas según lo que se hubiera pulsado antes. Ahora muestra por dispositivo cuántas filas saldrían realmente, y en caso de «no encaja» **qué fila obligatoria falta** — con lo que «22 dispositivos alcanzados, 17 de ellos ganados» se convirtió en el honesto «22 alcanzados, 1 ganado · 21× no encaja». **Y la prueba calcula como lo hace la creación**: al principio comparaba solo con la única otra plantilla de mayor puntuación — si esa no valía para el dispositivo, la plantilla examinada se declaraba vencedora. Así «punto de medida puro» anunciaba una victoria en un Tasmota, aunque en medio está la plantilla de enchufe, que allí sí encaja. Ahora recorre la lista de coincidencias como lo hace `vorschlag`; al volver a medir, los 150 pares de plantilla y dispositivo concuerdan\n* Un alias cuyo origen ha desaparecido del sistema se nota ahora sin hacer clic en él. Hasta ahora solo se decía en el detalle desplegado y en el recuadro de comprobaciones — la fila de la lista callaba, porque preguntaba si había un origen **introducido**, no si **existe**. La fila lleva ahora el `!` rojo con la nota «el origen no existe», la cabecera una etiqueta «1 punto apunta al vacío» con la lista en su ayuda emergente, y el árbol de alias un `!` rojo en el canal afectado. Esto no es cosmético: el js-controller recuerda «falta el origen» de forma duradera y no lo corrige nunca — solo ayuda borrar y crear de nuevo. Se calcula una vez al cargar los objetos, no en cada dibujado; en el sistema productivo, 531 puntos de alias en 5,2 ms. Se encontraron dos de inmediato: un contacto de ventana que seguía apuntando al adaptador `zigbee` sustituido hace mucho, y un punto NSPanel con origen `0_userdata` ausente tanto para leer como para escribir. Una fila **sin ningún** origen conserva su propia nota — está sin terminar, no rota\n* Nuevo: **«Se menciona en»** en el alias existente. El recuadro bajo la comparación de cambios busca al hacer clic todo lo que aún menciona el identificador — los **scripts** del adaptador javascript con carpeta, nombre, estado y números de línea, los **archivos** de las carpetas de instancia (es decir, las vistas de vis y vis-2), cada **objeto** cargado (allí donde los puentes matter guardan sus miembros, por ejemplo), las **enumeraciones** y las entradas del propio punto (`SET → influxdb.0`) — y lo mismo para el **origen**, incluidos otros alias sobre él. Eso responde a la pregunta de qué quedó atrás al pasar al alias. Medido en el sistema productivo con 24.706 objetos y 66 archivos: la primera mirada tarda 1,3 segundos, cada alias siguiente 0,17. Las interfaces web de los adaptadores no se registran — 160 de los 177 MB de texto del árbol de archivos, idénticas en cada ioBroker, y llevan ejemplos como `alias.0.Floor.Room.MotionSensor`; sin ese límite el banco de trabajo encontraría sus propios fuentes como usuarios de sí mismo. Deliberadamente sin veredicto: un origen todavía mencionado no es un fallo — un script que lo alimenta está exactamente donde debe (de 376 alias con origen, 61 seguían teniendo el origen mencionado directamente, buena parte de ellos con razón). **Y el diálogo de borrado busca ahora también en los scripts** — eso solo existía al mover, aunque lo irreversible es precisamente borrar\n* La elección de campo en un punto JSON se las arregla ahora con cualquier clave. Hasta ahora el banco de trabajo pegaba el nombre del campo al acceso con puntos — lo que solo funciona mientras cada parte sea un nombre de JavaScript válido. `gpu_usages.amd-vaapi.gpu` se convertía en una expresión aritmética (`?.amd - vaapi?.gpu`), `service.storage./dev/shm.free` y `cpu_usages.1111740.mem` en un error de sintaxis. Medido en un telegrama de Frigate: de 233 campos ofrecidos **27** eran utilizables, los otros 206 acababan en el mensaje rojo «fórmula rota». `feldFormel` usa ahora corchetes donde la clave no es un nombre — `JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null` — y los vuelve a leer, de modo que la elección permanece en el campo escogido en lugar de caer en «fórmula propia». Para nombres corrientes no cambia **ni un solo carácter**, así que las plantillas suministradas quedan intactas. Un punto dentro de la propia clave (`frigate.full_system`) sigue siendo irresoluble y muestra todavía «fórmula propia»",
15
+ "pl": "* Po zapisaniu kolejne kliknięcie w drzewie pytało o **„niezapisane zmiany”** — w sprawie aliasu, który właśnie został zapisany. Znacznik „jest tu coś niezapisanego” był w całym programie tylko ustawiany i nigdy nie kasowany; znikał wyłącznie wtedy, gdy znikał sam szkic, czyli przy usuwaniu i przy przenoszeniu. Teraz opada po każdym udanym zapisie — i tylko wtedy: jeśli coś się nie powiodło, zmiany naprawdę jeszcze nie ma w środku, a pytanie pozostaje uzasadnione. **Jest i drugi skutek, którego długo brakowało**: dopóki znacznik stał, warsztat celowo nie przebudowywał szkicu. Po zapisie zostawał więc stary, zamiast zbudować się na nowo na świeżo zapisanym aliasie.\n* Drugie naciśnięcie **„Zaproponuj wolne miejsca”** cofało wiersz, który sam ustawiłeś. Na klimatyzatorze: kazać odgadnąć dziewięć miejsc, ręcznie ustawić rolę wiersza SPEED na `level.speed`, odrzucić — a następna propozycja znowu wstawiała odgadnięte `level.mode.fan`. Miejsce wzorca wyglądało na wolne, więc ten sam wiersz był odgadywany po raz drugi; niósł wtedy **oba** znaczniki, „zmieniony” i „przypuszczalny”, które się wykluczają — to, co dopiero odgadnięto, nie mogło być wcześniej zmienione. Teraz odgadywanie zostawia w spokoju każdy wiersz ze znacznikiem „zmieniony”. Miejsce pozostaje wolne, a komunikat poniżej mówi dlaczego. Położenie obok drugiego wiersza było alternatywą — ten sam punkt źródłowy zajmowałby wtedy dwa miejsca, a ósme sprawdzenie słusznie by to zgłosiło.\n* Gdy tylko pojawiały się nierozstrzygnięte przypuszczenia, przycisk na pasku wzorców zmieniał nazwę na **„Odrzuć propozycje”** — a drugi z tym samym słowem i tym samym skutkiem stał na niebieskim pasku poniżej. Dwa przyciski, jedna klamka. Na pasku zawsze widnieje teraz „Zaproponuj wolne miejsca”, i tylko dopóki zostało coś do odgadnięcia; gdy wszystko jest odgadnięte, przycisk znika. Odrzuca się tam, gdzie to miejsce: na niebieskim pasku, obok „zachowaj wszystkie”.\n* Zamiast „albo wszystkie miejsca są zajęte, albo żaden pozostały punkt danych nie pasuje” komunikat nazywa teraz przypadek, który naprawdę zachodzi — z **nazwami** miejsc, które pozostają wolne: „Wolne pozostają SPEED, SWING … Każdy pozostały punkt danych służy już jako źródło odczytu lub zapisu w zajętym wierszu”, albo „… Żaden pozostały punkt danych tu nie pasuje”. Jeśli decyzja podjęta ręcznie trzyma miejsce otwarte, dochodzi zdanie: „1 wierszy rozstrzygnięto ręcznie i pozostają nietknięte.” Przypadek „wszystkie miejsca zajęte” milczy bez pytania — mówi „nic do zrobienia”, a inaczej stałby przy niemal każdym urządzeniu.\n* Klimatyzator Ricarda rozpoznawany jest jako **termostat** i zajmuje 3 z 24 miejsc. **airCondition** odpada, bo jego jedyne obowiązkowe miejsce MODE nie niesie roli — i na tym koniec, skoro „nie pasuje” ma ostatnie słowo. Z automatyczną propozycją doszedłby do **9 z 29** wobec 8 z 24. Teraz stoi to obok pola wzorca: „· airCondition może pasowałby lepiej” — jeden wiersz, obie liczby w podpowiedzi. Nazywany jest **jeden** wzorzec — najlepszy — i tylko wtedy, gdy jest naprawdę lepszy; mierzy się zajętymi miejscami, nie proporcją. Obok siedzi mały przycisk **→**, który robi oba kroki naraz: przełącza na ten wzorzec i od razu naciska „Zaproponuj wolne miejsca” — inaczej wskazówka byłaby zapowiedzią bez działania. Na liście wzorców każdy dotknięty wiersz niesie „z propozycją: pasuje” za powodem odmowy. Liczone jest raz przy wyborze urządzenia, a potem tylko przy zmianie wiersza — propozycja czyta nazwy, listy wartości, jednostki i typy, a nie wartości mierzone.\n* W **arkuszu wzorca** i w oknie „zapisz jako szablon” typ urządzenia pokazywał swój **klucz wzorca** zamiast nazwy: przy roletach czytało się „blinds”, przy odtwarzaczu „mediaPlayer”, przy suwaku „levelSlider” — słowa, które nigdzie indziej w interfejsie nie występują. Zapisana wartość była przez cały czas poprawna (typ, od 11.09.2026); tylko etykieta brała się z niewłaściwego pola, a ponieważ Admin nie zna tych trzech kluczy, razem z nimi znikała też przetłumaczona nazwa. Teraz stoi tam to samo co w wyborze wzorca obok: „Rolety · blind”.\n* Można teraz utworzyć **przycisk chwilowy**. `STOP` przy rolecie tylko zapisuje — naciśnięcie klawisza nie ma stanu do odczytu — i to dawniej wywracało **cały** alias: próba na sucho mówiła „STOP: nie wybrano źródła”, „utwórz teraz” pozostawało szare, i żaden alias rolety nigdy nie dostał STOP. Pierwsza diagnoza była błędna, i warto to powiedzieć: nie chodziło o zbyt surowe sprawdzenie zapisu. **ioBroker odrzuca alias bez źródła odczytu** — `{ id: { write: … } }` daje „Alias id is invalid: The id is empty!”. Właściwa postać to ta, której Ricardo od dawna używa na swoich dziesięciu ręcznie zbudowanych STOP: `alias.id` jako zwykły tekst wskazujący punkt poleceń, plus `common.read: false` na punkcie aliasu. To mówi vis, Alexie i matter, żeby narysowały **przycisk chwilowy**, a nie przełącznik na zawsze zablokowany w pozycji „wył.”. Decyduje **cel**, nie rola: `read: false` zapisuje sam adapter (zmierzone na prawdziwym STOP w `hm-rpc`). Jeśli cel jest czytelny, blokada zostaje — wtedy brakujące źródło odczytu jest rzeczywiście wadą. Przycisk przeżywa też ponowne wczytanie: wszystkie trzy miejsca, które odtwarzają alias, teraz o nim wiedzą, inaczej `read` po cichu przeskoczyłby na `true` przy następnej aktualizacji. **Z tego samego pytania wyrosło nowe sprawdzenie**: „cel potrafi to, czego się od niego wymaga”. Warsztat pisze do obcych punktów i czyta z obcych punktów, ani razu nie sprawdzając, czy one to potrafią. Trzy sposoby na ciche rozsypanie się — formuła zapisu wydaje tekst, a cel tekstu nie przyjmuje; cel niesie `write: false` (ioBroker i tak odkłada wartość, ale adapter nic dalej nie przekazuje: cichy strzał w próżnię); źródło odczytu niesie `read: false` i nigdy niczego nie zgłasza. Wszystkie trzy pojawiają się teraz w ramce sprawdzeń i jako plakietka przy identyfikatorze w widoku szczegółów, dokładnie tam, gdzie wpisuje się formułę\n* Warsztat sam tworzy **punkty wysyłkowe** MQTT — punkt `cmnd` powstaje w ioBrokerze dopiero wtedy, gdy coś zostało opublikowane na jego temacie; wcześniej alias nie miałby dokąd pisać. Typ brał z wiedzy o poleceniach, a `POWER` figuruje tam jako `boolean` — tuż obok formuły zapisu `val ? \"ON\" : \"OFF\"`. Jedno z drugim się nie zgadza: js-controller przy zapisie przelicza wynik formuły z powrotem na typ **celu**, „ON” znowu staje się `true`, a formuła leży w aliasie bez działania. Przełączanie i tak działa — Tasmota przyjmuje zarówno `on`, jak i `true` — ale punkt wyglądał inaczej niż każdy punkt tworzony przez mqtt-client, a formuła twierdziła coś, czego nie robiła. W systemie produkcyjnym był to **jeden ze 196** punktów aliasu z celem zapisu MQTT, i pochodził od nas. Reguła brzmi teraz: **gdzie istnieje formuła zapisu, punkt tworzony jest jako `mixed`** — nie wyjątek dla `POWER`, lecz reguła obejmująca także `Fade` i `LedTable`. Bez formuły zostaje dokładny typ, bo admin wyprowadza min, maks i jednostkę z `number`. **Do tego dwa miejsca, w których staje się to widoczne**: typ punktu docelowego widnieje teraz jako plakietka za jego identyfikatorem w widoku szczegółów — dokładnie tam, gdzie wpisuje się formułę — w kolorze ostrzegawczym, gdy jedno z drugim się nie zgadza. A ramka sprawdzeń ma ósme sprawdzenie, „formuła zapisu działa”, które to nazywa, zamiast milczeć\n* Szablon uchodzi teraz za pasujący tylko tam, gdzie jego **wiersze obowiązkowe** rzeczywiście znajdują swoje źródło. Dotąd decydowało samo rozpoznanie, a rozpoznanie zadaje inne pytanie niż zastosowanie: `pruefeVorlage` sprawdza, czy wymienione **punkty** istnieją, wierszom potrzebne są określone **pola w ich wnętrzu**. Samodzielnie zbudowany szablon licznika energii, którego wiersz obowiązkowy czyta `tele.SENSOR · SML.Total_Summe`, wygrywał w ten sposób na **17** zwykłych Tasmotach i dostarczał tam dokładnie jeden — w dodatku odznaczony — wiersz tam, gdzie szablon gniazdka zbudowałby jedenaście. Przy urządzeniu stało „rozpoznano jako: licznik Tasmota”, a szkic był pusty. Teraz w ogóle tam nie staje na starcie, a miejsce dostaje następny najlepszy; to, co pominięto, stoi w „dlaczego”. Wiersze opcjonalne się nie liczą, po to są opcjonalne — zmierzone na istniejącym zasobie **żaden** z pozostałych piętnastu szablonów nie traci ani jednego ze swoich 51 zwycięstw. **A próba w arkuszu wzorca**: pobiera teraz także wartości punktów, z których czytają wiersze. Bez nich sądziła o polach, których nie mogła zobaczyć, i ten sam szablon podawał różne liczby zależnie od tego, co kliknięto wcześniej. Pokazuje teraz przy każdym urządzeniu, ile wierszy naprawdę by powstało, a przy „nie pasuje” **którego wiersza obowiązkowego brakuje** — tak z „22 urządzenia trafione, 17 z nich wygranych” zrobiło się uczciwe „22 trafione, 1 wygrane · 21× nie pasuje”. **A próba liczy teraz tak jak tworzenie**: początkowo porównywała tylko z jednym innym szablonem o najwyższej punktacji — jeśli ten nie pasował do urządzenia, badany szablon ogłaszał się zwycięzcą. Tak „czysty punkt pomiarowy” zgłaszał zwycięstwo na Tasmocie, choć pomiędzy stoi szablon gniazdka, który tam naprawdę pasuje. Teraz przechodzi listę trafień tak jak `vorschlag`; po ponownym pomiarze wszystkie 150 par szablon–urządzenie się zgadza\n* Alias, którego źródło zniknęło z systemu, rzuca się teraz w oczy bez klikania w niego. Dotąd mówiło się o tym tylko w rozwiniętym szczególe i w ramce sprawdzeń — wiersz na liście milczał, bo pytał, czy źródło jest **wpisane**, a nie czy **istnieje**. Wiersz niesie teraz czerwony `!` z adnotacją „źródło nie istnieje”, nagłówek plakietkę „1 punkt wskazuje w pustkę” z listą w podpowiedzi, a drzewo aliasów czerwony `!` przy dotkniętym kanale. To nie jest usterka kosmetyczna: js-controller zapamiętuje „brak źródła” trwale i nigdy tego nie poprawia — pomaga tylko usunięcie i utworzenie na nowo. Liczone jest raz przy wczytywaniu obiektów, a nie przy każdym rysowaniu; w systemie produkcyjnym 531 punktów aliasu w 5,2 ms. Od razu znalazły się dwa: kontaktron okienny wciąż wskazujący dawno zastąpiony adapter `zigbee` oraz punkt NSPanel z brakującym źródłem `0_userdata` zarówno do odczytu, jak i do zapisu. Wiersz **całkiem bez** źródła zachowuje własną adnotację — jest niedokończony, a nie zepsuty\n* Nowość: **„Wymieniany w”** przy istniejącym aliasie. Ramka pod porównaniem zmian szuka po kliknięciu wszystkiego, co jeszcze wymienia identyfikator — **skryptów** adaptera javascript z folderem, nazwą, stanem i numerami wierszy, **plików** folderów instancji (czyli widoków vis i vis-2), każdego wczytanego **obiektu** (na przykład tam, gdzie mosty matter trzymają swoich członków), **wyliczeń** oraz wpisów przy samym punkcie (`SET → influxdb.0`) — i tego samego dla **źródła**, łącznie z innymi aliasami na nim. To odpowiada na pytanie, co zostało z tyłu przy przejściu na alias. Zmierzone w systemie produkcyjnym z 24 706 obiektami i 66 plikami: pierwsze spojrzenie zajmuje 1,3 sekundy, każdy kolejny alias potem 0,17. Interfejsy webowe adapterów nie są przeszukiwane — 160 ze 177 MB tekstu w drzewie plików, identyczne na każdym ioBrokerze, a niosą przykłady w rodzaju `alias.0.Floor.Room.MotionSensor`; bez tej granicy warsztat znalazłby własne pliki źródłowe jako użytkowników samego siebie. Celowo bez wyroku: źródło, które nadal jest wymieniane, nie jest błędem — skrypt, który je zasila, jest dokładnie tam, gdzie trzeba (z 376 aliasów ze źródłem 61 miało źródło nadal wymienione wprost, spora ich część słusznie). **A okno usuwania przeszukuje teraz również skrypty** — to istniało tylko przy przenoszeniu, choć to usuwanie jest nieodwracalne\n* Wybór pola przy punkcie JSON radzi sobie teraz z każdym kluczem. Dotąd warsztat doklejał nazwę pola do dostępu kropkami — co działa tylko dopóty, dopóki każda część jest poprawną nazwą JavaScriptu. `gpu_usages.amd-vaapi.gpu` zamieniał się w wyrażenie arytmetyczne (`?.amd - vaapi?.gpu`), `service.storage./dev/shm.free` i `cpu_usages.1111740.mem` w błąd składni. Zmierzone na telegramie Frigate: z 233 oferowanych pól **27** nadawało się do użytku, pozostałych 206 kończyło się czerwonym komunikatem „formuła zepsuta”. `feldFormel` stawia teraz nawiasy tam, gdzie klucz nie jest nazwą — `JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null` — i odczytuje je z powrotem, dzięki czemu wybór zostaje na wskazanym polu, zamiast cofać się do „własnej formuły”. Dla zwykłych nazw nie zmienia się **ani jeden znak**, więc dostarczane szablony pozostają nietknięte. Kropka wewnątrz samego klucza (`frigate.full_system`) pozostaje nierozwiązywalna i nadal pokazuje „własna formuła”",
16
+ "uk": "* Після збереження наступний клік у дереві запитував **«незбережені зміни»** — про аліас, який щойно було записано. Позначка «тут є незаписане» у всій програмі лише виставлялася і ніколи не знімалася; вона зникала тільки тоді, коли зникав сам чернетковий запис, тобто при видаленні та при перенесенні. Тепер вона знімається після кожного вдалого запису — і тільки тоді: якщо щось не вдалося, зміна справді ще не всередині, і питання лишається виправданим. **Є і другий ефект, якого давно бракувало**: доки позначка стояла, верстак навмисно не перебудовував чернетку. Після запису лишалася стара замість того, щоб зібратися наново за щойно записаним аліасом.\n* Друге натискання **«Запропонувати вільні місця»** повертало назад рядок, який ви задали самі. На кондиціонері: вгадати дев’ять місць, вручну поставити роль рядка SPEED на `level.speed`, відхилити — і наступна пропозиція знову підставляла вгадане `level.mode.fan`. Місце шаблону виглядало вільним, тож той самий рядок вгадувався вдруге; після цього він ніс **обидві** позначки, «змінено» та «припущено», які виключають одна одну — те, що щойно вгадано, не могло бути змінене раніше. Тепер вгадування не чіпає рядок із позначкою «змінено». Місце лишається вільним, а повідомлення під смугою каже чому. Покласти поруч другий рядок було альтернативою — тоді та сама вихідна точка посіла б два місця, і восьма перевірка справедливо повідомила б про це.\n* Щойно з’являлися припущення, кнопка у смузі шаблону перейменовувалася на **«Відхилити пропозиції»** — а друга з тим самим словом і тією самою дією стояла в синій смузі під нею. Дві кнопки, одна ручка. У смузі тепер завжди написано «Запропонувати вільні місця», і лише доки є що вгадувати; коли вгадано все, кнопка зникає. Відхиляють там, де цьому місце: у синій смузі, поруч із «залишити всі».\n* Замість «або всі місця зайняті, або жодна решта точок не підходить» повідомлення тепер називає випадок, який справді має місце — з **іменами** місць, що лишаються вільними: «Вільними лишаються SPEED, SWING … Кожна решта точок уже служить джерелом читання або запису в зайнятому рядку» або «… Жодна решта точок сюди не підходить». Якщо рішення, ухвалене вручну, тримає місце відкритим, додається речення: «1 рядків вирішено вручну і лишаються недоторканими». Випадок «усі місця зайняті» без запиту мовчить — він каже «робити нічого», а інакше стояв би майже біля кожного пристрою.\n* Кондиціонер Рікардо розпізнається як **термостат** і займає 3 з 24 місць. **airCondition** не проходить, бо його єдине обов’язкове місце MODE не несе потрібної ролі — і на цьому все, адже «не підходить» лишається останнім словом. З автоматичною пропозицією він дійшов би до **9 з 29** проти 8 з 24. Тепер це стоїть поруч із полем шаблону: «· airCondition, можливо, підійшов би краще» — один рядок, обидва числа у спливній підказці. Називається **один** шаблон — найкращий — і лише тоді, коли він справді кращий; міряється зайнятими місцями, а не часткою. Поруч сидить маленька кнопка **→**, яка робить обидва кроки відразу: перемикає на цей шаблон і тут же натискає «Запропонувати вільні місця» — інакше підказка була б оголошенням без дії. У списку шаблонів кожен зачеплений рядок несе «з пропозицією: підходить» після причини відмови. Рахується один раз при виборі пристрою і далі лише при зміні рядка — пропозиція читає імена, списки значень, одиниці й типи, але не виміряні значення.\n* У **аркуші шаблону** та в діалозі «зберегти як шаблон» тип пристрою показувався своїм **ключем шаблону**, а не іменем: у жалюзі читалося «blinds», у медіаплеєра «mediaPlayer», у повзунка «levelSlider» — слова, яких більше ніде в інтерфейсі немає. Збережене значення весь цей час було правильним (тип, від 11.09.2026); хибним був лише підпис, він приходив з іншого поля, а оскільки Admin не знає цих трьох ключів, разом із ними зникало й перекладене ім’я. Тепер там написано те саме, що й у виборі шаблону поруч: «Жалюзі · blind».\n* Тепер можна створити **кнопку**. `STOP` у жалюзі лише пише — у натискання клавіші немає стану для читання — і це раніше зривало **весь** аліас: пробний прогін казав «STOP: джерело не обрано», «створити зараз» лишалася сірою, і жоден аліас жалюзі так і не отримав STOP. Перший діагноз був хибним, і це варто сказати: річ була не в надто суворій перевірці запису. **ioBroker відхиляє аліас без джерела читання** — `{ id: { write: … } }` дає «Alias id is invalid: The id is empty!». Правильна форма — та, яку Рікардо давно використовує на своїх десяти рукотворних STOP: `alias.id` як простий текст, що вказує на командну точку, плюс `common.read: false` на точці аліаса. Це каже vis, Alexa і matter малювати **кнопку**, а не перемикач, назавжди застряглий у «вимк». Вирішує **ціль**, а не роль: `read: false` пише сам адаптер (виміряно на справжньому STOP у `hm-rpc`). Якщо ціль читана, блокування лишається — тоді відсутнє джерело читання справді є дефектом. Кнопка переживає й зворотне читання: усі три місця, що відновлюють аліас, тепер про неї знають, інакше `read` тихо перемкнувся б на `true` при наступному оновленні. **З того самого питання виросла нова перевірка**: «ціль уміє те, чого від неї вимагають». Верстак пише в чужі точки і читає з чужих точок, жодного разу не перевіривши, чи вміють вони це. Три способи тихо розвалитися — формула запису видає текст, а ціль тексту не приймає; ціль несе `write: false` (ioBroker усе одно кладе значення, але адаптер нічого далі не передає: тихий холостий хід); джерело читання несе `read: false` і ніколи нічого не повідомляє. Усі три тепер з’являються у блоці перевірок і як значок біля ідентифікатора в детальному вигляді, рівно там, де набирається формула\n* Верстак сам створює **точки надсилання** MQTT — точка `cmnd` виникає в ioBroker лише після того, як у її топік щось опубліковано; до того аліасу не було б куди писати. Тип він брав зі знання про команди, а `POWER` записаний там як `boolean` — просто поруч із формулою запису `val ? \"ON\" : \"OFF\"`. Одне з одним не сходиться: js-controller під час запису перетворює результат формули назад до типу **цілі**, «ON» знову стає `true`, і формула лежить в аліасі без дії. Перемикання все одно працює — Tasmota приймає і `on`, і `true` — але точка виглядала інакше, ніж будь-яка точка, створена mqtt-client, а формула стверджувала те, чого не робила. На продуктивній системі це була **одна з 196** точок аліасів із ціллю запису MQTT, і прийшла вона від нас. Правило тепер таке: **де є формула запису, точка створюється як `mixed`** — не виняток для `POWER`, а правило, що покриває і `Fade`, і `LedTable`. Без формули точний тип зберігається, бо admin виводить min, max і одиницю з `number`. **Плюс два місця, де це стає видно**: тип цільової точки тепер показано значком після її ідентифікатора в детальному вигляді — рівно там, де набирається формула — попереджувальним кольором, коли одне з одним не сходиться. А у блоці перевірок з’явилася восьма перевірка «формула запису діє», яка називає це замість того, щоб мовчати\n* Шаблон тепер вважається відповідним лише там, де його **обов’язкові рядки** справді знаходять своє джерело. Досі вирішувало саме лише розпізнавання, а розпізнавання ставить інше питання, ніж застосування: `pruefeVorlage` перевіряє, чи є названі **точки**, рядкам же потрібні певні **поля всередині них**. Саморобний шаблон лічильника електроенергії, чий обов’язковий рядок читає `tele.SENSOR · SML.Total_Summe`, перемагав таким чином на **17** звичайних пристроях Tasmota і видавав там рівно один — до того ж знятий — рядок там, де шаблон розетки побудував би одинадцять. Біля пристрою стояло «розпізнано як: лічильник Tasmota», а чернетка була порожня. Тепер він там навіть не виходить на старт, і місце дістається наступному за силою; що було пропущено, написано в «чому». Необов’язкові рядки не рахуються, на те вони й необов’язкові — за виміром на наявному фонді **жоден** із п’ятнадцяти решти шаблонів не втрачає жодної зі своїх 51 перемог. **І пробний прогін в аркуші шаблону**: він тепер забирає й значення точок, з яких читають рядки. Без них він судив про поля, яких не бачив, і той самий шаблон повідомляв різні числа залежно від передісторії. Тепер він показує по кожному пристрою, скільки рядків вийшло б насправді, а при «не підходить» — **якого обов’язкового рядка бракує**; так «22 пристрої зачеплено, 17 з них виграно» перетворилося на чесне «22 зачеплено, 1 виграно · 21× не підходить». **І пробний прогін рахує так само, як створення**: спершу він порівнював лише з одним іншим шаблоном, що набрав найбільше очок — якщо той не підходив пристрою, перевірюваний оголошував себе переможцем. Так «чиста точка вимірювання» повідомляла про перемогу на Tasmota, хоча між ними стоїть шаблон розетки, який там справді підходить. Тепер він проходить список збігів так само, як `vorschlag`; при повторному вимірі всі 150 пар «шаблон — пристрій» збігаються\n* Аліас, чиє джерело зникло із системи, тепер помітний без кліку по ньому. Досі про це говорилося лише в розгорнутій подробиці та в блоці перевірок — рядок у списку мовчав, бо запитував, чи **внесене** джерело, а не чи воно **існує**. Тепер рядок несе червоний `!` із приміткою «джерела не існує», заголовок — значок «1 точка вказує в порожнечу» зі списком у спливній підказці, а дерево аліасів — червоний `!` біля зачепленого каналу. Це не косметика: js-controller запам’ятовує «джерела бракує» назавжди і ніколи сам цього не виправляє — допомагає лише видалити і створити наново. Рахується один раз при завантаженні об’єктів, а не при кожному малюванні; на продуктивній системі 531 точка аліасів за 5,2 мс. Одразу знайшлися дві: віконний контакт, що досі вказував на давно замінений адаптер `zigbee`, і точка NSPanel із відсутнім джерелом `0_userdata` і для читання, і для запису. Рядок **зовсім** без джерела зберігає власну примітку — він недороблений, а не зламаний\n* Нове: **«Згадується в»** біля наявного аліаса. Блок під порівнянням змін шукає за кліком усе, що ще згадує ідентифікатор — **скрипти** адаптера javascript із текою, іменем, станом і номерами рядків, **файли** тек екземплярів (тобто види vis і vis-2), кожен завантажений **об’єкт** (наприклад, там, де мости matter тримають своїх учасників), **переліки** та записи біля самої точки (`SET → influxdb.0`) — і те саме для **джерела**, включно з іншими аліасами на ньому. Це відповідає на питання, що лишилося позаду при переході на аліас. Виміряно на продуктивній системі з 24 706 об’єктами і 66 файлами: перший погляд займає 1,3 секунди, кожен наступний аліас після цього 0,17. Веб-інтерфейси адаптерів не обшукуються — 160 із 177 МБ тексту у файловому дереві, однакові на кожному ioBroker, і вони несуть приклади на кшталт `alias.0.Floor.Room.MotionSensor`; без цієї межі верстак знайшов би власні вихідні файли як своїх же користувачів. Навмисно без вироку: джерело, яке досі згадується, не помилка — скрипт, що його живить, розташований саме там, де треба (із 376 аліасів із джерелом у 61 джерело й далі згадувалося напряму, і в доброї частини заслужено). **А діалог видалення тепер теж шукає по скриптах** — це було лише при перенесенні, хоча незворотним є якраз видалення\n* Вибір поля у точці JSON тепер дає раду з будь-яким ключем. Досі верстак приклеював ім’я поля до звертання через крапки — що працює лише доти, доки кожна частина є припустимим іменем JavaScript. `gpu_usages.amd-vaapi.gpu` перетворювався на арифметичний вираз (`?.amd - vaapi?.gpu`), `service.storage./dev/shm.free` і `cpu_usages.1111740.mem` — на синтаксичну помилку. Виміряно на телеграмі Frigate: із 233 запропонованих полів придатними були **27**, решта 206 закінчувалися червоним повідомленням «формула зламана». `feldFormel` тепер ставить дужки там, де ключ не є іменем — `JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null` — і читає їх назад, тож вибір лишається на обраному полі замість того, щоб відкочуватися до «власної формули». Для звичайних імен не змінюється **жодного символу**, тож шаблони з постачання не зачеплені. Крапка всередині самого ключа (`frigate.full_system`) лишається нерозв’язною і далі показує «власна формула»",
17
+ "zh-cn": "* 保存之后,在树中的下一次点击仍会询问**“未保存的更改”**——而那个别名刚刚才写入。“这里还有未写入的东西”这个标记在整个程序里只会被置上,从不被清除;只有当草稿本身消失时它才消失,也就是删除和移动的时候。现在它在每次成功写入后都会落下——而且仅在此时:若出了差错,更改确实还没进去,这个询问依然是有道理的。**还有一个早就缺失的第二重作用**:只要标记还在,工作台就刻意不重建草稿。因此写入之后留下的是旧的那份,而不是依照刚写好的别名重新构建。\n* 第二次按下**“建议空闲位置”**会把你自己设定过的行掰回去。以空调为例:让它猜出九个位置,手工把 SPEED 行的角色改成 `level.speed`,然后放弃——下一次建议又把猜出来的 `level.mode.fan` 放了回去。模式位置看上去是空的,于是同一行被第二次猜测;它随后同时带着**两个**标记,“已更改”和“推测”,而这两者互相排斥——刚刚猜出来的东西不可能事先被更改过。现在猜测会放过任何带“已更改”标记的行。位置保持空着,下面的提示说明原因。在旁边再放一行是另一种做法——那样同一个源数据点就会占据两个位置,第八项检查会理所当然地报出来。\n* 只要还有未决的推测,模式栏里的按钮就把自己改名为**“放弃建议”**——而蓝色条里还站着第二个,用词相同、作用相同。两个按钮,一个把手。栏里现在始终写着“建议空闲位置”,而且只在还有东西可猜时才出现;全部猜完,它就消失。放弃就在它该在的地方进行:蓝色条里,紧挨着“全部保留”。\n* 提示不再说“要么所有位置都已占用,要么没有剩余数据点合适”,而是指出真正出现的那一种情形——并附上仍然空着的位置**名称**:“空着的是 SPEED、SWING …… 每一个剩余数据点都已在某个已占用的行里充当读取源或写入源”,或者“…… 没有剩余数据点与之相配”。若某个手工决定让位置一直空着,还会补上一句:“1 行由手工决定,保持不动。”“所有位置都已占用”这一情形在未被询问时保持沉默——它说的是“无事可做”,否则几乎每台设备旁都会挂着这句话。\n* Ricardo 的空调被识别为**恒温器**,占用 24 个位置中的 3 个。**airCondition** 落选,因为它唯一的必需位置 MODE 没有带上那个角色——事情就此了结,毕竟“不匹配”是最后一句话。若使用自动建议,它会达到 **9/29**,而不是 8/24。现在这句话就写在模式字段旁边:“· airCondition 或许更合适”——只有一行,两个数字都在悬停提示里。只会点名**一个**模式——最好的那个——而且只有当它确实更好时;衡量的是已占用位置数,而不是比例。旁边有一个小小的 **→** 按钮,一次做完两件事:切换到该模式并立刻按下“建议空闲位置”——否则这条提示就只是通告而没有动作。在模式列表里,每个相关行都在其落选原因后面带着“配合建议:匹配”。计算在选中设备时进行一次,此后只在行发生变动时再算——建议读取的是名称、取值列表、单位和类型,不读测量值。\n* 在**模板页**和“另存为模板”对话框中,设备类型显示的是它的**模式键**而不是名称:卷帘上读到的是 “blinds”,媒体播放器是 “mediaPlayer”,滑块是 “levelSlider”——这些词在界面别处根本不会出现。保存下来的值一直是对的(类型,自 2026-09-11 起);错的只是标签,它取自错误的字段,而由于 Admin 并不认识这三个键,翻译过的名称也随之一并丢失。现在那里写的与旁边的模式选择一致:“卷帘 · blind”。\n* 现在可以创建**点动按钮**了。卷帘上的 `STOP` 只写不读——按一下键没有可读的状态——而这以前会让**整个**别名失败:试运行说“STOP:未选择源”,“立即创建”一直是灰的,没有一个卷帘别名拿到过 STOP。第一次的判断是错的,这点值得说明:问题不在写入检查过于严格。**ioBroker 会拒绝没有读取源的别名**——`{ id: { write: … } }` 得到的是 “Alias id is invalid: The id is empty!”。正确的写法正是 Ricardo 早就用在他那十个手工 STOP 上的:`alias.id` 作为纯文本指向命令点,再加上别名点上的 `common.read: false`。这会告诉 vis、Alexa 和 matter 画出一个**点动按钮**,而不是一个永远卡在“关”的开关。起决定作用的是**目标**,而不是角色:`read: false` 由适配器自己写入(在真实的 `hm-rpc` STOP 上测得)。若目标可读,拦截依然保留——那时缺少读取源确实是缺陷。这个按钮也经得起回读:重建别名的那三处现在都认得它,否则 `read` 会在下次更新时悄悄翻回 `true`。**同一个问题还长出了一项新检查**:“目标能做被要求的事”。工作台向别人的数据点写入、从别人的数据点读取,却从不检查它们是否做得到。三种无声崩塌的方式——写入公式产出文本而目标不接受文本;目标带着 `write: false`(ioBroker 照样存下数值,但适配器不会往下传递:一记无声的空响);读取源带着 `read: false`,永远不报告任何东西。这三种现在都出现在检查框里,并在详细视图中作为标识旁的小标签显示,正是输入公式的那个位置\n* 工作台自己创建 MQTT **发送点**——`cmnd` 点只有在其主题上发布过内容之后才会在 ioBroker 中诞生;在那之前别名根本无处可写。它此前从命令知识中取类型,而 `POWER` 在那里记作 `boolean`——就紧挨着写入公式 `val ? \"ON\" : \"OFF\"`。两者对不上:js-controller 在写入时会把公式结果换算回**目标**的类型,“ON” 又变回 `true`,公式留在别名里却毫无作用。切换照样有效——Tasmota 既接受 `on` 也接受 `true`——但这个点看起来与 mqtt-client 创建的任何点都不一样,而公式声称了它并没有做到的事。在生产系统上,它是带 MQTT 写入目标的 **196 个别名点之一**,而且出自我们自己。现在的规则是:**凡有写入公式,该点就按 `mixed` 创建**——不是为 `POWER` 开的例外,而是一条同样覆盖 `Fade` 和 `LedTable` 的规则。没有公式时保留精确类型,因为 admin 会从 `number` 推导出最小值、最大值和单位。**另外还有两处让它变得看得见**:目标点的类型现在作为小标签显示在详细视图中它的标识后面——正是输入公式的地方——两者对不上时用警示色。检查框也多了第八项检查“写入公式生效”,把这件事说出来,而不是保持沉默\n* 模板现在只在其**必需行**确实找得到各自的源时才算匹配。此前只由识别来决定,而识别提出的问题与套用不同:`pruefeVorlage` 检查点名的**数据点**是否存在,行需要的却是**其中特定的字段**。一个自制的电表模板,其必需行读取 `tele.SENSOR · SML.Total_Summe`,就这样在 **17** 台普通 Tasmota 上胜出,并在那里只产出一行——而且还是未勾选的——而插座模板本可以建出十一行。设备上写着“识别为:Tasmota 电表”,草稿却是空的。现在它在那里根本不参赛,位置归下一个最合适的;被越过的内容写在“为什么”里。可选行不计入,可选正是这个意思——以现有设备实测,其余十五个模板中**没有一个**丢掉它 51 次胜出中的任何一次。**还有模板页里的试运行**:它现在也会取回各行所读数据点的数值。没有这些数值时,它评判的是自己看不见的字段,同一个模板会因为之前点过什么而报出不同的数字。它现在按设备显示实际会产生多少行,并在“不匹配”时说明**缺的是哪一条必需行**——于是“命中 22 台设备,其中 17 台胜出”变成了诚实的“命中 22 台,胜出 1 台 · 21 次不匹配”。**而且试运行现在的算法与实际创建一致**:起初它只与得分最高的那一个其他模板比较——若那个模板并不适合该设备,被检查的模板就宣布自己获胜。于是“纯测量点”在一台 Tasmota 上报出胜利,尽管中间还隔着真正适合的插座模板。它现在像 `vorschlag` 那样遍历命中列表;重新测量后,模板与设备的全部 150 对结果一致\n* 源已从系统中消失的别名,现在不用点开就看得出来。此前只有在展开的详情里和检查框中才会说明——列表中的行保持沉默,因为它问的是源是否已**填写**,而不是源是否**存在**。这一行现在带着红色的 `!` 和注记“源不存在”,标题行带着“1 个点指向空处”的小标签并在悬停提示中列出清单,别名树则在受影响的通道上带一个红色 `!`。这不是表面瑕疵:js-controller 会长期记住“源缺失”且从不自行纠正——只有删除并重建才有用。计算在对象载入时进行一次,而不是每次绘制;在生产系统上 531 个别名点用时 5.2 毫秒。当场就找到两个:一个窗磁仍指向早已被替换的 `zigbee` 适配器,还有一个 NSPanel 点的 `0_userdata` 源在读和写两边都缺失。**完全没有**源的行保留它自己的注记——那是没做完,不是坏了\n* 新增:现有别名上的**“被引用于”**。更改对比下方的方框在点击后会搜索一切仍然提到该标识的地方——javascript 适配器的**脚本**,连同文件夹、名称、状态和行号;各实例文件夹中的**文件**(也就是 vis 与 vis-2 的视图);每一个已载入的**对象**(例如 matter 网桥存放其成员的地方);**枚举**以及数据点自身上的条目(`SET → influxdb.0`)——对**源**也做同样的搜索,包括其上的其他别名。这回答了“转用别名之后还有什么留在后面”这个问题。在拥有 24 706 个对象和 66 个文件的生产系统上实测:第一次查看需要 1.3 秒,之后每个别名 0.17 秒。适配器的网页界面不在搜索之列——它们占文件树 177 MB 文本中的 160 MB,在每台 ioBroker 上都相同,而且带有 `alias.0.Floor.Room.MotionSensor` 之类的示例;没有这条界线,工作台会把自己的源文件当成自己的使用者找出来。刻意不下判断:仍被提到的源并不是错误——给它供数的脚本正该在那里(376 个带源的别名中,61 个的源仍被直接提到,其中相当一部分理所应当)。**而且删除对话框现在也会搜索脚本**——这原先只在移动时才有,尽管不可逆的恰恰是删除\n* JSON 数据点上的字段选择现在能应付任何键名。此前工作台用点号把字段名粘到取值表达式上——只有当每一段都是合法的 JavaScript 名称时才行得通。`gpu_usages.amd-vaapi.gpu` 变成了算术表达式(`?.amd - vaapi?.gpu`),`service.storage./dev/shm.free` 和 `cpu_usages.1111740.mem` 则成了语法错误。在一份 Frigate 报文上实测:233 个可选字段中只有 **27** 个能用,其余 206 个都以红色的“公式已损坏”收场。`feldFormel` 现在在键名不是名称的地方改用方括号——`JSON.parse(val)?.gpu_usages?.['amd-vaapi']?.gpu ?? null`——并且能再读回来,因此选择会停在所选字段上,而不是退回“自定义公式”。对于普通名称,**一个字符也不会**改变,所以随附的模板不受影响。键名内部本身带点的情况(`frigate.full_system`)仍然无法解析,依旧显示“自定义公式”"
18
+ },
19
+ "0.9.10": {
20
+ "en": "* Four things from the full test run. **A channel identifier** was not sanitised in the multi-output path: from the channel name “Licht, Bar” the js-controller quietly made `Licht_ Bar`, while the workbench displayed “Licht, Bar” and wrote it into the enumerations — an identifier that never existed, and after deleting the alias it stayed there as a leftover. `ausgangName` now sanitises itself, and where two channels produce the same name the second gets a `_2`. **The caption** differed between the two views: where the point's name equals the row name, “Edit alias” showed it and “Create alias” an empty field. **The row list** now counts like the tree — `POWER2` before `POWER10`. And **an enumeration the workbench created itself** now also disappears when it becomes empty through a change of function, not only when the alias is deleted\n* Tidying: \"turn an alias object into a draft row\" was written out five times — each with the same write-source rule and slightly different surroundings. Four bugs in this version came from exactly that: the lost write source on the roller shutter, a switching point that became a read-only one, the missing caption on `alias.0.Solar.Netz`, and a deviation the workbench had produced itself. The reading now lives in one place; what the four callers do with it — compare, create, overwrite — stays with them. Behaviour is unchanged\n* Three small things spotted during the run. **RSSI** was pre-ticked in the five Tasmota and measuring-point templates but not in the eleven Homematic ones — the same device property, two answers depending on the vendor; it is now unticked everywhere, like the rest of the diagnostics. **The `MAP_URL` slot** in the vacuum pattern got no role because its expression starts without `^` and the derivation demanded both anchors; a missing start anchor no longer counts against a slot. **And the \"guessed\" tag** in the swap dialog looked like text stuck to the point name — its styling hung on three parent levels that do not exist there. It is now a pill like in the state list and says in its tooltip whether the guess came from the point name or from the role\n* The save button in the template dialog now also checks when pressed, not only when drawn. It is re-evaluated when a field is left — typing an open bracket into the name hint and clicking \"Save template\" without leaving the field left you with a blue button and saved a template with a broken expression. The five lock reasons now live in one place that drawing and saving share\n* Three places now say why they cannot. **The save button in the template dialog** was greyed out and silent — five reasons can lock it and none of them was shown; every applicable one now appears on the button and as a box in the dialog. **The error dialog when deleting** only gave a count (\"1 operations failed\") and not which id is stuck; writing has had that list all along. **And the reason a send point could not be created** hung on a button that the same callback threw away 120 ms later — it now sits at the top of the dry run and survives the rebuild\n* If a point's type does not match its pattern slot, all three places now say so — not just the expanded row. If the slot was **required**, the pattern stops applying altogether, and the whole list showed up tinted: on the Bastelzimmer_Licht, switching SET from `boolean` to `mixed` was enough for eight of eight rows to count as \"no slot\", while the pattern field reported \"✕ SET missing\" — SET was right there. It now reads \"✕ SET: type mixed instead of boolean\", and above the list: \"The light pattern does not apply right now: SET requires boolean, but mixed is set. That is why no row has a slot.\" Only the row that causes it is tinted now — the whole list used to light up, which showed the consequence instead of the cause.\n* A late answer to `system.config` now really does carry the expert mode over. The tab gives up after 2.5 seconds and continues with the browser language; if the answer arrives later, the language stays as it is (switching after the labels are drawn would be worse), the expert mode is adopted and the tree is redrawn once. That had long been built — but above it sat a guard from the time before, which bailed out in exactly this case. Without the mode, every node under `system.*` and `enum.*` was missing, with nothing saying why\n* The swap dialog notices when one level up fits better. The picker lets you choose any node with data points underneath — it has to, because on a flat adapter the channel is the device. With MQTT, though, `stat`, `tele` and `cmnd` are topic folders: landing there finds fewer points, and the lock would ask you to remove some. The workbench now also computes the parent level and says so — \"One level up (…) finds a target for 7 of 7 points, here only 5\" — with a button that switches the selection. Nothing is forbidden\n* The device list in the swap dialog keeps its position. Scrolling down a long list and picking a device used to jump back to the top, with the freshly picked entry out of sight — picking rebuilds the dialog, and the tree is a different element afterwards. If the selected row still ends up outside, it is brought into view. A new search and a freshly opened dialog still start at the top\n* When swapping the source, a write target no longer counts if it coincides with the read source. The search tries the bare point name as its last form, so `cmnd.POWER` found a status point that also ends in `POWER` — the alias would then have written to its own read source. Guessing already caught this, matching by path did not; it showed when the new source was picked as a sub-node instead of the device\n* When swapping the source, a point that cannot come along now stops the swap instead of letting it fail halfway. A point with separate sources — reads from `stat.POWER`, writes to `cmnd.POWER` — needs both at the new source. If the write target is missing, ioBroker has **no** form that means \"reads, writes nowhere\": a plain id means \"write to the status point\", `{read: X}` without `write` is rejected by the js-controller, and `common.write: false` does not protect the source (measured: writing to such an alias overwrote the read source). So the user decides — the checkbox \"remove this point when swapping\" now appears in this case as well, and \"Swap now\" stays disabled until someone has decided; the reason shows on the button and as a line in the dialog. Before, the swap started, failed at the controller and left the alias half on the old and half on the new source\n* If a write fails during the swap, **nothing** is deleted. The deletions used to run anyway, so an alias that was already half migrated lost points on top of it. Moving an alias has followed that rule for a long time\n* \"All data points of the device\" no longer moves the storage location. For a device with several outputs the workbench creates a folder with one channel per output. The button rebuilds the draft and passed on only the **finished target**; `setzeZiel` reads its last segment as the device name — with several outputs that segment is the output, and it ended up in the folder as well. Every press pushed the location one level deeper, and that is where it was written, too: three clicks produced four folders instead of one (`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`). The button now passes folder and name separately, the way the output selector next to it has always done. A single-output device was never affected",
21
+ "de": "* Vier Sachen aus dem kompletten Durchlauf. **Eine Kanalkennung** wurde im Mehrfach-Pfad nicht gesäubert: aus dem Kanalnamen „Licht, Bar\" machte der js-controller still `Licht_ Bar`, während die Werkbank „Licht, Bar\" anzeigte und in die Aufzählungen eintrug — eine Kennung, die es nie gab, und nach dem Löschen blieb sie dort als Leiche stehen. Jetzt säubert `ausgangName` selbst, und wo zwei Kanäle denselben Namen ergeben, bekommt der zweite ein `_2`. **Die Beschriftung** stand in beiden Ansichten verschieden: wo der Name des Punktes dem Zeilennamen gleicht, zeigte „Alias bearbeiten\" ihn und „Alias anlegen\" ein leeres Feld. **Die Zeilenliste** zählt jetzt wie der Baum — `POWER2` vor `POWER10`. Und **eine Aufzählung, die die Werkbank selbst angelegt hat**, verschwindet auch dann, wenn sie durch einen Wechsel der Funktion leer wird, nicht nur beim Löschen des Alias\n* Aufgeräumt: „Aus einem Alias-Objekt wird eine Entwurfszeile\" war fünfmal ausprogrammiert — jedes Mal mit derselben Schreibquellenregel und leicht anderem Drumherum. Vier Fehler dieser Version stammten genau daher: die verlorene Schreibquelle am Rollladen, ein schaltender Punkt der zum lesenden wurde, die fehlende Beschriftung an `alias.0.Solar.Netz` und eine Abweichung, die die Werkbank selbst erzeugt hatte. Die Ablesung steht jetzt an einer Stelle; was die vier Aufrufer damit tun — vergleichen, anlegen, überschreiben — bleibt bei ihnen. Am Verhalten ändert sich nichts\n* Drei Kleinigkeiten, die beim Durchgang aufgefallen sind. **RSSI** war in den fünf Tasmota- und Messpunkt-Vorlagen vorgehakt, in den elf Homematic-Vorlagen nicht — dasselbe Gerätemerkmal, zwei Antworten je nach Hersteller; jetzt ist es überall abgewählt wie die übrige Diagnose. **Der Platz `MAP_URL`** im Staubsauger-Muster bekam keine Rolle, weil sein Ausdruck ohne `^` beginnt und die Ableitung beide Anker verlangte; der fehlende Anfangsanker zählt nicht mehr gegen den Platz. **Und die Marke „vermutet\"** im Tausch-Dialog sah aus wie Text, der am Punktnamen klebt — die Gestalt hing an drei Elternebenen, die es dort nicht gibt. Sie ist jetzt eine Pille wie in der Zustandsliste und sagt im Tooltip, ob über den Punktnamen oder über die Rolle geraten wurde\n* Der Speichern-Knopf im Vorlagendialog prüft jetzt auch beim Drücken, nicht nur beim Zeichnen. Er wird beim Verlassen eines Feldes neu bewertet — wer eine offene Klammer in den Namenshinweis schrieb und ohne Umweg auf „Vorlage speichern\" klickte, hatte einen blauen Knopf vor sich und speicherte eine Vorlage mit kaputtem Ausdruck. Die fünf Sperrgründe stehen dafür jetzt an einer Stelle, die Zeichnen und Speichern gemeinsam nutzen\n* Drei Stellen sagen jetzt, warum sie nicht können. **Der Speichern-Knopf im Vorlagendialog** war grau und schwieg — fünf Gründe können ihn sperren, und keiner stand dabei; jetzt stehen alle zutreffenden am Knopf und als Kasten im Dialog. **Der Fehlerdialog beim Löschen** nannte nur eine Zahl („1 Vorgänge gingen schief\") und nicht, welche Kennung hängt; beim Schreiben gab es die Liste längst. **Und die Begründung eines fehlgeschlagenen Sendepunkts** hing an einem Knopf, den derselbe Rückruf 120 ms später wegwarf — sie steht jetzt oben im Trockenlauf und überlebt dessen Neuaufbau\n* Passt der Typ eines Punktes nicht zu seinem Musterplatz, sagen das jetzt alle drei Stellen — und nicht mehr nur die aufgeklappte Zeile. War der Platz eine **Pflicht**, greift das Muster danach gar nicht mehr, und dann stand die ganze Liste getönt da: am Bastelzimmer_Licht reichte ein Wechsel an SET von `boolean` auf `mixed`, und acht von acht Zeilen galten als „ohne Platz\", während das Musterfeld „✕ SET fehlt\" meldete — SET war aber da. Jetzt steht im Musterfeld „✕ SET: Typ mixed statt boolean\" und über der Liste „Das Licht-Muster greift gerade nicht: SET verlangt boolean, eingestellt ist mixed. Deshalb hat keine Zeile einen Platz.\" Getönt wird dabei nur die Zeile, an der es hängt — vorher leuchtete die ganze Liste auf, und damit zeigte die Tönung die Folge statt der Ursache.\n* Eine späte Antwort auf `system.config` zieht den Expertenmodus jetzt wirklich nach. Der Reiter gibt nach 2,5 Sekunden auf und arbeitet mit der Browsersprache weiter; kommt die Antwort danach, bleibt die Sprache stehen (ein Sprung nach dem Beschriften wäre schlimmer), der Expertenmodus wird übernommen und der Baum einmal neu gezeichnet. Gebaut war das längst — nur stand darüber noch ein Wächter aus der Zeit davor, der genau in diesem Fall ausstieg. Ohne den Modus fehlten alle Knoten unter `system.*` und `enum.*`, ohne dass irgendwo stand, warum\n* Der Tausch-Dialog merkt, wenn eine Ebene höher besser passt. Der Auswahlbaum lässt jeden Knoten wählen, unter dem Datenpunkte hängen — das muss so sein, weil bei einem flachen Adapter der Kanal das Gerät ist. Bei MQTT sind `stat`, `tele` und `cmnd` aber Themenordner: wer dort landet, findet weniger Punkte wieder und würde von der Sperre aufgefordert, welche zu entfernen. Jetzt rechnet die Werkbank die Elternebene mit und sagt es — „Eine Ebene höher (…) finden 7 von 7 Punkten ein Ziel, hier nur 5\" —, mit einem Knopf, der die Wahl umstellt. Verboten wird nichts\n* Die Geräteliste im Tausch-Dialog bleibt stehen, wo sie stand. Wer in einer langen Liste nach unten scrollte und ein Gerät anklickte, landete danach wieder am Anfang und sah seinen eben gewählten Eintrag nicht mehr — das Wählen baut den Dialog neu auf, und der Baum ist danach ein anderes Element. Liegt die gewählte Zeile trotzdem ausserhalb, wird sie hereingeholt. Eine neue Suche und ein frisch geöffneter Dialog fangen weiterhin oben an\n* Beim Quellentausch zählt ein Schreibziel nicht mehr, wenn es mit der Lesequelle zusammenfällt. Die Suche probiert als letzte Form den blossen Punktnamen, und `cmnd.POWER` fand so einen Melder, der hinten auch `POWER` heisst — der Alias hätte danach auf seine eigene Lesequelle geschrieben. Beim Raten wurde das abgefangen, beim Pfadtreffer nicht; sichtbar wurde es, wenn man als neue Quelle einen Unterknoten statt des Geräts wählte\n* Beim Quellentausch hält ein Punkt, der nicht mitziehen kann, den Tausch jetzt auf, statt ihn mittendrin scheitern zu lassen. Ein Punkt mit getrennten Quellen — liest aus `stat.POWER`, schreibt nach `cmnd.POWER` — braucht an der neuen Quelle beides. Fehlt das Schreibziel, gibt es in ioBroker **keine** Form, die „liest, schreibt nirgendwohin\" ausdrückt: eine blosse Kennung heisst „schreib auf den Melder\", `{read: X}` ohne `write` weist der js-controller ab, und `common.write: false` schützt die Quelle nicht (gemessen: ein Schreibvorgang darauf hat die Lesequelle überschrieben). Deshalb entscheidet jetzt der Nutzer — das Kästchen „diesen Punkt beim Tauschen entfernen\" steht auch in diesem Fall da, und „Jetzt tauschen\" bleibt gesperrt, solange niemand entschieden hat; der Grund steht am Knopf und als Zeile im Dialog. Vorher lief der Tausch los, scheiterte am Controller und liess den Alias halb auf der alten und halb auf der neuen Quelle zurück\n* Schlägt beim Tauschen ein Schreibvorgang fehl, wird **nichts** gelöscht. Bisher liefen die Löschungen trotzdem, und an einem Alias, der noch halb umgestellt war, fehlten danach auch noch Punkte. Dieselbe Regel gilt beim Verlegen längst\n* „Alle Datenpunkte des Geräts\" verschiebt den Ablageort nicht mehr. Bei einem Gerät mit mehreren Ausgängen legt die Werkbank einen Ordner an und darin je Ausgang einen Kanal. Der Knopf baut den Entwurf neu auf und gab ihm dabei nur das **fertige Ziel** mit; `setzeZiel` liest dessen letztes Segment als Gerätenamen — bei mehreren Ausgängen ist das aber der Ausgang, und er landete zusätzlich im Ordner. Jeder Druck schob den Ablageort eine Ebene tiefer, und geschrieben wurde er auch so: nach drei Klicks entstanden vier Ordner statt einem (`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`). Jetzt gibt der Knopf Ordner und Namen getrennt weiter, wie es der Ausgangswechsel daneben seit jeher tut. Bei einem Gerät mit einem Ausgang trat es nie auf",
22
+ "ru": "* Четыре пункта из полного тестового прогона. **Идентификатор канала** не очищался в пути с несколькими выходами: из имени канала «Licht, Bar» js-controller молча делал `Licht_ Bar`, тогда как верстак показывал «Licht, Bar» и записывал это в перечисления — идентификатор, которого никогда не существовало, и после удаления алиаса он оставался там мусором. Теперь `ausgangName` очищает имя сам, а если два канала дают одно и то же имя, второй получает `_2`. **Подпись** различалась в двух представлениях: там, где имя точки совпадает с именем строки, «Изменить алиас» показывал его, а «Создать алиас» — пустое поле. **Список строк** теперь считает как дерево — `POWER2` перед `POWER10`. И **перечисление, созданное самим верстаком**, теперь исчезает и тогда, когда пустеет из-за смены функции, а не только при удалении алиаса\n* Уборка: «превратить объект алиаса в строку черновика» было написано пять раз — каждый раз с тем же правилом источника записи и слегка разным окружением. Четыре ошибки этой версии происходили именно оттуда: потерянный источник записи у рольставни, переключаемая точка, ставшая доступной только для чтения, отсутствующая подпись у `alias.0.Solar.Netz` и расхождение, которое верстак создал сам. Теперь чтение живёт в одном месте; что с ним делают четыре вызывающие стороны — сравнивают, создают, перезаписывают — остаётся за ними. Поведение не изменилось\n* Три мелочи, замеченные во время прогона. **RSSI** был предварительно отмечен в пяти шаблонах Tasmota и измерительных точек, но не в одиннадцати шаблонах Homematic — одно и то же свойство устройства, два ответа в зависимости от производителя; теперь он снят везде, как и остальная диагностика. **Место `MAP_URL`** в шаблоне пылесоса не получало роли, потому что его выражение начинается без `^`, а вывод требовал обоих якорей; отсутствие начального якоря больше не идёт в минус месту. **А метка «предположено»** в диалоге замены выглядела как текст, приклеенный к имени точки — её оформление опиралось на три родительских уровня, которых там нет. Теперь это такая же пилюля, как в списке состояний, и в подсказке сказано, по имени точки или по роли сделано предположение\n* Кнопка сохранения в диалоге шаблонов теперь проверяет и при нажатии, а не только при отрисовке. Она переоценивается при выходе из поля — кто вписывал открывающую скобку в подсказку имени и без промежуточного шага нажимал «Сохранить шаблон», видел перед собой синюю кнопку и сохранял шаблон с испорченным выражением. Пять причин блокировки теперь лежат в одном месте, общем для отрисовки и сохранения\n* Три места теперь говорят, почему они не могут. **Кнопка сохранения в диалоге шаблонов** была серой и молчала — заблокировать её могут пять причин, и ни одна не показывалась; теперь все подходящие стоят у кнопки и в виде рамки в диалоге. **Диалог ошибок при удалении** называл только число («1 операций не удалось»), а не то, какой идентификатор застрял; при записи такой список был давно. **А причина, по которой не удалось создать точку отправки**, висела на кнопке, которую тот же обратный вызов выбрасывал через 120 мс — теперь она стоит вверху пробного прогона и переживает его перестроение\n* Если тип точки не подходит к её месту в образце, об этом теперь говорят все три места, а не только развёрнутая строка. Если место было **обязательным**, образец перестаёт действовать вовсе, и весь список стоял подсвеченным: на Bastelzimmer_Licht хватило смены SET с `boolean` на `mixed`, и восемь строк из восьми считались «без места», тогда как поле образца сообщало «✕ SET отсутствует» — а SET был на месте. Теперь там написано «✕ SET: тип mixed вместо boolean», а над списком: «Образец света сейчас не действует: SET требует boolean, а установлено mixed. Поэтому ни у одной строки нет места.» Подсвечивается при этом только та строка, из-за которой всё висит — раньше загорался весь список, и подсветка показывала следствие вместо причины.\n* Поздний ответ на `system.config` теперь действительно переносит режим эксперта. Вкладка сдаётся через 2,5 секунды и работает дальше с языком браузера; если ответ приходит позже, язык остаётся как есть (переключение после отрисовки подписей было бы хуже), режим эксперта перенимается, а дерево один раз перерисовывается. Всё это было построено давно — но над ним сидел сторож из прежних времён, который выходил именно в этом случае. Без режима отсутствовали все узлы под `system.*` и `enum.*`, и нигде не было сказано почему\n* Диалог замены замечает, когда уровнем выше подходит лучше. Выбор позволяет взять любой узел, под которым есть точки данных — иначе нельзя, потому что у плоского адаптера канал и есть устройство. Но у MQTT `stat`, `tele` и `cmnd` — это папки тем: кто попадёт туда, найдёт меньше точек, и блокировка предложит какие-то удалить. Теперь верстак считает и родительский уровень и говорит об этом — «Уровнем выше (…) цель находят 7 из 7 точек, здесь только 5» — с кнопкой, которая переключает выбор. Ничего не запрещается\n* Список устройств в диалоге замены остаётся там, где стоял. Кто прокручивал длинный список вниз и щёлкал по устройству, оказывался снова в начале и не видел только что выбранную запись — выбор перестраивает диалог, и дерево после этого другой элемент. Если выбранная строка всё же оказывается за пределами, её подводят в поле зрения. Новый поиск и только что открытый диалог по-прежнему начинаются сверху\n* При замене источника цель записи больше не засчитывается, если она совпадает с источником чтения. Поиск пробует последней формой голое имя точки, и `cmnd.POWER` находил так точку состояния, которая сзади тоже зовётся `POWER` — алиас после этого писал бы в собственный источник чтения. При угадывании это перехватывалось, при совпадении по пути — нет; становилось видно, если новым источником выбирали подузел вместо устройства\n* При замене источника точка, которая не может переехать, теперь останавливает замену, а не даёт ей сорваться на середине. Точке с раздельными источниками — читает из `stat.POWER`, пишет в `cmnd.POWER` — на новом источнике нужно и то и другое. Если цели записи нет, в ioBroker **нет** формы, которая означала бы «читает, не пишет никуда»: голый идентификатор значит «пиши в точку состояния», `{read: X}` без `write` js-controller отклоняет, а `common.write: false` источник не защищает (измерено: запись в такой алиас перезаписала источник чтения). Поэтому решает пользователь — галочка «удалить эту точку при замене» теперь стоит и в этом случае, а «Заменить сейчас» остаётся заблокированной, пока никто не решил; причина видна у кнопки и строкой в диалоге. Раньше замена стартовала, срывалась на контроллере и оставляла алиас наполовину на старом, наполовину на новом источнике\n* Если при замене срывается запись, **ничего** не удаляется. Раньше удаления шли всё равно, и у алиаса, переведённого лишь наполовину, вдобавок пропадали точки. При переносе это правило действует уже давно\n* «Все точки данных устройства» больше не сдвигает место хранения. Для устройства с несколькими выходами верстак создаёт папку, а в ней по каналу на каждый выход. Кнопка перестраивает черновик и передавала при этом только **готовую цель**; `setzeZiel` читает её последний сегмент как имя устройства — но при нескольких выходах это выход, и он дополнительно попадал в папку. Каждое нажатие сдвигало место хранения на уровень глубже, и так же оно записывалось: после трёх щелчков возникали четыре папки вместо одной (`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`). Теперь кнопка передаёт папку и имя по отдельности, как это давно делает переключатель выходов рядом. У устройства с одним выходом такого не случалось никогда",
23
+ "pt": "* Quatro coisas vindas da execução de teste completa. **Um identificador de canal** não era limpo no caminho de várias saídas: do nome de canal «Licht, Bar» o js-controller fazia silenciosamente `Licht_ Bar`, enquanto a bancada mostrava «Licht, Bar» e o inscrevia nas enumerações — um identificador que nunca existiu, e depois de apagar o alias ele ficava lá como resto. Agora `ausgangName` limpa por si, e onde dois canais dão o mesmo nome o segundo recebe um `_2`. **A legenda** diferia nas duas vistas: onde o nome do ponto é igual ao nome da linha, «Editar alias» mostrava-o e «Criar alias» deixava o campo vazio. **A lista de linhas** conta agora como a árvore — `POWER2` antes de `POWER10`. E **uma enumeração criada pela própria bancada** também desaparece quando fica vazia por uma mudança de função, e não só ao apagar o alias\n* Arrumação: «transformar um objeto alias numa linha de rascunho» estava escrito cinco vezes — de cada vez com a mesma regra de fonte de escrita e um enquadramento ligeiramente diferente. Quatro erros desta versão vinham exatamente daí: a fonte de escrita perdida no estore, um ponto comutável que passou a ser só de leitura, a legenda em falta em `alias.0.Solar.Netz` e um desvio que a bancada tinha produzido ela mesma. A leitura vive agora num único sítio; o que os quatro chamadores fazem com ela — comparar, criar, sobrescrever — fica com eles. O comportamento não muda\n* Três pequenas coisas notadas durante a execução. **RSSI** estava pré-marcado nos cinco modelos Tasmota e de pontos de medição, mas não nos onze modelos Homematic — a mesma característica do aparelho, duas respostas conforme o fabricante; agora está desmarcado em todo o lado, como o resto do diagnóstico. **O lugar `MAP_URL`** no padrão do aspirador não recebia papel porque a sua expressão começa sem `^` e a dedução exigia ambas as âncoras; a âncora inicial em falta já não conta contra o lugar. **E a marca «suposto»** no diálogo de troca parecia texto colado ao nome do ponto — a sua forma dependia de três níveis superiores que ali não existem. Agora é uma pastilha como na lista de estados e diz na dica se a suposição veio do nome do ponto ou do papel\n* O botão de guardar no diálogo de modelos verifica agora também ao ser premido, não só ao ser desenhado. É reavaliado ao sair de um campo — quem escrevia um parêntese aberto na dica de nome e clicava diretamente em «Guardar modelo» tinha à frente um botão azul e guardava um modelo com uma expressão partida. Os cinco motivos de bloqueio vivem agora num único sítio partilhado pelo desenho e pelo guardar\n* Três sítios dizem agora porque não conseguem. **O botão de guardar no diálogo de modelos** estava cinzento e calado — cinco motivos podem bloqueá-lo e nenhum era indicado; agora todos os aplicáveis aparecem no botão e como caixa no diálogo. **O diálogo de erro ao apagar** dava apenas um número («1 operações falharam») e não qual o identificador preso; na escrita essa lista já existia há muito. **E o motivo por que um ponto de envio não pôde ser criado** estava pendurado num botão que a mesma chamada de retorno deitava fora 120 ms depois — agora fica no topo da simulação e sobrevive à sua reconstrução\n* Se o tipo de um ponto não combina com o seu lugar no padrão, agora dizem-no os três sítios — e não só a linha aberta. Se o lugar era **obrigatório**, o padrão deixa de se aplicar por completo, e a lista inteira ficava tingida: no Bastelzimmer_Licht bastava mudar SET de `boolean` para `mixed` para que oito de oito linhas contassem como «sem lugar», enquanto o campo do padrão dizia «✕ SET em falta» — mas SET estava lá. Agora lê-se «✕ SET: tipo mixed em vez de boolean» e, por cima da lista: «O padrão de luz não se aplica neste momento: SET exige boolean, está definido mixed. Por isso nenhuma linha tem lugar.» Tinge-se apenas a linha de que depende — antes acendia-se a lista toda, e assim o tom mostrava a consequência em vez da causa.\n* Uma resposta tardia a `system.config` passa agora mesmo o modo perito. O separador desiste ao fim de 2,5 segundos e continua com a língua do navegador; se a resposta chegar depois, a língua fica como está (mudar depois das etiquetas seria pior), o modo perito é adotado e a árvore é redesenhada uma vez. Isso estava construído há muito — mas por cima estava um guarda de outros tempos, que saía exatamente neste caso. Sem o modo faltavam todos os nós sob `system.*` e `enum.*`, sem que em lado nenhum se dissesse porquê\n* O diálogo de troca repara quando um nível acima assenta melhor. O seletor deixa escolher qualquer nó sob o qual haja pontos de dados — tem de ser assim, porque num adaptador plano o canal é o aparelho. Com MQTT, porém, `stat`, `tele` e `cmnd` são pastas de tópicos: quem aterra ali encontra menos pontos, e o bloqueio pediria para remover alguns. A bancada calcula agora também o nível superior e di-lo — «Um nível acima (…) 7 de 7 pontos encontram destino, aqui só 5» — com um botão que muda a escolha. Nada é proibido\n* A lista de aparelhos no diálogo de troca fica onde estava. Quem descia numa lista longa e clicava num aparelho voltava ao início e já não via a entrada acabada de escolher — escolher reconstrói o diálogo, e a árvore passa a ser outro elemento. Se a linha selecionada ficar mesmo assim de fora, é trazida à vista. Uma nova pesquisa e um diálogo acabado de abrir continuam a começar em cima\n* Na troca da fonte, um destino de escrita já não conta se coincidir com a fonte de leitura. A procura tenta como última forma o nome nu do ponto, e `cmnd.POWER` encontrava assim um ponto de estado que também acaba em `POWER` — o alias teria depois escrito na sua própria fonte de leitura. Ao adivinhar isso era apanhado, na correspondência por caminho não; via-se quando como nova fonte se escolhia um subnó em vez do aparelho\n* Na troca da fonte, um ponto que não pode acompanhar trava agora a troca em vez de a deixar falhar a meio. Um ponto com fontes separadas — lê de `stat.POWER`, escreve em `cmnd.POWER` — precisa de ambas na nova fonte. Se faltar o destino de escrita, o ioBroker **não** tem forma que exprima «lê, não escreve em lado nenhum»: um identificador nu significa «escreve no ponto de estado», `{read: X}` sem `write` é recusado pelo js-controller, e `common.write: false` não protege a fonte (medido: escrever num tal alias sobrescreveu a fonte de leitura). Por isso decide o utilizador — a caixa «remover este ponto ao trocar» aparece também neste caso, e «Trocar agora» fica bloqueado enquanto ninguém decidir; o motivo consta no botão e como linha no diálogo. Antes a troca arrancava, falhava no controlador e deixava o alias metade na fonte antiga e metade na nova\n* Se durante a troca uma escrita falhar, **nada** é apagado. Até agora as eliminações corriam à mesma, e a um alias convertido só até meio faltavam ainda pontos. Na mudança de sítio essa regra vale há muito\n* «Todos os pontos de dados do aparelho» já não desloca o local de arrumação. Para um aparelho com várias saídas a bancada cria uma pasta e, dentro dela, um canal por saída. O botão reconstrói o rascunho e passava-lhe apenas o **destino pronto**; `setzeZiel` lê o seu último segmento como nome do aparelho — mas com várias saídas esse segmento é a saída, e ia parar também à pasta. Cada pressão empurrava o local um nível mais fundo, e assim era também escrito: após três cliques nasciam quatro pastas em vez de uma (`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`). O botão passa agora pasta e nome em separado, como o seletor de saída ao lado sempre fez. Num aparelho com uma só saída isto nunca aconteceu",
24
+ "nl": "* Vier dingen uit de volledige testronde. **Een kanaalidentificatie** werd in het pad met meerdere uitgangen niet opgeschoond: van de kanaalnaam «Licht, Bar» maakte de js-controller stilletjes `Licht_ Bar`, terwijl de werkbank «Licht, Bar» toonde en het in de opsommingen schreef — een identificatie die nooit bestaan heeft, en na het wissen van de alias bleef ze daar als restant staan. Nu schoont `ausgangName` zelf op, en waar twee kanalen dezelfde naam opleveren, krijgt de tweede een `_2`. **Het opschrift** verschilde tussen de twee weergaven: waar de naam van het punt gelijk is aan de rijnaam, toonde «Alias bewerken» hem en «Alias aanmaken» een leeg veld. **De rijenlijst** telt nu als de boom — `POWER2` vóór `POWER10`. En **een opsomming die de werkbank zelf heeft aangelegd** verdwijnt nu ook wanneer ze door een functiewissel leeg raakt, niet alleen bij het wissen van de alias\n* Opgeruimd: «van een aliasobject een ontwerpregel maken» stond vijf keer uitgeschreven — telkens met dezelfde schrijfbronregel en een iets andere omgeving. Vier fouten van deze versie kwamen precies daarvandaan: de verloren schrijfbron bij het rolluik, een schakelend punt dat lezend werd, het ontbrekende opschrift bij `alias.0.Solar.Netz` en een afwijking die de werkbank zelf had gemaakt. Het uitlezen staat nu op één plek; wat de vier aanroepers ermee doen — vergelijken, aanmaken, overschrijven — blijft bij hen. Aan het gedrag verandert niets\n* Drie kleinigheden die tijdens de ronde opvielen. **RSSI** stond in de vijf Tasmota- en meetpuntsjablonen vooraf aangevinkt, in de elf Homematic-sjablonen niet — dezelfde apparaateigenschap, twee antwoorden naargelang de fabrikant; nu is het overal uitgevinkt, zoals de rest van de diagnose. **De plek `MAP_URL`** in het stofzuigerpatroon kreeg geen rol omdat de uitdrukking zonder `^` begint en de afleiding beide ankers eiste; het ontbrekende beginanker telt niet meer tegen de plek. **En het merkteken «vermoed»** in het wisseldialoogvenster zag eruit als tekst die aan de puntnaam plakt — de vormgeving hing aan drie ouderniveaus die daar niet bestaan. Het is nu een pil zoals in de toestandenlijst en zegt in de tooltip of er via de puntnaam of via de rol geraden is\n* De opslaanknop in het sjabloondialoogvenster controleert nu ook bij het indrukken, niet alleen bij het tekenen. Hij wordt opnieuw beoordeeld bij het verlaten van een veld — wie een openende haak in de naamhint schreef en meteen op «Sjabloon opslaan» klikte, had een blauwe knop voor zich en sloeg een sjabloon met een kapotte uitdrukking op. De vijf blokkeerredenen staan daarvoor nu op één plek, gedeeld door tekenen en opslaan\n* Drie plekken zeggen nu waarom ze niet kunnen. **De opslaanknop in het sjabloondialoogvenster** was grijs en zweeg — vijf redenen kunnen hem blokkeren en geen ervan werd getoond; nu staan alle toepasselijke bij de knop en als kader in het dialoogvenster. **Het foutdialoogvenster bij het wissen** noemde alleen een aantal («1 bewerkingen mislukt») en niet welke identificatie vastzit; bij het schrijven bestond die lijst al lang. **En de reden waarom een zendpunt niet kon worden aangemaakt** hing aan een knop die dezelfde callback 120 ms later weggooide — ze staat nu bovenaan de proefdraai en overleeft de heropbouw\n* Past het type van een punt niet bij zijn plek in het patroon, dan zeggen alle drie de plekken dat nu — en niet meer alleen de uitgeklapte rij. Was de plek **verplicht**, dan grijpt het patroon helemaal niet meer, en stond de hele lijst getint: bij de Bastelzimmer_Licht volstond het SET van `boolean` op `mixed` te zetten, en acht van de acht rijen golden als «zonder plek», terwijl het patroonveld «✕ SET ontbreekt» meldde — SET was er wel degelijk. Nu staat er «✕ SET: type mixed in plaats van boolean», en boven de lijst: «Het lichtpatroon grijpt momenteel niet: SET vereist boolean, ingesteld is mixed. Daarom heeft geen enkele rij een plek.» Getint wordt daarbij alleen de rij waar het aan ligt — vroeger lichtte de hele lijst op, en zo toonde de tint het gevolg in plaats van de oorzaak.\n* Een laat antwoord op `system.config` neemt de expertmodus nu werkelijk over. Het tabblad geeft het na 2,5 seconden op en werkt verder met de browsertaal; komt het antwoord daarna, dan blijft de taal staan (een sprong na het benoemen zou erger zijn), de expertmodus wordt overgenomen en de boom wordt eenmaal opnieuw getekend. Dat was allang gebouwd — alleen zat er nog een wachter uit de tijd daarvóór boven, die er juist in dit geval uitstapte. Zonder de modus ontbraken alle knopen onder `system.*` en `enum.*`, zonder dat ergens stond waarom\n* Het wisseldialoogvenster merkt wanneer een niveau hoger beter past. De keuzeboom laat elke knoop kiezen waaronder datapunten hangen — dat moet, want bij een platte adapter is het kanaal het apparaat. Bij MQTT zijn `stat`, `tele` en `cmnd` echter onderwerpmappen: wie daar belandt, vindt minder punten terug, en de vergrendeling zou vragen er enkele te verwijderen. De werkbank rekent nu ook het ouderniveau mee en zegt het — «Eén niveau hoger (…) vinden 7 van de 7 punten een doel, hier maar 5» — met een knop die de keuze omzet. Verboden wordt niets\n* De apparatenlijst in het wisseldialoogvenster blijft staan waar ze stond. Wie in een lange lijst naar beneden scrolde en een apparaat aanklikte, kwam daarna weer bovenaan uit en zag het zojuist gekozen item niet meer — kiezen bouwt het dialoogvenster opnieuw op, en de boom is daarna een ander element. Ligt de gekozen rij toch buiten beeld, dan wordt ze in beeld gehaald. Een nieuwe zoekopdracht en een net geopend dialoogvenster beginnen nog steeds bovenaan\n* Bij het wisselen van bron telt een schrijfdoel niet meer mee als het samenvalt met de leesbron. De zoektocht probeert als laatste vorm de kale puntnaam, en `cmnd.POWER` vond zo een statuspunt dat achteraan ook `POWER` heet — de alias zou daarna op zijn eigen leesbron hebben geschreven. Bij het raden werd dat opgevangen, bij een padtreffer niet; het werd zichtbaar wanneer men als nieuwe bron een onderknoop in plaats van het apparaat koos\n* Bij het wisselen van bron houdt een punt dat niet mee kan de wissel nu tegen, in plaats van hem halverwege te laten mislukken. Een punt met gescheiden bronnen — leest uit `stat.POWER`, schrijft naar `cmnd.POWER` — heeft bij de nieuwe bron beide nodig. Ontbreekt het schrijfdoel, dan kent ioBroker **geen** vorm die «leest, schrijft nergens heen» uitdrukt: een kale identificatie betekent «schrijf op het statuspunt», `{read: X}` zonder `write` wijst de js-controller af, en `common.write: false` beschermt de bron niet (gemeten: een schrijfactie daarop overschreef de leesbron). Daarom beslist nu de gebruiker — het vakje «dit punt bij het wisselen verwijderen» staat er ook in dit geval, en «Nu wisselen» blijft geblokkeerd zolang niemand beslist heeft; de reden staat bij de knop en als regel in het dialoogvenster. Voorheen startte de wissel, mislukte bij de controller en liet de alias half op de oude en half op de nieuwe bron achter\n* Mislukt tijdens het wisselen een schrijfactie, dan wordt er **niets** gewist. Tot nu toe liepen de verwijderingen toch door, en bij een alias die pas half was omgezet ontbraken daarna ook nog punten. Bij het verplaatsen geldt die regel al lang\n* «Alle datapunten van het apparaat» verschuift de bergplaats niet meer. Bij een apparaat met meerdere uitgangen legt de werkbank een map aan en daarin per uitgang een kanaal. De knop bouwt het ontwerp opnieuw op en gaf het daarbij alleen het **kant-en-klare doel** mee; `setzeZiel` leest het laatste segment daarvan als apparaatnaam — bij meerdere uitgangen is dat echter de uitgang, en die belandde ook nog in de map. Elke druk schoof de bergplaats een niveau dieper, en zo werd ze ook geschreven: na drie klikken ontstonden vier mappen in plaats van één (`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`). De knop geeft map en naam nu apart door, zoals de uitgangskeuze ernaast dat altijd al deed. Bij een apparaat met één uitgang trad het nooit op",
25
+ "fr": "* Quatre choses issues du parcours de test complet. **Un identifiant de canal** n'était pas nettoyé dans le chemin à sorties multiples : à partir du nom de canal « Licht, Bar », le js-controller faisait silencieusement `Licht_ Bar`, alors que l'établi affichait « Licht, Bar » et l'inscrivait dans les énumérations — un identifiant qui n'a jamais existé, et après la suppression de l'alias il y restait comme résidu. Désormais `ausgangName` nettoie lui-même, et là où deux canaux donnent le même nom, le second reçoit un `_2`. **Le libellé** différait entre les deux vues : là où le nom du point est identique au nom de la ligne, « Modifier l'alias » l'affichait et « Créer un alias » montrait un champ vide. **La liste des lignes** compte maintenant comme l'arbre — `POWER2` avant `POWER10`. Et **une énumération créée par l'établi lui-même** disparaît aussi lorsqu'elle se vide par un changement de fonction, et non plus seulement à la suppression de l'alias\n* Rangement : « transformer un objet alias en ligne de brouillon » était écrit cinq fois — chaque fois avec la même règle de source d'écriture et un entourage légèrement différent. Quatre bogues de cette version venaient précisément de là : la source d'écriture perdue sur le volet roulant, un point commutable devenu point de lecture, le libellé manquant sur `alias.0.Solar.Netz` et un écart que l'établi avait produit lui-même. La lecture vit désormais à un seul endroit ; ce que les quatre appelants en font — comparer, créer, écraser — leur reste. Le comportement est inchangé\n* Trois petites choses repérées pendant le parcours. **RSSI** était coché d'avance dans les cinq modèles Tasmota et points de mesure, mais pas dans les onze modèles Homematic — la même propriété d'appareil, deux réponses selon le fabricant ; il est maintenant décoché partout, comme le reste du diagnostic. **L'emplacement `MAP_URL`** du motif aspirateur n'obtenait aucun rôle parce que son expression commence sans `^` et que la déduction exigeait les deux ancres ; l'ancre de début manquante ne compte plus contre l'emplacement. **Et la marque « supposé »** dans la boîte de dialogue d'échange ressemblait à du texte collé au nom du point — sa mise en forme dépendait de trois niveaux parents qui n'existent pas là. C'est désormais une pastille comme dans la liste d'états, et l'infobulle indique si la supposition vient du nom du point ou du rôle\n* Le bouton d'enregistrement de la boîte de dialogue des modèles vérifie maintenant aussi à l'appui, et pas seulement au dessin. Il est réévalué quand on quitte un champ — qui écrivait une parenthèse ouvrante dans l'indice de nom et cliquait directement sur « Enregistrer le modèle » avait devant lui un bouton bleu et enregistrait un modèle avec une expression cassée. Les cinq motifs de blocage vivent désormais à un seul endroit, partagé par le dessin et l'enregistrement\n* Trois endroits disent maintenant pourquoi ils ne peuvent pas. **Le bouton d'enregistrement de la boîte de dialogue des modèles** était grisé et muet — cinq motifs peuvent le bloquer et aucun n'était indiqué ; tous ceux qui s'appliquent figurent à présent sur le bouton et dans un encadré du dialogue. **La boîte d'erreur à la suppression** ne donnait qu'un nombre (« 1 opérations ont échoué ») et non l'identifiant bloqué ; à l'écriture, cette liste existait depuis longtemps. **Et la raison pour laquelle un point d'envoi n'a pas pu être créé** pendait à un bouton que le même rappel jetait 120 ms plus tard — elle se trouve maintenant en haut de l'essai à blanc et survit à sa reconstruction\n* Si le type d'un point ne correspond pas à son emplacement dans le motif, les trois endroits le disent désormais — et plus seulement la ligne dépliée. Si l'emplacement était **obligatoire**, le motif ne s'applique plus du tout, et toute la liste apparaissait teintée : sur le Bastelzimmer_Licht, il suffisait de passer SET de `boolean` à `mixed` pour que huit lignes sur huit comptent comme « sans emplacement », tandis que le champ du motif signalait « ✕ SET manquant » — alors que SET était bien là. On lit maintenant « ✕ SET : type mixed au lieu de boolean », et au-dessus de la liste : « Le motif lumière ne s'applique pas actuellement : SET exige boolean, mixed est réglé. C'est pourquoi aucune ligne n'a d'emplacement. » Seule la ligne en cause est teintée — auparavant toute la liste s'allumait, ce qui montrait la conséquence au lieu de la cause.\n* Une réponse tardive à `system.config` reporte maintenant vraiment le mode expert. L'onglet abandonne après 2,5 secondes et continue avec la langue du navigateur ; si la réponse arrive ensuite, la langue reste telle quelle (changer après l'étiquetage serait pire), le mode expert est repris et l'arbre est redessiné une fois. Tout cela était construit depuis longtemps — mais au-dessus siégeait un garde d'avant, qui sortait exactement dans ce cas. Sans le mode, tous les nœuds sous `system.*` et `enum.*` manquaient, sans que rien n'en dise la raison\n* La boîte de dialogue d'échange remarque quand un niveau plus haut convient mieux. Le sélecteur laisse choisir n'importe quel nœud sous lequel pendent des points de données — il le faut, car sur un adaptateur plat le canal est l'appareil. Avec MQTT, en revanche, `stat`, `tele` et `cmnd` sont des dossiers de sujets : qui atterrit là retrouve moins de points, et le verrou demanderait d'en retirer. L'établi calcule maintenant aussi le niveau parent et le dit — « Un niveau plus haut (…) 7 points sur 7 trouvent une cible, ici seulement 5 » — avec un bouton qui change la sélection. Rien n'est interdit\n* La liste des appareils dans la boîte de dialogue d'échange reste où elle était. Qui faisait défiler une longue liste et cliquait sur un appareil se retrouvait au début et ne voyait plus l'entrée qu'il venait de choisir — le choix reconstruit le dialogue, et l'arbre est ensuite un autre élément. Si la ligne sélectionnée se retrouve malgré tout en dehors, elle est ramenée dans le champ de vision. Une nouvelle recherche et un dialogue fraîchement ouvert commencent toujours en haut\n* Lors de l'échange de source, une cible d'écriture ne compte plus si elle coïncide avec la source de lecture. La recherche essaie en dernière forme le simple nom du point, et `cmnd.POWER` trouvait ainsi un point d'état qui se termine aussi par `POWER` — l'alias aurait alors écrit dans sa propre source de lecture. À la devinette, c'était intercepté ; à la correspondance par chemin, non ; cela se voyait quand on choisissait comme nouvelle source un sous-nœud au lieu de l'appareil\n* Lors de l'échange de source, un point qui ne peut pas suivre arrête désormais l'échange au lieu de le laisser échouer en cours de route. Un point à sources séparées — lit depuis `stat.POWER`, écrit vers `cmnd.POWER` — a besoin des deux à la nouvelle source. Si la cible d'écriture manque, ioBroker n'a **aucune** forme qui exprime « lit, n'écrit nulle part » : un simple identifiant signifie « écris sur le point d'état », `{read: X}` sans `write` est rejeté par le js-controller, et `common.write: false` ne protège pas la source (mesuré : une écriture sur un tel alias a écrasé la source de lecture). C'est donc l'utilisateur qui décide — la case « retirer ce point lors de l'échange » apparaît aussi dans ce cas, et « Échanger maintenant » reste bloqué tant que personne n'a décidé ; la raison figure sur le bouton et comme ligne dans le dialogue. Auparavant, l'échange démarrait, échouait au contrôleur et laissait l'alias moitié sur l'ancienne, moitié sur la nouvelle source\n* Si une écriture échoue pendant l'échange, **rien** n'est supprimé. Jusqu'ici les suppressions se faisaient quand même, et un alias à moitié migré perdait en plus des points. Pour le déplacement, cette règle vaut depuis longtemps\n* « Tous les points de données de l'appareil » ne déplace plus l'emplacement de rangement. Pour un appareil à plusieurs sorties, l'établi crée un dossier et, dedans, un canal par sortie. Le bouton reconstruit le brouillon et ne lui transmettait que la **cible finie** ; `setzeZiel` lit son dernier segment comme nom d'appareil — mais avec plusieurs sorties, c'est la sortie, et elle atterrissait en plus dans le dossier. Chaque appui poussait l'emplacement d'un niveau plus profond, et c'est ainsi qu'il était écrit : après trois clics, quatre dossiers naissaient au lieu d'un (`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`). Le bouton transmet maintenant le dossier et le nom séparément, comme le fait depuis toujours le sélecteur de sortie à côté. Sur un appareil à une seule sortie, cela n'est jamais arrivé",
26
+ "it": "* Quattro cose emerse dal giro di prova completo. **Un identificativo di canale** non veniva ripulito nel percorso a più uscite: dal nome di canale «Licht, Bar» il js-controller ricavava silenziosamente `Licht_ Bar`, mentre il banco di lavoro mostrava «Licht, Bar» e lo iscriveva nelle enumerazioni — un identificativo che non è mai esistito, e dopo la cancellazione dell'alias restava lì come residuo. Ora `ausgangName` ripulisce da sé, e dove due canali producono lo stesso nome il secondo riceve un `_2`. **La didascalia** era diversa nelle due viste: dove il nome del punto coincide con il nome della riga, «Modifica alias» lo mostrava e «Crea alias» lasciava il campo vuoto. **L'elenco delle righe** ora conta come l'albero — `POWER2` prima di `POWER10`. E **un'enumerazione creata dal banco di lavoro stesso** sparisce anche quando si svuota per un cambio di funzione, non solo alla cancellazione dell'alias\n* Riordino: «da un oggetto alias a una riga di bozza» era scritto cinque volte — ogni volta con la stessa regola della sorgente di scrittura e un contorno leggermente diverso. Quattro errori di questa versione venivano proprio da lì: la sorgente di scrittura persa sulla tapparella, un punto commutabile diventato di sola lettura, la didascalia mancante su `alias.0.Solar.Netz` e uno scostamento che il banco di lavoro aveva prodotto da sé. La lettura ora vive in un solo posto; ciò che i quattro chiamanti ne fanno — confrontare, creare, sovrascrivere — resta a loro. Il comportamento non cambia\n* Tre piccolezze notate durante il giro. **RSSI** era spuntato in anticipo nei cinque modelli Tasmota e dei punti di misura, ma non negli undici modelli Homematic — la stessa caratteristica del dispositivo, due risposte a seconda del produttore; ora è deselezionato ovunque, come il resto della diagnostica. **Il posto `MAP_URL`** nello schema aspirapolvere non riceveva alcun ruolo perché la sua espressione inizia senza `^` e la deduzione pretendeva entrambe le ancore; l'ancora iniziale mancante non conta più contro il posto. **E il contrassegno «supposto»** nella finestra di scambio sembrava testo incollato al nome del punto — la sua forma dipendeva da tre livelli superiori che lì non esistono. Ora è una pillola come nell'elenco degli stati e nel suggerimento dice se la supposizione viene dal nome del punto o dal ruolo\n* Il pulsante di salvataggio nella finestra dei modelli ora controlla anche alla pressione, non solo al disegno. Viene rivalutato quando si lascia un campo — chi scriveva una parentesi aperta nel suggerimento di nome e cliccava direttamente su «Salva modello» si trovava davanti un pulsante blu e salvava un modello con un'espressione rotta. I cinque motivi di blocco stanno ora in un unico posto, condiviso da disegno e salvataggio\n* Tre punti dicono ora perché non possono. **Il pulsante di salvataggio nella finestra dei modelli** era grigio e muto — cinque motivi possono bloccarlo e nessuno era indicato; ora tutti quelli applicabili compaiono sul pulsante e come riquadro nella finestra. **La finestra di errore alla cancellazione** dava solo un numero («1 operazioni non riuscite») e non quale identificativo fosse bloccato; in scrittura quell'elenco c'era da tempo. **E il motivo per cui un punto di invio non è stato creato** era appeso a un pulsante che la stessa callback buttava via 120 ms dopo — ora sta in cima alla prova a vuoto e sopravvive alla sua ricostruzione\n* Se il tipo di un punto non si adatta al suo posto nello schema, ora lo dicono tutti e tre i posti — non più solo la riga aperta. Se il posto era **obbligatorio**, lo schema non si applica più affatto, e l'intero elenco appariva colorato: sul Bastelzimmer_Licht bastava cambiare SET da `boolean` a `mixed` perché otto righe su otto valessero come «senza posto», mentre il campo dello schema segnalava «✕ SET manca» — ma SET c'era. Ora si legge «✕ SET: tipo mixed invece di boolean», e sopra l'elenco: «Lo schema luce al momento non si applica: SET richiede boolean, è impostato mixed. Per questo nessuna riga ha un posto.» Viene colorata solo la riga da cui dipende — prima si illuminava tutto l'elenco, e così la colorazione mostrava la conseguenza invece della causa.\n* Una risposta tardiva a `system.config` ora riporta davvero la modalità esperto. La scheda si arrende dopo 2,5 secondi e prosegue con la lingua del browser; se la risposta arriva dopo, la lingua resta com'è (cambiarla dopo le etichette sarebbe peggio), la modalità esperto viene assunta e l'albero ridisegnato una volta. Tutto ciò era costruito da tempo — ma sopra sedeva un guardiano di prima, che usciva esattamente in questo caso. Senza la modalità mancavano tutti i nodi sotto `system.*` ed `enum.*`, senza che da nessuna parte fosse detto perché\n* La finestra di scambio si accorge quando un livello più in alto va meglio. Il selettore lascia scegliere qualsiasi nodo sotto cui pendano punti dati — deve essere così, perché in un adattatore piatto il canale è il dispositivo. Con MQTT, però, `stat`, `tele` e `cmnd` sono cartelle di argomenti: chi finisce lì ritrova meno punti, e il blocco chiederebbe di rimuoverne. Ora il banco di lavoro calcola anche il livello superiore e lo dice — «Un livello più in alto (…) 7 punti su 7 trovano una destinazione, qui solo 5» — con un pulsante che cambia la scelta. Nulla viene vietato\n* L'elenco dei dispositivi nella finestra di scambio resta dov'era. Chi scorreva in basso in un elenco lungo e cliccava un dispositivo si ritrovava di nuovo all'inizio e non vedeva più la voce appena scelta — la scelta ricostruisce la finestra, e l'albero dopo è un altro elemento. Se la riga selezionata finisce comunque fuori, viene riportata in vista. Una nuova ricerca e una finestra appena aperta cominciano ancora dall'alto\n* Nello scambio della sorgente una destinazione di scrittura non conta più se coincide con la sorgente di lettura. La ricerca prova come ultima forma il semplice nome del punto, e `cmnd.POWER` trovava così un punto di stato che in coda si chiama anch'esso `POWER` — l'alias avrebbe poi scritto sulla propria sorgente di lettura. Nell'indovinare veniva intercettato, nella corrispondenza per percorso no; si vedeva quando come nuova sorgente si sceglieva un sottonodo invece del dispositivo\n* Nello scambio della sorgente, un punto che non può seguire ora ferma lo scambio invece di lasciarlo fallire a metà. Un punto con sorgenti separate — legge da `stat.POWER`, scrive su `cmnd.POWER` — alla nuova sorgente ha bisogno di entrambe. Se manca la destinazione di scrittura, in ioBroker **non** esiste forma che esprima «legge, non scrive da nessuna parte»: un identificativo nudo significa «scrivi sul punto di stato», `{read: X}` senza `write` viene respinto dal js-controller, e `common.write: false` non protegge la sorgente (misurato: una scrittura su un tale alias ha sovrascritto la sorgente di lettura). Perciò decide l'utente — la casella «rimuovi questo punto allo scambio» compare anche in questo caso, e «Scambia ora» resta bloccato finché nessuno ha deciso; il motivo sta sul pulsante e come riga nella finestra. Prima lo scambio partiva, falliva al controller e lasciava l'alias metà sulla vecchia e metà sulla nuova sorgente\n* Se durante lo scambio una scrittura fallisce, **non** viene cancellato nulla. Finora le cancellazioni partivano lo stesso, e a un alias già convertito a metà mancavano poi anche dei punti. Nello spostamento questa regola vale da tempo\n* «Tutti i punti dati del dispositivo» non sposta più il luogo di archiviazione. Per un dispositivo con più uscite il banco di lavoro crea una cartella e dentro un canale per ogni uscita. Il pulsante ricostruisce la bozza e le passava solo la **destinazione finita**; `setzeZiel` legge il suo ultimo segmento come nome del dispositivo — con più uscite però quello è l'uscita, e finiva in più nella cartella. Ogni pressione spingeva il luogo di archiviazione un livello più in basso, e così veniva anche scritto: dopo tre clic nascevano quattro cartelle invece di una (`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`). Ora il pulsante passa cartella e nome separatamente, come fa da sempre il selettore di uscita accanto. Su un dispositivo con una sola uscita non è mai successo",
27
+ "es": "* Cuatro cosas salidas del recorrido de prueba completo. **Un identificador de canal** no se depuraba en la ruta de varias salidas: del nombre de canal «Licht, Bar» el js-controller hacía en silencio `Licht_ Bar`, mientras el banco de trabajo mostraba «Licht, Bar» y lo inscribía en las enumeraciones — un identificador que nunca existió, y tras borrar el alias se quedaba allí como resto. Ahora `ausgangName` depura por sí mismo, y donde dos canales dan el mismo nombre, el segundo recibe un `_2`. **El rótulo** difería entre las dos vistas: donde el nombre del punto coincide con el nombre de la fila, «Editar alias» lo mostraba y «Crear alias» dejaba el campo vacío. **La lista de filas** cuenta ahora como el árbol — `POWER2` antes que `POWER10`. Y **una enumeración creada por el propio banco de trabajo** desaparece también cuando se queda vacía por un cambio de función, no solo al borrar el alias\n* Orden: «convertir un objeto alias en una fila de borrador» estaba escrito cinco veces — cada vez con la misma regla de fuente de escritura y un entorno algo distinto. Cuatro fallos de esta versión venían justo de ahí: la fuente de escritura perdida en la persiana, un punto conmutable que pasó a ser de solo lectura, el rótulo ausente en `alias.0.Solar.Netz` y una desviación que el banco de trabajo había producido él mismo. La lectura vive ahora en un solo sitio; lo que los cuatro llamantes hagan con ella — comparar, crear, sobrescribir — queda de su parte. El comportamiento no cambia\n* Tres pequeñeces detectadas durante el recorrido. **RSSI** estaba marcado de antemano en las cinco plantillas de Tasmota y de puntos de medida, pero no en las once de Homematic — la misma característica del aparato, dos respuestas según el fabricante; ahora está desmarcado en todas partes, como el resto del diagnóstico. **El puesto `MAP_URL`** del patrón de aspiradora no recibía rol porque su expresión empieza sin `^` y la deducción exigía ambas anclas; el ancla inicial ausente ya no cuenta en contra del puesto. **Y la marca «supuesto»** en el diálogo de intercambio parecía texto pegado al nombre del punto — su forma dependía de tres niveles superiores que allí no existen. Ahora es una píldora como en la lista de estados y dice en la ayuda emergente si la suposición vino del nombre del punto o del rol\n* El botón de guardar del diálogo de plantillas comprueba ahora también al pulsarlo, no solo al dibujarse. Se reevalúa al abandonar un campo — quien escribía un paréntesis abierto en la pista de nombre y pulsaba directamente «Guardar plantilla» tenía delante un botón azul y guardaba una plantilla con una expresión rota. Los cinco motivos de bloqueo están ahora en un único sitio que comparten dibujo y guardado\n* Tres sitios dicen ahora por qué no pueden. **El botón de guardar del diálogo de plantillas** estaba gris y callado — cinco motivos pueden bloquearlo y ninguno se mostraba; ahora todos los que aplican aparecen en el botón y como recuadro en el diálogo. **El diálogo de error al borrar** solo daba un número («1 operaciones fallaron») y no qué identificador está atascado; al escribir esa lista existía desde hace tiempo. **Y el motivo por el que no se pudo crear un punto de envío** colgaba de un botón que la misma retrollamada tiraba 120 ms después — ahora está arriba en la marcha en seco y sobrevive a su reconstrucción\n* Si el tipo de un punto no encaja con su puesto en el patrón, ahora lo dicen los tres sitios — y no solo la fila desplegada. Si el puesto era **obligatorio**, el patrón deja de aplicarse del todo, y la lista entera aparecía teñida: en el Bastelzimmer_Licht bastaba cambiar SET de `boolean` a `mixed` para que ocho de ocho filas contaran como «sin puesto», mientras el campo del patrón informaba «✕ falta SET» — pero SET estaba ahí. Ahora pone «✕ SET: tipo mixed en lugar de boolean», y sobre la lista: «El patrón de luz no se aplica ahora mismo: SET exige boolean y está puesto mixed. Por eso ninguna fila tiene puesto.» Se tiñe solo la fila de la que depende — antes se encendía la lista entera, y así el tinte mostraba la consecuencia en vez de la causa.\n* Una respuesta tardía a `system.config` traspasa ahora de verdad el modo experto. La pestaña se rinde tras 2,5 segundos y sigue con el idioma del navegador; si la respuesta llega después, el idioma se queda como está (cambiarlo tras rotular sería peor), el modo experto se adopta y el árbol se redibuja una vez. Eso estaba construido desde hacía tiempo — pero encima había un guardián de la época anterior que se salía justo en este caso. Sin el modo faltaban todos los nodos bajo `system.*` y `enum.*`, sin que en ningún sitio se dijera por qué\n* El diálogo de intercambio nota cuándo un nivel más arriba encaja mejor. El selector deja elegir cualquier nodo bajo el que cuelguen puntos de datos — tiene que ser así, porque en un adaptador plano el canal es el aparato. Con MQTT, en cambio, `stat`, `tele` y `cmnd` son carpetas de temas: quien aterriza ahí encuentra menos puntos, y el bloqueo pediría quitar alguno. El banco de trabajo calcula ahora también el nivel superior y lo dice — «Un nivel más arriba (…) 7 de 7 puntos encuentran destino, aquí solo 5» — con un botón que cambia la elección. No se prohíbe nada\n* La lista de aparatos del diálogo de intercambio se queda donde estaba. Quien bajaba por una lista larga y pulsaba un aparato volvía al principio y ya no veía la entrada recién elegida — elegir reconstruye el diálogo, y el árbol es después otro elemento. Si la fila seleccionada queda aun así fuera, se trae a la vista. Una búsqueda nueva y un diálogo recién abierto siguen empezando arriba\n* Al intercambiar la fuente, un destino de escritura ya no cuenta si coincide con la fuente de lectura. La búsqueda prueba como última forma el nombre desnudo del punto, y `cmnd.POWER` encontraba así un punto de estado que también termina en `POWER` — el alias habría escrito luego sobre su propia fuente de lectura. Al adivinar se interceptaba; al coincidir por ruta, no; se veía cuando como nueva fuente se elegía un subnodo en vez del aparato\n* Al intercambiar la fuente, un punto que no puede acompañar detiene ahora el intercambio en vez de dejar que fracase a medias. Un punto con fuentes separadas — lee de `stat.POWER`, escribe en `cmnd.POWER` — necesita ambas en la nueva fuente. Si falta el destino de escritura, en ioBroker **no** hay forma que exprese «lee, no escribe en ninguna parte»: un identificador desnudo significa «escribe en el punto de estado», `{read: X}` sin `write` lo rechaza el js-controller, y `common.write: false` no protege la fuente (medido: escribir en semejante alias sobrescribió la fuente de lectura). Por eso decide el usuario — la casilla «quitar este punto al intercambiar» aparece también en este caso, y «Intercambiar ahora» queda bloqueado mientras nadie haya decidido; el motivo consta en el botón y como línea en el diálogo. Antes el intercambio arrancaba, fracasaba en el controlador y dejaba el alias mitad en la fuente vieja y mitad en la nueva\n* Si durante el intercambio falla una escritura, **no** se borra nada. Hasta ahora los borrados se ejecutaban igualmente, y a un alias convertido a medias le faltaban además puntos. Al trasladar, esa regla rige desde hace tiempo\n* «Todos los puntos de datos del aparato» ya no desplaza el lugar de almacenamiento. Para un aparato con varias salidas el banco de trabajo crea una carpeta y dentro un canal por salida. El botón reconstruye el borrador y le pasaba solo el **destino terminado**; `setzeZiel` lee su último segmento como nombre del aparato — pero con varias salidas ese segmento es la salida, y acababa además en la carpeta. Cada pulsación empujaba el lugar un nivel más hondo, y así se escribía también: tras tres clics nacían cuatro carpetas en vez de una (`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`). Ahora el botón pasa carpeta y nombre por separado, como hace desde siempre el selector de salida de al lado. En un aparato con una sola salida nunca ocurrió",
28
+ "pl": "* Cztery rzeczy z pełnego przebiegu testowego. **Identyfikator kanału** nie był oczyszczany na ścieżce z wieloma wyjściami: z nazwy kanału „Licht, Bar” js-controller po cichu robił `Licht_ Bar`, podczas gdy warsztat pokazywał „Licht, Bar” i wpisywał to do wyliczeń — identyfikator, którego nigdy nie było, a po usunięciu aliasu zostawał tam jako pozostałość. Teraz `ausgangName` oczyszcza sam, a gdy dwa kanały dają tę samą nazwę, drugi dostaje `_2`. **Podpis** różnił się w obu widokach: tam, gdzie nazwa punktu jest równa nazwie wiersza, „Edytuj alias” ją pokazywał, a „Utwórz alias” zostawiał puste pole. **Lista wierszy** liczy teraz jak drzewo — `POWER2` przed `POWER10`. A **wyliczenie założone przez sam warsztat** znika też wtedy, gdy opustoszeje wskutek zmiany funkcji, a nie tylko przy usunięciu aliasu\n* Porządki: „z obiektu aliasu zrób wiersz szkicu” było rozpisane pięć razy — za każdym razem z tą samą regułą źródła zapisu i nieco innym otoczeniem. Cztery błędy tej wersji brały się dokładnie stąd: utracone źródło zapisu przy rolecie, punkt przełączający, który stał się odczytowym, brakujący podpis przy `alias.0.Solar.Netz` i rozbieżność, którą warsztat sam wytworzył. Odczyt mieszka teraz w jednym miejscu; co robią z nim cztery miejsca wywołujące — porównują, zakładają, nadpisują — zostaje po ich stronie. Zachowanie się nie zmienia\n* Trzy drobiazgi zauważone w trakcie przebiegu. **RSSI** był wstępnie zaznaczony w pięciu szablonach Tasmota i punktów pomiarowych, ale nie w jedenastu szablonach Homematic — ta sama cecha urządzenia, dwie odpowiedzi zależnie od producenta; teraz jest wszędzie odznaczony, jak reszta diagnostyki. **Miejsce `MAP_URL`** we wzorcu odkurzacza nie dostawało roli, bo jego wyrażenie zaczyna się bez `^`, a wyprowadzenie wymagało obu kotwic; brakująca kotwica początkowa nie liczy się już przeciw miejscu. **A znacznik „domyślone”** w oknie zamiany wyglądał jak tekst przyklejony do nazwy punktu — jego wygląd wisiał na trzech poziomach nadrzędnych, których tam nie ma. Teraz jest pigułką jak na liście stanów i w podpowiedzi mówi, czy domysł wziął się z nazwy punktu, czy z roli\n* Przycisk zapisu w oknie szablonów sprawdza teraz także przy naciśnięciu, nie tylko przy rysowaniu. Jest ponownie oceniany przy opuszczeniu pola — kto wpisał otwierający nawias w podpowiedź nazwy i bez zwłoki kliknął „Zapisz szablon”, miał przed sobą niebieski przycisk i zapisywał szablon z zepsutym wyrażeniem. Pięć powodów blokady leży teraz w jednym miejscu, wspólnym dla rysowania i zapisu\n* Trzy miejsca mówią teraz, dlaczego nie mogą. **Przycisk zapisu w oknie szablonów** był szary i milczał — zablokować go może pięć powodów i żaden nie był podany; teraz wszystkie pasujące stoją przy przycisku i jako ramka w oknie. **Okno błędu przy usuwaniu** podawało tylko liczbę („1 operacji nie powiodło się”), a nie który identyfikator zawadza; przy zapisie taka lista była od dawna. **A powód, dla którego nie udało się utworzyć punktu wysyłki**, wisiał na przycisku, który to samo wywołanie zwrotne wyrzucało 120 ms później — teraz stoi u góry próby na sucho i przeżywa jej przebudowę\n* Jeśli typ punktu nie pasuje do jego miejsca we wzorcu, mówią to teraz wszystkie trzy miejsca — a nie tylko rozwinięty wiersz. Jeśli miejsce było **obowiązkowe**, wzorzec przestaje działać w ogóle i cała lista stała podbarwiona: przy Bastelzimmer_Licht wystarczyła zmiana SET z `boolean` na `mixed`, by osiem z ośmiu wierszy liczyło się jako „bez miejsca”, podczas gdy pole wzorca meldowało „✕ brak SET” — a SET tam był. Teraz stoi tam „✕ SET: typ mixed zamiast boolean”, a nad listą: „Wzorzec światła w tej chwili nie działa: SET wymaga boolean, ustawione jest mixed. Dlatego żaden wiersz nie ma miejsca.” Podbarwiany jest przy tym tylko ten wiersz, na którym to wisi — wcześniej rozświetlała się cała lista, a więc podbarwienie pokazywało skutek zamiast przyczyny.\n* Późna odpowiedź na `system.config` naprawdę przenosi teraz tryb eksperta. Zakładka poddaje się po 2,5 sekundy i pracuje dalej z językiem przeglądarki; jeśli odpowiedź przyjdzie później, język zostaje, jak jest (skok po opisaniu byłby gorszy), tryb eksperta zostaje przejęty, a drzewo raz przerysowane. To było zbudowane od dawna — tylko nad tym siedział strażnik z czasów wcześniejszych, który wychodził dokładnie w tym przypadku. Bez trybu brakowało wszystkich węzłów pod `system.*` i `enum.*`, a nigdzie nie było powiedziane, dlaczego\n* Okno zamiany zauważa, kiedy poziom wyżej pasuje lepiej. Drzewo wyboru pozwala wybrać każdy węzeł, pod którym wiszą punkty danych — tak być musi, bo przy płaskim adapterze kanał jest urządzeniem. W MQTT `stat`, `tele` i `cmnd` to jednak foldery tematów: kto tam wyląduje, odnajdzie mniej punktów, a blokada poprosi o usunięcie części. Warsztat liczy teraz także poziom nadrzędny i to mówi — „Poziom wyżej (…) cel znajduje 7 z 7 punktów, tutaj tylko 5” — z przyciskiem, który przestawia wybór. Nic nie jest zabronione\n* Lista urządzeń w oknie zamiany zostaje tam, gdzie była. Kto przewinął długą listę w dół i kliknął urządzenie, lądował z powrotem na początku i nie widział właśnie wybranej pozycji — wybór przebudowuje okno, a drzewo jest potem innym elementem. Jeśli wybrany wiersz mimo to wypadnie poza kadr, zostaje przyciągnięty do widoku. Nowe wyszukiwanie i świeżo otwarte okno nadal zaczynają od góry\n* Przy zamianie źródła cel zapisu nie liczy się już, jeśli pokrywa się ze źródłem odczytu. Wyszukiwanie próbuje jako ostatniej formy gołej nazwy punktu i `cmnd.POWER` znajdowało tak punkt stanu, który z tyłu też nazywa się `POWER` — alias pisałby potem na własne źródło odczytu. Przy zgadywaniu było to wyłapywane, przy trafieniu po ścieżce nie; ujawniało się, gdy jako nowe źródło wybrano podwęzeł zamiast urządzenia\n* Przy zamianie źródła punkt, który nie może pójść razem, zatrzymuje teraz zamianę, zamiast dać jej się załamać w połowie. Punkt z rozdzielonymi źródłami — czyta z `stat.POWER`, pisze do `cmnd.POWER` — potrzebuje przy nowym źródle obu. Gdy brakuje celu zapisu, ioBroker **nie** ma postaci, która wyrażałaby „czyta, nie pisze nigdzie”: goły identyfikator znaczy „pisz na punkt stanu”, `{read: X}` bez `write` js-controller odrzuca, a `common.write: false` nie chroni źródła (zmierzone: zapis na taki alias nadpisał źródło odczytu). Dlatego decyduje użytkownik — pole „usuń ten punkt przy zamianie” stoi także w tym przypadku, a „Zamień teraz” pozostaje zablokowane, dopóki nikt nie zdecydował; powód widnieje przy przycisku i jako wiersz w oknie. Wcześniej zamiana ruszała, załamywała się na kontrolerze i zostawiała alias w połowie na starym, a w połowie na nowym źródle\n* Jeśli przy zamianie zapis się nie powiedzie, **nic** nie zostaje usunięte. Dotąd usunięcia szły mimo to, a aliasowi przestawionemu dopiero w połowie brakowało potem jeszcze punktów. Przy przenoszeniu ta reguła obowiązuje od dawna\n* „Wszystkie punkty danych urządzenia” nie przesuwa już miejsca odkładania. Dla urządzenia z wieloma wyjściami warsztat zakłada folder, a w nim po kanale na każde wyjście. Przycisk buduje szkic od nowa i przekazywał mu przy tym tylko **gotowy cel**; `setzeZiel` czyta jego ostatni segment jako nazwę urządzenia — przy wielu wyjściach jest to jednak wyjście i lądowało dodatkowo w folderze. Każde naciśnięcie spychało miejsce odkładania o poziom głębiej i tak też było zapisywane: po trzech kliknięciach powstawały cztery foldery zamiast jednego (`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`). Przycisk przekazuje teraz folder i nazwę osobno, tak jak od zawsze robi to przełącznik wyjść obok. Przy urządzeniu z jednym wyjściem nigdy to nie wystąpiło",
29
+ "uk": "* Чотири пункти з повного тестового прогону. **Ідентифікатор каналу** не очищався на шляху з кількома виходами: з імені каналу «Licht, Bar» js-controller мовчки робив `Licht_ Bar`, тоді як верстак показував «Licht, Bar» і вписував це до переліків — ідентифікатор, якого ніколи не було, і після видалення аліаса він залишався там як сміття. Тепер `ausgangName` очищає сам, а якщо два канали дають однакове ім'я, другий отримує `_2`. **Підпис** відрізнявся у двох поданнях: там, де ім'я точки збігається з іменем рядка, «Редагувати аліас» його показував, а «Створити аліас» лишав поле порожнім. **Список рядків** тепер рахує як дерево — `POWER2` перед `POWER10`. І **перелік, який верстак створив сам**, зникає й тоді, коли порожніє через зміну функції, а не лише при видаленні аліаса\n* Прибирання: «зробити з об'єкта аліаса рядок чернетки» було розписано п'ять разів — щоразу з тим самим правилом джерела запису та дещо іншим обрамленням. Чотири помилки цієї версії походили саме звідти: втрачене джерело запису на ролеті, перемикальна точка, що стала лише читальною, відсутній підпис у `alias.0.Solar.Netz` і розбіжність, яку верстак створив сам. Зчитування тепер живе в одному місці; що з ним роблять чотири викликачі — порівнюють, створюють, перезаписують — лишається за ними. Поведінка не змінилася\n* Три дрібниці, помічені під час прогону. **RSSI** був заздалегідь позначений у п'яти шаблонах Tasmota та точок вимірювання, але не в одинадцяти шаблонах Homematic — та сама властивість пристрою, дві відповіді залежно від виробника; тепер його знято скрізь, як і решту діагностики. **Місце `MAP_URL`** у зразку пилососа не отримувало ролі, бо його вираз починається без `^`, а виведення вимагало обох якорів; відсутній початковий якір більше не рахується проти місця. **А позначка «припущено»** у діалозі заміни виглядала як текст, приклеєний до імені точки — її оформлення трималося на трьох батьківських рівнях, яких там немає. Тепер це така сама пігулка, як у списку станів, і в підказці сказано, чи припущення зроблено за іменем точки, чи за роллю\n* Кнопка збереження в діалозі шаблонів тепер перевіряє й при натисканні, а не лише при малюванні. Її переоцінюють при виході з поля — хто вписував відкриту дужку в підказку імені й одразу тиснув «Зберегти шаблон», мав перед собою синю кнопку і зберігав шаблон із зіпсованим виразом. П'ять причин блокування лежать тепер в одному місці, спільному для малювання і збереження\n* Три місця тепер кажуть, чому вони не можуть. **Кнопка збереження в діалозі шаблонів** була сірою і мовчала — заблокувати її можуть п'ять причин, і жодної не було видно; тепер усі доречні стоять біля кнопки і як рамка в діалозі. **Діалог помилки при видаленні** називав лише число («1 операцій не вдалося»), а не те, який ідентифікатор застряг; при записі такий список був давно. **А причина, чому не вдалося створити точку надсилання**, висіла на кнопці, яку той самий зворотний виклик викидав за 120 мс — тепер вона стоїть угорі пробного прогону і переживає його перебудову\n* Якщо тип точки не пасує до її місця у зразку, про це тепер кажуть усі три місця — а не лише розгорнутий рядок. Якщо місце було **обов'язковим**, зразок перестає діяти зовсім, і весь список стояв підсвіченим: на Bastelzimmer_Licht вистачило змінити SET з `boolean` на `mixed`, і вісім рядків з восьми вважалися «без місця», тоді як поле зразка повідомляло «✕ SET бракує» — а SET був на місці. Тепер там написано «✕ SET: тип mixed замість boolean», а над списком: «Зразок світла зараз не діє: SET вимагає boolean, а встановлено mixed. Тому в жодного рядка немає місця.» Підсвічується при цьому лише той рядок, через який усе стоїть — раніше засвічувався весь список, і підсвітка показувала наслідок замість причини.\n* Пізня відповідь на `system.config` тепер справді переносить режим експерта. Вкладка здається за 2,5 секунди і працює далі з мовою браузера; якщо відповідь приходить пізніше, мова лишається як є (перемикання після підписів було б гірше), режим експерта переймається, а дерево один раз перемальовується. Це було збудовано давно — але над ним сидів вартовий із давніших часів, який виходив саме в цьому випадку. Без режиму бракувало всіх вузлів під `system.*` та `enum.*`, і ніде не було сказано чому\n* Діалог заміни помічає, коли рівнем вище пасує краще. Дерево вибору дозволяє взяти будь-який вузол, під яким висять точки даних — інакше не можна, бо в пласкому адаптері канал і є пристроєм. Але в MQTT `stat`, `tele` і `cmnd` — це теки тем: хто потрапить туди, знайде менше точок, і блокування попросить якісь прибрати. Верстак тепер рахує і батьківський рівень та каже про це — «Рівнем вище (…) ціль знаходять 7 із 7 точок, тут лише 5» — з кнопкою, яка перемикає вибір. Нічого не забороняється\n* Список пристроїв у діалозі заміни лишається там, де стояв. Хто прокручував довгий список униз і клацав пристрій, опинявся знову на початку і не бачив щойно обраного запису — вибір перебудовує діалог, і дерево після цього інший елемент. Якщо обраний рядок усе ж опиняється поза межами, його підводять у поле зору. Новий пошук і щойно відкритий діалог і далі починаються згори\n* При заміні джерела ціль запису більше не зараховується, якщо вона збігається з джерелом читання. Пошук пробує останньою формою голе ім'я точки, і `cmnd.POWER` знаходив так точку стану, яка ззаду теж зветься `POWER` — аліас після цього писав би у власне джерело читання. При вгадуванні це перехоплювалося, при збігу за шляхом — ні; ставало видно, коли новим джерелом обирали підвузол замість пристрою\n* При заміні джерела точка, яка не може перейти, тепер зупиняє заміну, а не дає їй зірватися посередині. Точці з роздільними джерелами — читає з `stat.POWER`, пише в `cmnd.POWER` — на новому джерелі потрібні обидва. Якщо цілі запису немає, в ioBroker **немає** форми, яка означала б «читає, не пише нікуди»: голий ідентифікатор значить «пиши на точку стану», `{read: X}` без `write` js-controller відхиляє, а `common.write: false` джерело не захищає (виміряно: запис у такий аліас перезаписав джерело читання). Тому вирішує користувач — галочка «видалити цю точку при заміні» стоїть і в цьому випадку, а «Замінити зараз» лишається заблокованою, доки ніхто не вирішив; причина видна біля кнопки і рядком у діалозі. Раніше заміна стартувала, зривалася на контролері й лишала аліас наполовину на старому, наполовину на новому джерелі\n* Якщо під час заміни зривається запис, **нічого** не видаляється. Досі видалення йшли попри це, і в аліаса, переведеного лише наполовину, ще й бракувало точок. При перенесенні це правило діє вже давно\n* «Усі точки даних пристрою» більше не зсуває місце зберігання. Для пристрою з кількома виходами верстак створює теку, а в ній по каналу на кожен вихід. Кнопка перебудовує чернетку і передавала при цьому лише **готову ціль**; `setzeZiel` читає її останній сегмент як ім'я пристрою — але за кількох виходів це вихід, і він додатково потрапляв до теки. Кожне натискання зсувало місце зберігання на рівень глибше, і так само воно й записувалося: після трьох клацань виникали чотири теки замість однієї (`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`). Тепер кнопка передає теку та ім'я окремо, як це давно робить перемикач виходів поруч. У пристрою з одним виходом такого не траплялося ніколи",
30
+ "zh-cn": "* 完整测试流程带来的四件事。**通道标识**在多输出路径下没有被清理:对于通道名“Licht, Bar”,js-controller 悄悄生成 `Licht_ Bar`,而工作台显示的是“Licht, Bar”,并把它写进了枚举——一个从未存在过的标识;删除别名后,它还作为残留留在那里。现在 `ausgangName` 自己清理,若两个通道得出同一个名字,第二个会加上 `_2`。**标注**在两个视图中不一致:当数据点的名称与行名相同时,“编辑别名”显示它,“新建别名”却是空白字段。**行列表**现在与树排序一致——`POWER2` 排在 `POWER10` 之前。而**工作台自己建立的枚举**,在因功能变更而变空时也会一并删除,不再只限于删除别名时\n* 整理:“把别名对象变成草稿行”曾被写了五遍——每次都是同一条写入源规则,外围略有不同。本版本的四个错误正源于此:卷帘上丢失的写入源、一个从可开关变成只读的数据点、`alias.0.Solar.Netz` 缺失的标注,以及工作台自己制造的一处偏差。读取现在只在一处;四个调用方拿它做什么——比较、新建、覆盖——仍归它们自己。行为没有变化\n* 流程中发现的三件小事。**RSSI** 在五个 Tasmota 与测量点模板中默认勾选,在十一个 Homematic 模板中却没有——同一项设备属性,因厂商不同而有两种答案;现在与其余诊断项一样,处处不勾选。**吸尘器模式中的 `MAP_URL` 位置**得不到角色,因为它的表达式不以 `^` 开头,而推导要求两端锚点;缺少起始锚点不再算作该位置的减分。**而交换对话框中的“推测”标记**看上去像黏在点名后面的文字——它的样式依赖于三层父级,而那里并不存在。现在它和状态列表中一样是一枚药丸标签,并在提示中说明推测来自点名还是角色\n* 模板对话框中的保存按钮现在按下时也会检查,而不只在绘制时。离开字段时会重新判定——在名称提示里写下一个左括号后径直点击“保存模板”的人,面前是一个蓝色按钮,于是保存了一个表达式损坏的模板。五条锁定理由因此集中到一处,绘制与保存共用\n* 三处地方现在会说明为什么不行。**模板对话框中的保存按钮**原本灰着且沉默——有五条理由可以锁住它,却一条也没显示;现在所有适用的理由都出现在按钮旁,并以方框形式显示在对话框中。**删除时的错误对话框**只给出一个数字(“1 个操作失败”),没说是哪个标识卡住了;写入时早就有这份清单。**而发送点未能建立的原因**挂在一个按钮上,同一个回调 120 毫秒后就把它丢掉了——现在它位于试运行的顶部,并能挺过重建\n* 若某个数据点的类型与它在样板中的位置不符,现在三处地方都会说明——不再只有展开的那一行。若该位置是**必需**的,样板便完全不再生效,于是整份列表都被着色:在 Bastelzimmer_Licht 上,只要把 SET 从 `boolean` 改成 `mixed`,八行中就有八行算作“无位置”,而样板字段却报告“✕ 缺少 SET”——可 SET 明明在那里。现在写的是“✕ SET:类型为 mixed 而非 boolean”,列表上方则写着:“灯光样板目前不生效:SET 要求 boolean,而设置的是 mixed。因此没有任何一行有位置。”着色的只有真正出问题的那一行——从前整份列表都亮起来,于是着色显示的是结果而非原因。\n* 对 `system.config` 的迟到回答现在真的会把专家模式带过来。标签页在 2.5 秒后放弃,并继续使用浏览器语言;若回答随后才到,语言保持原样(在标注完成后再跳变会更糟),专家模式被接受,树重绘一次。这一切早就写好了——只是上面还坐着一个更早时期的守卫,恰好在这种情况下退出。没有该模式,`system.*` 与 `enum.*` 下的所有节点都会缺失,却没有任何地方说明原因\n* 交换对话框会注意到上一层更合适的情况。选择树允许选中任何其下挂有数据点的节点——必须如此,因为在扁平适配器中通道就是设备。但在 MQTT 中,`stat`、`tele` 和 `cmnd` 是主题文件夹:落到那里能找回的点更少,锁定机制便会要求移除一些。工作台现在也一并计算父级层级并加以说明——“上一层(…)7 个点中有 7 个能找到目标,这里只有 5 个”——并附带一个切换选择的按钮。什么都不禁止\n* 交换对话框中的设备列表会停在原处。在长列表中向下滚动并点击设备的人,之前会回到顶部,看不到刚选中的条目——选择会重建对话框,之后的树是另一个元素。若所选行仍落在视野之外,会把它带入视野。新的搜索和刚打开的对话框仍从顶部开始\n* 交换源时,写入目标若与读取源重合,便不再算数。搜索的最后一种形式是裸的点名,`cmnd.POWER` 因此会找到一个末尾同样叫 `POWER` 的状态点——别名随后就会写到自己的读取源上。猜测时已经拦住了,按路径命中时却没有;当新源选的是子节点而非设备时,这一点便会显现\n* 交换源时,无法一同迁移的数据点现在会中止交换,而不是让它中途失败。源分离的数据点——从 `stat.POWER` 读取、向 `cmnd.POWER` 写入——在新源处两者都需要。若缺少写入目标,ioBroker 中**没有**任何形式能表达“读取,但不写往任何地方”:裸标识意味着“写到状态点上”,不带 `write` 的 `{read: X}` 会被 js-controller 拒绝,而 `common.write: false` 并不能保护源(实测:对这样的别名写入会覆盖读取源)。因此由用户决定——“交换时移除该点”复选框在这种情况下也会出现,且在无人决定之前“立即交换”保持禁用;理由显示在按钮旁,并作为一行出现在对话框中。此前交换会启动、在控制器处失败,并让别名一半留在旧源、一半留在新源\n* 若交换过程中某次写入失败,将**不会**删除任何东西。此前删除仍会照常执行,于是一个才迁移了一半的别名还会丢失数据点。移动别名早就遵循这条规则\n* “设备的全部数据点”不再移动存放位置。对于有多个输出的设备,工作台会建立一个文件夹,并在其中为每个输出建立一个通道。该按钮会重建草稿,而当时只把**完整目标**传了过去;`setzeZiel` 把其最后一段读作设备名——但在多输出时那一段是输出,于是它又进了文件夹一层。每按一次,存放位置就深一级,写入时也是如此:点击三次便生成四个文件夹而不是一个(`…Garten-Ventilinsel.POWER2.POWER2.POWER2.POWER2`)。现在按钮分别传递文件夹和名称,就像旁边的输出切换一向所做的那样。单输出设备从未出现过这种情况"
31
+ },
6
32
  "0.9.9": {
7
33
  "en": "* The build source moved from `src/` to `src-admin/`. ioBroker reserves that name for frontend sources that are bundled into `admin/` and never reach the user, and the adapter checker skips such directories when it looks for missing dependencies. `@iobroker/type-detector` therefore stays in `devDependencies`, which is where it belongs: esbuild bakes it into `admin/detector.js` at build time and nothing loads it at runtime. Users receive the finished 71 KB file, not the 548 KB package (W5042)\n* The settings page now takes its translations from `admin/i18n/` — the dictionary ioBroker reads itself (`\"i18n\": true`) and that Weblate can work with. The eleven languages it already carried moved there unchanged; not a word was retranslated. The tab keeps its own dictionary, now at `admin/sprachen/`: 588 keys in German and English, with an unknown language falling back to English. Two dictionaries, two jobs — the name `i18n` is the one the adapter checker inspects, and it expects all eleven languages there (W5603, W5614, W5015)\n* The changelog entries for 0.9.7 and 0.9.8 are now complete in all eleven languages. Nine of them carried only a short summary — the English text for 0.9.7 ran to 3,000 characters with five headings and 22 items, the Russian one to 480 without any structure. A test now checks every entry for length, headings and item count against the English original (W1145)\n* Two developer-side additions, invisible in the adapter itself: `.vscode/settings.json` wires up the JSON schemas, so mistakes in `io-package.json` or `jsonConfig.json` show up while typing instead of in the adapter checker (S4036). And the GitHub Actions updates no longer run `monthly` — that would ask on the first of every month, at the same moment as everyone else; a cron schedule spreads the load while keeping the monthly rhythm (S8906)\n* The data type now follows the role. A pattern slot prescribes not only the role but also the type, and both sit in the same type-detector record — so picking a role sets the matching type as well. Where a slot allows several types nothing is set, and where it prescribes none any choice stays right. If the type does not fit the slot after all, the workbench says so instead of staying quiet: in the row (\"expects number\"), as a warning underneath, and in the pattern field, which now gives the reason — \"✕ CONSUMPTION: type mixed instead of number\" — rather than a bare \"does not fit\". Before, a state with the right role and the wrong type dropped out of the pattern silently, and the whole device was recognised as something lesser Where a role matches several slots that differ in type — the blind's travel direction sits on DIRECTION as a boolean and on DIRECTION_ENUM as a number — the workbench picks the slot whose type fits, and both forms count as right.\n* Saving a template no longer loses the write targets. Every actuator that keeps its own state writes to the same point it reads - a blind, a dimmer and a thermostat all use 1.LEVEL for both. Saving dropped the write path in exactly that case, and the resulting alias showed the position but could no longer be moved. Rows that only write, like the blind's STOP, disappeared altogether. With Tasmota it never showed, because there tele.STATE is read and cmnd.POWER is written. The device type in the template sheet was affected by a second slip: three patterns are named differently from their type (blinds/blind, mediaPlayer/media, levelSlider/slider), so a blind always claimed to have no type at all",
8
34
  "de": "* Die Bauvorlage liegt jetzt in `src-admin/` statt in `src/`. Diesen Namen hat ioBroker für Frontend-Quellen vorgesehen, die nach `admin/` gebacken werden und beim Nutzer nie ankommen; der Adapterprüfer überspringt solche Ordner bei der Suche nach fehlenden Abhängigkeiten. `@iobroker/type-detector` bleibt deshalb in `devDependencies`, und dort gehört er hin: esbuild backt ihn beim Bauen in `admin/detector.js` ein, zur Laufzeit lädt ihn niemand. Ausgeliefert werden die fertigen 71 KB, nicht das 548-KB-Paket (W5042)\n* Die Einstellungsseite nimmt ihre Übersetzungen jetzt aus `admin/i18n/` — dem Wörterbuch, das ioBroker selbst liest (`\"i18n\": true`) und mit dem Weblate arbeiten kann. Die elf Sprachen, die sie ohnehin schon trug, sind unverändert dorthin umgezogen; kein Wort wurde neu übersetzt. Der Reiter behält sein eigenes Wörterbuch, jetzt unter `admin/sprachen/`: 588 Schlüssel auf Deutsch und Englisch, eine unbekannte Sprache fällt auf Englisch zurück. Zwei Wörterbücher, zwei Aufgaben — den Namen `i18n` sieht sich der Adapterprüfer an und erwartet dort alle elf Sprachen (W5603, W5614, W5015)\n* Die Changelog-Einträge zu 0.9.7 und 0.9.8 stehen jetzt vollständig in allen elf Sprachen. Neun davon trugen nur eine Kurzfassung — der englische Text zu 0.9.7 hat 3.000 Zeichen mit fünf Überschriften und 22 Punkten, der russische hatte 480 ohne jede Gliederung. Ein Test hält jeden Eintrag nun nach Länge, Überschriften und Punktzahl gegen das englische Original (W1145)\n* Zwei Zutaten für die Entwicklung, im Adapter selbst unsichtbar: `.vscode/settings.json` hängt die JSON-Schemata ein, sodass Fehler in `io-package.json` oder `jsonConfig.json` schon beim Tippen auffallen statt erst im Adapterprüfer (S4036). Und die Aktualisierung der GitHub Actions läuft nicht mehr `monthly` — das fragt am Monatsersten an, im selben Moment wie alle anderen; ein cron-Takt verteilt die Last und behält den monatlichen Rhythmus (S8906)\n* Der Datentyp folgt jetzt der Rolle. Ein Musterplatz gibt nicht nur die Rolle vor, sondern auch den Typ, und beides steht im selben Datensatz des type-detector — wer eine Rolle wählt, bekommt den passenden Typ also gleich mit. Wo ein Platz mehrere Typen zulässt, wird nichts gesetzt; wo er keinen vorgibt, bleibt jede Wahl richtig. Passt der Typ trotzdem nicht zum Platz, sagt es die Werkbank, statt zu schweigen: in der Zeile („erwartet number“), als Warnung darunter, und im Musterfeld, das jetzt den Grund nennt — „✕ CONSUMPTION: Typ mixed statt number“ — statt eines blanken „passt nicht“. Vorher fiel ein Punkt mit richtiger Rolle und falschem Typ lautlos aus dem Muster, und das ganze Gerät wurde als etwas Geringeres erkannt Trifft eine Rolle mehrere Plätze, die sich im Typ unterscheiden — die Fahrtrichtung des Rollladens sitzt als Wahrheitswert auf DIRECTION und als Zahl auf DIRECTION_ENUM —, wählt die Werkbank den Platz, dessen Typ passt, und beide Formen gelten als richtig.\n* Beim Speichern einer Vorlage gehen die Schreibziele nicht mehr verloren. Jeder Aktor, der seinen eigenen Zustand führt, schreibt auf denselben Punkt, den er liest — Rollladen, Dimmer und Thermostat benutzen dafür alle 1.LEVEL. Genau in diesem Fall warf das Speichern den Schreibweg weg, und der daraus gebaute Alias zeigte die Stellung an, liess sich aber nicht mehr verstellen. Zeilen, die nur schreiben — der STOP des Rollladens — fielen ganz heraus. Bei Tasmota fiel es nie auf, weil dort tele.STATE gelesen und cmnd.POWER geschrieben wird. Der Gerätetyp im Vorlagenblatt litt an einem zweiten Versehen: Drei Muster heissen anders als ihr Typ (blinds/blind, mediaPlayer/media, levelSlider/slider), und ein Rollladen behauptete deshalb, gar keinen Typ zu haben",
@@ -67,32 +93,6 @@
67
93
  "pl": "To, co zapisano w istniejącym aliasie, teraz obowiązuje: podpis zostaje, alias tylko do odczytu pozostaje taki, i dotyczy to każdego punktu — także gdy kilka wskazuje to samo źródło. Alias, którego kanał istnieje wyłącznie jako identyfikator, jest wreszcie porównywany, a interfejs nie zapowiada już tworzenia tam, gdzie zmienia. Przebieg próbny pokazuje wyliczenia w porównaniu, a wiersz czytający z innego adaptera dostaje wartość już przy pierwszym kliknięciu.",
68
94
  "uk": "Те, що записано в наявному аліасі, тепер має силу: підпис залишається, аліас лише для читання таким і лишається, і це для кожної точки — навіть коли кілька вказують на те саме джерело. Аліас, канал якого існує лише як ідентифікатор, нарешті порівнюється, а інтерфейс більше не оголошує створення там, де змінює. Пробний прогін показує переліки в порівнянні, а рядок з іншого адаптера отримує значення вже при першому кліку.",
69
95
  "zh-cn": "现有别名中已保存的内容现在具有优先权:标题保留,只读别名仍为只读,并且对每个数据点都适用——即使多个点指向同一数据源。通道仅以标识符形式存在的别名现在也会被比对,界面不再在修改时宣告“新建”。试运行会以对比方式显示枚举,来自其他适配器的数据行在第一次点击时就能取到值。"
70
- },
71
- "0.8.2": {
72
- "en": "A second alias on the same source is now announced instead of created silently — with a button to move the existing one instead. Switching to a template that finds nothing now works. Roles the workbench adapted are marked and can be taken back. Escape discards in every field of the target bar. New adapter icon.",
73
- "de": "Ein zweiter Alias auf dieselbe Quelle wird jetzt angesagt statt stillschweigend angelegt — daneben ein Knopf, der stattdessen den vorhandenen verlegt. Der Wechsel auf eine Vorlage, die nichts findet, greift jetzt. Angepasste Rollen sind markiert und lassen sich zurückholen. Escape verwirft in jedem Feld des Zielbalkens. Neues Adaptersymbol.",
74
- "ru": "Второй алиас на тот же источник теперь объявляется, а не создаётся молча — рядом кнопка, чтобы вместо этого перенести существующий. Переключение на шаблон, который ничего не находит, теперь работает. Изменённые роли помечаются и могут быть возвращены. Escape отменяет ввод в каждом поле целевой строки. Новый значок адаптера.",
75
- "pt": "Um segundo alias sobre a mesma fonte passa a ser anunciado em vez de criado em silêncio — com um botão para mover o existente. A mudança para um modelo que não encontra nada passa a funcionar. Os papéis adaptados são assinalados e podem ser revertidos. Escape descarta em todos os campos da barra de destino. Novo ícone do adaptador.",
76
- "nl": "Een tweede alias op dezelfde bron wordt nu gemeld in plaats van stil aangemaakt — met een knop om de bestaande te verplaatsen. Overschakelen naar een sjabloon dat niets vindt werkt nu. Aangepaste rollen worden gemarkeerd en kunnen worden teruggehaald. Escape verwerpt in elk veld van de doelbalk. Nieuw adapterpictogram.",
77
- "fr": "Un deuxième alias sur la même source est désormais signalé au lieu d’être créé en silence — avec un bouton pour déplacer celui qui existe. Le passage à un modèle qui ne trouve rien fonctionne maintenant. Les rôles adaptés sont marqués et peuvent être repris. Échap annule dans chaque champ de la barre de destination. Nouvelle icône d’adaptateur.",
78
- "it": "Un secondo alias sulla stessa sorgente viene ora annunciato invece che creato in silenzio — con un pulsante per spostare quello esistente. Il passaggio a un modello che non trova nulla ora funziona. I ruoli adattati sono contrassegnati e si possono ripristinare. Esc annulla in ogni campo della barra di destinazione. Nuova icona dell’adattatore.",
79
- "es": "Un segundo alias sobre la misma fuente ahora se anuncia en lugar de crearse en silencio — con un botón para mover el existente. Cambiar a una plantilla que no encuentra nada ya funciona. Los roles adaptados se marcan y se pueden recuperar. Escape descarta en cada campo de la barra de destino. Nuevo icono del adaptador.",
80
- "pl": "Drugi alias na to samo źródło jest teraz zapowiadany, a nie tworzony po cichu — obok przycisk, który zamiast tego przenosi istniejący. Przełączenie na szablon, który nic nie znajduje, teraz działa. Zmienione role są oznaczone i można je cofnąć. Escape odrzuca w każdym polu paska celu. Nowa ikona adaptera.",
81
- "uk": "Другий аліас на те саме джерело тепер оголошується, а не створюється мовчки — поруч кнопка, щоб натомість перенести наявний. Перемикання на шаблон, який нічого не знаходить, тепер працює. Змінені ролі позначені й їх можна повернути. Escape скасовує в кожному полі цільового рядка. Нова піктограма адаптера.",
82
- "zh-cn": "同一数据源上的第二个别名现在会有提示,而不是被静默创建——旁边有按钮可改为移动已有的别名。切换到没有匹配项的模板现在也能生效。被调整过的角色会被标记,并可撤回。Escape 在目标栏的每个字段中都会放弃输入。新的适配器图标。"
83
- },
84
- "0.8.1": {
85
- "en": "Published through npm trusted publishing (OIDC) — releases are signed with provenance from now on. No functional changes.",
86
- "de": "Veröffentlichung über npm Trusted Publishing (OIDC) — Ausgaben sind ab jetzt mit Herkunftsnachweis signiert. Keine funktionalen Änderungen.",
87
- "ru": "Публикация через npm trusted publishing (OIDC) — выпуски теперь подписаны с подтверждением происхождения. Функциональных изменений нет.",
88
- "pt": "Publicação através de npm trusted publishing (OIDC) — as versões passam a ser assinadas com proveniência. Sem alterações funcionais.",
89
- "nl": "Publicatie via npm trusted publishing (OIDC) — releases worden voortaan ondertekend met herkomst. Geen functionele wijzigingen.",
90
- "fr": "Publication via npm trusted publishing (OIDC) — les versions sont désormais signées avec provenance. Aucun changement fonctionnel.",
91
- "it": "Pubblicazione tramite npm trusted publishing (OIDC) — le versioni sono ora firmate con provenienza. Nessuna modifica funzionale.",
92
- "es": "Publicación mediante npm trusted publishing (OIDC): las versiones se firman con procedencia a partir de ahora. Sin cambios funcionales.",
93
- "pl": "Publikacja przez npm trusted publishing (OIDC) — wydania są od teraz podpisywane z poświadczeniem pochodzenia. Bez zmian funkcjonalnych.",
94
- "uk": "Публікація через npm trusted publishing (OIDC) — випуски тепер підписані з підтвердженням походження. Функціональних змін немає.",
95
- "zh-cn": "通过 npm 可信发布(OIDC)发布——此后的版本均带有来源签名。无功能变更。"
96
96
  }
97
97
  },
98
98
  "titleLang": {