diff --git a/packages/core/src/lib/qrFd.ts b/packages/core/src/lib/qrFd.ts index 2f3d8dbb..46f69860 100644 --- a/packages/core/src/lib/qrFd.ts +++ b/packages/core/src/lib/qrFd.ts @@ -77,6 +77,12 @@ function joinSegments(payload: string, manual: boolean, mixed: boolean, utf8: bo return out.join(''); } +/** Payload start in a ^BQ field, after the switch or the three bytes qrFdToModel drops. Manual-mode segments count as payload. */ +export function qrFdPayloadStart(fd: string): number { + const m = QR_FD_SWITCHES.exec(fd); + return m ? m[0].length - (m[4]?.length ?? 0) : Math.min(3, fd.length); +} + export interface QrFdParse { errorCorrection: QrEcLevel; content: string; diff --git a/src/components/Output/ZplCodeMirror.tsx b/src/components/Output/ZplCodeMirror.tsx index 964af899..b2322061 100644 --- a/src/components/Output/ZplCodeMirror.tsx +++ b/src/components/Output/ZplCodeMirror.tsx @@ -17,6 +17,7 @@ import { zpl, blobRanges, commandAtCursor, commandInsertion, placesCaret, points import { toDiagnostic } from '../../lib/zplCmLint'; import { hideSidecarsExt, visibleLineNumber } from '../../lib/zplCmSidecars'; import { commandMarksExt } from '../../lib/zplCmCommandMarks'; +import { blankFieldsExt } from '../../lib/zplCmBlankFields'; import { crlfIndex, isPureCrlf, minimalSplice, toDocPos } from '../../lib/sourceOffsets'; // Text.toString() always joins with LF; only sliceString honours the @@ -78,6 +79,7 @@ const theme = EditorView.theme({ outlineOffset: '-1px', borderRadius: '2px', }, + '.cm-zplBlankHint': { opacity: '0.45', fontStyle: 'italic', userSelect: 'none', WebkitUserSelect: 'none' }, // CM's base theme paints the tooltip for a light host (no `dark` declared // here), and the pane itself is surface-2: without the app's token plus // elevation the popup reads as text pasted onto the code. @@ -125,10 +127,11 @@ const NO_LINES: ReadonlySet = new Set(); const readOnlyExt = (ro: boolean) => [EditorState.readOnly.of(ro), EditorView.editable.of(!ro)]; const highlightExt = (lines: ReadonlySet) => EditorView.decorations.of((v) => highlightDecorations(v.state, lines)); -// One compartment: both are locale strings that change on the same event. -const localeExt = (ariaLabel: string, placeholderText: string) => [ +// One compartment: the three strings change together, on a locale switch or the preview lock. +const localeExt = (ariaLabel: string, placeholderText: string, blankFieldHint: string | undefined) => [ EditorView.contentAttributes.of({ 'aria-label': ariaLabel }), placeholder(placeholderText), + blankFieldsExt(blankFieldHint), ]; function useCompartmentSync(viewRef: RefObject, compartment: Compartment, build: (value: T) => Extension, value: T): void { @@ -187,6 +190,7 @@ export default function ZplCodeMirror({ onChange, ariaLabel, placeholderText, + blankFieldHint, readOnly = false, highlightLines = NO_LINES, historyEpoch = 0, @@ -203,6 +207,8 @@ export default function ZplCodeMirror({ ariaLabel: string; /** Shown while the doc is empty (authoring a label from scratch). */ placeholderText: string; + /** Inlay label on every empty ^FD or ^FV slot, none when absent. */ + blankFieldHint?: string; readOnly?: boolean; /** 0-based doc lines tinted as the canvas selection's emitted source. */ highlightLines?: ReadonlySet; @@ -281,7 +287,7 @@ export default function ZplCodeMirror({ highlightCompartment.of(highlightExt(highlightLines)), sidecarCompartment.of(hideSidecarsExt(hideSidecars)), commandMarksCompartment.of(commandMarksExt(catalogRow)), - localeCompartment.of(localeExt(ariaLabel, placeholderText)), + localeCompartment.of(localeExt(ariaLabel, placeholderText, blankFieldHint)), // lintKeymap opens the diagnostics panel, the keyboard's only route to a repair action. keymap.of([{ key: 'Escape', run: () => onEscapeRef.current?.() ?? false }, ...defaultKeymap, ...historyKeymap, ...foldKeymap, ...lintKeymap]), EditorView.updateListener.of((u) => { @@ -336,9 +342,9 @@ export default function ZplCodeMirror({ const view = viewRef.current; if (!view) return; view.dispatch({ - effects: localeCompartment.reconfigure(localeExt(ariaLabel, placeholderText)), + effects: localeCompartment.reconfigure(localeExt(ariaLabel, placeholderText, blankFieldHint)), }); - }, [ariaLabel, placeholderText, localeCompartment]); + }, [ariaLabel, placeholderText, blankFieldHint, localeCompartment]); const mountEpoch = useRef(historyEpoch); useEffect(() => { diff --git a/src/components/Output/ZplSourceEditor.tsx b/src/components/Output/ZplSourceEditor.tsx index 7a9f51b3..9897c5d1 100644 --- a/src/components/Output/ZplSourceEditor.tsx +++ b/src/components/Output/ZplSourceEditor.tsx @@ -108,6 +108,7 @@ export function ZplSourceEditor({ highlightLines={highlightedLines} historyEpoch={historyEpoch} placeholderText={t.output.editSourcePlaceholder} + blankFieldHint={readOnly ? undefined : t.output.blankFieldHint} diagnostics={diagnostics} hideSidecars={hideSidecars} insertPage={insertPage} diff --git a/src/lib/zplCmBlankFields.test.ts b/src/lib/zplCmBlankFields.test.ts new file mode 100644 index 00000000..958d8837 --- /dev/null +++ b/src/lib/zplCmBlankFields.test.ts @@ -0,0 +1,90 @@ +// @vitest-environment jsdom +import { describe, it, expect, afterEach } from "vitest"; +import { EditorView } from "@codemirror/view"; +import { EditorState } from "@codemirror/state"; +import { zpl } from "./zplLanguage"; +import { blankFieldsExt } from "./zplCmBlankFields"; + +let view: EditorView | null = null; +afterEach(() => { + view?.destroy(); + view = null; +}); + +function open(doc: string, hint?: string): EditorView { + view = new EditorView({ state: EditorState.create({ doc, extensions: [zpl(), blankFieldsExt(hint)] }), parent: document.body }); + return view; +} + +/** Document offsets carrying the hint. */ +function hints(v: EditorView): number[] { + const out: number[] = []; + for (const deco of v.state.facet(EditorView.decorations)) { + (typeof deco === "function" ? deco(v) : deco).between(0, v.state.doc.length, (from, _to, value) => { + if ((value.spec.widget as { text?: string } | undefined)?.text === "placeholder") out.push(from); + }); + } + return out; +} + +/** The offset right after the n-th `needle`. */ +const after = (doc: string, needle: string, n = 1): number => { + let at = -1; + for (let i = 0; i < n; i++) at = doc.indexOf(needle, at + 1); + return at + needle.length; +}; + +describe("blankFieldsExt", () => { + it("labels an empty field right after its ^FD and leaves a filled one alone", () => { + const doc = "^XA\n^FO10,10^BCN,100^FD^FS\n^FO10,80^A0N,30^FDHELLO^FS\n^XZ"; + const v = open(doc, "placeholder"); + expect(hints(v)).toEqual([after(doc, "^FD")]); + expect(v.dom.querySelector(".cm-zplBlankHint")?.textContent).toBe("placeholder"); + expect(v.state.doc.toString()).not.toContain("placeholder"); + }); + + it("skips a slot the printer fills through ^FN, armed, or bound after the data", () => { + expect(hints(open("^XA\n^FO10,10^FN1^FD^FS\n^FO10,80^FN2^FH_^FD^FS\n^FO10,90^FD^FN3^FS\n^XZ", "placeholder"))).toEqual([]); + }); + + it("treats a line break as the nothing the printer prints, and labels ^FV like ^FD", () => { + const v = open("^XA\n^FO1,1^FD\n^FS\n^FO1,9^FV^FS\n^FO1,9^FD ^FS\n^XZ", "placeholder"); + const doc = v.state.doc.toString(); + expect(hints(v)).toEqual([after(doc, "^FD"), after(doc, "^FV")]); + }); + + it("looks the field up in the tree, not in the visible slice", () => { + const doc = "^XA\n^FO10,10\n^FN1\n^FD^FS\n^XZ"; + const v = open(doc, "placeholder"); + Object.defineProperty(v, "visibleRanges", { get: () => [{ from: doc.indexOf("^FD"), to: doc.length }] }); + expect(hints(v)).toEqual([]); + }); + + it("puts the QR label after the switch, whichever form it takes", () => { + const doc = "^XA\n^FO1,1^BQN,2,4^FDQA,^FS\n^FO1,9^BQN,2,4^FDD030122,QM,^FS\n^FO1,9^BQN,2,4^FDQA,hi^FS\n^XZ"; + expect(hints(open(doc, "placeholder"))).toEqual([after(doc, "QA,"), after(doc, "QM,")]); + }); + + it("follows a ^CC remap", () => { + const doc = "^XA^CC#\n#FO10,10#FD#FS\n#XZ"; + expect(hints(open(doc, "placeholder"))).toEqual([after(doc, "#FD")]); + }); + + it("labels a field that runs to the end of the document, and reads CRLF text", () => { + const v = open("^XA\r\n^FO1,1^FD^FS\r\n^FO1,9^FD", "placeholder"); + const doc = v.state.doc.toString(); + expect(hints(v)).toEqual([after(doc, "^FD"), after(doc, "^FD", 2)]); + }); + + it("clears only the label that is typed into", () => { + const doc = "^XA\n^FO10,10^FD^FS\n^FO10,80^FD^FS\n^XZ"; + const v = open(doc, "placeholder"); + expect(hints(v)).toHaveLength(2); + v.dispatch({ changes: { from: after(doc, "^FD"), insert: "A" }, userEvent: "input.type" }); + expect(hints(v)).toEqual([after(doc, "^FD", 2) + 1]); + }); + + it("labels nothing without a hint text", () => { + expect(hints(open("^XA^FO1,1^FD^FS^XZ"))).toEqual([]); + }); +}); diff --git a/src/lib/zplCmBlankFields.ts b/src/lib/zplCmBlankFields.ts new file mode 100644 index 00000000..588dbc5c --- /dev/null +++ b/src/lib/zplCmBlankFields.ts @@ -0,0 +1,77 @@ +import { RangeSetBuilder, type EditorState, type Extension } from '@codemirror/state'; +import { Decoration, EditorView, WidgetType, type DecorationSet } from '@codemirror/view'; +import { syntaxTree } from '@codemirror/language'; +import type { SyntaxNode } from '@lezer/common'; +import { qrFdPayloadStart } from '@zplab/core/lib/qrFd'; +import { stripDataLineBreaks } from '@zplab/core/lib/zplParser/helpers'; +import { commandName, commandOccurrences } from './zplLanguage'; + +class HintWidget extends WidgetType { + readonly text: string; + constructor(text: string) { + super(); + this.text = text; + } + eq(other: HintWidget): boolean { + return other.text === this.text; + } + toDOM(): HTMLElement { + const span = document.createElement('span'); + span.className = 'cm-zplBlankHint'; + span.textContent = this.text; + return span; + } + /** A click on the label places the caret beside it, as on text. */ + ignoreEvent(): boolean { + return false; + } +} + +const DATA_COMMANDS = new Set(['^FD', '^FV']); + +/** Commands that bound a field: the search for its ^FN and ^BQ stops here. */ +const FIELD_BOUNDARY = new Set(['^FO', '^FT', '^FS', '^XA', '^XZ']); + +/** The command ids sharing the field of `node`, in either direction. */ +function* fieldCommands(state: EditorState, node: SyntaxNode): Generator { + for (const step of ['prevSibling', 'nextSibling'] as const) { + for (let sibling = node[step]; sibling; sibling = sibling[step]) { + const id = commandName(state, sibling.firstChild); + if (id === null) continue; + if (FIELD_BOUNDARY.has(id)) break; + yield id; + } + } +} + +/** Where the empty data slot of the data command `node` begins, or null when the field is filled or the printer fills it. */ +function blankSlot(state: EditorState, node: SyntaxNode, dataFrom: number): number | null { + const ids = [...fieldCommands(state, node)]; + if (ids.includes('^FN')) return null; + // A line break is the one byte the printer drops from field data. + const data = stripDataLineBreaks(state.sliceDoc(dataFrom, node.to)); + const start = ids.includes('^BQ') ? qrFdPayloadStart(data) : 0; + return start === data.length ? dataFrom + start : null; +} + +function blankHints(view: EditorView, widget: HintWidget): DecorationSet { + const builder = new RangeSetBuilder(); + const decoration = Decoration.widget({ widget, side: 1 }); + const tree = syntaxTree(view.state); + for (const { from, to } of view.visibleRanges) { + for (const occurrence of commandOccurrences(view.state, from, to)) { + if (!DATA_COMMANDS.has(occurrence.id)) continue; + const node = tree.resolveInner(occurrence.from, 1).parent; + const at = node ? blankSlot(view.state, node, occurrence.to) : null; + if (at !== null && at >= from && at <= to) builder.add(at, at, decoration); + } + } + return builder.finish(); +} + +/** Labels every empty ^FD or ^FV slot with `hint`, read from the text, so typing into a slot clears its label. */ +export function blankFieldsExt(hint: string | undefined): Extension { + if (hint === undefined) return []; + const widget = new HintWidget(hint); + return EditorView.decorations.of((v) => blankHints(v, widget)); +} diff --git a/src/lib/zplLanguage.ts b/src/lib/zplLanguage.ts index 107bf0f0..3867e1ab 100644 --- a/src/lib/zplLanguage.ts +++ b/src/lib/zplLanguage.ts @@ -279,6 +279,11 @@ function readCommandName(state: EditorState, token: SyntaxNodeRef): { id: string return { id: `${token.name === "TildeCmdName" ? "~" : "^"}${name}`, name }; } +/** The canonical id of a command's name node, or null for any other node. */ +export function commandName(state: EditorState, node: SyntaxNodeRef | null): string | null { + return node && NAME_NODES.has(node.name) ? readCommandName(state, node).id : null; +} + /** The command whose bytes surround `pos`, or null between commands; the command * starting at the caret wins over the one ending there. */ export function commandAtCursor(state: EditorState, pos: number): CaretCommand | null { diff --git a/src/locales/ar.ts b/src/locales/ar.ts index 6e18bea8..14fdb73f 100644 --- a/src/locales/ar.ts +++ b/src/locales/ar.ts @@ -994,6 +994,7 @@ const ar = { catalogNo: 'لا', catalogNoCursor: 'ضع المؤشر على أمر لمعرفة وظيفته.', catalogNoMatch: 'لا توجد أوامر تطابق البحث.', + blankFieldHint: 'عنصر نائب', catalogDismissed: 'تم إخفاء المرجع. انقر على الأمر في الكود لإظهاره مرة أخرى.', catalogNoEntryFmt: '{cmd} غير موجود في المرجع.', copy: 'نسخ', diff --git a/src/locales/bg.ts b/src/locales/bg.ts index ce6a3c2c..4ef6a710 100644 --- a/src/locales/bg.ts +++ b/src/locales/bg.ts @@ -994,6 +994,7 @@ const bg = { catalogNo: 'не', catalogNoCursor: 'Поставете курсора върху команда, за да видите какво прави.', catalogNoMatch: 'Няма команди, отговарящи на търсенето.', + blankFieldHint: 'запазено място', catalogDismissed: 'Справката е скрита. Щракнете върху командата в кода, за да я покажете отново.', catalogNoEntryFmt: '{cmd} не е в справката.', copy: 'Копирай', diff --git a/src/locales/cs.ts b/src/locales/cs.ts index 484f26c6..e5e9770f 100644 --- a/src/locales/cs.ts +++ b/src/locales/cs.ts @@ -994,6 +994,7 @@ const cs = { catalogNo: 'ne', catalogNoCursor: 'Umístěte kurzor na příkaz a zobrazí se jeho popis.', catalogNoMatch: 'Žádné příkazy neodpovídají hledání.', + blankFieldHint: 'zástupný text', catalogDismissed: 'Reference je skrytá. Klikněte na příkaz v kódu a znovu se zobrazí.', catalogNoEntryFmt: '{cmd} není v referenci.', copy: 'Kopírovat', diff --git a/src/locales/da.ts b/src/locales/da.ts index 014d6af3..6e984394 100644 --- a/src/locales/da.ts +++ b/src/locales/da.ts @@ -994,6 +994,7 @@ const da = { catalogNo: 'nej', catalogNoCursor: 'Placer markøren på en kommando for at se, hvad den gør.', catalogNoMatch: 'Ingen kommandoer matcher søgningen.', + blankFieldHint: 'pladsholder', catalogDismissed: 'Referencen er skjult. Klik på kommandoen i koden for at vise den igen.', catalogNoEntryFmt: '{cmd} findes ikke i referencen.', copy: 'Kopiér', diff --git a/src/locales/de.ts b/src/locales/de.ts index 7e13ce2d..33e39df3 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -1024,6 +1024,7 @@ const de = { catalogNo: 'nein', catalogNoCursor: 'Cursor auf einen Befehl setzen, um seine Funktion zu sehen.', catalogNoMatch: 'Keine Befehle passen zur Suche.', + blankFieldHint: 'Platzhalter', catalogDismissed: 'Referenz ausgeblendet. Auf den Befehl im Code klicken, um sie wieder einzublenden.', catalogNoEntryFmt: '{cmd} steht nicht in der Referenz.', copy: 'Kopieren', diff --git a/src/locales/el.ts b/src/locales/el.ts index 0602bcf0..6d901f6a 100644 --- a/src/locales/el.ts +++ b/src/locales/el.ts @@ -994,6 +994,7 @@ const el = { catalogNo: 'όχι', catalogNoCursor: 'Τοποθετήστε τον δρομέα σε μια εντολή για να δείτε τι κάνει.', catalogNoMatch: 'Καμία εντολή δεν ταιριάζει με την αναζήτηση.', + blankFieldHint: 'δεσμευτικό θέσης', catalogDismissed: 'Η αναφορά είναι κρυμμένη. Κάντε κλικ στην εντολή στον κώδικα για να εμφανιστεί ξανά.', catalogNoEntryFmt: '{cmd} δεν υπάρχει στην αναφορά.', copy: 'Αντιγραφή', diff --git a/src/locales/en.ts b/src/locales/en.ts index 32805d82..5f93f89e 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -1024,6 +1024,7 @@ const en = { catalogNo: 'no', catalogNoCursor: 'Place the cursor on a command to see what it does.', catalogNoMatch: 'No commands match the search.', + blankFieldHint: 'placeholder', catalogDismissed: 'Reference hidden. Click the command in the code to show it again.', catalogNoEntryFmt: '{cmd} is not in the reference.', copy: 'Copy', diff --git a/src/locales/es.ts b/src/locales/es.ts index a8754cbf..87f4b8a6 100644 --- a/src/locales/es.ts +++ b/src/locales/es.ts @@ -994,6 +994,7 @@ const es = { catalogNo: 'no', catalogNoCursor: 'Coloca el cursor sobre un comando para ver qué hace.', catalogNoMatch: 'Ningún comando coincide con la búsqueda.', + blankFieldHint: 'marcador de posición', catalogDismissed: 'Referencia oculta. Haz clic en el comando del código para volver a mostrarla.', catalogNoEntryFmt: '{cmd} no está en la referencia.', copy: 'Copiar', diff --git a/src/locales/et.ts b/src/locales/et.ts index 002a2988..91991cf3 100644 --- a/src/locales/et.ts +++ b/src/locales/et.ts @@ -994,6 +994,7 @@ const et = { catalogNo: 'ei', catalogNoCursor: 'Aseta kursor käsule, et näha, mida see teeb.', catalogNoMatch: 'Otsingule ei vasta ükski käsk.', + blankFieldHint: 'kohahoidja', catalogDismissed: 'Teatmik on peidetud. Klõpsa koodis käsul, et seda uuesti näidata.', catalogNoEntryFmt: '{cmd} ei ole teatmikus.', copy: 'Kopeeri', diff --git a/src/locales/fa.ts b/src/locales/fa.ts index 9cdd6461..d9f9f34f 100644 --- a/src/locales/fa.ts +++ b/src/locales/fa.ts @@ -994,6 +994,7 @@ const fa = { catalogNo: 'خیر', catalogNoCursor: 'مکان‌نما را روی یک دستور قرار دهید تا عملکرد آن را ببینید.', catalogNoMatch: 'هیچ دستوری با جستجو مطابقت ندارد.', + blankFieldHint: 'جای‌نگه‌دار', catalogDismissed: 'مرجع پنهان شد. در کد روی دستور کلیک کنید تا دوباره نمایش داده شود.', catalogNoEntryFmt: '{cmd} در مرجع نیست.', copy: 'کپی', diff --git a/src/locales/fi.ts b/src/locales/fi.ts index cc5e4197..d9a85028 100644 --- a/src/locales/fi.ts +++ b/src/locales/fi.ts @@ -994,6 +994,7 @@ const fi = { catalogNo: 'ei', catalogNoCursor: 'Aseta kohdistin komentoon nähdäksesi, mitä se tekee.', catalogNoMatch: 'Mikään komento ei vastaa hakua.', + blankFieldHint: 'paikkamerkki', catalogDismissed: 'Viiteopas on piilotettu. Napsauta komentoa koodissa, niin se tulee taas näkyviin.', catalogNoEntryFmt: '{cmd} ei ole viiteoppaassa.', copy: 'Kopioi', diff --git a/src/locales/fr.ts b/src/locales/fr.ts index c249ded3..653274ba 100644 --- a/src/locales/fr.ts +++ b/src/locales/fr.ts @@ -994,6 +994,7 @@ const fr = { catalogNo: 'non', catalogNoCursor: "Placez le curseur sur une commande pour voir ce qu'elle fait.", catalogNoMatch: 'Aucune commande ne correspond à la recherche.', + blankFieldHint: 'espace réservé', catalogDismissed: "Référence masquée. Cliquez sur la commande dans le code pour l'afficher à nouveau.", catalogNoEntryFmt: '{cmd} ne figure pas dans la référence.', copy: 'Copier', diff --git a/src/locales/he.ts b/src/locales/he.ts index e145a6ae..4b204737 100644 --- a/src/locales/he.ts +++ b/src/locales/he.ts @@ -994,6 +994,7 @@ const he = { catalogNo: 'לא', catalogNoCursor: 'הנח את הסמן מעל פקודה כדי לראות מה היא עושה.', catalogNoMatch: 'אין פקודות התואמות את החיפוש.', + blankFieldHint: 'ממלא מקום', catalogDismissed: 'המדריך מוסתר. לחץ על הפקודה בקוד כדי להציג אותו שוב.', catalogNoEntryFmt: '{cmd} לא נמצא במדריך.', copy: 'העתק', diff --git a/src/locales/hr.ts b/src/locales/hr.ts index 05fc5cbf..bcdcd9fc 100644 --- a/src/locales/hr.ts +++ b/src/locales/hr.ts @@ -994,6 +994,7 @@ const hr = { catalogNo: 'ne', catalogNoCursor: 'Postavite pokazivač na naredbu da vidite što radi.', catalogNoMatch: 'Nijedna naredba ne odgovara pretrazi.', + blankFieldHint: 'rezervirano mjesto', catalogDismissed: 'Referenca je skrivena. Kliknite naredbu u kodu da je ponovno prikažete.', catalogNoEntryFmt: '{cmd} nije u referenci.', copy: 'Kopiraj', diff --git a/src/locales/hu.ts b/src/locales/hu.ts index 732a89d1..20aacff9 100644 --- a/src/locales/hu.ts +++ b/src/locales/hu.ts @@ -994,6 +994,7 @@ const hu = { catalogNo: 'nem', catalogNoCursor: 'Helyezze a kurzort egy parancsra, hogy lássa, mit csinál.', catalogNoMatch: 'Nincs a keresésnek megfelelő parancs.', + blankFieldHint: 'helyőrző', catalogDismissed: 'A referencia rejtve van. Kattintson a parancsra a kódban, hogy újra megjelenjen.', catalogNoEntryFmt: '{cmd} nincs a referenciában.', copy: 'Másolás', diff --git a/src/locales/it.ts b/src/locales/it.ts index a0b4bdfd..96606d76 100644 --- a/src/locales/it.ts +++ b/src/locales/it.ts @@ -994,6 +994,7 @@ const it = { catalogNo: 'no', catalogNoCursor: 'Posiziona il cursore su un comando per vedere cosa fa.', catalogNoMatch: 'Nessun comando corrisponde alla ricerca.', + blankFieldHint: 'segnaposto', catalogDismissed: 'Riferimento nascosto. Fai clic sul comando nel codice per mostrarlo di nuovo.', catalogNoEntryFmt: '{cmd} non è nel riferimento.', copy: 'Copia', diff --git a/src/locales/ja.ts b/src/locales/ja.ts index 4a9cb667..35e59168 100644 --- a/src/locales/ja.ts +++ b/src/locales/ja.ts @@ -994,6 +994,7 @@ const ja = { catalogNo: 'いいえ', catalogNoCursor: 'コマンドにカーソルを合わせると内容が表示されます。', catalogNoMatch: '検索に一致するコマンドがありません。', + blankFieldHint: 'プレースホルダー', catalogDismissed: 'リファレンスを非表示にしました。コード内のコマンドをクリックすると再表示されます。', catalogNoEntryFmt: '{cmd} はリファレンスにありません。', copy: 'コピー', diff --git a/src/locales/ko.ts b/src/locales/ko.ts index 4e9134d4..54b9f5a5 100644 --- a/src/locales/ko.ts +++ b/src/locales/ko.ts @@ -994,6 +994,7 @@ const ko = { catalogNo: '아니요', catalogNoCursor: '명령어에 커서를 놓으면 기능을 확인할 수 있습니다.', catalogNoMatch: '검색과 일치하는 명령이 없습니다.', + blankFieldHint: '자리 표시자', catalogDismissed: '참조를 숨겼습니다. 코드에서 명령어를 클릭하면 다시 표시됩니다.', catalogNoEntryFmt: '{cmd} 명령은 참조에 없습니다.', copy: '복사', diff --git a/src/locales/lt.ts b/src/locales/lt.ts index 4fd406d3..04489ef3 100644 --- a/src/locales/lt.ts +++ b/src/locales/lt.ts @@ -994,6 +994,7 @@ const lt = { catalogNo: 'ne', catalogNoCursor: 'Užveskite žymeklį ant komandos, kad pamatytumėte, ką ji daro.', catalogNoMatch: 'Nė viena komanda neatitinka paieškos.', + blankFieldHint: 'vietaženklis', catalogDismissed: 'Žinynas paslėptas. Spustelėkite komandą kode, kad jis vėl būtų rodomas.', catalogNoEntryFmt: 'Komandos {cmd} žinyne nėra.', copy: 'Kopijuoti', diff --git a/src/locales/lv.ts b/src/locales/lv.ts index b563048b..3ba645ea 100644 --- a/src/locales/lv.ts +++ b/src/locales/lv.ts @@ -994,6 +994,7 @@ const lv = { catalogNo: 'nē', catalogNoCursor: 'Novietojiet kursoru uz komandas, lai redzētu, ko tā dara.', catalogNoMatch: 'Neviena komanda neatbilst meklēšanai.', + blankFieldHint: 'vietturis', catalogDismissed: 'Uzziņas ir paslēptas. Noklikšķiniet uz komandas kodā, lai tās atkal parādītu.', catalogNoEntryFmt: 'Komanda {cmd} uzziņās nav atrodama.', copy: 'Kopēt', diff --git a/src/locales/nl.ts b/src/locales/nl.ts index bc3c90fe..2532347a 100644 --- a/src/locales/nl.ts +++ b/src/locales/nl.ts @@ -994,6 +994,7 @@ const nl = { catalogNo: 'nee', catalogNoCursor: 'Plaats de cursor op een opdracht om te zien wat deze doet.', catalogNoMatch: 'Geen opdrachten komen overeen met de zoekopdracht.', + blankFieldHint: 'tijdelijke aanduiding', catalogDismissed: 'Referentie verborgen. Klik op de opdracht in de code om deze weer te tonen.', catalogNoEntryFmt: '{cmd} staat niet in de referentie.', copy: 'Kopiëren', diff --git a/src/locales/no.ts b/src/locales/no.ts index 10ec4dd5..020a124e 100644 --- a/src/locales/no.ts +++ b/src/locales/no.ts @@ -994,6 +994,7 @@ const no = { catalogNo: 'nei', catalogNoCursor: 'Plasser markøren på en kommando for å se hva den gjør.', catalogNoMatch: 'Ingen kommandoer samsvarer med søket.', + blankFieldHint: 'plassholder', catalogDismissed: 'Referansen er skjult. Klikk på kommandoen i koden for å vise den igjen.', catalogNoEntryFmt: '{cmd} finnes ikke i referansen.', copy: 'Kopier', diff --git a/src/locales/pl.ts b/src/locales/pl.ts index ebc47eb2..4ad57ace 100644 --- a/src/locales/pl.ts +++ b/src/locales/pl.ts @@ -994,6 +994,7 @@ const pl = { catalogNo: 'nie', catalogNoCursor: 'Ustaw kursor na poleceniu, aby zobaczyć, co ono robi.', catalogNoMatch: 'Żadne polecenie nie pasuje do wyszukiwania.', + blankFieldHint: 'symbol zastępczy', catalogDismissed: 'Dokumentacja jest ukryta. Kliknij polecenie w kodzie, aby wyświetlić ją ponownie.', catalogNoEntryFmt: 'Polecenia {cmd} nie ma w dokumentacji.', copy: 'Kopiuj', diff --git a/src/locales/pt.ts b/src/locales/pt.ts index 7a6ce91d..5c429805 100644 --- a/src/locales/pt.ts +++ b/src/locales/pt.ts @@ -994,6 +994,7 @@ const pt = { catalogNo: 'não', catalogNoCursor: 'Posicione o cursor sobre um comando para ver o que ele faz.', catalogNoMatch: 'Nenhum comando corresponde à pesquisa.', + blankFieldHint: 'marcador de posição', catalogDismissed: 'Referência oculta. Clique no comando do código para mostrá-la novamente.', catalogNoEntryFmt: '{cmd} não está na referência.', copy: 'Copiar', diff --git a/src/locales/ro.ts b/src/locales/ro.ts index 3f7fba0c..da97977b 100644 --- a/src/locales/ro.ts +++ b/src/locales/ro.ts @@ -994,6 +994,7 @@ const ro = { catalogNo: 'nu', catalogNoCursor: 'Poziționați cursorul pe o comandă pentru a vedea ce face.', catalogNoMatch: 'Nicio comandă nu corespunde căutării.', + blankFieldHint: 'substituent', catalogDismissed: 'Referința este ascunsă. Faceți clic pe comanda din cod pentru a o afișa din nou.', catalogNoEntryFmt: '{cmd} nu se află în referință.', copy: 'Copiați', diff --git a/src/locales/sk.ts b/src/locales/sk.ts index d084181c..77744683 100644 --- a/src/locales/sk.ts +++ b/src/locales/sk.ts @@ -994,6 +994,7 @@ const sk = { catalogNo: 'nie', catalogNoCursor: 'Umiestnite kurzor na príkaz a zobrazí sa jeho popis.', catalogNoMatch: 'Žiadne príkazy nezodpovedajú vyhľadávaniu.', + blankFieldHint: 'zástupný symbol', catalogDismissed: 'Referencia je skrytá. Kliknite na príkaz v kóde a znova sa zobrazí.', catalogNoEntryFmt: '{cmd} nie je v referencii.', copy: 'Kopírovať', diff --git a/src/locales/sl.ts b/src/locales/sl.ts index fd06aeee..c3acc6fb 100644 --- a/src/locales/sl.ts +++ b/src/locales/sl.ts @@ -994,6 +994,7 @@ const sl = { catalogNo: 'ne', catalogNoCursor: 'Postavite kazalec na ukaz, da vidite, kaj počne.', catalogNoMatch: 'Noben ukaz ne ustreza iskanju.', + blankFieldHint: 'rezervirano mesto', catalogDismissed: 'Referenca je skrita. Kliknite ukaz v kodi, da jo znova prikažete.', catalogNoEntryFmt: '{cmd} ni v referenci.', copy: 'Kopiraj', diff --git a/src/locales/sr.ts b/src/locales/sr.ts index 85932fac..923aa8cb 100644 --- a/src/locales/sr.ts +++ b/src/locales/sr.ts @@ -994,6 +994,7 @@ const sr = { catalogNo: 'не', catalogNoCursor: 'Postavite kursor na komandu da vidite šta ona radi.', catalogNoMatch: 'Nijedna komanda ne odgovara pretrazi.', + blankFieldHint: 'rezervisano mesto', catalogDismissed: 'Referenca je sakrivena. Kliknite komandu u kodu da je ponovo prikažete.', catalogNoEntryFmt: '{cmd} nije u referenci.', copy: 'Kopiraj', diff --git a/src/locales/sv.ts b/src/locales/sv.ts index f1705241..b59788d0 100644 --- a/src/locales/sv.ts +++ b/src/locales/sv.ts @@ -994,6 +994,7 @@ const sv = { catalogNo: 'nej', catalogNoCursor: 'Placera markören på ett kommando för att se vad det gör.', catalogNoMatch: 'Inga kommandon matchar sökningen.', + blankFieldHint: 'platshållare', catalogDismissed: 'Referensen är dold. Klicka på kommandot i koden för att visa den igen.', catalogNoEntryFmt: '{cmd} finns inte i referensen.', copy: 'Kopiera', diff --git a/src/locales/tr.ts b/src/locales/tr.ts index 0ffd5154..bf001ed8 100644 --- a/src/locales/tr.ts +++ b/src/locales/tr.ts @@ -994,6 +994,7 @@ const tr = { catalogNo: 'hayır', catalogNoCursor: 'Ne yaptığını görmek için imleci bir komutun üzerine getirin.', catalogNoMatch: 'Aramayla eşleşen komut yok.', + blankFieldHint: 'yer tutucu', catalogDismissed: 'Referans gizlendi. Tekrar göstermek için kodda komuta tıklayın.', catalogNoEntryFmt: '{cmd} referansta yok.', copy: 'Kopyala', diff --git a/src/locales/zh-hans.ts b/src/locales/zh-hans.ts index 5785b214..2e697ba0 100644 --- a/src/locales/zh-hans.ts +++ b/src/locales/zh-hans.ts @@ -994,6 +994,7 @@ const zhHans = { catalogNo: '否', catalogNoCursor: '将光标放在命令上可查看其作用。', catalogNoMatch: '没有匹配搜索的命令。', + blankFieldHint: '占位符', catalogDismissed: '参考已隐藏。点击代码中的命令可再次显示。', catalogNoEntryFmt: '{cmd} 不在参考中。', copy: '复制', diff --git a/src/locales/zh-hant.ts b/src/locales/zh-hant.ts index eeea5d4b..4c4cc7ca 100644 --- a/src/locales/zh-hant.ts +++ b/src/locales/zh-hant.ts @@ -994,6 +994,7 @@ const zhHant = { catalogNo: '否', catalogNoCursor: '將游標放在命令上可查看其作用。', catalogNoMatch: '沒有符合搜尋的指令。', + blankFieldHint: '佔位符', catalogDismissed: '參考已隱藏。點選程式碼中的指令可再次顯示。', catalogNoEntryFmt: '{cmd} 不在參考中。', copy: '複製',