v2.5.7: Reservation overhaul, Day Detail Panel, i18n, paste support, auto dark mode

BREAKING: Reservations have been completely rebuilt. Existing place-level
reservations are no longer used. All reservations must be re-created via
the Bookings tab. Your trips, places, and other data are unaffected.

Reservation System (rebuilt from scratch):
- Reservations now link to specific day assignments instead of places
- Same place on different days can have independent reservations
- New assignment picker in booking modal (grouped by day, searchable)
- Removed day/place dropdowns from booking form
- Reservation badges in day plan sidebar with type-specific icons
- Reservation details in place inspector (only for selected assignment)
- Reservation summary in day detail panel

Day Detail Panel (new):
- Opens on day click in the sidebar
- Detailed weather: hourly forecast, precipitation, wind, sunrise/sunset
- Historical climate averages for dates beyond 16 days
- Accommodation management with check-in/check-out, confirmation number
- Hotel assignment across multiple days with day range picker
- Reservation overview for the day

Places:
- Places can now be assigned to the same day multiple times
- Start time + end time fields (replaces single time field)
- Map badges show multiple position numbers (e.g. "1 · 4")
- Route optimization fixed for duplicate places
- File attachments during place editing (not just creation)
- Cover image upload during trip creation (not just editing)
- Paste support (Ctrl+V) for images in trip, place, and file forms

Internationalization:
- 200+ hardcoded German strings translated to i18n (EN + DE)
- Server error messages in English
- Category seeds in English for new installations
- All planner, register, photo, packing components translated

UI/UX:
- Auto dark mode (follows system preference, configurable in settings)
- Navbar toggle switches light/dark (overrides auto)
- Sidebar minimize buttons z-index fixed
- Transport mode selector removed from day plan
- CustomSelect supports grouped headers (isHeader option)
- Optimistic updates for day notes (instant feedback)
- Booking cards redesigned with type-colored headers and structured details

Weather:
- Wind speed in mph when using Fahrenheit setting
- Weather description language matches app language

