feat(labels): the Label Designer — QSO and address labels for paper QSL
The designer's data model lives in internal/labels: STOCKS are the physical roll in the printer (geometry in mm, margins, dpi — seeded with the common Brother DK sizes, the QL family being what prompted the feature), TEMPLATES are one design each, of two kinds: the QSO label glued on the card, whose repeating table carries several contacts of the same station, and the address label for the envelope, whose lines collapse when a variable is empty. Everything is measured in millimetres — labels are sold in mm, and an operator lining a design up against a physical sticker thinks in mm; pixels exist only in the renderer, at the stock's dpi. The canvas renderer is shared between the editor's preview and the future print path, so there is no second implementation for the preview to disagree with. The preview is fed with the log's latest contacts rather than lorem ipsum: real data shows a too-narrow column immediately. Printing (PDF, one page per label at exact size) is the next module; nothing here prints yet.
This commit is contained in:
@@ -131,6 +131,28 @@ const en: Dict = {
|
||||
'wk.catWarnTci': 'The CW keyer is set to the radio, but the CAT backend is "{backend}". Pick TCI in Settings → CAT, or another keying engine.',
|
||||
'wk.tciHint': "Keying goes through the radio's own macro keyer, over the link already open — no WinKeyer and no second serial port. The radio can stop a message but cannot un-type one, so there is no type-ahead correction here.",
|
||||
'gen.miles': 'Distances in miles', 'gen.milesHint': '(instead of kilometres)',
|
||||
'tools.labelDesigner': "Label Designer…",
|
||||
'lbl.title': "Label Designer",
|
||||
'lbl.newQso': "QSO label", 'lbl.newAddr': "Address label",
|
||||
'lbl.newQsoName': "QSO label", 'lbl.newAddrName': "Address label",
|
||||
'lbl.kindQso': "QSO label", 'lbl.kindAddr': "Address label",
|
||||
'lbl.namePh': "Template name", 'lbl.forProfile': "this profile only",
|
||||
'lbl.save': "Save", 'lbl.delete': "Delete", 'lbl.setDefault': "Use as the default for its kind",
|
||||
'lbl.empty': "No label yet — create a QSO label for the card, an address label for the envelope.",
|
||||
'lbl.intro': "Design the labels for your paper QSL work: the QSO label glued on the card, the address labels for the envelope. Pick a saved design on the left or create one.",
|
||||
'lbl.stocks': "Label sizes", 'lbl.pickStock': "Pick a size to edit…", 'lbl.newStock': "New size",
|
||||
'lbl.customStock': "Custom label", 'lbl.saveStock': "Save size", 'lbl.noStock': "Define a label size first.",
|
||||
'lbl.widthMm': "Width mm", 'lbl.heightMm': "Height mm", 'lbl.stock': "Label",
|
||||
'lbl.addText': "Text", 'lbl.addLine': "Line", 'lbl.addAddr': "Address block", 'lbl.addTable': "QSO table",
|
||||
'lbl.removeEl': "Remove element", 'lbl.newText': "New text",
|
||||
'lbl.selectHint': "Click an element on the label to edit it; drag to move it. Positions are in millimetres, snapped to 0.5 mm.",
|
||||
'lbl.el_text': "Text", 'lbl.el_line': "Line", 'lbl.el_qso_table': "QSO table", 'lbl.el_addr_block': "Address block",
|
||||
'lbl.text': "Text", 'lbl.insertVar': "Insert a variable…",
|
||||
'lbl.alignLeft': "Left", 'lbl.alignCenter': "Center", 'lbl.alignRight': "Right",
|
||||
'lbl.thickness': "Thickness mm",
|
||||
'lbl.addrLines': "Address lines", 'lbl.addrHint': "One line each; a line whose variables are empty is skipped.",
|
||||
'lbl.lineGap': "Gap mm",
|
||||
'lbl.rows': "Rows", 'lbl.rowH': "Row mm", 'lbl.header': "Header row", 'lbl.columns': "Columns", 'lbl.addColumn': "Add column",
|
||||
'qslm.thStation': 'Station',
|
||||
'qslm.qrzTitle': 'Open this callsign on QRZ.com',
|
||||
'qslm.lotwDetail': 'QSL details',
|
||||
@@ -632,6 +654,28 @@ const fr: Dict = {
|
||||
'wk.catWarnTci': "Le manipulateur CW est réglé sur la radio, mais le backend CAT est « {backend} ». Choisissez TCI dans Réglages → CAT, ou un autre moteur de manipulation.",
|
||||
'wk.tciHint': "La manipulation passe par le keyer à macros de la radio, sur la liaison déjà ouverte — ni WinKeyer ni second port série. La radio sait interrompre un message mais pas en effacer la fin, donc pas de correction en frappe anticipée ici.",
|
||||
'gen.miles': 'Distances en miles', 'gen.milesHint': '(au lieu des kilomètres)',
|
||||
'tools.labelDesigner': "Créateur d'étiquettes…",
|
||||
'lbl.title': "Créateur d'étiquettes",
|
||||
'lbl.newQso': "Étiquette QSO", 'lbl.newAddr': "Étiquette adresse",
|
||||
'lbl.newQsoName': "Étiquette QSO", 'lbl.newAddrName': "Étiquette adresse",
|
||||
'lbl.kindQso': "Étiquette QSO", 'lbl.kindAddr': "Étiquette adresse",
|
||||
'lbl.namePh': "Nom du modèle", 'lbl.forProfile': "ce profil seulement",
|
||||
'lbl.save': "Enregistrer", 'lbl.delete': "Supprimer", 'lbl.setDefault': "Modèle par défaut pour son type",
|
||||
'lbl.empty': "Aucune étiquette — créez une étiquette QSO pour la carte, une étiquette adresse pour l'enveloppe.",
|
||||
'lbl.intro': "Dessinez les étiquettes de vos QSL papier : l'étiquette QSO collée sur la carte, les étiquettes adresse pour l'enveloppe. Choisissez un modèle à gauche ou créez-en un.",
|
||||
'lbl.stocks': "Formats d'étiquette", 'lbl.pickStock': "Choisir un format à modifier…", 'lbl.newStock': "Nouveau format",
|
||||
'lbl.customStock': "Étiquette personnalisée", 'lbl.saveStock': "Enregistrer le format", 'lbl.noStock': "Définissez d'abord un format d'étiquette.",
|
||||
'lbl.widthMm': "Largeur mm", 'lbl.heightMm': "Hauteur mm", 'lbl.stock': "Étiquette",
|
||||
'lbl.addText': "Texte", 'lbl.addLine': "Trait", 'lbl.addAddr': "Bloc adresse", 'lbl.addTable': "Tableau QSO",
|
||||
'lbl.removeEl': "Supprimer l'élément", 'lbl.newText': "Nouveau texte",
|
||||
'lbl.selectHint': "Cliquez un élément de l'étiquette pour le modifier ; glissez pour le déplacer. Positions en millimètres, au demi-millimètre.",
|
||||
'lbl.el_text': "Texte", 'lbl.el_line': "Trait", 'lbl.el_qso_table': "Tableau QSO", 'lbl.el_addr_block': "Bloc adresse",
|
||||
'lbl.text': "Texte", 'lbl.insertVar': "Insérer une variable…",
|
||||
'lbl.alignLeft': "Gauche", 'lbl.alignCenter': "Centré", 'lbl.alignRight': "Droite",
|
||||
'lbl.thickness': "Épaisseur mm",
|
||||
'lbl.addrLines': "Lignes d'adresse", 'lbl.addrHint': "Une ligne par ligne ; une ligne dont les variables sont vides est sautée.",
|
||||
'lbl.lineGap': "Interligne mm",
|
||||
'lbl.rows': "Lignes", 'lbl.rowH': "Ligne mm", 'lbl.header': "Ligne d'en-tête", 'lbl.columns': "Colonnes", 'lbl.addColumn': "Ajouter une colonne",
|
||||
'qslm.thStation': 'Station',
|
||||
'qslm.qrzTitle': 'Ouvrir cet indicatif sur QRZ.com',
|
||||
'qslm.lotwDetail': 'Détails QSL',
|
||||
|
||||
Reference in New Issue
Block a user