| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- {
- "page": {
- "notFound": "Service record not found",
- "updated": "Service record updated",
- "failedUpdate": "Failed to update service record",
- "deleteTitle": "Delete Service Record",
- "deleteDescription": "This will permanently delete this service record and all associated data. This cannot be undone.",
- "deleted": "Service record deleted",
- "failedDelete": "Failed to delete",
- "datesExpiredTitle": "Invoice Dates Expired",
- "datesExpiredDescription": "The invoice date or due date has passed. Would you like to update them before proceeding?",
- "datesExpiredUpdate": "Update dates and proceed",
- "datesExpiredProceed": "Proceed without changes",
- "datesExpiredUseToday": "Update to today's date",
- "datesExpiredCustomize": "Choose dates manually",
- "datesExpiredBack": "Back",
- "datesExpiredSetToday": "Set to today",
- "customFieldsInvalid": "Please fill in all required custom fields",
- "customFieldsSaveFailed": "Failed to save custom fields"
- },
- "header": {
- "tabs": {
- "details": "Details",
- "images": "Images",
- "video": "Video",
- "documents": "Documents",
- "statusReports": "Status Reports"
- },
- "save": "Save",
- "pdf": "PDF",
- "email": "Email",
- "share": "Share",
- "notify": "Notify",
- "delete": "Delete",
- "unpaid": "Unpaid",
- "unsavedChanges": "Unsaved changes",
- "saved": "Saved",
- "joinCall": "Join video call"
- },
- "basicInfo": {
- "title": "Basic Information",
- "invoiceDetails": "Invoice Details",
- "customerInfo": "Customer & Vehicle",
- "paid": "Paid",
- "markPaid": "Mark as Paid",
- "markUnpaid": "Mark as Unpaid",
- "vehicle": "Vehicle",
- "open": "Open",
- "customer": "Customer",
- "titleLabel": "Title *",
- "titlePlaceholder": "Oil Change",
- "date": "Date",
- "type": "Type",
- "mileage": "Mileage",
- "mileageMarine": "Engine Hours",
- "status": "Status",
- "technician": "Technician",
- "invoiceNumber": "Invoice Number",
- "invoiceDate": "Invoice Date",
- "invoiceDueDate": "Due Date",
- "typeOptions": {
- "maintenance": "Maintenance",
- "repair": "Repair",
- "upgrade": "Upgrade",
- "inspection": "Inspection"
- },
- "statusOptions": {
- "pending": "Pending",
- "in_progress": "In Progress",
- "waiting_parts": "Waiting Parts",
- "completed": "Completed"
- },
- "searchVehicles": "Search vehicles...",
- "noVehicleFound": "No vehicle found.",
- "techPicker": {
- "placeholder": "Select or type a name...",
- "searchPlaceholder": "Search or type name...",
- "useCustom": "Use \"{search}\"",
- "typePrompt": "Type a name...",
- "boardTechnicians": "Board Technicians",
- "teamMembers": "Team Members"
- },
- "design": "Invoice design",
- "designDefault": "Workshop default",
- "designFollowing": "Default ({name})",
- "designPinned": "The sheet was frozen when the invoice was issued on {date}. A new choice applies only after an owner unlocks the invoice and it is sent again.",
- "designSaved": "Invoice design updated",
- "designFollowingRule": "Default ({name}, {rule})",
- "designRule": {
- "parts_sale": "Parts-Only Sale"
- },
- "designSaveFailed": "Could not change the invoice design"
- },
- "parts": {
- "title": "Parts",
- "fromInventory": "From Inventory",
- "addPart": "Add Part",
- "partNumber": "Part #",
- "name": "Name",
- "qty": "Qty",
- "unitCost": "Cost",
- "unitCostHint": "Vendor cost (internal — not shown to customer)",
- "markupPercent": "Markup %",
- "markupPercentHint": "Markup applied to cost (internal — not shown to customer)",
- "applyMarkup": "Apply {percent}%",
- "applyMarkupHint": "Re-apply {percent}% markup to cost on every row",
- "unitPrice": "Unit Price",
- "total": "Total",
- "namePlaceholder": "Name *",
- "subtotal": "Parts Subtotal: {amount}",
- "inventoryTitle": "Select Part from Inventory",
- "searchInventory": "Search inventory...",
- "inStock": "{quantity} in stock",
- "noInventory": "No inventory parts found.",
- "scanBarcode": "Scan",
- "scanTitle": "Scan Barcode",
- "partFound": "Added \"{name}\" from inventory",
- "partNotFound": "No part found for barcode \"{barcode}\"",
- "deleteRow": "Delete row",
- "outOfStock": "Out of stock",
- "onBackorder": "On backorder ({count})",
- "nameMissingHint": "Rows without a part name are not saved."
- },
- "labor": {
- "title": "Labor & Services",
- "addLabor": "Add Labor",
- "addService": "Add Service",
- "addFinding": "Observation",
- "newObservation": "New Observation",
- "addExisting": "Show Existing ({count})",
- "fromPresets": "From Presets",
- "description": "Description",
- "hours": "Hours",
- "qty": "Qty",
- "qtyOrHours": "Unit / Hours",
- "rate": "Rate ({currency}/hr)",
- "total": "Total",
- "descriptionPlaceholder": "Description *",
- "subtotal": "Labor Subtotal: {amount}",
- "hourlyTag": "HR",
- "serviceTag": "SVC",
- "switchToHourly": "Switch to hourly pricing",
- "switchToService": "Switch to service pricing",
- "switchToHourlyHint": "Hourly: priced by hours worked (hours × rate/hr). Click to switch.",
- "switchToServiceHint": "Service: priced as a flat fee per unit. Click to switch.",
- "deleteRow": "Delete row"
- },
- "totals": {
- "title": "Totals",
- "parts": "Parts",
- "labor": "Labor",
- "subtotal": "Subtotal",
- "subtotalInclTax": "Subtotal (incl. tax)",
- "discount": "Discount",
- "discountNone": "None",
- "discountPercentage": "Percentage",
- "discountFixed": "Fixed",
- "tax": "Tax",
- "taxIncluded": "Tax (incl.)",
- "total": "Total",
- "inclusiveModeHint": "Line item prices are entered with tax included. Totals show the net + tax breakdown.",
- "partsCost": "Parts cost (internal)"
- },
- "notes": {
- "title": "Notes",
- "public": "Public",
- "internal": "Internal",
- "publicPlaceholder": "Notes visible on the invoice...",
- "internalPlaceholder": "Internal notes (not shown on invoice)...",
- "publicHelper": "Shown on the invoice and shared documents",
- "internalHelper": "Only visible to your team",
- "aiWrite": "AI Write",
- "aiGenerated": "AI notes generated successfully",
- "aiGenerateFailed": "Failed to generate AI notes",
- "aiDialogTitle": "AI Write",
- "aiDialogDescription": "AI will analyze the parts and labor in this service record and generate a professional description. The result will be written to the currently selected note type.",
- "aiGenerate": "Generate",
- "aiOverwriteDescription": "The current note already has content. You can replace it or append the AI-generated text below it.",
- "aiOverwriteReplace": "Replace",
- "aiOverwriteAppend": "Append",
- "aiOverwriteCancel": "Cancel",
- "aiDontShowAgain": "Don't show this again"
- },
- "invoice": {
- "title": "Invoice Summary",
- "parts": "Parts",
- "labor": "Labor",
- "subtotal": "Subtotal",
- "subtotalInclTax": "Subtotal (incl. tax)",
- "discount": "Discount",
- "tax": "Tax ({rate}%)",
- "taxIncluded": "Tax (incl., {rate}%)",
- "total": "Total",
- "paid": "Paid",
- "balanceDue": "Balance Due",
- "paidBadge": "PAID",
- "entityLabel": "Invoice",
- "emailSubject": "Payment Confirmation",
- "statusEmailSubject": "Service Status Update",
- "markCompletedTitle": "Mark this invoice as completed?",
- "markCompletedDescription": "It has gone to the customer but is still marked as not finished, so it will keep showing on the work board.",
- "markCompletedConfirm": "Mark completed",
- "lockedFieldsetLabel": "Locked invoice, editing disabled"
- },
- "payments": {
- "title": "Payments",
- "markUnpaid": "Mark as Unpaid",
- "markPaid": "Mark as Paid",
- "recordPayment": "Record Payment",
- "totalPaid": "Total Paid",
- "amount": "Amount",
- "date": "Date",
- "method": "Method",
- "note": "Note",
- "notePlaceholder": "Optional note",
- "savePayment": "Save Payment",
- "methodOptions": {
- "cash": "Cash",
- "card": "Card",
- "transfer": "Transfer",
- "other": "Other"
- },
- "recorded": "Payment recorded",
- "markedPaid": "Marked as paid",
- "markedUnpaid": "Marked as unpaid",
- "deleted": "Payment deleted",
- "failedRecord": "Failed to record payment",
- "failedStatus": "Failed to update payment status",
- "failedDelete": "Failed to delete payment",
- "deleteTitle": "Delete Payment",
- "deleteDescription": "This will remove this payment record.",
- "failedPdf": "Failed to generate PDF invoice"
- },
- "attachments": {
- "deleteTitle": "Delete Attachment",
- "deleteDescription": "This will permanently delete this attachment. This cannot be undone.",
- "deleted": "Attachment deleted",
- "failedDelete": "Failed to delete",
- "images": "Images ({count})",
- "videos": "Videos ({count})",
- "diagnostics": "Diagnostic Reports ({count})",
- "documents": "Documents ({count})",
- "download": "Download",
- "close": "Close"
- },
- "share": {
- "title": "Share Invoice",
- "description": "Generate a public link that allows anyone to view and download this invoice without signing in.",
- "notifyTitle": "Notify {name}",
- "email": "Email",
- "noEmail": "(no email on file)",
- "sms": "SMS",
- "noPhone": "(no phone on file)",
- "sendNotification": "Send Notification",
- "revokeLink": "Revoke Link",
- "generateLink": "Generate Public Link",
- "emailSent": "Email sent",
- "failedEmail": "Failed to send email",
- "smsSent": "SMS sent",
- "failedSms": "Failed to send SMS",
- "copyLink": "Copy link"
- },
- "sidebar": {
- "vehicle": "Vehicle",
- "customer": "Customer",
- "vin": "VIN: {vin}",
- "mileageAtService": "Mileage at service: {mileage} {unit}",
- "engineHoursAtService": "Engine hours at service: {mileage} {unit}",
- "sharedLink": {
- "title": "Shared Link",
- "sharedOn": "Shared on {date}",
- "notViewed": "Not viewed yet",
- "viewedTimes": "Viewed {count, plural, one {# time} other {# times}}",
- "lastViewed": "Last {date}",
- "copyLink": "Copy link",
- "linkCopied": "Link copied"
- }
- },
- "images": {
- "title": "Service Images",
- "dropzone": "Drop images here or click to browse",
- "uploading": "Uploading...",
- "formats": "JPG, PNG, WebP — max 10MB each",
- "uploadingImages": "Uploading images...",
- "limitReached": "Image limit reached ({count}/{max})",
- "upgradePrompt": "Upgrade your plan to upload more images.",
- "onlyAllowed": "Only JPG, PNG, and WebP images are allowed. {names} skipped.",
- "onlyUploading": "Only uploading {count} image(s) to stay within limit.",
- "uploadingCount": "Uploading {count} image(s)...",
- "uploadedCount": "{count} image(s) uploaded",
- "uploadFailed": "Upload failed",
- "deleted": "Image deleted",
- "failedDelete": "Failed to delete image",
- "failedUpdate": "Failed to update",
- "description": "Description...",
- "invoice": "Invoice"
- },
- "videos": {
- "title": "Service Videos",
- "dropzone": "Drop videos here or click to browse",
- "uploading": "Uploading...",
- "formats": "MP4, WebM, MOV — max 10MB each",
- "uploadingVideos": "Uploading videos...",
- "uploadingCount": "Uploading {count} video(s)...",
- "uploadedCount": "{count} video(s) uploaded",
- "uploadFailed": "Upload failed",
- "deleted": "Video deleted",
- "failedDelete": "Failed to delete video",
- "failedUpdate": "Failed to update",
- "invoice": "Invoice"
- },
- "documents": {
- "diagnosticTitle": "Diagnostic Reports",
- "documentsTitle": "Documents",
- "dropzone": "Drop files here or click to browse",
- "uploading": "Uploading...",
- "diagnosticFormats": "PDF, CSV, TXT — max 10MB each",
- "documentFormats": "PDF, DOCX, XLSX, CSV, TXT — max 10MB each",
- "uploadingReports": "Uploading reports...",
- "uploadingDocuments": "Uploading documents...",
- "diagnosticLimitReached": "Diagnostic report limit reached ({count}/{max})",
- "documentLimitReached": "Document limit reached ({count}/{max})",
- "upgradePrompt": "Upgrade your plan to upload more.",
- "diagnosticLabel": "Diagnostic report",
- "documentLabel": "Document",
- "limitReachedToast": "{label} limit reached ({count}/{max}). Upgrade your plan for more.",
- "onlyUploading": "Only uploading {count} file(s) to stay within limit.",
- "uploadingCount": "Uploading {count} file(s)...",
- "uploadedCount": "{count} file(s) uploaded",
- "uploadFailed": "Upload failed",
- "deleted": "File deleted",
- "failedDelete": "Failed to delete file",
- "failedUpdate": "Failed to update",
- "invoice": "Invoice"
- },
- "schedule": {
- "title": "Schedule",
- "date": "Date",
- "startTime": "Start Time",
- "endTime": "End Time",
- "technician": "Technician",
- "selectTechnician": "Select technician...",
- "searchOrCreate": "Search or create technician...",
- "createTechnician": "Create \"{name}\"",
- "creating": "Creating...",
- "failedCreate": "Failed to create technician",
- "addNew": "+ Add New",
- "add": "Add",
- "newTechPlaceholder": "Technician name...",
- "assign": "Assign to Board",
- "assigned": "Assigned to work board",
- "failedAssign": "Failed to assign",
- "endBeforeStart": "End time must be after start time",
- "failedUpdate": "Failed to update schedule times",
- "splitCreated": "Job spans multiple days — continuation created for next day",
- "platformUsers": "Platform Users",
- "customTechnicians": "Custom",
- "readMore": "Read More",
- "setDefaults": "Set Defaults",
- "workBay": "Work bay",
- "selectWorkBay": "Select work bay...",
- "noWorkBay": "No work bay",
- "noTechnician": "No technician",
- "technicians": "Technicians",
- "otherTeamMembers": "Other team members",
- "makeTechnician": "Makes them a technician",
- "addSomeoneNew": "Add someone new",
- "notOnBoard": "Not on the board yet",
- "putOnBoard": "Put on board",
- "slotTaken": "{count, plural, one {This slot is already booked} other {This slot has # clashes}}",
- "anotherJob": "another job",
- "clashTechnician": "the technician is busy",
- "clashBay": "the bay is in use",
- "clashBoth": "both are taken",
- "bookedAnyway": "Saved anyway. Change the time, or pick the next free slot.",
- "pickNextAvailable": "Pick next available slot",
- "findingSlot": "Finding a slot…",
- "slotPicked": "Booked into the next free slot",
- "noSlotFound": "No free slot found in the next few weeks"
- },
- "notifications": {
- "title": "Customer Notifications",
- "viaSms": "via SMS",
- "viaEmail": "via Email",
- "justNow": "Just now",
- "minutesAgo": "{count}m ago",
- "hoursAgo": "{count}h ago",
- "daysAgo": "{count}d ago"
- },
- "table": {
- "warranty": "Warranty"
- },
- "warranty": {
- "title": "Warranty",
- "months": "Duration (months)",
- "mileage": "Mileage Limit",
- "notes": "Warranty Terms",
- "notesPlaceholder": "e.g. 12-month warranty on all parts and labor...",
- "expiresAt": "Expires",
- "presets": {
- "3months": "3 mo",
- "6months": "6 mo",
- "12months": "12 mo",
- "24months": "24 mo"
- },
- "status": {
- "active": "Active",
- "expiring": "Expiring",
- "expired": "Expired",
- "none": "N/A"
- },
- "defaults": {
- "title": "Default Warranty Settings",
- "description": "Set default warranty terms for new service records"
- }
- },
- "concerns": {
- "title": "Customer concerns",
- "addFirst": "Add a customer concern",
- "add": "Add another",
- "placeholder": "There is a noise from the back when I brake",
- "remove": "Remove this concern",
- "notAnswered": "Nothing found against this yet",
- "answered": "{count} finding(s) against this"
- },
- "videoCall": {
- "title": "Video call",
- "none": "No video call on this work order.",
- "needsSchedule": "Set a start time first. The meeting follows the schedule.",
- "add": "Add {provider} meeting",
- "addedHere": "added from this work order",
- "fromCalendar": "from the calendar event",
- "join": "Join",
- "copy": "Copy link",
- "copied": "Link copied",
- "remove": "Remove",
- "removeTitle": "Remove the video call?",
- "removeDescription": "The meeting is deleted at the provider. Anyone who already has the link can no longer join.",
- "created": "Meeting created. The link is on the work order.",
- "removed": "Meeting removed",
- "failed": "Something went wrong",
- "shareHint": "The customer only gets this link when you send it.",
- "shareHintNoChannel": "The customer only gets this link when you send it. No messaging channel is set up, so copy it into a message yourself.",
- "send": {
- "button": "Send to customer",
- "title": "Send the video call link",
- "description": "Send the join link to {name}.",
- "messageLabel": "Note (optional)",
- "messagePlaceholder": "Anything the customer should know before the call...",
- "linkAlwaysIncluded": "The join link is always added below your note.",
- "sms": "SMS",
- "email": "Email",
- "telegram": "Telegram",
- "noPhone": "(no phone)",
- "noEmail": "(no email)",
- "noTelegram": "(no chat linked)",
- "notAvailable": "(not set up)",
- "cancel": "Cancel",
- "send": "Send",
- "sent": "Video call link sent",
- "partlySent": "Sent by {sent}; not by {failed}",
- "failed": "Could not send the link"
- },
- "notify": {
- "invitation": "Hi {name}, your video call about the {vehicle} is on {when}. Join here: {url}",
- "invitationNoTime": "Hi {name}, here is the link for the video call about the {vehicle}: {url}",
- "joinLine": "Join the video call here: {url}",
- "emailSubject": "Video call about your {vehicle}"
- }
- }
- }
|