Added opaque join-token support across backend and frontend: new migration/model/service/endpoints, guest controllers now resolve tokens, and the demo seeder seeds a token. Tenant event details list/manage tokens with copy/revoke actions, and the guest PWA uses tokens end-to-end (routing, storage, uploads, achievements, etc.). Docs TODO updated to reflect completed steps.
This commit is contained in:
61
resources/js/admin/i18n/index.ts
Normal file
61
resources/js/admin/i18n/index.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
|
||||
import deCommon from './locales/de/common.json';
|
||||
import enCommon from './locales/en/common.json';
|
||||
import deDashboard from './locales/de/dashboard.json';
|
||||
import enDashboard from './locales/en/dashboard.json';
|
||||
import deOnboarding from './locales/de/onboarding.json';
|
||||
import enOnboarding from './locales/en/onboarding.json';
|
||||
import deManagement from './locales/de/management.json';
|
||||
import enManagement from './locales/en/management.json';
|
||||
|
||||
const DEFAULT_NAMESPACE = 'common';
|
||||
|
||||
const resources = {
|
||||
de: {
|
||||
common: deCommon,
|
||||
dashboard: deDashboard,
|
||||
onboarding: deOnboarding,
|
||||
management: deManagement,
|
||||
},
|
||||
en: {
|
||||
common: enCommon,
|
||||
dashboard: enDashboard,
|
||||
onboarding: enOnboarding,
|
||||
management: enManagement,
|
||||
},
|
||||
} as const;
|
||||
|
||||
const FALLBACK_LOCALE = 'de';
|
||||
|
||||
if (!i18n.isInitialized) {
|
||||
i18n
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
resources,
|
||||
fallbackLng: FALLBACK_LOCALE,
|
||||
lng: document.documentElement.lang || undefined,
|
||||
supportedLngs: ['de', 'en'],
|
||||
defaultNS: DEFAULT_NAMESPACE,
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
detection: {
|
||||
order: ['htmlTag', 'localStorage', 'cookie', 'navigator'],
|
||||
caches: ['localStorage'],
|
||||
htmlTag: document.documentElement,
|
||||
},
|
||||
returnEmptyString: false,
|
||||
})
|
||||
.catch((error) => {
|
||||
if (import.meta.env.DEV) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Failed to initialize i18n', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default i18n;
|
||||
21
resources/js/admin/i18n/locales/de/common.json
Normal file
21
resources/js/admin/i18n/locales/de/common.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"app": {
|
||||
"brand": "Fotospiel Tenant Admin",
|
||||
"languageSwitch": "Sprache"
|
||||
},
|
||||
"navigation": {
|
||||
"dashboard": "Dashboard",
|
||||
"events": "Events",
|
||||
"tasks": "Aufgaben",
|
||||
"billing": "Abrechnung",
|
||||
"settings": "Einstellungen"
|
||||
},
|
||||
"language": {
|
||||
"de": "Deutsch",
|
||||
"en": "Englisch"
|
||||
},
|
||||
"actions": {
|
||||
"open": "Öffnen",
|
||||
"viewAll": "Alle anzeigen"
|
||||
}
|
||||
}
|
||||
72
resources/js/admin/i18n/locales/de/dashboard.json
Normal file
72
resources/js/admin/i18n/locales/de/dashboard.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"actions": {
|
||||
"newEvent": "Neues Event",
|
||||
"allEvents": "Alle Events",
|
||||
"guidedSetup": "Guided Setup"
|
||||
},
|
||||
"welcome": {
|
||||
"fallbackName": "Tenant-Admin",
|
||||
"greeting": "Hallo {{name}}!",
|
||||
"subtitle": "Behalte deine Events, Credits und Aufgaben im Blick."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Dashboard konnte nicht geladen werden."
|
||||
},
|
||||
"alerts": {
|
||||
"errorTitle": "Fehler"
|
||||
},
|
||||
"welcomeCard": {
|
||||
"title": "Starte mit der Welcome Journey",
|
||||
"summary": "Lerne die Storytelling-Elemente kennen, wähle dein Paket und erstelle dein erstes Event mit geführten Schritten.",
|
||||
"body1": "Wir begleiten dich durch Pakete, Aufgaben und Galerie-Konfiguration, damit dein Event glänzt.",
|
||||
"body2": "Du kannst jederzeit zur Welcome Journey zurückkehren, auch wenn bereits Events laufen.",
|
||||
"cta": "Jetzt starten"
|
||||
},
|
||||
"overview": {
|
||||
"title": "Kurzer Überblick",
|
||||
"description": "Wichtigste Kennzahlen deines Tenants auf einen Blick.",
|
||||
"noPackage": "Kein aktives Paket",
|
||||
"stats": {
|
||||
"activeEvents": "Aktive Events",
|
||||
"publishedHint": "{{count}} veröffentlicht",
|
||||
"newPhotos": "Neue Fotos (7 Tage)",
|
||||
"taskProgress": "Task-Fortschritt",
|
||||
"credits": "Credits",
|
||||
"lowCredits": "Auffüllen empfohlen"
|
||||
}
|
||||
},
|
||||
"quickActions": {
|
||||
"title": "Schnellaktionen",
|
||||
"description": "Starte durch mit den wichtigsten Aktionen.",
|
||||
"createEvent": {
|
||||
"label": "Event erstellen",
|
||||
"description": "Plane dein nächstes Highlight."
|
||||
},
|
||||
"moderatePhotos": {
|
||||
"label": "Fotos moderieren",
|
||||
"description": "Prüfe neue Uploads."
|
||||
},
|
||||
"organiseTasks": {
|
||||
"label": "Tasks organisieren",
|
||||
"description": "Sorge für klare Verantwortungen."
|
||||
},
|
||||
"manageCredits": {
|
||||
"label": "Credits verwalten",
|
||||
"description": "Sieh dir Balance & Ledger an."
|
||||
}
|
||||
},
|
||||
"upcoming": {
|
||||
"title": "Kommende Events",
|
||||
"description": "Die nächsten Termine inklusive Status & Zugriff.",
|
||||
"settings": "Einstellungen öffnen",
|
||||
"empty": {
|
||||
"message": "Noch keine Termine geplant. Lege dein erstes Event an!",
|
||||
"cta": "Event planen"
|
||||
},
|
||||
"status": {
|
||||
"live": "Live",
|
||||
"planning": "In Planung",
|
||||
"noDate": "Kein Datum"
|
||||
}
|
||||
}
|
||||
}
|
||||
150
resources/js/admin/i18n/locales/de/management.json
Normal file
150
resources/js/admin/i18n/locales/de/management.json
Normal file
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"billing": {
|
||||
"title": "Billing und Credits",
|
||||
"subtitle": "Verwalte Guthaben, Pakete und Abrechnungen.",
|
||||
"actions": {
|
||||
"refresh": "Aktualisieren",
|
||||
"exportCsv": "Export als CSV"
|
||||
},
|
||||
"errors": {
|
||||
"load": "Billing-Daten konnten nicht geladen werden.",
|
||||
"more": "Weitere Ledger-Einträge konnten nicht geladen werden."
|
||||
},
|
||||
"sections": {
|
||||
"overview": {
|
||||
"title": "Credits und Status",
|
||||
"description": "Dein aktuelles Guthaben und das aktive Reseller-Paket.",
|
||||
"cards": {
|
||||
"balance": {
|
||||
"label": "Verfügbare Credits"
|
||||
},
|
||||
"used": {
|
||||
"label": "Genutzte Events",
|
||||
"helper": "Verfügbar: {{count}}"
|
||||
},
|
||||
"price": {
|
||||
"label": "Preis (netto)"
|
||||
},
|
||||
"expires": {
|
||||
"label": "Ablauf",
|
||||
"helper": "Automatisch verlängern, falls aktiv"
|
||||
}
|
||||
}
|
||||
},
|
||||
"packages": {
|
||||
"title": "Paket-Historie",
|
||||
"description": "Übersicht über aktive und vergangene Reseller-Pakete.",
|
||||
"empty": "Noch keine Pakete gebucht.",
|
||||
"card": {
|
||||
"statusActive": "Aktiv",
|
||||
"statusInactive": "Inaktiv",
|
||||
"used": "Genutzte Events",
|
||||
"available": "Verfügbar",
|
||||
"expires": "Ablauf"
|
||||
}
|
||||
},
|
||||
"ledger": {
|
||||
"title": "Credit Ledger",
|
||||
"description": "Alle Zu- und Abbuchungen deines Credits-Kontos.",
|
||||
"empty": "Noch keine Ledger-Einträge vorhanden.",
|
||||
"loadMore": "Mehr laden",
|
||||
"reasons": {
|
||||
"purchase": "Credit-Kauf",
|
||||
"usage": "Verbrauch",
|
||||
"manual": "Manuelle Anpassung"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"members": {
|
||||
"title": "Event-Mitglieder",
|
||||
"subtitle": "Verwalte Moderatoren, Admins und Helfer für dieses Event.",
|
||||
"actions": {
|
||||
"back": "Zurück zur Übersicht"
|
||||
},
|
||||
"errors": {
|
||||
"missingSlug": "Kein Event-Slug angegeben.",
|
||||
"load": "Mitglieder konnten nicht geladen werden.",
|
||||
"emailRequired": "Bitte gib eine E-Mail-Adresse ein.",
|
||||
"invite": "Einladung konnte nicht verschickt werden.",
|
||||
"remove": "Mitglied konnte nicht entfernt werden."
|
||||
},
|
||||
"alerts": {
|
||||
"notFoundTitle": "Event nicht gefunden",
|
||||
"notFoundDescription": "Bitte kehre zur Eventliste zurück.",
|
||||
"lockedTitle": "Feature noch nicht aktiviert",
|
||||
"lockedDescription": "Die Mitgliederverwaltung ist für dieses Event noch nicht verfügbar. Bitte kontaktiere den Support, um das Feature freizuschalten."
|
||||
},
|
||||
"sections": {
|
||||
"list": {
|
||||
"title": "Mitglieder",
|
||||
"empty": "Noch keine Mitglieder eingeladen."
|
||||
},
|
||||
"invite": {
|
||||
"title": "Neues Mitglied einladen"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"status": "Status: {{status}}",
|
||||
"joined": "Beigetreten: {{date}}"
|
||||
},
|
||||
"form": {
|
||||
"emailLabel": "E-Mail",
|
||||
"emailPlaceholder": "person@example.com",
|
||||
"nameLabel": "Name (optional)",
|
||||
"namePlaceholder": "Name",
|
||||
"roleLabel": "Rolle",
|
||||
"rolePlaceholder": "Rolle wählen",
|
||||
"submit": "Einladung senden"
|
||||
},
|
||||
"roles": {
|
||||
"tenantAdmin": "Tenant-Admin",
|
||||
"member": "Mitglied",
|
||||
"guest": "Gast"
|
||||
},
|
||||
"statuses": {
|
||||
"published": "Veröffentlicht",
|
||||
"draft": "Entwurf",
|
||||
"active": "Aktiv"
|
||||
},
|
||||
"eventStatus": "Status: {{status}}",
|
||||
"events": {
|
||||
"untitled": "Unbenanntes Event"
|
||||
}
|
||||
},
|
||||
"tasks": {
|
||||
"title": "Event-Tasks",
|
||||
"subtitle": "Verwalte Aufgaben, die diesem Event zugeordnet sind.",
|
||||
"actions": {
|
||||
"back": "Zurück zur Übersicht",
|
||||
"assign": "Ausgewählte Tasks zuweisen"
|
||||
},
|
||||
"errors": {
|
||||
"missingSlug": "Kein Event-Slug angegeben.",
|
||||
"load": "Event-Tasks konnten nicht geladen werden.",
|
||||
"assign": "Tasks konnten nicht zugewiesen werden."
|
||||
},
|
||||
"alerts": {
|
||||
"notFoundTitle": "Event nicht gefunden",
|
||||
"notFoundDescription": "Bitte kehre zur Eventliste zurück."
|
||||
},
|
||||
"eventStatus": "Status: {{status}}",
|
||||
"sections": {
|
||||
"assigned": {
|
||||
"title": "Zugeordnete Tasks",
|
||||
"empty": "Noch keine Tasks zugewiesen."
|
||||
},
|
||||
"library": {
|
||||
"title": "Tasks aus Bibliothek hinzufügen",
|
||||
"empty": "Keine Tasks in der Bibliothek gefunden."
|
||||
}
|
||||
},
|
||||
"priorities": {
|
||||
"low": "Niedrig",
|
||||
"medium": "Mittel",
|
||||
"high": "Hoch",
|
||||
"urgent": "Dringend"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
268
resources/js/admin/i18n/locales/de/onboarding.json
Normal file
268
resources/js/admin/i18n/locales/de/onboarding.json
Normal file
@@ -0,0 +1,268 @@
|
||||
{
|
||||
"layout": {
|
||||
"eyebrow": "Fotospiel Tenant Admin",
|
||||
"title": "Willkommen im Event-Erlebnisstudio",
|
||||
"subtitle": "Starte mit einer inspirierten Einführung, sichere dir dein Event-Paket und kreiere die perfekte Gästegalerie – alles optimiert für mobile Hosts.",
|
||||
"alreadyFamiliar": "Schon vertraut mit Fotospiel?",
|
||||
"jumpToDashboard": "Direkt zum Dashboard"
|
||||
},
|
||||
"hero": {
|
||||
"eyebrow": "Dein Event, deine Bühne",
|
||||
"title": "Gestalte das nächste Fotospiel Erlebnis",
|
||||
"scriptTitle": "Einmalig für Gäste, mühelos für dich.",
|
||||
"description": "Mit nur wenigen Schritten führst du deine Gäste durch ein magisches Fotoabenteuer – inklusive Storytelling, Aufgaben und moderierter Galerie.",
|
||||
"primary": {
|
||||
"label": "Pakete entdecken",
|
||||
"button": "Pakete entdecken"
|
||||
},
|
||||
"secondary": {
|
||||
"label": "Events anzeigen",
|
||||
"button": "Bestehende Events anzeigen"
|
||||
}
|
||||
},
|
||||
"highlights": {
|
||||
"gallery": {
|
||||
"title": "Premium Gästegalerie",
|
||||
"description": "Kuratiere Fotos in Echtzeit, markiere Highlights und teile QR-Codes mit einem Tap.",
|
||||
"badge": "Neu"
|
||||
},
|
||||
"team": {
|
||||
"title": "Flexibles Team-Onboarding",
|
||||
"description": "Lade Co-Hosts ein, weise Rollen zu und behalte den Überblick über Moderation und Aufgaben."
|
||||
},
|
||||
"story": {
|
||||
"title": "Storytelling in Etappen",
|
||||
"description": "Geführte Aufgaben und Emotionskarten machen jedes Event zu einer erinnerungswürdigen Reise."
|
||||
}
|
||||
},
|
||||
"ctaList": {
|
||||
"choosePackage": {
|
||||
"label": "Dein Eventpaket auswählen",
|
||||
"description": "Reserviere Credits oder Abos, um sofort Events zu aktivieren. Flexible Optionen für jede Eventgröße.",
|
||||
"button": "Weiter zu Paketen"
|
||||
},
|
||||
"createEvent": {
|
||||
"label": "Event vorbereiten",
|
||||
"description": "Sammle Eventdetails, plane Aufgaben und sorge für einen reibungslosen Ablauf noch vor dem Tag des Events.",
|
||||
"button": "Zum Event-Manager"
|
||||
}
|
||||
},
|
||||
"packages": {
|
||||
"layout": {
|
||||
"eyebrow": "Schritt 2",
|
||||
"title": "Wähle dein Eventpaket",
|
||||
"subtitle": "Fotospiel bietet flexible Preismodelle: einmalige Credits oder Abos, die mehrere Events abdecken."
|
||||
},
|
||||
"step": {
|
||||
"title": "Aktiviere die passenden Credits",
|
||||
"description": "Sichere dir Kapazität für dein nächstes Event. Du kannst jederzeit upgraden – bezahle nur, was du brauchst."
|
||||
},
|
||||
"state": {
|
||||
"loading": "Pakete werden geladen …",
|
||||
"errorTitle": "Fehler beim Laden",
|
||||
"errorDescription": "Bitte versuche es erneut oder kontaktiere den Support.",
|
||||
"emptyTitle": "Der Katalog ist leer",
|
||||
"emptyDescription": "Aktuell sind keine Pakete verfügbar. Wende dich an den Support, um neue Angebote freizuschalten."
|
||||
},
|
||||
"card": {
|
||||
"subscription": "Abo",
|
||||
"creditPack": "Credit-Paket",
|
||||
"description": "Sofort einsatzbereit für dein nächstes Event.",
|
||||
"descriptionWithPhotos": "Bis zu {{count}} Fotos inklusive – perfekt für lebendige Reportagen.",
|
||||
"active": "Aktives Paket",
|
||||
"select": "Paket wählen",
|
||||
"onRequest": "Auf Anfrage",
|
||||
"purchased": "Bereits gekauft am {{date}}",
|
||||
"purchasedUnknown": "unbekanntem Datum",
|
||||
"badges": {
|
||||
"guests": "{{count}} Gäste",
|
||||
"days": "{{count}} Tage Galerie",
|
||||
"photos": "{{count}} Fotos"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"subscription": "Abo-Verlängerung",
|
||||
"priority_support": "Priorisierter Support",
|
||||
"custom_domain": "Eigene Domain",
|
||||
"analytics": "Analytics",
|
||||
"team_management": "Teamverwaltung",
|
||||
"moderation_tools": "Moderationstools",
|
||||
"prints": "Print-Uploads"
|
||||
},
|
||||
"cta": {
|
||||
"billing": {
|
||||
"label": "Direkt zum Billing",
|
||||
"description": "Falls du schon weißt, welches Paket du brauchst, gelangst du hier zum bekannten Abrechnungsbereich.",
|
||||
"button": "Billing öffnen"
|
||||
},
|
||||
"summary": {
|
||||
"label": "Bestellübersicht anzeigen",
|
||||
"description": "Prüfe Paketdetails und entscheide, ob du direkt zahlen oder später fortfahren möchtest.",
|
||||
"button": "Weiter zur Übersicht"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": {
|
||||
"layout": {
|
||||
"eyebrow": "Schritt 3",
|
||||
"title": "Bestellübersicht",
|
||||
"subtitle": "Prüfe Paket, Preis und Abrechnung bevor du zum Event-Setup wechselst."
|
||||
},
|
||||
"footer": {
|
||||
"back": "Zurück zur Paketauswahl"
|
||||
},
|
||||
"step": {
|
||||
"title": "Deine Auswahl im Überblick",
|
||||
"description": "Du kannst sofort abrechnen oder das Setup fortsetzen und später bezahlen."
|
||||
},
|
||||
"state": {
|
||||
"loading": "Wir prüfen verfügbare Pakete …",
|
||||
"errorTitle": "Paketdaten derzeit nicht verfügbar",
|
||||
"errorDescription": "Bitte versuche es erneut oder kontaktiere den Support.",
|
||||
"missingTitle": "Keine Paketauswahl gefunden",
|
||||
"missingDescription": "Bitte wähle zuerst ein Paket aus oder aktualisiere die Seite, falls sich Daten geändert haben."
|
||||
},
|
||||
"details": {
|
||||
"subscription": "Abo",
|
||||
"creditPack": "Credit-Paket",
|
||||
"photos": "Bis zu {{count}} Fotos",
|
||||
"galleryDays": "Galerie {{count}} Tage",
|
||||
"guests": "{{count}} Gäste",
|
||||
"infinity": "∞",
|
||||
"features": {
|
||||
"subscription": "Abo",
|
||||
"priority_support": "Priorisierter Support",
|
||||
"custom_domain": "Eigene Domain",
|
||||
"analytics": "Analytics",
|
||||
"team_management": "Teamverwaltung",
|
||||
"moderation_tools": "Moderationstools",
|
||||
"prints": "Print-Uploads"
|
||||
},
|
||||
"section": {
|
||||
"photosTitle": "Fotos & Galerie",
|
||||
"photosValue": "Bis zu {{count}} Fotos, Galerie {{days}} Tage",
|
||||
"photosUnlimited": "Unbegrenzte Fotos, flexible Galerie",
|
||||
"guestsTitle": "Gäste & Team",
|
||||
"guestsValue": "{{count}} Gäste inklusive, Co-Hosts frei planbar",
|
||||
"guestsUnlimited": "Unbegrenzte Gästeliste",
|
||||
"featuresTitle": "Highlights",
|
||||
"featuresNone": "Standard",
|
||||
"statusTitle": "Status",
|
||||
"statusActive": "Bereits gebucht",
|
||||
"statusInactive": "Noch nicht gebucht"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"pendingTitle": "Abrechnung steht noch aus",
|
||||
"pendingDescription": "Du kannst das Event bereits vorbereiten. Spätestens zur Veröffentlichung benötigst du ein aktives Paket."
|
||||
},
|
||||
"free": {
|
||||
"description": "Dieses Paket ist kostenlos. Du kannst es sofort deinem Tenant zuweisen und direkt mit dem Setup weitermachen.",
|
||||
"activate": "Gratis-Paket aktivieren",
|
||||
"progress": "Aktivierung läuft …",
|
||||
"successTitle": "Gratis-Paket aktiviert",
|
||||
"successDescription": "Deine Credits wurden hinzugefügt. Weiter geht's mit dem Event-Setup.",
|
||||
"failureTitle": "Aktivierung fehlgeschlagen",
|
||||
"errorMessage": "Kostenloses Paket konnte nicht aktiviert werden.",
|
||||
},
|
||||
"stripe": {
|
||||
"sectionTitle": "Kartenzahlung (Stripe)",
|
||||
"heading": "Kartenzahlung",
|
||||
"notReady": "Zahlungsmodul noch nicht bereit. Bitte lade die Seite neu.",
|
||||
"genericError": "Zahlung fehlgeschlagen. Bitte erneut versuchen.",
|
||||
"missingPaymentId": "Zahlung konnte nicht bestätigt werden (fehlende Zahlungs-ID).",
|
||||
"completionFailed": "Der Kauf wurde bei uns noch nicht verbucht. Bitte kontaktiere den Support mit deiner Zahlungsbestätigung.",
|
||||
"errorTitle": "Zahlung fehlgeschlagen",
|
||||
"submitting": "Zahlung wird bestätigt …",
|
||||
"submit": "Jetzt bezahlen",
|
||||
"hint": "Sicherer Checkout über Stripe. Du erhältst eine Bestätigung, sobald der Kauf verbucht wurde.",
|
||||
"loading": "Zahlungsdetails werden geladen …",
|
||||
"unavailableTitle": "Stripe nicht verfügbar",
|
||||
"unavailableDescription": "Stripe konnte nicht initialisiert werden.",
|
||||
"missingKey": "Stripe Publishable Key fehlt. Bitte konfiguriere VITE_STRIPE_PUBLISHABLE_KEY.",
|
||||
"intentFailed": "Stripe-Zahlung konnte nicht vorbereitet werden."
|
||||
},
|
||||
"paypal": {
|
||||
"sectionTitle": "PayPal",
|
||||
"heading": "PayPal",
|
||||
"createFailed": "PayPal-Bestellung konnte nicht erstellt werden. Bitte versuche es erneut.",
|
||||
"captureFailed": "PayPal-Zahlung konnte nicht abgeschlossen werden. Bitte kontaktiere den Support, falls der Betrag bereits abgebucht wurde.",
|
||||
"errorTitle": "PayPal-Fehler",
|
||||
"genericError": "PayPal hat ein Problem gemeldet. Bitte versuche es später erneut.",
|
||||
"missingOrderId": "PayPal hat keine Order-ID geliefert.",
|
||||
"cancelled": "PayPal-Zahlung wurde abgebrochen.",
|
||||
"hint": "PayPal leitet dich ggf. weiter, um die Zahlung zu bestätigen. Anschließend kommst du automatisch zurück.",
|
||||
"notConfiguredTitle": "PayPal nicht konfiguriert",
|
||||
"notConfiguredDescription": "Hinterlege VITE_PAYPAL_CLIENT_ID, damit Gastgeber optional mit PayPal bezahlen können."
|
||||
},
|
||||
"nextStepsTitle": "Nächste Schritte",
|
||||
"nextSteps": [
|
||||
"Optional: Abrechnung abschließen (Stripe/PayPal) im Billing-Bereich.",
|
||||
"Event-Setup durchlaufen und Aufgaben, Team & Galerie konfigurieren.",
|
||||
"Vor dem Go-Live Credits prüfen und Gäste-Link teilen."
|
||||
],
|
||||
"cta": {
|
||||
"billing": {
|
||||
"label": "Abrechnung starten",
|
||||
"description": "Öffnet den Billing-Bereich mit allen Kaufoptionen (Stripe, PayPal, Credits).",
|
||||
"button": "Zu Billing & Zahlung"
|
||||
},
|
||||
"setup": {
|
||||
"label": "Mit Event-Setup fortfahren",
|
||||
"description": "Du kannst später jederzeit zur Abrechnung zurückkehren.",
|
||||
"button": "Weiter zum Setup"
|
||||
}
|
||||
}
|
||||
},
|
||||
"eventSetup": {
|
||||
"layout": {
|
||||
"eyebrow": "Schritt 4",
|
||||
"title": "Bereite dein erstes Event vor",
|
||||
"subtitle": "Fülle wenige Details aus, lade Co-Hosts ein und öffne deine Gästegalerie für das große Ereignis."
|
||||
},
|
||||
"step": {
|
||||
"title": "Event-Setup in Minuten",
|
||||
"description": "Wir führen dich durch Name, Datum, Mood und Aufgaben. Danach kannst du Fotos moderieren und Gäste live begleiten."
|
||||
},
|
||||
"tiles": {
|
||||
"story": {
|
||||
"title": "Story & Stimmung",
|
||||
"copy": "Wähle Bildsprache, Farben und Emotionskarten für dein Event."
|
||||
},
|
||||
"team": {
|
||||
"title": "Team organisieren",
|
||||
"copy": "Lade Moderator*innen oder Fotograf*innen ein und teile Rollen zu."
|
||||
},
|
||||
"launch": {
|
||||
"title": "Go-Live vorbereiten",
|
||||
"copy": "Erstelle QR-Codes, teste die Gästegalerie und kommuniziere den Ablauf."
|
||||
}
|
||||
},
|
||||
"cta": {
|
||||
"heading": "Bereit für dein erstes Event?",
|
||||
"description": "Du wechselst jetzt in den Event-Manager. Dort kannst du Tasks zuweisen, Mitglieder einladen und die Gästegalerie testen. Keine Sorge: Du kannst jederzeit zur Welcome Journey zurückkehren.",
|
||||
"button": "Event erstellen"
|
||||
},
|
||||
"actions": {
|
||||
"back": {
|
||||
"label": "Noch einmal Pakete prüfen",
|
||||
"description": "Vergleiche Preise oder aktualisiere dein derzeitiges Paket.",
|
||||
"button": "Zu Paketen"
|
||||
},
|
||||
"dashboard": {
|
||||
"label": "Zum Dashboard",
|
||||
"description": "Springe ins Management, um bestehende Events zu bearbeiten.",
|
||||
"button": "Dashboard öffnen"
|
||||
},
|
||||
"events": {
|
||||
"label": "Eventübersicht",
|
||||
"description": "Behalte den Überblick über aktive und archivierte Events.",
|
||||
"button": "Eventliste"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
21
resources/js/admin/i18n/locales/en/common.json
Normal file
21
resources/js/admin/i18n/locales/en/common.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"app": {
|
||||
"brand": "Fotospiel Tenant Admin",
|
||||
"languageSwitch": "Language"
|
||||
},
|
||||
"navigation": {
|
||||
"dashboard": "Dashboard",
|
||||
"events": "Events",
|
||||
"tasks": "Tasks",
|
||||
"billing": "Billing",
|
||||
"settings": "Settings"
|
||||
},
|
||||
"language": {
|
||||
"de": "German",
|
||||
"en": "English"
|
||||
},
|
||||
"actions": {
|
||||
"open": "Open",
|
||||
"viewAll": "View all"
|
||||
}
|
||||
}
|
||||
72
resources/js/admin/i18n/locales/en/dashboard.json
Normal file
72
resources/js/admin/i18n/locales/en/dashboard.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"actions": {
|
||||
"newEvent": "New Event",
|
||||
"allEvents": "All events",
|
||||
"guidedSetup": "Guided setup"
|
||||
},
|
||||
"welcome": {
|
||||
"fallbackName": "Tenant Admin",
|
||||
"greeting": "Welcome, {{name}}!",
|
||||
"subtitle": "Keep your events, credits, and tasks on track."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Dashboard could not be loaded."
|
||||
},
|
||||
"alerts": {
|
||||
"errorTitle": "Error"
|
||||
},
|
||||
"welcomeCard": {
|
||||
"title": "Start with the welcome journey",
|
||||
"summary": "Discover the storytelling elements, choose your package, and create your first event with guided steps.",
|
||||
"body1": "We guide you through packages, tasks, and gallery setup so your event shines.",
|
||||
"body2": "You can return to the welcome journey at any time, even once events are live.",
|
||||
"cta": "Start now"
|
||||
},
|
||||
"overview": {
|
||||
"title": "At a glance",
|
||||
"description": "Key tenant metrics at a glance.",
|
||||
"noPackage": "No active package",
|
||||
"stats": {
|
||||
"activeEvents": "Active events",
|
||||
"publishedHint": "{{count}} published",
|
||||
"newPhotos": "New photos (7 days)",
|
||||
"taskProgress": "Task progress",
|
||||
"credits": "Credits",
|
||||
"lowCredits": "Top up recommended"
|
||||
}
|
||||
},
|
||||
"quickActions": {
|
||||
"title": "Quick actions",
|
||||
"description": "Jump straight to the most important actions.",
|
||||
"createEvent": {
|
||||
"label": "Create event",
|
||||
"description": "Plan your next highlight."
|
||||
},
|
||||
"moderatePhotos": {
|
||||
"label": "Moderate photos",
|
||||
"description": "Review new uploads."
|
||||
},
|
||||
"organiseTasks": {
|
||||
"label": "Organise tasks",
|
||||
"description": "Assign clear responsibilities."
|
||||
},
|
||||
"manageCredits": {
|
||||
"label": "Manage credits",
|
||||
"description": "Review balance and ledger."
|
||||
}
|
||||
},
|
||||
"upcoming": {
|
||||
"title": "Upcoming events",
|
||||
"description": "The next dates including status and quick access.",
|
||||
"settings": "Open settings",
|
||||
"empty": {
|
||||
"message": "No events scheduled yet. Create your first one!",
|
||||
"cta": "Plan event"
|
||||
},
|
||||
"status": {
|
||||
"live": "Live",
|
||||
"planning": "In planning",
|
||||
"noDate": "No date"
|
||||
}
|
||||
}
|
||||
}
|
||||
149
resources/js/admin/i18n/locales/en/management.json
Normal file
149
resources/js/admin/i18n/locales/en/management.json
Normal file
@@ -0,0 +1,149 @@
|
||||
{
|
||||
"billing": {
|
||||
"title": "Billing & credits",
|
||||
"subtitle": "Manage balances, packages, and invoicing.",
|
||||
"actions": {
|
||||
"refresh": "Refresh",
|
||||
"exportCsv": "Export CSV"
|
||||
},
|
||||
"errors": {
|
||||
"load": "Unable to load billing data.",
|
||||
"more": "Unable to load more ledger entries."
|
||||
},
|
||||
"sections": {
|
||||
"overview": {
|
||||
"title": "Credits & status",
|
||||
"description": "Your current balance and active reseller package.",
|
||||
"cards": {
|
||||
"balance": {
|
||||
"label": "Available credits"
|
||||
},
|
||||
"used": {
|
||||
"label": "Events used",
|
||||
"helper": "Remaining: {{count}}"
|
||||
},
|
||||
"price": {
|
||||
"label": "Price (net)"
|
||||
},
|
||||
"expires": {
|
||||
"label": "Expires",
|
||||
"helper": "Auto-renews when active"
|
||||
}
|
||||
}
|
||||
},
|
||||
"packages": {
|
||||
"title": "Package history",
|
||||
"description": "Overview of active and past reseller packages.",
|
||||
"empty": "No packages purchased yet.",
|
||||
"card": {
|
||||
"statusActive": "Active",
|
||||
"statusInactive": "Inactive",
|
||||
"used": "Events used",
|
||||
"available": "Remaining",
|
||||
"expires": "Expires"
|
||||
}
|
||||
},
|
||||
"ledger": {
|
||||
"title": "Credit ledger",
|
||||
"description": "All credit additions and deductions.",
|
||||
"empty": "No ledger entries recorded yet.",
|
||||
"loadMore": "Load more",
|
||||
"reasons": {
|
||||
"purchase": "Credit purchase",
|
||||
"usage": "Usage",
|
||||
"manual": "Manual adjustment"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"members": {
|
||||
"title": "Event members",
|
||||
"subtitle": "Manage moderators, admins, and helpers for this event.",
|
||||
"actions": {
|
||||
"back": "Back to overview"
|
||||
},
|
||||
"errors": {
|
||||
"missingSlug": "No event slug provided.",
|
||||
"load": "Could not load members.",
|
||||
"emailRequired": "Please provide an email address.",
|
||||
"invite": "Invitation could not be sent.",
|
||||
"remove": "Member could not be removed."
|
||||
},
|
||||
"alerts": {
|
||||
"notFoundTitle": "Event not found",
|
||||
"notFoundDescription": "Please return to the event list.",
|
||||
"lockedTitle": "Feature not enabled",
|
||||
"lockedDescription": "Member management isn’t available for this event yet. Contact support to activate the feature."
|
||||
},
|
||||
"sections": {
|
||||
"list": {
|
||||
"title": "Members",
|
||||
"empty": "No members invited yet."
|
||||
},
|
||||
"invite": {
|
||||
"title": "Invite new member"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"status": "Status: {{status}}",
|
||||
"joined": "Joined: {{date}}"
|
||||
},
|
||||
"form": {
|
||||
"emailLabel": "Email",
|
||||
"emailPlaceholder": "person@example.com",
|
||||
"nameLabel": "Name (optional)",
|
||||
"namePlaceholder": "Name",
|
||||
"roleLabel": "Role",
|
||||
"rolePlaceholder": "Select role",
|
||||
"submit": "Send invitation"
|
||||
},
|
||||
"roles": {
|
||||
"tenantAdmin": "Tenant admin",
|
||||
"member": "Member",
|
||||
"guest": "Guest"
|
||||
},
|
||||
"statuses": {
|
||||
"published": "Published",
|
||||
"draft": "Draft",
|
||||
"active": "Active"
|
||||
},
|
||||
"eventStatus": "Status: {{status}}",
|
||||
"events": {
|
||||
"untitled": "Untitled event"
|
||||
}
|
||||
},
|
||||
"tasks": {
|
||||
"title": "Event tasks",
|
||||
"subtitle": "Manage tasks associated with this event.",
|
||||
"actions": {
|
||||
"back": "Back to overview",
|
||||
"assign": "Assign selected tasks"
|
||||
},
|
||||
"errors": {
|
||||
"missingSlug": "No event slug provided.",
|
||||
"load": "Event tasks could not be loaded.",
|
||||
"assign": "Tasks could not be assigned."
|
||||
},
|
||||
"alerts": {
|
||||
"notFoundTitle": "Event not found",
|
||||
"notFoundDescription": "Please return to the event list."
|
||||
},
|
||||
"eventStatus": "Status: {{status}}",
|
||||
"sections": {
|
||||
"assigned": {
|
||||
"title": "Assigned tasks",
|
||||
"empty": "No tasks assigned yet."
|
||||
},
|
||||
"library": {
|
||||
"title": "Add tasks from library",
|
||||
"empty": "No tasks found in the library."
|
||||
}
|
||||
},
|
||||
"priorities": {
|
||||
"low": "Low",
|
||||
"medium": "Medium",
|
||||
"high": "High",
|
||||
"urgent": "Urgent"
|
||||
}
|
||||
}
|
||||
}
|
||||
264
resources/js/admin/i18n/locales/en/onboarding.json
Normal file
264
resources/js/admin/i18n/locales/en/onboarding.json
Normal file
@@ -0,0 +1,264 @@
|
||||
{
|
||||
"layout": {
|
||||
"eyebrow": "Fotospiel Tenant Admin",
|
||||
"title": "Welcome to your event studio",
|
||||
"subtitle": "Begin with an inspired introduction, secure your package, and craft the perfect guest gallery – all optimised for mobile hosts.",
|
||||
"alreadyFamiliar": "Already familiar with Fotospiel?",
|
||||
"jumpToDashboard": "Jump to dashboard"
|
||||
},
|
||||
"hero": {
|
||||
"eyebrow": "Your event, your stage",
|
||||
"title": "Design the next Fotospiel experience",
|
||||
"scriptTitle": "Memorable for guests, effortless for you.",
|
||||
"description": "In just a few steps you guide guests through a magical photo journey – complete with storytelling, tasks, and a moderated gallery.",
|
||||
"primary": {
|
||||
"label": "Explore packages",
|
||||
"button": "Explore packages"
|
||||
},
|
||||
"secondary": {
|
||||
"label": "View events",
|
||||
"button": "View existing events"
|
||||
}
|
||||
},
|
||||
"highlights": {
|
||||
"gallery": {
|
||||
"title": "Premium guest gallery",
|
||||
"description": "Curate photos in real time, highlight favourites, and share QR codes in a tap.",
|
||||
"badge": "New"
|
||||
},
|
||||
"team": {
|
||||
"title": "Flexible team onboarding",
|
||||
"description": "Invite co-hosts, assign roles, and stay on top of moderation and tasks."
|
||||
},
|
||||
"story": {
|
||||
"title": "Storytelling in chapters",
|
||||
"description": "Guided tasks and emotion cards turn every event into a memorable journey."
|
||||
}
|
||||
},
|
||||
"ctaList": {
|
||||
"choosePackage": {
|
||||
"label": "Choose your package",
|
||||
"description": "Reserve credits or subscriptions to activate events instantly. Flexible options for any event size.",
|
||||
"button": "Continue to packages"
|
||||
},
|
||||
"createEvent": {
|
||||
"label": "Prepare event",
|
||||
"description": "Collect event details, plan tasks, and ensure a smooth flow before the big day.",
|
||||
"button": "Go to event manager"
|
||||
}
|
||||
},
|
||||
"packages": {
|
||||
"layout": {
|
||||
"eyebrow": "Step 2",
|
||||
"title": "Choose your package",
|
||||
"subtitle": "Fotospiel supports flexible pricing: single-use credits or subscriptions covering multiple events."
|
||||
},
|
||||
"step": {
|
||||
"title": "Activate the right credits",
|
||||
"description": "Secure capacity for your next event. Upgrade at any time – only pay for what you need."
|
||||
},
|
||||
"state": {
|
||||
"loading": "Loading packages …",
|
||||
"errorTitle": "Failed to load",
|
||||
"errorDescription": "Please try again or contact support.",
|
||||
"emptyTitle": "Catalogue is empty",
|
||||
"emptyDescription": "No packages are currently available. Reach out to support to enable new offers."
|
||||
},
|
||||
"card": {
|
||||
"subscription": "Subscription",
|
||||
"creditPack": "Credit pack",
|
||||
"description": "Ready for your next event right away.",
|
||||
"descriptionWithPhotos": "Up to {{count}} photos included – perfect for vibrant storytelling.",
|
||||
"active": "Active package",
|
||||
"select": "Select package",
|
||||
"onRequest": "On request",
|
||||
"purchased": "Purchased on {{date}}",
|
||||
"purchasedUnknown": "unknown date",
|
||||
"badges": {
|
||||
"guests": "{{count}} guests",
|
||||
"days": "{{count}} gallery days",
|
||||
"photos": "{{count}} photos"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"subscription": "Subscription",
|
||||
"priority_support": "Priority support",
|
||||
"custom_domain": "Custom domain",
|
||||
"analytics": "Analytics",
|
||||
"team_management": "Team management",
|
||||
"moderation_tools": "Moderation tools",
|
||||
"prints": "Print uploads"
|
||||
},
|
||||
"cta": {
|
||||
"billing": {
|
||||
"label": "Go to billing",
|
||||
"description": "Already know what you need? Jump straight to the billing area you know.",
|
||||
"button": "Open billing"
|
||||
},
|
||||
"summary": {
|
||||
"label": "View order summary",
|
||||
"description": "Review package details and decide whether to pay now or later.",
|
||||
"button": "Continue to summary"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": {
|
||||
"layout": {
|
||||
"eyebrow": "Step 3",
|
||||
"title": "Order summary",
|
||||
"subtitle": "Review package, price, and payment before proceeding to the event setup."
|
||||
},
|
||||
"footer": {
|
||||
"back": "Back to package selection"
|
||||
},
|
||||
"step": {
|
||||
"title": "Your selection at a glance",
|
||||
"description": "Hand off to billing now or continue setup and pay later."
|
||||
},
|
||||
"state": {
|
||||
"loading": "Checking available packages …",
|
||||
"errorTitle": "Package data temporarily unavailable",
|
||||
"errorDescription": "Please try again or contact support.",
|
||||
"missingTitle": "No package selected",
|
||||
"missingDescription": "Select a package first or refresh if data changed."
|
||||
},
|
||||
"details": {
|
||||
"subscription": "Subscription",
|
||||
"creditPack": "Credit pack",
|
||||
"photos": "Up to {{count}} photos",
|
||||
"galleryDays": "{{count}} gallery days",
|
||||
"guests": "{{count}} guests",
|
||||
"infinity": "∞",
|
||||
"features": {
|
||||
"subscription": "Subscription",
|
||||
"priority_support": "Priority support",
|
||||
"custom_domain": "Custom domain",
|
||||
"analytics": "Analytics",
|
||||
"team_management": "Team management",
|
||||
"moderation_tools": "Moderation tools",
|
||||
"prints": "Print uploads"
|
||||
},
|
||||
"section": {
|
||||
"photosTitle": "Photos & gallery",
|
||||
"photosValue": "Up to {{count}} photos, gallery {{days}} days",
|
||||
"photosUnlimited": "Unlimited photos, flexible gallery",
|
||||
"guestsTitle": "Guests & team",
|
||||
"guestsValue": "{{count}} guests included, co-hosts flexible",
|
||||
"guestsUnlimited": "Unlimited guest list",
|
||||
"featuresTitle": "Highlights",
|
||||
"featuresNone": "Standard",
|
||||
"statusTitle": "Status",
|
||||
"statusActive": "Already purchased",
|
||||
"statusInactive": "Not purchased yet"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"pendingTitle": "Payment still pending",
|
||||
"pendingDescription": "You can start preparing the event. An active package is required before going live."
|
||||
},
|
||||
"free": {
|
||||
"description": "This package is free. Assign it to your tenant and continue immediately.",
|
||||
"activate": "Activate free package",
|
||||
"progress": "Activating …",
|
||||
"successTitle": "Free package activated",
|
||||
"successDescription": "Credits added. Continue with the setup.",
|
||||
"failureTitle": "Activation failed",
|
||||
"errorMessage": "The free package could not be activated."
|
||||
},
|
||||
"stripe": {
|
||||
"sectionTitle": "Card payment (Stripe)",
|
||||
"heading": "Card payment",
|
||||
"notReady": "Payment module not ready yet. Please refresh.",
|
||||
"genericError": "Payment failed. Please try again.",
|
||||
"missingPaymentId": "Could not confirm payment (missing payment ID).",
|
||||
"completionFailed": "Purchase not recorded yet. Contact support with your payment confirmation.",
|
||||
"errorTitle": "Payment failed",
|
||||
"submitting": "Confirming payment …",
|
||||
"submit": "Pay now",
|
||||
"hint": "Secure checkout via Stripe. You'll receive confirmation once recorded.",
|
||||
"loading": "Loading payment details …",
|
||||
"unavailableTitle": "Stripe unavailable",
|
||||
"unavailableDescription": "Stripe could not be initialised.",
|
||||
"missingKey": "Stripe publishable key missing. Configure VITE_STRIPE_PUBLISHABLE_KEY.",
|
||||
"intentFailed": "Stripe could not prepare the payment."
|
||||
},
|
||||
"paypal": {
|
||||
"sectionTitle": "PayPal",
|
||||
"heading": "PayPal",
|
||||
"createFailed": "PayPal order could not be created. Please try again.",
|
||||
"captureFailed": "PayPal payment could not be captured. Contact support if funds were withdrawn.",
|
||||
"errorTitle": "PayPal error",
|
||||
"genericError": "PayPal reported a problem. Please try again later.",
|
||||
"missingOrderId": "PayPal did not return an order ID.",
|
||||
"cancelled": "PayPal payment was cancelled.",
|
||||
"hint": "PayPal may redirect you briefly to confirm. You'll return automatically afterwards.",
|
||||
"notConfiguredTitle": "PayPal not configured",
|
||||
"notConfiguredDescription": "Provide VITE_PAYPAL_CLIENT_ID so hosts can pay with PayPal."
|
||||
},
|
||||
"nextStepsTitle": "Next steps",
|
||||
"nextSteps": [
|
||||
"Optional: finish billing (Stripe/PayPal) inside the billing area.",
|
||||
"Complete the event setup and configure tasks, team, and gallery.",
|
||||
"Check credits before go-live and share your guest link."
|
||||
],
|
||||
"cta": {
|
||||
"billing": {
|
||||
"label": "Start billing",
|
||||
"description": "Opens the billing area with Stripe, PayPal, and credit options.",
|
||||
"button": "Go to billing"
|
||||
},
|
||||
"setup": {
|
||||
"label": "Continue to event setup",
|
||||
"description": "You can return to billing any time.",
|
||||
"button": "Continue to setup"
|
||||
}
|
||||
}
|
||||
},
|
||||
"eventSetup": {
|
||||
"layout": {
|
||||
"eyebrow": "Step 4",
|
||||
"title": "Prepare your first event",
|
||||
"subtitle": "Fill in a few details, invite co-hosts, and open your guest gallery for the big day."
|
||||
},
|
||||
"step": {
|
||||
"title": "Event setup in minutes",
|
||||
"description": "We guide you through name, date, mood, and tasks. Afterwards you can moderate photos and support guests live."
|
||||
},
|
||||
"tiles": {
|
||||
"story": {
|
||||
"title": "Story & mood",
|
||||
"copy": "Pick imagery, colours, and emotion cards for your event."
|
||||
},
|
||||
"team": {
|
||||
"title": "Organise your team",
|
||||
"copy": "Invite moderators or photographers and assign roles."
|
||||
},
|
||||
"launch": {
|
||||
"title": "Prepare go-live",
|
||||
"copy": "Create QR codes, test the gallery, and align the run of show."
|
||||
}
|
||||
},
|
||||
"cta": {
|
||||
"heading": "Ready for your first event?",
|
||||
"description": "You're switching to the event manager. Assign tasks, invite members, and test the gallery. You can always return to the welcome journey.",
|
||||
"button": "Create event"
|
||||
},
|
||||
"actions": {
|
||||
"back": {
|
||||
"label": "Review packages again",
|
||||
"description": "Compare pricing or update your current package.",
|
||||
"button": "Back to packages"
|
||||
},
|
||||
"dashboard": {
|
||||
"label": "Go to dashboard",
|
||||
"description": "Jump into management to edit existing events.",
|
||||
"button": "Open dashboard"
|
||||
},
|
||||
"events": {
|
||||
"label": "Event overview",
|
||||
"description": "Keep track of active and archived events.",
|
||||
"button": "Open event list"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user