polish: rebrand to Fleet Ops, add trilingual i18n, adaptive demo guide, and UX overhaul

Rebrands the product from MobilityOps to Fleet Ops across the UI, backend defaults and
knowledge base, and makes nl-BE/en-GB/fr-BE full first-class languages: i18next with
eager-bundled per-namespace resources, a persisted accessible language switcher (topbar
and mobile drawer), locale-aware date/number formatting, and a coverage test that fails
the build on any missing or empty translation key.

Backend dynamic content (demo scenarios, blocked-reason text, integration status) moves
from fixed English/Dutch prose to stable message codes + params so the frontend can
localize it; the demo knowledge base gains a fully translated NL/EN/FR procedure corpus
(11 documents each) with per-language retrieval and localized evidence-state messages.

The Demo Guide becomes breakpoint-adaptive: a docked rail on extra-wide desktop, a
floating panel that auto-collapses to a persistent, closable progress chip on standard
desktop/tablet, and a collapsed/half/full bottom sheet on mobile -- with scroll+focus+
highlight on "go to this step", Escape handling, and reduced-motion support.

The Data Quality Workbench gets accessible choice-card decisions with a clear primary/
secondary/tertiary action hierarchy; the Automation ledger groups repeated successes and
uses meaningful short refs; the Audit trail groups events by correlation id with human
action labels and readable before/after diffs. Attention Queue, Today's movements,
Vehicles, Bookings and Data Quality rows are fully clickable (stretched-link pattern)
with independent secondary links, keyboard support and mobile touch targets.

