iobroker.alias-workbench 0.11.0 → 0.12.0
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/README.md +19 -7
- package/admin/css/werkbank.css +73 -0
- package/admin/i18n/de.json +65 -0
- package/admin/i18n/en.json +65 -0
- package/admin/i18n/es.json +65 -0
- package/admin/i18n/fr.json +65 -0
- package/admin/i18n/it.json +65 -0
- package/admin/i18n/nl.json +65 -0
- package/admin/i18n/pl.json +65 -0
- package/admin/i18n/pt.json +65 -0
- package/admin/i18n/ru.json +65 -0
- package/admin/i18n/uk.json +65 -0
- package/admin/i18n/zh-cn.json +65 -0
- package/admin/js/attrappe.js +749 -0
- package/admin/js/baum.js +52 -5
- package/admin/js/entwurf.js +133 -6
- package/admin/js/ergebnis.js +77 -2
- package/admin/js/quellentausch.js +823 -16
- package/admin/js/sprache.js +4 -0
- package/admin/js/zustand.js +28 -0
- package/admin/tab.html +24 -0
- package/io-package.json +14 -14
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -187,8 +187,9 @@ Early. Usable, but not finished.
|
|
|
187
187
|
|
|
188
188
|
- Works as an admin tab; the adapter itself runs no process (`mode: none`).
|
|
189
189
|
The instance exists only to carry the settings.
|
|
190
|
-
- Interface in
|
|
191
|
-
|
|
190
|
+
- Interface in all eleven admin languages, 712 keys each — one dictionary at
|
|
191
|
+
`admin/i18n/`, shared by the tab and the settings page. An unknown language
|
|
192
|
+
falls back to English
|
|
192
193
|
- 16 bundled templates: eleven Homematic, four Tasmota, one plain measuring point
|
|
193
194
|
- **Missing:** "who uses this alias" — vis views, Alexa and Google names cannot
|
|
194
195
|
be searched from here, so a rename warns you instead of pretending to be
|
|
@@ -590,6 +591,22 @@ imported, and that all eleven language files carry the same keys.
|
|
|
590
591
|
|
|
591
592
|
## Changelog
|
|
592
593
|
|
|
594
|
+
### 0.12.0 (2026-10-14)
|
|
595
|
+
**Swapping the source**
|
|
596
|
+
* **Swapping now asks the same recognition as the tree.** The existing stages all started from the **old** source — path, remembered template, names, roles. Yet swapping asks the same question the workbench answers anyway when you click a device: which point **there** is the `ELECTRIC_POWER`? Now, before guessing, the draft of the **new** source is computed and mapped through its pattern slots — template first, otherwise the detector. That carries in **both** directions, which was the point: to a device that labels its points (Matter: `role: value.power`, `unit: W`) the detector answers; to one that labels nothing, the template does. Measured at `mqtt-client.0.SmartHome.PC_Jonas`: all ten points without `common.role`, type `mixed`, the type detector makes `info` of it — but the Tasmota template knows that `stat.POWER` is the status point and the power sits in `tele.SENSOR` under `ENERGY.Power`. Swapping from Matter back to MQTT previously found **0 of 7** points; now 6 of 7, with separate read and write sources.
|
|
597
|
+
* **And the formulas come along.** They belong to the source, not to the alias: `JSON.parse(val)?.ENERGY?.Power ?? null` describes how to get a power reading out of a Tasmota telemetry message. Left in place when swapping to Matter, the point sat silently at `null` — four readings empty with no error at all, and `SET` would have written the string from `val ? "ON" : "OFF"` onto a boolean. Each direction now brings its own: none towards Matter, the JSON formula again back to Tasmota.
|
|
598
|
+
* **A point no stage can find can be named by hand.** Until now the only choices were "remove" or leave it. The row now offers a list of every point on the new device, with role and unit beside it. What you pick there carries the mark "by hand" and the note that **formula, unit and value range stay as they are on the alias** — the workbench knows nothing about that point, so it changes nothing about it.
|
|
599
|
+
* **When the unit changes, the numbers sit beside it — nothing is decided for you.** Tasmota delivers `ENERGY.Total` in kWh, Matter `CONSUMPTION` in Wh: the same meter, factor 1000, invisible. Nothing is converted automatically, because the labelling itself is unreliable — Matter writes the unit `mA` on `CURRENT` and delivers amperes (0.926 at 245 W and 228 V). An automation that believed the label would have made 926 A of it. Instead the row states the finding ("on the alias A · new source: none"), shows what the alias displays today, and offers **two free fields**: unit and factor, both at the current state. The result recomputes as you type. Where the workbench knows something, a shortcut sits beside the field (`Wh`, `/ 1000`) — a suggestion from the labelling, checkable against the numbers above. Free fields, because fixed buttons fail where the target carries **no** unit at all: a JSON collector point has none, the unit sits in the field. This is only shown when the **new source** delivers something other than the old one — swapping between devices of the same kind shows nothing.
|
|
600
|
+
* **When swapping, the remembered template is checked against the new source.** An alias remembers which template it came from, and the workbench keeps applying it until you explicitly change it — exactly right for a like-for-like replacement. For a differently built device it was not, and the bad part was the silence: after swapping a Tasmota socket for a Matter one, the channel still read "Tasmota socket, forced, ✕ cmnd.POWER" — and the **formulas** from that same template stayed on the points. `JSON.parse(val)?.ENERGY?.Power ?? null` is meant for a telemetry JSON; Matter delivers a plain number, and the point sat at `null`. Four readings were empty with no error anywhere, and `SET` would have written the string from `val ? "ON" : "OFF"` onto a boolean. The dialog now checks the remembered template against the **new** device: if it still fits, nothing changes; if it does not, it says why, how many points carry formulas, and — if a different template fits the new source — which one. Plus a pre-ticked box that drops the remembering and the formulas along with it. **Nothing is decided automatically**: the formula belongs to the source, not to the alias, and on the way back to MQTT it is needed again — deleting it silently would be the same mistake as silently keeping it. `native.geraetetyp` and the whole of `common` are left untouched; the swap changes the source, not what the device is.
|
|
601
|
+
* **Source swapping now also asks the alias point itself.** Until now all three mapping stages started from the **old source** — its path, its template row, the name or role of the old state. That works while both devices are built alike and fails completely once they are not: moving an alias from a Tasmota socket to a Matter socket produced **0 out of 8** mappings, for two devices that do the same thing. Both reasons were on the source side, never on the target — `mqtt-client` keeps no roles, and five of the eight points read from **one** telemetry JSON. Yet the answer is already in the alias: `ELECTRIC_POWER` carries `role: value.power`, and the new device holds exactly one point of that name with that role. So before guessing, the **alias point** is asked. If **name and role** match and the point exists exactly once, that counts like a path hit and the row carries the grey mark "from alias"; if only the **role** matches, and it too exactly once, it is a suggestion marked "guessed". Two points of the same role cancel each other out instead of one being picked. In the measured case that is six out of eight, spread over **both** Matter endpoints; `TODAY` and `YESTERDAY` stay empty because the new device has no such thing.
|
|
602
|
+
* **If one point at the new device both reads and writes, it may do so.** The rule "the write target is never the read source" guards against a guessed status point (`stat.POWER` instead of `cmnd.POWER`). Where a single point can do both — `OnOffPlugInUnit-1.SET` on Matter, `1.STATE` on Homematic — it was too strict and reported "no write target found" at exactly the point meant for it. The exception applies only to the evidenced hit via the alias point, and only when both sides are writable; a status point such as `ACTUAL` still gets none.
|
|
603
|
+
|
|
604
|
+
**Tree**
|
|
605
|
+
* **Several branches can be selected as one device.** Some adapters spread one device across sibling branches: Matter stores a socket as a folder without data points of its own, holding two `device` nodes — the switch in one, the readings in the other. The folder was not selectable, and each endpoint on its own produced half a device: at the switch the detector recognised a socket and offered the five readings as "to be created", while the neighbouring branch already had them. **Ctrl-click** now adds a branch to the selection or takes it out; the selection moves to the common parent, and every branch involved is marked in the tree. The same sits in the **context menu**, for anyone without a keyboard, and in the header of the right-hand side as a button **"Add neighbouring branches (N)"** — where the adapter provides evidence, the tooltip says so (Matter writes the same node id to every endpoint). Point names are shortened where they are unambiguous: `OnOffPlugInUnit-1.SET` becomes `SET`. Not for Tasmota — there the branch carries meaning, and the templates address `stat.POWER` and `tele.SENSOR`. **Nothing is merged automatically**: many devices can sit side by side under one node, and only a person knows what counts as one device.
|
|
606
|
+
* **Right-click a node → "Export as mock device".** Everything below that node goes into a file: the objects and the values they carry right now. The point is not backup but rebuilding — from that file a device can be recreated elsewhere, so a template can be built for a device you do not own. What goes in is a positive list, not a filter: `native` is dropped entirely, and from `common` only `name`, `role`, `type`, `unit`, `read`, `write`, `min`, `max`, `def` and `states` are kept. `states` has to come along, otherwise the type detector does not recognise the slots with `statesDefined`. Paths are relative to the exported node, which is why the mock device matches the same templates somewhere else. Levels without an object of their own are recorded as such.
|
|
607
|
+
* **Before writing the file, the workbench shows what goes into it.** One row per entry with value, path, type, role and name — and a checkbox per value: untick what should not travel, and the object still stays. Values that look like an IP, a MAC or an identifier are highlighted. Above that stands what travels even without `native`: identifiers often sit **in the path and in the names too**, and leaving out `native` does not remove those. Measured on a HomeMatic central: twelve such places, although the file carries no `native` at all.
|
|
608
|
+
* **And read back in.** Right-click → "Import mock device …" takes such a file and builds a device from it again — **always under `0_userdata.0.wb-attrappe.<name>`, never at the original path.** That is not a rule but a way of building: a foreign export cannot overwrite a real device. The templates still match, because they check relative names (`stat.POWER`, `1.LEVEL`) and not the root. Beforehand a dialog shows every object that would appear, with a name to change; a file that does not fit is rejected with a reason. Measured: an HmIP wall thermostat, exported and imported as a mock device, is recognised there by the same template — same device type, the same eleven filled slots.
|
|
609
|
+
|
|
593
610
|
### 0.11.0 (2026-10-11)
|
|
594
611
|
**Templates**
|
|
595
612
|
* **Template notes are German and English.** The description, the recognition note and each row note are `{ "de", "en" }`. The tab shows the admin language, otherwise English, otherwise German. The name hint stays one search pattern (`licht|lampe|light|…`): it matches the device name, which does not follow the admin language.
|
|
@@ -734,11 +751,6 @@ All changes in detail, with cause and measurement: [docs/aenderungen-ausfuehrlic
|
|
|
734
751
|
* 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.
|
|
735
752
|
* 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
|
|
736
753
|
|
|
737
|
-
### 0.9.8
|
|
738
|
-
* The changelog only lists versions that actually exist on npm. The entries 0.9.1 to 0.9.6 were local intermediate steps and were never published; their content is now summarised under 0.9.7. Found by the repochecker (E2004, E1032)
|
|
739
|
-
* The README no longer describes how to add the adapter by hand — in the official repository it is picked from the adapter list (E6013)
|
|
740
|
-
* `dependabot.yml` gets a seven-day cooldown for npm packages: what appears today is proposed a week later. If a compromised release is pulled within that time, it never arrives here (E8915). And `@types/node` stays on its major version — the types must match the Node release the adapter runs on (E8917)
|
|
741
|
-
|
|
742
754
|
Older entries: [CHANGELOG_OLD.md](CHANGELOG_OLD.md).
|
|
743
755
|
|
|
744
756
|
## License
|
package/admin/css/werkbank.css
CHANGED
|
@@ -191,6 +191,10 @@
|
|
|
191
191
|
.tree .node.leer { opacity:.45; font-style:italic; }
|
|
192
192
|
.tree .node.leer .kind { background:transparent; border:1px solid var(--line); }
|
|
193
193
|
.tree .node.sel { background:var(--accent); color:var(--accent-ink); font-weight:600; }
|
|
194
|
+
/* Der gemeinsame Elternknoten einer Mehrfachauswahl: markiert, aber
|
|
195
|
+
schwaecher als die Zweige selbst. Er ist der Ort, auf dem der
|
|
196
|
+
Entwurf steht - angeklickt hat ihn niemand. */
|
|
197
|
+
.tree .node.selEltern { background:var(--accent-soft); font-weight:600; }
|
|
194
198
|
.tree .node.sel .kind { background:rgba(255,255,255,.22); color:inherit; }
|
|
195
199
|
/* Die Vorlagenliste benutzt dieselben Knotenzeilen, hat aber statt
|
|
196
200
|
`kind`/`nam`/`cnt` ein Abzeichen, einen Namen und rechts die Kennung.
|
|
@@ -633,6 +637,19 @@
|
|
|
633
637
|
.rat { font-family:var(--sans); font-size:8px; font-weight:700; letter-spacing:.05em;
|
|
634
638
|
text-transform:uppercase; background:var(--accent-soft); color:var(--accent);
|
|
635
639
|
padding:0 6px; border-radius:999px; margin-left:6px; white-space:nowrap; }
|
|
640
|
+
/* Name und Marke im Tauschdialog untereinander. Die Namensspalte ist
|
|
641
|
+
120 Pixel breit; „ERKANNT" hinter `ELECTRIC_POWER` lief sonst in die
|
|
642
|
+
Pfade der Nachbarzeile (Ricardo, 13.10.2026). */
|
|
643
|
+
#swap-body .slot .zuname { display:flex; flex-direction:column;
|
|
644
|
+
align-items:flex-start; gap:3px; }
|
|
645
|
+
#swap-body .slot .zuname .rat,
|
|
646
|
+
#swap-body .slot .zuname .herk { margin-left:0; }
|
|
647
|
+
/* Herkunftsmarke am Quellentausch: dieselbe Form wie „vermutet", aber
|
|
648
|
+
grau statt farbig - sie warnt nicht, sie sagt nur, woher die
|
|
649
|
+
Zuordnung kommt (Stufe 4, ueber den Alias-Punkt). */
|
|
650
|
+
.herk { font-family:var(--sans); font-size:8px; font-weight:700; letter-spacing:.05em;
|
|
651
|
+
text-transform:uppercase; background:var(--surface-3); color:var(--ink-3);
|
|
652
|
+
padding:0 6px; border-radius:999px; margin-left:6px; white-space:nowrap; }
|
|
636
653
|
.erow .nm3 .ratknopf { font-family:var(--sans); font-size:11px; cursor:pointer; margin-left:5px;
|
|
637
654
|
color:var(--ink-3); padding:0 4px; border-radius:var(--r-sm); }
|
|
638
655
|
.erow .nm3 .ratknopf:hover { background:var(--surface-3); color:var(--ink); }
|
|
@@ -1176,3 +1193,59 @@
|
|
|
1176
1193
|
}
|
|
1177
1194
|
.katalog-laedt .kl-kopf { font-weight:600; font-size:12.5px; color:var(--ink); }
|
|
1178
1195
|
.katalog-laedt .kl-text { margin-top:3px; font-size:11.5px; color:var(--ink-3); }
|
|
1196
|
+
|
|
1197
|
+
/* Das Menue am Baum (Rechtsklick). Liegt am body, nicht in der Zeile:
|
|
1198
|
+
der Baum scrollt, und ein Kind der Zeile wuerde am Rand abgeschnitten. */
|
|
1199
|
+
.baummenue {
|
|
1200
|
+
position:fixed; z-index:200; min-width:190px;
|
|
1201
|
+
background:var(--surface); border:1px solid var(--line-strong);
|
|
1202
|
+
border-radius:var(--r); box-shadow:var(--shadow-hoch); padding:4px 0;
|
|
1203
|
+
}
|
|
1204
|
+
.baummenue .bm-zeile {
|
|
1205
|
+
padding:6px 13px; font-size:12.5px; color:var(--ink); cursor:pointer;
|
|
1206
|
+
white-space:nowrap;
|
|
1207
|
+
}
|
|
1208
|
+
.baummenue .bm-zeile:hover { background:var(--hover); color:var(--hover-ink); }
|
|
1209
|
+
|
|
1210
|
+
/* Die Vorschau vor dem Ausgeben einer Attrappe. */
|
|
1211
|
+
.mk-kopf { margin-bottom:10px; }
|
|
1212
|
+
.mk-kopf .mk-wurzel { font:12.5px var(--mono); color:var(--ink); word-break:break-all; }
|
|
1213
|
+
.mk-kopf .mk-zahlen { margin-top:3px; font-size:11.5px; color:var(--ink-3); }
|
|
1214
|
+
.mk-kopf .mk-ohne { margin-top:3px; font-size:11.5px; color:var(--ink-2); }
|
|
1215
|
+
.mk-warn {
|
|
1216
|
+
margin:0 0 10px; padding:7px 10px; border-radius:var(--r);
|
|
1217
|
+
background:var(--warn-soft); color:var(--warn); font-size:11.5px;
|
|
1218
|
+
}
|
|
1219
|
+
.mk-warn .mk-warn-kopf { font-weight:600; }
|
|
1220
|
+
.mk-warn .mk-warn-liste { margin:4px 0 0; padding-left:16px; }
|
|
1221
|
+
.mk-warn .mk-warn-liste li { font:11px var(--mono); word-break:break-all; }
|
|
1222
|
+
table.mk-tab { width:100%; border-collapse:collapse; font-size:12px; }
|
|
1223
|
+
table.mk-tab th {
|
|
1224
|
+
text-align:left; font-weight:600; font-size:11px; color:var(--ink-3);
|
|
1225
|
+
border-bottom:1px solid var(--line); padding:4px 7px; position:sticky; top:0;
|
|
1226
|
+
background:var(--surface);
|
|
1227
|
+
}
|
|
1228
|
+
table.mk-tab td { padding:3px 7px; border-bottom:1px solid var(--line); vertical-align:top; }
|
|
1229
|
+
table.mk-tab tr.mk-virt { color:var(--ink-3); }
|
|
1230
|
+
table.mk-tab tr.mk-aus .mk-wtext { text-decoration:line-through; color:var(--ink-3); }
|
|
1231
|
+
.mk-wert label { display:flex; gap:5px; align-items:baseline; cursor:pointer; }
|
|
1232
|
+
.mk-wtext { font:11.5px var(--mono); word-break:break-all; }
|
|
1233
|
+
.mk-wtext.auff { background:var(--warn-soft); color:var(--warn); border-radius:3px; padding:0 3px; }
|
|
1234
|
+
.mk-pfad { font:11.5px var(--mono); }
|
|
1235
|
+
.mk-name { color:var(--ink-2); }
|
|
1236
|
+
.mk-fehler {
|
|
1237
|
+
padding:8px 11px; border-radius:var(--r);
|
|
1238
|
+
background:var(--bad-soft); color:var(--bad); font-size:12px;
|
|
1239
|
+
}
|
|
1240
|
+
.mk-namenszeile { display:flex; gap:7px; align-items:center; margin:7px 0 3px; }
|
|
1241
|
+
.mk-namenszeile .mk-lbl { font-size:11.5px; color:var(--ink-3); }
|
|
1242
|
+
.mk-namenszeile input.tx { max-width:260px; }
|
|
1243
|
+
.mk-schon { color:var(--ink-3); font-size:11px; }
|
|
1244
|
+
/* Von welcher Zeile das Baummenue spricht. Bewusst anders als die
|
|
1245
|
+
Auswahl `.sel`: ein Rechtsklick waehlt nicht aus, und zwei gleich
|
|
1246
|
+
aussehende Zeilen waeren irrefuehrend. */
|
|
1247
|
+
.tree .node.menueziel {
|
|
1248
|
+
outline:2px solid var(--accent); outline-offset:-2px; border-radius:var(--r);
|
|
1249
|
+
}
|
|
1250
|
+
.mk-warn.mk-gross { background:var(--warn-soft); }
|
|
1251
|
+
.mk-mehr { margin-top:6px; font-size:11.5px; color:var(--ink-3); }
|
package/admin/i18n/de.json
CHANGED
|
@@ -259,6 +259,32 @@
|
|
|
259
259
|
"list.tplDiffers": "weicht von der Vorlage ab",
|
|
260
260
|
"list.tplHint": "Hakt genau die Punkte an, die die Vorlage vorschlägt — unabhängig davon, was heute im Alias steht.",
|
|
261
261
|
"list.willBeCreated": "angelegt werden",
|
|
262
|
+
"mock.colName": "Name",
|
|
263
|
+
"mock.colPath": "Pfad",
|
|
264
|
+
"mock.colRole": "Rolle",
|
|
265
|
+
"mock.colType": "Typ",
|
|
266
|
+
"mock.colValue": "Wert",
|
|
267
|
+
"mock.counts": "{0} Einträge, {1} mit Wert · geschrieben von alias-workbench {2} · Quelle {3}",
|
|
268
|
+
"mock.inNames": "Achtung: {0} Kennungen stehen auch im Pfad oder in Namen — das Weglassen von `native` entfernt die nicht",
|
|
269
|
+
"mock.more": "… und {0} weitere Einträge (nicht gezeigt, aber in der Datei)",
|
|
270
|
+
"mock.noNative": "`native` ist nicht enthalten. Werte, die nicht mitsollen, einfach abwählen.",
|
|
271
|
+
"mock.save": "Datei speichern",
|
|
272
|
+
"mock.suspicious": "Sieht aus wie: {0}",
|
|
273
|
+
"mock.tooBig": "Das ist viel: {0} Einträge (ein Gerät hat meist weniger als {1})",
|
|
274
|
+
"mock.tooBigHint": "War ein einzelnes Gerät gemeint? Ausgeben geht trotzdem.",
|
|
275
|
+
"mockin.bad": "Diese Datei passt nicht",
|
|
276
|
+
"mockin.badEntry": "{0} Einträge haben keinen Pfad.",
|
|
277
|
+
"mockin.badFormat": "Format {0}, diese Fassung liest aber {1}.",
|
|
278
|
+
"mockin.badJson": "Nicht als JSON lesbar.",
|
|
279
|
+
"mockin.badObjects": "Keine Objekte in der Datei.",
|
|
280
|
+
"mockin.counts": "{0} Objekte, {1} mit Wert, {2} schon vorhanden",
|
|
281
|
+
"mockin.create": "Jetzt anlegen",
|
|
282
|
+
"mockin.exists": "(gibt es schon)",
|
|
283
|
+
"mockin.from": "Aus {0} · geschrieben von alias-workbench {1} · Quelle {2}",
|
|
284
|
+
"mockin.name": "Name",
|
|
285
|
+
"mockin.nameTaken": "Den Namen „{0}\" gibt es schon — dort liegen {1} Objekte",
|
|
286
|
+
"mockin.nameTakenHint": "Bitte einen anderen Namen wählen. In eine vorhandene Attrappe zu schreiben würde beide vermischen: ersetzt wird nur, wo der Pfad gleich ist, der Rest der alten bleibt stehen — und heraus käme ein Gerät, das es nie gab.",
|
|
287
|
+
"mockin.noRoot": "Der Eintrag für die Wurzel fehlt.",
|
|
262
288
|
"move.button": "Verlegen …",
|
|
263
289
|
"move.done": "Verlegt. Der Alias steht jetzt unter {0}.",
|
|
264
290
|
"move.exists": "{0} gibt es schon. Erst entfernen oder einen anderen Namen wählen.",
|
|
@@ -375,6 +401,9 @@
|
|
|
375
401
|
"pattern.typeOr": " oder ",
|
|
376
402
|
"pattern.usualOnly": "nur die üblichen",
|
|
377
403
|
"pattern.viaRole": "Rolle {0}",
|
|
404
|
+
"result.addNeighbours": "Nachbarzweige dazunehmen ({0})",
|
|
405
|
+
"result.addNeighboursHint": "Manche Adapter verteilen ein Gerät auf Geschwisterzweige. Das hier nimmt alle; einzelne wählt man mit Strg-Klick im Baum.",
|
|
406
|
+
"result.addNeighboursSame": "Diese Zweige gehören laut Adapter zu einem Gerät — dieselbe Node-Kennung und derselbe Verbindungspunkt. Das hier nimmt alle; einzelne wählt man mit Strg-Klick im Baum.",
|
|
378
407
|
"result.allAnyway": "Trotzdem alle ",
|
|
379
408
|
"result.channelsHint": "Dieses Gerät hat {0} Kanäle. Unten kannst du wählen: alles flach in einem Alias, oder die Struktur der Quelle übernehmen — ein Ordner für das Gerät, darunter je Kanal einer.",
|
|
380
409
|
"result.extraSwitches": "Mit dabei: {0} Punkte aus weiteren Kanälen, für die das {1}-Muster keinen Platz hat. Sie werden angelegt, gelten aber nicht als Schalter oder Rückmeldung des Geräts. Für getrennte Bedienung unten „je Kanal ein Gerät\" wählen.",
|
|
@@ -405,18 +434,32 @@
|
|
|
405
434
|
"roles.slotTaken": "belegt von {0}",
|
|
406
435
|
"swap.blocked": "Erst entscheiden — diese Punkte können nicht mitziehen: {0}. Entweder beim Tauschen entfernen oder den Tausch lassen; ein Punkt, der schreiben soll, braucht ein Schreibziel.",
|
|
407
436
|
"swap.button": "Quelle tauschen …",
|
|
437
|
+
"swap.byHandCheck": "Formel, Einheit und Wertebereich bleiben, wie sie am Alias stehen — bitte danach prüfen.",
|
|
438
|
+
"swap.byHandHint": "Diesen Punkt hast du selbst benannt — die Werkbank konnte ihn am neuen Gerät nicht ableiten.",
|
|
439
|
+
"swap.byHandMark": "von Hand",
|
|
408
440
|
"swap.diffRange": "Wertebereich {0} → {1}",
|
|
409
441
|
"swap.diffType": "Typ {0} → {1}",
|
|
410
442
|
"swap.diffUnit": "Einheit {0} → {1}",
|
|
411
443
|
"swap.done": "Getauscht. Der Alias liest jetzt aus {0}.",
|
|
444
|
+
"swap.factorField": "Faktor",
|
|
445
|
+
"swap.formula": "Formel",
|
|
446
|
+
"swap.formulaNone": "keine",
|
|
412
447
|
"swap.from": "Liest heute aus:",
|
|
448
|
+
"swap.fromAlias": "Über den Alias-Punkt selbst zugeordnet: unter der neuen Quelle liegt genau ein Punkt, der „{0}“ heißt und die Rolle „{1}“ trägt.",
|
|
449
|
+
"swap.fromAliasMark": "aus dem Alias",
|
|
450
|
+
"swap.fromDetect": "Zugeordnet wie beim Anklicken des Geräts im Baum: Die neue Quelle beschriftet ihre Punkte selbst, und der Detektor erkennt dort „{0}“.",
|
|
451
|
+
"swap.fromDetectMark": "erkannt",
|
|
452
|
+
"swap.fromTpl": "Zugeordnet wie beim Anklicken des Geräts im Baum: Auf die neue Quelle passt die Vorlage „{0}“, und die weiß, welcher Punkt zu diesem Platz gehört — samt Formel.",
|
|
453
|
+
"swap.fromTplMark": "aus der Vorlage",
|
|
413
454
|
"swap.goHigher": "eine Ebene höher nehmen",
|
|
414
455
|
"swap.gone": "Dieses Gerät gibt es nicht mehr — genau dafür ist dieser Weg gedacht.",
|
|
415
456
|
"swap.guessHint": "Die mit „vermutet“ gekennzeichneten Zeilen sind über Namen oder Rolle geraten — die bitte einzeln prüfen.",
|
|
457
|
+
"swap.guessedByAliasRole": "Über die Rolle des Alias-Punkts geraten: unter der neuen Quelle trägt genau ein Punkt die Rolle „{0}“. Bitte prüfen.",
|
|
416
458
|
"swap.guessedByName": "Über den Punktnamen geraten: unter der neuen Quelle heißt ebenfalls etwas „{0}\". Das kann weit danebenliegen — bitte prüfen.",
|
|
417
459
|
"swap.guessedByRole": "Über die Rolle geraten: unter der neuen Quelle trägt ein Punkt dieselbe Rolle „{0}\". Bitte prüfen.",
|
|
418
460
|
"swap.higherLevel": "Eine Ebene höher ({0}) finden {1} von {2} Punkten ein Ziel, hier nur {3}.",
|
|
419
461
|
"swap.keeps": "Der Alias behält seine Kennung, seine Namen, Rollen und Formeln, die Aufzeichnung in der Datenbank sowie Raum und Funktion. Geändert wird nur, woher jeder Punkt liest und wohin er schreibt.",
|
|
462
|
+
"swap.loadingValues": "Das neue Gerät wird gelesen …",
|
|
420
463
|
"swap.mapping": "Zuordnung",
|
|
421
464
|
"swap.mind": "Darauf achten:",
|
|
422
465
|
"swap.mindHint": "Die Formeln des Alias bleiben unverändert — rechnet die neue Quelle anders als die alte, stimmen die Werte danach nicht mehr. Die Formel steht in der Detailzeile des Punkts.",
|
|
@@ -424,13 +467,27 @@
|
|
|
424
467
|
"swap.noMatch": "kein passender Punkt gefunden",
|
|
425
468
|
"swap.noWriteMatch": "kein Schreibziel gefunden — dieser Punkt schreibt danach nirgendwohin",
|
|
426
469
|
"swap.now": "Jetzt tauschen",
|
|
470
|
+
"swap.pickByHand": "… oder selbst einen Punkt wählen",
|
|
427
471
|
"swap.pickFirst": "Erst eine neue Quelle wählen.",
|
|
428
472
|
"swap.removeIt": "diesen Punkt beim Tauschen entfernen",
|
|
429
473
|
"swap.same": "Das ist dieselbe Quelle wie bisher.",
|
|
430
474
|
"swap.search": "Suchen (Kennung oder Name) …",
|
|
475
|
+
"swap.suggestionHint": "Ein Vorschlag aus der Beschriftung — Klick setzt ihn ins Feld. Prüfe ihn an den beiden Werten darüber: die Beschriftung kann falsch sein.",
|
|
431
476
|
"swap.title": "Quelle tauschen",
|
|
432
477
|
"swap.to": "Neue Quelle",
|
|
478
|
+
"swap.tplDrop": "Gemerkte Vorlage mit entfernen ({0} Objekte)",
|
|
479
|
+
"swap.tplFormulas": "Die Formeln von {0} Punkten werden ohnehin durch die des neuen Geräts ersetzt — sie gehören zur Quelle, nicht zum Alias. Jede Zeile zeigt, was danach dort steht.",
|
|
480
|
+
"swap.tplGone": "Diese Vorlage gibt es nicht mehr.",
|
|
481
|
+
"swap.tplOther": "Auf die neue Quelle passt eine andere Vorlage: „{0}“. Sie lässt sich nach dem Tausch über die Vorlagenwahl anwenden — sie bringt ihre eigenen Formeln und Namen mit.",
|
|
482
|
+
"swap.tplStale": "Die gemerkte Vorlage „{0}“ passt nicht zur neuen Quelle",
|
|
433
483
|
"swap.unchanged": "unverändert",
|
|
484
|
+
"swap.unitChanged": "Einheit: am Alias {0} · neue Quelle: {1}",
|
|
485
|
+
"swap.unitField": "Einheit am Alias",
|
|
486
|
+
"swap.unitHistWarn": "An diesem Punkt hängt eine Aufzeichnung. Ihre Historie liegt in der alten Einheit — eine Reihe, die mittendrin den Faktor wechselt, lässt sich nicht reparieren.",
|
|
487
|
+
"swap.unitNoFactor": "Keine Umrechnung angeboten: Diese beiden Einheiten sind kein bekanntes Paar.",
|
|
488
|
+
"swap.unitNone": "keine",
|
|
489
|
+
"swap.unitResult": "Ergebnis: {0} {1}",
|
|
490
|
+
"swap.unitValOld": "Dein Alias zeigt heute: {0} {1}",
|
|
434
491
|
"swap.unknown": "(nicht ermittelbar)",
|
|
435
492
|
"target.alsoRoom": "Raum auch auf „{0}\" setzen?",
|
|
436
493
|
"target.alsoRoomNew": "Raum „{0}\" gibt es nicht — anlegen und zuordnen?",
|
|
@@ -574,11 +631,19 @@
|
|
|
574
631
|
"tpls.whichNumber": "Nummer dieses Ausgangs",
|
|
575
632
|
"tpls.wissen": "+ {0} weitere Punkte als Rollenwissen — greift in der Ansicht „Alle Datenpunkte des Geräts“",
|
|
576
633
|
"tree.aliases": "Alias bearbeiten",
|
|
634
|
+
"tree.branchAdd": "Diesen Zweig zur Auswahl dazunehmen",
|
|
635
|
+
"tree.branchForeign": "Diese Zweige liegen nicht in derselben Instanz. Ein Gerät liegt in einer Instanz — nimm Zweige, die einen gemeinsamen Elternknoten haben.",
|
|
636
|
+
"tree.branchHint": "Manche Adapter verteilen ein Gerät auf Geschwisterzweige — Matter legt den Schalter in den einen und die Messwerte in den anderen. Mehrere Zweige ergeben zusammen ein Gerät. Dasselbe wie Strg-Klick.",
|
|
637
|
+
"tree.branchRemove": "Diesen Zweig aus der Auswahl herausnehmen",
|
|
577
638
|
"tree.collapseAll": "alles zuklappen",
|
|
578
639
|
"tree.emptyNode": "keine Datenpunkte — der Knoten steht in der Datenbank, ist aber leer",
|
|
579
640
|
"tree.expandAll": "alles aufklappen",
|
|
641
|
+
"tree.exportMock": "Als Attrappe ausgeben",
|
|
642
|
+
"tree.exportMockHint": "Schreibt alles unterhalb von {0} in eine Datei: Objekte und aktuelle Werte, ohne native",
|
|
580
643
|
"tree.filter": "filtern …",
|
|
581
644
|
"tree.filterAria": "Objekte filtern",
|
|
645
|
+
"tree.importMock": "Attrappe einlesen …",
|
|
646
|
+
"tree.importMockHint": "Landet immer unter {0} — nie am Originalpfad",
|
|
582
647
|
"tree.loading": "lade Objekte …",
|
|
583
648
|
"tree.looksLikeDevice": "sieht wie ein einzelnes Gerät aus",
|
|
584
649
|
"tree.noObjectHint": "kein echter Ordner",
|
package/admin/i18n/en.json
CHANGED
|
@@ -259,6 +259,32 @@
|
|
|
259
259
|
"list.tplDiffers": "differs from the template",
|
|
260
260
|
"list.tplHint": "Checks exactly the points the template proposes — regardless of what the alias holds today.",
|
|
261
261
|
"list.willBeCreated": "will be created:",
|
|
262
|
+
"mock.colName": "Name",
|
|
263
|
+
"mock.colPath": "Path",
|
|
264
|
+
"mock.colRole": "Role",
|
|
265
|
+
"mock.colType": "Type",
|
|
266
|
+
"mock.colValue": "Value",
|
|
267
|
+
"mock.counts": "{0} entries, {1} with a value · written by alias-workbench {2} · source {3}",
|
|
268
|
+
"mock.inNames": "Watch out: {0} identifiers also sit in the path or in names — leaving out native does not remove those",
|
|
269
|
+
"mock.more": "… and {0} more entries (not shown, but they go into the file)",
|
|
270
|
+
"mock.noNative": "native is not included. Untick any value you do not want to pass on.",
|
|
271
|
+
"mock.save": "Save file",
|
|
272
|
+
"mock.suspicious": "Looks like: {0}",
|
|
273
|
+
"mock.tooBig": "That is a lot: {0} entries (a device usually has fewer than {1})",
|
|
274
|
+
"mock.tooBigHint": "Did you mean a single device? Exporting works anyway.",
|
|
275
|
+
"mockin.bad": "This file does not fit",
|
|
276
|
+
"mockin.badEntry": "{0} entries have no path.",
|
|
277
|
+
"mockin.badFormat": "Format {0}, but this version reads {1}.",
|
|
278
|
+
"mockin.badJson": "Not readable as JSON.",
|
|
279
|
+
"mockin.badObjects": "No objects in the file.",
|
|
280
|
+
"mockin.counts": "{0} objects, {1} with a value, {2} already there",
|
|
281
|
+
"mockin.create": "Create now",
|
|
282
|
+
"mockin.exists": "(already there)",
|
|
283
|
+
"mockin.from": "From {0} · written by alias-workbench {1} · source {2}",
|
|
284
|
+
"mockin.name": "Name",
|
|
285
|
+
"mockin.nameTaken": "The name “{0}” is taken — {1} objects already sit there",
|
|
286
|
+
"mockin.nameTakenHint": "Please choose a different name. Writing into an existing mock device would mix the two: only matching paths are replaced, the rest of the old one stays — and you would end up with a device that never existed.",
|
|
287
|
+
"mockin.noRoot": "The root entry is missing.",
|
|
262
288
|
"move.button": "Move …",
|
|
263
289
|
"move.done": "Moved. The alias is now at {0}.",
|
|
264
290
|
"move.exists": "{0} already exists. Remove it first or pick another name.",
|
|
@@ -375,6 +401,9 @@
|
|
|
375
401
|
"pattern.typeOr": " or ",
|
|
376
402
|
"pattern.usualOnly": "the usual ones only",
|
|
377
403
|
"pattern.viaRole": "role {0}",
|
|
404
|
+
"result.addNeighbours": "Add neighbouring branches ({0})",
|
|
405
|
+
"result.addNeighboursHint": "Some adapters split one device across sibling branches. This takes them all; Ctrl-click in the tree picks single ones.",
|
|
406
|
+
"result.addNeighboursSame": "These branches belong to one device according to the adapter — same node id and same online state. This takes them all; Ctrl-click in the tree picks single ones.",
|
|
378
407
|
"result.allAnyway": "All anyway ",
|
|
379
408
|
"result.channelsHint": "This device has {0} channels. Choose below: everything flat in one alias, or mirror the structure of the source — a folder for the device, one channel each below it.",
|
|
380
409
|
"result.extraSwitches": "Included: {0} points from other channels that the {1} pattern has no slot for. They are created, but do not count as the device’s switch or feedback. For separate control, use \"one device per channel\" below.",
|
|
@@ -405,18 +434,32 @@
|
|
|
405
434
|
"roles.slotTaken": "taken by {0}",
|
|
406
435
|
"swap.blocked": "Decide first — these points cannot come along: {0}. Either remove them during the swap or leave the swap be; a point that is meant to write needs a write target.",
|
|
407
436
|
"swap.button": "Swap source …",
|
|
437
|
+
"swap.byHandCheck": "Formula, unit and value range stay as they are on the alias — please check them afterwards.",
|
|
438
|
+
"swap.byHandHint": "You named this point yourself — the workbench could not derive it from the new device.",
|
|
439
|
+
"swap.byHandMark": "by hand",
|
|
408
440
|
"swap.diffRange": "range {0} → {1}",
|
|
409
441
|
"swap.diffType": "type {0} → {1}",
|
|
410
442
|
"swap.diffUnit": "unit {0} → {1}",
|
|
411
443
|
"swap.done": "Swapped. The alias now reads from {0}.",
|
|
444
|
+
"swap.factorField": "Factor",
|
|
445
|
+
"swap.formula": "Formula",
|
|
446
|
+
"swap.formulaNone": "none",
|
|
412
447
|
"swap.from": "Currently reads from:",
|
|
448
|
+
"swap.fromAlias": "Mapped from the alias point itself: exactly one point under the new source is called \"{0}\" and carries the role \"{1}\".",
|
|
449
|
+
"swap.fromAliasMark": "from alias",
|
|
450
|
+
"swap.fromDetect": "Mapped the same way as clicking the device in the tree: the new source labels its points itself, and the detector recognises \"{0}\" there.",
|
|
451
|
+
"swap.fromDetectMark": "recognised",
|
|
452
|
+
"swap.fromTpl": "Mapped the same way as clicking the device in the tree: the template \"{0}\" fits the new source and says which point belongs to this slot — including its formula.",
|
|
453
|
+
"swap.fromTplMark": "from template",
|
|
413
454
|
"swap.goHigher": "use the level above",
|
|
414
455
|
"swap.gone": "This device no longer exists — which is exactly what this is for.",
|
|
415
456
|
"swap.guessHint": "Rows marked “guessed” were matched by name or role — please check those individually.",
|
|
457
|
+
"swap.guessedByAliasRole": "Guessed from the role of the alias point: exactly one point under the new source carries the role \"{0}\". Please check.",
|
|
416
458
|
"swap.guessedByName": "Guessed from the point name: something under the new source is also called \"{0}\". That can be far off — please check.",
|
|
417
459
|
"swap.guessedByRole": "Guessed from the role: a point under the new source carries the same role \"{0}\". Please check.",
|
|
418
460
|
"swap.higherLevel": "One level up ({0}) finds a target for {1} of {2} points, here only {3}.",
|
|
419
461
|
"swap.keeps": "The alias keeps its id, names, roles and formulas, its history in the database and its room and function. Only where each point reads from and writes to changes.",
|
|
462
|
+
"swap.loadingValues": "Reading the new device …",
|
|
420
463
|
"swap.mapping": "Mapping",
|
|
421
464
|
"swap.mind": "Watch out:",
|
|
422
465
|
"swap.mindHint": "The alias formulas stay as they are — if the new source scales differently, the values will be wrong afterwards. The formula sits in the point's detail row.",
|
|
@@ -424,13 +467,27 @@
|
|
|
424
467
|
"swap.noMatch": "no matching point found",
|
|
425
468
|
"swap.noWriteMatch": "no write target found — this point will not write anywhere",
|
|
426
469
|
"swap.now": "Swap now",
|
|
470
|
+
"swap.pickByHand": "… or pick a point yourself",
|
|
427
471
|
"swap.pickFirst": "Pick a new source first.",
|
|
428
472
|
"swap.removeIt": "remove this point while swapping",
|
|
429
473
|
"swap.same": "That is the same source as before.",
|
|
430
474
|
"swap.search": "Search (id or name) …",
|
|
475
|
+
"swap.suggestionHint": "A suggestion from the labelling — click to put it in the field. Check it against the two values above: the labelling can be wrong.",
|
|
431
476
|
"swap.title": "Swap source",
|
|
432
477
|
"swap.to": "New source",
|
|
478
|
+
"swap.tplDrop": "Drop the remembered template as well ({0} objects)",
|
|
479
|
+
"swap.tplFormulas": "The formulas of {0} points are replaced by those of the new device anyway — they belong to the source, not to the alias. Each row shows what it will read afterwards.",
|
|
480
|
+
"swap.tplGone": "This template no longer exists.",
|
|
481
|
+
"swap.tplOther": "A different template fits the new source: \"{0}\". You can apply it after the swap via the template selector — it brings its own formulas and names.",
|
|
482
|
+
"swap.tplStale": "The remembered template \"{0}\" does not fit the new source",
|
|
433
483
|
"swap.unchanged": "unchanged",
|
|
484
|
+
"swap.unitChanged": "Unit: on the alias {0} · new source: {1}",
|
|
485
|
+
"swap.unitField": "Unit on the alias",
|
|
486
|
+
"swap.unitHistWarn": "A recording hangs on this point. Its history is in the old unit — a series that changes factor halfway cannot be repaired.",
|
|
487
|
+
"swap.unitNoFactor": "No conversion offered: these two units are not a known pair.",
|
|
488
|
+
"swap.unitNone": "none",
|
|
489
|
+
"swap.unitResult": "Result: {0} {1}",
|
|
490
|
+
"swap.unitValOld": "Your alias shows today: {0} {1}",
|
|
434
491
|
"swap.unknown": "(cannot be determined)",
|
|
435
492
|
"target.alsoRoom": "Set room to \"{0}\" as well?",
|
|
436
493
|
"target.alsoRoomNew": "There is no room \"{0}\" — create and assign it?",
|
|
@@ -574,11 +631,19 @@
|
|
|
574
631
|
"tpls.whichNumber": "Number of this output",
|
|
575
632
|
"tpls.wissen": "+ {0} more states as role knowledge — used in the “All data points of the device” view",
|
|
576
633
|
"tree.aliases": "Edit alias",
|
|
634
|
+
"tree.branchAdd": "Add this branch to the selection",
|
|
635
|
+
"tree.branchForeign": "Those branches are not in the same instance. A device lives in one instance — pick branches that share a parent.",
|
|
636
|
+
"tree.branchHint": "Some adapters split one device across sibling branches — Matter puts the switch in one and the meter in another. Several branches together form one device. Same as Ctrl-click.",
|
|
637
|
+
"tree.branchRemove": "Remove this branch from the selection",
|
|
577
638
|
"tree.collapseAll": "collapse all",
|
|
578
639
|
"tree.emptyNode": "no datapoints — the node exists in the database but is empty",
|
|
579
640
|
"tree.expandAll": "expand all",
|
|
641
|
+
"tree.exportMock": "Export as mock device",
|
|
642
|
+
"tree.exportMockHint": "Writes everything below {0} to a file: objects and current values, without native",
|
|
580
643
|
"tree.filter": "filter …",
|
|
581
644
|
"tree.filterAria": "Filter objects",
|
|
645
|
+
"tree.importMock": "Import mock device …",
|
|
646
|
+
"tree.importMockHint": "Always lands under {0} — never at the original path",
|
|
582
647
|
"tree.loading": "loading objects …",
|
|
583
648
|
"tree.looksLikeDevice": "looks like a single device",
|
|
584
649
|
"tree.noObjectHint": "not a real folder",
|
package/admin/i18n/es.json
CHANGED
|
@@ -259,6 +259,32 @@
|
|
|
259
259
|
"list.tplDiffers": "difiere de la plantilla",
|
|
260
260
|
"list.tplHint": "Comprueba exactamente los puntos que propone la plantilla, independientemente de lo que contenga actualmente el alias.",
|
|
261
261
|
"list.willBeCreated": "se creará:",
|
|
262
|
+
"mock.colName": "Nombre",
|
|
263
|
+
"mock.colPath": "Ruta",
|
|
264
|
+
"mock.colRole": "Rol",
|
|
265
|
+
"mock.colType": "Tipo",
|
|
266
|
+
"mock.colValue": "Valor",
|
|
267
|
+
"mock.counts": "{0} entradas, {1} con valor · escrito por alias-workbench {2} · origen {3}",
|
|
268
|
+
"mock.inNames": "Atención: {0} identificadores están también en la ruta o en los nombres — omitir `native` no los quita",
|
|
269
|
+
"mock.more": "… y {0} entradas más (no mostradas, pero van al archivo)",
|
|
270
|
+
"mock.noNative": "`native` no se incluye. Desmarca los valores que no quieras compartir.",
|
|
271
|
+
"mock.save": "Guardar archivo",
|
|
272
|
+
"mock.suspicious": "Parece: {0}",
|
|
273
|
+
"mock.tooBig": "Son muchas: {0} entradas (un dispositivo suele tener menos de {1})",
|
|
274
|
+
"mock.tooBigHint": "¿Querías un solo dispositivo? La exportación funciona igualmente.",
|
|
275
|
+
"mockin.bad": "Este archivo no sirve",
|
|
276
|
+
"mockin.badEntry": "{0} entradas no tienen ruta.",
|
|
277
|
+
"mockin.badFormat": "Formato {0}, pero esta versión lee {1}.",
|
|
278
|
+
"mockin.badJson": "No se puede leer como JSON.",
|
|
279
|
+
"mockin.badObjects": "No hay objetos en el archivo.",
|
|
280
|
+
"mockin.counts": "{0} objetos, {1} con valor, {2} ya existen",
|
|
281
|
+
"mockin.create": "Crear ahora",
|
|
282
|
+
"mockin.exists": "(ya existe)",
|
|
283
|
+
"mockin.from": "De {0} · escrito por alias-workbench {1} · origen {2}",
|
|
284
|
+
"mockin.name": "Nombre",
|
|
285
|
+
"mockin.nameTaken": "El nombre «{0}» ya existe — allí hay {1} objetos",
|
|
286
|
+
"mockin.nameTakenHint": "Elige otro nombre. Escribir en un dispositivo simulado existente mezclaría ambos: solo se sustituye lo que tiene la misma ruta, el resto del antiguo permanece — y saldría un dispositivo que nunca existió.",
|
|
287
|
+
"mockin.noRoot": "Falta la entrada de la raíz.",
|
|
262
288
|
"move.button": "Mover…",
|
|
263
289
|
"move.done": "Se ha trasladado. El alias se encuentra ahora en {0}.",
|
|
264
290
|
"move.exists": "{0} ya existe. Elimínalo primero o elige otro nombre.",
|
|
@@ -375,6 +401,9 @@
|
|
|
375
401
|
"pattern.typeOr": " o ",
|
|
376
402
|
"pattern.usualOnly": "solo los de siempre",
|
|
377
403
|
"pattern.viaRole": "papel {0}",
|
|
404
|
+
"result.addNeighbours": "Añadir ramas vecinas ({0})",
|
|
405
|
+
"result.addNeighboursHint": "Algunos adaptadores reparten un aparato entre ramas hermanas. Esto las toma todas; para elegir una sola, Ctrl+clic en el árbol.",
|
|
406
|
+
"result.addNeighboursSame": "Según el adaptador, estas ramas pertenecen a un aparato — mismo id de nodo y mismo punto de conexión. Esto las toma todas; si no, Ctrl+clic.",
|
|
378
407
|
"result.allAnyway": "En fin, todo ",
|
|
379
408
|
"result.channelsHint": "Este dispositivo tiene {0} canales. Elige una de las siguientes opciones: todo en un único alias, o replicar la estructura de la fuente —una carpeta para el dispositivo y un canal por debajo de cada una—.",
|
|
380
409
|
"result.extraSwitches": "Incluidos: {0} puntos de otros canales para los que el patrón {1} no dispone de ranura. Se crean, pero no cuentan como interruptor ni como retroalimentación del dispositivo. Para un control independiente, utiliza la opción «un dispositivo por canal» que aparece a continuación.",
|
|
@@ -405,18 +434,32 @@
|
|
|
405
434
|
"roles.slotTaken": "tomada por {0}",
|
|
406
435
|
"swap.blocked": "Decide primero: estos puntos no pueden incluirse: {0}. O bien los eliminas durante el intercambio o bien dejas el intercambio tal cual; un punto destinado a la escritura necesita un destino de escritura.",
|
|
407
436
|
"swap.button": "Intercambiar fuente…",
|
|
437
|
+
"swap.byHandCheck": "Fórmula, unidad y rango se quedan como están en el alias — compruébelos después.",
|
|
438
|
+
"swap.byHandHint": "Este punto lo ha indicado usted — el banco no pudo deducirlo del nuevo aparato.",
|
|
439
|
+
"swap.byHandMark": "a mano",
|
|
408
440
|
"swap.diffRange": "intervalo {0} → {1}",
|
|
409
441
|
"swap.diffType": "tipo {0} → {1}",
|
|
410
442
|
"swap.diffUnit": "unidad {0} → {1}",
|
|
411
443
|
"swap.done": "Se ha cambiado. El alias ahora lee desde {0}.",
|
|
444
|
+
"swap.factorField": "Factor",
|
|
445
|
+
"swap.formula": "Fórmula",
|
|
446
|
+
"swap.formulaNone": "ninguna",
|
|
412
447
|
"swap.from": "Actualmente se lee desde:",
|
|
448
|
+
"swap.fromAlias": "Asignado por el propio punto del alias: bajo la nueva fuente hay exactamente un punto llamado «{0}» con el rol «{1}».",
|
|
449
|
+
"swap.fromAliasMark": "del alias",
|
|
450
|
+
"swap.fromDetect": "Asignado igual que al pulsar en el árbol: la nueva fuente etiqueta sus propios puntos y el detector reconoce allí «{0}».",
|
|
451
|
+
"swap.fromDetectMark": "reconocido",
|
|
452
|
+
"swap.fromTpl": "Asignado igual que al pulsar el aparato en el árbol: a la nueva fuente le encaja la plantilla «{0}», que sabe qué punto corresponde a este puesto — fórmula incluida.",
|
|
453
|
+
"swap.fromTplMark": "de la plantilla",
|
|
413
454
|
"swap.goHigher": "utiliza el nivel superior",
|
|
414
455
|
"swap.gone": "Este dispositivo ya no existe, y precisamente para eso sirve esto.",
|
|
415
456
|
"swap.guessHint": "Las filas marcadas como «supuestas» se han emparejado por nombre o cargo; por favor, compruébalas una por una.",
|
|
457
|
+
"swap.guessedByAliasRole": "Deducido del rol del punto del alias: bajo la nueva fuente exactamente un punto tiene el rol «{0}». Compruébelo.",
|
|
416
458
|
"swap.guessedByName": "Por lo que se deduce del nombre del punto: hay algo en la nueva fuente que también se llama «{0}». Puede que esté muy lejos; compruébalo, por favor.",
|
|
417
459
|
"swap.guessedByRole": "Lo deduzco por la función: un punto debajo de la nueva fuente tiene la misma función «{0}». Por favor, compruébalo.",
|
|
418
460
|
"swap.higherLevel": "Un nivel más arriba ({0}) encuentra un objetivo para {1} de {2} puntos; aquí solo {3}.",
|
|
419
461
|
"swap.keeps": "El alias conserva su identificador, sus nombres, sus roles y sus fórmulas, su historial en la base de datos, así como su sala y su función. Lo único que cambia es el origen y el destino de las lecturas y escrituras de cada punto.",
|
|
462
|
+
"swap.loadingValues": "Leyendo el nuevo aparato …",
|
|
420
463
|
"swap.mapping": "Cartografía",
|
|
421
464
|
"swap.mind": "Cuidado:",
|
|
422
465
|
"swap.mindHint": "Las fórmulas de los alias se mantienen tal y como están: si la nueva fuente se escala de forma diferente, los valores serán erróneos posteriormente. La fórmula se encuentra en la fila de detalles del punto.",
|
|
@@ -424,13 +467,27 @@
|
|
|
424
467
|
"swap.noMatch": "No se ha encontrado ningún punto coincidente",
|
|
425
468
|
"swap.noWriteMatch": "No se ha encontrado ningún destino de escritura: este punto no se escribirá en ningún sitio",
|
|
426
469
|
"swap.now": "Cambia ahora",
|
|
470
|
+
"swap.pickByHand": "… o elija usted mismo un punto",
|
|
427
471
|
"swap.pickFirst": "Elige primero una nueva fuente.",
|
|
428
472
|
"swap.removeIt": "eliminar este punto al intercambiar",
|
|
429
473
|
"swap.same": "Es la misma fuente que antes.",
|
|
430
474
|
"swap.search": "Buscar (ID o nombre) …",
|
|
475
|
+
"swap.suggestionHint": "Una sugerencia del etiquetado — al pulsar se pone en el campo. Compruébela con los dos valores de arriba: la etiqueta puede estar mal.",
|
|
431
476
|
"swap.title": "Intercambiar fuente",
|
|
432
477
|
"swap.to": "Nueva fuente",
|
|
478
|
+
"swap.tplDrop": "Quitar también la plantilla recordada ({0} objetos)",
|
|
479
|
+
"swap.tplFormulas": "Las fórmulas de {0} puntos se sustituyen de todos modos por las del nuevo aparato — pertenecen a la fuente, no al alias. Cada fila muestra lo que quedará.",
|
|
480
|
+
"swap.tplGone": "Esta plantilla ya no existe.",
|
|
481
|
+
"swap.tplOther": "Otra plantilla encaja con la nueva fuente: «{0}». Puede aplicarla tras el cambio desde la selección de plantillas — trae sus propias fórmulas y nombres.",
|
|
482
|
+
"swap.tplStale": "La plantilla recordada «{0}» no encaja con la nueva fuente",
|
|
433
483
|
"swap.unchanged": "sin cambios",
|
|
484
|
+
"swap.unitChanged": "Unidad: en el alias {0} · nueva fuente: {1}",
|
|
485
|
+
"swap.unitField": "Unidad en el alias",
|
|
486
|
+
"swap.unitHistWarn": "Hay un registro asociado a este punto. Su histórico está en la unidad antigua — una serie que cambia de factor a mitad no se puede reparar.",
|
|
487
|
+
"swap.unitNoFactor": "Sin conversión: estas dos unidades no son un par conocido.",
|
|
488
|
+
"swap.unitNone": "ninguna",
|
|
489
|
+
"swap.unitResult": "Resultado: {0} {1}",
|
|
490
|
+
"swap.unitValOld": "Su alias muestra hoy: {0} {1}",
|
|
434
491
|
"swap.unknown": "(no se puede determinar)",
|
|
435
492
|
"target.alsoRoom": "¿También se debe establecer la sala en «{0}»?",
|
|
436
493
|
"target.alsoRoomNew": "No existe la carpeta «{0}»: ¿quieres crearla y asignarla?",
|
|
@@ -574,11 +631,19 @@
|
|
|
574
631
|
"tpls.whichNumber": "Número de esta salida",
|
|
575
632
|
"tpls.wissen": "+ {0} estados más como información de rol — se utiliza en la vista «Todos los puntos de datos del dispositivo»",
|
|
576
633
|
"tree.aliases": "Editar alias",
|
|
634
|
+
"tree.branchAdd": "Añadir esta rama a la selección",
|
|
635
|
+
"tree.branchForeign": "Esas ramas no están en la misma instancia. Un aparato vive en una instancia — elija ramas con un nodo padre común.",
|
|
636
|
+
"tree.branchHint": "Algunos adaptadores reparten un aparato entre ramas hermanas — Matter pone el interruptor en una y las medidas en otra. Varias ramas forman juntas un aparato. Lo mismo que Ctrl+clic.",
|
|
637
|
+
"tree.branchRemove": "Quitar esta rama de la selección",
|
|
577
638
|
"tree.collapseAll": "ocultar todo",
|
|
578
639
|
"tree.emptyNode": "No hay datos: el nodo existe en la base de datos, pero está vacío.",
|
|
579
640
|
"tree.expandAll": "Mostrar todo",
|
|
641
|
+
"tree.exportMock": "Exportar como dispositivo simulado",
|
|
642
|
+
"tree.exportMockHint": "Escribe todo lo que hay debajo de {0} en un archivo: objetos y valores actuales, sin native",
|
|
580
643
|
"tree.filter": "filtrar …",
|
|
581
644
|
"tree.filterAria": "Filtrar objetos",
|
|
645
|
+
"tree.importMock": "Importar dispositivo simulado …",
|
|
646
|
+
"tree.importMockHint": "Siempre acaba bajo {0} — nunca en la ruta original",
|
|
582
647
|
"tree.loading": "Cargando objetos…",
|
|
583
648
|
"tree.looksLikeDevice": "parece un único dispositivo",
|
|
584
649
|
"tree.noObjectHint": "no es una carpeta real",
|