diff --git a/README.md b/README.md index 01973e19..ec43a0dd 100644 --- a/README.md +++ b/README.md @@ -152,24 +152,24 @@ Both `.zpl` and `.json` round-trip cleanly. `.zpl` preserves all printable conte ## Coverage -107 of the 204 ZPL II commands tracked in the [roadmap](docs/zpl-roadmap.md) are supported today. Categorical breakdown: +113 of the 225 ZPL II commands tracked in the [roadmap](docs/zpl-roadmap.md) are supported today. Categorical breakdown: | Area | Supported | |---|---| | Layout & flow | 16 / 16 | | Templates & variables | 4 / 4 | | Barcodes | 28 / 28 | -| Fields | 17 / 20 | +| Fields | 18 / 20 | | Serialisation | 2 / 2 | -| Encoding & language | 3 / 4 | +| Encoding & language | 3 / 3 | | Clock & time | 3 / 3 | | Identity & access | 3 / 3 | | Graphics | 6 / 12 | -| Media & feed | 8 / 10 | +| Media & feed | 10 / 10 | | Text & fonts | 7 / 14 | -| Print quality | 7 / 16 | +| Print quality | 10 / 18 | | Configuration & persistence | 3 / 5 | -| Hardware / Host comm / RFID / Network | 0 / 67 | +| Hardware / Host comm / RFID / Network | 0 / 87 | --- diff --git a/docs/zpl-roadmap.md b/docs/zpl-roadmap.md index e771ba1c..7eb3bec8 100644 --- a/docs/zpl-roadmap.md +++ b/docs/zpl-roadmap.md @@ -6,16 +6,25 @@ What's supported, what's next, what's planned. | Mark | Meaning | |:-:|---| -| `[x]` | Supported in the current build | +| `[x]` | Supported: parsed on import, visible and editable in the UI, re-emitted on export. Two exemptions from the UI leg: structural commands (`^XA`, `^FS`, prefix changers) carry no user state, and control commands the app normalises (`^FW`/`^LR`/`^BY` into per-object properties, `^CI` into canonical UTF-8), where auto-management beats a manual field. Rows with a parenthesised caveat have a known sub-limitation (the import report flags it) but still count as supported | | `[ ]` | Not yet supported; the **Bucket** column says when | **Buckets** (for `[ ]` rows): | Bucket | What it means | |---|---| -| `Coming soon` | Next sweep of registry / parser work, no infrastructure dependency | -| `Native build` | Requires bidirectional printer connection (host queries, calibration feedback, RFID read, serial config); waits for Tauri | -| `Out of scope` | Intentionally not modelled (e.g. ~SE encoding-table tilde-form) — see related Modal-tab field for the supported alternative | +| `Coming soon` | Modellable in the designer / settings UI with no printer connection; next registry / parser sweep | +| `Native build` | Needs a connected printer or printer-resident state (host queries, calibration, downloads to printer storage, RFID hardware). Some rows are one-way data commands and candidates for the passthrough lane rather than full modelling | +| `Out of scope` | Intentionally not modelled; every such row states its reason inline (device-specific hardware like `^JW` PAX ribbon tension, legacy transport, or a superseding command) | + +Tracked scope: the ZPL II Programming Guide. Legacy-RFID-guide commands +(`^RA`, `^RE`, `^WF`, `^WV`) and `^WI` (duplicated by `^ND`) sit outside the +table; passthrough preserves them. +Convention: one row per command; prefix twins of the SAME command (e.g. +`^HL` / `~HL`) share a row unless their support status diverges (^PH/~PH, +^PP/~PP); distinct commands never share. The row total is +pinned in `scripts/gen-coverage.mjs`; adding or removing a row is a +deliberate act that must move the pin. The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encoding & Language / Identity) is now shipped; commands that didn't make the first cut sit under `Coming soon` and slot into the existing tab UI without infrastructure work. @@ -61,8 +70,8 @@ The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encodi | `[x]` | `^BY` | barcode field default | | | `[ ]` | `^FM` | PDF417/MicroPDF417 structured-append origins (niche; ignored by all other commands) | `Out of scope` | | `[x]` | `^FP` | vertical / reverse field layout (CJK / RTL) | | -| `[ ]` | `^CO` | font cache size | `Coming soon` | -| `[ ]` | `^CP` | change parser | `Coming soon` | +| `[x]` | `^CO` | font cache size (scalable character cache) | | +| `[ ]` | `^CP` | kiosk remove label: eject / retract presented page (KR403 only) | `Out of scope` | | `[x]` | `^CV` | code validation | | ## Text & fonts @@ -71,17 +80,17 @@ The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encodi |:-:|---|---|---| | `[x]` | `^A0` | scalable font 0 | | | `[x]` | `^A` | fonts A to Z, 0 to 9 (best effort sizing) | | -| `[x]` | `^A@` | TrueType reference | | +| `[x]` | `^A@` | TrueType reference (face not imported; best-effort sizing) | | | `[x]` | `^CF` | change default font | | | `[x]` | `^CI` | international encoding | | | `[x]` | `^CW` | font alias (printer resident) | | | `[x]` | `^FL` | font linking | | | `[ ]` | `^LF` | list font links | `Native build` | -| `[ ]` | `~DB` | download bitmap font | `Native build` | -| `[ ]` | `~DS` | download scalable font | `Native build` | -| `[ ]` | `~DT` | download TrueType font | `Native build` | -| `[ ]` | `~DU` | download unbounded TrueType | `Native build` | -| `[ ]` | `~DE` | download encoding | `Native build` | +| `[ ]` | `~DB` | download bitmap font (one-way payload; passthrough candidate) | `Native build` | +| `[ ]` | `~DS` | download scalable font (one-way payload; passthrough candidate) | `Native build` | +| `[ ]` | `~DT` | download TrueType font (one-way payload; passthrough candidate) | `Native build` | +| `[ ]` | `~DU` | download unbounded TrueType (one-way payload; passthrough candidate) | `Native build` | +| `[ ]` | `~DE` | download encoding (one-way payload; passthrough candidate) | `Native build` | | `[ ]` | `~DN` | abort download | `Native build` | ## Barcodes @@ -105,7 +114,7 @@ The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encodi | `[x]` | `^B9` | UPC E | | | `[x]` | `^BR` | GS1 Databar | | | `[x]` | `^B5` | Planet Code | | -| `[x]` | `^BZ` | POSTNET | | +| `[x]` | `^BZ` | POSTNET / Intelligent Mail / Planet | | | `[x]` | `^BS` | UPC / EAN 2 or 5 digit supplement | | | `[x]` | `^B4` | Code 49 | | | `[x]` | `^BQ` | QR Code | | @@ -114,7 +123,7 @@ The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encodi | `[x]` | `^BF` | MicroPDF417 | | | `[x]` | `^B0` / `^BO` | Aztec | | | `[x]` | `^BB` | CODABLOCK F | | -| `[x]` | `^BV` | UPS MaxiCode (also accepts `^BD` on some firmware generations as an alias) | | +| `[x]` | `^BD` | UPS MaxiCode | | | `[x]` | `^BT` | TLC39 | | ## Graphics @@ -125,21 +134,21 @@ The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encodi | `[x]` | `^GD` | diagonal line | | | `[x]` | `^GE` | ellipse | | | `[x]` | `^GC` | circle | | -| `[x]` | `^GF` | monochrome bitmap | | +| `[x]` | `^GF` | monochrome bitmap (^GFA and B64/Z64-wrapped B/C; raw binary skipped) | | | `[x]` | `^GS` | graphic symbol (printer resident chars) | | | `[ ]` | `^IL` | image load | `Native build` | | `[ ]` | `^IM` | image move | `Native build` | -| `[ ]` | `^ID` | image delete | `Native build` | +| `[ ]` | `^ID` | object delete: graphics, fonts, stored formats (wildcards) | `Native build` | | `[ ]` | `^IS` | image save | `Native build` | -| `[ ]` | `~DG` | download graphic | `Native build` | +| `[ ]` | `~DG` | download graphic (one-way payload; passthrough candidate) | `Native build` | | `[ ]` | `~EG` | erase download graphics | `Native build` | ## Serialisation | Status | Command | Description | Bucket | |:-:|---|---|---| -| `[x]` | `^SN` | counter (post field) | | -| `[x]` | `^SF` | counter (pre field) | | +| `[x]` | `^SN` | serial counter, own start value | | +| `[x]` | `^SF` | serial mask over ^FD data | | ## Templates & variables @@ -159,9 +168,9 @@ The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encodi | `[x]` | `^MF` | media feed | | | `[x]` | `^XB` | suppress backfeed | | | `[x]` | `^MA` | maintenance alert | | -| `[ ]` | `^MC` | map clear | `Coming soon` | +| `[x]` | `^MC` | map clear (N retains the bitmap behind subsequent labels) | | | `[x]` | `^MI` | maintenance info message | | -| `[ ]` | `^MP` | mode protection | `Coming soon` | +| `[x]` | `^MP` | mode protection (panel lockdown; E re-enables) | | | `[x]` | `^MU` | units of measure | | | `[x]` | `^MW` | head cold warning | | @@ -174,14 +183,16 @@ The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encodi | `[x]` | `~TA` | tear off adjust | | | `[x]` | `^PA` | advanced text properties | | | `[x]` | `^JH` | early warning settings | | -| `[x]` | `~JS` | change backfeed sequence | | -| `[ ]` | `^PF` | slew given number of dot rows | `Coming soon` | -| `[ ]` | `^PH` | slew home (feed one blank label) | `Coming soon` | -| `[ ]` | `~PH` | slew home (immediate) | `Native build` | -| `[ ]` | `^PP` | programmable pause (in format) | `Coming soon` | +| `[x]` | `~JS` | change backfeed sequence (A/B/N/O or percent 10-90) | | +| `[x]` | `^PF` | slew given number of dot rows | | +| `[x]` | `^PH` | slew home (feed one blank label) | | +| `[ ]` | `~PH` | slew home (control form; after current format or at pause) | `Native build` | +| `[x]` | `^PP` | programmable pause (in format) | | | `[ ]` | `~PP` | pause (immediate) | `Native build` | | `[ ]` | `~PR` | applicator reprint | `Native build` | | `[ ]` | `~PS` | print start (resume from pause) | `Native build` | +| `[ ]` | `^CN` | cut now (KR403 kiosk cutter) | `Out of scope` | +| `[ ]` | `~PL` | present length addition (KR403 kiosk presenter) | `Out of scope` | | `[ ]` | `^PN` | presenter cycle (KR403 kiosk only) | `Out of scope` | | `[ ]` | `^JW` | set ribbon tension (PAX series only) | `Out of scope` | | `[x]` | `^JU` | configuration update | | @@ -201,7 +212,6 @@ The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encodi | `[x]` | `^KL` | define language | | | `[x]` | `^SE` | encoding table | | | `[x]` | `^SZ` | set ZPL mode | | -| `[ ]` | `~SE` | encoding table (tilde-form, immediate) | `Out of scope` | ## Identity & access @@ -228,16 +238,20 @@ These need printer-side feedback or are intrinsically connection bound. | Status | Command | Description | Bucket | |:-:|---|---|---| | `[ ]` | `~JA` | cancel all | `Native build` | -| `[ ]` | `^JB` / `~JB` | initialize flash / reset | `Native build` | +| `[ ]` | `^JB` | initialize flash memory | `Native build` | +| `[ ]` | `~JB` | reset optional memory (battery models) | `Native build` | | `[ ]` | `~JC` | media sensor calibration | `Native build` | -| `[ ]` | `~JD` / `~JE` | enable / disable comm diagnostics | `Native build` | -| `[ ]` | `~JF` | set battery condition | `Native build` | +| `[ ]` | `~JD` | enable communications diagnostics | `Native build` | +| `[ ]` | `~JE` | disable communications diagnostics | `Native build` | +| `[ ]` | `~JF` | set battery condition (PA/PT400 battery printers) | `Out of scope` | | `[ ]` | `~JG` | graphing sensor calibration | `Native build` | -| `[ ]` | `~JI` | start ZBI | `Native build` | +| `[ ]` | `^JI` / `~JI` | start ZBI | `Native build` | | `[ ]` | `^JJ` | set auxiliary port | `Native build` | +| `[ ]` | `^JS` | sensor select (reflective / transmissive) | `Native build` | | `[ ]` | `~JL` | set label length | `Native build` | -| `[ ]` | `^JM` | set dots per millimeter | `Native build` | -| `[ ]` | `~JN` / `~JO` | head test fatal / non fatal | `Native build` | +| `[ ]` | `^JM` | set dots per millimeter (B halves density and doubles format scale; A = normal, default) | `Coming soon` | +| `[ ]` | `~JN` | head test fatal | `Native build` | +| `[ ]` | `~JO` | head test non-fatal | `Native build` | | `[ ]` | `~JP` | pause and cancel format | `Native build` | | `[ ]` | `~JQ` | terminate ZBI | `Native build` | | `[ ]` | `~JR` | power on reset | `Native build` | @@ -245,8 +259,8 @@ These need printer-side feedback or are intrinsically connection bound. | `[ ]` | `~RO` | reset advanced counter | `Native build` | | `[ ]` | `^SC` | set serial comm | `Native build` | | `[ ]` | `^SI` | set sensor intensity | `Native build` | -| `[ ]` | `^SP` | start ZBI program | `Native build` | -| `[ ]` | `^SQ` | halt ZBI execution | `Native build` | +| `[ ]` | `^SP` | start print at dot row (throughput hint, no visual effect) | `Out of scope` | +| `[ ]` | `^SQ` | halt ZebraNet alert (companion to ^SX) | `Native build` | | `[ ]` | `^SR` | set printhead resistance | `Native build` | | `[ ]` | `^SS` | set media sensors | `Native build` | | `[ ]` | `^SX` | set ZebraNet alert | `Native build` | @@ -254,15 +268,17 @@ These need printer-side feedback or are intrinsically connection bound. | `[ ]` | `~WC` | print configuration label | `Native build` | | `[ ]` | `^WD` | print directory label | `Native build` | | `[ ]` | `~WQ` | write query | `Native build` | -| `[ ]` | `^WT` | write tag (RFID) | `Native build` | +| `[ ]` | `^WT` | legacy RFID write; superseded by ^RF | `Out of scope` | +| `[ ]` | `^KV` | kiosk values: cutter / presenter config (KR403 only) | `Out of scope` | | `[ ]` | `^XS` | set dynamic media calibration | `Native build` | -| `[ ]` | `^ZZ` | printer sleep | `Native build` | +| `[ ]` | `~PM` | decommissioning mode | `Native build` | +| `[ ]` | `^ZZ` | printer sleep (PA/PT400 only) | `Out of scope` | ## Host communication | Status | Command | Description | Bucket | |:-:|---|---|---| -| `[ ]` | `~HB` | battery status | `Native build` | +| `[ ]` | `~HB` | battery status (mobile printers) | `Out of scope` | | `[ ]` | `~HD` | head diagnostic | `Native build` | | `[ ]` | `^HF` | host format | `Native build` | | `[ ]` | `^HG` | host graphic | `Native build` | @@ -274,38 +290,57 @@ These need printer-side feedback or are intrinsically connection bound. | `[ ]` | `^HT` | host linked fonts list | `Native build` | | `[ ]` | `~HU` | ZebraNet alert config | `Native build` | | `[ ]` | `^HV` | host verification | `Native build` | -| `[ ]` | `^KV` | firmware version query | `Native build` | | `[ ]` | `^HW` | host directory | `Native build` | | `[ ]` | `^HY` | upload graphics | `Native build` | | `[ ]` | `^HZ` | display description info | `Native build` | ## RFID +Needs an R-series printer, which no test device covers; modelled rows are +spec-only. Stage A: ^RS/^RB/^RW settings. Stage B: ^RF write element plus its +password-coupled ^RL. Read-back stays native. ^RM/^RR folded into ^RS, +^RN/~RV dropped from the current guide; all four passthrough only. + | Status | Command | Description | Bucket | |:-:|---|---|---| -| `[ ]` | `^RF` | read / write RFID | `Native build` | +| `[ ]` | `^RF` | read / write RFID (write path plannable; read-back stays native) | `Coming soon` | | `[ ]` | `^RI` | get tag ID | `Native build` | -| `[ ]` | `^RM` | enable motion | `Native build` | -| `[ ]` | `^RN` | detect multiple tags | `Native build` | -| `[ ]` | `^RQ` | quick write | `Native build` | -| `[ ]` | `^RR` | read timeout | `Native build` | -| `[ ]` | `^RS` | RFID setup | `Native build` | -| `[ ]` | `^RT` | read tag | `Native build` | -| `[ ]` | `^RU` | read UHF | `Native build` | -| `[ ]` | `^RV` | report encoding result | `Native build` | -| `[ ]` | `^RW` | set read & write power | `Native build` | -| `[ ]` | `^RZ` | set tag password | `Native build` | -| `[ ]` | `^HL` | RFID data log | `Native build` | +| `[ ]` | `^RM` | enable motion (pre-Link-OS; folded into ^RS; passthrough) | `Out of scope` | +| `[ ]` | `^RN` | detect multiple tags (pre-Link-OS; absent from current guide; passthrough) | `Out of scope` | +| `[ ]` | `^RR` | RFID retries (pre-Link-OS; folded into ^RS; passthrough) | `Out of scope` | +| `[ ]` | `^RB` | define EPC data structure (partitions consumed by ^RF EPC writes) | `Coming soon` | +| `[ ]` | `^RS` | RFID setup (tag type, programming position, retries, error handling) | `Coming soon` | +| `[ ]` | `^RT` | read tag (legacy; superseded by ^RF read) | `Native build` | +| `[ ]` | `^RU` | read unique chip serialization (TID-derived EPC serial) | `Native build` | +| `[ ]` | `~RV` | report encoding result (pre-Link-OS; absent from current guide; passthrough) | `Out of scope` | +| `[ ]` | `^RW` | set read & write power | `Coming soon` | +| `[ ]` | `^RL` | lock / permalock tag memory (password-coupled companion of ^RF) | `Coming soon` | +| `[ ]` | `^HR` | calibrate RFID tag position | `Native build` | +| `[ ]` | `^HL` / `~HL` | RFID data log (return to host) | `Native build` | ## Network | Status | Command | Description | Bucket | |:-:|---|---|---| -| `[ ]` | `^NB` | search network printer | `Native build` | -| `[ ]` | `^NC` / `~NC` | primary network device | `Native build` | -| `[ ]` | `^NI` | network ID | `Native build` | +| `[ ]` | `^NB` | check for wired print server at boot | `Native build` | +| `[ ]` | `^NC` | select wired / wireless primary device | `Native build` | +| `[ ]` | `~NC` | network connect (legacy RS-485 multidrop addressing) | `Out of scope` | +| `[ ]` | `^NI` | network ID (legacy RS-485 multidrop addressing) | `Out of scope` | | `[ ]` | `^NN` | set SNMP | `Native build` | -| `[ ]` | `^NP` | primary / backup device | `Native build` | -| `[ ]` | `~NR` | set all network printers transparent | `Native build` | -| `[ ]` | `~NT` | set SMTP | `Native build` | +| `[ ]` | `^NP` | boot settings source: printer vs print server | `Native build` | +| `[ ]` | `~NR` | set all transparent (legacy RS-485 multidrop addressing) | `Out of scope` | +| `[ ]` | `^NT` | set SMTP | `Native build` | +| `[ ]` | `~NT` | set connected printer transparent (legacy RS-485 multidrop addressing) | `Out of scope` | | `[ ]` | `^NW` | web auth timeout | `Native build` | +| `[ ]` | `^KC` | set client identifier (DHCP option 61) | `Native build` | +| `[ ]` | `^ND` | change network settings | `Native build` | +| `[ ]` | `^NS` | change wired network settings | `Native build` | +| `[ ]` | `^WA` | set antenna parameters | `Native build` | +| `[ ]` | `^WE` | set WEP mode (obsolete wireless security; use ^WX) | `Out of scope` | +| `[ ]` | `^WL` | set LEAP (obsolete wireless security; use ^WX) | `Out of scope` | +| `[ ]` | `^WP` | set wireless password | `Native build` | +| `[ ]` | `^WR` | set transmit rate | `Native build` | +| `[ ]` | `^WS` | set wireless radio card values | `Native build` | +| `[ ]` | `^WX` | configure wireless security | `Native build` | +| `[ ]` | `~WL` | print network configuration label | `Native build` | +| `[ ]` | `~WR` | reset wireless radio card | `Native build` | diff --git a/packages/core/src/lib/zplGenerator.ts b/packages/core/src/lib/zplGenerator.ts index 15433086..73950872 100644 --- a/packages/core/src/lib/zplGenerator.ts +++ b/packages/core/src/lib/zplGenerator.ts @@ -448,6 +448,14 @@ export function planFieldEmission( return { headerLines, bodyLines: shifted.flatMap(emitLeaf) }; } +/** Positional-command slots with trailing empties dropped, so unset + * params fall back to the printer's own defaults on the wire. */ +export function trimTrailingEmptySlots(slots: readonly string[]): string[] { + const trimmed = [...slots]; + while (trimmed.length > 0 && trimmed[trimmed.length - 1] === "") trimmed.pop(); + return trimmed; +} + export function generateZPL( label: LabelConfig, objects: LabelObject[], @@ -531,6 +539,11 @@ export function generateZPL( if (label.darkness !== undefined) lines.push(`^MD${label.darkness}`); if (label.printOrientation) lines.push(`^PO${label.printOrientation}`); if (label.mirror) lines.push(`^PM${label.mirror}`); + if (label.mapClear) lines.push(`^MC${label.mapClear}`); + // slewDotRows=0 is a valid explicit "no slew"; check undefined. + if (label.slewDotRows !== undefined) lines.push(`^PF${label.slewDotRows}`); + if (label.slewToHome) lines.push('^PH'); + if (label.programmablePause) lines.push('^PP'); // ^LH / ^LT subtract below from per-field absolute (x,y) so emit matches editor. const homeX = label.labelHomeX ?? 0; const homeY = label.labelHomeY ?? 0; @@ -552,12 +565,11 @@ export function generateZPL( label.defaultFontHeight !== undefined || label.defaultFontWidth !== undefined ) { - const slots = [ + const slots = trimTrailingEmptySlots([ label.defaultFontId ?? "", label.defaultFontHeight !== undefined ? String(label.defaultFontHeight) : "", label.defaultFontWidth !== undefined ? String(label.defaultFontWidth) : "", - ]; - while (slots.length > 1 && slots[slots.length - 1] === "") slots.pop(); + ]); lines.push(`^CF${slots.join(",")}`); } diff --git a/packages/core/src/lib/zplParser.ts b/packages/core/src/lib/zplParser.ts index 10041c4b..eed11fbd 100644 --- a/packages/core/src/lib/zplParser.ts +++ b/packages/core/src/lib/zplParser.ts @@ -152,8 +152,12 @@ export function parseZPL( // ^DY font uploads are intentionally not flagged. const replayRiskCodes = new Set(Object.keys(setupScriptHandlers)); const deviceActionCodes = new Set([ - "JA", "JM", "JC", "JD", "JE", "JI", "JR", "PP", + "JA", "JM", "JC", "JD", "JE", "JI", "JR", ]); + // ^PH/^PP are modelled per-format settings, but their tilde twins are + // immediate device controls; the handler map keys have no prefix, so the + // split happens at dispatch via the token's source char. + const tildeDeviceCodes = new Set(["PH", "PP"]); Object.assign(handlers, setupScriptHandlers); Object.assign(handlers, createLabelConfigHandlers(s, dpmm)); Object.assign(handlers, createUnitsHandler(s, dpmm)); @@ -323,6 +327,12 @@ export function parseZPL( const p = rest.split(s.format.delimiterChar); // Flag printer-config commands: lossless replay re-emits them, so they run // on the user's printer at print/export. Recorded by code (deduped later). + // ~PH/~PP: flagged as device actions AND skipped entirely, or they would + // fall through to the unknown bucket and surface twice in the summary. + if (tildeDeviceCodes.has(cmd) && zpl[start] === s.format.tildeChar) { + deviceAction.push(`~${cmd}`); + continue; + } if (replayRiskCodes.has(cmd)) replayRisk.push(`^${cmd}`); else if (deviceActionCodes.has(cmd)) deviceAction.push(`^${cmd}`); const handler = handlers[cmd] ?? wildcards.find((w) => w.matches(cmd))?.handle; diff --git a/packages/core/src/lib/zplParser/handlers/barcodes.ts b/packages/core/src/lib/zplParser/handlers/barcodes.ts index 7a20960c..6061fcfe 100644 --- a/packages/core/src/lib/zplParser/handlers/barcodes.ts +++ b/packages/core/src/lib/zplParser/handlers/barcodes.ts @@ -153,15 +153,12 @@ export function createBarcodeHandlers(s: ParserState): Record { B0: handleAztec, BO: handleAztec, - // ^BVo,{mode},{symbolNumber},{totalSymbols}: Maxicode (fixed - // physical size, no magnification). symbolNumber/totalSymbols - // describe structured-append composition; we don't expose that - // in the editor, so the params are read but the emitted form - // pins them to (1, 1). - // ^BV orientation slot is a firmware no-op; canonicalized on emit. - BV(p) { + // ^BDm,{symbolNumber},{totalSymbols}: Maxicode (spec p106; fixed + // physical size, no orientation slot). Structured-append params are + // read but pinned to (1,1) on emit. + BD(p) { field.fieldType = "maxicode"; - const m = int(p[1], 4); + const m = int(p[0], 4); field.maxicodeMode = (m >= 2 && m <= 6 ? m : 4) as MaxicodeProps["mode"]; }, diff --git a/packages/core/src/lib/zplParser/handlers/labelConfig.ts b/packages/core/src/lib/zplParser/handlers/labelConfig.ts index eb58c8dd..09e2397a 100644 --- a/packages/core/src/lib/zplParser/handlers/labelConfig.ts +++ b/packages/core/src/lib/zplParser/handlers/labelConfig.ts @@ -1,5 +1,6 @@ -import { DARKNESS_INSTANT_RANGE, DARKNESS_PERMANENT_RANGE, MAX_LABEL_LENGTH_RANGE, SPEED_RANGE, isBackfeedSequence, isMediaFeedMode, isMediaMode, isMediaTracking, isMediaType, isPrintOrientation } from "../../../types/LabelConfig"; +import { DARKNESS_INSTANT_RANGE, DARKNESS_PERMANENT_RANGE, MAX_LABEL_LENGTH_RANGE, SLEW_DOT_ROWS_RANGE, SPEED_RANGE, isBackfeedPercent, isBackfeedSequence, isMediaFeedMode, isMediaMode, isMediaTracking, isMediaType, isPrintOrientation } from "../../../types/LabelConfig"; import { parseIntOrUndef } from "../../inputParse"; +import { isYesNo } from "../../../types/typeHelpers"; import type { ParserState } from "../context"; import { dotsFor, firstChar, inRange, int, strParam } from "../helpers"; import type { Handler } from "../types"; @@ -38,7 +39,7 @@ export function createLabelConfigHandlers( } if (p.length > 3) { const o = (p[3] ?? "").toUpperCase(); - if (o === "Y" || o === "N") labelConfig.overridePauseCount = o; + if (isYesNo(o)) labelConfig.overridePauseCount = o; } }, MM(_, rest) { @@ -65,6 +66,22 @@ export function createLabelConfigHandlers( const mt = firstChar(rest); if (isMediaType(mt)) labelConfig.mediaType = mt; }, + MC(p) { + const v = strParam(p[0]); + if (isYesNo(v)) labelConfig.mapClear = v; + }, + PF(p) { + const v = inRange(parseIntOrUndef(p[0]), SLEW_DOT_ROWS_RANGE); + if (v !== undefined) labelConfig.slewDotRows = v; + }, + // ^PH/^PP take no parameters; the tilde forms never reach these handlers + // (dispatch routes them as device actions). + PH() { + labelConfig.slewToHome = true; + }, + PP() { + labelConfig.programmablePause = true; + }, MN(p) { // ^MNa,b: b is an optional black-mark offset for W/M modes, // which we don't model. Reading p[0] instead of the raw rest @@ -92,7 +109,7 @@ export function createLabelConfigHandlers( }, PM(_, rest) { const m = firstChar(rest); - if (m === "Y" || m === "N") labelConfig.mirror = m; + if (isYesNo(m)) labelConfig.mirror = m; }, // ~SD: instant darkness set (00..30). Tilde-prefix, so the tokenizer // drops the delimiter and this is the canonical SD handler. @@ -100,12 +117,18 @@ export function createLabelConfigHandlers( const v = inRange(parseIntOrUndef(rest), DARKNESS_INSTANT_RANGE); if (v !== undefined) labelConfig.instantDarkness = v; }, - // ~JS: change backfeed sequence. A/B/N/O modeled; percent forms - // (10-90) aren't, so track them as a partial-import loss. + // ~JS: change backfeed sequence. Percent forms round to the nearest + // ten like the printer does (~JS55 -> 60, p276). JS(_, rest) { const v = firstChar(rest); - if (isBackfeedSequence(v)) labelConfig.backfeedSequence = v; - else if (rest) s.result.partialCmds.add("~JS"); + if (isBackfeedSequence(v)) { + labelConfig.backfeedSequence = v; + return; + } + const pct = inRange(parseIntOrUndef(rest), { min: 10, max: 90 }); + if (pct === undefined) return; + const rounded = Math.round(pct / 10) * 10; + if (isBackfeedPercent(rounded)) labelConfig.backfeedSequence = rounded; }, }; } diff --git a/packages/core/src/lib/zplParser/handlers/setupScript.ts b/packages/core/src/lib/zplParser/handlers/setupScript.ts index e385c23e..6e22dc3d 100644 --- a/packages/core/src/lib/zplParser/handlers/setupScript.ts +++ b/packages/core/src/lib/zplParser/handlers/setupScript.ts @@ -1,19 +1,55 @@ -import { CLOCK_TOLERANCE_RANGE, FONT_LINKS_PATH_MAX_LEN, HEAD_CLEANING_INTERVAL_METERS, HEAD_TEST_INTERVAL_RANGE, JH_SLOT_F, JH_SLOT_G, MAINTENANCE_ALERT_DEFAULTS, MAINTENANCE_DISTANCE_MAX_BY_TYPE, MAINTENANCE_MESSAGE_MAX_LEN, PRINTER_NAME_MAX_LEN, PRINTER_PASSWORD_REGEX, TEAR_OFF_ADJUST_RANGE, isClockFormat, isClockLanguage, isConfigUpdateAction, isMaintenanceAlertPrint, isMaintenanceAlertType, isMaintenanceAlertUnit, isPrinterLocale, isZplMode, setupScriptUnsafeCharRegex } from "../../../types/PrinterProfile"; +import { CLOCK_TOLERANCE_RANGE, FONT_CACHE_KB_RANGE, FONT_LINKS_PATH_MAX_LEN, HEAD_CLEANING_INTERVAL_METERS, HEAD_TEST_INTERVAL_RANGE, JH_SLOT_F, JH_SLOT_G, MAINTENANCE_ALERT_DEFAULTS, MAINTENANCE_DISTANCE_MAX_BY_TYPE, MAINTENANCE_MESSAGE_MAX_LEN, PRINTER_NAME_MAX_LEN, PRINTER_PASSWORD_REGEX, TEAR_OFF_ADJUST_RANGE, isClockFormat, isClockLanguage, isConfigUpdateAction, isFontCacheType, isMaintenanceAlertPrint, isMaintenanceAlertType, isMaintenanceAlertUnit, isModeProtection, isPrinterLocale, isZplMode, setupScriptUnsafeCharRegex } from "../../../types/PrinterProfile"; import { parseIntOrUndef } from "../../inputParse"; +import { isYesNo } from "../../../types/typeHelpers"; import { parseRealtimeClock } from "../../realtimeClock"; import type { ParserState } from "../context"; import { inRange, strParam } from "../helpers"; import type { Handler } from "../types"; -/** Setup-Script commands (^JZ, ^JT, ~TA, ^ST, ^KD, ^KL, ^SE, ^SZ, - * ^KN, ^SL, ^KP, ^MA, ^MI, ^MW, ^JH, ^JU): all write the shared - * `printerProfile` slice. */ +/** Setup-Script command handlers: all write the shared `printerProfile` slice. */ export function createSetupScriptHandlers(s: ParserState): Record { const printerProfile = s.result.printerProfile; return { + // Each ^CO is a complete command: an empty slot means the printer's own + // default, so it clears a value an earlier ^CO in the stream had set. + CO(p) { + const on = strParam(p[0]); + // A fully-empty ^CO would parse to nothing and vanish on re-emit; + // normalise it to its a-slot default (Y, cache on) instead. + if (on === "" && strParam(p[1]) === "" && strParam(p[2]) === "") { + printerProfile.fontCacheOn = "Y"; + delete printerProfile.fontCacheAddKb; + delete printerProfile.fontCacheType; + return; + } + if (on === "") delete printerProfile.fontCacheOn; + else if (isYesNo(on)) printerProfile.fontCacheOn = on; + const rawKb = strParam(p[1]); + if (rawKb === "") delete printerProfile.fontCacheAddKb; + else { + const kb = inRange(parseIntOrUndef(rawKb), FONT_CACHE_KB_RANGE); + if (kb !== undefined) printerProfile.fontCacheAddKb = kb; + } + const type = strParam(p[2]); + if (type === "") delete printerProfile.fontCacheType; + else if (isFontCacheType(type)) printerProfile.fontCacheType = type; + }, + MP(p) { + const v = strParam(p[0]); + // E re-enables all modes, wiping the protection set. It also anchors + // the set as absolute; without it the stream only ADDS modes and the + // emitter must not inject a resetting ^MPE baseline. + if (v === "E") { + printerProfile.modeProtection = []; + printerProfile.modeProtectionExplicit = true; + } else if (isModeProtection(v)) { + const set = printerProfile.modeProtection ?? []; + if (!set.includes(v)) printerProfile.modeProtection = [...set, v]; + } + }, JZ(p) { const v = strParam(p[0]); - if (v === "Y" || v === "N") printerProfile.reprintAfterError = v; + if (isYesNo(v)) printerProfile.reprintAfterError = v; }, JT(p) { const v = inRange(parseIntOrUndef(p[0]), HEAD_TEST_INTERVAL_RANGE); @@ -130,11 +166,11 @@ export function createSetupScriptHandlers(s: ParserState): Record = { label: "Maxicode", icon: "⬡", - zplCmd: "^BV", + zplCmd: "^BD", group: "code-2d", bindable: true, defaultProps: { @@ -32,10 +32,10 @@ export const maxicode: ObjectTypeCore = { toZPL: (obj, ctx) => { const p = obj.props; - // ^BV; structured-append slots fixed at (1,1) since unexposed. + // Structured-append slots fixed at (1,1) since unexposed. return [ fieldPosZ(obj), - `^BVN,${p.mode},1,1`, + `^BD${p.mode},1,1`, fdFieldFor(p.content, ctx), ].join(""); }, diff --git a/packages/core/src/types/LabelConfig.ts b/packages/core/src/types/LabelConfig.ts index 815736c9..93559516 100644 --- a/packages/core/src/types/LabelConfig.ts +++ b/packages/core/src/types/LabelConfig.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { intInRange, makeEnumGuard } from './typeHelpers'; +import { YES_NO_VALUES, intInRange, makeEnumGuard } from './typeHelpers'; /** Two row shapes: uploaded font (path + optional preview, bytes in cache) * or manual printer-resident reference (path only, no bytes). Empty strings @@ -30,10 +30,14 @@ export const isMediaTracking = makeEnumGuard(MEDIA_TRACKING_VALUES); export const isMediaFeedMode = makeEnumGuard(MEDIA_FEED_VALUES); /** ~JS backfeed sequence: A=100% after, B=before next label, N=normal, - * O=off. Percent forms 10-90 are not modeled (param-fidelity limit). */ + * O=off, or percent-after in tens (printer rounds to the nearest ten, p276). */ export const BACKFEED_SEQUENCE_VALUES = ['A', 'B', 'N', 'O'] as const; export type BackfeedSequence = (typeof BACKFEED_SEQUENCE_VALUES)[number]; export const isBackfeedSequence = makeEnumGuard(BACKFEED_SEQUENCE_VALUES); +export const BACKFEED_PERCENT_VALUES = [10, 20, 30, 40, 50, 60, 70, 80, 90] as const; +export type BackfeedPercent = (typeof BACKFEED_PERCENT_VALUES)[number]; +export const isBackfeedPercent = (n: number): n is BackfeedPercent => + (BACKFEED_PERCENT_VALUES as readonly number[]).includes(n); /** ^MM print mode (per-label cut/peel/tear behaviour). */ export const MEDIA_MODE_VALUES = ['T', 'V', 'D', 'K'] as const; @@ -63,6 +67,7 @@ export const DARKNESS_PERMANENT_RANGE = { min: -30, max: 30 } as const; export const DARKNESS_INSTANT_RANGE = { min: 0, max: 30 } as const; /** ^ML: maximum label length, in dots. Zebra spec accepts 1..32000. */ export const MAX_LABEL_LENGTH_RANGE = { min: 1, max: 32000 } as const; +export const SLEW_DOT_ROWS_RANGE = { min: 0, max: 32000 } as const; /** ^MU b,c dpi tokens; 200 = 203 dpi; ratio drives resampling. */ export const MU_DPI_VALUES = [150, 200, 300, 600] as const; @@ -78,6 +83,18 @@ export const muResamplingSchema = z.object({ }); export type MuResampling = z.infer; +/** Setting one slot seeds the other from it, keeping both-or-neither. */ +export function composeMuResampling( + current: MuResampling | undefined, + slot: keyof MuResampling, + dpi: MuDpi, +): MuResampling { + return { + formatDpi: slot === 'formatDpi' ? dpi : current?.formatDpi ?? dpi, + outputDpi: slot === 'outputDpi' ? dpi : current?.outputDpi ?? dpi, + }; +} + /** ^SO offset slots; mirrors the b,c,d,e,f,g wire-format order. All * fields signed; omitted = 0. Schema-natural order in our type is * years/months/days/hours/minutes/seconds; the parser/generator @@ -140,7 +157,7 @@ export const labelConfigSchema = z.object({ /** ^PQ p3: replicates of each serialised label. */ replicates: z.number().int().min(0).max(99999999).optional(), /** ^PQ p4: override pause count (cutter behaviour). */ - overridePauseCount: z.enum(['Y', 'N']).optional(), + overridePauseCount: z.enum(YES_NO_VALUES).optional(), mediaMode: z.enum(MEDIA_MODE_VALUES).optional(), labelShift: z.number().optional(), /** ^LH x; field FOs shifted at export so screen == print. */ @@ -160,7 +177,7 @@ export const labelConfigSchema = z.object({ mediaType: z.enum(MEDIA_TYPE_VALUES).optional(), printOrientation: z.enum(PRINT_ORIENTATION_VALUES).optional(), /** ^PM: mirror image (left/right flip). */ - mirror: z.enum(['Y', 'N']).optional(), + mirror: z.enum(YES_NO_VALUES).optional(), defaultFontId: z.string().min(1).optional(), defaultFontHeight: z.number().int().positive().optional(), /** ^CF width param. Spec allows 0 → printer auto-derives from height. */ @@ -178,13 +195,23 @@ export const labelConfigSchema = z.object({ /** ^XB: suppress backfeed for the next label. Standalone toggle. */ suppressBackfeed: z.boolean().optional(), /** ~JS: backfeed sequence. Immediate/transient, emitted before ^XA. */ - backfeedSequence: z.enum(BACKFEED_SEQUENCE_VALUES).optional(), + backfeedSequence: z + .union([z.enum(BACKFEED_SEQUENCE_VALUES), z.number().refine(isBackfeedPercent)]) + .optional(), /** ^MU b,c; set only when both slots arrived valid. */ muResampling: muResamplingSchema.optional(), /** ^SO2: secondary clock offset (`«clock2:T»` markers resolve through this). */ secondaryClockOffset: z.preprocess(coerceEmptyOffset, clockOffsetSchema.optional()), /** ^SO3: tertiary clock offset (`«clock3:T»` markers resolve through this). */ tertiaryClockOffset: z.preprocess(coerceEmptyOffset, clockOffsetSchema.optional()), + /** ^MC: N retains the bitmap as background of subsequent labels. */ + mapClear: z.enum(YES_NO_VALUES).optional(), + /** ^PF: slew this many dot rows instead of printing blank bottom area. */ + slewDotRows: intInRange(SLEW_DOT_ROWS_RANGE).optional(), + /** ^PH: feed one blank label after the format prints. */ + slewToHome: z.boolean().optional(), + /** ^PP: pause after the format prints (until PAUSE or ~PS). */ + programmablePause: z.boolean().optional(), }); export type LabelConfig = z.infer; @@ -201,10 +228,13 @@ export const PER_LABEL_ZPL_FIELDS = [ 'darkness', 'instantDarkness', 'labelHomeX', 'labelHomeY', 'labelTop', 'labelShift', 'printQuantity', 'pauseCount', 'replicates', 'overridePauseCount', + 'mapClear', 'slewDotRows', 'slewToHome', 'programmablePause', ] as const satisfies readonly (keyof LabelConfig)[]; -/** The ^PQ family is scoped to its own ^XA block; every other config field is - * persistent printer state a later block may contribute to the design. */ +/** Fields the import fold scopes to their own ^XA block; the rest is + * persistent state a later block may extend. ^MC persists on the wire + * (p300), but folding a later ^MCN back would leak its bitmap into page two. */ export const PER_FORMAT_ZPL_FIELDS = [ 'printQuantity', 'pauseCount', 'replicates', 'overridePauseCount', + 'slewDotRows', 'slewToHome', 'programmablePause', 'mapClear', ] as const satisfies readonly (keyof LabelConfig)[]; diff --git a/packages/core/src/types/PrinterProfile.ts b/packages/core/src/types/PrinterProfile.ts index 8ed48d8f..29e9f288 100644 --- a/packages/core/src/types/PrinterProfile.ts +++ b/packages/core/src/types/PrinterProfile.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { intInRange, makeEnumGuard } from './typeHelpers'; +import { YES_NO_VALUES, intInRange, makeEnumGuard } from './typeHelpers'; /** ^ST real-time clock value (HTML5 datetime-local shape). */ export const realtimeClockIsoRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?$/; @@ -56,6 +56,29 @@ export type ClockFormat = (typeof CLOCK_FORMAT_VALUES)[number]; export const isClockFormat = makeEnumGuard(CLOCK_FORMAT_VALUES); export const HEAD_TEST_INTERVAL_RANGE = { min: 0, max: 10000 } as const; + +/** ^CO b: additional cache memory in KB. */ +export const FONT_CACHE_KB_RANGE = { min: 1, max: 9999 } as const; +/** ^CO c: 0 = normal cache buffer, 1 = internal (Asian fonts). */ +export const FONT_CACHE_TYPE_VALUES = ['0', '1'] as const; +export const isFontCacheType = makeEnumGuard(FONT_CACHE_TYPE_VALUES); +/** ^MP one-letter modes; E (enable all) clears the protection set. */ +export const MODE_PROTECTION_VALUES = ['D', 'P', 'C', 'S', 'W', 'F', 'X', 'M'] as const; +export type ModeProtection = (typeof MODE_PROTECTION_VALUES)[number]; +export const isModeProtection = makeEnumGuard(MODE_PROTECTION_VALUES); + +/** Only reachable in the UI's Custom mode, where the set is always defined: + * [] is the visible "protect nothing" state that emits the explicit ^MPE. */ +export function toggleModeProtection( + current: readonly ModeProtection[] | undefined, + mode: ModeProtection, + on: boolean, +): ModeProtection[] { + const set = new Set(current ?? []); + if (on) set.add(mode); + else set.delete(mode); + return MODE_PROTECTION_VALUES.filter((v) => set.has(v)); +} export const TEAR_OFF_ADJUST_RANGE = { min: -120, max: 120 } as const; /** ^KP 4-digit; '0000' disables LCD-setup protection. */ @@ -116,7 +139,7 @@ export const MAINTENANCE_ALERT_DEFAULTS = { /** EEPROM-persistent fields; separated from labelConfig so design files * don't leak per-install values. */ export const printerProfileSchema = z.object({ - reprintAfterError: z.enum(['Y', 'N']).optional(), + reprintAfterError: z.enum(YES_NO_VALUES).optional(), headTestInterval: intInRange(HEAD_TEST_INTERVAL_RANGE).optional(), tearOffAdjust: intInRange(TEAR_OFF_ADJUST_RANGE).optional(), setRealtimeClock: z.string().regex(realtimeClockIsoRegex).optional(), @@ -136,7 +159,7 @@ export const printerProfileSchema = z.object({ /** Requires earlyWarningMaintenance==='E' to fire; per-type caps in superRefine. */ maintenanceAlert: z.object({ type: z.enum(MAINTENANCE_ALERT_TYPES), - print: z.enum(['Y', 'N']), + print: z.enum(YES_NO_VALUES), threshold: z.number().int().min(0).max(MAINTENANCE_DISTANCE_MAX_BY_TYPE.R), frequency: z.number().int().min(0).max(MAINTENANCE_DISTANCE_MAX_BY_TYPE.R), units: z.enum(MAINTENANCE_ALERT_UNITS), @@ -147,9 +170,20 @@ export const printerProfileSchema = z.object({ text: z.string().min(1).max(MAINTENANCE_MESSAGE_MAX_LEN).regex(setupScriptSafeStringRegex), }).optional(), /** ^MW head-cold warning LCD/alert toggle. */ - headColdWarning: z.enum(['Y', 'N']).optional(), + headColdWarning: z.enum(YES_NO_VALUES).optional(), + /** ^CO a: character cache on/off (session-scoped DRAM sizing). */ + fontCacheOn: z.enum(YES_NO_VALUES).optional(), + /** ^CO b: additional cache KB; resizing discards cached characters. */ + fontCacheAddKb: intInRange(FONT_CACHE_KB_RANGE).optional(), + /** ^CO c: cache type. */ + fontCacheType: z.enum(FONT_CACHE_TYPE_VALUES).optional(), + /** ^MP: control-panel modes to protect; one command per letter on emit. */ + modeProtection: z.array(z.enum(MODE_PROTECTION_VALUES)).optional(), + /** True when the set is absolute (stream carried ^MPE, or UI-authored): + * emit resets with ^MPE first. Absent = relative additions only. */ + modeProtectionExplicit: z.boolean().optional(), /** ^CV barcode validation (session-scoped per spec, not persisted by ^JUS). */ - codeValidation: z.enum(['Y', 'N']).optional(), + codeValidation: z.enum(YES_NO_VALUES).optional(), /** ^PA advanced text properties (ZPL II PG P1012728 p.299, firmware * V60.14.x+). Four session-scoped 0/1 slots. 0=printer default, * 1=feature on. a: show font's missing-glyph box (instead of space). diff --git a/packages/core/src/types/typeHelpers.ts b/packages/core/src/types/typeHelpers.ts index 3a3db5a9..9ecc67a8 100644 --- a/packages/core/src/types/typeHelpers.ts +++ b/packages/core/src/types/typeHelpers.ts @@ -11,3 +11,8 @@ export function makeEnumGuard(values: readonly T[]): (v: strin export function intInRange(r: { min: number; max: number }) { return z.number().int().min(r.min).max(r.max); } + +/** The recurring Y/N command slot, shared so parser guards cannot drift from + * the z.enum(['Y','N']) schema fields they feed. */ +export const YES_NO_VALUES = ['Y', 'N'] as const; +export const isYesNo = makeEnumGuard(YES_NO_VALUES); diff --git a/scripts/gen-coverage.mjs b/scripts/gen-coverage.mjs index 5b813e8e..5eab8892 100644 --- a/scripts/gen-coverage.mjs +++ b/scripts/gen-coverage.mjs @@ -47,6 +47,10 @@ const README_ROWS = [ // so the status-legend and bucket example tables (prose second cell) are skipped. const ROW_RE = /^\|\s*`\[([ x])\]`\s*\|\s*`([~^][A-Z0-9@]+)`/; +// The roadmap is a full partition of the ZPL II guide's commands; +// a row added or removed MUST consciously move this number. +const TRACKED_TOTAL = 225; + /** Parse the roadmap into { section -> { supported, total, cmds:[{cmd,ok}] } }. */ function parseRoadmap() { const lines = readFileSync(ROADMAP, 'utf8').split(/\r?\n/); @@ -63,6 +67,14 @@ function parseRoadmap() { s.total++; if (ok) s.supported++; s.cmds.push({ cmd: m[2], ok }); } + const total = [...sections.values()].reduce((n, s) => n + s.total, 0); + if (total !== TRACKED_TOTAL) { + console.error( + `roadmap tracks ${total} commands, pin says ${TRACKED_TOTAL}; ` + + 'update TRACKED_TOTAL only for a deliberate row change', + ); + process.exit(1); + } return sections; } diff --git a/src/components/PrinterSettings/FontsTab.tsx b/src/components/PrinterSettings/FontsTab.tsx index 71b0ebff..e57773ec 100644 --- a/src/components/PrinterSettings/FontsTab.tsx +++ b/src/components/PrinterSettings/FontsTab.tsx @@ -4,6 +4,8 @@ import { useFontCacheVersion } from "../../hooks/useFontCacheVersion"; import { uploadedFontPath } from "@zplab/core/lib/customFonts"; import { useLabelStore } from "../../store/labelStore"; import { zplCommandTagCls } from "../ui/formStyles"; +import { FONT_CACHE_KB_RANGE, FONT_CACHE_TYPE_VALUES } from "@zplab/core/types/PrinterProfile"; +import { ZplBoundedIntInput, ZplEnumSegmented } from "./zplFieldPrimitives"; import { FontLinksField } from "./FontLinksField"; /** Setup-Script rail entry: per-printer font choices. @@ -12,6 +14,9 @@ export function FontsTab() { const t = useT(); useFontCacheVersion(); const setupFonts = useLabelStore((s) => s.printerProfile.setupFonts); + const fontCacheOn = useLabelStore((s) => s.printerProfile.fontCacheOn); + const fontCacheAddKb = useLabelStore((s) => s.printerProfile.fontCacheAddKb); + const fontCacheType = useLabelStore((s) => s.printerProfile.fontCacheType); const patchPrinterProfile = useLabelStore((s) => s.patchPrinterProfile); const loc = t.printerSettings.fonts; @@ -93,6 +98,37 @@ export function FontsTab() { + +
+ patchPrinterProfile({ fontCacheOn: v })} + defaultLabel={t.printerSettings.defaultOption} + optionLabel={(v) => v === 'Y' ? loc.fontCacheEnabled : loc.fontCacheDisabled} + /> + patchPrinterProfile({ fontCacheAddKb: v })} + unit={loc.fontCacheKbUnit} + hint={loc.fontCacheHint} + /> + patchPrinterProfile({ fontCacheType: v })} + defaultLabel={t.printerSettings.defaultOption} + optionLabel={(v) => v === '0' ? loc.fontCacheTypeNormal : loc.fontCacheTypeInternal} + /> +
); } diff --git a/src/components/PrinterSettings/IdentityTab.test.tsx b/src/components/PrinterSettings/IdentityTab.test.tsx new file mode 100644 index 00000000..33c4050d --- /dev/null +++ b/src/components/PrinterSettings/IdentityTab.test.tsx @@ -0,0 +1,77 @@ +// @vitest-environment jsdom +import { describe, it, expect, afterEach, beforeEach } from "vitest"; +import { render, cleanup, fireEvent, act } from "@testing-library/react"; +import { IdentityTab } from "./IdentityTab"; +import { useLabelStore } from "../../store/labelStore"; +import { fallbackTranslations as en } from "../../locales"; + +afterEach(cleanup); +beforeEach(() => { + act(() => { + useLabelStore.setState({ printerProfile: {} } as never); + }); +}); + +const loc = en.printerSettings.identity; + +describe("IdentityTab ^MP mode protection tri-state", () => { + it("pristine default renders no mode checkboxes and no set", () => { + const { queryByText } = render(); + expect(queryByText(loc.modeProtectDarkness)).toBeNull(); + expect(useLabelStore.getState().printerProfile.modeProtection).toBeUndefined(); + }); + + it("entering Custom creates the visible empty set (explicit ^MPE)", () => { + const { getByRole } = render(); + act(() => { + fireEvent.click(getByRole("button", { name: loc.modeProtectCustom })); + }); + const p = useLabelStore.getState().printerProfile; + expect(p.modeProtection).toEqual([]); + expect(p.modeProtectionExplicit).toBe(true); + }); + + it("toggling inside Custom keeps [] visible instead of collapsing to unset", () => { + const { getByRole, getByText } = render(); + act(() => { + fireEvent.click(getByRole("button", { name: loc.modeProtectCustom })); + }); + const box = () => getByText(loc.modeProtectDarkness); + act(() => { + fireEvent.click(box()); + }); + expect(useLabelStore.getState().printerProfile.modeProtection).toEqual(["D"]); + act(() => { + fireEvent.click(box()); + }); + expect(useLabelStore.getState().printerProfile.modeProtection).toEqual([]); + }); + + it("returning to Default clears set and explicit flag (no fabricated ^MPE)", () => { + act(() => { + useLabelStore.setState({ + printerProfile: { modeProtection: ["D"], modeProtectionExplicit: true }, + } as never); + }); + const { getByRole } = render(); + act(() => { + fireEvent.click(getByRole("button", { name: en.printerSettings.defaultOption })); + }); + const p = useLabelStore.getState().printerProfile; + expect(p.modeProtection).toBeUndefined(); + expect(p.modeProtectionExplicit).toBeUndefined(); + }); + + it("an imported relative set shows as Custom and becomes absolute on touch", () => { + act(() => { + useLabelStore.setState({ printerProfile: { modeProtection: ["D"] } } as never); + }); + const { getByText } = render(); + act(() => { + fireEvent.click(getByText(loc.modeProtectFeed)); + }); + const p = useLabelStore.getState().printerProfile; + expect(p.modeProtection).toEqual(["D", "F"]); + expect(p.modeProtectionExplicit).toBe(true); + }); +}); diff --git a/src/components/PrinterSettings/IdentityTab.tsx b/src/components/PrinterSettings/IdentityTab.tsx index ca85bf62..05b6bad8 100644 --- a/src/components/PrinterSettings/IdentityTab.tsx +++ b/src/components/PrinterSettings/IdentityTab.tsx @@ -5,17 +5,33 @@ import { inputCls, labelCls } from "../ui/formStyles"; import { CONFIG_UPDATE_VALUES, type ConfigUpdateAction, + MODE_PROTECTION_VALUES, + type ModeProtection, PRINTER_NAME_MAX_LEN, PRINTER_PASSWORD_REGEX, + toggleModeProtection, } from "@zplab/core/types/PrinterProfile"; import { SafeStringInput, + ZplCheckbox, ZplCommandLabel, ZplEnumCustomSelect, + ZplEnumSegmented, ZplField, ZplSubField, } from "./zplFieldPrimitives"; +const MODE_PROTECTION_LABEL_KEYS = { + D: "modeProtectDarkness", + P: "modeProtectPosition", + C: "modeProtectCalibration", + S: "modeProtectSaves", + W: "modeProtectPause", + F: "modeProtectFeed", + X: "modeProtectCancel", + M: "modeProtectMenu", +} as const satisfies Record; + type LocIdentity = ReturnType["printerSettings"]["identity"]; /** Explicit value → locale-key map; `satisfies` forces every @@ -116,6 +132,46 @@ export function IdentityTab() { + {/* Tri-state: unset leaves the printer alone; Custom is the absolute + set (empty = visible ^MPE enable-all), avoiding a checkbox group's + invisible []-vs-undefined ambiguity. */} + + patchPrinterProfile( + v === 'custom' + ? { modeProtection: [], modeProtectionExplicit: true } + : { modeProtection: undefined, modeProtectionExplicit: undefined }, + ) + } + defaultLabel={t.printerSettings.defaultOption} + optionLabel={() => loc.modeProtectCustom} + hint={profile.modeProtection?.length === 0 ? loc.modeProtectCustomHint : undefined} + /> + {profile.modeProtection !== undefined && ( + +
+ {MODE_PROTECTION_VALUES.map((m) => ( + { + patchPrinterProfile({ + modeProtection: toggleModeProtection(profile.modeProtection, m, on), + modeProtectionExplicit: true, + }); + }} + /> + ))} +
+
+ )} + ["printerSettings"]["mediaFeed"]; /** Static lookup table from enum value to the locale-key that @@ -102,6 +104,27 @@ export function MediaFeedTab() { /> + + setLabelConfig({ slewDotRows: v })} + hint={loc.slewDotRowsHint} + /> + + + + setLabelConfig({ slewToHome: v || undefined })} + /> + + setLabelConfig({ backfeedSequence: v })} + values={BACKFEED_VALUE_STRINGS} + value={label.backfeedSequence === undefined ? undefined : String(label.backfeedSequence)} + onChange={(v) => + setLabelConfig({ + backfeedSequence: + v === undefined ? undefined : isBackfeedSequence(v) ? v : (Number(v) as BackfeedPercent), + }) + } defaultLabel={t.printerSettings.defaultOption} - optionLabel={(m) => loc[BACKFEED_LABEL_KEYS[m]]} + optionLabel={(m) => + isBackfeedSequence(m) ? loc[BACKFEED_LABEL_KEYS[m]] : loc.backfeedSeqPctFmt.replace("{pct}", m) + } /> diff --git a/src/components/PrinterSettings/OutputTab.tsx b/src/components/PrinterSettings/OutputTab.tsx index 030afb68..e6724b62 100644 --- a/src/components/PrinterSettings/OutputTab.tsx +++ b/src/components/PrinterSettings/OutputTab.tsx @@ -96,6 +96,12 @@ export function OutputTab() { value={label.pauseCount} onChange={(pauseCount) => setLabelConfig({ pauseCount })} /> + setLabelConfig({ programmablePause: v || undefined })} + /> = { '150': '152', '200': '203', '300': '300', '600': '600' }; + type LocPrintQuality = ReturnType["printerSettings"]["printQuality"]; const ORIENTATION_LABEL_KEYS = { @@ -22,14 +28,22 @@ const ORIENTATION_LABEL_KEYS = { } as const satisfies Record; /** Tab 2 of the Printer Settings Modal. Per-label print quality - * (orientation, mirror, speed, darkness) plus setup-script-only - * ^JZ / ^JT / ~TA / ^CV which the user provisions once. */ + * (orientation, mirror, map clear, speed, darkness, ^MU resampling) + * plus setup-script-only ^JZ / ^JT / ~TA / ^CV provisioned once. */ export function PrintQualityTab() { const t = useT(); const label = useLabelStore((s) => s.label); const setLabelConfig = useLabelStore((s) => s.setLabelConfig); const profile = useLabelStore((s) => s.printerProfile); const patchPrinterProfile = useLabelStore((s) => s.patchPrinterProfile); + const setMuSlot = (slot: 'formatDpi' | 'outputDpi', v: string | undefined) => { + setLabelConfig({ + muResampling: + v === undefined + ? undefined + : composeMuResampling(label.muResampling, slot, Number(v) as MuDpi), + }); + }; const loc = t.printerSettings.printQuality; return ( @@ -55,6 +69,20 @@ export function PrintQualityTab() { /> + {/* Tri-state so an imported explicit ^MCY stays visible and editable. */} + + setLabelConfig({ mapClear })} + defaultLabel={t.printerSettings.defaultOption} + optionLabel={(v) => v === 'Y' ? loc.mapClearOptionClear : loc.mapClearOptionRetain} + hint={loc.mapClearHint} + /> + + {/* Speed triple: ^PR a,b,c; print / slew / backfeed. All three share the same 2..14 ips range and one ^PR command, so group them under one ZplField + tag header. */} @@ -125,6 +153,33 @@ export function PrintQualityTab() { /> + {/* ^MU b,c: both-or-neither pair; picking one slot seeds the other. */} + + + +
+ setMuSlot('formatDpi', v)} + defaultLabel={t.printerSettings.defaultOption} + optionLabel={(d) => `${MU_PHYSICAL_DPI[d] ?? d} dpi`} + className={fieldGridCell} + /> + setMuSlot('outputDpi', v)} + defaultLabel={t.printerSettings.defaultOption} + optionLabel={(d) => `${MU_PHYSICAL_DPI[d] ?? d} dpi`} + className={fieldGridCell} + /> +
+
+
+ {/* Printer default for ^JZ is "Y" (reprint enabled). The unchecked state must explicitly emit "N", otherwise the printer falls back to its default and the user cannot diff --git a/src/components/PrinterSettings/zplFieldPrimitives.tsx b/src/components/PrinterSettings/zplFieldPrimitives.tsx index 44c8f32e..1032c257 100644 --- a/src/components/PrinterSettings/zplFieldPrimitives.tsx +++ b/src/components/PrinterSettings/zplFieldPrimitives.tsx @@ -326,6 +326,7 @@ export function ZplEnumSegmented({ onChange, defaultLabel, optionLabel, + hint, }: { label: string; command: string; @@ -334,6 +335,7 @@ export function ZplEnumSegmented({ onChange: (next: T | undefined) => void; defaultLabel: string; optionLabel: (v: T) => string; + hint?: ReactNode; }) { return ( @@ -345,6 +347,7 @@ export function ZplEnumSegmented({ defaultLabel={defaultLabel} options={values.map((v) => ({ value: v, label: optionLabel(v) }))} /> + {hint ? {hint} : null} ); } @@ -357,6 +360,7 @@ export function ZplBoundedIntInput({ value, onChange, unit, + hint, }: { label: string; command: string; @@ -365,6 +369,7 @@ export function ZplBoundedIntInput({ value: number | undefined; onChange: (next: number | undefined) => void; unit?: string; + hint?: ReactNode; }) { const id = useId(); const inputBox = ( @@ -383,6 +388,7 @@ export function ZplBoundedIntInput({ ) : inputBox} + {hint ? {hint} : null} ); } diff --git a/src/lib/spawn.test.ts b/src/lib/spawn.test.ts index 3f21375e..b37b1855 100644 --- a/src/lib/spawn.test.ts +++ b/src/lib/spawn.test.ts @@ -25,7 +25,7 @@ describe('spawnRotationOverride', () => { expect(spawnRotationOverride('line', undefined, 90)).toBeUndefined(); }); - // ^BV has no working ZPL orientation and no graphic-emit fallback, so the + // ^BD has no orientation parameter and no graphic-emit fallback, so the // props carry no rotation and the spawn override must skip it. it('skips maxicode (not rotatable in ZPL)', () => { expect(spawnRotationOverride('maxicode', undefined, 90)).toBeUndefined(); diff --git a/src/lib/zplCommandSupport.ts b/src/lib/zplCommandSupport.ts index de8f6a8c..520d0cfa 100644 --- a/src/lib/zplCommandSupport.ts +++ b/src/lib/zplCommandSupport.ts @@ -67,16 +67,8 @@ const ZPL_COMMANDS: readonly ZplCommandInfo[] = [ }, { cmd: 'TB', status: 'supported', description: 'Text block: alternative to ^A + ^FB for wrapped/justified text' }, { cmd: 'PA', status: 'supported', description: 'Advanced text properties: glyph/bidi/shaping/OpenType flags; round-trips through the Printer Settings setup script' }, - { - cmd: 'CW', status: 'browser-limit', - description: 'Font identifier: assigns a single-letter alias to a printer-resident font', - loss: 'Cannot access printer font storage; alias is ignored but subsequent ^A references fall back to default font', - }, - { - cmd: 'FL', status: 'browser-limit', - description: 'Font linking: links host fonts on the printer', - loss: 'Requires printer font storage; not applicable in the browser', - }, + { cmd: 'CW', status: 'supported', description: 'Font identifier: alias-to-font mapping, round-trips; canvas renders the substitute font' }, + { cmd: 'FL', status: 'supported', description: 'Font linking: round-trips through the Printer Settings setup script' }, { cmd: 'HT', status: 'browser-limit', description: 'Host linked font list: retrieves font data from printer', @@ -105,7 +97,7 @@ const ZPL_COMMANDS: readonly ZplCommandInfo[] = [ { cmd: 'BA', status: 'supported', description: 'Code 93 barcode' }, { cmd: 'BB', status: 'supported', description: 'CODABLOCK barcode' }, { cmd: 'BC', status: 'supported', description: 'Code 128 barcode' }, - { cmd: 'BD', status: 'unsupported', description: 'UPS MaxiCode barcode' }, + { cmd: 'BD', status: 'supported', description: 'UPS MaxiCode barcode' }, { cmd: 'BE', status: 'supported', description: 'EAN-13 barcode' }, { cmd: 'BF', status: 'supported', description: 'MicroPDF417 barcode' }, { cmd: 'BI', status: 'supported', description: 'Industrial 2 of 5 barcode' }, @@ -118,7 +110,7 @@ const ZPL_COMMANDS: readonly ZplCommandInfo[] = [ { cmd: 'BQ', status: 'supported', description: 'QR Code' }, { cmd: 'BR', status: 'supported', description: 'GS1 Databar' }, { cmd: 'BS', status: 'supported', description: 'UPC/EAN 2- or 5-digit supplement barcode' }, - { cmd: 'BT', status: 'unsupported', description: 'TLC39 barcode' }, + { cmd: 'BT', status: 'supported', description: 'TLC39 barcode (MicroPDF417 + Code 39)' }, { cmd: 'BU', status: 'supported', description: 'UPC-A barcode' }, { cmd: 'BX', status: 'supported', description: 'DataMatrix code' }, { cmd: 'BZ', status: 'supported', description: 'POSTAL barcode' }, @@ -131,13 +123,9 @@ const ZPL_COMMANDS: readonly ZplCommandInfo[] = [ { cmd: 'GF', status: 'partial', description: 'Graphic field: embedded monochrome bitmap', - loss: 'Only ^GFA (hex / ZPL-compressed format) is supported; ^GFB and ^GFC formats are skipped', - }, - { - cmd: 'GS', status: 'browser-limit', - description: 'Graphic symbol: prints a printer-resident symbol character', - loss: 'Symbols are stored on the printer; cannot be rendered in the browser', + loss: 'Raw binary ^GFB/^GFC payloads are skipped; ^GFA and :B64:/:Z64:-wrapped B/C payloads decode', }, + { cmd: 'GS', status: 'supported', description: 'Graphic symbol glyph (registered/copyright/trademark/UL/CSA)' }, // ── Serialisation ───────────────────────────────────────────────────────── { cmd: 'SN', status: 'supported', description: 'Serialisation data (^SNv,n,z; the start value is the field data)' }, @@ -146,24 +134,29 @@ const ZPL_COMMANDS: readonly ZplCommandInfo[] = [ // ── Clock & time ────────────────────────────────────────────────────────── { cmd: 'SO', status: 'supported', description: 'Set offset: secondary/tertiary RTC clock offsets; round-trips via labelConfig' }, + // ── Fonts & panel ───────────────────────────────────────────────────────── + { cmd: 'CO', status: 'supported', description: 'Cache on: size the scalable-character cache (on/off, extra KB, buffer type); session-scoped' }, + { cmd: 'MP', status: 'supported', description: 'Mode protection: lock control-panel modes; one letter per command, E re-enables all' }, + { cmd: 'CV', status: 'supported', description: 'Code validation: round-trips through the Printer Settings setup script' }, + // ── Encoding ────────────────────────────────────────────────────────────── - { cmd: 'CI', status: 'structural', description: 'Change international font/encoding: not required; UTF-8 is used natively in the browser' }, + { cmd: 'CI', status: 'supported', description: 'Change international encoding: parsed on import; exports emit ^CI28 (UTF-8)' }, // ── Control & media ─────────────────────────────────────────────────────── - { cmd: 'MC', status: 'structural', description: 'Map clear: clears the bitmap buffer before building the label' }, + { cmd: 'MC', status: 'supported', description: 'Map clear: Y clears the bitmap per label (default); N retains it behind subsequent labels' }, { cmd: 'MD', status: 'structural', description: 'Media darkness: printer hardware setting' }, { cmd: 'ML', status: 'structural', description: 'Maximum label length: printer calibration value' }, { cmd: 'MN', status: 'structural', description: 'Media tracking: continuous/gap/mark sensing (hardware)' }, // ── Print control ───────────────────────────────────────────────────────── - { cmd: 'PF', status: 'structural', description: 'Slew given number of dot rows: printer movement command' }, - { cmd: 'PH', status: 'structural', description: 'Slew to home position: printer movement command' }, - { cmd: 'PM', status: 'structural', description: 'Print mirror image: hardware mirror setting' }, - { cmd: 'PO', status: 'structural', description: 'Print orientation: sets label print orientation on printer' }, - { cmd: 'PP', status: 'structural', description: 'Programmable pause: pauses after each label (hardware)' }, + { cmd: 'PF', status: 'supported', description: 'Slew given number of dot rows (0-32000) instead of printing a blank bottom area' }, + { cmd: 'PH', status: 'supported', description: 'Slew to home: feed one blank label after the format prints (caret form; ~PH is a device action)' }, + { cmd: 'PM', status: 'supported', description: 'Print mirror image: round-trips as label config' }, + { cmd: 'PO', status: 'supported', description: 'Print orientation: round-trips as label config' }, + { cmd: 'PP', status: 'supported', description: 'Programmable pause after the format prints, until PAUSE or ~PS (caret form; ~PP is a device action)' }, { cmd: 'PR', status: 'structural', description: 'Print rate: sets print speed (hardware)' }, { cmd: 'PS', status: 'structural', description: 'Print start: resumes printing after a pause (hardware)' }, - { cmd: 'JS', status: 'partial', description: 'Change backfeed sequence (A/B/N/O)', loss: 'Percent backfeed forms (10-90) are not modeled; A/B/N/O are supported' }, + { cmd: 'JS', status: 'supported', description: 'Change backfeed sequence (A/B/N/O or percent 10-90, rounded to tens like the printer)' }, // ── Printer storage & resources ─────────────────────────────────────────── { diff --git a/src/lib/zplGenerator.printerSettings.test.ts b/src/lib/zplGenerator.printerSettings.test.ts index 8f7da352..9a7c1300 100644 --- a/src/lib/zplGenerator.printerSettings.test.ts +++ b/src/lib/zplGenerator.printerSettings.test.ts @@ -14,6 +14,31 @@ describe("Printer Settings Modal Tab 1 — generator", () => { expect(zpl).not.toContain("^XB"); }); + it("emits ^MC / ^PF / ^PH / ^PP only when set and round-trips them", () => { + expect(generateZPL(base, [])).not.toMatch(/\^MC|\^PF|\^PH|\^PP/); + const zpl = generateZPL( + { ...base, mapClear: "N", slewDotRows: 120, slewToHome: true, programmablePause: true }, + [], + ); + expect(zpl).toContain("^MCN"); + expect(zpl).toContain("^PF120"); + expect(zpl).toContain("^PH"); + expect(zpl).toContain("^PP"); + const back = parseZPL(zpl, 8).labelConfig; + expect(back.mapClear).toBe("N"); + expect(back.slewDotRows).toBe(120); + expect(back.slewToHome).toBe(true); + expect(back.programmablePause).toBe(true); + }); + + it("emits ^PF0 (explicit no-slew) rather than dropping the zero", () => { + expect(generateZPL({ ...base, slewDotRows: 0 }, [])).toContain("^PF0"); + }); + + it("emits an explicit imported ^MCY (both enum states are representable)", () => { + expect(generateZPL({ ...base, mapClear: "Y" }, [])).toContain("^MCY"); + }); + it("emits ^MN with the selected tracking mode", () => { const zpl = generateZPL({ ...base, mediaTracking: "W" }, []); expect(zpl).toContain("^MNW"); diff --git a/src/lib/zplGenerator.test.ts b/src/lib/zplGenerator.test.ts index 1e818235..58c899c2 100644 --- a/src/lib/zplGenerator.test.ts +++ b/src/lib/zplGenerator.test.ts @@ -653,6 +653,12 @@ describe('generateZPL — printer params', () => { expect(zpl.indexOf('~JSB')).toBeLessThan(zpl.indexOf('^XA')); }); + it('emits ~JS percent form and round-trips it', () => { + const zpl = generateZPL({ ...BASE_LABEL, backfeedSequence: 40 }, []); + expect(zpl).toContain('~JS40'); + expect(parseZPL(zpl, 8).labelConfig.backfeedSequence).toBe(40); + }); + it('emits ^PR when only slew or backfeed is set (printSpeed undefined)', () => { expect(generateZPL({ ...BASE_LABEL, slewSpeed: 8 }, [])).toContain('^PR8'); // backfeed-only: ZPL has no positional skip, so slew slot repeats the diff --git a/src/lib/zplImportService.test.ts b/src/lib/zplImportService.test.ts index a57dbd88..8ec81290 100644 --- a/src/lib/zplImportService.test.ts +++ b/src/lib/zplImportService.test.ts @@ -42,6 +42,26 @@ describe('importZplText - cross-block parser state (parser-owned pages)', () => expect(r.labelConfig.printQuantity).toBeUndefined(); }); + it('keeps block 0 config; a later block ^PF/^PH/^PP does not leak (format-scoped)', () => { + const r = importZplText( + '^XA^FO10,10^A0N,30,30^FDa^FS^XZ^XA^PF200^PH^PP^FO10,10^A0N,30,30^FDb^FS^XZ', + 8, + ); + expect(r.labelConfig.slewDotRows).toBeUndefined(); + expect(r.labelConfig.slewToHome).toBeUndefined(); + expect(r.labelConfig.programmablePause).toBeUndefined(); + }); + + // A folded-back ^MCN would retain page one's bitmap INTO page two on + // re-export, garbage the original stream never printed. + it('keeps block 0 config; a later block ^MC does not leak', () => { + const r = importZplText( + '^XA^FO10,10^A0N,30,30^FDa^FS^XZ^XA^MCN^FO10,10^A0N,30,30^FDb^FS^XZ', + 8, + ); + expect(r.labelConfig.mapClear).toBeUndefined(); + }); + it('accepts the ZPLLAB sidecar from a later block while no object was seen (settings-block re-export)', () => { const sc = '^FXZPLLAB:{"dpmm":12,"wMm":100,"hMm":50}^FS'; const r = importZplText(`^XA^MMT^XZ^XA${sc}^PW1200^LL600^FO10,10^A0N,30,30^FDx^FS^XZ`, 8); diff --git a/src/lib/zplParser.test.ts b/src/lib/zplParser.test.ts index 84849424..f54da793 100644 --- a/src/lib/zplParser.test.ts +++ b/src/lib/zplParser.test.ts @@ -1369,11 +1369,59 @@ describe('parseZPL — printer params', () => { expect(labelConfig.overridePauseCount).toBe('Y'); }); + it('parses ^BD maxicode; nonexistent ^BV stays an unknown token', () => { + // ^BDm,n,t (spec p106): mode is the FIRST param. + const bd = parseSingle('^XA^FO10,10^BD5,1,1^FDx^FS^XZ', 8); + expect(props(bd.objects[0]).mode).toBe(5); + // ^BV is not a ZPL command; it must not fabricate a maxicode object. + const bv = parseSingle('^XA^FO10,10^BVN,3,1,1^FDx^FS^XZ', 8); + expect(bv.objects.some((o) => 'props' in o && (o.props as { mode?: number }).mode === 3)).toBe(false); + expect(commandsOf(bv, 'unknown').some((c) => c.startsWith('^BV'))).toBe(true); + }); + it('parses ^PM mirror', () => { expect(parseZPL('^XA^PMY^XZ', 8).labelConfig.mirror).toBe('Y'); expect(parseZPL('^XA^PMN^XZ', 8).labelConfig.mirror).toBe('N'); }); + it('parses ^MC, ^PF, ^PH and ^PP into the label config', () => { + const { labelConfig } = parseZPL('^XA^MCN^PF120^PH^PP^XZ', 8); + expect(labelConfig.mapClear).toBe('N'); + expect(labelConfig.slewDotRows).toBe(120); + expect(labelConfig.slewToHome).toBe(true); + expect(labelConfig.programmablePause).toBe(true); + }); + + it('drops an out-of-range ^PF instead of clamping into the model', () => { + expect(parseZPL('^XA^PF33000^XZ', 8).labelConfig.slewDotRows).toBeUndefined(); + }); + + it('routes ~PH/~PP as device actions without touching the model', () => { + const r = parseSingle('~PH~PP^XA^XZ', 8); + expect(r.labelConfig.slewToHome).toBeUndefined(); + expect(r.labelConfig.programmablePause).toBeUndefined(); + expect(commandsOf(r, 'deviceAction')).toContain('~PH'); + expect(commandsOf(r, 'deviceAction')).toContain('~PP'); + // Flagged once, not additionally surfaced as unrecognised. + expect(commandsOf(r, 'unknown')).toEqual([]); + }); + + it('parses ^CO into the printer profile with per-slot validation', () => { + const { printerProfile } = parseZPL('^XA^COY,78,1^XZ', 8); + expect(printerProfile.fontCacheOn).toBe('Y'); + expect(printerProfile.fontCacheAddKb).toBe(78); + expect(printerProfile.fontCacheType).toBe('1'); + // Out-of-range KB slot is dropped, valid slots still land. + const partial = parseZPL('^XA^CON,0,0^XZ', 8).printerProfile; + expect(partial.fontCacheOn).toBe('N'); + expect(partial.fontCacheAddKb).toBeUndefined(); + }); + + it('accumulates ^MP modes and lets ^MPE reset the set', () => { + expect(parseZPL('^XA^MPD^MPC^MPD^XZ', 8).printerProfile.modeProtection).toEqual(['D', 'C']); + expect(parseZPL('^XA^MPD^MPE^XZ', 8).printerProfile.modeProtection).toEqual([]); + }); + it('parses ^CF width into defaultFontWidth', () => { const { labelConfig } = parseSingle('^XA^CFA,30,20^XZ', 8); expect(labelConfig.defaultFontId).toBe('A'); @@ -1444,12 +1492,15 @@ describe('parseZPL — printer params', () => { expect(parseZPL('~SD30^XA^XZ', 8).labelConfig.instantDarkness).toBe(30); }); - it('parses ~JS backfeed sequence; percent forms surface as partial', () => { + it('parses ~JS backfeed sequence including percent forms', () => { expect(parseZPL('~JSA^XA^XZ', 8).labelConfig.backfeedSequence).toBe('A'); expect(parseZPL('~JSO^XA^XZ', 8).labelConfig.backfeedSequence).toBe('O'); - const { labelConfig, findings } = parseSingle('~JS40^XA^XZ', 8); - expect(labelConfig.backfeedSequence).toBeUndefined(); - expect(commandsOf({ findings }, 'partial')).toContain('~JS'); + expect(parseZPL('~JS40^XA^XZ', 8).labelConfig.backfeedSequence).toBe(40); + // Printer rounds to the nearest ten (~JS55 -> 60, p276); mirror that. + expect(parseZPL('~JS55^XA^XZ', 8).labelConfig.backfeedSequence).toBe(60); + // Out of range or garbage: dropped, never clamped in. + expect(parseZPL('~JS95^XA^XZ', 8).labelConfig.backfeedSequence).toBeUndefined(); + expect(parseZPL('~JSX^XA^XZ', 8).labelConfig.backfeedSequence).toBeUndefined(); }); it('parses ^MD darkness including 0', () => { diff --git a/src/lib/zplSetupScript.test.ts b/src/lib/zplSetupScript.test.ts index 805ca1ff..6ca5c388 100644 --- a/src/lib/zplSetupScript.test.ts +++ b/src/lib/zplSetupScript.test.ts @@ -428,9 +428,57 @@ describe("generateSetupScript — output shape", () => { "paSlotB", "paSlotC", "paSlotD", + "fontCacheOn", + "fontCacheAddKb", + "fontCacheType", + "modeProtection", + "modeProtectionExplicit", ]); }); + it("emits ^CO with only the slots the profile sets (parse-generate identity)", () => { + expect(generateSetupScript({})).not.toContain("^CO"); + expect(generateSetupScript({ fontCacheAddKb: 78 })).toContain("^CO,78"); + expect(generateSetupScript({ fontCacheOn: "N", fontCacheType: "1" })).toContain("^CON,,1"); + expect(generateSetupScript({ fontCacheOn: "Y" })).toMatch(/\^COY(?!,)/); + }); + + it("emits the ^MPE baseline only for an absolute set", () => { + expect(generateSetupScript({})).not.toContain("^MP"); + // Absolute (UI-authored or stream carried ^MPE): reset first. + const absolute = generateSetupScript({ modeProtection: ["D", "C"], modeProtectionExplicit: true }); + expect(absolute).toContain("^MPE\n^MPD\n^MPC"); + // Relative import (^MPD without ^MPE): additions only, no injected reset. + const relative = generateSetupScript({ modeProtection: ["D", "C"] }); + expect(relative).toContain("^MPD\n^MPC"); + expect(relative).not.toContain("^MPE"); + // Imported enable-all (^MPE with nothing after) round-trips as empty set. + expect(generateSetupScript({ modeProtection: [], modeProtectionExplicit: true })).toContain("^MPE"); + }); + + it("a fully-empty ^CO normalises to its a-slot default and round-trips", () => { + const { printerProfile } = parseZPL("^XA^CO^XZ"); + expect(printerProfile.fontCacheOn).toBe("Y"); + expect(generateSetupScript(printerProfile)).toMatch(/\^COY(?!,)/); + }); + + it("later shorter ^CO clears slots an earlier ^CO had set (last command wins)", () => { + const { printerProfile } = parseZPL("^XA^COY,78,1^CON^XZ"); + expect(printerProfile.fontCacheOn).toBe("N"); + expect(printerProfile.fontCacheAddKb).toBeUndefined(); + expect(printerProfile.fontCacheType).toBeUndefined(); + }); + + it("a relative ^MP import round-trips without a fabricated ^MPE", () => { + const { printerProfile } = parseZPL("^XA^MPD^XZ"); + expect(printerProfile.modeProtection).toEqual(["D"]); + expect(printerProfile.modeProtectionExplicit).toBeUndefined(); + expect(generateSetupScript(printerProfile)).not.toContain("^MPE"); + const explicit = parseZPL("^XA^MPE^MPD^XZ").printerProfile; + expect(explicit.modeProtectionExplicit).toBe(true); + expect(generateSetupScript(explicit)).toContain("^MPE\n^MPD"); + }); + it("places configurationUpdate as the last persistent entry so ^JUS commits the block", () => { // Tripwire: ^JU emits whatever persistent writes precede it, so a // future persistent field added after configurationUpdate would diff --git a/src/lib/zplSetupScript.ts b/src/lib/zplSetupScript.ts index a250781d..3b5daad1 100644 --- a/src/lib/zplSetupScript.ts +++ b/src/lib/zplSetupScript.ts @@ -6,6 +6,7 @@ import { type PrinterProfile, } from '@zplab/core/types/PrinterProfile'; import { formatFontDownloadFromPath } from '@zplab/core/lib/customFonts'; +import { trimTrailingEmptySlots } from '@zplab/core/lib/zplGenerator'; import { formatRealtimeClockForZpl, toLocalIsoString } from '@zplab/core/lib/realtimeClock'; /** Generates the one-shot Setup-Script ZPL for a printer profile: @@ -239,6 +240,41 @@ const SETUP_SCRIPT_EMITTERS = { paSlotB: { kind: 'foldedInto', target: 'paSlotA' }, paSlotC: { kind: 'foldedInto', target: 'paSlotA' }, paSlotD: { kind: 'foldedInto', target: 'paSlotA' }, + // ^CO sizes the DRAM character cache: session state, gone at power-off. + // fontCacheOn owns the composite; unset slots stay EMPTY (printer applies + // its spec defaults) so parse(generate(p)) returns exactly p. + fontCacheOn: { + kind: 'emit', + channel: 'block', + scope: 'session', + emit: (p) => { + const slots = trimTrailingEmptySlots([ + p.fontCacheOn ?? '', + p.fontCacheAddKb?.toString() ?? '', + p.fontCacheType ?? '', + ]); + return slots.length > 0 ? `^CO${slots.join(',')}` : null; + }, + }, + fontCacheAddKb: { kind: 'foldedInto', target: 'fontCacheOn' }, + fontCacheType: { kind: 'foldedInto', target: 'fontCacheOn' }, + // ^MPE baseline only for an absolute set; a relative import (^MPD without + // ^MPE) re-emits additions only, since injecting the reset would first + // unprotect everything else. Never tied to ^JUS, so session-scoped. + modeProtection: { + kind: 'emit', + channel: 'block', + scope: 'session', + emit: (p) => { + if (p.modeProtection === undefined) return null; + const lines = [ + ...(p.modeProtectionExplicit ? ['^MPE'] : []), + ...p.modeProtection.map((m) => `^MP${m}`), + ]; + return lines.length > 0 ? lines.join('\n') : null; + }, + }, + modeProtectionExplicit: { kind: 'foldedInto', target: 'modeProtection' }, } as const satisfies Partial>; /** Public list of the PrinterProfile fields that flow through the diff --git a/src/locales/ar.ts b/src/locales/ar.ts index 5a307021..5fae0553 100644 --- a/src/locales/ar.ts +++ b/src/locales/ar.ts @@ -398,6 +398,7 @@ const ar = { emitZJustifyHint: 'إرسال باركود أحادي البعد مثبت من الجهة اليمنى باستخدام معامل المحاذاة في ZPL، بحيث تحافظ الطابعة على ثبات الحافة اليمنى للأرقام التسلسلية والبيانات المتغيرة. يتطلب البرنامج الثابت V50.14 أو أحدث؛ الطابعات الأقدم قد تضع هذه الباركودات في مكان خاطئ.', printQuantity: 'كمية الطباعة', pauseCount: 'إيقاف مؤقت كل N ملصق', + programmablePause: 'إيقاف مؤقت بعد كل ملصق', replicates: 'نسخ لكل ملصق', overridePauseCount: 'تجاوز عدد التوقف', overridePauseCountHint: 'قص الملصق الأخير فقط في الدفعة بدلاً من كل حد توقف.', @@ -501,6 +502,9 @@ const ar = { mediaTrackingM: 'استشعار العلامة السوداء', mediaTrackingA: 'اكتشاف تلقائي', maxLabelLength: 'أقصى طول للملصق', + slewDotRows: 'تخطي الصفوف الفارغة', + slewDotRowsHint: 'يتخطى المنطقة السفلية الفارغة بسرعة عالية بدلاً من طباعتها.', + slewToHome: 'تقديم ملصق فارغ واحد بعد الطباعة', mediaFeedHeading: 'تغذية الوسائط', mediaFeedPowerUp: 'عند التشغيل', mediaFeedHeadClose: 'بعد إغلاق الرأس', @@ -515,6 +519,7 @@ const ar = { backfeedSeqB: 'قبل الملصق التالي', backfeedSeqA: '100% بعد الطباعة', backfeedSequence: 'تسلسل التغذية العكسية', + backfeedSeqPctFmt: '{pct}% بعد الطباعة', }, printQuality: { printOrientation: 'اتجاه الطباعة', @@ -533,6 +538,13 @@ const ar = { codeValidation: 'التحقق من الرمز', codeValidationOn: 'تشغيل', codeValidationOff: 'إيقاف', + mapClear: 'صورة الملصق بعد الطباعة', + mapClearOptionClear: 'مسح', + mapClearOptionRetain: 'الاحتفاظ', + mapClearHint: 'يؤدي "الاحتفاظ" إلى إبقاء هذا الملصق كخلفية للملصقات التالية (طباعة على نموذج).', + muHeading: 'تحويل الكثافة', + muFormatDpi: 'كثافة التنسيق', + muOutputDpi: 'كثافة الطابعة', }, clockTime: { setRealtimeClock: 'ضبط ساعة الوقت الفعلي', @@ -616,6 +628,15 @@ const ar = { uploadToggle: 'إرسال عند الإعداد', missingBytes: 'الخط مفقود. حمّله أو احذف الإدخال.', removeOrphan: 'إزالة الإدخال القديم', + fontCache: 'ذاكرة تخزين مؤقت للأحرف القابلة للتحجيم', + fontCacheEnabled: 'تشغيل', + fontCacheDisabled: 'إيقاف', + fontCacheAddKb: 'ذاكرة تخزين مؤقت إضافية', + fontCacheKbUnit: 'كيلوبايت', + fontCacheHint: 'قم بزيادتها عندما تُطبع الأحرف المكبّرة الكبيرة ببطء أو لا تُطبع إطلاقًا.', + fontCacheType: 'نوع ذاكرة التخزين المؤقت', + fontCacheTypeNormal: 'مخزن مؤقت عادي', + fontCacheTypeInternal: 'داخلي (خطوط آسيوية)', }, identity: { printerName: 'اسم الطابعة', @@ -629,6 +650,17 @@ const ar = { configurationUpdateOptionR: 'استدعاء آخر إعداد محفوظ', configurationUpdateOptionN: 'إعادة تحميل إعدادات الشبكة المصنعية (مدمر)', configurationUpdateOptionF: 'إعادة الضبط للمصنع (مدمر)', + modeProtection: 'أوضاع اللوحة المحمية', + modeProtectCustom: 'مجموعة مخصصة', + modeProtectCustomHint: 'تؤدي المجموعة المخصصة الفارغة إلى إعادة تفعيل كل أوضاع لوحة التحكم على الطابعة.', + modeProtectDarkness: 'وضع التعتيم', + modeProtectPosition: 'وضع الموضع', + modeProtectCalibration: 'وضع المعايرة', + modeProtectSaves: 'حفظ الوضع', + modeProtectPause: 'إيقاف مؤقت', + modeProtectFeed: 'تقديم', + modeProtectCancel: 'إلغاء', + modeProtectMenu: 'تغييرات القائمة', }, maintenance: { maintenanceAlertHeading: 'تنبيه الصيانة', diff --git a/src/locales/bg.ts b/src/locales/bg.ts index c064efbc..2990dadf 100644 --- a/src/locales/bg.ts +++ b/src/locales/bg.ts @@ -398,6 +398,7 @@ const bg = { emitZJustifyHint: 'Извежда 1D баркодове, закотвени вдясно, с параметъра за подравняване на ZPL, така че принтерът да запазва десния край фиксиран за серийни номера и променливи данни. Изисква фърмуер V50.14 или по-нов; по-старите принтери биха позиционирали грешно тези баркодове.', printQuantity: 'Количество за печат', pauseCount: 'Пауза на всеки N етикета', + programmablePause: 'Пауза след всеки етикет', replicates: 'Реплики на етикет', overridePauseCount: 'Замени брояча на пауза', overridePauseCountHint: 'Отрязва само последния етикет от партидата вместо при всяка граница на пауза.', @@ -501,6 +502,9 @@ const bg = { mediaTrackingM: 'Разпознаване по маркер', mediaTrackingA: 'Автоматично разпознаване', maxLabelLength: 'Максимална дължина на етикета', + slewDotRows: 'Пропускане на празни редове', + slewDotRowsHint: 'Пропуска празна долна област с висока скорост, вместо да я отпечатва.', + slewToHome: 'Подаване на един празен етикет след печат', mediaFeedHeading: 'Подаване на носителя', mediaFeedPowerUp: 'При включване', mediaFeedHeadClose: 'След затваряне на главата', @@ -515,6 +519,7 @@ const bg = { backfeedSeqB: 'Преди следващия етикет', backfeedSeqA: '100% след печат', backfeedSequence: 'Последователност на обратно подаване', + backfeedSeqPctFmt: '{pct}% след печат', }, printQuality: { printOrientation: 'Ориентация на печат', @@ -533,6 +538,13 @@ const bg = { codeValidation: 'Валидация на кода', codeValidationOn: 'Вкл.', codeValidationOff: 'Изкл.', + mapClear: 'Изображение на етикета след печат', + mapClearOptionClear: 'Изчистване', + mapClearOptionRetain: 'Запазване', + mapClearHint: '„Запазване“ оставя този етикет като фон на следващите етикети (печат върху шаблон).', + muHeading: 'Прекодиране на плътност', + muFormatDpi: 'Плътност на формата', + muOutputDpi: 'Плътност на принтера', }, clockTime: { setRealtimeClock: 'Настройка на часовник в реално време', @@ -616,6 +628,15 @@ const bg = { uploadToggle: 'Изпрати при настройка', missingBytes: 'Шрифтът липсва. Качете го или премахнете записа.', removeOrphan: 'Премахни остарелия запис', + fontCache: 'Кеш за мащабируеми знаци', + fontCacheEnabled: 'Вкл.', + fontCacheDisabled: 'Изкл.', + fontCacheAddKb: 'Допълнителна кеш памет', + fontCacheKbUnit: 'КБ', + fontCacheHint: 'Увеличете, ако големи мащабирани символи се отпечатват бавно или изобщо не се отпечатват.', + fontCacheType: 'Тип кеш', + fontCacheTypeNormal: 'Нормален буфер', + fontCacheTypeInternal: 'Вътрешен (азиатски шрифтове)', }, identity: { printerName: 'Име на принтера', @@ -629,6 +650,17 @@ const bg = { configurationUpdateOptionR: 'Извикване на последно записаното', configurationUpdateOptionN: 'Зареди фабрични мрежови настройки (разрушително)', configurationUpdateOptionF: 'Фабрично нулиране (разрушително)', + modeProtection: 'Защитени режими на панела', + modeProtectCustom: 'Персонализиран набор', + modeProtectCustomHint: 'Празен персонализиран набор отново активира всички режими на контролния панел на принтера.', + modeProtectDarkness: 'Режим на плътност', + modeProtectPosition: 'Режим на позиция', + modeProtectCalibration: 'Режим на калибриране', + modeProtectSaves: 'Запазване на режим', + modeProtectPause: 'Пауза', + modeProtectFeed: 'Подаване', + modeProtectCancel: 'Отказ', + modeProtectMenu: 'Промени в менюто', }, maintenance: { maintenanceAlertHeading: 'Сигнал за поддръжка', diff --git a/src/locales/cs.ts b/src/locales/cs.ts index cf1c0c47..6f6a5daa 100644 --- a/src/locales/cs.ts +++ b/src/locales/cs.ts @@ -398,6 +398,7 @@ const cs = { emitZJustifyHint: 'Odešle vpravo ukotvené 1D čárové kódy s parametrem zarovnání ZPL, aby tiskárna udržela pravý okraj pevný pro sériová čísla a proměnná data. Vyžaduje firmware V50.14 nebo novější; starší tiskárny by tyto čárové kódy umístily špatně.', printQuantity: 'Počet výtisků', pauseCount: 'Pauza každých N štítků', + programmablePause: 'Pauza po každé etiketě', replicates: 'Replikace na štítek', overridePauseCount: 'Přepsat počet pauz', overridePauseCountHint: 'Řezat pouze poslední štítek dávky místo na každé hranici pauzy.', @@ -501,6 +502,9 @@ const cs = { mediaTrackingM: 'Detekce značky', mediaTrackingA: 'Automatická detekce', maxLabelLength: 'Maximální délka etikety', + slewDotRows: 'Přeskočit prázdné řádky', + slewDotRowsHint: 'Přeskočí prázdnou oblast dole vysokou rychlostí místo jejího tisku.', + slewToHome: 'Po tisku podat jednu prázdnou etiketu', mediaFeedHeading: 'Posuv média', mediaFeedPowerUp: 'Při zapnutí', mediaFeedHeadClose: 'Po zavření hlavy', @@ -515,6 +519,7 @@ const cs = { backfeedSeqB: 'Před dalším štítkem', backfeedSeqA: '100% po tisku', backfeedSequence: 'Sekvence zpětného posuvu', + backfeedSeqPctFmt: '{pct}% po tisku', }, printQuality: { printOrientation: 'Orientace tisku', @@ -533,6 +538,13 @@ const cs = { codeValidation: 'Validace kódu', codeValidationOn: 'Zapnuto', codeValidationOff: 'Vypnuto', + mapClear: 'Obraz etikety po tisku', + mapClearOptionClear: 'Vymazat', + mapClearOptionRetain: 'Zachovat', + mapClearHint: 'Možnost Zachovat ponechá tuto etiketu jako pozadí následujících etiket (tisk na formulář).', + muHeading: 'Přepočet hustoty', + muFormatDpi: 'Hustota formátu', + muOutputDpi: 'Hustota tiskárny', }, clockTime: { setRealtimeClock: 'Nastavit hodiny reálného času', @@ -616,6 +628,15 @@ const cs = { uploadToggle: 'Odeslat při nastavení', missingBytes: 'Písmo chybí. Nahrajte je nebo odeberte záznam.', removeOrphan: 'Odebrat zastaralý záznam', + fontCache: 'Mezipaměť škálovatelných znaků', + fontCacheEnabled: 'Zapnuto', + fontCacheDisabled: 'Vypnuto', + fontCacheAddKb: 'Dodatečná mezipaměť', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Zvyšte, pokud se velké škálované znaky tisknou pomalu nebo vůbec.', + fontCacheType: 'Typ mezipaměti', + fontCacheTypeNormal: 'Normální vyrovnávací paměť', + fontCacheTypeInternal: 'Interní (asijská písma)', }, identity: { printerName: 'Název tiskárny', @@ -629,6 +650,17 @@ const cs = { configurationUpdateOptionR: 'Obnovit poslední uloženou', configurationUpdateOptionN: 'Načíst tovární síťová nastavení (destruktivní)', configurationUpdateOptionF: 'Tovární reset (destruktivní)', + modeProtection: 'Chráněné režimy panelu', + modeProtectCustom: 'Vlastní sada', + modeProtectCustomHint: 'Prázdná vlastní sada znovu povolí všechny režimy ovládacího panelu tiskárny.', + modeProtectDarkness: 'Režim sytosti tisku', + modeProtectPosition: 'Režim polohy', + modeProtectCalibration: 'Režim kalibrace', + modeProtectSaves: 'Ukládání režimu', + modeProtectPause: 'Pauza', + modeProtectFeed: 'Posuv', + modeProtectCancel: 'Zrušit', + modeProtectMenu: 'Změny nabídky', }, maintenance: { maintenanceAlertHeading: 'Upozornění na údržbu', diff --git a/src/locales/da.ts b/src/locales/da.ts index ff91b217..68cdfec8 100644 --- a/src/locales/da.ts +++ b/src/locales/da.ts @@ -398,6 +398,7 @@ const da = { emitZJustifyHint: 'Udsender højreforankrede 1D-stregkoder med ZPL-justeringsparameteren, så printeren holder højrekanten fast for serienumre og variable data. Kræver firmware V50.14 eller nyere; ældre printere ville placere disse stregkoder forkert.', printQuantity: 'Udskriftsmængde', pauseCount: 'Pause hver N etiket', + programmablePause: 'Pause efter hver etiket', replicates: 'Replikeringer pr. etiket', overridePauseCount: 'Tilsidesæt pausetæller', overridePauseCountHint: 'Skær kun den sidste etiket i batchen i stedet for ved hver pausegrænse.', @@ -501,6 +502,9 @@ const da = { mediaTrackingM: 'Mærkeregistrering', mediaTrackingA: 'Automatisk registrering', maxLabelLength: 'Maks. etiketlængde', + slewDotRows: 'Spring blanke linjer over', + slewDotRowsHint: 'Springer et blankt bundområde over ved høj hastighed i stedet for at udskrive det.', + slewToHome: 'Fremfør én blank etiket efter udskrivning', mediaFeedHeading: 'Mediefremføring', mediaFeedPowerUp: 'Ved opstart', mediaFeedHeadClose: 'Efter hovedlukning', @@ -515,6 +519,7 @@ const da = { backfeedSeqB: 'Før næste etiket', backfeedSeqA: '100% efter udskrivning', backfeedSequence: 'Tilbageføringssekvens', + backfeedSeqPctFmt: '{pct}% efter udskrivning', }, printQuality: { printOrientation: 'Udskriftsretning', @@ -533,6 +538,13 @@ const da = { codeValidation: 'Kodevalidering', codeValidationOn: 'Til', codeValidationOff: 'Fra', + mapClear: 'Etiketbillede efter udskrivning', + mapClearOptionClear: 'Ryd', + mapClearOptionRetain: 'Behold', + mapClearHint: 'Behold bevarer denne etiket som baggrund for de efterfølgende etiketter (formularudskrivning).', + muHeading: 'Densitetskonvertering', + muFormatDpi: 'Formatdensitet', + muOutputDpi: 'Printerdensitet', }, clockTime: { setRealtimeClock: 'Indstil realtidsur', @@ -616,6 +628,15 @@ const da = { uploadToggle: 'Send ved opsætning', missingBytes: 'Skrifttype mangler. Upload den eller fjern posten.', removeOrphan: 'Fjern forældet post', + fontCache: 'Cache til skalerbare tegn', + fontCacheEnabled: 'Til', + fontCacheDisabled: 'Fra', + fontCacheAddKb: 'Ekstra cachehukommelse', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Forøg, når store skalerede tegn udskrives langsomt eller slet ikke.', + fontCacheType: 'Cachetype', + fontCacheTypeNormal: 'Normal buffer', + fontCacheTypeInternal: 'Intern (asiatiske skrifttyper)', }, identity: { printerName: 'Printernavn', @@ -629,6 +650,17 @@ const da = { configurationUpdateOptionR: 'Hent senest gemte', configurationUpdateOptionN: 'Indlæs fabrik-netværksindstillinger (destruktiv)', configurationUpdateOptionF: 'Fabriksnulstilling (destruktiv)', + modeProtection: 'Beskyttede panel-tilstande', + modeProtectCustom: 'Brugerdefineret sæt', + modeProtectCustomHint: 'Et tomt brugerdefineret sæt genaktiverer alle kontrolpaneltilstande på printeren.', + modeProtectDarkness: 'Mørkhedstilstand', + modeProtectPosition: 'Positionstilstand', + modeProtectCalibration: 'Kalibreringstilstand', + modeProtectSaves: 'Tilstandsgemning', + modeProtectPause: 'Pause', + modeProtectFeed: 'Fremfør', + modeProtectCancel: 'Annuller', + modeProtectMenu: 'Menuændringer', }, maintenance: { maintenanceAlertHeading: 'Vedligeholdelsesalarm', diff --git a/src/locales/de.ts b/src/locales/de.ts index 54221dcb..7fd8aaba 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -398,6 +398,7 @@ const de = { emitZJustifyHint: 'Rechtsverankerte 1D-Barcodes mit dem ZPL-Ausrichtungsparameter ausgeben, damit der Drucker die rechte Kante für Seriennummern und variable Daten fixiert hält. Erfordert Firmware V50.14 oder neuer; ältere Drucker platzieren diese Barcodes sonst falsch.', printQuantity: 'Druckanzahl', pauseCount: 'Pause nach N Etiketten', + programmablePause: 'Nach jedem Etikett anhalten', replicates: 'Wiederholungen pro Etikett', overridePauseCount: 'Pausenanzahl überschreiben', overridePauseCountHint: 'Nur das letzte Etikett der Charge schneiden, statt an jeder Pausengrenze.', @@ -501,6 +502,9 @@ const de = { mediaTrackingM: 'Markerkennung', mediaTrackingA: 'Auto-Erkennung', maxLabelLength: 'Maximale Etikettenlänge', + slewDotRows: 'Leerzeilen überspringen', + slewDotRowsHint: 'Überspringt einen leeren unteren Bereich mit hoher Geschwindigkeit, statt ihn zu drucken.', + slewToHome: 'Nach dem Druck ein leeres Etikett ausgeben', mediaFeedHeading: 'Medien-Vorschub', mediaFeedPowerUp: 'Beim Einschalten', mediaFeedHeadClose: 'Nach Kopfschluss', @@ -515,6 +519,7 @@ const de = { backfeedSeqB: 'Vor nächstem Etikett', backfeedSeqA: '100% nach Druck', backfeedSequence: 'Rückführungssequenz', + backfeedSeqPctFmt: '{pct}% nach Druck', }, printQuality: { printOrientation: 'Druckorientierung', @@ -533,6 +538,13 @@ const de = { codeValidation: 'Code-Validierung', codeValidationOn: 'Ein', codeValidationOff: 'Aus', + mapClear: 'Etikettenbild nach dem Drucken', + mapClearOptionClear: 'Löschen', + mapClearOptionRetain: 'Beibehalten', + mapClearHint: 'Beibehalten lässt dieses Etikett als Hintergrund der folgenden Etiketten bestehen (Vordruck-Druck).', + muHeading: 'Dichte-Umrechnung', + muFormatDpi: 'Format-Dichte', + muOutputDpi: 'Drucker-Dichte', }, clockTime: { setRealtimeClock: 'Echtzeituhr stellen', @@ -616,6 +628,15 @@ const de = { uploadToggle: 'Beim Setup senden', missingBytes: 'Schrift fehlt. Neu hochladen oder Eintrag entfernen.', removeOrphan: 'Verwaisten Eintrag entfernen', + fontCache: 'Skalierbarer Zeichen-Cache', + fontCacheEnabled: 'Ein', + fontCacheDisabled: 'Aus', + fontCacheAddKb: 'Zusätzlicher Cache-Speicher', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Erhöhen, wenn große skalierte Zeichen langsam oder gar nicht gedruckt werden.', + fontCacheType: 'Cache-Typ', + fontCacheTypeNormal: 'Normaler Puffer', + fontCacheTypeInternal: 'Intern (asiatische Schriften)', }, identity: { printerName: 'Druckername', @@ -629,6 +650,17 @@ const de = { configurationUpdateOptionR: 'Letzten Zustand wiederherstellen', configurationUpdateOptionN: 'Werks-Netzwerkeinstellungen laden (destruktiv)', configurationUpdateOptionF: 'Werkseinstellungen (destruktiv)', + modeProtection: 'Geschützte Bedienfeldmodi', + modeProtectCustom: 'Benutzerdefiniert', + modeProtectCustomHint: 'Ein leeres benutzerdefiniertes Set aktiviert alle Bedienfeldmodi des Druckers wieder.', + modeProtectDarkness: 'Modus Druckdichte', + modeProtectPosition: 'Modus Position', + modeProtectCalibration: 'Modus Kalibrierung', + modeProtectSaves: 'Moduswerte speichern', + modeProtectPause: 'Pause', + modeProtectFeed: 'Vorschub', + modeProtectCancel: 'Abbrechen', + modeProtectMenu: 'Menüänderungen', }, maintenance: { maintenanceAlertHeading: 'Wartungswarnung', diff --git a/src/locales/el.ts b/src/locales/el.ts index 2acb8ea1..bc48effd 100644 --- a/src/locales/el.ts +++ b/src/locales/el.ts @@ -398,6 +398,7 @@ const el = { emitZJustifyHint: 'Εκπέμπει γραμμωτούς κώδικες 1D αγκυρωμένους στα δεξιά με την παράμετρο στοίχισης ZPL, ώστε ο εκτυπωτής να διατηρεί σταθερή τη δεξιά άκρη για σειριακούς αριθμούς και μεταβλητά δεδομένα. Απαιτεί υλικολογισμικό V50.14 ή νεότερο· παλαιότεροι εκτυπωτές θα τοποθετούσαν λανθασμένα αυτούς τους κώδικες.', printQuantity: 'Ποσότητα εκτύπωσης', pauseCount: 'Παύση κάθε Ν ετικέτες', + programmablePause: 'Παύση μετά από κάθε ετικέτα', replicates: 'Αντίγραφα ανά ετικέτα', overridePauseCount: 'Παράκαμψη μετρητή παύσης', overridePauseCountHint: 'Κόψτε μόνο την τελευταία ετικέτα της παρτίδας αντί σε κάθε όριο παύσης.', @@ -501,6 +502,9 @@ const el = { mediaTrackingM: 'Ανίχνευση μάρκας', mediaTrackingA: 'Αυτόματη ανίχνευση', maxLabelLength: 'Μέγιστο μήκος ετικέτας', + slewDotRows: 'Παράλειψη κενών γραμμών', + slewDotRowsHint: 'Παραλείπει μια κενή περιοχή στο κάτω μέρος με υψηλή ταχύτητα αντί να την εκτυπώνει.', + slewToHome: 'Προώθηση μίας κενής ετικέτας μετά την εκτύπωση', mediaFeedHeading: 'Τροφοδοσία μέσου', mediaFeedPowerUp: 'Στην εκκίνηση', mediaFeedHeadClose: 'Μετά το κλείσιμο της κεφαλής', @@ -515,6 +519,7 @@ const el = { backfeedSeqB: 'Πριν από την επόμενη ετικέτα', backfeedSeqA: '100% μετά την εκτύπωση', backfeedSequence: 'Ακολουθία ανάδρομης τροφοδοσίας', + backfeedSeqPctFmt: '{pct}% μετά την εκτύπωση', }, printQuality: { printOrientation: 'Προσανατολισμός εκτύπωσης', @@ -533,6 +538,13 @@ const el = { codeValidation: 'Επικύρωση κώδικα', codeValidationOn: 'Ενεργό', codeValidationOff: 'Ανενεργό', + mapClear: 'Εικόνα ετικέτας μετά την εκτύπωση', + mapClearOptionClear: 'Εκκαθάριση', + mapClearOptionRetain: 'Διατήρηση', + mapClearHint: 'Η Διατήρηση κρατά αυτήν την ετικέτα ως φόντο των επόμενων ετικετών (εκτύπωση σε φόρμα).', + muHeading: 'Μετατροπή πυκνότητας', + muFormatDpi: 'Πυκνότητα μορφής', + muOutputDpi: 'Πυκνότητα εκτυπωτή', }, clockTime: { setRealtimeClock: 'Ρύθμιση ρολογιού πραγματικού χρόνου', @@ -616,6 +628,15 @@ const el = { uploadToggle: 'Αποστολή κατά την εγκατάσταση', missingBytes: 'Λείπει η γραμματοσειρά. Ανεβάστε την ή αφαιρέστε την καταχώρηση.', removeOrphan: 'Αφαίρεση παρωχημένης καταχώρησης', + fontCache: 'Κρυφή μνήμη κλιμακούμενων χαρακτήρων', + fontCacheEnabled: 'Ενεργό', + fontCacheDisabled: 'Ανενεργό', + fontCacheAddKb: 'Πρόσθετη μνήμη κρυφής μνήμης', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Αυξήστε όταν οι μεγάλοι κλιμακούμενοι χαρακτήρες εκτυπώνονται αργά ή καθόλου.', + fontCacheType: 'Τύπος κρυφής μνήμης', + fontCacheTypeNormal: 'Κανονική προσωρινή μνήμη', + fontCacheTypeInternal: 'Εσωτερική (ασιατικές γραμματοσειρές)', }, identity: { printerName: 'Όνομα εκτυπωτή', @@ -629,6 +650,17 @@ const el = { configurationUpdateOptionR: 'Ανάκτηση τελευταίας αποθηκευμένης', configurationUpdateOptionN: 'Φόρτωση εργοστασιακών ρυθμίσεων δικτύου (καταστροφικό)', configurationUpdateOptionF: 'Επαναφορά εργοστασίου (καταστροφικό)', + modeProtection: 'Προστατευμένες λειτουργίες πίνακα', + modeProtectCustom: 'Προσαρμοσμένο σύνολο', + modeProtectCustomHint: 'Ένα κενό προσαρμοσμένο σύνολο επανενεργοποιεί όλες τις λειτουργίες του πίνακα ελέγχου του εκτυπωτή.', + modeProtectDarkness: 'Λειτουργία πυκνότητας', + modeProtectPosition: 'Λειτουργία θέσης', + modeProtectCalibration: 'Λειτουργία βαθμονόμησης', + modeProtectSaves: 'Αποθηκεύσεις λειτουργίας', + modeProtectPause: 'Παύση', + modeProtectFeed: 'Προώθηση', + modeProtectCancel: 'Ακύρωση', + modeProtectMenu: 'Αλλαγές μενού', }, maintenance: { maintenanceAlertHeading: 'Ειδοποίηση συντήρησης', diff --git a/src/locales/en.ts b/src/locales/en.ts index 99f699da..d7d80746 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -398,6 +398,7 @@ const en = { emitZJustifyHint: 'Emit right-anchored 1D barcodes with the ZPL justification parameter so the printer keeps the right edge fixed for serial numbers and variable data. Requires firmware V50.14 or newer; older printers would misplace these barcodes.', printQuantity: 'Print quantity', pauseCount: 'Pause every N labels', + programmablePause: 'Pause after each label', replicates: 'Replicates per label', overridePauseCount: 'Override pause count', overridePauseCountHint: 'Cut only the last label in the batch instead of every pause-count boundary.', @@ -501,6 +502,9 @@ const en = { mediaTrackingM: 'Mark sensing', mediaTrackingA: 'Auto-detect', maxLabelLength: 'Maximum label length', + slewDotRows: 'Slew dot rows', + slewDotRowsHint: 'Skips a blank bottom area at high speed instead of printing it.', + slewToHome: 'Feed one blank label after printing', mediaFeedHeading: 'Media feed', mediaFeedPowerUp: 'At power up', mediaFeedHeadClose: 'After head close', @@ -515,6 +519,7 @@ const en = { backfeedSeqB: 'Before next label', backfeedSeqA: '100% after print', backfeedSequence: 'Backfeed sequence', + backfeedSeqPctFmt: '{pct}% after printing', }, printQuality: { printOrientation: 'Print orientation', @@ -533,6 +538,13 @@ const en = { codeValidation: 'Code validation', codeValidationOn: 'On', codeValidationOff: 'Off', + mapClear: 'Label image after printing', + mapClearOptionClear: 'Clear', + mapClearOptionRetain: 'Retain', + mapClearHint: 'Retain keeps this label as the background of the following labels (template printing).', + muHeading: 'Density resampling', + muFormatDpi: 'Format density', + muOutputDpi: 'Printer density', }, clockTime: { setRealtimeClock: 'Set real-time clock', @@ -616,6 +628,15 @@ const en = { uploadToggle: 'Send at setup', missingBytes: 'Font missing. Upload it or remove this entry.', removeOrphan: 'Remove stale entry', + fontCache: 'Scalable character cache', + fontCacheEnabled: 'On', + fontCacheDisabled: 'Off', + fontCacheAddKb: 'Additional cache memory', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Increase when large scaled characters print slowly or not at all.', + fontCacheType: 'Cache type', + fontCacheTypeNormal: 'Normal buffer', + fontCacheTypeInternal: 'Internal (Asian fonts)', }, identity: { printerName: 'Printer name', @@ -629,6 +650,17 @@ const en = { configurationUpdateOptionR: 'Recall last saved', configurationUpdateOptionN: 'Reload factory network settings (destructive)', configurationUpdateOptionF: 'Factory reset (destructive)', + modeProtection: 'Protected panel modes', + modeProtectCustom: 'Custom set', + modeProtectCustomHint: 'An empty custom set re-enables every control-panel mode on the printer.', + modeProtectDarkness: 'Darkness mode', + modeProtectPosition: 'Position mode', + modeProtectCalibration: 'Calibration mode', + modeProtectSaves: 'Mode saves', + modeProtectPause: 'Pause', + modeProtectFeed: 'Feed', + modeProtectCancel: 'Cancel', + modeProtectMenu: 'Menu changes', }, maintenance: { maintenanceAlertHeading: 'Maintenance alert', diff --git a/src/locales/es.ts b/src/locales/es.ts index b454bb31..7555e8db 100644 --- a/src/locales/es.ts +++ b/src/locales/es.ts @@ -398,6 +398,7 @@ const es = { emitZJustifyHint: 'Emite códigos de barras 1D anclados a la derecha con el parámetro de justificación ZPL para que la impresora mantenga fijo el borde derecho en números de serie y datos variables. Requiere firmware V50.14 o posterior; las impresoras más antiguas colocarían mal estos códigos de barras.', printQuantity: 'Cantidad de impresión', pauseCount: 'Pausa cada N etiquetas', + programmablePause: 'Pausar después de cada etiqueta', replicates: 'Repeticiones por etiqueta', overridePauseCount: 'Anular conteo de pausa', overridePauseCountHint: 'Cortar solo la última etiqueta del lote en lugar de cada límite de pausa.', @@ -501,6 +502,9 @@ const es = { mediaTrackingM: 'Detección por marca', mediaTrackingA: 'Detección automática', maxLabelLength: 'Longitud máxima de etiqueta', + slewDotRows: 'Omitir filas en blanco', + slewDotRowsHint: 'Omite un área en blanco en la parte inferior a alta velocidad en lugar de imprimirla.', + slewToHome: 'Avanzar una etiqueta en blanco tras imprimir', mediaFeedHeading: 'Avance de medio', mediaFeedPowerUp: 'Al encender', mediaFeedHeadClose: 'Tras cerrar el cabezal', @@ -515,6 +519,7 @@ const es = { backfeedSeqB: 'Antes de la siguiente etiqueta', backfeedSeqA: '100% después de imprimir', backfeedSequence: 'Secuencia de retroceso', + backfeedSeqPctFmt: '{pct}% después de imprimir', }, printQuality: { printOrientation: 'Orientación de impresión', @@ -533,6 +538,13 @@ const es = { codeValidation: 'Validación del código', codeValidationOn: 'Activado', codeValidationOff: 'Desactivado', + mapClear: 'Imagen de la etiqueta después de imprimir', + mapClearOptionClear: 'Borrar', + mapClearOptionRetain: 'Conservar', + mapClearHint: 'Conservar mantiene esta etiqueta como fondo de las siguientes (impresión sobre formulario).', + muHeading: 'Reescalado de densidad', + muFormatDpi: 'Densidad del formato', + muOutputDpi: 'Densidad de la impresora', }, clockTime: { setRealtimeClock: 'Ajustar reloj en tiempo real', @@ -616,6 +628,15 @@ const es = { uploadToggle: 'Enviar en configuración', missingBytes: 'Falta la fuente. Súbela o elimina la entrada.', removeOrphan: 'Eliminar entrada obsoleta', + fontCache: 'Caché de caracteres escalables', + fontCacheEnabled: 'Activado', + fontCacheDisabled: 'Desactivado', + fontCacheAddKb: 'Memoria de caché adicional', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Aumente cuando los caracteres escalados grandes se impriman lentamente o no se impriman.', + fontCacheType: 'Tipo de caché', + fontCacheTypeNormal: 'Búfer normal', + fontCacheTypeInternal: 'Interno (fuentes asiáticas)', }, identity: { printerName: 'Nombre de la impresora', @@ -629,6 +650,17 @@ const es = { configurationUpdateOptionR: 'Recuperar última guardada', configurationUpdateOptionN: 'Restablecer red de fábrica (destructivo)', configurationUpdateOptionF: 'Restablecer de fábrica (destructivo)', + modeProtection: 'Modos de panel protegidos', + modeProtectCustom: 'Conjunto personalizado', + modeProtectCustomHint: 'Un conjunto personalizado vacío reactiva todos los modos del panel de control de la impresora.', + modeProtectDarkness: 'Modo de densidad', + modeProtectPosition: 'Modo de posición', + modeProtectCalibration: 'Modo de calibración', + modeProtectSaves: 'Guardados de modo', + modeProtectPause: 'Pausa', + modeProtectFeed: 'Avance', + modeProtectCancel: 'Cancelar', + modeProtectMenu: 'Cambios de menú', }, maintenance: { maintenanceAlertHeading: 'Alerta de mantenimiento', diff --git a/src/locales/et.ts b/src/locales/et.ts index c3c7fed2..06e479da 100644 --- a/src/locales/et.ts +++ b/src/locales/et.ts @@ -398,6 +398,7 @@ const et = { emitZJustifyHint: 'Väljastab paremale ankurdatud 1D-triipkoodid ZPL joondusparameetriga, et printer hoiaks parema serva seerianumbrite ja muutuvate andmete jaoks paigal. Nõuab püsivara V50.14 või uuemat; vanemad printerid paigutaksid need triipkoodid valesti.', printQuantity: 'Trükikogus', pauseCount: 'Paus iga N sildi järel', + programmablePause: 'Paus pärast iga etiketti', replicates: 'Korduvad sildi kohta', overridePauseCount: 'Tühista pausi loendur', overridePauseCountHint: 'Lõika ainult partii viimane silt iga pausi piiri asemel.', @@ -501,6 +502,9 @@ const et = { mediaTrackingM: 'Märgistuvastus', mediaTrackingA: 'Automaatne tuvastus', maxLabelLength: 'Maksimaalne etiketi pikkus', + slewDotRows: 'Jäta tühjad read vahele', + slewDotRowsHint: 'Jätab tühja alumise ala kiirelt vahele, selle asemel et seda printida.', + slewToHome: 'Sööda pärast printimist üks tühi etikett', mediaFeedHeading: 'Kandja söötmine', mediaFeedPowerUp: 'Sisselülitamisel', mediaFeedHeadClose: 'Pärast pea sulgemist', @@ -515,6 +519,7 @@ const et = { backfeedSeqB: 'Enne järgmist etiketti', backfeedSeqA: '100% pärast printimist', backfeedSequence: 'Tagasisöötmise jada', + backfeedSeqPctFmt: '{pct}% pärast printimist', }, printQuality: { printOrientation: 'Prindi suund', @@ -533,6 +538,13 @@ const et = { codeValidation: 'Koodi valideerimine', codeValidationOn: 'Sees', codeValidationOff: 'Väljas', + mapClear: 'Etiketi kujutis pärast printimist', + mapClearOptionClear: 'Tühjendamine', + mapClearOptionRetain: 'Säilita', + mapClearHint: 'Säilita jätab selle etiketi järgnevate etikettide taustaks (vormile printimine).', + muHeading: 'Tiheduse teisendus', + muFormatDpi: 'Vormingu tihedus', + muOutputDpi: 'Printeri tihedus', }, clockTime: { setRealtimeClock: 'Määra reaalajakell', @@ -616,6 +628,15 @@ const et = { uploadToggle: 'Saada seadistusel', missingBytes: 'Font puudub. Laadi üles või eemalda kirje.', removeOrphan: 'Eemalda aegunud kirje', + fontCache: 'Skaleeritavate märkide puhver', + fontCacheEnabled: 'Sees', + fontCacheDisabled: 'Väljas', + fontCacheAddKb: 'Täiendav puhvermälu', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Suurendage, kui suured skaleeritud märgid prinditakse aeglaselt või üldse mitte.', + fontCacheType: 'Puhvri tüüp', + fontCacheTypeNormal: 'Tavaline puhver', + fontCacheTypeInternal: 'Sisemine (Aasia fondid)', }, identity: { printerName: 'Printeri nimi', @@ -629,6 +650,17 @@ const et = { configurationUpdateOptionR: 'Viimase salvestatu taastamine', configurationUpdateOptionN: 'Tehase võrgusätete taastamine (hävitav)', configurationUpdateOptionF: 'Tehase lähtestamine (hävitav)', + modeProtection: 'Kaitstud paneeli režiimid', + modeProtectCustom: 'Kohandatud komplekt', + modeProtectCustomHint: 'Tühi kohandatud komplekt taasaktiveerib printeri kõik juhtpaneeli režiimid.', + modeProtectDarkness: 'Tumeduse režiim', + modeProtectPosition: 'Asendi režiim', + modeProtectCalibration: 'Kalibreerimise režiim', + modeProtectSaves: 'Režiimi salvestamine', + modeProtectPause: 'Paus', + modeProtectFeed: 'Söötmine', + modeProtectCancel: 'Tühista', + modeProtectMenu: 'Menüü muudatused', }, maintenance: { maintenanceAlertHeading: 'Hooldushoiatus', diff --git a/src/locales/fa.ts b/src/locales/fa.ts index 10ca0490..ebc36402 100644 --- a/src/locales/fa.ts +++ b/src/locales/fa.ts @@ -398,6 +398,7 @@ const fa = { emitZJustifyHint: 'بارکدهای یک‌بعدی لنگرشده به راست را با پارامتر تراز ZPL ارسال می‌کند تا چاپگر لبه راست را برای شماره‌های سریال و داده‌های متغیر ثابت نگه دارد. نیازمند فریمور V50.14 یا جدیدتر است؛ چاپگرهای قدیمی‌تر این بارکدها را نادرست قرار می‌دهند.', printQuantity: 'تعداد چاپ', pauseCount: 'توقف هر N برچسب', + programmablePause: 'توقف پس از هر برچسب', replicates: 'تکرار در هر برچسب', overridePauseCount: 'نادیده گرفتن شمارش توقف', overridePauseCountHint: 'فقط آخرین برچسب دسته را برش بزن، نه در هر مرز توقف.', @@ -501,6 +502,9 @@ const fa = { mediaTrackingM: 'تشخیص علامت', mediaTrackingA: 'تشخیص خودکار', maxLabelLength: 'حداکثر طول برچسب', + slewDotRows: 'رد شدن از سطرهای خالی', + slewDotRowsHint: 'به‌جای چاپ ناحیه خالی پایینی، آن را با سرعت بالا رد می‌کند.', + slewToHome: 'تغذیه یک برچسب خالی پس از چاپ', mediaFeedHeading: 'تغذیه رسانه', mediaFeedPowerUp: 'هنگام روشن شدن', mediaFeedHeadClose: 'پس از بستن هد', @@ -515,6 +519,7 @@ const fa = { backfeedSeqB: 'قبل از برچسب بعدی', backfeedSeqA: '۱۰۰٪ بعد از چاپ', backfeedSequence: 'توالی پسخور', + backfeedSeqPctFmt: '{pct}٪ بعد از چاپ', }, printQuality: { printOrientation: 'جهت چاپ', @@ -533,6 +538,13 @@ const fa = { codeValidation: 'اعتبارسنجی کد', codeValidationOn: 'روشن', codeValidationOff: 'خاموش', + mapClear: 'تصویر برچسب پس از چاپ', + mapClearOptionClear: 'پاک کردن', + mapClearOptionRetain: 'نگه‌داشتن', + mapClearHint: 'نگه‌داشتن این برچسب را به‌عنوان پس‌زمینه برچسب‌های بعدی حفظ می‌کند (چاپ روی فرم).', + muHeading: 'تبدیل تراکم', + muFormatDpi: 'تراکم قالب', + muOutputDpi: 'تراکم چاپگر', }, clockTime: { setRealtimeClock: 'تنظیم ساعت زمان واقعی', @@ -616,6 +628,15 @@ const fa = { uploadToggle: 'ارسال هنگام راه‌اندازی', missingBytes: 'فونت موجود نیست. بارگذاری کنید یا ورودی را حذف کنید.', removeOrphan: 'حذف ورودی منسوخ', + fontCache: 'حافظه پنهان نویسه‌های مقیاس‌پذیر', + fontCacheEnabled: 'روشن', + fontCacheDisabled: 'خاموش', + fontCacheAddKb: 'حافظه پنهان اضافی', + fontCacheKbUnit: 'کیلوبایت', + fontCacheHint: 'زمانی که کاراکترهای بزرگ مقیاس‌شده به‌کندی یا اصلاً چاپ نمی‌شوند، این مقدار را افزایش دهید.', + fontCacheType: 'نوع حافظه پنهان', + fontCacheTypeNormal: 'بافر معمولی', + fontCacheTypeInternal: 'داخلی (فونت‌های آسیایی)', }, identity: { printerName: 'نام چاپگر', @@ -629,6 +650,17 @@ const fa = { configurationUpdateOptionR: 'فراخوانی آخرین ذخیره', configurationUpdateOptionN: 'بازنشانی تنظیمات شبکه کارخانه (مخرب)', configurationUpdateOptionF: 'بازنشانی کارخانه (مخرب)', + modeProtection: 'حالت‌های محافظت‌شده پنل', + modeProtectCustom: 'مجموعه سفارشی', + modeProtectCustomHint: 'مجموعه سفارشی خالی همه حالت‌های پنل کنترل چاپگر را دوباره فعال می‌کند.', + modeProtectDarkness: 'حالت تیرگی', + modeProtectPosition: 'حالت موقعیت', + modeProtectCalibration: 'حالت کالیبراسیون', + modeProtectSaves: 'ذخیره‌سازی حالت', + modeProtectPause: 'توقف', + modeProtectFeed: 'تغذیه', + modeProtectCancel: 'لغو', + modeProtectMenu: 'تغییرات منو', }, maintenance: { maintenanceAlertHeading: 'هشدار نگهداری', diff --git a/src/locales/fi.ts b/src/locales/fi.ts index 2ac64122..54895321 100644 --- a/src/locales/fi.ts +++ b/src/locales/fi.ts @@ -398,6 +398,7 @@ const fi = { emitZJustifyHint: 'Lähettää oikealle ankkuroituja 1D-viivakoodeja ZPL:n tasausparametrilla, jotta tulostin pitää oikean reunan kiinteänä sarjanumeroille ja muuttuvalle datalle. Vaatii laiteohjelmiston V50.14 tai uudemman; vanhemmat tulostimet sijoittaisivat nämä viivakoodit väärin.', printQuantity: 'Tulostusmäärä', pauseCount: 'Tauko joka N. etiketti', + programmablePause: 'Tauko jokaisen etiketin jälkeen', replicates: 'Replikoinnit per etiketti', overridePauseCount: 'Ohita taukolaskuri', overridePauseCountHint: 'Leikkaa vain erän viimeinen etiketti jokaisen taukorajan sijaan.', @@ -501,6 +502,9 @@ const fi = { mediaTrackingM: 'Merkkitunnistus', mediaTrackingA: 'Automaattinen tunnistus', maxLabelLength: 'Etiketin enimmäispituus', + slewDotRows: 'Ohita tyhjät rivit', + slewDotRowsHint: 'Ohittaa tyhjän alaosan suurella nopeudella tulostamisen sijaan.', + slewToHome: 'Syötä yksi tyhjä etiketti tulostuksen jälkeen', mediaFeedHeading: 'Materiaalin syöttö', mediaFeedPowerUp: 'Käynnistyksessä', mediaFeedHeadClose: 'Pään sulkemisen jälkeen', @@ -515,6 +519,7 @@ const fi = { backfeedSeqB: 'Ennen seuraavaa etikettiä', backfeedSeqA: '100% tulostuksen jälkeen', backfeedSequence: 'Takaisinsyöttöjärjestys', + backfeedSeqPctFmt: '{pct}% tulostuksen jälkeen', }, printQuality: { printOrientation: 'Tulostussuunta', @@ -533,6 +538,13 @@ const fi = { codeValidation: 'Koodin tarkistus', codeValidationOn: 'Päällä', codeValidationOff: 'Pois', + mapClear: 'Etiketin kuva tulostuksen jälkeen', + mapClearOptionClear: 'Tyhjennä', + mapClearOptionRetain: 'Säilytä', + mapClearHint: 'Säilytä pitää tämän etiketin seuraavien etikettien taustana (lomaketulostus).', + muHeading: 'Tiheyden muunnos', + muFormatDpi: 'Muodon tiheys', + muOutputDpi: 'Tulostimen tiheys', }, clockTime: { setRealtimeClock: 'Aseta reaaliaikakello', @@ -616,6 +628,15 @@ const fi = { uploadToggle: 'Lähetä asennuksessa', missingBytes: 'Fontti puuttuu. Lataa se tai poista merkintä.', removeOrphan: 'Poista vanhentunut merkintä', + fontCache: 'Skaalautuvien merkkien välimuisti', + fontCacheEnabled: 'Päällä', + fontCacheDisabled: 'Pois', + fontCacheAddKb: 'Lisävälimuisti', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Kasvata, jos suuret skaalatut merkit tulostuvat hitaasti tai eivät ollenkaan.', + fontCacheType: 'Välimuistin tyyppi', + fontCacheTypeNormal: 'Normaali puskuri', + fontCacheTypeInternal: 'Sisäinen (aasialaiset fontit)', }, identity: { printerName: 'Tulostimen nimi', @@ -629,6 +650,17 @@ const fi = { configurationUpdateOptionR: 'Palauta viimeisin tallennettu', configurationUpdateOptionN: 'Palauta tehtaan verkkoasetukset (tuhoava)', configurationUpdateOptionF: 'Tehdasasetusten palautus (tuhoava)', + modeProtection: 'Suojatut paneelitilat', + modeProtectCustom: 'Mukautettu joukko', + modeProtectCustomHint: 'Tyhjä mukautettu joukko ottaa uudelleen käyttöön kaikki tulostimen ohjauspaneelin tilat.', + modeProtectDarkness: 'Tummuustila', + modeProtectPosition: 'Sijaintitila', + modeProtectCalibration: 'Kalibrointitila', + modeProtectSaves: 'Tilan tallennus', + modeProtectPause: 'Tauko', + modeProtectFeed: 'Syöttö', + modeProtectCancel: 'Peruuta', + modeProtectMenu: 'Valikon muutokset', }, maintenance: { maintenanceAlertHeading: 'Huoltohälytys', diff --git a/src/locales/fr.ts b/src/locales/fr.ts index 5efdd272..f11b2a9a 100644 --- a/src/locales/fr.ts +++ b/src/locales/fr.ts @@ -398,6 +398,7 @@ const fr = { emitZJustifyHint: "Émettre des codes-barres 1D ancrés à droite avec le paramètre de justification ZPL afin que l'imprimante conserve le bord droit fixe pour les numéros de série et les données variables. Nécessite le firmware V50.14 ou plus récent ; les imprimantes plus anciennes positionneraient mal ces codes-barres.", printQuantity: 'Quantité d\'impression', pauseCount: 'Pause toutes les N étiquettes', + programmablePause: 'Pause après chaque étiquette', replicates: 'Réplications par étiquette', overridePauseCount: 'Remplacer le nombre de pauses', overridePauseCountHint: 'Couper uniquement la dernière étiquette du lot au lieu de chaque limite de pause.', @@ -501,6 +502,9 @@ const fr = { mediaTrackingM: 'Détection de marque', mediaTrackingA: 'Détection automatique', maxLabelLength: "Longueur maximale d'étiquette", + slewDotRows: 'Ignorer les lignes vierges', + slewDotRowsHint: "Saute une zone vierge en bas de l'étiquette à grande vitesse au lieu de l'imprimer.", + slewToHome: "Faire avancer une étiquette vierge après l'impression", mediaFeedHeading: 'Avance du support', mediaFeedPowerUp: 'À la mise sous tension', mediaFeedHeadClose: 'Après fermeture de la tête', @@ -515,6 +519,7 @@ const fr = { backfeedSeqB: 'Avant la prochaine étiquette', backfeedSeqA: '100% après impression', backfeedSequence: 'Séquence de recul', + backfeedSeqPctFmt: '{pct}% après impression', }, printQuality: { printOrientation: 'Orientation d’impression', @@ -533,6 +538,13 @@ const fr = { codeValidation: 'Validation du code', codeValidationOn: 'Activé', codeValidationOff: 'Désactivé', + mapClear: "Image de l'étiquette après impression", + mapClearOptionClear: 'Effacer', + mapClearOptionRetain: 'Conserver', + mapClearHint: 'Conserver garde cette étiquette comme arrière-plan des étiquettes suivantes (impression sur formulaire).', + muHeading: 'Reconversion de densité', + muFormatDpi: 'Densité du format', + muOutputDpi: "Densité de l'imprimante", }, clockTime: { setRealtimeClock: 'Régler l\'horloge temps réel', @@ -616,6 +628,15 @@ const fr = { uploadToggle: "Envoyer à l'installation", missingBytes: "Police manquante. Téléversez-la ou supprimez l'entrée.", removeOrphan: "Supprimer l'entrée obsolète", + fontCache: 'Cache de caractères vectoriels', + fontCacheEnabled: 'Activé', + fontCacheDisabled: 'Désactivé', + fontCacheAddKb: 'Mémoire cache supplémentaire', + fontCacheKbUnit: 'Ko', + fontCacheHint: "Augmenter lorsque les grands caractères mis à l'échelle s'impriment lentement ou pas du tout.", + fontCacheType: 'Type de cache', + fontCacheTypeNormal: 'Tampon normal', + fontCacheTypeInternal: 'Interne (polices asiatiques)', }, identity: { printerName: 'Nom de l\'imprimante', @@ -629,6 +650,17 @@ const fr = { configurationUpdateOptionR: 'Rappeler la dernière sauvegarde', configurationUpdateOptionN: 'Recharger les réglages réseau d\'usine (destructif)', configurationUpdateOptionF: 'Réinitialisation usine (destructif)', + modeProtection: 'Modes de panneau protégés', + modeProtectCustom: 'Ensemble personnalisé', + modeProtectCustomHint: "Un ensemble personnalisé vide réactive tous les modes du panneau de contrôle de l'imprimante.", + modeProtectDarkness: "Mode densité d'impression", + modeProtectPosition: 'Mode position', + modeProtectCalibration: 'Mode calibration', + modeProtectSaves: 'Enregistrements de mode', + modeProtectPause: 'Pause', + modeProtectFeed: 'Avance', + modeProtectCancel: 'Annuler', + modeProtectMenu: 'Modifications du menu', }, maintenance: { maintenanceAlertHeading: 'Alerte de maintenance', diff --git a/src/locales/he.ts b/src/locales/he.ts index 907db4b5..33758947 100644 --- a/src/locales/he.ts +++ b/src/locales/he.ts @@ -398,6 +398,7 @@ const he = { emitZJustifyHint: 'פליטת ברקודים חד-ממדיים מעוגנים לימין באמצעות פרמטר היישור של ZPL, כך שהמדפסת שומרת על הקצה הימני קבוע עבור מספרים סידוריים ונתונים משתנים. דורש קושחה V50.14 ומעלה; מדפסות ישנות יותר ימקמו ברקודים אלה באופן שגוי.', printQuantity: 'כמות הדפסה', pauseCount: 'השהיה כל N תוויות', + programmablePause: 'השהיה אחרי כל תווית', replicates: 'שכפולים לכל תווית', overridePauseCount: 'עקוף ספירת השהיה', overridePauseCountHint: 'חתוך רק את התווית האחרונה באצווה במקום בכל גבול השהיה.', @@ -501,6 +502,9 @@ const he = { mediaTrackingM: 'חישת סימן', mediaTrackingA: 'זיהוי אוטומטי', maxLabelLength: 'אורך תווית מרבי', + slewDotRows: 'דילוג על שורות ריקות', + slewDotRowsHint: 'מדלג על אזור תחתון ריק במהירות גבוהה במקום להדפיס אותו.', + slewToHome: 'הזנת תווית ריקה אחת לאחר ההדפסה', mediaFeedHeading: 'הזנת מדיה', mediaFeedPowerUp: 'בהפעלה', mediaFeedHeadClose: 'לאחר סגירת הראש', @@ -515,6 +519,7 @@ const he = { backfeedSeqB: 'לפני התווית הבאה', backfeedSeqA: '100% אחרי הדפסה', backfeedSequence: 'רצף הזנה לאחור', + backfeedSeqPctFmt: '{pct}% אחרי הדפסה', }, printQuality: { printOrientation: 'כיוון הדפסה', @@ -533,6 +538,13 @@ const he = { codeValidation: 'אימות קוד', codeValidationOn: 'מופעל', codeValidationOff: 'כבוי', + mapClear: 'תמונת התווית לאחר ההדפסה', + mapClearOptionClear: 'ניקוי', + mapClearOptionRetain: 'שמירה', + mapClearHint: 'שמירה משאירה את התווית הזו כרקע לתוויות הבאות (הדפסה על תבנית).', + muHeading: 'המרת צפיפות', + muFormatDpi: 'צפיפות הפורמט', + muOutputDpi: 'צפיפות המדפסת', }, clockTime: { setRealtimeClock: 'הגדר שעון זמן אמת', @@ -616,6 +628,15 @@ const he = { uploadToggle: 'שלח בהתקנה', missingBytes: 'הגופן חסר. העלה אותו או הסר את הרשומה.', removeOrphan: 'הסר רשומה מיושנת', + fontCache: 'מטמון תווים ניתנים לשינוי גודל', + fontCacheEnabled: 'מופעל', + fontCacheDisabled: 'כבוי', + fontCacheAddKb: 'זיכרון מטמון נוסף', + fontCacheKbUnit: 'KB', + fontCacheHint: 'הגדל כאשר תווים מוגדלים גדולים מודפסים לאט או לא מודפסים כלל.', + fontCacheType: 'סוג מטמון', + fontCacheTypeNormal: 'מאגר רגיל', + fontCacheTypeInternal: 'פנימי (גופנים אסייתיים)', }, identity: { printerName: 'שם המדפסת', @@ -629,6 +650,17 @@ const he = { configurationUpdateOptionR: 'שחזור הגדרה אחרונה', configurationUpdateOptionN: 'טען מחדש הגדרות רשת יצרן (הרסני)', configurationUpdateOptionF: 'איפוס יצרן (הרסני)', + modeProtection: 'מצבי פאנל מוגנים', + modeProtectCustom: 'קבוצה מותאמת אישית', + modeProtectCustomHint: 'קבוצה מותאמת אישית ריקה מפעילה מחדש את כל מצבי לוח הבקרה במדפסת.', + modeProtectDarkness: 'מצב כהות', + modeProtectPosition: 'מצב מיקום', + modeProtectCalibration: 'מצב כיול', + modeProtectSaves: 'שמירות מצב', + modeProtectPause: 'השהיה', + modeProtectFeed: 'הזנה', + modeProtectCancel: 'ביטול', + modeProtectMenu: 'שינויי תפריט', }, maintenance: { maintenanceAlertHeading: 'התראת תחזוקה', diff --git a/src/locales/hr.ts b/src/locales/hr.ts index 21d66152..0fcb0da4 100644 --- a/src/locales/hr.ts +++ b/src/locales/hr.ts @@ -398,6 +398,7 @@ const hr = { emitZJustifyHint: 'Generira 1D crtične kodove usidrene s desne strane pomoću ZPL parametra poravnanja, kako bi pisač zadržao desni rub fiksnim za serijske brojeve i promjenjive podatke. Zahtijeva firmver V50.14 ili noviji; stariji pisači bi te crtične kodove pogrešno postavili.', printQuantity: 'Količina ispisa', pauseCount: 'Pauza svakih N etiketa', + programmablePause: 'Pauza nakon svake etikete', replicates: 'Replike po etiketi', overridePauseCount: 'Premosti brojač pauze', overridePauseCountHint: 'Reže samo posljednju etiketu serije umjesto na svakoj granici pauze.', @@ -501,6 +502,9 @@ const hr = { mediaTrackingM: 'Detekcija oznake', mediaTrackingA: 'Automatska detekcija', maxLabelLength: 'Maksimalna duljina etikete', + slewDotRows: 'Preskoči prazne retke', + slewDotRowsHint: 'Preskače prazno donje područje velikom brzinom umjesto da ga ispisuje.', + slewToHome: 'Pomakni jednu praznu etiketu nakon ispisa', mediaFeedHeading: 'Pomak medija', mediaFeedPowerUp: 'Pri uključivanju', mediaFeedHeadClose: 'Nakon zatvaranja glave', @@ -515,6 +519,7 @@ const hr = { backfeedSeqB: 'Prije sljedeće naljepnice', backfeedSeqA: '100% nakon ispisa', backfeedSequence: 'Slijed povratnog uvlačenja', + backfeedSeqPctFmt: '{pct}% nakon ispisa', }, printQuality: { printOrientation: 'Orijentacija ispisa', @@ -533,6 +538,13 @@ const hr = { codeValidation: 'Validacija koda', codeValidationOn: 'Uključeno', codeValidationOff: 'Isključeno', + mapClear: 'Slika etikete nakon ispisa', + mapClearOptionClear: 'Brisanje', + mapClearOptionRetain: 'Zadrži', + mapClearHint: 'Zadrži zadržava ovu etiketu kao pozadinu sljedećih etiketa (ispis na predlošku).', + muHeading: 'Pretvorba gustoće', + muFormatDpi: 'Gustoća formata', + muOutputDpi: 'Gustoća pisača', }, clockTime: { setRealtimeClock: 'Postavi sat u stvarnom vremenu', @@ -616,6 +628,15 @@ const hr = { uploadToggle: 'Pošalji pri postavljanju', missingBytes: 'Font nedostaje. Učitajte ga ili uklonite unos.', removeOrphan: 'Ukloni zastarjeli unos', + fontCache: 'Predmemorija skalabilnih znakova', + fontCacheEnabled: 'Uključeno', + fontCacheDisabled: 'Isključeno', + fontCacheAddKb: 'Dodatna memorija predmemorije', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Povećajte kada se veliki skalirani znakovi ispisuju sporo ili se uopće ne ispisuju.', + fontCacheType: 'Vrsta predmemorije', + fontCacheTypeNormal: 'Normalni međuspremnik', + fontCacheTypeInternal: 'Interni (azijski fontovi)', }, identity: { printerName: 'Naziv pisača', @@ -629,6 +650,17 @@ const hr = { configurationUpdateOptionR: 'Vrati zadnju spremljenu', configurationUpdateOptionN: 'Vrati tvorničke mrežne postavke (destruktivno)', configurationUpdateOptionF: 'Tvornički reset (destruktivno)', + modeProtection: 'Zaštićeni načini rada ploče', + modeProtectCustom: 'Prilagođeni skup', + modeProtectCustomHint: 'Prazan prilagođeni skup ponovno omogućuje sve načine upravljačke ploče pisača.', + modeProtectDarkness: 'Način zatamnjenja', + modeProtectPosition: 'Način položaja', + modeProtectCalibration: 'Način kalibracije', + modeProtectSaves: 'Spremanje načina', + modeProtectPause: 'Pauza', + modeProtectFeed: 'Pomak', + modeProtectCancel: 'Odustani', + modeProtectMenu: 'Promjene izbornika', }, maintenance: { maintenanceAlertHeading: 'Upozorenje o održavanju', diff --git a/src/locales/hu.ts b/src/locales/hu.ts index b8cee368..673eb64a 100644 --- a/src/locales/hu.ts +++ b/src/locales/hu.ts @@ -398,6 +398,7 @@ const hu = { emitZJustifyHint: 'Jobbra rögzített 1D vonalkódokat küld a ZPL igazítási paraméterével, hogy a nyomtató a sorozatszámok és a változó adatok jobb szélét fixen tartsa. V50.14 vagy újabb firmware szükséges; a régebbi nyomtatók rosszul helyeznék el ezeket a vonalkódokat.', printQuantity: 'Nyomtatási mennyiség', pauseCount: 'Szünet N címkénként', + programmablePause: 'Szünet minden címke után', replicates: 'Ismétlés címkénként', overridePauseCount: 'Szünetszám felülbírálása', overridePauseCountHint: 'Csak a köteg utolsó címkéjét vágja minden szünethatár helyett.', @@ -501,6 +502,9 @@ const hu = { mediaTrackingM: 'Jelölésérzékelés', mediaTrackingA: 'Automatikus felismerés', maxLabelLength: 'Maximális címkehossz', + slewDotRows: 'Üres sorok kihagyása', + slewDotRowsHint: 'Nagy sebességgel átugorja az üres alsó területet nyomtatás helyett.', + slewToHome: 'Nyomtatás után egy üres címke továbbítása', mediaFeedHeading: 'Hordozó továbbítása', mediaFeedPowerUp: 'Bekapcsoláskor', mediaFeedHeadClose: 'Fej zárása után', @@ -515,6 +519,7 @@ const hu = { backfeedSeqB: 'Következő címke előtt', backfeedSeqA: '100% nyomtatás után', backfeedSequence: 'Visszahúzási sorrend', + backfeedSeqPctFmt: '{pct}% nyomtatás után', }, printQuality: { printOrientation: 'Nyomtatási irány', @@ -533,6 +538,13 @@ const hu = { codeValidation: 'Kódellenőrzés', codeValidationOn: 'Be', codeValidationOff: 'Ki', + mapClear: 'Címkekép nyomtatás után', + mapClearOptionClear: 'Törlés', + mapClearOptionRetain: 'Megtartás', + mapClearHint: 'A Megtartás megőrzi ezt a címkét a következő címkék hátteréül (sablonnyomtatás).', + muHeading: 'Sűrűség-átszámítás', + muFormatDpi: 'Formátum sűrűsége', + muOutputDpi: 'Nyomtató sűrűsége', }, clockTime: { setRealtimeClock: 'Valós idejű óra beállítása', @@ -616,6 +628,15 @@ const hu = { uploadToggle: 'Küldés beállításkor', missingBytes: 'Hiányzó betűtípus. Töltsd fel vagy távolítsd el a bejegyzést.', removeOrphan: 'Elavult bejegyzés eltávolítása', + fontCache: 'Skálázható karakter-gyorsítótár', + fontCacheEnabled: 'Be', + fontCacheDisabled: 'Ki', + fontCacheAddKb: 'További gyorsítótár-memória', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Növelje, ha a nagy méretezett karakterek lassan vagy egyáltalán nem nyomtatódnak.', + fontCacheType: 'Gyorsítótár típusa', + fontCacheTypeNormal: 'Normál puffer', + fontCacheTypeInternal: 'Belső (ázsiai betűtípusok)', }, identity: { printerName: 'Nyomtató neve', @@ -629,6 +650,17 @@ const hu = { configurationUpdateOptionR: 'Utolsó mentett visszahívása', configurationUpdateOptionN: 'Gyári hálózati beállítások visszaállítása (destruktív)', configurationUpdateOptionF: 'Gyári visszaállítás (destruktív)', + modeProtection: 'Védett panelmódok', + modeProtectCustom: 'Egyéni készlet', + modeProtectCustomHint: 'Az üres egyéni készlet minden nyomtatói kezelőpanel-módot újra engedélyez.', + modeProtectDarkness: 'Sötétségi mód', + modeProtectPosition: 'Pozíció mód', + modeProtectCalibration: 'Kalibrálási mód', + modeProtectSaves: 'Mód mentése', + modeProtectPause: 'Szünet', + modeProtectFeed: 'Továbbítás', + modeProtectCancel: 'Mégse', + modeProtectMenu: 'Menüváltozások', }, maintenance: { maintenanceAlertHeading: 'Karbantartási riasztás', diff --git a/src/locales/it.ts b/src/locales/it.ts index be0c23c4..ab0edd4d 100644 --- a/src/locales/it.ts +++ b/src/locales/it.ts @@ -398,6 +398,7 @@ const it = { emitZJustifyHint: 'Emette codici a barre 1D ancorati a destra con il parametro di giustificazione ZPL affinché la stampante mantenga fisso il bordo destro per numeri di serie e dati variabili. Richiede firmware V50.14 o successivo; le stampanti più vecchie posizionerebbero male questi codici a barre.', printQuantity: 'Quantità di stampa', pauseCount: 'Pausa ogni N etichette', + programmablePause: 'Pausa dopo ogni etichetta', replicates: 'Repliche per etichetta', overridePauseCount: 'Sostituisci conteggio pause', overridePauseCountHint: 'Taglia solo l\'ultima etichetta del lotto invece di ogni limite di pausa.', @@ -501,6 +502,9 @@ const it = { mediaTrackingM: 'Rilevamento marcatura', mediaTrackingA: 'Rilevamento automatico', maxLabelLength: 'Lunghezza massima etichetta', + slewDotRows: 'Salta righe vuote', + slewDotRowsHint: "Salta un'area vuota in basso ad alta velocità invece di stamparla.", + slewToHome: "Avanza un'etichetta vuota dopo la stampa", mediaFeedHeading: 'Avanzamento supporto', mediaFeedPowerUp: 'All’accensione', mediaFeedHeadClose: 'Dopo chiusura testina', @@ -515,6 +519,7 @@ const it = { backfeedSeqB: 'Prima della prossima etichetta', backfeedSeqA: '100% dopo la stampa', backfeedSequence: 'Sequenza di retroazione', + backfeedSeqPctFmt: '{pct}% dopo la stampa', }, printQuality: { printOrientation: 'Orientamento di stampa', @@ -533,6 +538,13 @@ const it = { codeValidation: 'Convalida codice', codeValidationOn: 'Attivo', codeValidationOff: 'Disattivo', + mapClear: "Immagine dell'etichetta dopo la stampa", + mapClearOptionClear: 'Cancella', + mapClearOptionRetain: 'Mantieni', + mapClearHint: 'Mantieni conserva questa etichetta come sfondo delle etichette successive (stampa su modulo).', + muHeading: 'Ricampionamento densità', + muFormatDpi: 'Densità formato', + muOutputDpi: 'Densità stampante', }, clockTime: { setRealtimeClock: 'Imposta orologio in tempo reale', @@ -616,6 +628,15 @@ const it = { uploadToggle: 'Invia alla configurazione', missingBytes: 'Font mancante. Caricalo o rimuovi la voce.', removeOrphan: 'Rimuovi voce obsoleta', + fontCache: 'Cache dei caratteri scalabili', + fontCacheEnabled: 'Attivo', + fontCacheDisabled: 'Disattivo', + fontCacheAddKb: 'Memoria cache aggiuntiva', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Aumenta quando i caratteri ridimensionati di grandi dimensioni vengono stampati lentamente o non vengono stampati affatto.', + fontCacheType: 'Tipo di cache', + fontCacheTypeNormal: 'Buffer normale', + fontCacheTypeInternal: 'Interno (font asiatici)', }, identity: { printerName: 'Nome stampante', @@ -629,6 +650,17 @@ const it = { configurationUpdateOptionR: 'Richiama l\'ultima salvata', configurationUpdateOptionN: 'Ricarica impostazioni di rete di fabbrica (distruttivo)', configurationUpdateOptionF: 'Ripristino di fabbrica (distruttivo)', + modeProtection: 'Modalità pannello protette', + modeProtectCustom: 'Set personalizzato', + modeProtectCustomHint: 'Un set personalizzato vuoto riattiva tutte le modalità del pannello di controllo della stampante.', + modeProtectDarkness: 'Modalità densità di stampa', + modeProtectPosition: 'Modalità posizione', + modeProtectCalibration: 'Modalità calibrazione', + modeProtectSaves: 'Salvataggi di modalità', + modeProtectPause: 'Pausa', + modeProtectFeed: 'Avanzamento', + modeProtectCancel: 'Annulla', + modeProtectMenu: 'Modifiche al menu', }, maintenance: { maintenanceAlertHeading: 'Avviso di manutenzione', diff --git a/src/locales/ja.ts b/src/locales/ja.ts index 211c4ff9..cc761113 100644 --- a/src/locales/ja.ts +++ b/src/locales/ja.ts @@ -398,6 +398,7 @@ const ja = { emitZJustifyHint: 'ZPLの位置揃えパラメータを使用して右端固定の1Dバーコードを出力し、シリアル番号や可変データでプリンターが右端を固定したまま印字できるようにします。ファームウェアV50.14以降が必要です。古いプリンターではバーコードの位置がずれます。', printQuantity: '印刷枚数', pauseCount: 'N枚ごとに一時停止', + programmablePause: 'ラベルごとに一時停止', replicates: 'ラベルごとの複製数', overridePauseCount: '一時停止カウントを上書き', overridePauseCountHint: '各一時停止境界ではなく、バッチの最後のラベルのみカットします。', @@ -501,6 +502,9 @@ const ja = { mediaTrackingM: 'マーク検出', mediaTrackingA: '自動検出', maxLabelLength: 'ラベルの最大長', + slewDotRows: '空白行をスキップ', + slewDotRowsHint: '下部の空白領域を印刷せず、高速でスキップします。', + slewToHome: '印刷後に空白ラベルを1枚送る', mediaFeedHeading: 'メディア給紙', mediaFeedPowerUp: '電源投入時', mediaFeedHeadClose: 'ヘッド閉鎖後', @@ -515,6 +519,7 @@ const ja = { backfeedSeqB: '次のラベルの前', backfeedSeqA: '印刷後100%', backfeedSequence: 'バックフィード順序', + backfeedSeqPctFmt: '印刷後{pct}%', }, printQuality: { printOrientation: '印刷方向', @@ -533,6 +538,13 @@ const ja = { codeValidation: 'コード検証', codeValidationOn: 'オン', codeValidationOff: 'オフ', + mapClear: '印刷後のラベル画像', + mapClearOptionClear: 'クリア', + mapClearOptionRetain: '保持', + mapClearHint: '「保持」を選択すると、このラベルが以降のラベルの背景として残ります(フォーム印刷)。', + muHeading: '密度変換', + muFormatDpi: 'フォーマット密度', + muOutputDpi: 'プリンター密度', }, clockTime: { setRealtimeClock: 'リアルタイムクロックを設定', @@ -616,6 +628,15 @@ const ja = { uploadToggle: 'セットアップ時に送信', missingBytes: 'フォントが見つかりません。アップロードするか項目を削除してください。', removeOrphan: '古い項目を削除', + fontCache: '拡大縮小フォントのキャッシュ', + fontCacheEnabled: 'オン', + fontCacheDisabled: 'オフ', + fontCacheAddKb: '追加キャッシュメモリ', + fontCacheKbUnit: 'KB', + fontCacheHint: '大きく拡大された文字の印刷が遅い、または印刷されない場合は値を増やしてください。', + fontCacheType: 'キャッシュの種類', + fontCacheTypeNormal: '通常バッファ', + fontCacheTypeInternal: '内部(アジア言語フォント)', }, identity: { printerName: 'プリンター名', @@ -629,6 +650,17 @@ const ja = { configurationUpdateOptionR: '最後の保存を呼び出し', configurationUpdateOptionN: '工場ネットワーク設定の再読み込み (破壊的)', configurationUpdateOptionF: '工場リセット (破壊的)', + modeProtection: '保護されたパネルモード', + modeProtectCustom: 'カスタム設定', + modeProtectCustomHint: 'カスタム設定を空にすると、プリンターのコントロールパネルのすべてのモードが再び有効になります。', + modeProtectDarkness: '濃度モード', + modeProtectPosition: '位置モード', + modeProtectCalibration: 'キャリブレーションモード', + modeProtectSaves: 'モードの保存', + modeProtectPause: '一時停止', + modeProtectFeed: '送り', + modeProtectCancel: 'キャンセル', + modeProtectMenu: 'メニューの変更', }, maintenance: { maintenanceAlertHeading: 'メンテナンス警告', diff --git a/src/locales/ko.ts b/src/locales/ko.ts index 173b72e0..94aa6735 100644 --- a/src/locales/ko.ts +++ b/src/locales/ko.ts @@ -398,6 +398,7 @@ const ko = { emitZJustifyHint: 'ZPL 정렬 매개변수를 사용하여 오른쪽으로 고정된 1D 바코드를 출력하여, 프린터가 일련번호와 가변 데이터의 오른쪽 가장자리를 고정 유지하도록 합니다. 펌웨어 V50.14 이상이 필요하며, 이전 프린터에서는 바코드 위치가 잘못될 수 있습니다.', printQuantity: '인쇄 수량', pauseCount: 'N개 라벨마다 일시정지', + programmablePause: '라벨마다 일시 정지', replicates: '라벨당 복제 수', overridePauseCount: '일시정지 카운트 재정의', overridePauseCountHint: '각 일시정지 경계가 아닌 배치의 마지막 라벨만 자릅니다.', @@ -501,6 +502,9 @@ const ko = { mediaTrackingM: '마크 감지', mediaTrackingA: '자동 감지', maxLabelLength: '최대 라벨 길이', + slewDotRows: '빈 행 건너뛰기', + slewDotRowsHint: '하단의 빈 영역을 인쇄하지 않고 고속으로 건너뜁니다.', + slewToHome: '인쇄 후 빈 라벨 한 장 이송', mediaFeedHeading: '미디어 급지', mediaFeedPowerUp: '전원 켤 때', mediaFeedHeadClose: '헤드 닫은 후', @@ -515,6 +519,7 @@ const ko = { backfeedSeqB: '다음 라벨 전', backfeedSeqA: '인쇄 후 100%', backfeedSequence: '백피드 순서', + backfeedSeqPctFmt: '인쇄 후 {pct}%', }, printQuality: { printOrientation: '인쇄 방향', @@ -533,6 +538,13 @@ const ko = { codeValidation: '코드 검증', codeValidationOn: '켜기', codeValidationOff: '끄기', + mapClear: '인쇄 후 라벨 이미지', + mapClearOptionClear: '지우기', + mapClearOptionRetain: '유지', + mapClearHint: '유지를 선택하면 이 라벨이 이후 라벨의 배경으로 남습니다(양식 인쇄).', + muHeading: '밀도 리샘플링', + muFormatDpi: '포맷 밀도', + muOutputDpi: '프린터 밀도', }, clockTime: { setRealtimeClock: '실시간 시계 설정', @@ -616,6 +628,15 @@ const ko = { uploadToggle: '설정 시 전송', missingBytes: '글꼴 없음. 업로드하거나 항목을 제거하세요.', removeOrphan: '오래된 항목 제거', + fontCache: '확대/축소 가능한 문자 캐시', + fontCacheEnabled: '켜기', + fontCacheDisabled: '끄기', + fontCacheAddKb: '추가 캐시 메모리', + fontCacheKbUnit: 'KB', + fontCacheHint: '크게 확대된 문자가 느리게 인쇄되거나 전혀 인쇄되지 않을 때 늘리세요.', + fontCacheType: '캐시 유형', + fontCacheTypeNormal: '일반 버퍼', + fontCacheTypeInternal: '내부 (아시아 글꼴)', }, identity: { printerName: '프린터 이름', @@ -629,6 +650,17 @@ const ko = { configurationUpdateOptionR: '마지막 저장 불러오기', configurationUpdateOptionN: '공장 네트워크 설정 재로드 (파괴적)', configurationUpdateOptionF: '공장 초기화 (파괴적)', + modeProtection: '보호된 패널 모드', + modeProtectCustom: '사용자 지정 세트', + modeProtectCustomHint: '빈 사용자 지정 세트는 프린터의 모든 제어판 모드를 다시 활성화합니다.', + modeProtectDarkness: '농도 모드', + modeProtectPosition: '위치 모드', + modeProtectCalibration: '보정 모드', + modeProtectSaves: '모드 저장', + modeProtectPause: '일시 정지', + modeProtectFeed: '이송', + modeProtectCancel: '취소', + modeProtectMenu: '메뉴 변경', }, maintenance: { maintenanceAlertHeading: '유지보수 경고', diff --git a/src/locales/lt.ts b/src/locales/lt.ts index 1b9c346d..05c753f6 100644 --- a/src/locales/lt.ts +++ b/src/locales/lt.ts @@ -398,6 +398,7 @@ const lt = { emitZJustifyHint: 'Siunčia dešinėje pusėje užfiksuotus 1D brūkšninius kodus naudojant ZPL lygiavimo parametrą, kad spausdintuvas išlaikytų fiksuotą dešinįjį kraštą serijos numeriams ir kintamiems duomenims. Reikalinga V50.14 ar naujesnė programinė aparatinė įranga; senesni spausdintuvai šiuos brūkšninius kodus išdėstytų neteisingai.', printQuantity: 'Spausdinimo kiekis', pauseCount: 'Pauzė kas N etikečių', + programmablePause: 'Pauzė po kiekvienos etiketės', replicates: 'Pakartojimai etiketei', overridePauseCount: 'Nepaisyti pauzės skaitiklio', overridePauseCountHint: 'Kirpti tik paskutinę partijos etiketę vietoj kiekvienos pauzės ribos.', @@ -501,6 +502,9 @@ const lt = { mediaTrackingM: 'Žymos aptikimas', mediaTrackingA: 'Automatinis aptikimas', maxLabelLength: 'Didžiausias etiketės ilgis', + slewDotRows: 'Praleisti tuščias eilutes', + slewDotRowsHint: 'Praleidžia tuščią apatinę sritį dideliu greičiu vietoj jos spausdinimo.', + slewToHome: 'Po spausdinimo pastumti vieną tuščią etiketę', mediaFeedHeading: 'Laikmenos tiekimas', mediaFeedPowerUp: 'Įjungus', mediaFeedHeadClose: 'Uždarius galvutę', @@ -515,6 +519,7 @@ const lt = { backfeedSeqB: 'Prieš kitą etiketę', backfeedSeqA: '100% po spausdinimo', backfeedSequence: 'Grįžimo seka', + backfeedSeqPctFmt: '{pct}% po spausdinimo', }, printQuality: { printOrientation: 'Spausdinimo orientacija', @@ -533,6 +538,13 @@ const lt = { codeValidation: 'Kodo tikrinimas', codeValidationOn: 'Įjungta', codeValidationOff: 'Išjungta', + mapClear: 'Etiketės vaizdas po spausdinimo', + mapClearOptionClear: 'Išvalyti', + mapClearOptionRetain: 'Išsaugoti', + mapClearHint: 'Išsaugoti palieka šią etiketę kaip foną kitoms etiketėms (spausdinimas ant šablono).', + muHeading: 'Tankio konvertavimas', + muFormatDpi: 'Formato tankis', + muOutputDpi: 'Spausdintuvo tankis', }, clockTime: { setRealtimeClock: 'Nustatyti realaus laiko laikrodį', @@ -616,6 +628,15 @@ const lt = { uploadToggle: 'Siųsti sąrankoje', missingBytes: 'Trūksta šrifto. Įkelkite jį arba pašalinkite įrašą.', removeOrphan: 'Pašalinti pasenusį įrašą', + fontCache: 'Keičiamo dydžio simbolių podėlis', + fontCacheEnabled: 'Įjungta', + fontCacheDisabled: 'Išjungta', + fontCacheAddKb: 'Papildoma podėlio atmintis', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Padidinkite, kai dideli mastelio pakeisti simboliai spausdinami lėtai arba visai nespausdinami.', + fontCacheType: 'Podėlio tipas', + fontCacheTypeNormal: 'Įprastas buferis', + fontCacheTypeInternal: 'Vidinis (Azijos šriftai)', }, identity: { printerName: 'Spausdintuvo pavadinimas', @@ -629,6 +650,17 @@ const lt = { configurationUpdateOptionR: 'Atkurti paskutinę išsaugotą', configurationUpdateOptionN: 'Atkurti gamyklinius tinklo nustatymus (destruktyvus)', configurationUpdateOptionF: 'Gamyklinis atstatymas (destruktyvus)', + modeProtection: 'Apsaugoti skydelio režimai', + modeProtectCustom: 'Tinkinta rinkinys', + modeProtectCustomHint: 'Tuščias tinkintas rinkinys iš naujo įjungia visus spausdintuvo valdymo skydelio režimus.', + modeProtectDarkness: 'Tamsumo režimas', + modeProtectPosition: 'Padėties režimas', + modeProtectCalibration: 'Kalibravimo režimas', + modeProtectSaves: 'Režimo išsaugojimas', + modeProtectPause: 'Pauzė', + modeProtectFeed: 'Tiekimas', + modeProtectCancel: 'Atšaukti', + modeProtectMenu: 'Meniu pakeitimai', }, maintenance: { maintenanceAlertHeading: 'Techninės priežiūros įspėjimas', diff --git a/src/locales/lv.ts b/src/locales/lv.ts index c0ee099b..38d65dec 100644 --- a/src/locales/lv.ts +++ b/src/locales/lv.ts @@ -398,6 +398,7 @@ const lv = { emitZJustifyHint: 'Izvada pa labi enkurotus 1D svītrkodus ar ZPL līdzināšanas parametru, lai printeris saglabātu fiksētu labo malu sērijas numuriem un mainīgajiem datiem. Nepieciešams V50.14 vai jaunāks aparātprogrammatūras variants; vecāki printeri šos svītrkodus izvietotu nepareizi.', printQuantity: 'Drukāšanas daudzums', pauseCount: 'Pauze ik pēc N etiķetēm', + programmablePause: 'Pauze pēc katras etiķetes', replicates: 'Atkārtojumi uz etiķeti', overridePauseCount: 'Pārrakstīt pauzes skaitītāju', overridePauseCountHint: 'Griezt tikai pēdējo partijas etiķeti, nevis pie katras pauzes robežas.', @@ -501,6 +502,9 @@ const lv = { mediaTrackingM: 'Atzīmes noteikšana', mediaTrackingA: 'Automātiska noteikšana', maxLabelLength: 'Maksimālais etiķetes garums', + slewDotRows: 'Izlaist tukšās rindas', + slewDotRowsHint: 'Ātrā režīmā izlaiž tukšu zonu apakšā, tā vietā, lai to izdrukātu.', + slewToHome: 'Padot vienu tukšu etiķeti pēc drukāšanas', mediaFeedHeading: 'Materiāla padeve', mediaFeedPowerUp: 'Ieslēdzot', mediaFeedHeadClose: 'Pēc galviņas aizvēršanas', @@ -515,6 +519,7 @@ const lv = { backfeedSeqB: 'Pirms nākamās etiķetes', backfeedSeqA: '100% pēc drukāšanas', backfeedSequence: 'Atpakaļpadeves secība', + backfeedSeqPctFmt: '{pct}% pēc drukāšanas', }, printQuality: { printOrientation: 'Drukas orientācija', @@ -533,6 +538,13 @@ const lv = { codeValidation: 'Koda validācija', codeValidationOn: 'Ieslēgts', codeValidationOff: 'Izslēgts', + mapClear: 'Etiķetes attēls pēc drukāšanas', + mapClearOptionClear: 'Notīrīt', + mapClearOptionRetain: 'Saglabāt', + mapClearHint: 'Saglabāt saglabā šo etiķeti kā fonu turpmākajām etiķetēm (drukāšana uz veidnes).', + muHeading: 'Blīvuma pārveide', + muFormatDpi: 'Formāta blīvums', + muOutputDpi: 'Printera blīvums', }, clockTime: { setRealtimeClock: 'Iestatīt reālā laika pulksteni', @@ -616,6 +628,15 @@ const lv = { uploadToggle: 'Sūtīt iestatīšanā', missingBytes: 'Trūkst fonta. Augšupielādējiet to vai noņemiet ierakstu.', removeOrphan: 'Noņemt novecojušu ierakstu', + fontCache: 'Mērogojamu rakstzīmju kešatmiņa', + fontCacheEnabled: 'Ieslēgts', + fontCacheDisabled: 'Izslēgts', + fontCacheAddKb: 'Papildu kešatmiņas apjoms', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Palieliniet, ja lieli mērogoti rakstzīmes tiek drukātas lēni vai vispār netiek drukātas.', + fontCacheType: 'Kešatmiņas veids', + fontCacheTypeNormal: 'Parasts buferis', + fontCacheTypeInternal: 'Iekšējs (Āzijas fonti)', }, identity: { printerName: 'Printera nosaukums', @@ -629,6 +650,17 @@ const lv = { configurationUpdateOptionR: 'Atjaunot pēdējo saglabāto', configurationUpdateOptionN: 'Atjaunot rūpnīcas tīkla iestatījumus (destruktīvi)', configurationUpdateOptionF: 'Rūpnīcas atiestatīšana (destruktīvi)', + modeProtection: 'Aizsargāti paneļa režīmi', + modeProtectCustom: 'Pielāgota kopa', + modeProtectCustomHint: 'Tukša pielāgota kopa atkārtoti iespējo visus printera vadības paneļa režīmus.', + modeProtectDarkness: 'Tumšuma režīms', + modeProtectPosition: 'Pozīcijas režīms', + modeProtectCalibration: 'Kalibrēšanas režīms', + modeProtectSaves: 'Režīma saglabāšana', + modeProtectPause: 'Pauze', + modeProtectFeed: 'Padeve', + modeProtectCancel: 'Atcelt', + modeProtectMenu: 'Izvēlnes izmaiņas', }, maintenance: { maintenanceAlertHeading: 'Apkopes brīdinājums', diff --git a/src/locales/nl.ts b/src/locales/nl.ts index d9b26bc3..159ccb96 100644 --- a/src/locales/nl.ts +++ b/src/locales/nl.ts @@ -398,6 +398,7 @@ const nl = { emitZJustifyHint: 'Genereer rechts verankerde 1D-barcodes met de ZPL-uitlijningsparameter, zodat de printer de rechterrand vast houdt voor serienummers en variabele gegevens. Vereist firmware V50.14 of nieuwer; oudere printers plaatsen deze barcodes anders verkeerd.', printQuantity: 'Afdrukoplage', pauseCount: 'Pauze elke N labels', + programmablePause: 'Pauzeren na elk etiket', replicates: 'Replicaties per label', overridePauseCount: 'Pauzeteller overschrijven', overridePauseCountHint: 'Snijdt alleen het laatste label van de batch in plaats van bij elke pauzegrens.', @@ -501,6 +502,9 @@ const nl = { mediaTrackingM: 'Markeringsdetectie', mediaTrackingA: 'Automatische detectie', maxLabelLength: 'Maximale labellengte', + slewDotRows: 'Lege regels overslaan', + slewDotRowsHint: 'Slaat een leeg gebied onderaan met hoge snelheid over in plaats van het af te drukken.', + slewToHome: 'Eén leeg etiket doorvoeren na afdrukken', mediaFeedHeading: 'Materiaaldoorvoer', mediaFeedPowerUp: 'Bij inschakelen', mediaFeedHeadClose: 'Na sluiten kop', @@ -515,6 +519,7 @@ const nl = { backfeedSeqB: 'Voor volgend etiket', backfeedSeqA: '100% na afdrukken', backfeedSequence: 'Backfeed-volgorde', + backfeedSeqPctFmt: '{pct}% na afdrukken', }, printQuality: { printOrientation: 'Afdrukrichting', @@ -533,6 +538,13 @@ const nl = { codeValidation: 'Codevalidatie', codeValidationOn: 'Aan', codeValidationOff: 'Uit', + mapClear: 'Etiketafbeelding na afdrukken', + mapClearOptionClear: 'Wissen', + mapClearOptionRetain: 'Behouden', + mapClearHint: 'Behouden houdt dit etiket als achtergrond voor de volgende etiketten (sjabloonafdruk).', + muHeading: 'Dichtheidsconversie', + muFormatDpi: 'Formaatdichtheid', + muOutputDpi: 'Printerdichtheid', }, clockTime: { setRealtimeClock: 'Realtimeklok instellen', @@ -616,6 +628,15 @@ const nl = { uploadToggle: 'Verzenden bij installatie', missingBytes: 'Lettertype ontbreekt. Upload het of verwijder het item.', removeOrphan: 'Verouderd item verwijderen', + fontCache: 'Cache voor schaalbare tekens', + fontCacheEnabled: 'Aan', + fontCacheDisabled: 'Uit', + fontCacheAddKb: 'Extra cachegeheugen', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Verhogen wanneer grote geschaalde tekens langzaam of helemaal niet worden afgedrukt.', + fontCacheType: 'Cachetype', + fontCacheTypeNormal: 'Normale buffer', + fontCacheTypeInternal: 'Intern (Aziatische lettertypen)', }, identity: { printerName: 'Printernaam', @@ -629,6 +650,17 @@ const nl = { configurationUpdateOptionR: 'Laatst opgeslagen ophalen', configurationUpdateOptionN: 'Fabrieksnetwerkinstellingen opnieuw laden (destructief)', configurationUpdateOptionF: 'Fabrieksreset (destructief)', + modeProtection: 'Beveiligde paneelmodi', + modeProtectCustom: 'Aangepaste set', + modeProtectCustomHint: 'Een lege aangepaste set schakelt alle bedieningspaneelmodi van de printer weer in.', + modeProtectDarkness: 'Donkerheidsmodus', + modeProtectPosition: 'Positiemodus', + modeProtectCalibration: 'Kalibratiemodus', + modeProtectSaves: 'Modusopslag', + modeProtectPause: 'Pauze', + modeProtectFeed: 'Doorvoer', + modeProtectCancel: 'Annuleren', + modeProtectMenu: 'Menuwijzigingen', }, maintenance: { maintenanceAlertHeading: 'Onderhoudswaarschuwing', diff --git a/src/locales/no.ts b/src/locales/no.ts index ffc13ace..34a547db 100644 --- a/src/locales/no.ts +++ b/src/locales/no.ts @@ -398,6 +398,7 @@ const no = { emitZJustifyHint: 'Sender ut høyreforankrede 1D-strekkoder med ZPL-justeringsparameteren, slik at skriveren holder høyrekanten fast for serienumre og variable data. Krever fastvare V50.14 eller nyere; eldre skrivere ville plassert disse strekkodene feil.', printQuantity: 'Utskriftsmengde', pauseCount: 'Pause hver N etikett', + programmablePause: 'Pause etter hver etikett', replicates: 'Replikeringer per etikett', overridePauseCount: 'Overstyr pauseteller', overridePauseCountHint: 'Kutt kun siste etikett i partiet i stedet for ved hver pausegrense.', @@ -501,6 +502,9 @@ const no = { mediaTrackingM: 'Markørdeteksjon', mediaTrackingA: 'Automatisk deteksjon', maxLabelLength: 'Maks. etikettlengde', + slewDotRows: 'Hopp over blanke linjer', + slewDotRowsHint: 'Hopper over et blankt bunnområde i høy hastighet i stedet for å skrive det ut.', + slewToHome: 'Mat frem én blank etikett etter utskrift', mediaFeedHeading: 'Mediemating', mediaFeedPowerUp: 'Ved oppstart', mediaFeedHeadClose: 'Etter at hodet er lukket', @@ -515,6 +519,7 @@ const no = { backfeedSeqB: 'Før neste etikett', backfeedSeqA: '100% etter utskrift', backfeedSequence: 'Tilbaketrekkssekvens', + backfeedSeqPctFmt: '{pct}% etter utskrift', }, printQuality: { printOrientation: 'Utskriftsretning', @@ -533,6 +538,13 @@ const no = { codeValidation: 'Kodevalidering', codeValidationOn: 'På', codeValidationOff: 'Av', + mapClear: 'Etikettbilde etter utskrift', + mapClearOptionClear: 'Slett', + mapClearOptionRetain: 'Behold', + mapClearHint: 'Behold beholder denne etiketten som bakgrunn for de påfølgende etikettene (skjemautskrift).', + muHeading: 'Tetthetskonvertering', + muFormatDpi: 'Formattetthet', + muOutputDpi: 'Skrivertetthet', }, clockTime: { setRealtimeClock: 'Still inn sanntidsklokke', @@ -616,6 +628,15 @@ const no = { uploadToggle: 'Send ved oppsett', missingBytes: 'Skrift mangler. Last opp eller fjern oppføringen.', removeOrphan: 'Fjern utdatert oppføring', + fontCache: 'Buffer for skalerbare tegn', + fontCacheEnabled: 'På', + fontCacheDisabled: 'Av', + fontCacheAddKb: 'Ekstra bufferminne', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Øk når store skalerte tegn skrives ut sakte eller ikke i det hele tatt.', + fontCacheType: 'Buffertype', + fontCacheTypeNormal: 'Normal buffer', + fontCacheTypeInternal: 'Intern (asiatiske skrifter)', }, identity: { printerName: 'Skrivernavn', @@ -629,6 +650,17 @@ const no = { configurationUpdateOptionR: 'Hent sist lagrede', configurationUpdateOptionN: 'Last fabrikknettverksinnstillinger (destruktiv)', configurationUpdateOptionF: 'Fabrikknullstilling (destruktiv)', + modeProtection: 'Beskyttede panelmoduser', + modeProtectCustom: 'Tilpasset sett', + modeProtectCustomHint: 'Et tomt tilpasset sett aktiverer alle kontrollpaneltilstander på skriveren på nytt.', + modeProtectDarkness: 'Mørkhetsmodus', + modeProtectPosition: 'Posisjonsmodus', + modeProtectCalibration: 'Kalibreringsmodus', + modeProtectSaves: 'Modus-lagring', + modeProtectPause: 'Pause', + modeProtectFeed: 'Fremtrekk', + modeProtectCancel: 'Avbryt', + modeProtectMenu: 'Menyendringer', }, maintenance: { maintenanceAlertHeading: 'Vedlikeholdsvarsel', diff --git a/src/locales/pl.ts b/src/locales/pl.ts index 7a617c19..3e07c096 100644 --- a/src/locales/pl.ts +++ b/src/locales/pl.ts @@ -398,6 +398,7 @@ const pl = { emitZJustifyHint: 'Generuje kody kreskowe 1D zakotwiczone do prawej krawędzi za pomocą parametru justowania ZPL, dzięki czemu drukarka utrzymuje stałą prawą krawędź dla numerów seryjnych i danych zmiennych. Wymaga oprogramowania sprzętowego V50.14 lub nowszego; starsze drukarki błędnie umieszczałyby te kody kreskowe.', printQuantity: 'Ilość wydruków', pauseCount: 'Pauza co N etykiet', + programmablePause: 'Pauza po każdej etykiecie', replicates: 'Replikacje na etykietę', overridePauseCount: 'Zastąp licznik pauzy', overridePauseCountHint: 'Przytnij tylko ostatnią etykietę partii zamiast przy każdej granicy pauzy.', @@ -501,6 +502,9 @@ const pl = { mediaTrackingM: 'Wykrywanie znacznika', mediaTrackingA: 'Wykrywanie automatyczne', maxLabelLength: 'Maksymalna długość etykiety', + slewDotRows: 'Pomiń puste wiersze', + slewDotRowsHint: 'Pomija pusty obszar u dołu z dużą prędkością zamiast go drukować.', + slewToHome: 'Podaj jedną pustą etykietę po wydruku', mediaFeedHeading: 'Podawanie nośnika', mediaFeedPowerUp: 'Przy włączeniu', mediaFeedHeadClose: 'Po zamknięciu głowicy', @@ -515,6 +519,7 @@ const pl = { backfeedSeqB: 'Przed następną etykietą', backfeedSeqA: '100% po wydruku', backfeedSequence: 'Sekwencja cofania', + backfeedSeqPctFmt: '{pct}% po wydruku', }, printQuality: { printOrientation: 'Orientacja druku', @@ -533,6 +538,13 @@ const pl = { codeValidation: 'Walidacja kodu', codeValidationOn: 'Wł.', codeValidationOff: 'Wył.', + mapClear: 'Obraz etykiety po wydruku', + mapClearOptionClear: 'Czyszczenie', + mapClearOptionRetain: 'Zachowaj', + mapClearHint: 'Zachowaj pozostawia tę etykietę jako tło kolejnych etykiet (druk na formularzu).', + muHeading: 'Konwersja gęstości', + muFormatDpi: 'Gęstość formatu', + muOutputDpi: 'Gęstość drukarki', }, clockTime: { setRealtimeClock: 'Ustaw zegar czasu rzeczywistego', @@ -616,6 +628,15 @@ const pl = { uploadToggle: 'Wyślij przy konfiguracji', missingBytes: 'Brak czcionki. Prześlij ją lub usuń wpis.', removeOrphan: 'Usuń nieaktualny wpis', + fontCache: 'Pamięć podręczna skalowalnych znaków', + fontCacheEnabled: 'Wł.', + fontCacheDisabled: 'Wył.', + fontCacheAddKb: 'Dodatkowa pamięć podręczna', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Zwiększ, gdy duże skalowane znaki drukują się wolno lub w ogóle się nie drukują.', + fontCacheType: 'Typ pamięci podręcznej', + fontCacheTypeNormal: 'Normalny bufor', + fontCacheTypeInternal: 'Wewnętrzny (czcionki azjatyckie)', }, identity: { printerName: 'Nazwa drukarki', @@ -629,6 +650,17 @@ const pl = { configurationUpdateOptionR: 'Przywróć ostatnio zapisaną', configurationUpdateOptionN: 'Wczytaj fabryczne ustawienia sieci (destrukcyjny)', configurationUpdateOptionF: 'Reset fabryczny (destrukcyjny)', + modeProtection: 'Chronione tryby panelu', + modeProtectCustom: 'Zestaw niestandardowy', + modeProtectCustomHint: 'Pusty zestaw niestandardowy ponownie włącza wszystkie tryby panelu sterowania drukarki.', + modeProtectDarkness: 'Tryb gęstości druku', + modeProtectPosition: 'Tryb pozycji', + modeProtectCalibration: 'Tryb kalibracji', + modeProtectSaves: 'Zapis trybu', + modeProtectPause: 'Pauza', + modeProtectFeed: 'Podawanie', + modeProtectCancel: 'Anuluj', + modeProtectMenu: 'Zmiany w menu', }, maintenance: { maintenanceAlertHeading: 'Alert konserwacji', diff --git a/src/locales/pt.ts b/src/locales/pt.ts index fb6a3527..9f3576c3 100644 --- a/src/locales/pt.ts +++ b/src/locales/pt.ts @@ -398,6 +398,7 @@ const pt = { emitZJustifyHint: 'Emite códigos de barras 1D ancorados à direita com o parâmetro de justificação ZPL para que a impressora mantenha a borda direita fixa para números de série e dados variáveis. Requer firmware V50.14 ou mais recente; impressoras mais antigas posicionariam mal esses códigos de barras.', printQuantity: 'Quantidade de impressão', pauseCount: 'Pausa a cada N etiquetas', + programmablePause: 'Pausar após cada etiqueta', replicates: 'Réplicas por etiqueta', overridePauseCount: 'Substituir contagem de pausa', overridePauseCountHint: 'Cortar apenas a última etiqueta do lote em vez de cada limite de pausa.', @@ -501,6 +502,9 @@ const pt = { mediaTrackingM: 'Detecção por marca', mediaTrackingA: 'Detecção automática', maxLabelLength: 'Comprimento máximo da etiqueta', + slewDotRows: 'Ignorar linhas em branco', + slewDotRowsHint: 'Ignora uma área inferior em branco em alta velocidade em vez de a imprimir.', + slewToHome: 'Avançar uma etiqueta em branco após a impressão', mediaFeedHeading: 'Avanço da mídia', mediaFeedPowerUp: 'Ao ligar', mediaFeedHeadClose: 'Após fechar o cabeçote', @@ -515,6 +519,7 @@ const pt = { backfeedSeqB: 'Antes da próxima etiqueta', backfeedSeqA: '100% após impressão', backfeedSequence: 'Sequência de retrocesso', + backfeedSeqPctFmt: '{pct}% após impressão', }, printQuality: { printOrientation: 'Orientação de impressão', @@ -533,6 +538,13 @@ const pt = { codeValidation: 'Validação do código', codeValidationOn: 'Ativado', codeValidationOff: 'Desativado', + mapClear: 'Imagem da etiqueta após a impressão', + mapClearOptionClear: 'Limpar', + mapClearOptionRetain: 'Manter', + mapClearHint: 'Manter conserva esta etiqueta como fundo das etiquetas seguintes (impressão sobre formulário).', + muHeading: 'Reamostragem de densidade', + muFormatDpi: 'Densidade do formato', + muOutputDpi: 'Densidade da impressora', }, clockTime: { setRealtimeClock: 'Definir relógio em tempo real', @@ -616,6 +628,15 @@ const pt = { uploadToggle: 'Enviar na configuração', missingBytes: 'Fonte ausente. Envie-a ou remova a entrada.', removeOrphan: 'Remover entrada obsoleta', + fontCache: 'Cache de caracteres escaláveis', + fontCacheEnabled: 'Ativado', + fontCacheDisabled: 'Desativado', + fontCacheAddKb: 'Memória de cache adicional', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Aumente quando caracteres ampliados grandes forem impressos lentamente ou não forem impressos.', + fontCacheType: 'Tipo de cache', + fontCacheTypeNormal: 'Buffer normal', + fontCacheTypeInternal: 'Interno (fontes asiáticas)', }, identity: { printerName: 'Nome da impressora', @@ -629,6 +650,17 @@ const pt = { configurationUpdateOptionR: 'Recuperar último salvo', configurationUpdateOptionN: 'Recarregar configurações de rede de fábrica (destrutivo)', configurationUpdateOptionF: 'Restaurar fábrica (destrutivo)', + modeProtection: 'Modos de painel protegidos', + modeProtectCustom: 'Conjunto personalizado', + modeProtectCustomHint: 'Um conjunto personalizado vazio reativa todos os modos do painel de controlo da impressora.', + modeProtectDarkness: 'Modo de densidade', + modeProtectPosition: 'Modo de posição', + modeProtectCalibration: 'Modo de calibração', + modeProtectSaves: 'Gravações de modo', + modeProtectPause: 'Pausa', + modeProtectFeed: 'Avanço', + modeProtectCancel: 'Cancelar', + modeProtectMenu: 'Alterações de menu', }, maintenance: { maintenanceAlertHeading: 'Alerta de manutenção', diff --git a/src/locales/ro.ts b/src/locales/ro.ts index 1911b085..8b37d58d 100644 --- a/src/locales/ro.ts +++ b/src/locales/ro.ts @@ -398,6 +398,7 @@ const ro = { emitZJustifyHint: 'Emite coduri de bare 1D ancorate la dreapta cu parametrul de aliniere ZPL, astfel încât imprimanta să mențină marginea dreaptă fixă pentru numere de serie și date variabile. Necesită firmware V50.14 sau mai nou; imprimantele mai vechi ar poziționa greșit aceste coduri de bare.', printQuantity: 'Cantitate imprimare', pauseCount: 'Pauză la fiecare N etichete', + programmablePause: 'Pauză după fiecare etichetă', replicates: 'Replicări pe etichetă', overridePauseCount: 'Suprascrie nr. pauze', overridePauseCountHint: 'Taie doar ultima etichetă din lot în loc de fiecare limită de pauză.', @@ -501,6 +502,9 @@ const ro = { mediaTrackingM: 'Detectare marcaj', mediaTrackingA: 'Detectare automată', maxLabelLength: 'Lungime maximă a etichetei', + slewDotRows: 'Omite rândurile goale', + slewDotRowsHint: 'Omite o zonă goală din partea de jos la viteză mare, în loc să o tipărească.', + slewToHome: 'Alimentează o etichetă goală după tipărire', mediaFeedHeading: 'Alimentare suport', mediaFeedPowerUp: 'La pornire', mediaFeedHeadClose: 'După închiderea capului', @@ -515,6 +519,7 @@ const ro = { backfeedSeqB: 'Înainte de următoarea etichetă', backfeedSeqA: '100% după imprimare', backfeedSequence: 'Secvență de retragere', + backfeedSeqPctFmt: '{pct}% după imprimare', }, printQuality: { printOrientation: 'Orientarea tipăririi', @@ -533,6 +538,13 @@ const ro = { codeValidation: 'Validare cod', codeValidationOn: 'Activat', codeValidationOff: 'Dezactivat', + mapClear: 'Imaginea etichetei după tipărire', + mapClearOptionClear: 'Ștergere', + mapClearOptionRetain: 'Păstrează', + mapClearHint: 'Păstrează menține această etichetă ca fundal pentru etichetele următoare (tipărire pe formular).', + muHeading: 'Reconversie densitate', + muFormatDpi: 'Densitatea formatului', + muOutputDpi: 'Densitatea imprimantei', }, clockTime: { setRealtimeClock: 'Setează ceasul în timp real', @@ -616,6 +628,15 @@ const ro = { uploadToggle: 'Trimite la configurare', missingBytes: 'Font lipsă. Încarcă-l sau elimină intrarea.', removeOrphan: 'Elimină intrarea învechită', + fontCache: 'Cache de caractere scalabile', + fontCacheEnabled: 'Activat', + fontCacheDisabled: 'Dezactivat', + fontCacheAddKb: 'Memorie cache suplimentară', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Măriți atunci când caracterele mari scalate se tipăresc lent sau deloc.', + fontCacheType: 'Tip de cache', + fontCacheTypeNormal: 'Buffer normal', + fontCacheTypeInternal: 'Intern (fonturi asiatice)', }, identity: { printerName: 'Numele imprimantei', @@ -629,6 +650,17 @@ const ro = { configurationUpdateOptionR: 'Reapelare ultimă salvare', configurationUpdateOptionN: 'Reîncărcare setări de rețea din fabrică (distructiv)', configurationUpdateOptionF: 'Resetare din fabrică (distructiv)', + modeProtection: 'Moduri de panou protejate', + modeProtectCustom: 'Set personalizat', + modeProtectCustomHint: 'Un set personalizat gol reactivează toate modurile panoului de control al imprimantei.', + modeProtectDarkness: 'Mod densitate', + modeProtectPosition: 'Mod poziție', + modeProtectCalibration: 'Mod calibrare', + modeProtectSaves: 'Salvări de mod', + modeProtectPause: 'Pauză', + modeProtectFeed: 'Alimentare', + modeProtectCancel: 'Anulare', + modeProtectMenu: 'Modificări de meniu', }, maintenance: { maintenanceAlertHeading: 'Alertă de întreținere', diff --git a/src/locales/sk.ts b/src/locales/sk.ts index 7e7f7043..3730306f 100644 --- a/src/locales/sk.ts +++ b/src/locales/sk.ts @@ -398,6 +398,7 @@ const sk = { emitZJustifyHint: 'Odošle vpravo ukotvené 1D čiarové kódy s parametrom zarovnania ZPL, aby tlačiareň udržala pravý okraj pevný pre sériové čísla a premenlivé údaje. Vyžaduje firmvér V50.14 alebo novší; staršie tlačiarne by tieto čiarové kódy umiestnili nesprávne.', printQuantity: 'Počet výtlačkov', pauseCount: 'Pauza každých N štítkov', + programmablePause: 'Pauza po každej etikete', replicates: 'Replikácie na štítok', overridePauseCount: 'Prepísať počet páuz', overridePauseCountHint: 'Rezať iba posledný štítok dávky namiesto pri každej hranici pauzy.', @@ -501,6 +502,9 @@ const sk = { mediaTrackingM: 'Detekcia značky', mediaTrackingA: 'Automatická detekcia', maxLabelLength: 'Maximálna dĺžka etikety', + slewDotRows: 'Preskočiť prázdne riadky', + slewDotRowsHint: 'Vysokou rýchlosťou preskočí prázdnu oblasť naspodku namiesto jej tlače.', + slewToHome: 'Po tlači podať jednu prázdnu etiketu', mediaFeedHeading: 'Posuv média', mediaFeedPowerUp: 'Pri zapnutí', mediaFeedHeadClose: 'Po zatvorení hlavy', @@ -515,6 +519,7 @@ const sk = { backfeedSeqB: 'Pred ďalším štítkom', backfeedSeqA: '100% po tlači', backfeedSequence: 'Sekvencia spätného posuvu', + backfeedSeqPctFmt: '{pct}% po tlači', }, printQuality: { printOrientation: 'Orientácia tlače', @@ -533,6 +538,13 @@ const sk = { codeValidation: 'Validácia kódu', codeValidationOn: 'Zapnuté', codeValidationOff: 'Vypnuté', + mapClear: 'Obraz etikety po tlači', + mapClearOptionClear: 'Vymazať', + mapClearOptionRetain: 'Zachovať', + mapClearHint: 'Zachovať ponechá túto etiketu ako pozadie nasledujúcich etikiet (tlač na formulár).', + muHeading: 'Prepočet hustoty', + muFormatDpi: 'Hustota formátu', + muOutputDpi: 'Hustota tlačiarne', }, clockTime: { setRealtimeClock: 'Nastaviť hodiny reálneho času', @@ -616,6 +628,15 @@ const sk = { uploadToggle: 'Odoslať pri nastavení', missingBytes: 'Písmo chýba. Nahrajte ho alebo odstráňte záznam.', removeOrphan: 'Odstrániť zastaraný záznam', + fontCache: 'Vyrovnávacia pamäť škálovateľných znakov', + fontCacheEnabled: 'Zapnuté', + fontCacheDisabled: 'Vypnuté', + fontCacheAddKb: 'Dodatočná vyrovnávacia pamäť', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Zvýšte, keď sa veľké škálované znaky tlačia pomaly alebo vôbec.', + fontCacheType: 'Typ vyrovnávacej pamäte', + fontCacheTypeNormal: 'Normálny buffer', + fontCacheTypeInternal: 'Interný (ázijské písma)', }, identity: { printerName: 'Názov tlačiarne', @@ -629,6 +650,17 @@ const sk = { configurationUpdateOptionR: 'Obnoviť posledne uloženú', configurationUpdateOptionN: 'Načítať továrenské sieťové nastavenia (deštruktívne)', configurationUpdateOptionF: 'Továrenský reset (deštruktívny)', + modeProtection: 'Chránené režimy panela', + modeProtectCustom: 'Vlastná sada', + modeProtectCustomHint: 'Prázdna vlastná sada opäť povolí všetky režimy ovládacieho panela tlačiarne.', + modeProtectDarkness: 'Režim sýtosti tlače', + modeProtectPosition: 'Režim polohy', + modeProtectCalibration: 'Režim kalibrácie', + modeProtectSaves: 'Ukladanie režimu', + modeProtectPause: 'Pauza', + modeProtectFeed: 'Posuv', + modeProtectCancel: 'Zrušiť', + modeProtectMenu: 'Zmeny ponuky', }, maintenance: { maintenanceAlertHeading: 'Upozornenie na údržbu', diff --git a/src/locales/sl.ts b/src/locales/sl.ts index d13ac257..78df3e92 100644 --- a/src/locales/sl.ts +++ b/src/locales/sl.ts @@ -398,6 +398,7 @@ const sl = { emitZJustifyHint: 'Odda desno usidrane 1D črtne kode s parametrom poravnave ZPL, tako da tiskalnik ohranja desni rob nespremenjen za serijske številke in spremenljive podatke. Zahteva strojno programsko opremo V50.14 ali novejšo; starejši tiskalniki bi te črtne kode postavili napačno.', printQuantity: 'Količina tiskanja', pauseCount: 'Premor vsakih N etiket', + programmablePause: 'Premor po vsaki etiketi', replicates: 'Replike na etiketo', overridePauseCount: 'Razveljavi števec premorov', overridePauseCountHint: 'Reže le zadnjo etiketo serije namesto pri vsaki meji premora.', @@ -501,6 +502,9 @@ const sl = { mediaTrackingM: 'Zaznavanje oznake', mediaTrackingA: 'Samodejno zaznavanje', maxLabelLength: 'Največja dolžina etikete', + slewDotRows: 'Preskoči prazne vrstice', + slewDotRowsHint: 'Prazno spodnje območje preskoči z veliko hitrostjo, namesto da bi ga natisnil.', + slewToHome: 'Podaj eno prazno etiketo po tiskanju', mediaFeedHeading: 'Podajanje medija', mediaFeedPowerUp: 'Ob vklopu', mediaFeedHeadClose: 'Po zaprtju glave', @@ -515,6 +519,7 @@ const sl = { backfeedSeqB: 'Pred naslednjo etiketo', backfeedSeqA: '100% po tisku', backfeedSequence: 'Zaporedje povratnega podajanja', + backfeedSeqPctFmt: '{pct}% po tisku', }, printQuality: { printOrientation: 'Usmerjenost tiskanja', @@ -533,6 +538,13 @@ const sl = { codeValidation: 'Preverjanje kode', codeValidationOn: 'Vklopljeno', codeValidationOff: 'Izklopljeno', + mapClear: 'Slika etikete po tiskanju', + mapClearOptionClear: 'Počisti', + mapClearOptionRetain: 'Ohrani', + mapClearHint: 'Ohrani obdrži to etiketo kot ozadje naslednjih etiket (tiskanje na obrazec).', + muHeading: 'Pretvorba gostote', + muFormatDpi: 'Gostota formata', + muOutputDpi: 'Gostota tiskalnika', }, clockTime: { setRealtimeClock: 'Nastavi uro v realnem času', @@ -616,6 +628,15 @@ const sl = { uploadToggle: 'Pošlji pri namestitvi', missingBytes: 'Pisava manjka. Naložite jo ali odstranite vnos.', removeOrphan: 'Odstrani zastarel vnos', + fontCache: 'Predpomnilnik prilagodljivih znakov', + fontCacheEnabled: 'Vklopljeno', + fontCacheDisabled: 'Izklopljeno', + fontCacheAddKb: 'Dodaten pomnilnik predpomnilnika', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Povečajte, kadar se veliki povečani znaki tiskajo počasi ali sploh ne.', + fontCacheType: 'Vrsta predpomnilnika', + fontCacheTypeNormal: 'Običajni medpomnilnik', + fontCacheTypeInternal: 'Notranji (azijske pisave)', }, identity: { printerName: 'Ime tiskalnika', @@ -629,6 +650,17 @@ const sl = { configurationUpdateOptionR: 'Prikliči nazadnje shranjeno', configurationUpdateOptionN: 'Ponovno naloži tovarniške omrežne nastavitve (destruktivno)', configurationUpdateOptionF: 'Tovarniška ponastavitev (destruktivno)', + modeProtection: 'Zaščiteni načini plošče', + modeProtectCustom: 'Sklop po meri', + modeProtectCustomHint: 'Prazen sklop po meri znova omogoči vse načine nadzorne plošče tiskalnika.', + modeProtectDarkness: 'Način temnosti', + modeProtectPosition: 'Način položaja', + modeProtectCalibration: 'Način umerjanja', + modeProtectSaves: 'Shranjevanje načina', + modeProtectPause: 'Premor', + modeProtectFeed: 'Podajanje', + modeProtectCancel: 'Prekliči', + modeProtectMenu: 'Spremembe menija', }, maintenance: { maintenanceAlertHeading: 'Opozorilo o vzdrževanju', diff --git a/src/locales/sr.ts b/src/locales/sr.ts index 4bd4d473..3599e3ef 100644 --- a/src/locales/sr.ts +++ b/src/locales/sr.ts @@ -398,6 +398,7 @@ const sr = { emitZJustifyHint: 'Emituje 1D bar kodove usidrene s desne strane pomoću ZPL parametra za poravnanje, tako da štampač zadržava desnu ivicu fiksnom za serijske brojeve i promenljive podatke. Zahteva firmver V50.14 ili noviji; stariji štampači bi ove bar kodove pogrešno pozicionirali.', printQuantity: 'Количина штампе', pauseCount: 'Пауза сваких N етикета', + programmablePause: 'Pauza posle svake etikete', replicates: 'Реплике по етикети', overridePauseCount: 'Премости бројач паузе', overridePauseCountHint: 'Сече само последњу етикету серије уместо на свакој граници паузе.', @@ -501,6 +502,9 @@ const sr = { mediaTrackingM: 'Детекција ознаке', mediaTrackingA: 'Аутоматска детекција', maxLabelLength: 'Maksimalna dužina etikete', + slewDotRows: 'Preskoči prazne redove', + slewDotRowsHint: 'Preskače prazno donje područje velikom brzinom umesto da ga štampa.', + slewToHome: 'Pomeri jednu praznu etiketu nakon štampanja', mediaFeedHeading: 'Увлачење медијума', mediaFeedPowerUp: 'При укључивању', mediaFeedHeadClose: 'Након затварања главе', @@ -515,6 +519,7 @@ const sr = { backfeedSeqB: 'Пре следеће налепнице', backfeedSeqA: '100% након штампе', backfeedSequence: 'Редослед повратног увлачења', + backfeedSeqPctFmt: '{pct}% након штампе', }, printQuality: { printOrientation: 'Orijentacija štampe', @@ -533,6 +538,13 @@ const sr = { codeValidation: 'Validacija koda', codeValidationOn: 'Uključeno', codeValidationOff: 'Isključeno', + mapClear: 'Slika etikete nakon štampanja', + mapClearOptionClear: 'Brisanje', + mapClearOptionRetain: 'Zadrži', + mapClearHint: 'Zadrži zadržava ovu etiketu kao pozadinu sledećih etiketa (štampanje na obrascu).', + muHeading: 'Конверзија густине', + muFormatDpi: 'Густина формата', + muOutputDpi: 'Густина штампача', }, clockTime: { setRealtimeClock: 'Подеси сат у реалном времену', @@ -616,6 +628,15 @@ const sr = { uploadToggle: 'Пошаљи при подешавању', missingBytes: 'Фонт недостаје. Отпремите га или уклоните унос.', removeOrphan: 'Уклони застарели унос', + fontCache: 'Keš skalabilnih znakova', + fontCacheEnabled: 'Uključeno', + fontCacheDisabled: 'Isključeno', + fontCacheAddKb: 'Dodatna memorija keša', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Povećajte kada se veliki skalirani znakovi štampaju sporo ili se uopšte ne štampaju.', + fontCacheType: 'Vrsta keša', + fontCacheTypeNormal: 'Normalni bafer', + fontCacheTypeInternal: 'Interni (azijski fontovi)', }, identity: { printerName: 'Назив штампача', @@ -629,6 +650,17 @@ const sr = { configurationUpdateOptionR: 'Vrati poslednju sačuvanu', configurationUpdateOptionN: 'Učitaj fabričke mrežne postavke (destruktivno)', configurationUpdateOptionF: 'Fabričko resetovanje (destruktivno)', + modeProtection: 'Zaštićeni režimi panela', + modeProtectCustom: 'Прилагођени скуп', + modeProtectCustomHint: 'Празан прилагођени скуп поново активира све режиме контролне табле штампача.', + modeProtectDarkness: 'Režim zatamnjenja', + modeProtectPosition: 'Režim položaja', + modeProtectCalibration: 'Režim kalibracije', + modeProtectSaves: 'Čuvanje režima', + modeProtectPause: 'Pauza', + modeProtectFeed: 'Pomeranje', + modeProtectCancel: 'Otkaži', + modeProtectMenu: 'Izmene menija', }, maintenance: { maintenanceAlertHeading: 'Upozorenje o održavanju', diff --git a/src/locales/sv.ts b/src/locales/sv.ts index caef377a..e2a2f4fd 100644 --- a/src/locales/sv.ts +++ b/src/locales/sv.ts @@ -398,6 +398,7 @@ const sv = { emitZJustifyHint: 'Skickar högerförankrade 1D-streckkoder med ZPL:s justeringsparameter så att skrivaren håller högerkanten fast för serienummer och variabel data. Kräver firmware V50.14 eller nyare; äldre skrivare skulle placera dessa streckkoder fel.', printQuantity: 'Utskriftsmängd', pauseCount: 'Paus var N:e etikett', + programmablePause: 'Pausa efter varje etikett', replicates: 'Repliker per etikett', overridePauseCount: 'Åsidosätt pausräknare', overridePauseCountHint: 'Klipp endast den sista etiketten i partiet istället för vid varje pausgräns.', @@ -501,6 +502,9 @@ const sv = { mediaTrackingM: 'Markörsdetektering', mediaTrackingA: 'Automatisk detektering', maxLabelLength: 'Maximal etikettlängd', + slewDotRows: 'Hoppa över tomma rader', + slewDotRowsHint: 'Hoppar över ett tomt område längst ned med hög hastighet i stället för att skriva ut det.', + slewToHome: 'Mata fram en tom etikett efter utskrift', mediaFeedHeading: 'Materialmatning', mediaFeedPowerUp: 'Vid start', mediaFeedHeadClose: 'Efter att huvudet stängts', @@ -515,6 +519,7 @@ const sv = { backfeedSeqB: 'Före nästa etikett', backfeedSeqA: '100% efter utskrift', backfeedSequence: 'Bakmatningssekvens', + backfeedSeqPctFmt: '{pct}% efter utskrift', }, printQuality: { printOrientation: 'Utskriftsriktning', @@ -533,6 +538,13 @@ const sv = { codeValidation: 'Kodvalidering', codeValidationOn: 'På', codeValidationOff: 'Av', + mapClear: 'Etikettbild efter utskrift', + mapClearOptionClear: 'Rensa', + mapClearOptionRetain: 'Behåll', + mapClearHint: 'Behåll gör att den här etiketten finns kvar som bakgrund för efterföljande etiketter (formulärutskrift).', + muHeading: 'Densitetskonvertering', + muFormatDpi: 'Formattäthet', + muOutputDpi: 'Skrivartäthet', }, clockTime: { setRealtimeClock: 'Ställ in realtidsklocka', @@ -616,6 +628,15 @@ const sv = { uploadToggle: 'Skicka vid installation', missingBytes: 'Teckensnitt saknas. Ladda upp eller ta bort posten.', removeOrphan: 'Ta bort föråldrad post', + fontCache: 'Cache för skalbara tecken', + fontCacheEnabled: 'På', + fontCacheDisabled: 'Av', + fontCacheAddKb: 'Ytterligare cacheminne', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Öka när stora skalade tecken skrivs ut långsamt eller inte alls.', + fontCacheType: 'Cachetyp', + fontCacheTypeNormal: 'Normal buffert', + fontCacheTypeInternal: 'Intern (asiatiska teckensnitt)', }, identity: { printerName: 'Skrivarnamn', @@ -629,6 +650,17 @@ const sv = { configurationUpdateOptionR: 'Återställ senast sparade', configurationUpdateOptionN: 'Läs in fabriksnätverksinställningar (destruktiv)', configurationUpdateOptionF: 'Återställ till fabrik (destruktiv)', + modeProtection: 'Skyddade panellägen', + modeProtectCustom: 'Anpassad uppsättning', + modeProtectCustomHint: 'En tom anpassad uppsättning återaktiverar alla kontrollpanelslägen på skrivaren.', + modeProtectDarkness: 'Mörkhetsläge', + modeProtectPosition: 'Positionsläge', + modeProtectCalibration: 'Kalibreringsläge', + modeProtectSaves: 'Lägessparning', + modeProtectPause: 'Paus', + modeProtectFeed: 'Frammatning', + modeProtectCancel: 'Avbryt', + modeProtectMenu: 'Menyändringar', }, maintenance: { maintenanceAlertHeading: 'Underhållsvarning', diff --git a/src/locales/tr.ts b/src/locales/tr.ts index a1de91fa..bcaea6a7 100644 --- a/src/locales/tr.ts +++ b/src/locales/tr.ts @@ -398,6 +398,7 @@ const tr = { emitZJustifyHint: 'Yazıcının seri numaraları ve değişken veriler için sağ kenarı sabit tutması amacıyla ZPL hizalama parametresiyle sağa sabitlenmiş 1D barkodlar üretir. V50.14 veya daha yeni bir aygıt yazılımı gerektirir; eski yazıcılar bu barkodları yanlış konumlandırır.', printQuantity: 'Baskı miktarı', pauseCount: 'Her N etikette duraklat', + programmablePause: 'Her etiketten sonra duraklat', replicates: 'Etiket başına kopya', overridePauseCount: 'Duraklatma sayısını geçersiz kıl', overridePauseCountHint: 'Her duraklatma sınırında değil, partinin yalnızca son etiketini kes.', @@ -501,6 +502,9 @@ const tr = { mediaTrackingM: 'İşaret algılama', mediaTrackingA: 'Otomatik algılama', maxLabelLength: 'Maksimum etiket uzunluğu', + slewDotRows: 'Boş satırları atla', + slewDotRowsHint: 'Alt kısımdaki boş alanı yazdırmak yerine yüksek hızda atlar.', + slewToHome: 'Yazdırmadan sonra bir boş etiket besle', mediaFeedHeading: 'Ortam beslemesi', mediaFeedPowerUp: 'Açılışta', mediaFeedHeadClose: 'Kafa kapandıktan sonra', @@ -515,6 +519,7 @@ const tr = { backfeedSeqB: 'Sonraki etiketten önce', backfeedSeqA: 'Baskıdan sonra %100', backfeedSequence: 'Geri besleme sırası', + backfeedSeqPctFmt: 'Baskıdan sonra %{pct}', }, printQuality: { printOrientation: 'Yazdırma yönü', @@ -533,6 +538,13 @@ const tr = { codeValidation: 'Kod doğrulama', codeValidationOn: 'Açık', codeValidationOff: 'Kapalı', + mapClear: 'Yazdırmadan sonra etiket görüntüsü', + mapClearOptionClear: 'Temizle', + mapClearOptionRetain: 'Koru', + mapClearHint: 'Koru, bu etiketi sonraki etiketlerin arka planı olarak tutar (form baskısı).', + muHeading: 'Yoğunluk dönüştürme', + muFormatDpi: 'Format yoğunluğu', + muOutputDpi: 'Yazıcı yoğunluğu', }, clockTime: { setRealtimeClock: 'Gerçek zamanlı saati ayarla', @@ -616,6 +628,15 @@ const tr = { uploadToggle: 'Kurulumda gönder', missingBytes: 'Yazı tipi eksik. Yükleyin veya kaydı kaldırın.', removeOrphan: 'Eski kaydı kaldır', + fontCache: 'Ölçeklenebilir karakter önbelleği', + fontCacheEnabled: 'Açık', + fontCacheDisabled: 'Kapalı', + fontCacheAddKb: 'Ek önbellek belleği', + fontCacheKbUnit: 'KB', + fontCacheHint: 'Büyük ölçeklendirilmiş karakterler yavaş yazdırılıyorsa veya hiç yazdırılmıyorsa artırın.', + fontCacheType: 'Önbellek türü', + fontCacheTypeNormal: 'Normal arabellek', + fontCacheTypeInternal: 'Dahili (Asya yazı tipleri)', }, identity: { printerName: 'Yazıcı adı', @@ -629,6 +650,17 @@ const tr = { configurationUpdateOptionR: 'Son kaydedileni geri çağır', configurationUpdateOptionN: 'Fabrika ağ ayarlarını yeniden yükle (yıkıcı)', configurationUpdateOptionF: 'Fabrika ayarlarına sıfırla (yıkıcı)', + modeProtection: 'Korumalı panel modları', + modeProtectCustom: 'Özel küme', + modeProtectCustomHint: 'Boş bir özel küme, yazıcıdaki tüm kontrol paneli modlarını yeniden etkinleştirir.', + modeProtectDarkness: 'Koyuluk modu', + modeProtectPosition: 'Konum modu', + modeProtectCalibration: 'Kalibrasyon modu', + modeProtectSaves: 'Mod kaydetme', + modeProtectPause: 'Duraklat', + modeProtectFeed: 'Besleme', + modeProtectCancel: 'İptal', + modeProtectMenu: 'Menü değişiklikleri', }, maintenance: { maintenanceAlertHeading: 'Bakım uyarısı', diff --git a/src/locales/zh-hans.ts b/src/locales/zh-hans.ts index 4d91e81f..49a87793 100644 --- a/src/locales/zh-hans.ts +++ b/src/locales/zh-hans.ts @@ -398,6 +398,7 @@ const zhHans = { emitZJustifyHint: '使用 ZPL 对齐参数发出右对齐的一维条码,使打印机在打印序列号和可变数据时保持右边缘固定。需要 V50.14 或更新的固件;较旧的打印机会错误定位这些条码。', printQuantity: '打印数量', pauseCount: '每 N 个标签暂停', + programmablePause: '每张标签后暂停', replicates: '每个标签的副本数', overridePauseCount: '覆盖暂停计数', overridePauseCountHint: '仅切批次最后一个标签,而不是每个暂停边界。', @@ -501,6 +502,9 @@ const zhHans = { mediaTrackingM: '标记检测', mediaTrackingA: '自动检测', maxLabelLength: '标签最大长度', + slewDotRows: '跳过空白行', + slewDotRowsHint: '以高速跳过底部空白区域,而不是打印它。', + slewToHome: '打印后送出一张空白标签', mediaFeedHeading: '介质走纸', mediaFeedPowerUp: '开机时', mediaFeedHeadClose: '打印头关闭后', @@ -515,6 +519,7 @@ const zhHans = { backfeedSeqB: '在下一张标签前', backfeedSeqA: '打印后100%', backfeedSequence: '回拉顺序', + backfeedSeqPctFmt: '打印后{pct}%', }, printQuality: { printOrientation: '打印方向', @@ -533,6 +538,13 @@ const zhHans = { codeValidation: '编码验证', codeValidationOn: '开', codeValidationOff: '关', + mapClear: '打印后标签图像', + mapClearOptionClear: '清除', + mapClearOptionRetain: '保留', + mapClearHint: '“保留”会将此标签作为后续标签的背景保留下来(表单打印)。', + muHeading: '密度重采样', + muFormatDpi: '格式密度', + muOutputDpi: '打印机密度', }, clockTime: { setRealtimeClock: '设置实时时钟', @@ -616,6 +628,15 @@ const zhHans = { uploadToggle: '设置时发送', missingBytes: '缺少字体。请上传或删除该条目。', removeOrphan: '移除过时条目', + fontCache: '可缩放字符缓存', + fontCacheEnabled: '开', + fontCacheDisabled: '关', + fontCacheAddKb: '附加缓存内存', + fontCacheKbUnit: 'KB', + fontCacheHint: '当大号缩放字符打印缓慢或无法打印时增大此值。', + fontCacheType: '缓存类型', + fontCacheTypeNormal: '常规缓冲区', + fontCacheTypeInternal: '内部(亚洲字体)', }, identity: { printerName: '打印机名称', @@ -629,6 +650,17 @@ const zhHans = { configurationUpdateOptionR: '调用上次保存', configurationUpdateOptionN: '重新载入出厂网络设置 (破坏性)', configurationUpdateOptionF: '恢复出厂设置 (破坏性)', + modeProtection: '受保护的面板模式', + modeProtectCustom: '自定义组合', + modeProtectCustomHint: '空的自定义组合会重新启用打印机上的所有控制面板模式。', + modeProtectDarkness: '浓度模式', + modeProtectPosition: '位置模式', + modeProtectCalibration: '校准模式', + modeProtectSaves: '模式保存', + modeProtectPause: '暂停', + modeProtectFeed: '走纸', + modeProtectCancel: '取消', + modeProtectMenu: '菜单更改', }, maintenance: { maintenanceAlertHeading: '维护警报', diff --git a/src/locales/zh-hant.ts b/src/locales/zh-hant.ts index 408eaa3d..9e943896 100644 --- a/src/locales/zh-hant.ts +++ b/src/locales/zh-hant.ts @@ -398,6 +398,7 @@ const zhHant = { emitZJustifyHint: '使用 ZPL 對齊參數發出右對齊的一維條碼,讓印表機在列印序號和可變資料時保持右邊緣固定。需要 V50.14 或更新的韌體;較舊的印表機會錯誤定位這些條碼。', printQuantity: '列印數量', pauseCount: '每 N 個標籤暫停', + programmablePause: '每張標籤後暫停', replicates: '每個標籤的副本數', overridePauseCount: '覆寫暫停計數', overridePauseCountHint: '僅切批次最後一個標籤,而不是每個暫停邊界。', @@ -501,6 +502,9 @@ const zhHant = { mediaTrackingM: '標記偵測', mediaTrackingA: '自動偵測', maxLabelLength: '標籤最大長度', + slewDotRows: '跳過空白列', + slewDotRowsHint: '以高速跳過底部空白區域,而不列印它。', + slewToHome: '列印後送出一張空白標籤', mediaFeedHeading: '介質送紙', mediaFeedPowerUp: '開機時', mediaFeedHeadClose: '印頭關閉後', @@ -515,6 +519,7 @@ const zhHant = { backfeedSeqB: '在下一張標籤前', backfeedSeqA: '列印後100%', backfeedSequence: '回拉順序', + backfeedSeqPctFmt: '列印後{pct}%', }, printQuality: { printOrientation: '列印方向', @@ -533,6 +538,13 @@ const zhHant = { codeValidation: '編碼驗證', codeValidationOn: '開', codeValidationOff: '關', + mapClear: '列印後標籤影像', + mapClearOptionClear: '清除', + mapClearOptionRetain: '保留', + mapClearHint: '「保留」會將此標籤作為後續標籤的背景保留下來(表單列印)。', + muHeading: '密度重新取樣', + muFormatDpi: '格式密度', + muOutputDpi: '印表機密度', }, clockTime: { setRealtimeClock: '設定即時時鐘', @@ -616,6 +628,15 @@ const zhHant = { uploadToggle: '設定時傳送', missingBytes: '缺少字型。請上傳或移除該項目。', removeOrphan: '移除過時項目', + fontCache: '可縮放字元快取', + fontCacheEnabled: '開', + fontCacheDisabled: '關', + fontCacheAddKb: '額外快取記憶體', + fontCacheKbUnit: 'KB', + fontCacheHint: '當大型縮放字元列印緩慢或無法列印時,請增大此值。', + fontCacheType: '快取類型', + fontCacheTypeNormal: '一般緩衝區', + fontCacheTypeInternal: '內部(亞洲字型)', }, identity: { printerName: '印表機名稱', @@ -629,6 +650,17 @@ const zhHant = { configurationUpdateOptionR: '取回上次儲存', configurationUpdateOptionN: '重新載入出廠網路設定 (破壞性)', configurationUpdateOptionF: '還原出廠設定 (破壞性)', + modeProtection: '受保護的面板模式', + modeProtectCustom: '自訂組合', + modeProtectCustomHint: '空白的自訂組合會重新啟用印表機上的所有控制面板模式。', + modeProtectDarkness: '濃度模式', + modeProtectPosition: '位置模式', + modeProtectCalibration: '校準模式', + modeProtectSaves: '模式儲存', + modeProtectPause: '暫停', + modeProtectFeed: '走紙', + modeProtectCancel: '取消', + modeProtectMenu: '選單變更', }, maintenance: { maintenanceAlertHeading: '維護警報', diff --git a/src/registry/maxicode.panel.tsx b/src/registry/maxicode.panel.tsx index 65ce9e78..faa58aac 100644 --- a/src/registry/maxicode.panel.tsx +++ b/src/registry/maxicode.panel.tsx @@ -38,7 +38,7 @@ export const maxicodePanel: ObjectTypeUi = {
- {loc.mode} + {loc.mode} value={p.mode} onChange={(mode) => onChange({ mode })} diff --git a/src/registry/maxicode.test.ts b/src/registry/maxicode.test.ts index 84c5eadd..0c735622 100644 --- a/src/registry/maxicode.test.ts +++ b/src/registry/maxicode.test.ts @@ -20,13 +20,13 @@ function makeObj(props: MaxicodeProps, overrides?: Partial): La describe("maxicode.toZPL", () => { const def = defined(ObjectRegistry["maxicode"]); - it("emits ^BV with mode and pinned (1,1) structured-append fields", () => { + it("emits ^BD with mode and pinned (1,1) structured-append fields", () => { const zpl = def.toZPL(makeObj({ content: "abc", mode: 4, })); expect(zpl).toContain("^FO100,200"); - expect(zpl).toContain("^BVN,4,1,1"); + expect(zpl).toContain("^BD4,1,1"); expect(zpl).toContain("^FDabc^FS"); }); }); @@ -56,21 +56,20 @@ describe("validateMaxicodeBwip", () => { }); describe("maxicode parser roundtrip", () => { - it("parses ^BV back to a maxicode object; the no-op orientation slot is canonicalized away", () => { - const src = "^XA^PW400^LL400^FO50,50^BVR,3,1,1^FDPAYLOAD^FS^XZ"; + it("parses ^BD back to a maxicode object", () => { + const src = "^XA^PW400^LL400^FO50,50^BD3,1,1^FDPAYLOAD^FS^XZ"; const { objects } = parseSingle(src); const obj = objects[0]; expect(obj?.type).toBe("maxicode"); if (obj?.type !== "maxicode") return; expect(obj.props.content).toBe("PAYLOAD"); expect(obj.props.mode).toBe(3); - // Firmware ignores the slot; re-emit pins it to N. - expect(defined(ObjectRegistry["maxicode"]).toZPL(obj)).toContain("^BVN,3,1,1"); + expect(defined(ObjectRegistry["maxicode"]).toZPL(obj)).toContain("^BD3,1,1"); }); it("defaults mode to 4 when an out-of-range value is given", () => { // mode 9 doesn't exist; parser clamps to the safe standalone default. - const src = "^XA^FO0,0^BVN,9,1,1^FDX^FS^XZ"; + const src = "^XA^FO0,0^BD9,1,1^FDX^FS^XZ"; const { objects } = parseSingle(src); const obj = objects[0]; if (obj?.type !== "maxicode") throw new Error("expected maxicode"); diff --git a/src/registry/registry.test.ts b/src/registry/registry.test.ts index 678d0dbe..7aa78c2c 100644 --- a/src/registry/registry.test.ts +++ b/src/registry/registry.test.ts @@ -676,7 +676,7 @@ describe('ObjectRegistry', () => { // The rotation prop's existence IS the rotatability capability (spawn, panel, // canvas and emit all key off it). qrcode rotates via a baked ^GFA like image; - // maxicode stays off (^BV is a no-op, MaxiCode is omnidirectional). Belongs + // maxicode stays off (^BD has no orientation slot, MaxiCode is omnidirectional). Belongs // here only with a working o=N/R/I/B or a baked graphic emit. it('rotation prop membership matches the ZPL orientation capability', () => { const rotatable = Object.entries(ObjectRegistry)