From 8ca15cc151937a45f3f5df1bbafa5c2e7a002b18 Mon Sep 17 00:00:00 2001 From: u8array Date: Fri, 16 Oct 2026 16:48:59 +0200 Subject: [PATCH 1/5] feat(setup): the sensor and calibration commands join the setup script --- README.md | 6 +- docs/zpl-coverage.md | 10 ++-- packages/core/src/catalog/commands.json | 37 ++++++------ packages/core/src/lib/importReport.ts | 4 +- packages/core/src/lib/zplParser.ts | 4 +- .../src/lib/zplParser/handlers/setupScript.ts | 58 +++++++++++++++++- .../src/lib/zplParser/handlers/unsupported.ts | 1 - packages/core/src/types/PrinterProfile.ts | 56 ++++++++++++++++++ src/lib/zplImportService.test.ts | 14 +++++ src/lib/zplParser.prefixDispatch.test.ts | 11 ++-- src/lib/zplParser.test.ts | 6 +- src/lib/zplSetupScript.test.ts | 58 ++++++++++++++++++ src/lib/zplSetupScript.ts | 59 ++++++++++++++++++- src/locales/catalog/ar.json | 11 +++- src/locales/catalog/bg.json | 11 +++- src/locales/catalog/cs.json | 11 +++- src/locales/catalog/da.json | 11 +++- src/locales/catalog/de.json | 11 +++- src/locales/catalog/el.json | 11 +++- src/locales/catalog/es.json | 11 +++- src/locales/catalog/et.json | 11 +++- src/locales/catalog/fa.json | 11 +++- src/locales/catalog/fi.json | 11 +++- src/locales/catalog/fr.json | 11 +++- src/locales/catalog/he.json | 11 +++- src/locales/catalog/hr.json | 11 +++- src/locales/catalog/hu.json | 11 +++- src/locales/catalog/it.json | 11 +++- src/locales/catalog/ja.json | 11 +++- src/locales/catalog/ko.json | 11 +++- src/locales/catalog/lt.json | 11 +++- src/locales/catalog/lv.json | 11 +++- src/locales/catalog/nl.json | 11 +++- src/locales/catalog/no.json | 11 +++- src/locales/catalog/pl.json | 11 +++- src/locales/catalog/pt.json | 11 +++- src/locales/catalog/ro.json | 11 +++- src/locales/catalog/sk.json | 11 +++- src/locales/catalog/sl.json | 11 +++- src/locales/catalog/sr.json | 11 +++- src/locales/catalog/sv.json | 11 +++- src/locales/catalog/tr.json | 11 +++- src/locales/catalog/zh-hans.json | 11 +++- src/locales/catalog/zh-hant.json | 11 +++- 44 files changed, 532 insertions(+), 133 deletions(-) diff --git a/README.md b/README.md index 467e70429..7273de56e 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,7 @@ On desktop, **Connect data** also reads an Excel worksheet. **File → Settings ### Printer settings -**File → Settings… → Per Label** configures media, print quality, output and RFID. The **Setup Script** covers clock, encoding, fonts, printer identity and maintenance. +**File → Settings… → Per Label** configures media, print quality, output and RFID. The **Setup Script** covers clock, encoding, fonts, printer identity, maintenance and sensors. - The **Objects** group selects the fonts and graphics the **Setup Script** uploads. - It lists cached images and deletes the unused ones. @@ -188,7 +188,7 @@ On desktop, **File → Settings… → App → MCP** starts a local MCP server, ## Coverage -125 of the 225 ZPL II commands are modelled in the browser; desktop covers 9 more with a connected printer. 2 more are planned for both builds. 67 need a connected printer and are planned for desktop. See per-command coverage: [docs/zpl-coverage.md](docs/zpl-coverage.md). +130 of the 225 ZPL II commands are modelled in the browser; desktop covers 9 more with a connected printer. 2 more are planned for both builds. 62 need a connected printer and are planned for desktop. See per-command coverage: [docs/zpl-coverage.md](docs/zpl-coverage.md). | Area | Modelled | |---|---| @@ -205,7 +205,7 @@ On desktop, **File → Settings… → App → MCP** starts a local MCP server, | Text & fonts | 14 / 15 | | Print quality | 10 / 18 | | Configuration & persistence | 4 / 5 | -| Hardware / Host comm / RFID / Network | 4 / 89 | +| Hardware / Host comm / RFID / Network | 9 / 89 | ## Limitations diff --git a/docs/zpl-coverage.md b/docs/zpl-coverage.md index 723ffdd8e..bc730f1c9 100644 --- a/docs/zpl-coverage.md +++ b/docs/zpl-coverage.md @@ -241,7 +241,7 @@ Printer-side control, calibration and device actions; most need a connection or | `~JG` | graphing sensor calibration | `[ ]` | `[~]` | `[~]` | | `^JI` / `~JI` | start ZBI | `[ ]` | `[~]` | `[~]` | | `^JJ` | set auxiliary port | `[ ]` | `[~]` | `[~]` | -| `^JS` | sensor select | `[ ]` | `[~]` | `[~]` | +| `^JS` | sensor select | `[x]` | `[x]` | `[x]` | | `~JL` | set label length | `[ ]` | `[~]` | `[~]` | | `^JM` | dots per millimeter | `[x]` | `[x]` | `[x]` | | `~JN` | printhead test fatal | `[ ]` | `[~]` | `[~]` | @@ -252,18 +252,18 @@ Printer-side control, calibration and device actions; most need a connection or | `~JX` | cancel partial format | `[ ]` | `[~]` | `[~]` | | `~RO` | reset advanced counter | `[ ]` | `[~]` | `[~]` | | `^SC` | set serial communications | `[ ]` | `[~]` | `[~]` | -| `^SI` | set sensor intensity | `[ ]` | `[~]` | `[~]` | +| `^SI` | set sensor intensity | `[x]` | `[x]` | `[x]` | | `^SP` | start print at dot row, throughput hint only | `[ ]` | `[ ]` | `[ ]` | | `^SQ` | halt ZebraNet alert | `[ ]` | `[~]` | `[~]` | -| `^SR` | set printhead resistance | `[ ]` | `[~]` | `[~]` | -| `^SS` | set media sensors | `[ ]` | `[~]` | `[~]` | +| `^SR` | set printhead resistance | `[x]` | `[x]` | `[x]` | +| `^SS` | set media sensors | `[x]` | `[x]` | `[x]` | | `^SX` | set ZebraNet alert | `[ ]` | `[~]` | `[~]` | | `^TO` | transfer object | `[ ]` | `[~]` | `[~]` | | `~WC` | print configuration label | `[ ]` | `[~]` | `[~]` | | `^WD` | print directory label | `[ ]` | `[~]` | `[~]` | | `~WQ` | write query | `[ ]` | `[~]` | `[~]` | | `^KV` | cutter and presenter settings, KR403 only | `[ ]` | `[ ]` | `[ ]` | -| `^XS` | set dynamic media calibration | `[ ]` | `[~]` | `[~]` | +| `^XS` | set dynamic media calibration | `[x]` | `[x]` | `[x]` | | `~PM` | decommissioning mode | `[ ]` | `[~]` | `[~]` | | `^ZZ` | printer sleep, PA400 and PT400 only | `[ ]` | `[ ]` | `[ ]` | | `^CP` | eject or retract a presented page, KR403 only | `[ ]` | `[ ]` | `[ ]` | diff --git a/packages/core/src/catalog/commands.json b/packages/core/src/catalog/commands.json index a722b7968..214b3830c 100644 --- a/packages/core/src/catalog/commands.json +++ b/packages/core/src/catalog/commands.json @@ -5312,9 +5312,8 @@ "example": "^JSA" }, "support": { - "web": "no", - "desktop": "planned", - "docker": "planned" + "web": "yes", + "desktop": "yes" } }, { @@ -5584,9 +5583,8 @@ "example": "^SI1,120" }, "support": { - "web": "no", - "desktop": "planned", - "docker": "planned" + "web": "yes", + "desktop": "yes" } }, { @@ -5671,9 +5669,8 @@ "example": "^SR0675" }, "support": { - "web": "no", - "desktop": "planned", - "docker": "planned" + "web": "yes", + "desktop": "yes" } }, { @@ -5745,9 +5742,8 @@ "example": "^SS075,045,070,0812,090,085,060,055,075" }, "support": { - "web": "no", - "desktop": "planned", - "docker": "planned" + "web": "yes", + "desktop": "yes" } }, { @@ -6000,9 +5996,9 @@ ], "section": "Hardware control & calibration", "title": "set dynamic media calibration", - "summary": "Controls dynamic recalibration of label length and sensor threshold after power-up or media-compartment open.", + "summary": "Controls dynamic recalibration of label length and sensor threshold after power-up or media-compartment open. The gain slot is announced for a later firmware.", "reference": { - "syntax": "^XSa,b", + "syntax": "^XSa,b,c", "params": [ { "name": "a", @@ -6015,14 +6011,19 @@ "meaning": "enable dynamic threshold calibration", "values": "Y enable, N disable", "default": "Y" + }, + { + "name": "c", + "meaning": "enable dynamic gain calibration", + "values": "Y enable, N disable", + "default": "Y" } ], - "example": "^XSY,Y" + "example": "^XSY,Y,Y" }, "support": { - "web": "no", - "desktop": "planned", - "docker": "planned" + "web": "yes", + "desktop": "yes" } }, { diff --git a/packages/core/src/lib/importReport.ts b/packages/core/src/lib/importReport.ts index 4f0be4d1a..842390564 100644 --- a/packages/core/src/lib/importReport.ts +++ b/packages/core/src/lib/importReport.ts @@ -50,7 +50,9 @@ export function resolveRoutedReport( } if (f.pageIndex === DOCUMENT_FINDING) return [f]; const newIndex = newIndexOf.get(f.pageIndex); - return newIndex === undefined ? [] : [{ ...f, pageIndex: newIndex }]; + // A setup-only page leaves with its block, but what the profile could not take is still lost. + if (newIndex === undefined) return f.kind === 'partial' ? [{ ...f, pageIndex: DOCUMENT_FINDING }] : []; + return [{ ...f, pageIndex: newIndex }]; }); return reportOf(findings); } diff --git a/packages/core/src/lib/zplParser.ts b/packages/core/src/lib/zplParser.ts index 9bd2e603c..cc1cfb3e3 100644 --- a/packages/core/src/lib/zplParser.ts +++ b/packages/core/src/lib/zplParser.ts @@ -161,7 +161,7 @@ export const BY_CONSUMING_BARCODE_TYPES = new Set([ * support "no" plus a handler also holds for ^FM, ^HT and ^LF. */ export const DEVICE_ACTION_IDS: ReadonlySet = new Set([ "~JA", "~JC", "~JD", "~JE", "^JI", "~JI", "~JR", "^ID", "^IS", "~EG", - "~PH", "~PP", "~PM", "~PR", "^JS", + "~PH", "~PP", "~PM", "~PR", ]); /** Commands defining persistent state a later field may consume implicitly; @@ -575,7 +575,7 @@ export function parseZPL( const canonical = `${prefix}${cmd}`; const takesPrefix = commandTakesPrefix(cmd, prefix); // The device action quotes its payload: the report must name the bytes that will run. - if (takesPrefix && replayRiskCodes.has(cmd)) replayRisk.push({ command: s.result.tokenCommand, span: s.result.tokenSpan }); + if (takesPrefix && (replayRiskCodes.has(cmd) || replayRiskCodes.has(canonical))) replayRisk.push({ command: s.result.tokenCommand, span: s.result.tokenSpan }); else if (takesPrefix && DEVICE_ACTION_IDS.has(canonical)) deviceAction.push({ command: sourceToken, span: s.result.tokenSpan }); // Balance bookkeeping needs the token offset and the state the handler is // about to flip, so it sits here rather than in the two handlers. diff --git a/packages/core/src/lib/zplParser/handlers/setupScript.ts b/packages/core/src/lib/zplParser/handlers/setupScript.ts index 6e22dc3de..59019c2de 100644 --- a/packages/core/src/lib/zplParser/handlers/setupScript.ts +++ b/packages/core/src/lib/zplParser/handlers/setupScript.ts @@ -1,8 +1,8 @@ -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 { 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, PRINTHEAD_RESISTANCE_RANGE, SENSOR_INTENSITY_RANGE, SENSOR_SLOTS, SI_FIELD_BY_SLOT, TEAR_OFF_ADJUST_RANGE, XS_SLOTS, isClockFormat, isClockLanguage, isConfigUpdateAction, isFontCacheType, isMaintenanceAlertPrint, isMaintenanceAlertType, isMaintenanceAlertUnit, isMediaSensorSelect, isModeProtection, isPrinterLocale, isZplMode, setupScriptUnsafeCharRegex, type SensorSlotField } from "../../../types/PrinterProfile"; import { parseIntOrUndef } from "../../inputParse"; import { isYesNo } from "../../../types/typeHelpers"; import { parseRealtimeClock } from "../../realtimeClock"; -import type { ParserState } from "../context"; +import { notePartial, type ParserState } from "../context"; import { inRange, strParam } from "../helpers"; import type { Handler } from "../types"; @@ -207,6 +207,60 @@ export function createSetupScriptHandlers(s: ParserState): Record 0) printerProfile.fontLinks = list; else delete printerProfile.fontLinks; }, + // Keyed with its prefix: ~JS is the backfeed sequence. + "^JS"(p) { + const v = strParam(p[0]); + if (isMediaSensorSelect(v)) printerProfile.mediaSensorSelect = v; + else notePartial(s.result, "^JS"); + }, + // The spec says nothing about a bad ^SS slot, so it follows ^SI and ^SC: the command changes nothing and the loss is reported. + SS(p) { + const read = new Map(); + for (const [i, [field, range]] of SENSOR_SLOTS.entries()) { + const text = strParam(p[i]); + // An empty slot leaves the calibrated value in force, so it clears the field. + const v = text === "" ? undefined : inRange(parseIntOrUndef(text), range); + if (text !== "" && v === undefined) { + notePartial(s.result, "^SS"); + return; + } + read.set(field, v); + } + for (const [field, v] of read) { + if (v === undefined) Reflect.deleteProperty(printerProfile, field); + else printerProfile[field] = v; + } + }, + // ^SI names one value and sets it, so an empty slot is a loss and not a clear, spec p.338. + SI(p) { + const field = SI_FIELD_BY_SLOT[strParam(p[0])]; + const v = inRange(parseIntOrUndef(p[1]), SENSOR_INTENSITY_RANGE); + if (field === undefined || v === undefined) notePartial(s.result, "^SI"); + else printerProfile[field] = v; + }, + XS(p) { + // Every slot defaults to Y, spec p.374, so a bare ^XS must not vanish on re-emit. + const bare = p.every((v) => v.trim() === ""); + const values = XS_SLOTS.map((_field, i) => (bare ? "Y" : strParam(p[i]))); + if (values.some((v) => v !== "" && !isYesNo(v)) || p.slice(XS_SLOTS.length).some((v) => v.trim() !== "")) { + notePartial(s.result, "^XS"); + return; + } + XS_SLOTS.forEach((field, i) => { + const v = values[i] ?? ""; + if (isYesNo(v)) printerProfile[field] = v; + else Reflect.deleteProperty(printerProfile, field); + }); + }, + SR(p) { + const text = strParam(p[0]); + if (text === "") delete printerProfile.printheadResistance; + else { + const v = inRange(parseIntOrUndef(text), PRINTHEAD_RESISTANCE_RANGE); + if (v === undefined) notePartial(s.result, "^SR"); + else printerProfile.printheadResistance = v; + } + }, // ^JH: only f/g modelled; other slots are runtime reset flags. // g is a 0..16 index into HEAD_CLEANING_INTERVAL_METERS per spec. JH(p) { diff --git a/packages/core/src/lib/zplParser/handlers/unsupported.ts b/packages/core/src/lib/zplParser/handlers/unsupported.ts index c9697df23..bc697d110 100644 --- a/packages/core/src/lib/zplParser/handlers/unsupported.ts +++ b/packages/core/src/lib/zplParser/handlers/unsupported.ts @@ -18,7 +18,6 @@ export function createUnsupportedHandlers(s: ParserState): Record deleteStoredObjects(s, p[0] ?? ""), IS: noop, diff --git a/packages/core/src/types/PrinterProfile.ts b/packages/core/src/types/PrinterProfile.ts index 8bdab1907..9a106df71 100644 --- a/packages/core/src/types/PrinterProfile.ts +++ b/packages/core/src/types/PrinterProfile.ts @@ -81,6 +81,40 @@ export function toggleModeProtection( } export const TEAR_OFF_ADJUST_RANGE = { min: -120, max: 120 } as const; +/** ^JS: A auto, R reflective, T transmissive. */ +export const MEDIA_SENSOR_SELECT_VALUES = ['A', 'R', 'T'] as const; +export type MediaSensorSelect = (typeof MEDIA_SENSOR_SELECT_VALUES)[number]; +export const isMediaSensorSelect = makeEnumGuard(MEDIA_SENSOR_SELECT_VALUES); +/** ^SS w, m, r, a, b, spec p.349. */ +const SENSOR_THRESHOLD_RANGE = { min: 0, max: 100 } as const; +/** ^SS n, o, c. */ +const SENSOR_LED_RANGE = { min: 0, max: 255 } as const; +/** ^SS l. */ +const SENSOR_LABEL_LENGTH_RANGE = { min: 1, max: 32000 } as const; +/** ^SI b, spec p.338. */ +export const SENSOR_INTENSITY_RANGE = { min: 0, max: 196 } as const; +/** ^XS a, b, c in wire order, spec p.374. */ +export const XS_SLOTS = ['dynamicCalibrationLength', 'dynamicCalibrationThreshold', 'dynamicCalibrationGain'] as const; +/** ^SR, spec p.348. */ +export const PRINTHEAD_RESISTANCE_RANGE = { min: 488, max: 1175 } as const; + +/** ^SS slots in wire order with their range and digit width, spec p.349. */ +export const SENSOR_SLOTS = [ + ['sensorWebThreshold', SENSOR_THRESHOLD_RANGE, 3], + ['sensorMediaThreshold', SENSOR_THRESHOLD_RANGE, 3], + ['sensorRibbonThreshold', SENSOR_THRESHOLD_RANGE, 3], + ['sensorLabelLengthDots', SENSOR_LABEL_LENGTH_RANGE, 4], + ['sensorMediaLedIntensity', SENSOR_LED_RANGE, 3], + ['sensorRibbonLedIntensity', SENSOR_LED_RANGE, 3], + ['sensorMarkThreshold', SENSOR_THRESHOLD_RANGE, 3], + ['sensorMarkMediaThreshold', SENSOR_THRESHOLD_RANGE, 3], + ['sensorMarkLedIntensity', SENSOR_LED_RANGE, 3], +] as const satisfies readonly (readonly [keyof PrinterProfile, { min: number; max: number }, number])[]; +export type SensorSlotField = (typeof SENSOR_SLOTS)[number][0]; +export const SENSOR_SLOT_RANGE = Object.fromEntries(SENSOR_SLOTS.map(([field, range]) => [field, range])) as Record; +/** ^SI a picks the value the b slot sets, spec p.338. */ +export const SI_FIELD_BY_SLOT: Readonly> = { '1': 'sensorBrightness', '2': 'sensorBaseline' }; + /** ^KP 4-digit; '0000' disables LCD-setup protection. */ export const PRINTER_PASSWORD_REGEX = /^\d{4}$/; @@ -220,6 +254,28 @@ export const printerProfileSchema = z.object({ path: z.string().min(1).max(FONT_LINKS_PATH_MAX_LEN).regex(setupScriptSafeStringRegex), gfa: z.string().min(1).max(SETUP_UPLOAD_MAX_CHARS), })).optional(), + /** ^JS media sensor. */ + mediaSensorSelect: z.enum(MEDIA_SENSOR_SELECT_VALUES).optional(), + /** ^SS slots, each on its own so one bad value drops one slot. */ + sensorWebThreshold: intInRange(SENSOR_THRESHOLD_RANGE).optional(), + sensorMediaThreshold: intInRange(SENSOR_THRESHOLD_RANGE).optional(), + sensorRibbonThreshold: intInRange(SENSOR_THRESHOLD_RANGE).optional(), + /** The calibrated length, not the design's ^LL. */ + sensorLabelLengthDots: intInRange(SENSOR_LABEL_LENGTH_RANGE).optional(), + sensorMediaLedIntensity: intInRange(SENSOR_LED_RANGE).optional(), + sensorRibbonLedIntensity: intInRange(SENSOR_LED_RANGE).optional(), + sensorMarkThreshold: intInRange(SENSOR_THRESHOLD_RANGE).optional(), + sensorMarkMediaThreshold: intInRange(SENSOR_THRESHOLD_RANGE).optional(), + sensorMarkLedIntensity: intInRange(SENSOR_LED_RANGE).optional(), + /** ^SI1 and ^SI2, the transmissive sensor's brightness and baseline. */ + sensorBrightness: intInRange(SENSOR_INTENSITY_RANGE).optional(), + sensorBaseline: intInRange(SENSOR_INTENSITY_RANGE).optional(), + /** ^XS length, threshold and gain slots. */ + dynamicCalibrationLength: z.enum(YES_NO_VALUES).optional(), + dynamicCalibrationThreshold: z.enum(YES_NO_VALUES).optional(), + dynamicCalibrationGain: z.enum(YES_NO_VALUES).optional(), + /** ^SR, a value above the head's rating damages it. */ + printheadResistance: intInRange(PRINTHEAD_RESISTANCE_RANGE).optional(), /** ^JH f master gate; without `E` ^MA sits dormant. */ earlyWarningMaintenance: z.enum(['E', 'D']).optional(), /** ^JH g; stored as meters for UX, wire is index into table. */ diff --git a/src/lib/zplImportService.test.ts b/src/lib/zplImportService.test.ts index 2b6540873..4aa740532 100644 --- a/src/lib/zplImportService.test.ts +++ b/src/lib/zplImportService.test.ts @@ -1100,6 +1100,20 @@ describe('replay-risk report helpers', () => { expect(stripped.partial).toEqual(report.partial); }); + it('a recall row that switches the media sensor stops batching and stays a page', () => { + const rows = (body: string) => `^XA^DFR:T.ZPL^FS^FO10,10^A0N,30,30^FN1^FS^XZ^XA^XFR:T.ZPL^FS${body}^FN1^FDa^FS^XZ^XA^XFR:T.ZPL^FS${body}^FN1^FDb^FS^XZ`; + expect(importZplText(rows('~PH'), 8).batch?.dataset.rows).toEqual([['a'], ['b']]); + expect(importZplText(rows('^JSA'), 8).batch).toBeUndefined(); + }); + + it('resolveRoutedReport keeps a partial of a routed setup-only page as a document finding', () => { + const imported = importZplText('^XA^SS999^SR0300^XZ', 8); + expect(imported.report.partial).toEqual(['^SS', '^SR']); + const routed = resolveRoutedReport(imported.report, []); + expect(routed.partial).toEqual(['^SS', '^SR']); + expect(routed.findings.every((f) => f.pageIndex === DOCUMENT_FINDING)).toBe(true); + }); + it('resolveRoutedReport keeps the dropped-field bucket', () => { const { report } = importZplText('^XA^FO10,10^A0N,30,30^FDa^FO10,60^A0N,30,30^FDb^FS^XZ', 8); expect(resolveRoutedReport(report, [0]).unterminatedField).toEqual(['^FO10,10']); diff --git a/src/lib/zplParser.prefixDispatch.test.ts b/src/lib/zplParser.prefixDispatch.test.ts index e738453e9..2c67df287 100644 --- a/src/lib/zplParser.prefixDispatch.test.ts +++ b/src/lib/zplParser.prefixDispatch.test.ts @@ -37,9 +37,10 @@ describe('parseZPL — the catalog is the one source of prefix knowledge', () => expect(commandsOf(tilde, 'deviceAction')).toEqual(['~PH', '~PP', '~PMY', '~PR4']); expect(commandsOf(tilde, 'unknown')).toEqual([]); expect(parseSingle('~JSB\n^XA^XZ', 8).labelConfig.backfeedSequence).toBe('B'); - const caretJs = parseSingle('^XA^JSB^XZ', 8); + const caretJs = parseSingle('^XA^JST^XZ', 8); expect(caretJs.labelConfig).toEqual(baseline); - expect(commandsOf(caretJs, 'deviceAction')).toEqual(['^JSB']); + expect(caretJs.printerProfile.mediaSensorSelect).toBe('T'); + expect(commandsOf(caretJs, 'replayRisk')).toEqual(['^JS']); }); it('keeps every unmodelled twin side out of the model, whatever the catalog adds later', () => { @@ -58,12 +59,12 @@ describe('parseZPL — the catalog is the one source of prefix knowledge', () => for (const id of DEVICE_ACTION_IDS) expect(catalogEntry(id), id).toBeDefined(); }); - it('registers twin-split names only under spelled keys, and setup-script codes only bare', () => { + it('registers twin-split names only under spelled keys, and every other code bare', () => { const s = createParserState(); - const keys = [...Object.keys(createLabelConfigHandlers(s, 8)), ...Object.keys(createUnsupportedHandlers(s))]; + const keys = [...Object.keys(createLabelConfigHandlers(s, 8)), ...Object.keys(createUnsupportedHandlers(s)), ...Object.keys(createSetupScriptHandlers(s))]; const bareTwins = keys.filter((key) => !/^[\^~]/.test(key) && commandTwinSplit(key)); expect(bareTwins).toEqual([]); - expect(Object.keys(createSetupScriptHandlers(s)).filter((key) => /^[\^~]/.test(key))).toEqual([]); + expect(keys.filter((key) => /^[\^~]/.test(key) && !commandTwinSplit(key.slice(1)))).toEqual([]); }); it('quotes a browser-limit token under the live prefix chars', () => { diff --git a/src/lib/zplParser.test.ts b/src/lib/zplParser.test.ts index aa6438ed5..c899ac244 100644 --- a/src/lib/zplParser.test.ts +++ b/src/lib/zplParser.test.ts @@ -1770,12 +1770,14 @@ describe('parseZPL — printer params', () => { expect(parseZPL('^XA^PF33000^XZ', 8).labelConfig.slewDotRows).toBeUndefined(); }); - it('keeps the twins ^JS, ~PM and ~PR off the modelled ~JS, ^PM and ^PR', () => { + it('keeps ^JS out of the per-label config and ~PM, ~PR out of the model', () => { const r = parseSingle('^XA^JSA~PMY123456,3~PR2^XZ', 8); expect(r.labelConfig.backfeedSequence).toBeUndefined(); expect(r.labelConfig.mirror).toBeUndefined(); expect(r.labelConfig.printSpeed).toBeUndefined(); - expect(commandsOf(r, 'deviceAction')).toEqual(expect.arrayContaining(['^JSA', '~PMY123456,3', '~PR2'])); + expect(r.printerProfile.mediaSensorSelect).toBe('A'); + expect(commandsOf(r, 'replayRisk')).toEqual(['^JS']); + expect(commandsOf(r, 'deviceAction')).toEqual(expect.arrayContaining(['~PMY123456,3', '~PR2'])); }); it('routes ~PH/~PP as device actions without touching the model', () => { diff --git a/src/lib/zplSetupScript.test.ts b/src/lib/zplSetupScript.test.ts index c66a2f698..8a35a09ff 100644 --- a/src/lib/zplSetupScript.test.ts +++ b/src/lib/zplSetupScript.test.ts @@ -437,6 +437,22 @@ describe("generateSetupScript — output shape", () => { "tearOffAdjust", "reprintAfterError", "headTestInterval", + "mediaSensorSelect", + "sensorWebThreshold", + "sensorMediaThreshold", + "sensorRibbonThreshold", + "sensorLabelLengthDots", + "sensorMediaLedIntensity", + "sensorRibbonLedIntensity", + "sensorMarkThreshold", + "sensorMarkMediaThreshold", + "sensorMarkLedIntensity", + "sensorBrightness", + "sensorBaseline", + "dynamicCalibrationLength", + "dynamicCalibrationThreshold", + "dynamicCalibrationGain", + "printheadResistance", "setRealtimeClock", "useCurrentTimeForClock", "clockFormat", @@ -469,6 +485,48 @@ describe("generateSetupScript — output shape", () => { ]); }); + it("emits the sensor commands as the spec writes them", () => { + const sensors = { + mediaSensorSelect: "T", sensorWebThreshold: 75, sensorMediaThreshold: 45, sensorRibbonThreshold: 70, sensorLabelLengthDots: 812, + sensorMediaLedIntensity: 90, sensorRibbonLedIntensity: 85, sensorMarkThreshold: 60, sensorMarkMediaThreshold: 55, sensorMarkLedIntensity: 75, + sensorBrightness: 120, sensorBaseline: 30, dynamicCalibrationLength: "N", dynamicCalibrationThreshold: "Y", dynamicCalibrationGain: "N", printheadResistance: 675, configurationUpdate: "S", + } as const; + const script = generateSetupScript(sensors); + expect(script).toContain("^JST\n^SS075,045,070,0812,090,085,060,055,075\n^SI1,120\n^SI2,30\n^XSN,Y,N\n^SR0675"); + expect(script.indexOf("^SR0675")).toBeLessThan(script.indexOf("^JUS")); + expect(generateSetupScript({})).not.toMatch(/\^(JS|SS|SI|XS|SR)/); + expect(parseZPL(script).printerProfile).toEqual(sensors); + for (const [partial, wire] of [ + [{ sensorLabelLengthDots: 812 }, "^SS,,,0812"], + [{ sensorBaseline: 30 }, "^SI2,30"], + [{ dynamicCalibrationThreshold: "N" }, "^XS,N"], + [{ dynamicCalibrationGain: "N" }, "^XS,,N"], + ] as const) { + const out = generateSetupScript(partial); + expect(out).toContain(wire); + expect(parseZPL(out).printerProfile).toEqual(partial); + } + }); + + it("applies calibration commands the way the printer does: a bad value changes nothing, an empty slot clears, a bare ^XS means Y", () => { + const { printerProfile, pages } = parseZPL("^XA^SS075,045,070,0812,090,085,060,055,075^SS,50,,,,300^SI3,10^SI1,200^SI2,40^XSY,,Y^XSQ^SR0400^JSB^XZ"); + expect(printerProfile).toEqual({ + sensorWebThreshold: 75, sensorMediaThreshold: 45, sensorRibbonThreshold: 70, sensorLabelLengthDots: 812, + sensorMediaLedIntensity: 90, sensorRibbonLedIntensity: 85, sensorMarkThreshold: 60, sensorMarkMediaThreshold: 55, sensorMarkLedIntensity: 75, + sensorBaseline: 40, + dynamicCalibrationLength: "Y", + dynamicCalibrationGain: "Y", + }); + expect(parseZPL("^XA^SS075,045^SS,050,,,,120^XZ").printerProfile).toEqual({ sensorMediaThreshold: 50, sensorRibbonLedIntensity: 120 }); + expect(parseZPL("^XA^XS^XZ").printerProfile).toEqual({ dynamicCalibrationLength: "Y", dynamicCalibrationThreshold: "Y", dynamicCalibrationGain: "Y" }); + expect(parseZPL("^XA^XSY,N^XSQ^XZ").printerProfile).toEqual({ dynamicCalibrationLength: "Y", dynamicCalibrationThreshold: "N" }); + expect(parseZPL("^XA^XSY,N,N^XS,,,Y^XZ").printerProfile).toEqual({ dynamicCalibrationLength: "Y", dynamicCalibrationThreshold: "N", dynamicCalibrationGain: "N" }); + expect(parseZPL("^XA^SI1,120^SI1,200^XZ").printerProfile).toEqual({ sensorBrightness: 120 }); + expect(parseZPL("^XA^SR0675^SR9999^XZ").printerProfile).toEqual({ printheadResistance: 675 }); + expect(pages[0]?.findings.filter((f) => f.kind === "partial").map((f) => f.command)).toEqual(["^SS", "^SI", "^XS", "^SR", "^JS"]); + expect(pages[0]?.findings.filter((f) => f.kind === "replayRisk").map((f) => f.command)).toContain("^JS"); + }); + 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"); diff --git a/src/lib/zplSetupScript.ts b/src/lib/zplSetupScript.ts index b6a461125..23adb3aa3 100644 --- a/src/lib/zplSetupScript.ts +++ b/src/lib/zplSetupScript.ts @@ -3,6 +3,8 @@ import { JH_SLOT_COUNT, JH_SLOT_F, JH_SLOT_G, + SENSOR_SLOTS, + XS_SLOTS, type PrinterProfile, } from '@zplab/core/types/PrinterProfile'; import { formatFontDownloadFromPath } from '@zplab/core/lib/customFonts'; @@ -26,6 +28,8 @@ import { formatRealtimeClockForZpl, toLocalIsoString } from '@zplab/core/lib/rea * only way to be sure the field actually lands there after an * earlier script left the printer in a non-default state. */ +const pad = (v: number | undefined, width: number): string => (v === undefined ? '' : String(v).padStart(width, '0')); + type SetupScriptEntry = | { kind: 'emit'; channel: 'tilde'; emit: (p: PrinterProfile) => string | null } // `scope` is required on block entries so every new command makes the @@ -69,7 +73,7 @@ const SETUP_SCRIPT_EMITTERS = { if (p.tearOffAdjust === undefined) return null; const v = p.tearOffAdjust; const sign = v < 0 ? '-' : ''; - const mag = String(Math.abs(v)).padStart(3, '0'); + const mag = pad(Math.abs(v), 3); return `~TA${sign}${mag}`; }, }, @@ -85,6 +89,59 @@ const SETUP_SCRIPT_EMITTERS = { scope: 'persistent', emit: (p) => p.headTestInterval !== undefined ? `^JT${p.headTestInterval}` : null, }, + mediaSensorSelect: { + kind: 'emit', + channel: 'block', + scope: 'persistent', + emit: (p) => p.mediaSensorSelect !== undefined ? `^JS${p.mediaSensorSelect}` : null, + }, + sensorWebThreshold: { + kind: 'emit', + channel: 'block', + scope: 'persistent', + emit: (p) => { + const slots = trimTrailingEmptySlots(SENSOR_SLOTS.map(([field, , width]) => pad(p[field], width))); + return slots.length > 0 ? `^SS${slots.join(',')}` : null; + }, + }, + sensorMediaThreshold: { kind: 'foldedInto', target: 'sensorWebThreshold' }, + sensorRibbonThreshold: { kind: 'foldedInto', target: 'sensorWebThreshold' }, + sensorLabelLengthDots: { kind: 'foldedInto', target: 'sensorWebThreshold' }, + sensorMediaLedIntensity: { kind: 'foldedInto', target: 'sensorWebThreshold' }, + sensorRibbonLedIntensity: { kind: 'foldedInto', target: 'sensorWebThreshold' }, + sensorMarkThreshold: { kind: 'foldedInto', target: 'sensorWebThreshold' }, + sensorMarkMediaThreshold: { kind: 'foldedInto', target: 'sensorWebThreshold' }, + sensorMarkLedIntensity: { kind: 'foldedInto', target: 'sensorWebThreshold' }, + sensorBrightness: { + kind: 'emit', + channel: 'block', + scope: 'persistent', + emit: (p) => { + const lines = [ + ...(p.sensorBrightness !== undefined ? [`^SI1,${p.sensorBrightness}`] : []), + ...(p.sensorBaseline !== undefined ? [`^SI2,${p.sensorBaseline}`] : []), + ]; + return lines.length > 0 ? lines.join('\n') : null; + }, + }, + sensorBaseline: { kind: 'foldedInto', target: 'sensorBrightness' }, + dynamicCalibrationLength: { + kind: 'emit', + channel: 'block', + scope: 'persistent', + emit: (p) => { + const slots = trimTrailingEmptySlots(XS_SLOTS.map((field) => p[field] ?? '')); + return slots.length > 0 ? `^XS${slots.join(',')}` : null; + }, + }, + dynamicCalibrationThreshold: { kind: 'foldedInto', target: 'dynamicCalibrationLength' }, + dynamicCalibrationGain: { kind: 'foldedInto', target: 'dynamicCalibrationLength' }, + printheadResistance: { + kind: 'emit', + channel: 'block', + scope: 'persistent', + emit: (p) => p.printheadResistance !== undefined ? `^SR${pad(p.printheadResistance, 4)}` : null, + }, setRealtimeClock: { kind: 'emit', channel: 'block', diff --git a/src/locales/catalog/ar.json b/src/locales/catalog/ar.json index 38a1cc324..b2999d673 100644 --- a/src/locales/catalog/ar.json +++ b/src/locales/catalog/ar.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "يتحكم في إعادة المعايرة الديناميكية لطول الملصق وعتبة المستشعر بعد التشغيل أو فتح حجرة الوسائط.", + "hash": "8f9e3e07", + "summary": "يتحكم في إعادة المعايرة الديناميكية لطول الملصق وعتبة المستشعر بعد التشغيل أو فتح حجرة الوسائط. تم الإعلان عن معامل الكسب لبرنامج ثابت لاحق.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "تفعيل المعايرة الديناميكية للطول", @@ -3635,6 +3635,11 @@ "meaning": "تفعيل المعايرة الديناميكية للعتبة", "values": "Y تفعيل، N تعطيل", "default": "Y" + }, + { + "meaning": "تفعيل المعايرة الديناميكية للكسب", + "values": "Y تفعيل، N تعطيل", + "default": "Y" } ] } diff --git a/src/locales/catalog/bg.json b/src/locales/catalog/bg.json index 73246648e..7924d49c7 100644 --- a/src/locales/catalog/bg.json +++ b/src/locales/catalog/bg.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Управлява динамичното прекалибриране на дължината на етикета и прага на сензора след включване или отваряне на отделението за носител.", + "hash": "8f9e3e07", + "summary": "Управлява динамичното прекалибриране на дължината на етикета и прага на сензора след включване или отваряне на отделението за носител. Параметърът за усилване е обявен за по-късна версия на фърмуера.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "разрешава динамично калибриране на дължината", @@ -3635,6 +3635,11 @@ "meaning": "разрешава динамично калибриране на прага", "values": "Y активиране, N деактивиране", "default": "Y" + }, + { + "meaning": "разрешава динамично калибриране на усилването", + "values": "Y активиране, N деактивиране", + "default": "Y" } ] } diff --git a/src/locales/catalog/cs.json b/src/locales/catalog/cs.json index cc5a0b061..69e25ae10 100644 --- a/src/locales/catalog/cs.json +++ b/src/locales/catalog/cs.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Řídí dynamickou rekalibraci délky štítku a prahu senzoru po zapnutí nebo otevření prostoru pro médium.", + "hash": "8f9e3e07", + "summary": "Řídí dynamickou rekalibraci délky štítku a prahu senzoru po zapnutí nebo otevření prostoru pro médium. Parametr zisku je ohlášen pro pozdější firmware.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "povolit dynamickou kalibraci délky", @@ -3635,6 +3635,11 @@ "meaning": "povolit dynamickou kalibraci prahu", "values": "Y povolit, N zakázat", "default": "Y" + }, + { + "meaning": "povolit dynamickou kalibraci zisku", + "values": "Y povolit, N zakázat", + "default": "Y" } ] } diff --git a/src/locales/catalog/da.json b/src/locales/catalog/da.json index d0fa8e672..0c3b966a1 100644 --- a/src/locales/catalog/da.json +++ b/src/locales/catalog/da.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Styrer dynamisk genkalibrering af etiketlængde og sensortærskel efter opstart eller åbning af medierummet.", + "hash": "8f9e3e07", + "summary": "Styrer dynamisk genkalibrering af etiketlængde og sensortærskel efter opstart eller åbning af medierummet. Gain-parameteren er annonceret til en senere firmware.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "aktiver dynamisk længdekalibrering", @@ -3635,6 +3635,11 @@ "meaning": "aktiver dynamisk tærskelkalibrering", "values": "Y aktiver, N deaktiver", "default": "Y" + }, + { + "meaning": "aktiver dynamisk gainkalibrering", + "values": "Y aktiver, N deaktiver", + "default": "Y" } ] } diff --git a/src/locales/catalog/de.json b/src/locales/catalog/de.json index 16b82bfe6..ec76906a2 100644 --- a/src/locales/catalog/de.json +++ b/src/locales/catalog/de.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Steuert die dynamische Neukalibrierung von Etikettenlänge und Sensorschwelle nach dem Einschalten oder Öffnen des Medienfachs.", + "hash": "8f9e3e07", + "summary": "Steuert die dynamische Neukalibrierung von Etikettenlänge und Sensorschwelle nach dem Einschalten oder Öffnen des Medienfachs. Der Verstärkungsparameter ist für eine spätere Firmware angekündigt.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "dynamische Längenkalibrierung aktivieren", @@ -3635,6 +3635,11 @@ "meaning": "dynamische Schwellwertkalibrierung aktivieren", "values": "Y aktivieren, N deaktivieren", "default": "Y" + }, + { + "meaning": "dynamische Verstärkungskalibrierung aktivieren", + "values": "Y aktivieren, N deaktivieren", + "default": "Y" } ] } diff --git a/src/locales/catalog/el.json b/src/locales/catalog/el.json index 8d78876d0..772cb9347 100644 --- a/src/locales/catalog/el.json +++ b/src/locales/catalog/el.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Ελέγχει τη δυναμική επαναβαθμονόμηση του μήκους ετικέτας και του ορίου αισθητήρα μετά την ενεργοποίηση ή το άνοιγμα του διαμερίσματος μέσων.", + "hash": "8f9e3e07", + "summary": "Ελέγχει τη δυναμική επαναβαθμονόμηση του μήκους ετικέτας και του ορίου αισθητήρα μετά την ενεργοποίηση ή το άνοιγμα του διαμερίσματος μέσων. Η παράμετρος κέρδους έχει ανακοινωθεί για μελλοντικό firmware.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "ενεργοποίηση δυναμικής βαθμονόμησης μήκους", @@ -3635,6 +3635,11 @@ "meaning": "ενεργοποίηση δυναμικής βαθμονόμησης κατωφλίου", "values": "Y ενεργοποίηση, N απενεργοποίηση", "default": "Y" + }, + { + "meaning": "ενεργοποίηση δυναμικής βαθμονόμησης κέρδους", + "values": "Y ενεργοποίηση, N απενεργοποίηση", + "default": "Y" } ] } diff --git a/src/locales/catalog/es.json b/src/locales/catalog/es.json index a76d51cf8..aaf1a5b90 100644 --- a/src/locales/catalog/es.json +++ b/src/locales/catalog/es.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Controla la recalibración dinámica de la longitud de la etiqueta y el umbral del sensor tras el encendido o la apertura del compartimento de material.", + "hash": "8f9e3e07", + "summary": "Controla la recalibración dinámica de la longitud de la etiqueta y el umbral del sensor tras el encendido o la apertura del compartimento de material. El parámetro de ganancia está anunciado para un firmware posterior.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "activar calibración dinámica de longitud", @@ -3635,6 +3635,11 @@ "meaning": "activar calibración dinámica de umbral", "values": "Y activar, N desactivar", "default": "Y" + }, + { + "meaning": "activar calibración dinámica de ganancia", + "values": "Y activar, N desactivar", + "default": "Y" } ] } diff --git a/src/locales/catalog/et.json b/src/locales/catalog/et.json index 16dfa89c4..57e788ab2 100644 --- a/src/locales/catalog/et.json +++ b/src/locales/catalog/et.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Määrab sildipikkuse ja anduri läve dünaamilise ümberkalibreerimise pärast sisselülitamist või kandjaosakonna avamist.", + "hash": "8f9e3e07", + "summary": "Määrab sildipikkuse ja anduri läve dünaamilise ümberkalibreerimise pärast sisselülitamist või kandjaosakonna avamist. Võimendusparameeter on välja kuulutatud hilisemale püsivarale.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "luba dünaamiline pikkuse kalibreerimine", @@ -3635,6 +3635,11 @@ "meaning": "luba dünaamiline läve kalibreerimine", "values": "Y luba, N keela", "default": "Y" + }, + { + "meaning": "luba dünaamiline võimenduse kalibreerimine", + "values": "Y luba, N keela", + "default": "Y" } ] } diff --git a/src/locales/catalog/fa.json b/src/locales/catalog/fa.json index cef3e0741..8141726b9 100644 --- a/src/locales/catalog/fa.json +++ b/src/locales/catalog/fa.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "کالیبراسیون مجدد پویای طول برچسب و آستانه سنسور را پس از روشن شدن یا باز شدن محفظه رسانه کنترل می‌کند.", + "hash": "8f9e3e07", + "summary": "کالیبراسیون مجدد پویای طول برچسب و آستانه سنسور را پس از روشن شدن یا باز شدن محفظه رسانه کنترل می‌کند. پارامتر گین برای فرم‌ور بعدی اعلام شده است.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "فعال‌سازی کالیبراسیون پویای طول", @@ -3635,6 +3635,11 @@ "meaning": "فعال‌سازی کالیبراسیون پویای آستانه", "values": "Y فعال، N غیرفعال", "default": "Y" + }, + { + "meaning": "فعال‌سازی کالیبراسیون پویای گین", + "values": "Y فعال، N غیرفعال", + "default": "Y" } ] } diff --git a/src/locales/catalog/fi.json b/src/locales/catalog/fi.json index ebf539f1f..19ddaf8c1 100644 --- a/src/locales/catalog/fi.json +++ b/src/locales/catalog/fi.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Ohjaa etiketin pituuden ja anturikynnyksen dynaamista uudelleenkalibrointia käynnistyksen tai materiaalilokeron avaamisen jälkeen.", + "hash": "8f9e3e07", + "summary": "Ohjaa etiketin pituuden ja anturikynnyksen dynaamista uudelleenkalibrointia käynnistyksen tai materiaalilokeron avaamisen jälkeen. Vahvistusparametri on ilmoitettu tulevaa laiteohjelmistoa varten.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "ota käyttöön dynaaminen pituuskalibrointi", @@ -3635,6 +3635,11 @@ "meaning": "ota käyttöön dynaaminen kynnysarvokalibrointi", "values": "Y ota käyttöön, N poista käytöstä", "default": "Y" + }, + { + "meaning": "ota käyttöön dynaaminen vahvistuskalibrointi", + "values": "Y ota käyttöön, N poista käytöstä", + "default": "Y" } ] } diff --git a/src/locales/catalog/fr.json b/src/locales/catalog/fr.json index 3e64d7441..084379f20 100644 --- a/src/locales/catalog/fr.json +++ b/src/locales/catalog/fr.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Contrôle le réétalonnage dynamique de la longueur d'étiquette et du seuil de capteur après la mise sous tension ou l'ouverture du compartiment support.", + "hash": "8f9e3e07", + "summary": "Contrôle le réétalonnage dynamique de la longueur d'étiquette et du seuil de capteur après la mise sous tension ou l'ouverture du compartiment support. Le paramètre de gain est annoncé pour un micrologiciel ultérieur.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "activer l'étalonnage dynamique de la longueur", @@ -3635,6 +3635,11 @@ "meaning": "activer l'étalonnage dynamique du seuil", "values": "Y activer, N désactiver", "default": "Y" + }, + { + "meaning": "activer l'étalonnage dynamique du gain", + "values": "Y activer, N désactiver", + "default": "Y" } ] } diff --git a/src/locales/catalog/he.json b/src/locales/catalog/he.json index e70c194ed..de4d31b1a 100644 --- a/src/locales/catalog/he.json +++ b/src/locales/catalog/he.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "שולטת בכיול מחדש דינמי של אורך התווית וסף החיישן לאחר הפעלה או פתיחת תא המדיה.", + "hash": "8f9e3e07", + "summary": "שולטת בכיול מחדש דינמי של אורך התווית וסף החיישן לאחר הפעלה או פתיחת תא המדיה. פרמטר ההגבר הוכרז לקושחה עתידית.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "הפעלת כיול אורך דינמי", @@ -3635,6 +3635,11 @@ "meaning": "הפעלת כיול סף דינמי", "values": "Y הפעלה, N ניטרול", "default": "Y" + }, + { + "meaning": "הפעלת כיול הגבר דינמי", + "values": "Y הפעלה, N ניטרול", + "default": "Y" } ] } diff --git a/src/locales/catalog/hr.json b/src/locales/catalog/hr.json index 2333d3bdc..353450dd4 100644 --- a/src/locales/catalog/hr.json +++ b/src/locales/catalog/hr.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Kontrolira dinamičku ponovnu kalibraciju duljine naljepnice i praga senzora nakon uključivanja ili otvaranja odjeljka za medij.", + "hash": "8f9e3e07", + "summary": "Kontrolira dinamičku ponovnu kalibraciju duljine naljepnice i praga senzora nakon uključivanja ili otvaranja odjeljka za medij. Parametar pojačanja najavljen je za buduću verziju firmvera.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "omogući dinamičku kalibraciju duljine", @@ -3635,6 +3635,11 @@ "meaning": "omogući dinamičku kalibraciju praga", "values": "Y omogući, N onemogući", "default": "Y" + }, + { + "meaning": "omogući dinamičku kalibraciju pojačanja", + "values": "Y omogući, N onemogući", + "default": "Y" } ] } diff --git a/src/locales/catalog/hu.json b/src/locales/catalog/hu.json index 0d0bddf02..b282a46e0 100644 --- a/src/locales/catalog/hu.json +++ b/src/locales/catalog/hu.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Vezérli a címkehossz és az érzékelő küszöbértékének dinamikus újrakalibrálását bekapcsolás vagy a médiarekesz kinyitása után.", + "hash": "8f9e3e07", + "summary": "Vezérli a címkehossz és az érzékelő küszöbértékének dinamikus újrakalibrálását bekapcsolás vagy a médiarekesz kinyitása után. Az erősítés-paraméter egy későbbi firmware-hez van bejelentve.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "dinamikus hosszkalibrálás engedélyezése", @@ -3635,6 +3635,11 @@ "meaning": "dinamikus küszöbérték-kalibrálás engedélyezése", "values": "Y engedélyezés, N letiltás", "default": "Y" + }, + { + "meaning": "dinamikus erősítés-kalibrálás engedélyezése", + "values": "Y engedélyezés, N letiltás", + "default": "Y" } ] } diff --git a/src/locales/catalog/it.json b/src/locales/catalog/it.json index 402b5179b..600b41f2d 100644 --- a/src/locales/catalog/it.json +++ b/src/locales/catalog/it.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Controlla la ricalibrazione dinamica della lunghezza dell'etichetta e della soglia del sensore dopo l'accensione o l'apertura del vano supporto.", + "hash": "8f9e3e07", + "summary": "Controlla la ricalibrazione dinamica della lunghezza dell'etichetta e della soglia del sensore dopo l'accensione o l'apertura del vano supporto. Il parametro di guadagno è annunciato per un firmware successivo.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "abilita la calibrazione dinamica della lunghezza", @@ -3635,6 +3635,11 @@ "meaning": "abilita la calibrazione dinamica della soglia", "values": "Y abilita, N disabilita", "default": "Y" + }, + { + "meaning": "abilita la calibrazione dinamica del guadagno", + "values": "Y abilita, N disabilita", + "default": "Y" } ] } diff --git a/src/locales/catalog/ja.json b/src/locales/catalog/ja.json index cb0ee19f9..83a97a657 100644 --- a/src/locales/catalog/ja.json +++ b/src/locales/catalog/ja.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "電源投入後や用紙室を開けた後に、ラベル長とセンサのしきい値を動的に再キャリブレーションするかどうかを制御する。", + "hash": "8f9e3e07", + "summary": "電源投入後や用紙室を開けた後に、ラベル長とセンサのしきい値を動的に再キャリブレーションするかどうかを制御する。 ゲインパラメータは将来のファームウェア向けに予告されている。", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "動的な長さキャリブレーションを有効化", @@ -3635,6 +3635,11 @@ "meaning": "動的なしきい値キャリブレーションを有効化", "values": "Y 有効、N 無効", "default": "Y" + }, + { + "meaning": "動的なゲインキャリブレーションを有効化", + "values": "Y 有効、N 無効", + "default": "Y" } ] } diff --git a/src/locales/catalog/ko.json b/src/locales/catalog/ko.json index 36ffb3731..3f1982d75 100644 --- a/src/locales/catalog/ko.json +++ b/src/locales/catalog/ko.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "전원을 켜거나 용지함을 연 후 라벨 길이와 센서 임계값을 자동으로 다시 보정할지 제어합니다.", + "hash": "8f9e3e07", + "summary": "전원을 켜거나 용지함을 연 후 라벨 길이와 센서 임계값을 자동으로 다시 보정할지 제어합니다. 게인 매개변수는 향후 펌웨어에 제공될 예정으로 공지되어 있습니다.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "동적 길이 보정 활성화", @@ -3635,6 +3635,11 @@ "meaning": "동적 임계값 보정 활성화", "values": "Y 활성화, N 비활성화", "default": "Y" + }, + { + "meaning": "동적 게인 보정 활성화", + "values": "Y 활성화, N 비활성화", + "default": "Y" } ] } diff --git a/src/locales/catalog/lt.json b/src/locales/catalog/lt.json index a64abab6a..c44df4044 100644 --- a/src/locales/catalog/lt.json +++ b/src/locales/catalog/lt.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Valdo dinaminį etiketės ilgio ir jutiklio ribos perkalibravimą po įjungimo arba medijos skyriaus atidarymo.", + "hash": "8f9e3e07", + "summary": "Valdo dinaminį etiketės ilgio ir jutiklio ribos perkalibravimą po įjungimo arba medijos skyriaus atidarymo. Stiprinimo parametras paskelbtas vėlesnei integruotai programinei įrangai.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "įjungia dinaminį ilgio kalibravimą", @@ -3635,6 +3635,11 @@ "meaning": "įjungia dinaminį slenksčio kalibravimą", "values": "Y įjungti, N išjungti", "default": "Y" + }, + { + "meaning": "įjungia dinaminį stiprinimo kalibravimą", + "values": "Y įjungti, N išjungti", + "default": "Y" } ] } diff --git a/src/locales/catalog/lv.json b/src/locales/catalog/lv.json index 36bde4ec0..1bd10f49a 100644 --- a/src/locales/catalog/lv.json +++ b/src/locales/catalog/lv.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Kontrolē etiķetes garuma un sensora robežvērtības dinamisku pārkalibrēšanu pēc ieslēgšanas vai materiāla nodalījuma atvēršanas.", + "hash": "8f9e3e07", + "summary": "Kontrolē etiķetes garuma un sensora robežvērtības dinamisku pārkalibrēšanu pēc ieslēgšanas vai materiāla nodalījuma atvēršanas. Pastiprinājuma parametrs ir paziņots turpmākam aparātprogrammatūras laidienam.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "iespējot dinamisku garuma kalibrēšanu", @@ -3635,6 +3635,11 @@ "meaning": "iespējot dinamisku sliekšņa kalibrēšanu", "values": "Y iespējot, N atspējot", "default": "Y" + }, + { + "meaning": "iespējot dinamisku stiprinājuma kalibrēšanu", + "values": "Y iespējot, N atspējot", + "default": "Y" } ] } diff --git a/src/locales/catalog/nl.json b/src/locales/catalog/nl.json index 33b39cf65..f5f3fd327 100644 --- a/src/locales/catalog/nl.json +++ b/src/locales/catalog/nl.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Regelt dynamische herkalibratie van labellengte en sensordrempel na het inschakelen of het openen van het mediacompartiment.", + "hash": "8f9e3e07", + "summary": "Regelt dynamische herkalibratie van labellengte en sensordrempel na het inschakelen of het openen van het mediacompartiment. De gainparameter is aangekondigd voor een latere firmware.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "dynamische lengtekalibratie inschakelen", @@ -3635,6 +3635,11 @@ "meaning": "dynamische drempelkalibratie inschakelen", "values": "Y inschakelen, N uitschakelen", "default": "Y" + }, + { + "meaning": "dynamische gainkalibratie inschakelen", + "values": "Y inschakelen, N uitschakelen", + "default": "Y" } ] } diff --git a/src/locales/catalog/no.json b/src/locales/catalog/no.json index 0cdb556dc..7788158b9 100644 --- a/src/locales/catalog/no.json +++ b/src/locales/catalog/no.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Styrer dynamisk rekalibrering av etikettlengde og sensorterskel etter oppstart eller åpning av materialrommet.", + "hash": "8f9e3e07", + "summary": "Styrer dynamisk rekalibrering av etikettlengde og sensorterskel etter oppstart eller åpning av materialrommet. Gain-parameteren er annonsert for en senere firmware.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "aktiver dynamisk lengdekalibrering", @@ -3635,6 +3635,11 @@ "meaning": "aktiver dynamisk terskelkalibrering", "values": "Y aktiver, N deaktiver", "default": "Y" + }, + { + "meaning": "aktiver dynamisk gainkalibrering", + "values": "Y aktiver, N deaktiver", + "default": "Y" } ] } diff --git a/src/locales/catalog/pl.json b/src/locales/catalog/pl.json index 993548397..89281aade 100644 --- a/src/locales/catalog/pl.json +++ b/src/locales/catalog/pl.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Steruje dynamiczną rekalibracją długości etykiety i progu czujnika po włączeniu zasilania lub otwarciu komory nośnika.", + "hash": "8f9e3e07", + "summary": "Steruje dynamiczną rekalibracją długości etykiety i progu czujnika po włączeniu zasilania lub otwarciu komory nośnika. Parametr wzmocnienia jest zapowiedziany dla późniejszego firmware.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "włączenie dynamicznej kalibracji długości", @@ -3635,6 +3635,11 @@ "meaning": "włączenie dynamicznej kalibracji progu", "values": "Y włącz, N wyłącz", "default": "Y" + }, + { + "meaning": "włączenie dynamicznej kalibracji wzmocnienia", + "values": "Y włącz, N wyłącz", + "default": "Y" } ] } diff --git a/src/locales/catalog/pt.json b/src/locales/catalog/pt.json index 4e1602f94..da685d686 100644 --- a/src/locales/catalog/pt.json +++ b/src/locales/catalog/pt.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Controla a recalibração dinâmica do comprimento da etiqueta e do limiar do sensor, após ligar a impressora ou abrir o compartimento do suporte.", + "hash": "8f9e3e07", + "summary": "Controla a recalibração dinâmica do comprimento da etiqueta e do limiar do sensor, após ligar a impressora ou abrir o compartimento do suporte. O parâmetro de ganho está anunciado para um firmware posterior.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "ativar calibração dinâmica do comprimento", @@ -3635,6 +3635,11 @@ "meaning": "ativar calibração dinâmica do limiar", "values": "Y habilitar, N desabilitar", "default": "Y" + }, + { + "meaning": "ativar calibração dinâmica do ganho", + "values": "Y habilitar, N desabilitar", + "default": "Y" } ] } diff --git a/src/locales/catalog/ro.json b/src/locales/catalog/ro.json index 10b096d48..06acff39a 100644 --- a/src/locales/catalog/ro.json +++ b/src/locales/catalog/ro.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Controlează recalibrarea dinamică a lungimii etichetei și a pragului senzorului, după pornire sau după deschiderea compartimentului de suport.", + "hash": "8f9e3e07", + "summary": "Controlează recalibrarea dinamică a lungimii etichetei și a pragului senzorului, după pornire sau după deschiderea compartimentului de suport. Parametrul de câștig este anunțat pentru un firmware ulterior.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "activează calibrarea dinamică a lungimii", @@ -3635,6 +3635,11 @@ "meaning": "activează calibrarea dinamică a pragului", "values": "Y activează, N dezactivează", "default": "Y" + }, + { + "meaning": "activează calibrarea dinamică a câștigului", + "values": "Y activează, N dezactivează", + "default": "Y" } ] } diff --git a/src/locales/catalog/sk.json b/src/locales/catalog/sk.json index bacef1d50..50f143f34 100644 --- a/src/locales/catalog/sk.json +++ b/src/locales/catalog/sk.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Riadi dynamickú rekalibráciu dĺžky etikety a prahu senzora po zapnutí alebo otvorení priestoru pre médium.", + "hash": "8f9e3e07", + "summary": "Riadi dynamickú rekalibráciu dĺžky etikety a prahu senzora po zapnutí alebo otvorení priestoru pre médium. Parameter zisku je ohlásený pre neskorší firmware.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "zapnúť dynamickú kalibráciu dĺžky", @@ -3635,6 +3635,11 @@ "meaning": "zapnúť dynamickú kalibráciu prahu", "values": "Y zapnúť, N vypnúť", "default": "Y" + }, + { + "meaning": "zapnúť dynamickú kalibráciu zisku", + "values": "Y zapnúť, N vypnúť", + "default": "Y" } ] } diff --git a/src/locales/catalog/sl.json b/src/locales/catalog/sl.json index 4155856b3..3bccbcecc 100644 --- a/src/locales/catalog/sl.json +++ b/src/locales/catalog/sl.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Nadzoruje dinamično ponovno umerjanje dolžine etikete in praga senzorja po vklopu ali odprtju predala za medij.", + "hash": "8f9e3e07", + "summary": "Nadzoruje dinamično ponovno umerjanje dolžine etikete in praga senzorja po vklopu ali odprtju predala za medij. Parameter ojačanja je napovedan za poznejšo strojno programsko opremo.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "omogoči dinamično umerjanje dolžine", @@ -3635,6 +3635,11 @@ "meaning": "omogoči dinamično umerjanje praga", "values": "Y omogoči, N onemogoči", "default": "Y" + }, + { + "meaning": "omogoči dinamično umerjanje ojačanja", + "values": "Y omogoči, N onemogoči", + "default": "Y" } ] } diff --git a/src/locales/catalog/sr.json b/src/locales/catalog/sr.json index b82b09712..77ccc3446 100644 --- a/src/locales/catalog/sr.json +++ b/src/locales/catalog/sr.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Управља динамичком поновном калибрацијом дужине налепнице и прага сензора после укључивања или отварања одељка за медијум.", + "hash": "8f9e3e07", + "summary": "Управља динамичком поновном калибрацијом дужине налепнице и прага сензора после укључивања или отварања одељка за медијум. Параметар појачања најављен је за будући фирмвер.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "омогући динамичку калибрацију дужине", @@ -3635,6 +3635,11 @@ "meaning": "омогући динамичку калибрацију прага", "values": "Y омогући, N онемогући", "default": "Y" + }, + { + "meaning": "омогући динамичку калибрацију појачања", + "values": "Y омогући, N онемогући", + "default": "Y" } ] } diff --git a/src/locales/catalog/sv.json b/src/locales/catalog/sv.json index a7ba4f897..2334f849f 100644 --- a/src/locales/catalog/sv.json +++ b/src/locales/catalog/sv.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Styr dynamisk omkalibrering av etikettlängd och sensortröskelvärde efter start eller när medielocket öppnats.", + "hash": "8f9e3e07", + "summary": "Styr dynamisk omkalibrering av etikettlängd och sensortröskelvärde efter start eller när medielocket öppnats. Gain-parametern är aviserad för en senare firmware.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "aktivera dynamisk längdkalibrering", @@ -3635,6 +3635,11 @@ "meaning": "aktivera dynamisk tröskelkalibrering", "values": "Y aktivera, N inaktivera", "default": "Y" + }, + { + "meaning": "aktivera dynamisk gainkalibrering", + "values": "Y aktivera, N inaktivera", + "default": "Y" } ] } diff --git a/src/locales/catalog/tr.json b/src/locales/catalog/tr.json index 49366f1b4..4e7510efd 100644 --- a/src/locales/catalog/tr.json +++ b/src/locales/catalog/tr.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "Açılış veya medya bölmesi açıldıktan sonra etiket uzunluğunun ve sensör eşiğinin dinamik yeniden kalibrasyonunu denetler.", + "hash": "8f9e3e07", + "summary": "Açılış veya medya bölmesi açıldıktan sonra etiket uzunluğunun ve sensör eşiğinin dinamik yeniden kalibrasyonunu denetler. Kazanç parametresi daha sonraki bir firmware için duyuruldu.", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "dinamik uzunluk kalibrasyonunu etkinleştir", @@ -3635,6 +3635,11 @@ "meaning": "dinamik eşik kalibrasyonunu etkinleştir", "values": "Y etkinleştir, N devre dışı bırak", "default": "Y" + }, + { + "meaning": "dinamik kazanç kalibrasyonunu etkinleştir", + "values": "Y etkinleştir, N devre dışı bırak", + "default": "Y" } ] } diff --git a/src/locales/catalog/zh-hans.json b/src/locales/catalog/zh-hans.json index b3af05a75..fe3ca647e 100644 --- a/src/locales/catalog/zh-hans.json +++ b/src/locales/catalog/zh-hans.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "控制开机后或介质仓打开后对标签长度和传感器阈值的动态重新校准。", + "hash": "8f9e3e07", + "summary": "控制开机后或介质仓打开后对标签长度和传感器阈值的动态重新校准。 增益参数已为后续固件版本预告。", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "是否启用动态长度校准", @@ -3635,6 +3635,11 @@ "meaning": "是否启用动态阈值校准", "values": "Y 启用,N 禁用", "default": "Y" + }, + { + "meaning": "是否启用动态增益校准", + "values": "Y 启用,N 禁用", + "default": "Y" } ] } diff --git a/src/locales/catalog/zh-hant.json b/src/locales/catalog/zh-hant.json index 82189cf05..cfabaac3e 100644 --- a/src/locales/catalog/zh-hant.json +++ b/src/locales/catalog/zh-hant.json @@ -3621,10 +3621,10 @@ } }, "^XS": { - "hash": "69f3838a", - "summary": "控制開機後或材質艙開啟後,標籤長度與感測器門檻的動態重新校正。", + "hash": "8f9e3e07", + "summary": "控制開機後或材質艙開啟後,標籤長度與感測器門檻的動態重新校正。 增益參數已為後續韌體版本預告。", "reference": { - "hash": "90fbe297", + "hash": "4c3c08cd", "params": [ { "meaning": "是否啟用動態長度校正", @@ -3635,6 +3635,11 @@ "meaning": "是否啟用動態門檻校正", "values": "Y 啟用,N 停用", "default": "Y" + }, + { + "meaning": "是否啟用動態增益校正", + "values": "Y 啟用,N 停用", + "default": "Y" } ] } From 1b3d64bc5a73b13106e9ce774f9bf486a2d8b861 Mon Sep 17 00:00:00 2001 From: u8array Date: Sat, 17 Oct 2026 12:41:30 +0200 Subject: [PATCH 2/5] feat(printer): settings labels take a tooltip and the footer says the setup script is pending --- .../PrinterSettings/PrinterSettingsModal.tsx | 2 +- .../PrinterSettings/zplFieldPrimitives.tsx | 37 +++++++++++++++++-- src/locales/ar.ts | 1 + src/locales/bg.ts | 1 + src/locales/cs.ts | 1 + src/locales/da.ts | 1 + src/locales/de.ts | 1 + src/locales/el.ts | 1 + src/locales/en.ts | 1 + src/locales/es.ts | 1 + src/locales/et.ts | 1 + src/locales/fa.ts | 1 + src/locales/fi.ts | 1 + src/locales/fr.ts | 1 + src/locales/he.ts | 1 + src/locales/hr.ts | 1 + src/locales/hu.ts | 1 + src/locales/it.ts | 1 + src/locales/ja.ts | 1 + src/locales/ko.ts | 1 + src/locales/lt.ts | 1 + src/locales/lv.ts | 1 + src/locales/nl.ts | 1 + src/locales/no.ts | 1 + src/locales/pl.ts | 1 + src/locales/pt.ts | 1 + src/locales/ro.ts | 1 + src/locales/sk.ts | 1 + src/locales/sl.ts | 1 + src/locales/sr.ts | 1 + src/locales/sv.ts | 1 + src/locales/tr.ts | 1 + src/locales/zh-hans.ts | 1 + src/locales/zh-hant.ts | 1 + 34 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/components/PrinterSettings/PrinterSettingsModal.tsx b/src/components/PrinterSettings/PrinterSettingsModal.tsx index 723851486..cc0976e57 100644 --- a/src/components/PrinterSettings/PrinterSettingsModal.tsx +++ b/src/components/PrinterSettings/PrinterSettingsModal.tsx @@ -299,7 +299,7 @@ export function PrinterSettingsModal() {