Files
mc_cars_gmbh_infraestructure/frontend/i18n.js
T
Lago 8be7d5aad2 feat: implement Marco's customer changes
- Remove 'Flotte ansehen' button from hero section
- Remove '24/7 Support' stat from hero section
- Remove 'Unsere Flotte' eyebrow from fleet section
- Remove ALL 'Warum wir' / 'Why us' references from nav links, i18n keys, and legal pages
- Update reviews: Ferrari references only (removed GT3 mentions)
- Update Impressum with correct company data (MC Cars GmbH)
- Add multi-photo gallery: DB migration (17-vehicle-photos.sql), admin UI for photo management, frontend carousel on cards and dialog
- Update SEO: Ferrari-focused meta tags, title, keywords, JSON-LD
- Clean up dead i18n keys (viewFleet, statSupport, fleetEyebrow, navWhy, why* keys)
- Fix legal page issues: add config.js script, fix logo references to SVG
- Add Playwright E2E tests (26/26 passing)
- Update footer tagline across all pages
2026-05-31 09:53:23 +02:00

512 lines
20 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Translations shared between public site and admin panel.
export const translations = {
de: {
navCars: "Fahrzeuge",
navReviews: "Stimmen",
navBook: "Buchen",
bookNow: "Jetzt buchen",
heroEyebrow: "MC Cars · Sportwagenvermietung",
heroTitle: "Fahren auf höchstem Niveau.",
heroLead: "Der Ferrari in der Steiermark. Faire Kaution, transparent, sofort startklar.",
statDeposit: "Faire Kaution",
statCars: "Fahrzeuge",
fleetTitle: "Handverlesen. Gepflegt. Startklar.",
fleetSub: "Filtern Sie nach Marke und Preis. Klicken Sie für Details oder buchen Sie direkt.",
filterBrand: "Marke",
filterSort: "Sortierung",
filterPrice: "Max. Preis / Tag",
all: "Alle",
sortPriceAsc: "Preis aufsteigend",
sortPriceDesc: "Preis absteigend",
sortPowerDesc: "Leistung absteigend",
details: "Details",
book: "Buchen",
perDay: "pro Tag",
hp: "PS",
kmh: "km/h",
accel: "0-100",
seats: "Sitze",
from: "ab",
noMatches: "Keine Fahrzeuge gefunden.",
reviewsEyebrow: "Kundenmeinungen",
reviewsTitle: "Erlebnisse, die bleiben.",
review: "Kundenmeinung",
bookingEyebrow: "Jetzt buchen",
bookingTitle: "Traumwagen unverbindlich anfragen.",
fieldName: "Name",
fieldEmail: "E-Mail",
fieldPhone: "Telefon",
fieldCar: "Fahrzeug",
fieldFrom: "Von",
fieldTo: "Bis",
fieldMessage: "Nachricht",
messagePlaceholder: "Wünsche, Uhrzeit, Anlass...",
sendRequest: "Anfrage senden",
invalidDates: "Bitte ein gültiges Datum wählen (Bis > Von).",
weekendSaturdayOnly: "Im Wochenendmodus bitte einen Samstag wählen.",
bookingSuccess: "Danke! Wir melden uns in Kürze per E-Mail.",
bookingFailed: "Anfrage konnte nicht gesendet werden. Bitte erneut versuchen.",
// BPF Wizard
bpfTitle: "Jetzt buchen",
bpfSubtitle: "Wähle dein Wunschfahrzeug, den Zeitraum und konfiguriere deine Buchung nach Wunsch.",
stepVehicleTime: "Fahrzeug & Zeitraum",
stepContact: "Kontaktdaten",
stepVerification: "ID-Verifizierung",
bpfRentalDuration: "Mietdauer",
bpfVehicle: "Fahrzeug",
bpfSelectVehicle: "Fahrzeug wählen",
bpfDuration: "Mietdauer",
bpfPresetDay: "1 Tag",
bpfPresetWeekend: "Wochenende",
bpfPresetCustom: "Individuell",
bpfPickDate: "Datum wählen",
bpfPickWeekend: "Wochenende wählen (Samstag)",
bpfStartDate: "Startdatum",
bpfEndDate: "Enddatum",
bpfSelectDate: "Datum wählen",
bpfNext: "Weiter",
bpfBack: "Zurück",
bpfDailyRate: "Tagesmiete",
bpfWeekendRate: "Wochenendmiete",
bpfWeekendDef: "Wochenende: Samstag 9:00 Sonntag 20:00",
bpfMaxKm: "Max. km/Tag",
bpfInclKmPerDay: "Inkl. km/Tag",
bpfExtraKm: "Extra km",
bpfPriceOverview: "Preisübersicht",
bpfSelectForPrice: "Wähle Fahrzeug und Datum für eine Preisübersicht",
bpfSubtotal: "Zwischensumme",
bpfVat: "MwSt. (20%)",
bpfTotal: "Gesamtbetrag",
bpfDeposit: "Kaution",
bpfIncludedKm: "Inkludierte Kilometer",
bpfIdUpload: "Ausweis / Führerschein",
bpfIncomeUpload: "Lohnzettel / Gehaltsnachweis (optional)",
bpfUploadHint: "PDF, JPG, PNG (max. 10 MB)",
bpfClickUpload: "Klicken zum Hochladen",
bpfIdNotice: "Ihre Dokumente werden vertraulich behandelt und dienen ausschließlich der Identitätsverifizierung.",
bpfSubmit: "Anfrage absenden",
bpfPerKm: "/km",
bpfDays: "Tage",
bpfWeekendDays: "Wochenendtage",
bpfWeekdays: "Wochentage",
// Weekend pricing on cards
perWeekend: "Wochenende",
weekendDef: "Sa 9:00 So 20:00",
footerTagline: "Sportwagenvermietung in der Steiermark, Österreich.",
footerLegal: "Rechtliches",
footerContact: "Kontakt",
footerNav: "Navigation",
imprint: "Impressum",
privacy: "Datenschutz",
terms: "AGB",
rentalTerms: "Mietbedingungen",
copyright: "Alle Rechte vorbehalten.",
close: "Schließen",
editVehicle: "Fahrzeug bearbeiten",
adminNavWebsite: "Website",
adminChangePw: "Passwort ändern",
adminLogout: "Logout",
adminLeads: "Leads",
adminCustomers: "Kunden",
adminVehicles: "Fahrzeuge",
adminSettings: "Einstellungen",
adminHeroImage: "Hauptbild (Hero-Bereich)",
adminHeroImageHint: "JPG/PNG/WebP. Wird als Hintergrundbild im Hero-Bereich der Website angezeigt.",
adminMietvertragTemplate: "Mietvertrag-Vorlage (DOCX)",
adminMietvertragHint: "DOCX-Vorlage mit Platzhaltern. Wird bei Qualifizierung automatisch ausgefüllt und als PDF per E-Mail versendet.",
adminMietvertragEmpty: "Keine Vorlage hochgeladen.",
adminNewVehicle: "Neues Fahrzeug",
adminAllVehicles: "Alle Fahrzeuge",
adminPhotoUpload: "Foto hochladen (JPG/PNG/WebP, max 50 MB)",
adminBrand: "Marke",
adminModel: "Modell",
adminPower: "PS",
adminSpeed: "Top-Speed km/h",
adminAccel: "0-100",
adminSeats: "Sitze",
adminPrice: "Preis / Tag (€)",
adminSort: "Reihenfolge",
adminLocation: "Standort",
adminDescDe: "Beschreibung (Deutsch)",
adminDescEn: "Description (English)",
adminActiveVisible: "Aktiv / auf Website sichtbar",
adminSave: "Speichern",
adminReset: "Neu",
adminPhoto: "Foto",
adminBrandTable: "Marke / Modell",
adminPriceTable: "€ / Tag",
adminActive: "Aktiv",
adminDel: "Löschen",
adminQualify: "Qualifizieren",
adminReject: "Ablehnen",
adminReopen: "Wieder öffnen",
adminDetails: "Details",
adminSetInactive: "Inaktiv setzen",
adminSetActive: "Aktiv setzen",
adminActiveLeads: "Aktive Leads",
adminClosedLeads: "Abgeschlossen",
adminSourceLead: "Quelle (Lead)",
adminFirstContact: "Erster Kontakt",
adminNameEmail: "Name / E-Mail",
adminPhone: "Telefon",
adminStatus: "Status",
adminReceived: "Eingang",
adminVehicleTab: "Fahrzeug",
adminPeriod: "Zeitraum",
adminKaution: "Kaution (€)",
adminMaxKmWeekend: "Inkl. km/Wochenende",
adminTotalPrice: "Gesamtbetrag",
adminLifetimeValueCol: "Gesamtwert",
adminTabGeneral: "Allgemein",
adminTabGeneralEn: "General",
adminTabPricing: "Preise",
adminTabPricingEn: "Pricing",
adminTabDocuments: "Dokumente",
adminTabDocumentsEn: "Documents",
adminTabNotes: "Notiz",
adminTabNotesEn: "Notes",
adminTabOrderHistory: "Bestellungen",
adminTabOrderHistoryEn: "Sales Orders",
adminPrivateNotes: "Private Notizen",
adminPrivateNotesEn: "Private Notes",
adminSaveNotes: "Notizen speichern",
adminSaveNotesEn: "Save notes",
adminNoOrders: "Keine Buchungen gefunden.",
adminNoOrdersEn: "No bookings found.",
adminKautionPending: "Kaution ausstehend",
adminKautionPaid: "Kaution ✓",
adminRentalPending: "Miete ausstehend",
adminRentalPaid: "Miete ✓",
adminCompletePending: "Abgeschlossen offen",
adminCompleteDone: "Abgeschlossen ✓",
adminLifetimeValue: "Gesamtwert aller Buchungen",
adminLifetimeValueEn: "Lifetime value",
adminDownload: "Herunterladen",
adminNoDocuments: "Keine Dokumente hochgeladen",
adminNoDocumentsEn: "No documents uploaded",
adminIdDoc: "Ausweis / Führerschein",
adminIdDocEn: "ID / Driving license",
adminIncomeDoc: "Lohnzettel",
adminIncomeDocEn: "Pay slip",
adminOtherDoc: "Sonstiges",
adminOtherDocEn: "Other",
adminWeekdays: "Wochentage",
adminWeekdaysEn: "Weekdays",
adminWeekendRateLabel: "Wochenendmiete",
adminWeekendRateLabelEn: "Weekend rate",
adminSubtotalLabel: "Zwischensumme",
adminSubtotalLabelEn: "Subtotal",
adminVatLabel: "MwSt. (20%)",
adminVatLabelEn: "VAT (20%)",
adminTotalLabel: "Gesamtbetrag",
adminTotalLabelEn: "Total",
adminInclVat: "inkl. MwSt.",
adminInclVatEn: "incl. VAT",
adminDepositLabel: "Kaution",
adminDepositLabelEn: "Deposit",
adminIncludedKmLabel: "Inkl. km",
adminIncludedKmLabelEn: "Included km",
adminTotalDaysLabel: "Tage gesamt",
adminTotalDaysLabelEn: "Total days",
adminFirstContacted: "Erster Kontakt",
adminFirstContactedEn: "First contacted",
adminNote: "Notiz",
adminNoteEn: "Note",
adminSave: "Speichern",
adminSaveEn: "Save",
adminPricePerKm: "Preis extra km (€)",
adminRentalType: "Miettyp",
rentalTypeWeekend: "Wochenende",
rentalTypeIndividuell: "Individuell",
adminSortOrder: "Ordnung",
adminEmailSent: "E-Mail gesendet",
sendEmailButton: "E-Mail senden",
emailSentToast: "E-Mail wird erstellt und in Kürze gesendet...",
emailAlreadySent: "Bereits gesendet",
bpfIndividuellTitle: "Individuelle Mietdauer",
bpfIndividuellDesc: "Bei Mietdauer über 2 Tagen erstellen wir ein persönliches Angebot. Wir prüfen Verfügbarkeit und melden uns in Kürze per E-Mail bei Ihnen.",
},
en: {
navCars: "Fleet",
navReviews: "Reviews",
navBook: "Book",
bookNow: "Book now",
heroEyebrow: "MC Cars · Sports car rental",
heroTitle: "Drive at the highest level.",
heroLead: "The Ferrari in Styria. Fair deposit, full transparency, ready to launch.",
statDeposit: "Fair Deposit",
statCars: "Vehicles",
fleetTitle: "Hand-picked. Maintained. Ready.",
fleetSub: "Filter by brand or price. Click for details or book directly.",
filterBrand: "Brand",
filterSort: "Sort",
filterPrice: "Max price / day",
all: "All",
sortPriceAsc: "Price ascending",
sortPriceDesc: "Price descending",
sortPowerDesc: "Power descending",
details: "Details",
book: "Book",
perDay: "per day",
hp: "HP",
kmh: "km/h",
accel: "0-62",
seats: "Seats",
from: "from",
noMatches: "No vehicles match the filters.",
reviewsEyebrow: "Testimonials",
reviewsTitle: "Experiences that last.",
review: "Review",
bookingEyebrow: "Book now",
bookingTitle: "Request your dream car without obligation.",
fieldName: "Name",
fieldEmail: "Email",
fieldPhone: "Phone",
fieldCar: "Vehicle",
fieldFrom: "From",
fieldTo: "To",
fieldMessage: "Message",
messagePlaceholder: "Wishes, timing, occasion...",
sendRequest: "Send request",
invalidDates: "Please pick valid dates (To > From).",
weekendSaturdayOnly: "In weekend mode, please select a Saturday.",
bookingSuccess: "Thank you! We'll get back to you shortly.",
bookingFailed: "Request could not be sent. Please try again.",
// BPF Wizard
bpfTitle: "Book now",
bpfSubtitle: "Choose your dream car, the time period, and configure your booking.",
stepVehicleTime: "Vehicle & Period",
stepContact: "Contact details",
stepVerification: "ID Verification",
bpfRentalDuration: "Rental duration",
bpfVehicle: "Vehicle",
bpfSelectVehicle: "Select vehicle",
bpfDuration: "Rental duration",
bpfPresetDay: "1 Day",
bpfPresetWeekend: "Weekend",
bpfPresetCustom: "Custom",
bpfPickDate: "Pick date",
bpfPickWeekend: "Pick weekend (Saturday)",
bpfStartDate: "Start date",
bpfEndDate: "End date",
bpfSelectDate: "Select date",
bpfNext: "Next",
bpfBack: "Back",
bpfDailyRate: "Daily rate",
bpfWeekendRate: "Weekend rate",
bpfWeekendDef: "Weekend: Saturday 9 AM Sunday 8 PM",
bpfMaxKm: "Max. km/day",
bpfInclKmPerDay: "Included km/day",
bpfExtraKm: "Extra km",
bpfPriceOverview: "Price overview",
bpfSelectForPrice: "Select vehicle and date for a price overview",
bpfSubtotal: "Subtotal",
bpfVat: "VAT (20%)",
bpfTotal: "Total",
bpfDeposit: "Deposit",
bpfIncludedKm: "Included kilometers",
bpfIdUpload: "ID / Driving license",
bpfIncomeUpload: "Pay slip / Income proof (optional)",
bpfUploadHint: "PDF, JPG, PNG (max. 10 MB)",
bpfClickUpload: "Click to upload",
bpfIdNotice: "Your documents are treated confidentially and are used exclusively for identity verification.",
bpfSubmit: "Submit request",
bpfPerKm: "/km",
bpfDays: "Days",
bpfWeekendDays: "Weekend days",
bpfWeekdays: "Weekdays",
// Weekend pricing on cards
perWeekend: "Weekend",
weekendDef: "Sat 9 AM Sun 8 PM",
footerTagline: "Sports car rental in Styria, Austria.",
footerLegal: "Legal",
footerContact: "Contact",
footerNav: "Navigation",
imprint: "Imprint",
privacy: "Privacy",
terms: "Terms",
rentalTerms: "Rental Terms",
copyright: "All rights reserved.",
close: "Close",
editVehicle: "Edit vehicle",
adminNavWebsite: "Website",
adminChangePw: "Change password",
adminLogout: "Logout",
adminLeads: "Leads",
adminCustomers: "Customers",
adminVehicles: "Vehicles",
adminSettings: "Settings",
adminHeroImage: "Main Photo (Hero Section)",
adminHeroImageHint: "JPG/PNG/WebP. Displayed as the background image in the hero section of the website.",
adminMietvertragTemplate: "Rental Contract Template (DOCX)",
adminMietvertragHint: "DOCX template with placeholders. Automatically filled and sent as PDF via email upon qualification.",
adminMietvertragEmpty: "No template uploaded.",
adminNewVehicle: "New vehicle",
adminAllVehicles: "All vehicles",
adminPhotoUpload: "Upload photo (JPG/PNG/WebP, max 50 MB)",
adminBrand: "Brand",
adminModel: "Model",
adminPower: "HP",
adminSpeed: "Top speed km/h",
adminAccel: "0-62",
adminSeats: "Seats",
adminPrice: "Price / day (€)",
adminSort: "Sort order",
adminLocation: "Location",
adminDescDe: "Description (German)",
adminDescEn: "Description (English)",
adminActiveVisible: "Active / visible on website",
adminSave: "Save",
adminReset: "New",
adminPhoto: "Photo",
adminBrandTable: "Brand / Model",
adminPriceTable: "€ / day",
adminActive: "Active",
adminDel: "Delete",
adminQualify: "Qualify",
adminReject: "Reject",
adminReopen: "Reopen",
adminDetails: "Details",
adminSetInactive: "Set inactive",
adminSetActive: "Set active",
adminActiveLeads: "Active leads",
adminClosedLeads: "Closed",
adminSourceLead: "Source (Lead)",
adminFirstContact: "First contact",
adminNameEmail: "Name / Email",
adminPhone: "Phone",
adminStatus: "Status",
adminReceived: "Received",
adminVehicleTab: "Vehicle",
adminPeriod: "Period",
adminKaution: "Deposit (€)",
adminMaxKmWeekend: "Included km/weekend",
adminTotalPrice: "Total",
adminLifetimeValueCol: "Lifetime",
adminTabGeneral: "General",
adminTabGeneralEn: "Allgemein",
adminTabPricing: "Pricing",
adminTabPricingEn: "Preise",
adminTabDocuments: "Documents",
adminTabDocumentsEn: "Dokumente",
adminTabNotes: "Notes",
adminTabNotesEn: "Notiz",
adminTabOrderHistory: "Sales Orders",
adminTabOrderHistoryEn: "Bestellungen",
adminPrivateNotes: "Private Notes",
adminPrivateNotesEn: "Private Notizen",
adminSaveNotes: "Save notes",
adminSaveNotesEn: "Notizen speichern",
adminNoOrders: "No bookings found.",
adminNoOrdersEn: "Keine Buchungen gefunden.",
adminKautionPending: "Deposit pending",
adminKautionPaid: "Deposit ✓",
adminRentalPending: "Rental pending",
adminRentalPaid: "Rental ✓",
adminCompletePending: "Complete open",
adminCompleteDone: "Complete ✓",
adminLifetimeValue: "Lifetime value",
adminLifetimeValueEn: "Gesamtwert aller Buchungen",
adminDownload: "Download",
adminNoDocuments: "No documents uploaded",
adminNoDocumentsEn: "Keine Dokumente hochgeladen",
adminIdDoc: "ID / Driving license",
adminIdDocEn: "Ausweis / Führerschein",
adminIncomeDoc: "Pay slip",
adminIncomeDocEn: "Lohnzettel",
adminOtherDoc: "Other",
adminOtherDocEn: "Sonstiges",
adminWeekdays: "Weekdays",
adminWeekdaysEn: "Wochentage",
adminWeekendRateLabel: "Weekend rate",
adminWeekendRateLabelEn: "Wochenendmiete",
adminSubtotalLabel: "Subtotal",
adminSubtotalLabelEn: "Zwischensumme",
adminVatLabel: "VAT (20%)",
adminVatLabelEn: "MwSt. (20%)",
adminTotalLabel: "Total",
adminTotalLabelEn: "Gesamtbetrag",
adminInclVat: "incl. VAT",
adminInclVatEn: "inkl. MwSt.",
adminDepositLabel: "Deposit",
adminDepositLabelEn: "Kaution",
adminIncludedKmLabel: "Included km",
adminIncludedKmLabelEn: "Inkl. km",
adminTotalDaysLabel: "Total days",
adminTotalDaysLabelEn: "Tage gesamt",
adminFirstContacted: "First contacted",
adminFirstContactedEn: "Erster Kontakt",
adminNote: "Note",
adminNoteEn: "Notiz",
adminSave: "Save",
adminSaveEn: "Speichern",
adminPricePerKm: "Extra km price (€)",
adminRentalType: "Rental type",
rentalTypeWeekend: "Weekend",
rentalTypeIndividuell: "Custom",
adminSortOrder: "Order",
adminEmailSent: "Email sent",
sendEmailButton: "Send Email",
emailSentToast: "Email is being prepared and will be sent shortly...",
emailAlreadySent: "Already sent",
bpfIndividuellTitle: "Custom Rental Duration",
bpfIndividuellDesc: "For rental periods over 2 days, we'll create a personalized quote. We'll check availability and get back to you via email shortly.",
},
};
export const REVIEWS = [
{ quote: "Die Buchung war klar und schnell. Der Ferrari war in einem herausragenden Zustand.", author: "Martin P.", lang: "de" },
{ quote: "Exzellenter Service und ein makellos vorbereiteter Ferrari. Unser Wochenendtrip war unvergesslich.", author: "James R.", lang: "de" },
{ quote: "Hervorragende Buchungsabwicklung und tadelloser Zustand des Ferrari. Sehr zufrieden.", author: "Thomas W.", lang: "de" },
{ quote: "Professionelles Team und erstklassiger Ferrari. Absolut empfehlenswert.", author: "David M.", lang: "de" },
{ quote: "Booking was clear and fast. The Ferrari arrived in outstanding condition.", author: "Jonas P.", lang: "en" },
];
export function getLang() {
return localStorage.getItem("mccars.lang") || "de";
}
export function setLang(lang) {
localStorage.setItem("mccars.lang", lang);
}
export function t(key) {
const lang = getLang();
return (translations[lang] && translations[lang][key]) || key;
}
export function applyI18n(root = document) {
const lang = getLang();
document.documentElement.lang = lang;
root.querySelectorAll("[data-i18n]").forEach((el) => {
const key = el.dataset.i18n;
if (translations[lang][key]) el.textContent = translations[lang][key];
});
root.querySelectorAll("[data-i18n-placeholder]").forEach((el) => {
const key = el.dataset.i18nPlaceholder;
if (translations[lang][key]) el.placeholder = translations[lang][key];
});
}