Initial commit — NOMAD (Navigation Organizer for Maps, Activities & Destinations)
Self-hosted travel planner with Express.js, SQLite, React & Tailwind CSS.
This commit is contained in:
36
client/src/i18n/TranslationContext.jsx
Normal file
36
client/src/i18n/TranslationContext.jsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import React, { createContext, useContext, useMemo } from 'react'
|
||||
import { useSettingsStore } from '../store/settingsStore'
|
||||
import de from './translations/de'
|
||||
import en from './translations/en'
|
||||
|
||||
const translations = { de, en }
|
||||
const TranslationContext = createContext({ t: (k) => k, language: 'de', locale: 'de-DE' })
|
||||
|
||||
export function TranslationProvider({ children }) {
|
||||
const language = useSettingsStore(s => s.settings.language) || 'de'
|
||||
|
||||
const value = useMemo(() => {
|
||||
const strings = translations[language] || translations.de
|
||||
const fallback = translations.de
|
||||
|
||||
function t(key, params) {
|
||||
let val = strings[key] ?? fallback[key] ?? key
|
||||
// Arrays/Objects direkt zurückgeben (z.B. Vorschläge-Liste)
|
||||
if (typeof val !== 'string') return val
|
||||
if (params) {
|
||||
Object.entries(params).forEach(([k, v]) => {
|
||||
val = val.replace(new RegExp(`\\{${k}\\}`, 'g'), v)
|
||||
})
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
return { t, language, locale: language === 'en' ? 'en-US' : 'de-DE' }
|
||||
}, [language])
|
||||
|
||||
return <TranslationContext.Provider value={value}>{children}</TranslationContext.Provider>
|
||||
}
|
||||
|
||||
export function useTranslation() {
|
||||
return useContext(TranslationContext)
|
||||
}
|
||||
1
client/src/i18n/index.js
Normal file
1
client/src/i18n/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export { TranslationProvider, useTranslation } from './TranslationContext'
|
||||
567
client/src/i18n/translations/de.js
Normal file
567
client/src/i18n/translations/de.js
Normal file
@@ -0,0 +1,567 @@
|
||||
const de = {
|
||||
// Allgemein
|
||||
'common.save': 'Speichern',
|
||||
'common.cancel': 'Abbrechen',
|
||||
'common.delete': 'Löschen',
|
||||
'common.edit': 'Bearbeiten',
|
||||
'common.add': 'Hinzufügen',
|
||||
'common.loading': 'Laden...',
|
||||
'common.error': 'Fehler',
|
||||
'common.back': 'Zurück',
|
||||
'common.all': 'Alle',
|
||||
'common.close': 'Schließen',
|
||||
'common.open': 'Öffnen',
|
||||
'common.upload': 'Hochladen',
|
||||
'common.search': 'Suchen',
|
||||
'common.confirm': 'Bestätigen',
|
||||
'common.ok': 'OK',
|
||||
'common.yes': 'Ja',
|
||||
'common.no': 'Nein',
|
||||
'common.or': 'oder',
|
||||
'common.none': 'Keine',
|
||||
'common.rename': 'Umbenennen',
|
||||
'common.name': 'Name',
|
||||
'common.email': 'E-Mail',
|
||||
'common.password': 'Passwort',
|
||||
'common.saving': 'Speichern...',
|
||||
'common.update': 'Aktualisieren',
|
||||
'common.change': 'Ändern',
|
||||
'common.uploading': 'Hochladen…',
|
||||
|
||||
// Navbar
|
||||
'nav.trip': 'Reise',
|
||||
'nav.share': 'Teilen',
|
||||
'nav.settings': 'Einstellungen',
|
||||
'nav.admin': 'Admin',
|
||||
'nav.logout': 'Abmelden',
|
||||
'nav.lightMode': 'Heller Modus',
|
||||
'nav.darkMode': 'Dunkler Modus',
|
||||
'nav.administrator': 'Administrator',
|
||||
|
||||
// Dashboard
|
||||
'dashboard.title': 'Meine Reisen',
|
||||
'dashboard.subtitle.loading': 'Reisen werden geladen...',
|
||||
'dashboard.subtitle.trips': '{count} Reisen ({archived} archiviert)',
|
||||
'dashboard.subtitle.empty': 'Starte deine erste Reise',
|
||||
'dashboard.subtitle.activeOne': '{count} aktive Reise',
|
||||
'dashboard.subtitle.activeMany': '{count} aktive Reisen',
|
||||
'dashboard.subtitle.archivedSuffix': ' · {count} archiviert',
|
||||
'dashboard.newTrip': 'Neue Reise',
|
||||
'dashboard.emptyTitle': 'Noch keine Reisen',
|
||||
'dashboard.emptyText': 'Erstelle deine erste Reise und beginne mit der Planung von Orten, Tagesabläufen und Packlisten.',
|
||||
'dashboard.emptyButton': 'Erste Reise erstellen',
|
||||
'dashboard.nextTrip': 'Nächste Reise',
|
||||
'dashboard.shared': 'Geteilt',
|
||||
'dashboard.sharedBy': 'Geteilt von {name}',
|
||||
'dashboard.days': 'Tage',
|
||||
'dashboard.places': 'Orte',
|
||||
'dashboard.archive': 'Archivieren',
|
||||
'dashboard.restore': 'Wiederherstellen',
|
||||
'dashboard.archived': 'Archiviert',
|
||||
'dashboard.status.ongoing': 'Laufend',
|
||||
'dashboard.status.today': 'Heute',
|
||||
'dashboard.status.tomorrow': 'Morgen',
|
||||
'dashboard.status.past': 'Vergangen',
|
||||
'dashboard.status.daysLeft': 'Noch {count} Tage',
|
||||
'dashboard.toast.loadError': 'Fehler beim Laden der Reisen',
|
||||
'dashboard.toast.created': 'Reise erfolgreich erstellt!',
|
||||
'dashboard.toast.createError': 'Fehler beim Erstellen',
|
||||
'dashboard.toast.updated': 'Reise aktualisiert!',
|
||||
'dashboard.toast.updateError': 'Fehler beim Aktualisieren',
|
||||
'dashboard.toast.deleted': 'Reise gelöscht',
|
||||
'dashboard.toast.deleteError': 'Fehler beim Löschen',
|
||||
'dashboard.toast.archived': 'Reise archiviert',
|
||||
'dashboard.toast.archiveError': 'Fehler beim Archivieren',
|
||||
'dashboard.toast.restored': 'Reise wiederhergestellt',
|
||||
'dashboard.toast.restoreError': 'Fehler beim Wiederherstellen',
|
||||
'dashboard.confirm.delete': 'Reise "{title}" löschen? Alle Orte und Pläne werden unwiderruflich gelöscht.',
|
||||
'dashboard.editTrip': 'Reise bearbeiten',
|
||||
'dashboard.createTrip': 'Neue Reise erstellen',
|
||||
'dashboard.tripTitle': 'Titel',
|
||||
'dashboard.tripTitlePlaceholder': 'z.B. Sommer in Japan',
|
||||
'dashboard.tripDescription': 'Beschreibung',
|
||||
'dashboard.tripDescriptionPlaceholder': 'Worum geht es bei dieser Reise?',
|
||||
'dashboard.startDate': 'Startdatum',
|
||||
'dashboard.endDate': 'Enddatum',
|
||||
'dashboard.noDateHint': 'Kein Datum gesetzt — es werden 7 Standardtage erstellt. Du kannst das jederzeit ändern.',
|
||||
'dashboard.coverImage': 'Titelbild',
|
||||
'dashboard.addCoverImage': 'Titelbild hinzufügen',
|
||||
'dashboard.coverSaved': 'Titelbild gespeichert',
|
||||
'dashboard.coverUploadError': 'Fehler beim Hochladen',
|
||||
'dashboard.coverRemoveError': 'Fehler beim Entfernen',
|
||||
'dashboard.titleRequired': 'Titel ist erforderlich',
|
||||
'dashboard.endDateError': 'Enddatum muss nach dem Startdatum liegen',
|
||||
|
||||
// Settings
|
||||
'settings.title': 'Einstellungen',
|
||||
'settings.subtitle': 'Konfigurieren Sie Ihre persönlichen Einstellungen',
|
||||
'settings.map': 'Karte',
|
||||
'settings.mapTemplate': 'Karten-Vorlage',
|
||||
'settings.mapTemplatePlaceholder.select': 'Vorlage auswählen...',
|
||||
'settings.mapDefaultHint': 'Leer lassen für OpenStreetMap (Standard)',
|
||||
'settings.mapTemplatePlaceholder': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
'settings.mapHint': 'URL-Template für die Kartenkacheln',
|
||||
'settings.latitude': 'Breitengrad',
|
||||
'settings.longitude': 'Längengrad',
|
||||
'settings.saveMap': 'Karte speichern',
|
||||
'settings.apiKeys': 'API-Schlüssel',
|
||||
'settings.mapsKey': 'Google Maps API-Schlüssel',
|
||||
'settings.mapsKeyHint': 'Für Ortsuche. Benötigt Places API (New). Erhalten unter console.cloud.google.com',
|
||||
'settings.weatherKey': 'OpenWeatherMap API-Schlüssel',
|
||||
'settings.weatherKeyHint': 'Für Wetterdaten. Kostenlos unter openweathermap.org/api',
|
||||
'settings.keyPlaceholder': 'Schlüssel eingeben...',
|
||||
'settings.configured': 'Konfiguriert',
|
||||
'settings.saveKeys': 'Schlüssel speichern',
|
||||
'settings.display': 'Darstellung',
|
||||
'settings.colorMode': 'Farbmodus',
|
||||
'settings.light': 'Hell',
|
||||
'settings.dark': 'Dunkel',
|
||||
'settings.language': 'Sprache',
|
||||
'settings.temperature': 'Temperatureinheit',
|
||||
'settings.timeFormat': 'Zeitformat',
|
||||
'settings.account': 'Konto',
|
||||
'settings.username': 'Benutzername',
|
||||
'settings.email': 'E-Mail',
|
||||
'settings.role': 'Rolle',
|
||||
'settings.roleAdmin': 'Administrator',
|
||||
'settings.roleUser': 'Benutzer',
|
||||
'settings.saveProfile': 'Profil speichern',
|
||||
'settings.toast.mapSaved': 'Karteneinstellungen gespeichert',
|
||||
'settings.toast.keysSaved': 'API-Schlüssel gespeichert',
|
||||
'settings.toast.displaySaved': 'Anzeigeeinstellungen gespeichert',
|
||||
'settings.toast.profileSaved': 'Profil aktualisiert',
|
||||
'settings.uploadAvatar': 'Profilbild hochladen',
|
||||
'settings.removeAvatar': 'Profilbild entfernen',
|
||||
'settings.avatarUploaded': 'Profilbild aktualisiert',
|
||||
'settings.avatarRemoved': 'Profilbild entfernt',
|
||||
'settings.avatarError': 'Fehler beim Hochladen',
|
||||
|
||||
// Login
|
||||
'login.error': 'Anmeldung fehlgeschlagen. Bitte Zugangsdaten prüfen.',
|
||||
'login.tagline': 'Deine Reisen.\nDein Plan.',
|
||||
'login.description': 'Plane Reisen mit interaktiven Karten, Tagesabläufen und smarten Checklisten.',
|
||||
'login.features.places': 'Orte',
|
||||
'login.features.schedule': 'Tagesplan',
|
||||
'login.features.packing': 'Packliste',
|
||||
'login.title': 'Anmelden',
|
||||
'login.subtitle': 'Willkommen zurück',
|
||||
'login.signingIn': 'Anmelden…',
|
||||
'login.signIn': 'Anmelden',
|
||||
'login.createAdmin': 'Admin-Konto erstellen',
|
||||
'login.createAdminHint': 'Erstelle das erste Admin-Konto für NOMAD.',
|
||||
'login.createAccount': 'Konto erstellen',
|
||||
'login.createAccountHint': 'Neues Konto registrieren.',
|
||||
'login.creating': 'Erstelle…',
|
||||
'login.noAccount': 'Noch kein Konto?',
|
||||
'login.hasAccount': 'Bereits ein Konto?',
|
||||
'login.register': 'Registrieren',
|
||||
'login.username': 'Benutzername',
|
||||
|
||||
// Admin
|
||||
'admin.title': 'Administration',
|
||||
'admin.subtitle': 'Benutzerverwaltung und Systemeinstellungen',
|
||||
'admin.tabs.users': 'Benutzer',
|
||||
'admin.tabs.categories': 'Kategorien',
|
||||
'admin.tabs.backup': 'Backup',
|
||||
'admin.stats.users': 'Benutzer',
|
||||
'admin.stats.trips': 'Reisen',
|
||||
'admin.stats.places': 'Orte',
|
||||
'admin.stats.photos': 'Fotos',
|
||||
'admin.stats.files': 'Dateien',
|
||||
'admin.table.user': 'Benutzer',
|
||||
'admin.table.email': 'E-Mail',
|
||||
'admin.table.role': 'Rolle',
|
||||
'admin.table.created': 'Erstellt',
|
||||
'admin.table.actions': 'Aktionen',
|
||||
'admin.you': '(Du)',
|
||||
'admin.editUser': 'Benutzer bearbeiten',
|
||||
'admin.newPassword': 'Neues Passwort',
|
||||
'admin.newPasswordHint': 'Leer lassen, um das Passwort nicht zu ändern',
|
||||
'admin.deleteUser': 'Benutzer "{name}" löschen? Alle Reisen werden unwiderruflich gelöscht.',
|
||||
'admin.deleteUserTitle': 'Benutzer löschen',
|
||||
'admin.newPasswordPlaceholder': 'Neues Passwort eingeben…',
|
||||
'admin.toast.loadError': 'Fehler beim Laden der Admin-Daten',
|
||||
'admin.toast.userUpdated': 'Benutzer aktualisiert',
|
||||
'admin.toast.updateError': 'Fehler beim Aktualisieren',
|
||||
'admin.toast.userDeleted': 'Benutzer gelöscht',
|
||||
'admin.toast.deleteError': 'Fehler beim Löschen',
|
||||
'admin.toast.cannotDeleteSelf': 'Eigenes Konto kann nicht gelöscht werden',
|
||||
'admin.tabs.settings': 'Einstellungen',
|
||||
'admin.allowRegistration': 'Registrierung erlauben',
|
||||
'admin.allowRegistrationHint': 'Neue Benutzer können sich selbst registrieren',
|
||||
'admin.apiKeys': 'API-Schlüssel',
|
||||
'admin.mapsKey': 'Google Maps API Key',
|
||||
'admin.mapsKeyHint': 'Für Ortsuche benötigt. Erstellen unter console.cloud.google.com',
|
||||
'admin.weatherKey': 'OpenWeatherMap API Key',
|
||||
'admin.weatherKeyHint': 'Für Wetterdaten. Kostenlos unter openweathermap.org',
|
||||
'admin.validateKey': 'Test',
|
||||
'admin.keyValid': 'Verbunden',
|
||||
'admin.keyInvalid': 'Ungültig',
|
||||
'admin.keySaved': 'API-Schlüssel gespeichert',
|
||||
|
||||
// Trip Planner
|
||||
'trip.tabs.plan': 'Planung',
|
||||
'trip.tabs.reservations': 'Reservierungen',
|
||||
'trip.tabs.packing': 'Packliste',
|
||||
'trip.tabs.packingShort': 'Packen',
|
||||
'trip.tabs.budget': 'Budget',
|
||||
'trip.tabs.files': 'Dateien',
|
||||
'trip.loading': 'Reise wird geladen...',
|
||||
'trip.mobilePlan': 'Planung',
|
||||
'trip.mobilePlaces': 'Orte',
|
||||
'trip.toast.placeUpdated': 'Ort aktualisiert',
|
||||
'trip.toast.placeAdded': 'Ort hinzugefügt',
|
||||
'trip.toast.placeDeleted': 'Ort gelöscht',
|
||||
'trip.toast.selectDay': 'Bitte wähle zuerst einen Tag aus',
|
||||
'trip.toast.assignedToDay': 'Ort wurde dem Tag zugewiesen',
|
||||
'trip.toast.reorderError': 'Fehler beim Sortieren',
|
||||
'trip.toast.reservationUpdated': 'Reservierung aktualisiert',
|
||||
'trip.toast.reservationAdded': 'Reservierung hinzugefügt',
|
||||
'trip.toast.deleted': 'Gelöscht',
|
||||
'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',
|
||||
'dayplan.noteAdd': 'Notiz hinzufügen',
|
||||
'dayplan.noteEdit': 'Notiz bearbeiten',
|
||||
'dayplan.noteTitle': 'Notiz',
|
||||
'dayplan.noteSubtitle': 'Tagesnotiz',
|
||||
'dayplan.totalCost': 'Gesamtkosten',
|
||||
'dayplan.days': 'Tage',
|
||||
'dayplan.dayN': 'Tag {n}',
|
||||
'dayplan.calculating': 'Berechne...',
|
||||
'dayplan.route': 'Route',
|
||||
'dayplan.optimize': 'Optimieren',
|
||||
'dayplan.optimized': 'Route optimiert',
|
||||
'dayplan.routeError': 'Fehler bei der Routenberechnung',
|
||||
'dayplan.confirmed': 'Bestätigt',
|
||||
'dayplan.pendingRes': 'Ausstehend',
|
||||
'dayplan.pdf': 'PDF',
|
||||
'dayplan.pdfTooltip': 'Tagesplan als PDF exportieren',
|
||||
'dayplan.pdfError': 'Fehler beim PDF-Export',
|
||||
|
||||
// Places Sidebar
|
||||
'places.addPlace': 'Ort hinzufügen',
|
||||
'places.all': 'Alle',
|
||||
'places.unplanned': 'Ungeplant',
|
||||
'places.search': 'Orte suchen...',
|
||||
'places.allCategories': 'Alle Kategorien',
|
||||
'places.count': '{count} Orte',
|
||||
'places.countSingular': '1 Ort',
|
||||
'places.allPlanned': 'Alle Orte sind eingeplant',
|
||||
'places.noneFound': 'Keine Orte gefunden',
|
||||
'places.editPlace': 'Ort bearbeiten',
|
||||
'places.formName': 'Name',
|
||||
'places.formNamePlaceholder': 'z.B. Eiffelturm',
|
||||
'places.formDescription': 'Beschreibung',
|
||||
'places.formDescriptionPlaceholder': 'Kurze Beschreibung...',
|
||||
'places.formAddress': 'Adresse',
|
||||
'places.formAddressPlaceholder': 'Straße, Stadt, Land',
|
||||
'places.formLat': 'Breitengrad (z.B. 48.8566)',
|
||||
'places.formLng': 'Längengrad (z.B. 2.3522)',
|
||||
'places.formCategory': 'Kategorie',
|
||||
'places.noCategory': 'Keine Kategorie',
|
||||
'places.categoryNamePlaceholder': 'Kategoriename',
|
||||
'places.formTime': 'Uhrzeit',
|
||||
'places.formWebsite': 'Website',
|
||||
'places.formNotesPlaceholder': 'Persönliche Notizen...',
|
||||
'places.formReservation': 'Reservierung',
|
||||
'places.reservationNotesPlaceholder': 'Reservierungsnotizen, Bestätigungsnummer...',
|
||||
'places.mapsSearchPlaceholder': 'Google Maps suchen...',
|
||||
'places.mapsSearchError': 'Google Maps Suche fehlgeschlagen. Bitte API-Schlüssel in den Einstellungen hinterlegen.',
|
||||
'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',
|
||||
'inspector.openingHours': 'Öffnungszeiten',
|
||||
'inspector.showHours': 'Öffnungszeiten anzeigen',
|
||||
'inspector.files': 'Dateien',
|
||||
'inspector.filesCount': '{count} Dateien',
|
||||
'inspector.removeFromDay': 'Vom Tag entfernen',
|
||||
'inspector.addToDay': 'Zum Tag hinzufügen',
|
||||
'inspector.confirmedRes': 'Bestätigte Reservierung',
|
||||
'inspector.pendingRes': 'Ausstehende Reservierung',
|
||||
'inspector.google': 'In Google Maps öffnen',
|
||||
'inspector.website': 'Webseite öffnen',
|
||||
|
||||
// Reservations
|
||||
'reservations.title': 'Reservierungen',
|
||||
'reservations.empty': 'Keine Reservierungen vorhanden',
|
||||
'reservations.emptyHint': 'Füge Reservierungen für Flüge, Hotels und mehr hinzu',
|
||||
'reservations.add': 'Reservierung hinzufügen',
|
||||
'reservations.addManual': 'Manuelle Buchung',
|
||||
'reservations.placeHint': 'Tipp: Buchungen werden am besten direkt über einen angelegten Ort erstellt, um sie mit dem Tagesplan zu verknüpfen.',
|
||||
'reservations.confirmed': 'Bestätigt',
|
||||
'reservations.pending': 'Ausstehend',
|
||||
'reservations.summary': '{confirmed} bestätigt, {pending} ausstehend',
|
||||
'reservations.fromPlan': 'Aus Planung',
|
||||
'reservations.showFiles': 'Dateien anzeigen',
|
||||
'reservations.editTitle': 'Reservierung bearbeiten',
|
||||
'reservations.status': 'Status',
|
||||
'reservations.datetime': 'Datum & Uhrzeit',
|
||||
'reservations.timeAlt': 'Uhrzeit (alternativ, z.B. 19:30)',
|
||||
'reservations.notes': 'Notizen',
|
||||
'reservations.notesPlaceholder': 'Zusätzliche Notizen...',
|
||||
'reservations.type.flight': 'Flug',
|
||||
'reservations.type.hotel': 'Hotel',
|
||||
'reservations.type.restaurant': 'Restaurant',
|
||||
'reservations.type.train': 'Zug',
|
||||
'reservations.type.car': 'Mietwagen',
|
||||
'reservations.type.cruise': 'Kreuzfahrt',
|
||||
'reservations.type.event': 'Veranstaltung',
|
||||
'reservations.type.tour': 'Tour',
|
||||
'reservations.type.other': 'Sonstiges',
|
||||
'reservations.confirm.delete': 'Möchtest du die Reservierung "{name}" wirklich löschen?',
|
||||
'reservations.toast.updated': 'Reservierung aktualisiert',
|
||||
'reservations.toast.removed': 'Reservierung gelöscht',
|
||||
'reservations.toast.saveError': 'Fehler beim Speichern',
|
||||
'reservations.toast.updateError': 'Fehler beim Aktualisieren',
|
||||
'reservations.toast.deleteError': 'Fehler beim Löschen',
|
||||
'reservations.confirm.remove': 'Reservierung für "{name}" entfernen?',
|
||||
'reservations.toast.fileUploaded': 'Datei hochgeladen',
|
||||
'reservations.toast.uploadError': 'Fehler beim Hochladen',
|
||||
'reservations.newTitle': 'Neue Buchung',
|
||||
'reservations.bookingType': 'Art der Buchung',
|
||||
'reservations.titleLabel': 'Titel',
|
||||
'reservations.titlePlaceholder': 'z.B. Lufthansa LH123, Hotel Adlon, ...',
|
||||
'reservations.locationAddress': 'Ort / Adresse',
|
||||
'reservations.locationPlaceholder': 'Adresse, Flughafen, Hotel...',
|
||||
'reservations.confirmationCode': 'Bestätigungsnummer / Buchungscode',
|
||||
'reservations.confirmationPlaceholder': 'z.B. ABC12345',
|
||||
'reservations.day': 'Tag',
|
||||
'reservations.noDay': 'Kein Tag',
|
||||
'reservations.place': 'Ort',
|
||||
'reservations.noPlace': 'Kein Ort',
|
||||
'reservations.pendingSave': 'wird gespeichert…',
|
||||
'reservations.uploading': 'Wird hochgeladen...',
|
||||
'reservations.attachFile': 'Datei anhängen',
|
||||
|
||||
// Budget
|
||||
'budget.title': 'Budget',
|
||||
'budget.emptyTitle': 'Noch kein Budget erstellt',
|
||||
'budget.emptyText': 'Erstelle Kategorien und Einträge, um dein Reisebudget zu planen',
|
||||
'budget.emptyPlaceholder': 'Kategoriename eingeben...',
|
||||
'budget.createCategory': 'Kategorie erstellen',
|
||||
'budget.category': 'Kategorie',
|
||||
'budget.categoryName': 'Kategoriename',
|
||||
'budget.table.name': 'Name',
|
||||
'budget.table.total': 'Gesamt',
|
||||
'budget.table.persons': 'Personen',
|
||||
'budget.table.days': 'Tage',
|
||||
'budget.table.perPerson': 'Pro Person',
|
||||
'budget.table.perDay': 'Pro Tag',
|
||||
'budget.table.perPersonDay': 'Pro Person/Tag',
|
||||
'budget.table.note': 'Notiz',
|
||||
'budget.newEntry': 'Neuer Eintrag',
|
||||
'budget.defaultEntry': 'Neuer Eintrag',
|
||||
'budget.defaultCategory': 'Neue Kategorie',
|
||||
'budget.total': 'Gesamt',
|
||||
'budget.totalBudget': 'Gesamtbudget',
|
||||
'budget.byCategory': 'Nach Kategorie',
|
||||
'budget.editTooltip': 'Klicken zum Bearbeiten',
|
||||
'budget.confirm.deleteCategory': 'Möchtest du die Kategorie "{name}" mit {count} Einträgen wirklich löschen?',
|
||||
'budget.deleteCategory': 'Kategorie löschen',
|
||||
|
||||
// Files
|
||||
'files.title': 'Dateien',
|
||||
'files.count': '{count} Dateien',
|
||||
'files.countSingular': '1 Datei',
|
||||
'files.uploaded': '{count} hochgeladen',
|
||||
'files.uploadError': 'Fehler beim Hochladen',
|
||||
'files.dropzone': 'Dateien hier ablegen',
|
||||
'files.dropzoneHint': 'oder klicken zum Auswählen',
|
||||
'files.uploading': 'Wird hochgeladen...',
|
||||
'files.filterAll': 'Alle',
|
||||
'files.filterPdf': 'PDFs',
|
||||
'files.filterImages': 'Bilder',
|
||||
'files.filterDocs': 'Dokumente',
|
||||
'files.empty': 'Keine Dateien vorhanden',
|
||||
'files.emptyHint': 'Lade Dateien hoch, um sie mit deiner Reise zu verknüpfen',
|
||||
'files.openTab': 'In neuem Tab öffnen',
|
||||
'files.confirm.delete': 'Möchtest du diese Datei wirklich löschen?',
|
||||
'files.toast.deleted': 'Datei gelöscht',
|
||||
'files.toast.deleteError': 'Fehler beim Löschen der Datei',
|
||||
'files.sourcePlan': 'Tagesplan',
|
||||
'files.sourceBooking': 'Buchung',
|
||||
|
||||
// Packing
|
||||
'packing.title': 'Packliste',
|
||||
'packing.empty': 'Packliste ist leer',
|
||||
'packing.progress': '{packed} von {total} gepackt ({percent}%)',
|
||||
'packing.clearChecked': '{count} abgehakte entfernen',
|
||||
'packing.suggestions': 'Vorschläge',
|
||||
'packing.suggestionsTitle': 'Vorschläge hinzufügen',
|
||||
'packing.allSuggested': 'Alle Vorschläge hinzugefügt',
|
||||
'packing.allPacked': 'Alles gepackt!',
|
||||
'packing.addPlaceholder': 'Neuen Gegenstand hinzufügen...',
|
||||
'packing.categoryPlaceholder': 'Kategorie...',
|
||||
'packing.filterAll': 'Alle',
|
||||
'packing.filterOpen': 'Offen',
|
||||
'packing.filterDone': 'Erledigt',
|
||||
'packing.emptyTitle': 'Packliste ist leer',
|
||||
'packing.emptyHint': 'Füge Gegenstände hinzu oder nutze die Vorschläge',
|
||||
'packing.emptyFiltered': 'Keine Gegenstände in diesem Filter',
|
||||
'packing.menuRename': 'Umbenennen',
|
||||
'packing.menuCheckAll': 'Alle abhaken',
|
||||
'packing.menuUncheckAll': 'Alle Haken entfernen',
|
||||
'packing.menuDeleteCat': 'Kategorie löschen',
|
||||
'packing.changeCategory': 'Kategorie ändern',
|
||||
'packing.confirm.clearChecked': 'Möchtest du {count} abgehakte Gegenstände wirklich entfernen?',
|
||||
'packing.confirm.deleteCat': 'Möchtest du die Kategorie "{name}" mit {count} Gegenständen wirklich löschen?',
|
||||
'packing.defaultCategory': 'Sonstiges',
|
||||
'packing.toast.saveError': 'Fehler beim Speichern',
|
||||
'packing.toast.deleteError': 'Fehler beim Löschen',
|
||||
'packing.toast.renameError': 'Fehler beim Umbenennen',
|
||||
'packing.toast.addError': 'Fehler beim Hinzufügen',
|
||||
|
||||
// Packing suggestions
|
||||
'packing.suggestions.items': [
|
||||
{ name: 'Reisepass', category: 'Dokumente' },
|
||||
{ name: 'Personalausweis', category: 'Dokumente' },
|
||||
{ name: 'Reiseversicherung', category: 'Dokumente' },
|
||||
{ name: 'Flugtickets', category: 'Dokumente' },
|
||||
{ name: 'Kreditkarte', category: 'Finanzen' },
|
||||
{ name: 'Bargeld', category: 'Finanzen' },
|
||||
{ name: 'Visum', category: 'Dokumente' },
|
||||
{ name: 'T-Shirts', category: 'Kleidung' },
|
||||
{ name: 'Hosen', category: 'Kleidung' },
|
||||
{ name: 'Unterwäsche', category: 'Kleidung' },
|
||||
{ name: 'Socken', category: 'Kleidung' },
|
||||
{ name: 'Jacke', category: 'Kleidung' },
|
||||
{ name: 'Schlafkleidung', category: 'Kleidung' },
|
||||
{ name: 'Badekleidung', category: 'Kleidung' },
|
||||
{ name: 'Regenjacke', category: 'Kleidung' },
|
||||
{ name: 'Bequeme Schuhe', category: 'Kleidung' },
|
||||
{ name: 'Zahnbürste', category: 'Hygiene' },
|
||||
{ name: 'Zahnpasta', category: 'Hygiene' },
|
||||
{ name: 'Shampoo', category: 'Hygiene' },
|
||||
{ name: 'Deo', category: 'Hygiene' },
|
||||
{ name: 'Sonnencreme', category: 'Hygiene' },
|
||||
{ name: 'Rasierer', category: 'Hygiene' },
|
||||
{ name: 'Ladegerät', category: 'Elektronik' },
|
||||
{ name: 'Powerbank', category: 'Elektronik' },
|
||||
{ name: 'Kopfhörer', category: 'Elektronik' },
|
||||
{ name: 'Reiseadapter', category: 'Elektronik' },
|
||||
{ name: 'Kamera', category: 'Elektronik' },
|
||||
{ name: 'Schmerzmittel', category: 'Gesundheit' },
|
||||
{ name: 'Pflaster', category: 'Gesundheit' },
|
||||
{ name: 'Desinfektionsmittel', category: 'Gesundheit' },
|
||||
],
|
||||
|
||||
// Members / Sharing
|
||||
'members.shareTrip': 'Reise teilen',
|
||||
'members.inviteUser': 'Benutzer einladen',
|
||||
'members.selectUser': 'Benutzer auswählen…',
|
||||
'members.invite': 'Einladen',
|
||||
'members.allHaveAccess': 'Alle Benutzer haben bereits Zugriff.',
|
||||
'members.access': 'Zugriff',
|
||||
'members.person': 'Person',
|
||||
'members.persons': 'Personen',
|
||||
'members.you': 'du',
|
||||
'members.owner': 'Eigentümer',
|
||||
'members.leaveTrip': 'Reise verlassen',
|
||||
'members.removeAccess': 'Zugriff entfernen',
|
||||
'members.confirmLeave': 'Reise verlassen? Du verlierst den Zugriff.',
|
||||
'members.confirmRemove': 'Zugriff für diesen Benutzer entfernen?',
|
||||
'members.loadError': 'Fehler beim Laden der Mitglieder',
|
||||
'members.added': 'hinzugefügt',
|
||||
'members.addError': 'Fehler beim Hinzufügen',
|
||||
'members.removed': 'Mitglied entfernt',
|
||||
'members.removeError': 'Fehler beim Entfernen',
|
||||
|
||||
// Categories (Admin)
|
||||
'categories.title': 'Kategorien',
|
||||
'categories.subtitle': 'Kategorien für Orte verwalten',
|
||||
'categories.new': 'Neue Kategorie',
|
||||
'categories.empty': 'Keine Kategorien vorhanden',
|
||||
'categories.namePlaceholder': 'Kategoriename',
|
||||
'categories.icon': 'Symbol',
|
||||
'categories.color': 'Farbe',
|
||||
'categories.customColor': 'Eigene Farbe wählen',
|
||||
'categories.preview': 'Vorschau',
|
||||
'categories.defaultName': 'Kategorie',
|
||||
'categories.update': 'Aktualisieren',
|
||||
'categories.create': 'Erstellen',
|
||||
'categories.confirm.delete': 'Kategorie löschen? Orte dieser Kategorie werden nicht gelöscht.',
|
||||
'categories.toast.loadError': 'Fehler beim Laden der Kategorien',
|
||||
'categories.toast.nameRequired': 'Bitte einen Namen eingeben',
|
||||
'categories.toast.updated': 'Kategorie aktualisiert',
|
||||
'categories.toast.created': 'Kategorie erstellt',
|
||||
'categories.toast.saveError': 'Fehler beim Speichern',
|
||||
'categories.toast.deleted': 'Kategorie gelöscht',
|
||||
'categories.toast.deleteError': 'Fehler beim Löschen',
|
||||
|
||||
// Backup (Admin)
|
||||
'backup.title': 'Datensicherung',
|
||||
'backup.subtitle': 'Datenbank und alle hochgeladenen Dateien',
|
||||
'backup.refresh': 'Aktualisieren',
|
||||
'backup.upload': 'Backup hochladen',
|
||||
'backup.uploading': 'Wird hochgeladen…',
|
||||
'backup.create': 'Backup erstellen',
|
||||
'backup.creating': 'Erstelle…',
|
||||
'backup.empty': 'Noch keine Backups vorhanden',
|
||||
'backup.createFirst': 'Erstes Backup erstellen',
|
||||
'backup.download': 'Herunterladen',
|
||||
'backup.restore': 'Wiederherstellen',
|
||||
'backup.confirm.restore': 'Backup "{name}" wiederherstellen?\n\nAlle aktuellen Daten werden durch den Backup-Stand ersetzt.',
|
||||
'backup.confirm.uploadRestore': 'Backup-Datei "{name}" hochladen und wiederherstellen?\n\nAlle aktuellen Daten werden überschrieben.',
|
||||
'backup.confirm.delete': 'Backup "{name}" löschen?',
|
||||
'backup.toast.loadError': 'Fehler beim Laden der Backups',
|
||||
'backup.toast.created': 'Backup erfolgreich erstellt',
|
||||
'backup.toast.createError': 'Fehler beim Erstellen des Backups',
|
||||
'backup.toast.restored': 'Backup wiederhergestellt. Seite wird neu geladen…',
|
||||
'backup.toast.restoreError': 'Fehler beim Wiederherstellen',
|
||||
'backup.toast.uploadError': 'Fehler beim Hochladen',
|
||||
'backup.toast.deleted': 'Backup gelöscht',
|
||||
'backup.toast.deleteError': 'Fehler beim Löschen',
|
||||
'backup.toast.downloadError': 'Download fehlgeschlagen',
|
||||
'backup.toast.settingsSaved': 'Auto-Backup Einstellungen gespeichert',
|
||||
'backup.toast.settingsError': 'Fehler beim Speichern der Einstellungen',
|
||||
'backup.auto.title': 'Auto-Backup',
|
||||
'backup.auto.subtitle': 'Automatische Sicherung nach Zeitplan',
|
||||
'backup.auto.enable': 'Auto-Backup aktivieren',
|
||||
'backup.auto.enableHint': 'Backups werden automatisch nach dem gewählten Zeitplan erstellt',
|
||||
'backup.auto.interval': 'Intervall',
|
||||
'backup.auto.keepLabel': 'Alte Backups löschen nach',
|
||||
'backup.interval.hourly': 'Stündlich',
|
||||
'backup.interval.daily': 'Täglich',
|
||||
'backup.interval.weekly': 'Wöchentlich',
|
||||
'backup.interval.monthly': 'Monatlich',
|
||||
'backup.keep.1day': '1 Tag',
|
||||
'backup.keep.3days': '3 Tage',
|
||||
'backup.keep.7days': '7 Tage',
|
||||
'backup.keep.14days': '14 Tage',
|
||||
'backup.keep.30days': '30 Tage',
|
||||
'backup.keep.forever': 'Immer behalten',
|
||||
|
||||
// PDF
|
||||
'pdf.travelPlan': 'Reiseplan',
|
||||
'pdf.planned': 'Eingeplant',
|
||||
'pdf.costLabel': 'Kosten EUR',
|
||||
'pdf.preview': 'PDF Vorschau',
|
||||
'pdf.saveAsPdf': 'Als PDF speichern',
|
||||
|
||||
// Dashboard Stats
|
||||
'stats.countries': 'Länder',
|
||||
'stats.cities': 'Städte',
|
||||
'stats.trips': 'Reisen',
|
||||
'stats.places': 'Orte',
|
||||
'stats.worldProgress': 'Weltfortschritt',
|
||||
'stats.visited': 'besucht',
|
||||
'stats.remaining': 'verbleibend',
|
||||
'stats.visitedCountries': 'Besuchte Länder',
|
||||
}
|
||||
|
||||
export default de
|
||||
567
client/src/i18n/translations/en.js
Normal file
567
client/src/i18n/translations/en.js
Normal file
@@ -0,0 +1,567 @@
|
||||
const en = {
|
||||
// Common
|
||||
'common.save': 'Save',
|
||||
'common.cancel': 'Cancel',
|
||||
'common.delete': 'Delete',
|
||||
'common.edit': 'Edit',
|
||||
'common.add': 'Add',
|
||||
'common.loading': 'Loading...',
|
||||
'common.error': 'Error',
|
||||
'common.back': 'Back',
|
||||
'common.all': 'All',
|
||||
'common.close': 'Close',
|
||||
'common.open': 'Open',
|
||||
'common.upload': 'Upload',
|
||||
'common.search': 'Search',
|
||||
'common.confirm': 'Confirm',
|
||||
'common.ok': 'OK',
|
||||
'common.yes': 'Yes',
|
||||
'common.no': 'No',
|
||||
'common.or': 'or',
|
||||
'common.none': 'None',
|
||||
'common.rename': 'Rename',
|
||||
'common.name': 'Name',
|
||||
'common.email': 'Email',
|
||||
'common.password': 'Password',
|
||||
'common.saving': 'Saving...',
|
||||
'common.update': 'Update',
|
||||
'common.change': 'Change',
|
||||
'common.uploading': 'Uploading…',
|
||||
|
||||
// Navbar
|
||||
'nav.trip': 'Trip',
|
||||
'nav.share': 'Share',
|
||||
'nav.settings': 'Settings',
|
||||
'nav.admin': 'Admin',
|
||||
'nav.logout': 'Log out',
|
||||
'nav.lightMode': 'Light Mode',
|
||||
'nav.darkMode': 'Dark Mode',
|
||||
'nav.administrator': 'Administrator',
|
||||
|
||||
// Dashboard
|
||||
'dashboard.title': 'My Trips',
|
||||
'dashboard.subtitle.loading': 'Loading trips...',
|
||||
'dashboard.subtitle.trips': '{count} trips ({archived} archived)',
|
||||
'dashboard.subtitle.empty': 'Start your first trip',
|
||||
'dashboard.subtitle.activeOne': '{count} active trip',
|
||||
'dashboard.subtitle.activeMany': '{count} active trips',
|
||||
'dashboard.subtitle.archivedSuffix': ' · {count} archived',
|
||||
'dashboard.newTrip': 'New Trip',
|
||||
'dashboard.emptyTitle': 'No trips yet',
|
||||
'dashboard.emptyText': 'Create your first trip and start planning!',
|
||||
'dashboard.emptyButton': 'Create First Trip',
|
||||
'dashboard.nextTrip': 'Next Trip',
|
||||
'dashboard.shared': 'Shared',
|
||||
'dashboard.sharedBy': 'Shared by {name}',
|
||||
'dashboard.days': 'Days',
|
||||
'dashboard.places': 'Places',
|
||||
'dashboard.archive': 'Archive',
|
||||
'dashboard.restore': 'Restore',
|
||||
'dashboard.archived': 'Archived',
|
||||
'dashboard.status.ongoing': 'Ongoing',
|
||||
'dashboard.status.today': 'Today',
|
||||
'dashboard.status.tomorrow': 'Tomorrow',
|
||||
'dashboard.status.past': 'Past',
|
||||
'dashboard.status.daysLeft': '{count} days left',
|
||||
'dashboard.toast.loadError': 'Failed to load trips',
|
||||
'dashboard.toast.created': 'Trip created successfully!',
|
||||
'dashboard.toast.createError': 'Failed to create trip',
|
||||
'dashboard.toast.updated': 'Trip updated!',
|
||||
'dashboard.toast.updateError': 'Failed to update trip',
|
||||
'dashboard.toast.deleted': 'Trip deleted',
|
||||
'dashboard.toast.deleteError': 'Failed to delete trip',
|
||||
'dashboard.toast.archived': 'Trip archived',
|
||||
'dashboard.toast.archiveError': 'Failed to archive trip',
|
||||
'dashboard.toast.restored': 'Trip restored',
|
||||
'dashboard.toast.restoreError': 'Failed to restore trip',
|
||||
'dashboard.confirm.delete': 'Delete trip "{title}"? All places and plans will be permanently deleted.',
|
||||
'dashboard.editTrip': 'Edit Trip',
|
||||
'dashboard.createTrip': 'Create New Trip',
|
||||
'dashboard.tripTitle': 'Title',
|
||||
'dashboard.tripTitlePlaceholder': 'e.g. Summer in Japan',
|
||||
'dashboard.tripDescription': 'Description',
|
||||
'dashboard.tripDescriptionPlaceholder': 'What is this trip about?',
|
||||
'dashboard.startDate': 'Start Date',
|
||||
'dashboard.endDate': 'End Date',
|
||||
'dashboard.noDateHint': 'No date set — 7 default days will be created. You can change this anytime.',
|
||||
'dashboard.coverImage': 'Cover Image',
|
||||
'dashboard.addCoverImage': 'Add cover image',
|
||||
'dashboard.coverSaved': 'Cover image saved',
|
||||
'dashboard.coverUploadError': 'Failed to upload',
|
||||
'dashboard.coverRemoveError': 'Failed to remove',
|
||||
'dashboard.titleRequired': 'Title is required',
|
||||
'dashboard.endDateError': 'End date must be after start date',
|
||||
|
||||
// Settings
|
||||
'settings.title': 'Settings',
|
||||
'settings.subtitle': 'Configure your personal settings',
|
||||
'settings.map': 'Map',
|
||||
'settings.mapTemplate': 'Map Template',
|
||||
'settings.mapTemplatePlaceholder.select': 'Select template...',
|
||||
'settings.mapDefaultHint': 'Leave empty for OpenStreetMap (default)',
|
||||
'settings.mapTemplatePlaceholder': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
'settings.mapHint': 'URL template for map tiles',
|
||||
'settings.latitude': 'Latitude',
|
||||
'settings.longitude': 'Longitude',
|
||||
'settings.saveMap': 'Save Map',
|
||||
'settings.apiKeys': 'API Keys',
|
||||
'settings.mapsKey': 'Google Maps API Key',
|
||||
'settings.mapsKeyHint': 'For place search. Requires Places API (New). Get at console.cloud.google.com',
|
||||
'settings.weatherKey': 'OpenWeatherMap API Key',
|
||||
'settings.weatherKeyHint': 'For weather data. Free at openweathermap.org/api',
|
||||
'settings.keyPlaceholder': 'Enter key...',
|
||||
'settings.configured': 'Configured',
|
||||
'settings.saveKeys': 'Save Keys',
|
||||
'settings.display': 'Display',
|
||||
'settings.colorMode': 'Color Mode',
|
||||
'settings.light': 'Light',
|
||||
'settings.dark': 'Dark',
|
||||
'settings.language': 'Language',
|
||||
'settings.temperature': 'Temperature Unit',
|
||||
'settings.timeFormat': 'Time Format',
|
||||
'settings.account': 'Account',
|
||||
'settings.username': 'Username',
|
||||
'settings.email': 'Email',
|
||||
'settings.role': 'Role',
|
||||
'settings.roleAdmin': 'Administrator',
|
||||
'settings.roleUser': 'User',
|
||||
'settings.saveProfile': 'Save Profile',
|
||||
'settings.toast.mapSaved': 'Map settings saved',
|
||||
'settings.toast.keysSaved': 'API keys saved',
|
||||
'settings.toast.displaySaved': 'Display settings saved',
|
||||
'settings.toast.profileSaved': 'Profile saved',
|
||||
'settings.uploadAvatar': 'Upload Profile Picture',
|
||||
'settings.removeAvatar': 'Remove Profile Picture',
|
||||
'settings.avatarUploaded': 'Profile picture updated',
|
||||
'settings.avatarRemoved': 'Profile picture removed',
|
||||
'settings.avatarError': 'Upload failed',
|
||||
|
||||
// Login
|
||||
'login.error': 'Login failed. Please check your credentials.',
|
||||
'login.tagline': 'Your Trips.\nYour Plan.',
|
||||
'login.description': 'Plan trips with interactive maps, daily schedules and smart checklists.',
|
||||
'login.features.places': 'Places',
|
||||
'login.features.schedule': 'Schedule',
|
||||
'login.features.packing': 'Packing List',
|
||||
'login.title': 'Sign In',
|
||||
'login.subtitle': 'Welcome back',
|
||||
'login.signingIn': 'Signing in…',
|
||||
'login.signIn': 'Sign In',
|
||||
'login.createAdmin': 'Create Admin Account',
|
||||
'login.createAdminHint': 'Set up the first admin account for NOMAD.',
|
||||
'login.createAccount': 'Create Account',
|
||||
'login.createAccountHint': 'Register a new account.',
|
||||
'login.creating': 'Creating…',
|
||||
'login.noAccount': "Don't have an account?",
|
||||
'login.hasAccount': 'Already have an account?',
|
||||
'login.register': 'Register',
|
||||
'login.username': 'Username',
|
||||
|
||||
// Admin
|
||||
'admin.title': 'Administration',
|
||||
'admin.subtitle': 'User management and system settings',
|
||||
'admin.tabs.users': 'Users',
|
||||
'admin.tabs.categories': 'Categories',
|
||||
'admin.tabs.backup': 'Backup',
|
||||
'admin.stats.users': 'Users',
|
||||
'admin.stats.trips': 'Trips',
|
||||
'admin.stats.places': 'Places',
|
||||
'admin.stats.photos': 'Photos',
|
||||
'admin.stats.files': 'Files',
|
||||
'admin.table.user': 'User',
|
||||
'admin.table.email': 'Email',
|
||||
'admin.table.role': 'Role',
|
||||
'admin.table.created': 'Created',
|
||||
'admin.table.actions': 'Actions',
|
||||
'admin.you': '(You)',
|
||||
'admin.editUser': 'Edit User',
|
||||
'admin.newPassword': 'New Password',
|
||||
'admin.newPasswordHint': 'Leave empty to keep current password',
|
||||
'admin.deleteUser': 'Delete user "{name}"? All trips will be permanently deleted.',
|
||||
'admin.deleteUserTitle': 'Delete user',
|
||||
'admin.newPasswordPlaceholder': 'Enter new password…',
|
||||
'admin.toast.loadError': 'Failed to load admin data',
|
||||
'admin.toast.userUpdated': 'User updated',
|
||||
'admin.toast.updateError': 'Failed to update',
|
||||
'admin.toast.userDeleted': 'User deleted',
|
||||
'admin.toast.deleteError': 'Failed to delete',
|
||||
'admin.toast.cannotDeleteSelf': 'Cannot delete your own account',
|
||||
'admin.tabs.settings': 'Settings',
|
||||
'admin.allowRegistration': 'Allow Registration',
|
||||
'admin.allowRegistrationHint': 'New users can register themselves',
|
||||
'admin.apiKeys': 'API Keys',
|
||||
'admin.mapsKey': 'Google Maps API Key',
|
||||
'admin.mapsKeyHint': 'Required for place search. Get at console.cloud.google.com',
|
||||
'admin.weatherKey': 'OpenWeatherMap API Key',
|
||||
'admin.weatherKeyHint': 'For weather data. Free at openweathermap.org',
|
||||
'admin.validateKey': 'Test',
|
||||
'admin.keyValid': 'Connected',
|
||||
'admin.keyInvalid': 'Invalid',
|
||||
'admin.keySaved': 'API keys saved',
|
||||
|
||||
// Trip Planner
|
||||
'trip.tabs.plan': 'Plan',
|
||||
'trip.tabs.reservations': 'Bookings',
|
||||
'trip.tabs.packing': 'Packing List',
|
||||
'trip.tabs.packingShort': 'Packing',
|
||||
'trip.tabs.budget': 'Budget',
|
||||
'trip.tabs.files': 'Files',
|
||||
'trip.loading': 'Loading trip...',
|
||||
'trip.mobilePlan': 'Plan',
|
||||
'trip.mobilePlaces': 'Places',
|
||||
'trip.toast.placeUpdated': 'Place updated',
|
||||
'trip.toast.placeAdded': 'Place added',
|
||||
'trip.toast.placeDeleted': 'Place deleted',
|
||||
'trip.toast.selectDay': 'Please select a day first',
|
||||
'trip.toast.assignedToDay': 'Place assigned to day',
|
||||
'trip.toast.reorderError': 'Failed to reorder',
|
||||
'trip.toast.reservationUpdated': 'Reservation updated',
|
||||
'trip.toast.reservationAdded': 'Reservation added',
|
||||
'trip.toast.deleted': 'Deleted',
|
||||
'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',
|
||||
'dayplan.noteAdd': 'Add Note',
|
||||
'dayplan.noteEdit': 'Edit Note',
|
||||
'dayplan.noteTitle': 'Note',
|
||||
'dayplan.noteSubtitle': 'Daily Note',
|
||||
'dayplan.totalCost': 'Total Cost',
|
||||
'dayplan.days': 'Days',
|
||||
'dayplan.dayN': 'Day {n}',
|
||||
'dayplan.calculating': 'Calculating...',
|
||||
'dayplan.route': 'Route',
|
||||
'dayplan.optimize': 'Optimize',
|
||||
'dayplan.optimized': 'Route optimized',
|
||||
'dayplan.routeError': 'Failed to calculate route',
|
||||
'dayplan.confirmed': 'Confirmed',
|
||||
'dayplan.pendingRes': 'Pending',
|
||||
'dayplan.pdf': 'PDF',
|
||||
'dayplan.pdfTooltip': 'Export day plan as PDF',
|
||||
'dayplan.pdfError': 'Failed to export PDF',
|
||||
|
||||
// Places Sidebar
|
||||
'places.addPlace': 'Add Place',
|
||||
'places.all': 'All',
|
||||
'places.unplanned': 'Unplanned',
|
||||
'places.search': 'Search places...',
|
||||
'places.allCategories': 'All Categories',
|
||||
'places.count': '{count} places',
|
||||
'places.countSingular': '1 place',
|
||||
'places.allPlanned': 'All places are planned',
|
||||
'places.noneFound': 'No places found',
|
||||
'places.editPlace': 'Edit Place',
|
||||
'places.formName': 'Name',
|
||||
'places.formNamePlaceholder': 'e.g. Eiffel Tower',
|
||||
'places.formDescription': 'Description',
|
||||
'places.formDescriptionPlaceholder': 'Short description...',
|
||||
'places.formAddress': 'Address',
|
||||
'places.formAddressPlaceholder': 'Street, City, Country',
|
||||
'places.formLat': 'Latitude (e.g. 48.8566)',
|
||||
'places.formLng': 'Longitude (e.g. 2.3522)',
|
||||
'places.formCategory': 'Category',
|
||||
'places.noCategory': 'No Category',
|
||||
'places.categoryNamePlaceholder': 'Category name',
|
||||
'places.formTime': 'Time',
|
||||
'places.formWebsite': 'Website',
|
||||
'places.formNotesPlaceholder': 'Personal notes...',
|
||||
'places.formReservation': 'Reservation',
|
||||
'places.reservationNotesPlaceholder': 'Reservation notes, confirmation number...',
|
||||
'places.mapsSearchPlaceholder': 'Search Google Maps...',
|
||||
'places.mapsSearchError': 'Google Maps search failed. Please add an API key in settings.',
|
||||
'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',
|
||||
'inspector.openingHours': 'Opening Hours',
|
||||
'inspector.showHours': 'Show opening hours',
|
||||
'inspector.files': 'Files',
|
||||
'inspector.filesCount': '{count} files',
|
||||
'inspector.removeFromDay': 'Remove from Day',
|
||||
'inspector.addToDay': 'Add to Day',
|
||||
'inspector.confirmedRes': 'Confirmed Reservation',
|
||||
'inspector.pendingRes': 'Pending Reservation',
|
||||
'inspector.google': 'Open in Google Maps',
|
||||
'inspector.website': 'Open Website',
|
||||
|
||||
// Reservations
|
||||
'reservations.title': 'Bookings',
|
||||
'reservations.empty': 'No reservations yet',
|
||||
'reservations.emptyHint': 'Add reservations for flights, hotels and more',
|
||||
'reservations.add': 'Add Reservation',
|
||||
'reservations.addManual': 'Manual Booking',
|
||||
'reservations.placeHint': 'Tip: Reservations are best created directly from a place to link them with your day plan.',
|
||||
'reservations.confirmed': 'Confirmed',
|
||||
'reservations.pending': 'Pending',
|
||||
'reservations.summary': '{confirmed} confirmed, {pending} pending',
|
||||
'reservations.fromPlan': 'From Plan',
|
||||
'reservations.showFiles': 'Show Files',
|
||||
'reservations.editTitle': 'Edit Reservation',
|
||||
'reservations.status': 'Status',
|
||||
'reservations.datetime': 'Date & Time',
|
||||
'reservations.timeAlt': 'Time (alternative, e.g. 19:30)',
|
||||
'reservations.notes': 'Notes',
|
||||
'reservations.notesPlaceholder': 'Additional notes...',
|
||||
'reservations.type.flight': 'Flight',
|
||||
'reservations.type.hotel': 'Hotel',
|
||||
'reservations.type.restaurant': 'Restaurant',
|
||||
'reservations.type.train': 'Train',
|
||||
'reservations.type.car': 'Rental Car',
|
||||
'reservations.type.cruise': 'Cruise',
|
||||
'reservations.type.event': 'Event',
|
||||
'reservations.type.tour': 'Tour',
|
||||
'reservations.type.other': 'Other',
|
||||
'reservations.confirm.delete': 'Are you sure you want to delete the reservation "{name}"?',
|
||||
'reservations.toast.updated': 'Reservation updated',
|
||||
'reservations.toast.removed': 'Reservation deleted',
|
||||
'reservations.toast.fileUploaded': 'File uploaded',
|
||||
'reservations.toast.uploadError': 'Failed to upload',
|
||||
'reservations.newTitle': 'New Reservation',
|
||||
'reservations.bookingType': 'Booking Type',
|
||||
'reservations.titleLabel': 'Title',
|
||||
'reservations.titlePlaceholder': 'e.g. Lufthansa LH123, Hotel Adlon, ...',
|
||||
'reservations.locationAddress': 'Location / Address',
|
||||
'reservations.locationPlaceholder': 'Address, Airport, Hotel...',
|
||||
'reservations.confirmationCode': 'Confirmation Number / Booking Code',
|
||||
'reservations.confirmationPlaceholder': 'e.g. ABC12345',
|
||||
'reservations.day': 'Day',
|
||||
'reservations.noDay': 'No Day',
|
||||
'reservations.place': 'Place',
|
||||
'reservations.noPlace': 'No Place',
|
||||
'reservations.pendingSave': 'will be saved…',
|
||||
'reservations.uploading': 'Uploading...',
|
||||
'reservations.attachFile': 'Attach file',
|
||||
'reservations.toast.saveError': 'Failed to save',
|
||||
'reservations.toast.updateError': 'Failed to update',
|
||||
'reservations.toast.deleteError': 'Failed to delete',
|
||||
'reservations.confirm.remove': 'Remove reservation for "{name}"?',
|
||||
|
||||
// Budget
|
||||
'budget.title': 'Budget',
|
||||
'budget.emptyTitle': 'No budget created yet',
|
||||
'budget.emptyText': 'Create categories and entries to plan your travel budget',
|
||||
'budget.emptyPlaceholder': 'Enter category name...',
|
||||
'budget.createCategory': 'Create Category',
|
||||
'budget.category': 'Category',
|
||||
'budget.categoryName': 'Category Name',
|
||||
'budget.table.name': 'Name',
|
||||
'budget.table.total': 'Total',
|
||||
'budget.table.persons': 'Persons',
|
||||
'budget.table.days': 'Days',
|
||||
'budget.table.perPerson': 'Per Person',
|
||||
'budget.table.perDay': 'Per Day',
|
||||
'budget.table.perPersonDay': 'Per Person/Day',
|
||||
'budget.table.note': 'Note',
|
||||
'budget.newEntry': 'New Entry',
|
||||
'budget.defaultEntry': 'New Entry',
|
||||
'budget.defaultCategory': 'New Category',
|
||||
'budget.total': 'Total',
|
||||
'budget.totalBudget': 'Total Budget',
|
||||
'budget.byCategory': 'By Category',
|
||||
'budget.editTooltip': 'Click to edit',
|
||||
'budget.confirm.deleteCategory': 'Are you sure you want to delete the category "{name}" with {count} entries?',
|
||||
'budget.deleteCategory': 'Delete Category',
|
||||
|
||||
// Files
|
||||
'files.title': 'Files',
|
||||
'files.count': '{count} files',
|
||||
'files.countSingular': '1 file',
|
||||
'files.uploaded': '{count} uploaded',
|
||||
'files.uploadError': 'Upload failed',
|
||||
'files.dropzone': 'Drop files here',
|
||||
'files.dropzoneHint': 'or click to browse',
|
||||
'files.uploading': 'Uploading...',
|
||||
'files.filterAll': 'All',
|
||||
'files.filterPdf': 'PDFs',
|
||||
'files.filterImages': 'Images',
|
||||
'files.filterDocs': 'Documents',
|
||||
'files.empty': 'No files yet',
|
||||
'files.emptyHint': 'Upload files to attach them to your trip',
|
||||
'files.openTab': 'Open in new tab',
|
||||
'files.confirm.delete': 'Are you sure you want to delete this file?',
|
||||
'files.toast.deleted': 'File deleted',
|
||||
'files.toast.deleteError': 'Failed to delete file',
|
||||
'files.sourcePlan': 'Day Plan',
|
||||
'files.sourceBooking': 'Booking',
|
||||
|
||||
// Packing
|
||||
'packing.title': 'Packing List',
|
||||
'packing.empty': 'Packing list is empty',
|
||||
'packing.progress': '{packed} of {total} packed ({percent}%)',
|
||||
'packing.clearChecked': 'Remove {count} checked',
|
||||
'packing.suggestions': 'Suggestions',
|
||||
'packing.suggestionsTitle': 'Add Suggestions',
|
||||
'packing.allSuggested': 'All suggestions added',
|
||||
'packing.allPacked': 'All packed!',
|
||||
'packing.addPlaceholder': 'Add new item...',
|
||||
'packing.categoryPlaceholder': 'Category...',
|
||||
'packing.filterAll': 'All',
|
||||
'packing.filterOpen': 'Open',
|
||||
'packing.filterDone': 'Done',
|
||||
'packing.emptyTitle': 'Packing list is empty',
|
||||
'packing.emptyHint': 'Add items or use the suggestions',
|
||||
'packing.emptyFiltered': 'No items match this filter',
|
||||
'packing.menuRename': 'Rename',
|
||||
'packing.menuCheckAll': 'Check All',
|
||||
'packing.menuUncheckAll': 'Uncheck All',
|
||||
'packing.menuDeleteCat': 'Delete Category',
|
||||
'packing.changeCategory': 'Change Category',
|
||||
'packing.confirm.clearChecked': 'Are you sure you want to remove {count} checked items?',
|
||||
'packing.confirm.deleteCat': 'Are you sure you want to delete the category "{name}" with {count} items?',
|
||||
'packing.defaultCategory': 'Other',
|
||||
'packing.toast.saveError': 'Failed to save',
|
||||
'packing.toast.deleteError': 'Failed to delete',
|
||||
'packing.toast.renameError': 'Failed to rename',
|
||||
'packing.toast.addError': 'Failed to add',
|
||||
|
||||
// Packing suggestions
|
||||
'packing.suggestions.items': [
|
||||
{ name: 'Passport', category: 'Documents' },
|
||||
{ name: 'ID Card', category: 'Documents' },
|
||||
{ name: 'Travel Insurance', category: 'Documents' },
|
||||
{ name: 'Flight Tickets', category: 'Documents' },
|
||||
{ name: 'Credit Card', category: 'Finances' },
|
||||
{ name: 'Cash', category: 'Finances' },
|
||||
{ name: 'Visa', category: 'Documents' },
|
||||
{ name: 'T-Shirts', category: 'Clothing' },
|
||||
{ name: 'Pants', category: 'Clothing' },
|
||||
{ name: 'Underwear', category: 'Clothing' },
|
||||
{ name: 'Socks', category: 'Clothing' },
|
||||
{ name: 'Jacket', category: 'Clothing' },
|
||||
{ name: 'Sleepwear', category: 'Clothing' },
|
||||
{ name: 'Swimwear', category: 'Clothing' },
|
||||
{ name: 'Rain Jacket', category: 'Clothing' },
|
||||
{ name: 'Comfortable Shoes', category: 'Clothing' },
|
||||
{ name: 'Toothbrush', category: 'Toiletries' },
|
||||
{ name: 'Toothpaste', category: 'Toiletries' },
|
||||
{ name: 'Shampoo', category: 'Toiletries' },
|
||||
{ name: 'Deodorant', category: 'Toiletries' },
|
||||
{ name: 'Sunscreen', category: 'Toiletries' },
|
||||
{ name: 'Razor', category: 'Toiletries' },
|
||||
{ name: 'Charger', category: 'Electronics' },
|
||||
{ name: 'Power Bank', category: 'Electronics' },
|
||||
{ name: 'Headphones', category: 'Electronics' },
|
||||
{ name: 'Travel Adapter', category: 'Electronics' },
|
||||
{ name: 'Camera', category: 'Electronics' },
|
||||
{ name: 'Pain Medication', category: 'Health' },
|
||||
{ name: 'Band-Aids', category: 'Health' },
|
||||
{ name: 'Disinfectant', category: 'Health' },
|
||||
],
|
||||
|
||||
// Members / Sharing
|
||||
'members.shareTrip': 'Share Trip',
|
||||
'members.inviteUser': 'Invite User',
|
||||
'members.selectUser': 'Select user…',
|
||||
'members.invite': 'Invite',
|
||||
'members.allHaveAccess': 'All users already have access.',
|
||||
'members.access': 'Access',
|
||||
'members.person': 'person',
|
||||
'members.persons': 'persons',
|
||||
'members.you': 'you',
|
||||
'members.owner': 'Owner',
|
||||
'members.leaveTrip': 'Leave trip',
|
||||
'members.removeAccess': 'Remove access',
|
||||
'members.confirmLeave': 'Leave trip? You will lose access.',
|
||||
'members.confirmRemove': 'Remove access for this user?',
|
||||
'members.loadError': 'Failed to load members',
|
||||
'members.added': 'added',
|
||||
'members.addError': 'Failed to add',
|
||||
'members.removed': 'Member removed',
|
||||
'members.removeError': 'Failed to remove',
|
||||
|
||||
// Categories (Admin)
|
||||
'categories.title': 'Categories',
|
||||
'categories.subtitle': 'Manage categories for places',
|
||||
'categories.new': 'New Category',
|
||||
'categories.empty': 'No categories yet',
|
||||
'categories.namePlaceholder': 'Category name',
|
||||
'categories.icon': 'Icon',
|
||||
'categories.color': 'Color',
|
||||
'categories.customColor': 'Choose custom color',
|
||||
'categories.preview': 'Preview',
|
||||
'categories.defaultName': 'Category',
|
||||
'categories.update': 'Update',
|
||||
'categories.create': 'Create',
|
||||
'categories.confirm.delete': 'Delete category? Places in this category will not be deleted.',
|
||||
'categories.toast.loadError': 'Failed to load categories',
|
||||
'categories.toast.nameRequired': 'Please enter a name',
|
||||
'categories.toast.updated': 'Category updated',
|
||||
'categories.toast.created': 'Category created',
|
||||
'categories.toast.saveError': 'Failed to save',
|
||||
'categories.toast.deleted': 'Category deleted',
|
||||
'categories.toast.deleteError': 'Failed to delete',
|
||||
|
||||
// Backup (Admin)
|
||||
'backup.title': 'Data Backup',
|
||||
'backup.subtitle': 'Database and all uploaded files',
|
||||
'backup.refresh': 'Refresh',
|
||||
'backup.upload': 'Upload Backup',
|
||||
'backup.uploading': 'Uploading…',
|
||||
'backup.create': 'Create Backup',
|
||||
'backup.creating': 'Creating…',
|
||||
'backup.empty': 'No backups yet',
|
||||
'backup.createFirst': 'Create first backup',
|
||||
'backup.download': 'Download',
|
||||
'backup.restore': 'Restore',
|
||||
'backup.confirm.restore': 'Restore backup "{name}"?\n\nAll current data will be replaced with the backup.',
|
||||
'backup.confirm.uploadRestore': 'Upload and restore backup file "{name}"?\n\nAll current data will be overwritten.',
|
||||
'backup.confirm.delete': 'Delete backup "{name}"?',
|
||||
'backup.toast.loadError': 'Failed to load backups',
|
||||
'backup.toast.created': 'Backup created successfully',
|
||||
'backup.toast.createError': 'Failed to create backup',
|
||||
'backup.toast.restored': 'Backup restored. Page will reload…',
|
||||
'backup.toast.restoreError': 'Failed to restore',
|
||||
'backup.toast.uploadError': 'Failed to upload',
|
||||
'backup.toast.deleted': 'Backup deleted',
|
||||
'backup.toast.deleteError': 'Failed to delete',
|
||||
'backup.toast.downloadError': 'Download failed',
|
||||
'backup.toast.settingsSaved': 'Auto-backup settings saved',
|
||||
'backup.toast.settingsError': 'Failed to save settings',
|
||||
'backup.auto.title': 'Auto-Backup',
|
||||
'backup.auto.subtitle': 'Automatic backup on a schedule',
|
||||
'backup.auto.enable': 'Enable auto-backup',
|
||||
'backup.auto.enableHint': 'Backups will be created automatically on the chosen schedule',
|
||||
'backup.auto.interval': 'Interval',
|
||||
'backup.auto.keepLabel': 'Delete old backups after',
|
||||
'backup.interval.hourly': 'Hourly',
|
||||
'backup.interval.daily': 'Daily',
|
||||
'backup.interval.weekly': 'Weekly',
|
||||
'backup.interval.monthly': 'Monthly',
|
||||
'backup.keep.1day': '1 day',
|
||||
'backup.keep.3days': '3 days',
|
||||
'backup.keep.7days': '7 days',
|
||||
'backup.keep.14days': '14 days',
|
||||
'backup.keep.30days': '30 days',
|
||||
'backup.keep.forever': 'Keep forever',
|
||||
|
||||
// PDF
|
||||
'pdf.travelPlan': 'Travel Plan',
|
||||
'pdf.planned': 'Planned',
|
||||
'pdf.costLabel': 'Cost EUR',
|
||||
'pdf.preview': 'PDF Preview',
|
||||
'pdf.saveAsPdf': 'Save as PDF',
|
||||
|
||||
// Dashboard Stats
|
||||
'stats.countries': 'Countries',
|
||||
'stats.cities': 'Cities',
|
||||
'stats.trips': 'Trips',
|
||||
'stats.places': 'Places',
|
||||
'stats.worldProgress': 'World Progress',
|
||||
'stats.visited': 'visited',
|
||||
'stats.remaining': 'remaining',
|
||||
'stats.visitedCountries': 'Visited Countries',
|
||||
}
|
||||
|
||||
export default en
|
||||
Reference in New Issue
Block a user