Admin:
- Weather info panel replaces OpenWeatherMap key input
- "Recommended" badge styling updated
This commit is contained in:
Maurice
2026-03-24 20:10:45 +01:00
parent e4607e426c
commit 0497032ed7
67 changed files with 2390 additions and 1322 deletions
+142 -9
View File
@@ -28,6 +28,8 @@ const de = {
'common.update': 'Aktualisieren',
'common.change': 'Ändern',
'common.uploading': 'Hochladen…',
'common.backToPlanning': 'Zurück zur Planung',
'common.reset': 'Zurücksetzen',
// Navbar
'nav.trip': 'Reise',
@@ -37,6 +39,7 @@ const de = {
'nav.logout': 'Abmelden',
'nav.lightMode': 'Heller Modus',
'nav.darkMode': 'Dunkler Modus',
'nav.autoMode': 'Automatischer Modus',
'nav.administrator': 'Administrator',
// Dashboard
@@ -120,6 +123,7 @@ const de = {
'settings.colorMode': 'Farbmodus',
'settings.light': 'Hell',
'settings.dark': 'Dunkel',
'settings.auto': 'Automatisch',
'settings.language': 'Sprache',
'settings.temperature': 'Temperatureinheit',
'settings.timeFormat': 'Zeitformat',
@@ -191,6 +195,35 @@ const de = {
'login.register': 'Registrieren',
'login.emailPlaceholder': 'deine@email.de',
'login.username': 'Benutzername',
'login.oidc.registrationDisabled': 'Registrierung ist deaktiviert. Kontaktiere den Administrator.',
'login.oidc.noEmail': 'Keine E-Mail vom Provider erhalten.',
'login.oidc.tokenFailed': 'Authentifizierung fehlgeschlagen.',
'login.oidc.invalidState': 'Ungültige Sitzung. Bitte erneut versuchen.',
'login.demoFailed': 'Demo-Login fehlgeschlagen',
'login.oidcSignIn': 'Anmelden mit {name}',
'login.demoHint': 'Demo ausprobieren — ohne Registrierung',
// Register
'register.passwordMismatch': 'Passwörter stimmen nicht überein',
'register.passwordTooShort': 'Passwort muss mindestens 6 Zeichen lang sein',
'register.failed': 'Registrierung fehlgeschlagen',
'register.getStarted': 'Jetzt starten',
'register.subtitle': 'Erstellen Sie ein Konto und beginnen Sie, Ihre Traumreisen zu planen.',
'register.feature1': 'Unbegrenzte Reisepläne',
'register.feature2': 'Interaktive Kartenansicht',
'register.feature3': 'Orte und Kategorien verwalten',
'register.feature4': 'Reservierungen tracken',
'register.feature5': 'Packlisten erstellen',
'register.feature6': 'Fotos und Dateien speichern',
'register.createAccount': 'Konto erstellen',
'register.startPlanning': 'Beginnen Sie Ihre Reiseplanung',
'register.minChars': 'Mind. 6 Zeichen',
'register.confirmPassword': 'Passwort bestätigen',
'register.repeatPassword': 'Passwort wiederholen',
'register.registering': 'Registrieren...',
'register.register': 'Registrieren',
'register.hasAccount': 'Bereits ein Konto?',
'register.signIn': 'Anmelden',
// Admin
'admin.title': 'Administration',
@@ -440,9 +473,6 @@ const de = {
'trip.confirm.deletePlace': 'Möchtest du diesen Ort wirklich löschen?',
// Day Plan Sidebar
'dayplan.transport.car': 'Auto',
'dayplan.transport.walk': 'Zu Fuß',
'dayplan.transport.bike': 'Fahrrad',
'dayplan.emptyDay': 'Keine Orte für diesen Tag geplant',
'dayplan.addNote': 'Notiz hinzufügen',
'dayplan.editNote': 'Notiz bearbeiten',
@@ -491,6 +521,8 @@ const de = {
'places.noCategory': 'Keine Kategorie',
'places.categoryNamePlaceholder': 'Kategoriename',
'places.formTime': 'Uhrzeit',
'places.startTime': 'Start',
'places.endTime': 'Ende',
'places.formWebsite': 'Website',
'places.formNotesPlaceholder': 'Persönliche Notizen...',
'places.formReservation': 'Reservierung',
@@ -502,11 +534,6 @@ const de = {
'places.categoryCreateError': 'Fehler beim Erstellen der Kategorie',
'places.nameRequired': 'Bitte einen Namen eingeben',
'places.saveError': 'Fehler beim Speichern',
'places.transport.walking': '🚶 Zu Fuß',
'places.transport.driving': '🚗 Auto',
'places.transport.cycling': '🚲 Fahrrad',
'places.transport.transit': '🚌 ÖPNV',
// Place Inspector
'inspector.opened': 'Geöffnet',
'inspector.closed': 'Geschlossen',
@@ -520,6 +547,8 @@ const de = {
'inspector.pendingRes': 'Ausstehende Reservierung',
'inspector.google': 'In Google Maps öffnen',
'inspector.website': 'Webseite öffnen',
'inspector.addRes': 'Reservierung',
'inspector.editRes': 'Reservierung bearbeiten',
// Reservations
'reservations.title': 'Buchungen',
@@ -536,6 +565,8 @@ const de = {
'reservations.editTitle': 'Reservierung bearbeiten',
'reservations.status': 'Status',
'reservations.datetime': 'Datum & Uhrzeit',
'reservations.date': 'Datum',
'reservations.time': 'Uhrzeit',
'reservations.timeAlt': 'Uhrzeit (alternativ, z.B. 19:30)',
'reservations.notes': 'Notizen',
'reservations.notesPlaceholder': 'Zusätzliche Notizen...',
@@ -563,7 +594,7 @@ const de = {
'reservations.titlePlaceholder': 'z.B. Lufthansa LH123, Hotel Adlon, ...',
'reservations.locationAddress': 'Ort / Adresse',
'reservations.locationPlaceholder': 'Adresse, Flughafen, Hotel...',
'reservations.confirmationCode': 'Bestätigungsnummer / Buchungscode',
'reservations.confirmationCode': 'Buchungscode',
'reservations.confirmationPlaceholder': 'z.B. ABC12345',
'reservations.day': 'Tag',
'reservations.noDay': 'Kein Tag',
@@ -572,6 +603,9 @@ const de = {
'reservations.pendingSave': 'wird gespeichert…',
'reservations.uploading': 'Wird hochgeladen...',
'reservations.attachFile': 'Datei anhängen',
'reservations.linkAssignment': 'Mit Tagesplanung verknüpfen',
'reservations.pickAssignment': 'Zuordnung aus dem Plan wählen...',
'reservations.noAssignment': 'Keine Verknüpfung',
// Budget
'budget.title': 'Budget',
@@ -620,6 +654,8 @@ const de = {
'files.toast.deleteError': 'Fehler beim Löschen der Datei',
'files.sourcePlan': 'Tagesplan',
'files.sourceBooking': 'Buchung',
'files.attach': 'Anhängen',
'files.pasteHint': 'Du kannst auch Bilder aus der Zwischenablage einfügen (Strg+V)',
// Packing
'packing.title': 'Packliste',
@@ -772,6 +808,21 @@ const de = {
'backup.keep.30days': '30 Tage',
'backup.keep.forever': 'Immer behalten',
// Photos
'photos.allDays': 'Alle Tage',
'photos.noPhotos': 'Noch keine Fotos',
'photos.uploadHint': 'Lade deine Reisefotos hoch',
'photos.clickToSelect': 'oder klicken zum Auswählen',
'photos.linkPlace': 'Ort verknüpfen',
'photos.noPlace': 'Kein Ort',
'photos.uploadN': '{n} Foto(s) hochladen',
// Backup restore modal
'backup.restoreConfirmTitle': 'Backup wiederherstellen?',
'backup.restoreWarning': 'Alle aktuellen Daten (Reisen, Orte, Benutzer, Uploads) werden unwiderruflich durch das Backup ersetzt. Dieser Vorgang kann nicht rückgängig gemacht werden.',
'backup.restoreTip': 'Tipp: Erstelle zuerst ein Backup des aktuellen Stands, bevor du wiederherstellst.',
'backup.restoreConfirm': 'Ja, wiederherstellen',
// PDF
'pdf.travelPlan': 'Reiseplan',
'pdf.planned': 'Eingeplant',
@@ -779,6 +830,68 @@ const de = {
'pdf.preview': 'PDF Vorschau',
'pdf.saveAsPdf': 'Als PDF speichern',
// Planner
'planner.places': 'Orte',
'planner.bookings': 'Buchungen',
'planner.packingList': 'Packliste',
'planner.documents': 'Dokumente',
'planner.dayPlan': 'Tagesplan',
'planner.reservations': 'Reservierungen',
'planner.minTwoPlaces': 'Mindestens 2 Orte mit Koordinaten benötigt',
'planner.noGeoPlaces': 'Keine Orte mit Koordinaten vorhanden',
'planner.routeCalculated': 'Route berechnet',
'planner.routeCalcFailed': 'Route konnte nicht berechnet werden',
'planner.routeError': 'Fehler bei der Routenberechnung',
'planner.routeOptimized': 'Route optimiert',
'planner.reservationUpdated': 'Reservierung aktualisiert',
'planner.reservationAdded': 'Reservierung hinzugefügt',
'planner.confirmDeleteReservation': 'Reservierung löschen?',
'planner.reservationDeleted': 'Reservierung gelöscht',
'planner.days': 'Tage',
'planner.allPlaces': 'Alle Orte',
'planner.totalPlaces': '{n} Orte gesamt',
'planner.noDaysPlanned': 'Noch keine Tage geplant',
'planner.editTrip': 'Reise bearbeiten \u2192',
'planner.placeOne': '1 Ort',
'planner.placeN': '{n} Orte',
'planner.addNote': 'Notiz hinzufügen',
'planner.noEntries': 'Keine Einträge für diesen Tag',
'planner.addPlace': 'Ort hinzufügen',
'planner.addPlaceShort': '+ Ort hinzufügen',
'planner.resPending': 'Reservierung ausstehend · ',
'planner.resConfirmed': 'Reservierung bestätigt · ',
'planner.notePlaceholder': 'Notiz\u2026',
'planner.noteTimePlaceholder': 'Zeit (optional)',
'planner.noteExamplePlaceholder': 'z.B. S3 um 14:30 ab Hauptbahnhof, Fähre ab Pier 7, Mittagspause\u2026',
'planner.totalCost': 'Gesamtkosten',
'planner.searchPlaces': 'Orte suchen\u2026',
'planner.allCategories': 'Alle Kategorien',
'planner.noPlacesFound': 'Keine Orte gefunden',
'planner.addFirstPlace': 'Ersten Ort hinzufügen',
'planner.noReservations': 'Keine Reservierungen',
'planner.addFirstReservation': 'Erste Reservierung hinzufügen',
'planner.new': 'Neu',
'planner.addToDay': '+ Tag',
'planner.calculating': 'Berechne\u2026',
'planner.route': 'Route',
'planner.optimize': 'Optimieren',
'planner.openGoogleMaps': 'In Google Maps öffnen',
'planner.selectDayHint': 'Wähle einen Tag aus der linken Liste um den Tagesplan zu sehen',
'planner.noPlacesForDay': 'Noch keine Orte für diesen Tag',
'planner.addPlacesLink': 'Orte hinzufügen \u2192',
'planner.minTotal': 'Min. gesamt',
'planner.noReservation': 'Keine Reservierung',
'planner.removeFromDay': 'Aus Tag entfernen',
'planner.addToThisDay': 'Zum Tag hinzufügen',
'planner.overview': 'Gesamtübersicht',
'planner.noDays': 'Noch keine Tage',
'planner.editTripToAddDays': 'Reise bearbeiten um Tage hinzuzufügen',
'planner.dayCount': '{n} Tage',
'planner.clickToUnlock': 'Klicken zum Entsperren',
'planner.keepPosition': 'Position bei Routenoptimierung beibehalten',
'planner.dayDetails': 'Tagesdetails',
'planner.dayN': 'Tag {n}',
// Dashboard Stats
'stats.countries': 'Länder',
'stats.cities': 'Städte',
@@ -788,6 +901,26 @@ const de = {
'stats.visited': 'besucht',
'stats.remaining': 'verbleibend',
'stats.visitedCountries': 'Besuchte Länder',
// Day Detail Panel
'day.precipProb': 'Regenwahrscheinlichkeit',
'day.precipitation': 'Niederschlag',
'day.wind': 'Wind',
'day.sunrise': 'Sonnenaufgang',
'day.sunset': 'Sonnenuntergang',
'day.hourlyForecast': 'Stündliche Vorhersage',
'day.climateHint': 'Historische Durchschnittswerte — echte Vorhersage verfügbar innerhalb von 16 Tagen vor diesem Datum.',
'day.noWeather': 'Keine Wetterdaten verfügbar. Füge einen Ort mit Koordinaten hinzu.',
'day.accommodation': 'Unterkunft',
'day.addAccommodation': 'Unterkunft hinzufügen',
'day.hotelDayRange': 'Auf Tage anwenden',
'day.noPlacesForHotel': 'Füge zuerst Orte zu deiner Reise hinzu',
'day.allDays': 'Alle',
'day.checkIn': 'Check-in',
'day.checkOut': 'Check-out',
'day.confirmation': 'Bestätigung',
'day.editAccommodation': 'Unterkunft bearbeiten',
'day.reservations': 'Reservierungen',
}
export default de
+142 -9
View File
@@ -28,6 +28,8 @@ const en = {
'common.update': 'Update',
'common.change': 'Change',
'common.uploading': 'Uploading…',
'common.backToPlanning': 'Back to Planning',
'common.reset': 'Reset',
// Navbar
'nav.trip': 'Trip',
@@ -37,6 +39,7 @@ const en = {
'nav.logout': 'Log out',
'nav.lightMode': 'Light Mode',
'nav.darkMode': 'Dark Mode',
'nav.autoMode': 'Auto Mode',
'nav.administrator': 'Administrator',
// Dashboard
@@ -120,6 +123,7 @@ const en = {
'settings.colorMode': 'Color Mode',
'settings.light': 'Light',
'settings.dark': 'Dark',
'settings.auto': 'Auto',
'settings.language': 'Language',
'settings.temperature': 'Temperature Unit',
'settings.timeFormat': 'Time Format',
@@ -191,6 +195,35 @@ const en = {
'login.register': 'Register',
'login.emailPlaceholder': 'your@email.com',
'login.username': 'Username',
'login.oidc.registrationDisabled': 'Registration is disabled. Contact your administrator.',
'login.oidc.noEmail': 'No email received from provider.',
'login.oidc.tokenFailed': 'Authentication failed.',
'login.oidc.invalidState': 'Invalid session. Please try again.',
'login.demoFailed': 'Demo login failed',
'login.oidcSignIn': 'Sign in with {name}',
'login.demoHint': 'Try the demo — no registration needed',
// Register
'register.passwordMismatch': 'Passwords do not match',
'register.passwordTooShort': 'Password must be at least 6 characters',
'register.failed': 'Registration failed',
'register.getStarted': 'Get Started',
'register.subtitle': 'Create an account and start planning your dream trips.',
'register.feature1': 'Unlimited trip plans',
'register.feature2': 'Interactive map view',
'register.feature3': 'Manage places and categories',
'register.feature4': 'Track reservations',
'register.feature5': 'Create packing lists',
'register.feature6': 'Store photos and files',
'register.createAccount': 'Create Account',
'register.startPlanning': 'Start your trip planning',
'register.minChars': 'Min. 6 characters',
'register.confirmPassword': 'Confirm Password',
'register.repeatPassword': 'Repeat password',
'register.registering': 'Registering...',
'register.register': 'Register',
'register.hasAccount': 'Already have an account?',
'register.signIn': 'Sign In',
// Admin
'admin.title': 'Administration',
@@ -440,9 +473,6 @@ const en = {
'trip.confirm.deletePlace': 'Are you sure you want to delete this place?',
// Day Plan Sidebar
'dayplan.transport.car': 'Car',
'dayplan.transport.walk': 'Walk',
'dayplan.transport.bike': 'Bike',
'dayplan.emptyDay': 'No places planned for this day',
'dayplan.addNote': 'Add Note',
'dayplan.editNote': 'Edit Note',
@@ -491,6 +521,8 @@ const en = {
'places.noCategory': 'No Category',
'places.categoryNamePlaceholder': 'Category name',
'places.formTime': 'Time',
'places.startTime': 'Start',
'places.endTime': 'End',
'places.formWebsite': 'Website',
'places.formNotesPlaceholder': 'Personal notes...',
'places.formReservation': 'Reservation',
@@ -502,11 +534,6 @@ const en = {
'places.categoryCreateError': 'Failed to create category',
'places.nameRequired': 'Please enter a name',
'places.saveError': 'Failed to save',
'places.transport.walking': '🚶 Walking',
'places.transport.driving': '🚗 Driving',
'places.transport.cycling': '🚲 Cycling',
'places.transport.transit': '🚌 Transit',
// Place Inspector
'inspector.opened': 'Open',
'inspector.closed': 'Closed',
@@ -520,6 +547,8 @@ const en = {
'inspector.pendingRes': 'Pending Reservation',
'inspector.google': 'Open in Google Maps',
'inspector.website': 'Open Website',
'inspector.addRes': 'Reservation',
'inspector.editRes': 'Edit Reservation',
// Reservations
'reservations.title': 'Bookings',
@@ -536,6 +565,8 @@ const en = {
'reservations.editTitle': 'Edit Reservation',
'reservations.status': 'Status',
'reservations.datetime': 'Date & Time',
'reservations.date': 'Date',
'reservations.time': 'Time',
'reservations.timeAlt': 'Time (alternative, e.g. 19:30)',
'reservations.notes': 'Notes',
'reservations.notesPlaceholder': 'Additional notes...',
@@ -559,7 +590,7 @@ const en = {
'reservations.titlePlaceholder': 'e.g. Lufthansa LH123, Hotel Adlon, ...',
'reservations.locationAddress': 'Location / Address',
'reservations.locationPlaceholder': 'Address, Airport, Hotel...',
'reservations.confirmationCode': 'Confirmation Number / Booking Code',
'reservations.confirmationCode': 'Booking Code',
'reservations.confirmationPlaceholder': 'e.g. ABC12345',
'reservations.day': 'Day',
'reservations.noDay': 'No Day',
@@ -572,6 +603,9 @@ const en = {
'reservations.toast.updateError': 'Failed to update',
'reservations.toast.deleteError': 'Failed to delete',
'reservations.confirm.remove': 'Remove reservation for "{name}"?',
'reservations.linkAssignment': 'Link to day assignment',
'reservations.pickAssignment': 'Select an assignment from your plan...',
'reservations.noAssignment': 'No link (standalone)',
// Budget
'budget.title': 'Budget',
@@ -620,6 +654,8 @@ const en = {
'files.toast.deleteError': 'Failed to delete file',
'files.sourcePlan': 'Day Plan',
'files.sourceBooking': 'Booking',
'files.attach': 'Attach',
'files.pasteHint': 'You can also paste images from clipboard (Ctrl+V)',
// Packing
'packing.title': 'Packing List',
@@ -772,6 +808,21 @@ const en = {
'backup.keep.30days': '30 days',
'backup.keep.forever': 'Keep forever',
// Photos
'photos.allDays': 'All Days',
'photos.noPhotos': 'No photos yet',
'photos.uploadHint': 'Upload your travel photos',
'photos.clickToSelect': 'or click to select',
'photos.linkPlace': 'Link Place',
'photos.noPlace': 'No Place',
'photos.uploadN': '{n} photo(s) upload',
// Backup restore modal
'backup.restoreConfirmTitle': 'Restore Backup?',
'backup.restoreWarning': 'All current data (trips, places, users, uploads) will be permanently replaced by the backup. This action cannot be undone.',
'backup.restoreTip': 'Tip: Create a backup of the current state before restoring.',
'backup.restoreConfirm': 'Yes, restore',
// PDF
'pdf.travelPlan': 'Travel Plan',
'pdf.planned': 'Planned',
@@ -779,6 +830,68 @@ const en = {
'pdf.preview': 'PDF Preview',
'pdf.saveAsPdf': 'Save as PDF',
// Planner
'planner.places': 'Places',
'planner.bookings': 'Bookings',
'planner.packingList': 'Packing List',
'planner.documents': 'Documents',
'planner.dayPlan': 'Day Plan',
'planner.reservations': 'Reservations',
'planner.minTwoPlaces': 'At least 2 places with coordinates needed',
'planner.noGeoPlaces': 'No places with coordinates available',
'planner.routeCalculated': 'Route calculated',
'planner.routeCalcFailed': 'Route could not be calculated',
'planner.routeError': 'Error calculating route',
'planner.routeOptimized': 'Route optimized',
'planner.reservationUpdated': 'Reservation updated',
'planner.reservationAdded': 'Reservation added',
'planner.confirmDeleteReservation': 'Delete reservation?',
'planner.reservationDeleted': 'Reservation deleted',
'planner.days': 'Days',
'planner.allPlaces': 'All Places',
'planner.totalPlaces': '{n} places total',
'planner.noDaysPlanned': 'No days planned yet',
'planner.editTrip': 'Edit trip \u2192',
'planner.placeOne': '1 place',
'planner.placeN': '{n} places',
'planner.addNote': 'Add note',
'planner.noEntries': 'No entries for this day',
'planner.addPlace': 'Add place',
'planner.addPlaceShort': '+ Add place',
'planner.resPending': 'Reservation pending · ',
'planner.resConfirmed': 'Reservation confirmed · ',
'planner.notePlaceholder': 'Note\u2026',
'planner.noteTimePlaceholder': 'Time (optional)',
'planner.noteExamplePlaceholder': 'e.g. S3 at 14:30 from central station, ferry from pier 7, lunch break\u2026',
'planner.totalCost': 'Total cost',
'planner.searchPlaces': 'Search places\u2026',
'planner.allCategories': 'All Categories',
'planner.noPlacesFound': 'No places found',
'planner.addFirstPlace': 'Add first place',
'planner.noReservations': 'No reservations',
'planner.addFirstReservation': 'Add first reservation',
'planner.new': 'New',
'planner.addToDay': '+ Day',
'planner.calculating': 'Calculating\u2026',
'planner.route': 'Route',
'planner.optimize': 'Optimize',
'planner.openGoogleMaps': 'Open in Google Maps',
'planner.selectDayHint': 'Select a day from the left list to see the day plan',
'planner.noPlacesForDay': 'No places for this day yet',
'planner.addPlacesLink': 'Add places \u2192',
'planner.minTotal': 'min. total',
'planner.noReservation': 'No reservation',
'planner.removeFromDay': 'Remove from day',
'planner.addToThisDay': 'Add to day',
'planner.overview': 'Overview',
'planner.noDays': 'No days yet',
'planner.editTripToAddDays': 'Edit trip to add days',
'planner.dayCount': '{n} Days',
'planner.clickToUnlock': 'Click to unlock',
'planner.keepPosition': 'Keep position during route optimization',
'planner.dayDetails': 'Day details',
'planner.dayN': 'Day {n}',
// Dashboard Stats
'stats.countries': 'Countries',
'stats.cities': 'Cities',
@@ -788,6 +901,26 @@ const en = {
'stats.visited': 'visited',
'stats.remaining': 'remaining',
'stats.visitedCountries': 'Visited Countries',
// Day Detail Panel
'day.precipProb': 'Rain probability',
'day.precipitation': 'Precipitation',
'day.wind': 'Wind',
'day.sunrise': 'Sunrise',
'day.sunset': 'Sunset',
'day.hourlyForecast': 'Hourly Forecast',
'day.climateHint': 'Historical averages — real forecast available within 16 days of this date.',
'day.noWeather': 'No weather data available. Add a place with coordinates.',
'day.accommodation': 'Accommodation',
'day.addAccommodation': 'Add accommodation',
'day.hotelDayRange': 'Apply to days',
'day.noPlacesForHotel': 'Add places to your trip first',
'day.allDays': 'All',
'day.checkIn': 'Check-in',
'day.checkOut': 'Check-out',
'day.confirmation': 'Confirmation',
'day.editAccommodation': 'Edit accommodation',
'day.reservations': 'Reservations',
}
export default en