Fixes a topbar overflow on mobile caused by the new language switcher (moved into the
mobile drawer at <=960px) and two dangling aria-labelledby references introduced this
session. Updates all affected Playwright specs for the new nl-BE default and the new
Audit/DemoGuide DOM structure, and adds new i18n-coverage, demo-guide-adaptive and
clickable-rows specs. 131 backend tests, Ruff and mypy, and 71 Playwright tests pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
NuklearRabbit
2026-08-03 18:33:22 +02:00
co-authored by Claude Sonnet 5
parent 257a4cf6c0
commit 337f8716bb
127 changed files with 5529 additions and 1287 deletions
@@ -0,0 +1,7 @@
{
"openRow": "Open: {{label}}",
"reducedMotion": "Reduced motion active",
"closeDialog": "Close dialog",
"expandSection": "Expand section",
"collapseSection": "Collapse section"
}
@@ -0,0 +1,64 @@
{
"eyebrow": "Assure / Immutable history",
"title": "Audit trail",
"description": "Trace important state changes, actors and correlation references.",
"actionFilterLabel": "Action",
"actionFilterPlaceholder": "e.g. demo_login",
"managerOnly": "The audit trail is visible to Operations Managers only.",
"managerOnlyDetail": "Audit history is visible to Operations Managers only.",
"loading": "Loading audit trail…",
"unavailable": "Audit trail is unavailable right now.",
"empty": "No audit events found",
"emptyDetail": "Adjust the action filter.",
"relatedFilterActive": "Showing only events linked to this action ({{count}} related events).",
"clearFilter": "Clear this filter",
"count": "{{count}} events",
"storedRendered": "UTC stored · Brussels rendered",
"columns": {
"when": "When",
"actor": "Actor",
"action": "Action",
"entity": "Entity",
"change": "Change",
"followUp": "Follow-up",
"details": "Details"
},
"viewRelatedEvents": "View related events",
"noChangeDetail": "No recorded change detail.",
"noFieldChange": "No field-level change detected.",
"reference": "Reference",
"relatedEventsCount": "{{count}} linked event",
"relatedEventsCount_other": "{{count}} linked events",
"showTechnicalEvents": "Show {{count}} technical event",
"showTechnicalEvents_other": "Show {{count}} technical events",
"hideTechnicalEvents": "Hide technical events",
"technicalDetails": "Technical details",
"fullReference": "Full reference",
"correlationId": "Correlation ID",
"diff": {
"setTo": "{{field}}: set to {{value}}",
"was": "{{field}}: was {{value}}",
"changed": "{{field}}: {{before}} → {{after}}"
},
"actions": {
"demo_login": "Logged in",
"demo_logout": "Logged out",
"demo_reset": "Demo data reset",
"demo_data_seeded": "Demo data seeded",
"return_registered": "Vehicle return registered",
"vehicle_status_changed": "Vehicle status changed",
"data_quality_issue_resolved": "Data-quality issue resolved",
"data_quality_issue_deferred": "Data-quality issue deferred",
"data_quality_issue_rejected": "Data-quality issue rejected",
"data_quality_fields_provided": "Missing fields provided",
"data_quality_odometer_corrected": "Odometer corrected",
"data_quality_odometer_retained": "Canonical odometer retained",
"data_quality_status_applied": "Recommended status applied",
"data_quality_booking_blocked": "Booking blocked",
"data_quality_scan_run": "Quality scan run",
"customer_merged": "Customers merged",
"workflow_retry": "Automation retried",
"knowledge_question_asked": "Knowledge question asked",
"mcp_tool_request": "MCP tool called"
}
}
+23
View File
@@ -0,0 +1,23 @@
{
"brandTagline": "Control Centre",
"orgLine": "Demo organisation: {{orgName}} (fictional)",
"headline1": "Every hand-off.",
"headline2": "One clear view.",
"defaultDescription": "Fleet Ops brings vehicle, booking and operational data together, supports rental processes, detects data-quality problems and automates controlled follow-up steps.",
"footnote": "Synthetic demo · no real customer or vehicle data · resettable at any time",
"accessEyebrow": "Demo access",
"accessHeading": "Choose how to start",
"accessIntro": "No password needed. Each role opens a scoped synthetic environment — all workflows and controls are really implemented.",
"startGuidedDemo": "Start guided demo",
"exploreAsOperationsManager": "Explore as Operations Manager",
"exploreAsOperationsManagerDetail": "Full overview, quality resolution and retries",
"exploreAsRentalEmployee": "Explore as Rental Employee",
"exploreAsRentalEmployeeDetail": "Bookings, returns, fleet and procedures",
"safeByDesignTitle": "Safe by design",
"safeByDesignDetail": "Every action is logged and is resettable in this demo.",
"loginFailed": "The demo session could not be started. The API may be unreachable.",
"roleOperationsManager": "Operations manager",
"roleRentalEmployee": "Rental employee",
"switchRole": "Switch role",
"logout": "Log out"
}
@@ -0,0 +1,52 @@
{
"list": {
"eyebrow": "Operations / Schedule",
"title": "Bookings",
"description": "Review active rental windows and upcoming vehicle commitments.",
"searchLabel": "Search",
"searchPlaceholder": "Booking, customer or vehicle",
"statusLabel": "Status",
"statusAll": "All statuses",
"loading": "Loading booking ledger…",
"empty": "No bookings found",
"emptyDetail": "Adjust the booking status filter.",
"noMatch": "No matching bookings",
"noMatchDetail": "Try a broader search term.",
"unavailable": "Booking list is unavailable right now.",
"count": "{{count}} bookings",
"pageOf": "Page {{page}} of {{total}}",
"columns": {
"reference": "Reference",
"customer": "Customer",
"vehicle": "Vehicle",
"window": "Window",
"status": "Status"
},
"paginationLabel": "Booking pages",
"previous": "Previous",
"next": "Next",
"rangeOf": "{{from}}–{{to}} of {{total}}"
},
"statuses": {
"reserved": "reserved",
"active": "active",
"returned": "returned",
"cancelled": "cancelled",
"blocked": "blocked"
},
"detail": {
"backLink": "Booking ledger",
"eyebrow": "Bookings / Rental record",
"notFound": "This booking could not be found.",
"loading": "Loading booking record…",
"customer": "Customer",
"vehicle": "Vehicle",
"starts": "Starts",
"ends": "Ends",
"startOdometer": "Start odometer",
"endOdometer": "End odometer",
"requirementsComplete": "Requirements complete",
"yes": "Yes",
"no": "No"
}
}
@@ -0,0 +1,44 @@
{
"appName": "Fleet Ops",
"orgName": "Northstar Mobility",
"brandTagline": "Control Centre",
"actions": {
"save": "Save",
"cancel": "Cancel",
"confirm": "Confirm",
"close": "Close",
"back": "Back",
"next": "Next",
"retry": "Retry",
"reset": "Reset",
"yes": "Yes",
"no": "No",
"viewDetails": "View details",
"technicalDetails": "Technical details"
},
"status": {
"loading": "Loading…",
"saving": "Saving…",
"error": "Something went wrong",
"success": "Success",
"noResults": "No results"
},
"states": {
"loadingDefault": "Loading workspace…",
"errorTitle": "We couldn't load this workspace."
},
"timezone": "Europe/Brussels",
"language": {
"label": "Language",
"nl-BE": "Nederlands",
"en-GB": "English",
"fr-BE": "Français"
},
"footer": {
"productLine": "Fleet Ops Demo",
"locale": "Europe/Brussels · Synthetic demo data"
},
"demo": {
"syntheticBadge": "Synthetic demo"
}
}
@@ -0,0 +1,67 @@
{
"eyebrow": "Operations / Live overview",
"title": "Good morning. Here's the fleet.",
"description": "Readiness, exceptions and hand-offs across today's operation.",
"viewFleet": "View fleet",
"demoStart": {
"title": "Try a demonstration scenario",
"readyCount": "{{ready}} of {{total}} scenarios ready for demo.",
"readyCountFallback": "Five focused scenarios.",
"startGuide": "Start demo guide",
"resumeGuide": "Continue demo guide ({{current}}/{{total}})",
"viewScenarios": "View scenarios"
},
"readiness": {
"title": "Fleet readiness",
"description": "Live from persisted vehicle state",
"openFleet": "Open fleet",
"available": "Available",
"rented": "Rented",
"cleaning": "Cleaning",
"maintenance": "Maintenance",
"blocked": "Blocked"
},
"attention": {
"title": "Attention queue",
"description": "{{openIssues}} open quality issues · {{workflowExceptions}} workflow exceptions",
"reviewQueue": "Review queue",
"filterPlaceholder": "Filter issues…",
"filterAriaLabel": "Search attention queue",
"severityAll": "All severity",
"severityHigh": "Critical",
"severityMedium": "Warning",
"severityLow": "Info",
"severityAriaLabel": "Severity",
"empty": "No issues match this filter.",
"openRecord": "Open {{title}}"
},
"movements": {
"title": "Today's movements",
"description": "Departures and returns in Europe/Brussels",
"allBookings": "All bookings",
"empty": "No movements scheduled today.",
"departure": "departure",
"return": "return",
"openBooking": "Open booking {{ref}}"
},
"integrationPulse": {
"title": "Integration pulse",
"description": "Current evidence from connected services",
"systemDetail": "System detail",
"n8nTitle": "n8n delivery",
"n8nSummary": "{{succeeded}} succeeded · {{failed}} failed",
"n8nLatest": "Latest event {{ref}}",
"n8nNoEvidence": "No workflow evidence recorded",
"knowledgeTitle": "Knowledge assistant",
"knowledgeSummary": "{{count}} procedures indexed",
"knowledgeUnavailable": "Health check unavailable",
"mcpTitle": "MCP Hub",
"mcpEnabled": "Registration enabled",
"mcpNotConnected": "Not yet connected"
},
"recent": {
"title": "Recent activity",
"description": "Latest audited workflow changes",
"empty": "No automation activity recorded."
}
}
+189
View File
@@ -0,0 +1,189 @@
{
"badge": {
"trigger": "Synthetic demo",
"dialogLabel": "About this demo environment",
"close": "Close",
"orgIntro": "<strong>{{orgName}}</strong> is a fictional organisation. All names, vehicles and bookings are synthetic.",
"orgIntroFallback": "All names, vehicles and bookings in this environment are synthetic.",
"realWorkflows": "The workflows, controls and automation are really implemented — only the data is invented.",
"lastReset": "Last reset: <strong>{{when}}</strong> · this environment is resettable at any time.",
"aboutLink": "About this demo",
"unknown": "unknown"
},
"guide": {
"dialogLabel": "Guided demo",
"trigger": "Demo guide",
"kicker": "Guided demo · step {{current}} of {{total}}",
"whatYouWillSee": "What you'll see",
"whyItMatters": "Why it matters",
"startAction": "Get started",
"expectedOutcome": "Expected outcome",
"goToStep": "Go to this step",
"next": "Next",
"close": "Close",
"restart": "Prepare demo again",
"restarting": "Restarting…",
"restartFailed": "Could not restart the demo.",
"allStepsLabel": "All steps",
"progressChip": "Demo guide · step {{current}} of {{total}}",
"expand": "Expand demo guide",
"collapse": "Collapse demo guide",
"steps": {
"understand-state": {
"title": "1. Understand the operational state",
"whatYouWillSee": "The dashboard shows fleet readiness, open attention points and today's movements.",
"whyItMatters": "An Operations Manager starts every day with this overview to decide where to step in.",
"startAction": "Open the dashboard and review the attention queue and today's timeline.",
"expectedOutcome": "You see which bookings, vehicles or data-quality issues need attention."
},
"open-booking": {
"title": "2. Open the booking needing attention",
"whatYouWillSee": "Booking BK-DEMO-RETURN, active and due for return today.",
"whyItMatters": "Returns are the moment incorrect odometer readings or damage first become visible.",
"startAction": "Open the booking from the dashboard or the booking list.",
"expectedOutcome": "You see the booking details and the button to process the return."
},
"process-return": {
"title": "3. Process a return with an odometer anomaly",
"whatYouWillSee": "A return form pre-filled with a suspicious odometer reading below the last known reading.",
"whyItMatters": "A falling odometer signals a data-entry mistake or a mixed-up vehicle — this must be caught before release.",
"startAction": "Submit the return with the suggested value and review the server preview before confirming.",
"expectedOutcome": "The return is processed, the vehicle gets an appropriate status, and a data-quality issue is created automatically."
},
"handle-quality-issue": {
"title": "4. Handle the created data-quality issue",
"whatYouWillSee": "A new 'odometer regression' issue at the top of the work queue.",
"whyItMatters": "Every detected issue has one bounded resolution step — nothing is silently auto-corrected.",
"startAction": "Open the data-quality overview and choose the newest issue.",
"expectedOutcome": "You see the recommended action, choose a resolution, and the issue resolves with an audit trail."
},
"merge-duplicate": {
"title": "5. Review and handle a possible duplicate customer",
"whatYouWillSee": "Two customer profiles with the same email and phone number, compared side by side.",
"whyItMatters": "Duplicate customers split booking history and confuse communication.",
"startAction": "Compare both profiles and choose which one survives.",
"expectedOutcome": "The profiles are merged, bookings are rewired, and the losing profile becomes a tombstone."
},
"ask-knowledge": {
"title": "6. Ask the procedure assistant a question",
"whatYouWillSee": "An answer with citation from the scoped demo knowledge base.",
"whyItMatters": "Staff need a quick, grounded answer about procedures, without guessing.",
"startAction": "Click one of the suggested questions, in the current interface language.",
"expectedOutcome": "You see the answer, the procedure used, and the source text — or an honest 'insufficient information' if none exists."
},
"check-automation-audit": {
"title": "7. Check automation and the audit trail",
"whatYouWillSee": "The delivery status of your return's automation job, and its related audit events.",
"whyItMatters": "Every important action must be traceable: who did what, when, and what followed.",
"startAction": "Open Integrations to see delivery status, and Audit trail for the full record.",
"expectedOutcome": "You see a successful (or recoverable) delivery and a readable audit trail of your actions."
},
"review-real-vs-simulated": {
"title": "8. Review what's real, simulated, or not yet connected",
"whatYouWillSee": "An overview of what's functionally implemented in this demo, what's synthetic, and which integrations aren't live yet.",
"whyItMatters": "A demo is only convincing if visitors can verify for themselves what really works and what's still ahead.",
"startAction": "Read the 'About this demo' page.",
"expectedOutcome": "You can explain yourself what Fleet Ops is and isn't, with no verbal explanation needed."
}
}
},
"scenarios": {
"eyebrow": "Demonstration scenarios",
"title": "Try a demonstration scenario",
"description": "Five focused scenarios that always use the same fixed bookings, customers and vehicles — always re-findable after a reset.",
"loading": "Loading scenarios…",
"ready": "Ready for demo",
"notReady": "Not available",
"duration": "Duration",
"durationValue": "± {{minutes}} min",
"role": "Role",
"demonstrates": "Demonstrates:",
"requiresRole": "Requires role: {{roles}}.",
"startScenario": "Start scenario",
"roleOr": "{{a}} or {{b}}",
"roles": {
"operations_manager": "Operations Manager",
"rental_employee": "Rental Employee"
},
"items": {
"return-anomaly": {
"title": "Return with an odometer anomaly",
"problem": "A vehicle comes back with an odometer reading lower than the last recorded reading — a sign of a data-entry mistake or a mixed-up vehicle.",
"demonstrates": "Return processing, automatic data-quality detection, and the audit trail it produces."
},
"duplicate-customer": {
"title": "Merge a possible duplicate customer",
"problem": "Two customer profiles share the same email address and phone number — likely the same person, registered twice.",
"demonstrates": "Merging customers while preserving booking history and the audit trail."
},
"booking-overlap": {
"title": "Resolve overlapping bookings",
"problem": "One vehicle is double-booked for overlapping periods — a scheduling error that must be resolved before departure.",
"demonstrates": "Detection and controlled resolution of scheduling conflicts."
},
"automation-retry": {
"title": "Retry a failed automation job",
"problem": "One earlier event could not be delivered to the automation job due to a simulated connection error.",
"demonstrates": "Reliable delivery with bounded retries and visible failure status."
},
"knowledge-question": {
"title": "Ask a procedure question",
"problem": "An employee isn't sure which procedure applies to a specific operational situation.",
"demonstrates": "Source-grounded answers from a scoped demo knowledge base."
}
},
"blockedReasons": {
"bookingNotFound": "Demo booking BK-DEMO-RETURN not found. {{resetHint}}",
"bookingAlreadyProcessed": "This booking has already been processed since the last reset. {{resetHint}}",
"duplicateIssueNotFound": "Demo issue DQ-DEMO-DUPLICATE not found. {{resetHint}}",
"issueAlreadyResolved": "This issue has already been resolved since the last reset. {{resetHint}}",
"overlapIssueNotFound": "Demo issue DQ-DEMO-OVERLAP not found. {{resetHint}}",
"failedEventNotFound": "The simulated failed event was not found. {{resetHint}}",
"eventAlreadyRecovered": "This event has already been recovered since the last reset. {{resetHint}}",
"knowledgeUnavailable": "The demo knowledge base is currently unavailable.",
"resetHint": "Reset the demo data to make this scenario available again."
}
},
"about": {
"eyebrow": "About this demo",
"title": "What Fleet Ops is and isn't",
"description": "{{orgName}} is a fictional rental organisation that makes this demo tangible — not a real company.",
"loading": "Loading demo information…",
"ctaTitle": "Prefer to jump right in?",
"ctaBody": "The guided demo walks through all eight steps above in practice.",
"ctaButton": "Start guided demo",
"problemTitle": "The fictional problem",
"problemBody": "{{orgName}} rents around 50 campers and vans from one main location. Bookings, returns, customer records and maintenance used to live in separate spreadsheets and verbal hand-offs, so problems (duplicate customers, incorrect odometer readings, double-booked vehicles) only surfaced late. Fleet Ops shows how one connected system flags these problems early and lets them be resolved under control.",
"scopeTitle": "Who it's for and its scope",
"scopeBody": "This demo is for anyone who wants to see how Fleet Ops tackles operational problems at a small rental company: Operations Managers and Rental Employees, and anyone evaluating the approach. The scope is deliberately focused on one connected proof of concept — no accounting, no payments, no public reservations, no full CRM or ERP.",
"realTitle": "What really works",
"realBody": "Everything below is functional code, not just a mockup: role-based access and sessions, vehicle and booking management, return processing with server-side validation, five data-quality rules each with its own resolution step, a full audit trail, automated delivery to n8n with bounded retries, Docker-based deployment, and an automated test suite (backend and Playwright end-to-end).",
"syntheticTitle": "What's synthetic",
"syntheticBody": "The organisation, all customers, vehicles, bookings, maintenance history, procedures in the knowledge base, and the pre-set-up scenarios are entirely invented. No data refers to a real person, vehicle or company; email addresses only use the {{testDomain}} test domain.",
"architectureTitle": "Architecture in brief",
"architectureBody": "A React/TypeScript frontend talks to a FastAPI backend (PostgreSQL via SQLAlchemy/Alembic migrations); important business rules live in the backend, not in n8n or in prompts. Returns and other events are committed locally first and only then delivered asynchronously to n8n through an automation job, so a temporary automation outage never blocks an operational action.",
"securityTitle": "Security and access",
"securityBody": "Access runs through signed, HTTP-only session cookies per role; each role is bound to a set of allowed routes, both enforced server-side and reflected in navigation. Important state changes are always checked and logged — never silently auto-corrected.",
"testingTitle": "How this is tested",
"testingBody": "An automated backend test suite covers business rules and API contracts; a full Playwright end-to-end suite covers the user flows, including this demo experience itself in three languages. Every change is also validated against a clean checkout (empty database, rebuilt from seed data) before deployment.",
"integrationsTitle": "Integrations — honestly labelled",
"integrationsDescription": "What's operational, what's demo mode, and what's not yet connected.",
"resetTitle": "Restoring the demo environment",
"resetBodyManager": "The environment can be reset to its starting state at any time. Last reset: <strong>{{when}}</strong>. Use <strong>Reset demo data</strong> in the sidebar to start over.",
"resetBodyEmployee": "The environment can be reset to its starting state at any time. Last reset: <strong>{{when}}</strong>. An Operations Manager can reset the demo environment via the sidebar.",
"limitationsTitle": "Limitations",
"limitationsBody": "This is a focused proof of concept, not a full ERP. RAGcore and the ITWorx MCP Hub are not yet live-connected; the knowledge assistant uses a local, scoped demo knowledge base instead of a live RAGcore environment.",
"unknown": "unknown"
},
"integrationSummary": {
"titles": {
"n8n": "Automation (n8n)",
"ragcore": "Knowledge assistant (RAGcore)",
"mcp_hub": "ITWorx MCP Hub"
},
"n8nDetail": "{{succeeded}} succeeded · {{failed}} failed · {{pending}} pending.",
"ragcoreDetail": "{{count}} procedures indexed in {{collection}}.",
"mcpDetailEnabled": "Prepared for future, controlled tool calls from the Hub.",
"mcpDetailNotConnected": "Not yet connected — prepared for future controlled tool calls from the Hub."
}
}
@@ -0,0 +1,8 @@
{
"generic": "Something went wrong. Please try again.",
"workspaceLoadFailed": "We couldn't load this workspace.",
"unauthorized": "Your session has expired. Please log in again.",
"forbidden": "You don't have access to this section.",
"notFound": "This record could not be found.",
"networkUnavailable": "The connection to the server is currently unavailable."
}
@@ -0,0 +1,68 @@
{
"list": {
"eyebrow": "Fleet / Registry",
"title": "Vehicle fleet",
"description": "Live operational state, location and service readiness.",
"searchLabel": "Search",
"searchPlaceholder": "Reference, make or location",
"statusLabel": "Status",
"statusAll": "All statuses",
"attentionOnly": "Attention only",
"loading": "Loading fleet registry…",
"empty": "No vehicles found",
"emptyDetail": "Adjust the current fleet filters.",
"noMatch": "No matching vehicles",
"noMatchDetail": "Try a broader search term.",
"unavailable": "Vehicle list is unavailable right now.",
"count": "{{count}} vehicles",
"persisted": "Persisted fleet data",
"columns": {
"reference": "Reference",
"makeModel": "Make / model",
"location": "Location",
"status": "Status",
"odometer": "Odometer (km)",
"attention": "Attention"
},
"needsAttention": "Needs attention"
},
"statuses": {
"available": "available",
"rented": "rented",
"cleaning": "cleaning",
"maintenance": "maintenance",
"blocked": "blocked"
},
"detail": {
"backLink": "Fleet registry",
"eyebrow": "Fleet / Vehicle record",
"notFound": "This vehicle could not be found.",
"loading": "Loading vehicle record…",
"needsAttention": "Needs attention",
"tabs": {
"overview": "Overview",
"bookings": "Bookings",
"inspections": "Inspections",
"maintenance": "Maintenance",
"quality": "Quality"
},
"tabsAriaLabel": "Vehicle sections",
"overview": {
"registration": "Registration",
"modelYear": "Model year",
"location": "Location",
"odometer": "Odometer",
"nextService": "Next service",
"active": "Active"
},
"yes": "Yes",
"no": "No",
"noBookings": "No bookings recorded.",
"noInspections": "No inspections recorded.",
"noMaintenance": "No maintenance records.",
"noQualityIssues": "No quality issues recorded.",
"fuel": "Fuel {{percent}}%",
"damage": "Damage",
"technicalWarning": "Technical warning"
}
}
@@ -0,0 +1,70 @@
{
"eyebrow": "Assure / Integrations",
"title": "Integration control",
"description": "Monitor delivery health, graceful degradation and retryable workflow events.",
"cards": {
"orchestrationKicker": "Orchestration",
"n8nTitle": "n8n delivery",
"n8nSummary": "{{succeeded}} succeeded · {{failed}} failed · {{pending}} pending · {{delivering}} delivering",
"n8nFallback": "Return events are committed locally first and then delivered through the automation job.",
"knowledgeKicker": "Knowledge",
"knowledgeTitle": "Knowledge assistant",
"knowledgeSummaryDemo": "Demo knowledge base · {{count}} procedures indexed in {{collection}}.",
"knowledgeSummaryRagcore": "RAGcore · {{count}} procedures indexed in {{collection}}.",
"knowledgeUnavailable": "Health evidence is currently unavailable.",
"gatewayKicker": "Tool gateway",
"mcpTitle": "MCP Hub",
"mcpEnabled": "Registration is enabled for this deployment.",
"mcpNotConnected": "Not yet connected — prepared for future controlled tool calls from the Hub."
},
"statusLabels": {
"notConnected": "Not connected",
"deliveryFailed": "Delivery failed",
"retryAvailable": "Retry available",
"operational": "Operational",
"prepared": "Prepared",
"demoMode": "Demo mode",
"unavailable": "Unavailable"
},
"ledger": {
"title": "Automation jobs",
"description": "Persisted automation attempts with the latest failure evidence.",
"filterLabel": "View",
"filterNeedsAttention": "Needs attention",
"filterRecent": "Recent",
"filterSucceeded": "Succeeded",
"filterAll": "All",
"statusFilterLabel": "Status",
"statusAll": "All statuses",
"statusPending": "Pending",
"statusDelivering": "Delivering",
"statusSucceeded": "Succeeded",
"statusFailed": "Failed",
"unavailable": "Automation jobs are unavailable right now.",
"managerOnly": "Automation is visible to Operations Managers only.",
"loading": "Loading automation jobs…",
"empty": "No automation jobs match this filter.",
"count": "{{count}} workflow events",
"boundedRetries": "Bounded retries",
"groupedSucceeded": "{{count}} succeeded vehicle-return jobs",
"showIndividually": "Show individual jobs",
"hideIndividually": "Hide individual jobs",
"columns": {
"event": "Job",
"type": "Type",
"booking": "Booking",
"status": "Status",
"attempts": "Attempts",
"lastError": "Last error",
"when": "When",
"action": "Action"
},
"retry": "Retry",
"retrying": "Retrying…",
"retryFailed": "Could not retry this delivery.",
"noAction": "—",
"eventTypes": {
"vehicle.returned.v1": "Vehicle return processed"
}
}
}
@@ -0,0 +1,41 @@
{
"eyebrow": "Assure / Grounded knowledge",
"title": "Procedure knowledge",
"description": "Ask operational questions. Answers are shown only when {{provider}} returns sufficient cited evidence.",
"providerDemo": "the demo knowledge base",
"providerRagcore": "RAGcore",
"statusAvailable": "Available",
"statusUnavailable": "Unavailable",
"proceduresIndexed": "{{count}} procedures indexed",
"providerNote": "This demo answers from a small, fixed set of indexed procedures — not a live RAGcore connection. A live RAGcore backend will later take over the same interface without changing how this page works.",
"askHeading": "Ask a procedure question",
"askSubheading": "Retrieval → evidence check → grounded answer",
"questionLabel": "Question",
"questionPlaceholder": "e.g. What must I do when a vehicle returns with damage?",
"ask": "Ask",
"asking": "Asking…",
"askFailed": "Could not reach the knowledge service.",
"suggestedLabel": "Try one:",
"suggestedQuestions": [
"What must I do when a vehicle returns with damage?",
"How do I register a vehicle return?",
"When may a vehicle be made available again?",
"Who reviews an unusual odometer reading?",
"Which checks are required before checkout?"
],
"emptyTitle": "Evidence before answers",
"emptyDescription": "Ask about returns, damage, inspections or another indexed procedure. Fleet Ops will not invent an answer when evidence is missing.",
"retrievalFlow": {
"question": "Question",
"sources": "Sources",
"answer": "Answer"
},
"questionLabelExchange": "Question",
"evidenceStates": {
"grounded": "Grounded in cited procedures",
"insufficient": "Insufficient evidence",
"unavailable": "Knowledge service unavailable"
},
"unavailableBody": "The knowledge service is currently unreachable. Operational features are unaffected — try again later.",
"sourceVersion": "v{{version}}"
}
@@ -0,0 +1,39 @@
{
"skipToContent": "Skip to main content",
"groups": {
"operate": "Operate",
"assure": "Assure"
},
"items": {
"overview": "Overview",
"fleet": "Fleet",
"bookings": "Bookings",
"quality": "Data quality",
"knowledge": "Knowledge",
"integrations": "Integrations",
"audit": "Audit trail"
},
"primaryNavLabel": "Primary navigation",
"mobileNavLabel": "Mobile navigation",
"more": "More",
"openNavigation": "Open navigation",
"closeNavigation": "Close navigation",
"sidebarEnvironment": "Demo environment",
"sidebarEnvironmentDetail": "Synthetic data only",
"resetDemoData": "Reset demo data",
"resetConfirmTitle": "Confirm demo reset",
"resetConfirmBody": "All synthetic changes will be discarded and deterministic demo data restored. You will be signed out.",
"resetting": "Resetting…",
"resetConfirmYes": "Yes, reset",
"resetCancel": "Cancel",
"resetFailed": "Could not reset demo data.",
"searchLabel": "Search Fleet Ops",
"searchPlaceholder": "Search fleet, booking or section…",
"searchShortcutHint": "Ctrl K",
"searchSearching": "Searching…",
"searchUnavailable": "Search is unavailable right now.",
"searchNoResults": "No matches for \"{{query}}\".",
"switchRole": "Switch role",
"switchRoleTitle": "Switch demo role",
"languageSwitcherLabel": "Change language"
}
@@ -0,0 +1,192 @@
{
"list": {
"eyebrow": "Assure / Workbench",
"title": "Data quality",
"description": "Resolve evidence-backed exceptions before they disrupt operations.",
"runScan": "Run quality scan",
"confirmScanTitle": "Confirm quality scan",
"confirmScanBody": "Run the deterministic scan across all five rule types now?",
"scanning": "Scanning…",
"confirmScanYes": "Yes, run scan",
"cancel": "Cancel",
"scanComplete": "Scan complete: {{summary}}",
"scanNoNew": "no new issues found (existing open issues are not recreated).",
"scanFailed": "Could not run the quality scan.",
"statusLabel": "Status",
"statusAll": "All statuses",
"statusOpen": "Open",
"statusDeferred": "Deferred",
"statusResolved": "Resolved",
"statusRejected": "Rejected",
"ruleTypeLabel": "Rule type",
"ruleTypeAll": "All rule types",
"demoScenariosOnly": "Demo scenarios only",
"loading": "Loading quality workbench…",
"queueClear": "Queue is clear",
"noIssuesMatch": "No issues match the current filters.",
"noDemoIssuesMatch": "No demo-scenario issues match",
"noDemoIssuesMatchDetail": "Uncheck 'Demo scenarios only' to see the full queue.",
"unavailable": "Data-quality issues are unavailable right now.",
"count": "{{count}} issues",
"evidenceBacked": "Evidence-backed detection",
"columns": {
"reference": "Reference",
"rule": "Rule",
"entity": "Entity",
"severity": "Severity",
"status": "Status"
}
},
"ruleTypes": {
"possible_duplicate_customer": "Possible duplicate customer",
"missing_required_field": "Missing required field",
"odometer_regression": "Odometer regression",
"booking_overlap": "Booking overlap",
"vehicle_status_conflict": "Vehicle status conflict"
},
"severities": {
"high": "Critical",
"medium": "Warning",
"low": "Info"
},
"detail": {
"backLink": "Quality workbench",
"eyebrow": "Quality / {{rule}}",
"title": "Review persisted evidence and record an audited resolution.",
"notFound": "This issue could not be found.",
"loading": "Loading issue evidence…",
"managerOnly": "The quality workbench is visible to Operations Managers only.",
"managerOnlyDetail": "Data-quality evidence and resolutions are visible to Operations Managers only.",
"summary": {
"rule": "Rule",
"entity": "Entity",
"evidenceSummary": "Evidence summary"
},
"resolved": {
"title": "Issue {{ref}} resolved",
"body": "The change has been applied and is recorded in the audit trail.",
"viewAudit": "View audit trail",
"viewVehicle": "View vehicle",
"continueDemo": "Continue the demo"
},
"deferOrReject": {
"heading": "Defer or reject",
"description": "Defer to review later, or reject if this is not a real issue.",
"defer": "Defer",
"reject": "Reject",
"deferFailed": "Could not defer this issue.",
"rejectFailed": "Could not reject this issue."
},
"explainer": {
"whatIsWrong": "What's wrong",
"whyItMatters": "Why it matters",
"possible_duplicate_customer": {
"whatIsWrong": "Two customer profiles share identifying details (email, phone or a very similar name) strongly enough that they are likely the same person, registered twice.",
"whyItMatters": "Duplicate customers split booking history across two records, risk duplicate billing, and confuse support conversations."
},
"missing_required_field": {
"whatIsWrong": "This record is missing information that's required for normal operation (for example, a customer with neither an email nor a phone number on file).",
"whyItMatters": "Without this data, the business can't reach the customer, or can't reliably identify the vehicle for compliance and hand-off checks."
},
"odometer_regression": {
"whatIsWrong": "A submitted odometer reading is lower than the vehicle's last known (canonical) reading.",
"whyItMatters": "A falling odometer usually means a data-entry mistake or that readings were recorded against the wrong vehicle. Letting it through silently would corrupt maintenance scheduling and resale mileage history."
},
"booking_overlap": {
"whatIsWrong": "The same vehicle is committed to two bookings whose date ranges overlap.",
"whyItMatters": "Only one of these bookings can actually be honoured. Left unresolved, a customer would arrive to find their vehicle already out with someone else."
},
"vehicle_status_conflict": {
"whatIsWrong": "This vehicle's stored operational status doesn't match what its own booking and inspection history implies it should be.",
"whyItMatters": "An incorrect status can make an unavailable vehicle appear bookable, or keep an available vehicle hidden from the fleet."
}
},
"duplicateCustomer": {
"heading": "Compare and merge",
"description": "Choose the canonical customer and review each conflicting field.",
"keepAsSurvivor": "Keep as survivor",
"differs": "Differs",
"match": "Match",
"mergePreview": "{{loser}} will become a tombstone linked to {{survivor}}; its bookings will be rewired.",
"mergeInto": "Merge into {{ref}}",
"confirmMergeTitle": "Confirm merge",
"confirmMergeBody": "Merge {{loser}} into {{survivor}}? This cannot be undone.",
"merging": "Merging…",
"confirmMergeYes": "Yes, merge",
"mergeFailed": "Could not merge these customers.",
"bothMissing": "Both customers in this comparison could not be loaded.",
"fieldColumn": "Field",
"fields": {
"first_name": "First name",
"last_name": "Last name",
"email": "Email",
"phone": "Phone",
"postal_code": "Postal code",
"city": "City"
}
},
"missingField": {
"heading": "Provide the missing fields",
"description": "Complete the record for {{ref}}. The issue resolves automatically once nothing required is missing.",
"atLeastOne": "At least one of email or phone is required.",
"saveAndRecheck": "Save and re-check",
"saving": "Saving…",
"saveFailed": "Could not save these fields.",
"fields": {
"first_name": "First name",
"last_name": "Last name",
"email": "Email",
"phone": "Phone",
"registration_number": "Registration number",
"make": "Make",
"model": "Model",
"location": "Location"
}
},
"odometerRegression": {
"heading": "Resolve the odometer regression",
"description": "The canonical odometer is never lowered automatically -- choose how to reconcile it.",
"canonicalOdometer": "Canonical odometer",
"decisionLegend": "Decision",
"retainCanonical": "Retain canonical reading",
"retainCanonicalDetail": "Treat the submitted reading as erroneous; nothing changes on the vehicle record.",
"correctReading": "Correct the reading",
"correctReadingDetail": "Update both the booking and the canonical odometer with the correct value.",
"noBookingAttached": "No related booking is attached to this issue, so only 'retain canonical' is available.",
"booking": "Booking",
"correctedOdometer": "Corrected odometer (km)",
"note": "Note",
"resolving": "Resolving…",
"resolveIssue": "Resolve issue",
"resolveFailed": "Could not resolve this issue."
},
"bookingOverlap": {
"heading": "Resolve the booking overlap",
"description": "Block one of the two overlapping commitments. The other keeps its current status.",
"columns": {
"booking": "Booking",
"window": "Window",
"status": "Status",
"blockThis": "Block this one"
},
"blockLabel": "Block {{ref}}",
"note": "Note",
"resolving": "Resolving…",
"blockButton": "Block {{ref}}",
"blockButtonFallback": "Block booking",
"resolveFailed": "Could not resolve this overlap."
},
"vehicleStatusConflict": {
"heading": "Resolve the status conflict",
"description": "One authoritative rule recommends a corrected operational status for this vehicle.",
"currentStatus": "Current status",
"calculateAndApply": "Calculate and apply recommended status",
"confirmTitle": "Confirm status change",
"confirmBody": "Apply the authoritative recommended status for this vehicle?",
"applying": "Applying…",
"confirmYes": "Yes, apply",
"applied": "Applied {{status}} — {{reason}}",
"applyFailed": "Could not apply a recommended status."
}
}
}
@@ -0,0 +1,73 @@
{
"progress": {
"capture": "Capture",
"review": "Review",
"result": "Result",
"ariaLabel": "Return registration progress"
},
"capture": {
"heading": "Register vehicle return",
"description": "Record the hand-back condition. The next step evaluates the exact operational consequences before anything is committed.",
"endOdometer": "End odometer (km)",
"fuelLevel": "Fuel level (%)",
"conditionLegend": "Vehicle condition",
"cleanlinessOk": "Cleanliness acceptable",
"damageReported": "Damage reported",
"technicalWarning": "Technical warning",
"notes": "Notes",
"evaluating": "Evaluating…",
"reviewReturn": "Review return"
},
"review": {
"heading": "Review return impact",
"description": "This is the server's authoritative evaluation of what committing will do — confirm before it updates fleet state and queues automation.",
"odometer": "Odometer",
"fuel": "Fuel",
"cleanliness": "Cleanliness",
"cleanlinessAccepted": "Accepted",
"cleanlinessFollowUp": "Follow-up needed",
"damage": "Damage",
"damageReported": "Reported",
"damageNone": "None reported",
"technicalWarning": "Technical warning",
"technicalWarningReported": "Reported",
"technicalWarningNone": "None reported",
"expectedState": "Expected fleet state:",
"odometerRegressionWarning": "Submitted odometer ({{submitted}} km) is below the canonical reading ({{canonical}} km). The canonical odometer will not change, and a data-quality issue will be opened.",
"nextBookingRisk": "Next booking {{ref}} starts {{when}} — may be affected by this return.",
"nextBookingLowRisk": "Next booking {{ref}} starts {{when}} — low risk.",
"commitList": {
"inspection": "Create a return inspection",
"updateAtomic": "Update the booking and vehicle atomically",
"queueAutomation": "Queue automation after the local commit"
},
"editDetails": "Edit details",
"registering": "Registering…",
"confirmReturn": "Confirm return"
},
"result": {
"committedLocally": "Committed locally",
"heading": "Return registered",
"inspection": "Inspection",
"resultingStatus": "Resulting vehicle status",
"qualityIssue": "Quality issue",
"noneCreated": "None created",
"automationEvent": "Automation job",
"queuedForDelivery": "Queued for delivery ({{ref}}) — local commit succeeded; automation delivery is asynchronous and not yet confirmed.",
"nextBookingRisk": "Next booking risk",
"nextBookingRiskValue": "{{ref}} {{status}}",
"atRisk": "— may be affected",
"lowRisk": "— low risk",
"noUpcomingBooking": "No upcoming booking for this vehicle",
"odometerRegressionNotice": "The submitted odometer reading was below the vehicle's canonical odometer. It was recorded as-is; the canonical odometer was not changed, and a data-quality issue was opened for review.",
"viewVehicle": "View vehicle {{ref}}",
"viewAutomation": "View automation status",
"viewAudit": "View audit trail",
"continueDemo": "Continue the demo"
},
"scenario": {
"title": "Demo scenario: odometer anomaly",
"body": "This vehicle currently reads {{odometer}} km. The form below is pre-filled with a return reading below that — a sign of a data-entry mistake or a mixed-up vehicle. Confirm the return to see how Fleet Ops detects and handles this.",
"preparing": "Preparing scenario…"
}
}