- Datenmodell: Tenant.tier (Default PROFI), lotseChatSeats, lotseChatHardLimit;
Tabelle lotse_chat_seats (RLS, TENANT_MODELS, pii-fields), Index für die
Monatszählung der Chat-Nachrichten (Migration 20260921100000_pakete)
- src/lib/plans.ts: Stufenregeln, 150 Chats je Platz, Mehrverbrauch in 100er-Paketen
- src/server/plan.ts: effektive Freischaltung = Stufe UND TenantModule, genutzt von
requireModule, assertModuleEnabled, API, Sync (Offline-Op → rejected mit Klartext),
Navigation, isLotseEnabled und planningAccess (Planung nur in Profi)
- Lotse-Chat: Platzprüfung (no_seat), Testphase ohne Platz, Kontingent mit
hartem Limit (quota_exhausted); Platzvergabe durch den Mandanten-Admin
- Betreiber: Stufe/Plätze/hartes Limit im Mandantendetail mit Bestätigung
und Plattform-Audit, Verbrauch laufender Monat/Vormonat, Stufe als Badge
- Demo-Seed: demo = Profi mit 3 Plätzen, demo2 = Basis
- Tests: test-pakete-{rules,gates,seats}
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
177 lines
8.7 KiB
JSON
177 lines
8.7 KiB
JSON
{
|
||
"badge": {
|
||
"label": "Synchronisation öffnen",
|
||
"synced": "Synchron",
|
||
"pending": "{count} offen",
|
||
"problem": "Prüfen",
|
||
"syncing": "Sync …"
|
||
},
|
||
"update": {
|
||
"available": "Neue Version verfügbar – neu laden",
|
||
"reload": "Neu laden"
|
||
},
|
||
"sync": {
|
||
"title": "Synchronisation",
|
||
"connection": "Verbindung",
|
||
"offlineHint": "Eingaben werden auf diesem Gerät gespeichert und übertragen, sobald wieder Verbindung besteht.",
|
||
"lastSync": "Letzte Synchronisation",
|
||
"lastPull": "Aufträge offline gespeichert",
|
||
"never": "Noch nie",
|
||
"stale": "Die Offline-Daten sind älter als {days} Tage. Bitte mit Verbindung aktualisieren.",
|
||
"status": "Stand",
|
||
"pendingOps": "{count, plural, =0 {Keine Änderungen offen} one {# Änderung wartet auf Übertragung} other {# Änderungen warten auf Übertragung}}",
|
||
"pendingUploads": "{count, plural, =0 {Keine Dateien offen} one {# Datei wartet auf Upload} other {# Dateien warten auf Upload}}",
|
||
"uploadSize": "{size} zu übertragen",
|
||
"uploading": "Datei wird hochgeladen … {percent} %",
|
||
"syncing": "Wird synchronisiert …",
|
||
"syncNow": "Jetzt synchronisieren",
|
||
"allSynced": "Alles übertragen.",
|
||
"waitingForAuth": "Anmeldung abgelaufen. Bitte neu anmelden – Ihre Eingaben bleiben auf dem Gerät gespeichert.",
|
||
"login": "Neu anmelden",
|
||
"problems": "Fehler und Konflikte",
|
||
"noProblems": "Keine Fehler oder Konflikte.",
|
||
"queue": "Warteschlange",
|
||
"attempts": "{count, plural, one {# Versuch} other {# Versuche}}",
|
||
"nextAttempt": "Nächster Versuch um {time}",
|
||
"createdAt": "Erfasst {time}",
|
||
"retry": "Erneut versuchen",
|
||
"discard": "Eintrag verwerfen",
|
||
"discardConfirm": "Eintrag endgültig verwerfen? Die Eingabe geht verloren.",
|
||
"discardYes": "Endgültig verwerfen",
|
||
"cancel": "Abbrechen",
|
||
"hide": "Hinweis ausblenden",
|
||
"storage": "Speicher auf diesem Gerät",
|
||
"storageUsage": "{usage} von {quota} belegt",
|
||
"storagePersisted": "Offline-Daten sind dauerhaft gespeichert.",
|
||
"storageNotPersisted": "Der Browser darf Offline-Daten bei Speichermangel löschen.",
|
||
"storageUnknown": "Speicherverbrauch nicht verfügbar.",
|
||
"offlineOrders": "{count, plural, =0 {Keine Aufträge offline verfügbar} one {# Auftrag offline verfügbar} other {# Aufträge offline verfügbar}}",
|
||
"saveOffline": "Für offline speichern",
|
||
"saveOfflineHint": "Heutige, kommende 3 Tage und laufende Aufträge inklusive Zeichnungen, Montageanleitungen und Sicherheitsunterlagen.",
|
||
"openOffline": "Offline-Ansicht öffnen",
|
||
"reset": "Lokale Daten zurücksetzen",
|
||
"resetConfirm": "Alle Offline-Daten Ihres Kontos auf diesem Gerät löschen?",
|
||
"resetWarning": "{count, plural, one {# Eingabe wurde} other {# Eingaben wurden}} noch nicht übertragen und {count, plural, one {geht} other {gehen}} verloren.",
|
||
"resetYes": "Jetzt zurücksetzen",
|
||
"resetDone": "Lokale Daten gelöscht."
|
||
},
|
||
"op": {
|
||
"session_start": "Einsatz gestartet",
|
||
"session_pause": "Pause",
|
||
"session_resume": "Weiter",
|
||
"session_end": "Zeiterfassung beendet",
|
||
"work_order_transition": "Statusänderung",
|
||
"note_create": "Notiz",
|
||
"checklist_toggle": "Checkliste",
|
||
"material_upsert": "Material",
|
||
"photo_attach": "Foto",
|
||
"voice_attach": "Sprachnotiz",
|
||
"report_save_draft": "Berichtsentwurf",
|
||
"report_submit": "Bericht",
|
||
"signature_capture": "Unterschrift",
|
||
"emergency_create": "Notdiensteinsatz"
|
||
},
|
||
"state": {
|
||
"queued": "Wartet",
|
||
"sending": "Wird gesendet",
|
||
"applied": "Übertragen",
|
||
"conflict": "Konflikt",
|
||
"rejected": "Nicht übernommen"
|
||
},
|
||
"problem": {
|
||
"conflictTransition": "Auftrag wurde im Büro geändert – Ihre Statusänderung wurde nicht übernommen. Das Büro prüft den Vorgang.",
|
||
"conflictReport": "Auftrag wurde im Büro geändert – Ihr Bericht wurde nicht übernommen. Das Büro prüft den Vorgang.",
|
||
"conflict": "Auftrag wurde im Büro geändert – Ihre Änderung wurde nicht übernommen. Das Büro prüft den Vorgang.",
|
||
"notFound": "Der Auftrag ist nicht mehr für Sie freigegeben. Die Eingabe wurde nicht übernommen.",
|
||
"forbidden": "Für diese Aktion fehlt Ihnen die Berechtigung.",
|
||
"blocked": "Pflichtangaben fehlen noch – bitte am Auftrag ergänzen und erneut versuchen.",
|
||
"invalid": "Die Eingabe ist unvollständig oder nicht mehr gültig.",
|
||
"upload": "Die Datei wurde nicht angenommen (Format oder Größe).",
|
||
"unauthorized": "Anmeldung abgelaufen – bitte neu anmelden.",
|
||
"network": "Keine Verbindung – wird automatisch erneut versucht.",
|
||
"internal": "Technischer Fehler – wird automatisch erneut versucht.",
|
||
"timeOverlap": "Der Zeitnachtrag überschneidet sich mit einer bereits erfassten Zeit und wurde nicht übernommen.",
|
||
"timeWindow": "Der Zeitnachtrag liegt außerhalb der erlaubten 7 Tage, in der Zukunft oder ist zu lang und wurde nicht übernommen.",
|
||
"otherSession": "Auf einem anderen Auftrag lief noch eine Zeiterfassung – der Start wurde nicht übernommen. Bitte erneut starten und wechseln.",
|
||
"notInPlan": "Im Paket Profi enthalten – für diesen Betrieb nicht freigeschaltet. Die Eingabe wurde nicht übernommen, bitte im Büro melden.",
|
||
"moduleDisabled": "Diese Funktion ist für diesen Betrieb ausgeschaltet. Die Eingabe wurde nicht übernommen, bitte im Büro melden."
|
||
},
|
||
"view": {
|
||
"title": "Offline-Ansicht",
|
||
"offlineHint": "Keine Verbindung. Sie sehen die auf diesem Gerät gespeicherten Aufträge.",
|
||
"onlineHint": "Verbindung besteht wieder.",
|
||
"backOnline": "Zur normalen Ansicht",
|
||
"empty": "Keine Aufträge auf diesem Gerät gespeichert. Mit Verbindung werden heutige und kommende Aufträge automatisch gespeichert.",
|
||
"loading": "Offline-Daten werden geladen …",
|
||
"notReady": "Offline-Daten sind erst nach einer Anmeldung mit Verbindung verfügbar.",
|
||
"notFound": "Dieser Auftrag ist nicht auf dem Gerät gespeichert.",
|
||
"backToList": "Alle gespeicherten Aufträge",
|
||
"open": "Auftrag öffnen",
|
||
"count": "{count, plural, one {# Auftrag} other {# Aufträge}}",
|
||
"pending": "{count, plural, one {# Änderung wartet} other {# Änderungen warten}}",
|
||
"conflict": "Konflikt – siehe Synchronisation",
|
||
"rejected": "Nicht übernommen – siehe Synchronisation",
|
||
"savedAt": "Stand: {time}",
|
||
"noDate": "Ohne Termin",
|
||
"customer": "Kunde",
|
||
"site": "Objekt",
|
||
"contact": "Ansprechpartner",
|
||
"call": "Anrufen",
|
||
"access": "Zugang",
|
||
"parking": "Parken",
|
||
"safety": "Sicherheit",
|
||
"technical": "Technik",
|
||
"hints": "Hinweise für Monteure",
|
||
"scope": "Leistungsumfang",
|
||
"description": "Beschreibung",
|
||
"checklist": "Checkliste",
|
||
"checklistEmpty": "Keine Checkliste.",
|
||
"required": "Pflicht",
|
||
"done": "Erledigt",
|
||
"open_item": "Offen",
|
||
"materials": "Material",
|
||
"materialsProgress": "{done} von {total} Positionen erfasst",
|
||
"documents": "Dokumente",
|
||
"noDocuments": "Keine Dokumente.",
|
||
"docOffline": "Offline verfügbar",
|
||
"docOnline": "Nur mit Verbindung",
|
||
"history": "Objekt-Historie",
|
||
"noHistory": "Keine freigegebenen Berichte am Objekt.",
|
||
"notes": "Notizen",
|
||
"notePlaceholder": "Kurz beschreiben, was vor Ort passiert ist …",
|
||
"noteSave": "Notiz speichern",
|
||
"draftRestored": "Entwurf wiederhergestellt.",
|
||
"photos": "Fotos",
|
||
"photo": "Foto aufnehmen",
|
||
"photoRequirements": "Pflichtfotos",
|
||
"photoMissing": "Fehlt",
|
||
"photoDone": "Vorhanden",
|
||
"pendingBadge": "Wartet auf Übertragung",
|
||
"time": "Zeiterfassung",
|
||
"actionAccept": "Annehmen",
|
||
"actionTravel": "Losfahren",
|
||
"actionStart": "Arbeit starten",
|
||
"actionPause": "Pause",
|
||
"actionResume": "Weiter",
|
||
"actionEnd": "Zeiterfassung beenden",
|
||
"completeOnline": "Abschließen ist nur mit Verbindung möglich (Pflichtangaben werden geprüft).",
|
||
"saving": "Wird gespeichert …",
|
||
"queued": "Gespeichert – wird übertragen, sobald Verbindung besteht.",
|
||
"saved": "Gespeichert und übertragen.",
|
||
"error": "Konnte nicht gespeichert werden."
|
||
},
|
||
"logout": {
|
||
"warning": "{count, plural, one {# Eingabe wurde} other {# Eingaben wurden}} noch nicht übertragen. Beim Abmelden werden die Offline-Daten dieses Geräts gelöscht – {count, plural, one {die Eingabe geht} other {die Eingaben gehen}} verloren.",
|
||
"syncFirst": "Erst synchronisieren",
|
||
"confirm": "Trotzdem abmelden",
|
||
"cancel": "Abbrechen"
|
||
},
|
||
"install": {
|
||
"title": "App auf dem Gerät",
|
||
"installed": "Craftvia ist als App installiert.",
|
||
"button": "Auf dem Startbildschirm installieren",
|
||
"ios": "Auf iPhone oder iPad: unten das Teilen-Symbol antippen und „Zum Home-Bildschirm“ wählen.",
|
||
"other": "Im Browser-Menü „App installieren“ oder „Zum Startbildschirm hinzufügen“ wählen."
|
||
}
|
||
}
|