service.json 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. {
  2. "page": {
  3. "notFound": "Service record not found",
  4. "updated": "Service record updated",
  5. "failedUpdate": "Failed to update service record",
  6. "deleteTitle": "Delete Service Record",
  7. "deleteDescription": "This will permanently delete this service record and all associated data. This cannot be undone.",
  8. "deleted": "Service record deleted",
  9. "failedDelete": "Failed to delete",
  10. "datesExpiredTitle": "Invoice Dates Expired",
  11. "datesExpiredDescription": "The invoice date or due date has passed. Would you like to update them before proceeding?",
  12. "datesExpiredUpdate": "Update dates and proceed",
  13. "datesExpiredProceed": "Proceed without changes",
  14. "datesExpiredUseToday": "Update to today's date",
  15. "datesExpiredCustomize": "Choose dates manually",
  16. "datesExpiredBack": "Back",
  17. "datesExpiredSetToday": "Set to today",
  18. "customFieldsInvalid": "Please fill in all required custom fields",
  19. "customFieldsSaveFailed": "Failed to save custom fields",
  20. "problems": {
  21. "title": "The job needs a title before it can be saved.",
  22. "negative": "Quantities, hours, prices and costs cannot be negative.",
  23. "partName": "Every priced part needs a name.",
  24. "laborDescription": "Every labour line with hours or a rate needs a description."
  25. }
  26. },
  27. "header": {
  28. "tabs": {
  29. "details": "Details",
  30. "images": "Images",
  31. "video": "Video",
  32. "documents": "Documents",
  33. "statusReports": "Status Reports"
  34. },
  35. "save": "Save",
  36. "pdf": "PDF",
  37. "email": "Email",
  38. "share": "Share",
  39. "notify": "Notify",
  40. "delete": "Delete",
  41. "unpaid": "Unpaid",
  42. "unsavedChanges": "Unsaved changes",
  43. "saved": "Saved",
  44. "joinCall": "Join video call"
  45. },
  46. "basicInfo": {
  47. "title": "Basic Information",
  48. "invoiceDetails": "Invoice Details",
  49. "customerInfo": "Customer & Vehicle",
  50. "paid": "Paid",
  51. "markPaid": "Mark as Paid",
  52. "markUnpaid": "Mark as Unpaid",
  53. "vehicle": "Vehicle",
  54. "open": "Open",
  55. "customer": "Customer",
  56. "titleLabel": "Title *",
  57. "titlePlaceholder": "Oil Change",
  58. "date": "Date",
  59. "type": "Type",
  60. "mileage": "Mileage",
  61. "mileageMarine": "Engine Hours",
  62. "status": "Status",
  63. "technician": "Technician",
  64. "invoiceNumber": "Invoice Number",
  65. "invoiceDate": "Invoice Date",
  66. "invoiceDueDate": "Due Date",
  67. "typeOptions": {
  68. "maintenance": "Maintenance",
  69. "repair": "Repair",
  70. "upgrade": "Upgrade",
  71. "inspection": "Inspection"
  72. },
  73. "statusOptions": {
  74. "pending": "Pending",
  75. "in_progress": "In Progress",
  76. "waiting_parts": "Waiting Parts",
  77. "completed": "Completed"
  78. },
  79. "searchVehicles": "Search vehicles...",
  80. "noVehicleFound": "No vehicle found.",
  81. "techPicker": {
  82. "placeholder": "Select or type a name...",
  83. "searchPlaceholder": "Search or type name...",
  84. "useCustom": "Use \"{search}\"",
  85. "typePrompt": "Type a name...",
  86. "boardTechnicians": "Board Technicians",
  87. "teamMembers": "Team Members"
  88. },
  89. "design": "Invoice design",
  90. "designDefault": "Workshop default",
  91. "designFollowing": "Default ({name})",
  92. "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.",
  93. "designSaved": "Invoice design updated",
  94. "designFollowingRule": "Default ({name}, {rule})",
  95. "designRule": {
  96. "parts_sale": "Parts-Only Sale"
  97. },
  98. "designSaveFailed": "Could not change the invoice design"
  99. },
  100. "parts": {
  101. "title": "Parts",
  102. "fromInventory": "From Inventory",
  103. "addPart": "Add Part",
  104. "partNumber": "Part #",
  105. "name": "Name",
  106. "qty": "Qty",
  107. "unitCost": "Cost",
  108. "unitCostHint": "Vendor cost (internal — not shown to customer)",
  109. "markupPercent": "Markup %",
  110. "markupPercentHint": "Markup applied to cost (internal — not shown to customer)",
  111. "applyMarkup": "Apply {percent}%",
  112. "applyMarkupHint": "Re-apply {percent}% markup to cost on every row",
  113. "unitPrice": "Unit Price",
  114. "total": "Total",
  115. "namePlaceholder": "Name *",
  116. "subtotal": "Parts Subtotal: {amount}",
  117. "inventoryTitle": "Select Part from Inventory",
  118. "searchInventory": "Search inventory...",
  119. "inStock": "{quantity} in stock",
  120. "noInventory": "No inventory parts found.",
  121. "scanBarcode": "Scan",
  122. "scanTitle": "Scan Barcode",
  123. "partFound": "Added \"{name}\" from inventory",
  124. "partNotFound": "No part found for barcode \"{barcode}\"",
  125. "deleteRow": "Delete row",
  126. "outOfStock": "Out of stock",
  127. "onBackorder": "On backorder ({count})",
  128. "nameMissingHint": "Rows without a part name are not saved."
  129. },
  130. "labor": {
  131. "title": "Labor & Services",
  132. "addLabor": "Add Labor",
  133. "addService": "Add Service",
  134. "addFinding": "Observation",
  135. "newObservation": "New Observation",
  136. "addExisting": "Show Existing ({count})",
  137. "fromPresets": "From Presets",
  138. "description": "Description",
  139. "hours": "Hours",
  140. "qty": "Qty",
  141. "qtyOrHours": "Unit / Hours",
  142. "rate": "Rate ({currency}/hr)",
  143. "total": "Total",
  144. "descriptionPlaceholder": "Description *",
  145. "subtotal": "Labor Subtotal: {amount}",
  146. "hourlyTag": "HR",
  147. "serviceTag": "SVC",
  148. "switchToHourly": "Switch to hourly pricing",
  149. "switchToService": "Switch to service pricing",
  150. "switchToHourlyHint": "Hourly: priced by hours worked (hours × rate/hr). Click to switch.",
  151. "switchToServiceHint": "Service: priced as a flat fee per unit. Click to switch.",
  152. "deleteRow": "Delete row",
  153. "descriptionMissingHint": "Rows without a description are not saved."
  154. },
  155. "totals": {
  156. "title": "Totals",
  157. "parts": "Parts",
  158. "labor": "Labor",
  159. "subtotal": "Subtotal",
  160. "subtotalInclTax": "Subtotal (incl. tax)",
  161. "discount": "Discount",
  162. "discountNone": "None",
  163. "discountPercentage": "Percentage",
  164. "discountFixed": "Fixed",
  165. "tax": "Tax",
  166. "taxIncluded": "Tax (incl.)",
  167. "total": "Total",
  168. "inclusiveModeHint": "Line item prices are entered with tax included. Totals show the net + tax breakdown.",
  169. "partsCost": "Parts cost (internal)"
  170. },
  171. "notes": {
  172. "title": "Notes",
  173. "public": "Public",
  174. "internal": "Internal",
  175. "publicPlaceholder": "Notes visible on the invoice...",
  176. "internalPlaceholder": "Internal notes (not shown on invoice)...",
  177. "publicHelper": "Shown on the invoice and shared documents",
  178. "internalHelper": "Only visible to your team",
  179. "aiWrite": "AI Write",
  180. "aiGenerated": "AI notes generated successfully",
  181. "aiGenerateFailed": "Failed to generate AI notes",
  182. "aiDialogTitle": "AI Write",
  183. "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.",
  184. "aiGenerate": "Generate",
  185. "aiOverwriteDescription": "The current note already has content. You can replace it or append the AI-generated text below it.",
  186. "aiOverwriteReplace": "Replace",
  187. "aiOverwriteAppend": "Append",
  188. "aiOverwriteCancel": "Cancel",
  189. "aiDontShowAgain": "Don't show this again"
  190. },
  191. "invoice": {
  192. "title": "Invoice Summary",
  193. "parts": "Parts",
  194. "labor": "Labor",
  195. "subtotal": "Subtotal",
  196. "subtotalInclTax": "Subtotal (incl. tax)",
  197. "discount": "Discount",
  198. "tax": "Tax ({rate}%)",
  199. "taxIncluded": "Tax (incl., {rate}%)",
  200. "total": "Total",
  201. "paid": "Paid",
  202. "balanceDue": "Balance Due",
  203. "paidBadge": "PAID",
  204. "entityLabel": "Invoice",
  205. "emailSubject": "Payment Confirmation",
  206. "statusEmailSubject": "Service Status Update",
  207. "markCompletedTitle": "Mark this invoice as completed?",
  208. "markCompletedDescription": "It has gone to the customer but is still marked as not finished, so it will keep showing on the work board.",
  209. "markCompletedConfirm": "Mark completed",
  210. "lockedFieldsetLabel": "Locked invoice, editing disabled"
  211. },
  212. "payments": {
  213. "title": "Payments",
  214. "markUnpaid": "Mark as Unpaid",
  215. "markPaid": "Mark as Paid",
  216. "recordPayment": "Record Payment",
  217. "totalPaid": "Total Paid",
  218. "amount": "Amount",
  219. "date": "Date",
  220. "method": "Method",
  221. "note": "Note",
  222. "notePlaceholder": "Optional note",
  223. "savePayment": "Save Payment",
  224. "methodOptions": {
  225. "cash": "Cash",
  226. "card": "Card",
  227. "transfer": "Transfer",
  228. "other": "Other"
  229. },
  230. "recorded": "Payment recorded",
  231. "markedPaid": "Marked as paid",
  232. "markedUnpaid": "Marked as unpaid",
  233. "deleted": "Payment deleted",
  234. "failedRecord": "Failed to record payment",
  235. "failedStatus": "Failed to update payment status",
  236. "failedDelete": "Failed to delete payment",
  237. "deleteTitle": "Delete Payment",
  238. "deleteDescription": "This will remove this payment record.",
  239. "failedPdf": "Failed to generate PDF invoice"
  240. },
  241. "attachments": {
  242. "deleteTitle": "Delete Attachment",
  243. "deleteDescription": "This will permanently delete this attachment. This cannot be undone.",
  244. "deleted": "Attachment deleted",
  245. "failedDelete": "Failed to delete",
  246. "images": "Images ({count})",
  247. "videos": "Videos ({count})",
  248. "diagnostics": "Diagnostic Reports ({count})",
  249. "documents": "Documents ({count})",
  250. "download": "Download",
  251. "close": "Close"
  252. },
  253. "share": {
  254. "title": "Share Invoice",
  255. "description": "Generate a public link that allows anyone to view and download this invoice without signing in.",
  256. "notifyTitle": "Notify {name}",
  257. "email": "Email",
  258. "noEmail": "(no email on file)",
  259. "sms": "SMS",
  260. "noPhone": "(no phone on file)",
  261. "sendNotification": "Send Notification",
  262. "revokeLink": "Revoke Link",
  263. "generateLink": "Generate Public Link",
  264. "emailSent": "Email sent",
  265. "failedEmail": "Failed to send email",
  266. "smsSent": "SMS sent",
  267. "failedSms": "Failed to send SMS",
  268. "copyLink": "Copy link"
  269. },
  270. "sidebar": {
  271. "vehicle": "Vehicle",
  272. "customer": "Customer",
  273. "vin": "VIN: {vin}",
  274. "mileageAtService": "Mileage at service: {mileage} {unit}",
  275. "engineHoursAtService": "Engine hours at service: {mileage} {unit}",
  276. "sharedLink": {
  277. "title": "Shared Link",
  278. "sharedOn": "Shared on {date}",
  279. "notViewed": "Not viewed yet",
  280. "viewedTimes": "Viewed {count, plural, one {# time} other {# times}}",
  281. "lastViewed": "Last {date}",
  282. "copyLink": "Copy link",
  283. "linkCopied": "Link copied"
  284. }
  285. },
  286. "images": {
  287. "title": "Service Images",
  288. "dropzone": "Drop images here or click to browse",
  289. "uploading": "Uploading...",
  290. "formats": "JPG, PNG, WebP — max 10MB each",
  291. "uploadingImages": "Uploading images...",
  292. "limitReached": "Image limit reached ({count}/{max})",
  293. "upgradePrompt": "Upgrade your plan to upload more images.",
  294. "onlyAllowed": "Only JPG, PNG, and WebP images are allowed. {names} skipped.",
  295. "onlyUploading": "Only uploading {count} image(s) to stay within limit.",
  296. "uploadingCount": "Uploading {count} image(s)...",
  297. "uploadedCount": "{count} image(s) uploaded",
  298. "uploadFailed": "Upload failed",
  299. "deleted": "Image deleted",
  300. "failedDelete": "Failed to delete image",
  301. "failedUpdate": "Failed to update",
  302. "description": "Description...",
  303. "invoice": "Invoice"
  304. },
  305. "videos": {
  306. "title": "Service Videos",
  307. "dropzone": "Drop videos here or click to browse",
  308. "uploading": "Uploading...",
  309. "formats": "MP4, WebM, MOV — max 10MB each",
  310. "uploadingVideos": "Uploading videos...",
  311. "uploadingCount": "Uploading {count} video(s)...",
  312. "uploadedCount": "{count} video(s) uploaded",
  313. "uploadFailed": "Upload failed",
  314. "deleted": "Video deleted",
  315. "failedDelete": "Failed to delete video",
  316. "failedUpdate": "Failed to update",
  317. "invoice": "Invoice"
  318. },
  319. "documents": {
  320. "diagnosticTitle": "Diagnostic Reports",
  321. "documentsTitle": "Documents",
  322. "dropzone": "Drop files here or click to browse",
  323. "uploading": "Uploading...",
  324. "diagnosticFormats": "PDF, CSV, TXT — max 10MB each",
  325. "documentFormats": "PDF, DOCX, XLSX, CSV, TXT — max 10MB each",
  326. "uploadingReports": "Uploading reports...",
  327. "uploadingDocuments": "Uploading documents...",
  328. "diagnosticLimitReached": "Diagnostic report limit reached ({count}/{max})",
  329. "documentLimitReached": "Document limit reached ({count}/{max})",
  330. "upgradePrompt": "Upgrade your plan to upload more.",
  331. "diagnosticLabel": "Diagnostic report",
  332. "documentLabel": "Document",
  333. "limitReachedToast": "{label} limit reached ({count}/{max}). Upgrade your plan for more.",
  334. "onlyUploading": "Only uploading {count} file(s) to stay within limit.",
  335. "uploadingCount": "Uploading {count} file(s)...",
  336. "uploadedCount": "{count} file(s) uploaded",
  337. "uploadFailed": "Upload failed",
  338. "deleted": "File deleted",
  339. "failedDelete": "Failed to delete file",
  340. "failedUpdate": "Failed to update",
  341. "invoice": "Invoice"
  342. },
  343. "schedule": {
  344. "title": "Schedule",
  345. "date": "Date",
  346. "startTime": "Start Time",
  347. "endTime": "End Time",
  348. "technician": "Technician",
  349. "selectTechnician": "Select technician...",
  350. "searchOrCreate": "Search or create technician...",
  351. "createTechnician": "Create \"{name}\"",
  352. "creating": "Creating...",
  353. "failedCreate": "Failed to create technician",
  354. "addNew": "+ Add New",
  355. "add": "Add",
  356. "newTechPlaceholder": "Technician name...",
  357. "assign": "Assign to Board",
  358. "assigned": "Assigned to work board",
  359. "failedAssign": "Failed to assign",
  360. "endBeforeStart": "End time must be after start time",
  361. "failedUpdate": "Failed to update schedule times",
  362. "splitCreated": "Job spans multiple days — continuation created for next day",
  363. "platformUsers": "Platform Users",
  364. "customTechnicians": "Custom",
  365. "readMore": "Read More",
  366. "setDefaults": "Set Defaults",
  367. "workBay": "Work bay",
  368. "selectWorkBay": "Select work bay...",
  369. "noWorkBay": "No work bay",
  370. "noTechnician": "No technician",
  371. "technicians": "Technicians",
  372. "otherTeamMembers": "Other team members",
  373. "makeTechnician": "Makes them a technician",
  374. "addSomeoneNew": "Add someone new",
  375. "notOnBoard": "Not on the board yet",
  376. "putOnBoard": "Put on board",
  377. "slotTaken": "{count, plural, one {This slot is already booked} other {This slot has # clashes}}",
  378. "anotherJob": "another job",
  379. "clashTechnician": "the technician is busy",
  380. "clashBay": "the bay is in use",
  381. "clashBoth": "both are taken",
  382. "bookedAnyway": "Saved anyway. Change the time, or pick the next free slot.",
  383. "pickNextAvailable": "Pick next available slot",
  384. "findingSlot": "Finding a slot…",
  385. "slotPicked": "Booked into the next free slot",
  386. "noSlotFound": "No free slot found in the next few weeks"
  387. },
  388. "notifications": {
  389. "title": "Customer Notifications",
  390. "viaSms": "via SMS",
  391. "viaEmail": "via Email",
  392. "justNow": "Just now",
  393. "minutesAgo": "{count}m ago",
  394. "hoursAgo": "{count}h ago",
  395. "daysAgo": "{count}d ago"
  396. },
  397. "table": {
  398. "warranty": "Warranty"
  399. },
  400. "warranty": {
  401. "title": "Warranty",
  402. "months": "Duration (months)",
  403. "mileage": "Mileage Limit",
  404. "notes": "Warranty Terms",
  405. "notesPlaceholder": "e.g. 12-month warranty on all parts and labor...",
  406. "expiresAt": "Expires",
  407. "presets": {
  408. "3months": "3 mo",
  409. "6months": "6 mo",
  410. "12months": "12 mo",
  411. "24months": "24 mo"
  412. },
  413. "status": {
  414. "active": "Active",
  415. "expiring": "Expiring",
  416. "expired": "Expired",
  417. "none": "N/A"
  418. },
  419. "defaults": {
  420. "title": "Default Warranty Settings",
  421. "description": "Set default warranty terms for new service records"
  422. }
  423. },
  424. "concerns": {
  425. "title": "Customer concerns",
  426. "addFirst": "Add a customer concern",
  427. "add": "Add another",
  428. "placeholder": "There is a noise from the back when I brake",
  429. "remove": "Remove this concern",
  430. "notAnswered": "Nothing found against this yet",
  431. "answered": "{count} finding(s) against this"
  432. },
  433. "videoCall": {
  434. "title": "Video call",
  435. "none": "No video call on this work order.",
  436. "needsSchedule": "Set a start time first. The meeting follows the schedule.",
  437. "add": "Add {provider} meeting",
  438. "addedHere": "added from this work order",
  439. "fromCalendar": "from the calendar event",
  440. "join": "Join",
  441. "copy": "Copy link",
  442. "copied": "Link copied",
  443. "remove": "Remove",
  444. "removeTitle": "Remove the video call?",
  445. "removeDescription": "The meeting is deleted at the provider. Anyone who already has the link can no longer join.",
  446. "created": "Meeting created. The link is on the work order.",
  447. "removed": "Meeting removed",
  448. "failed": "Something went wrong",
  449. "shareHint": "The customer only gets this link when you send it.",
  450. "shareHintNoChannel": "The customer only gets this link when you send it. No messaging channel is set up, so copy it into a message yourself.",
  451. "send": {
  452. "button": "Send to customer",
  453. "title": "Send the video call link",
  454. "description": "Send the join link to {name}.",
  455. "messageLabel": "Note (optional)",
  456. "messagePlaceholder": "Anything the customer should know before the call...",
  457. "linkAlwaysIncluded": "The join link is always added below your note.",
  458. "sms": "SMS",
  459. "email": "Email",
  460. "telegram": "Telegram",
  461. "noPhone": "(no phone)",
  462. "noEmail": "(no email)",
  463. "noTelegram": "(no chat linked)",
  464. "notAvailable": "(not set up)",
  465. "cancel": "Cancel",
  466. "send": "Send",
  467. "sent": "Video call link sent",
  468. "partlySent": "Sent by {sent}; not by {failed}",
  469. "failed": "Could not send the link"
  470. },
  471. "notify": {
  472. "invitation": "Hi {name}, your video call about the {vehicle} is on {when}. Join here: {url}",
  473. "invitationNoTime": "Hi {name}, here is the link for the video call about the {vehicle}: {url}",
  474. "joinLine": "Join the video call here: {url}",
  475. "emailSubject": "Video call about your {vehicle}"
  476. }
  477. }
  478. }