Organization writes were superadmin-only, so standing up a tenant needed an out-of-band superadmin. Creating one is now self-service, and an admin manages the org they belong to. - POST /api/orgs is open to any authenticated user. A creator who isn't a superadmin must have no organization yet (a single-valued membership relation means a second one would abandon the first), and is promoted to the new org's admin and first member in the same request. If that promotion fails the org is rolled back, so it is never left stranded with nobody able to administer it. Superadmins still create tenants without joining them. - PATCH/DELETE are manager-gated and scope an admin to their own org. An admin deletes theirs only as its sole member: they are detached and demoted to a plain user before the record goes, so the org is empty when it is removed. Other members still block deletion with a 409. - /api/me now carries organization + organizationName, which the clients need to tell "no org yet" from "org you administer". The panel, Web App (new OrgManager.vue in Settings) and Phone App (new _OrganizationSection) all mirror the server's gates rather than re-deciding them. The Phone App cached its role at login and gates the Users tab on it, so AuthService.adoptRole refreshes that from the profile instead of making a freshly promoted admin sign in again. Covered by orgs_test.go, which drives the real handler + middleware chain against a stand-in PocketBase: promotion, the already-a-member refusal, superadmin staying unattached, the rollback, own-org scoping, the detach-and-demote, and the blocking-member 409. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
252 lines
9.7 KiB
JSON
252 lines
9.7 KiB
JSON
{
|
|
"common": {
|
|
"save": "Zapisz",
|
|
"saving": "Zapisywanie…",
|
|
"saved": "Zapisano ✓",
|
|
"cancel": "Anuluj",
|
|
"remove": "Usuń",
|
|
"retry": "Ponów",
|
|
"required": "Wymagane",
|
|
"confirm": "Potwierdź",
|
|
"empty": "—"
|
|
},
|
|
"nav": {
|
|
"garage": "Garaż",
|
|
"charging": "Ładowanie",
|
|
"settings": "Ustawienia",
|
|
"users": "Użytkownicy"
|
|
},
|
|
"login": {
|
|
"tagline": "Twój samochód pod kontrolą.",
|
|
"email": "E-mail",
|
|
"password": "Hasło",
|
|
"showPassword": "Pokaż hasło",
|
|
"hidePassword": "Ukryj hasło",
|
|
"submit": "Zaloguj się",
|
|
"submitting": "Logowanie…",
|
|
"or": "lub",
|
|
"signInWithFace": "Zaloguj się rozpoznawaniem twarzy",
|
|
"signInWithFingerprint": "Zaloguj się odciskiem palca",
|
|
"signInWithBiometrics": "Zaloguj się biometrią",
|
|
"enrollTitle": "Włączyć logowanie biometryczne?",
|
|
"enrollBody": "Następnym razem możesz zalogować się za pomocą {method} zamiast wpisywać hasło.",
|
|
"enrollNotNow": "Nie teraz",
|
|
"enrollEnable": "Włącz",
|
|
"methodFace": "rozpoznawania twarzy",
|
|
"methodFingerprint": "odcisku palca",
|
|
"methodBiometrics": "biometrii",
|
|
"bioReasonSignInAs": "Zaloguj się jako {email}",
|
|
"bioReasonSignIn": "Zaloguj się do DriverVault",
|
|
"savedInvalid": "Zapisane dane logowania są już nieważne. Zaloguj się hasłem.",
|
|
"serverSettings": "Ustawienia serwera",
|
|
"apiServerUrl": "Adres serwera API",
|
|
"leaveBlank": "Pozostaw puste, aby użyć domyślnego.",
|
|
"reset": "Resetuj",
|
|
"savedNote": "Zapisano ✓",
|
|
"resetNote": "Zresetowano ✓"
|
|
},
|
|
"lock": {
|
|
"title": "DriverVault jest zablokowany",
|
|
"reason": "Odblokuj DriverVault",
|
|
"unlock": "Odblokuj",
|
|
"unlocking": "Odblokowywanie…",
|
|
"usePassword": "Użyj hasła"
|
|
},
|
|
"dashboard": {
|
|
"eyebrow": "TWOJE SAMOCHODY",
|
|
"title": "Garaż",
|
|
"addCar": "Dodaj samochód",
|
|
"lightMode": "Tryb jasny",
|
|
"darkMode": "Tryb ciemny",
|
|
"logOut": "Wyloguj się",
|
|
"empty": "Nie masz jeszcze samochodów.",
|
|
"shared": "Udostępniony",
|
|
"sharedReadOnly": "Udostępniony · tylko do odczytu",
|
|
"serviceLife": "ZUŻYCIE OKRESU SERWISOWEGO",
|
|
"lastService": "Ostatni serwis",
|
|
"currentOdometer": "Aktualny przebieg",
|
|
"nextDue": "Następny termin",
|
|
"nextDueKm": "Następny przebieg",
|
|
"serviceRecords": {
|
|
"one": "{n} wpis serwisowy",
|
|
"few": "{n} wpisy serwisowe",
|
|
"many": "{n} wpisów serwisowych",
|
|
"other": "{n} wpisu serwisowego"
|
|
}
|
|
},
|
|
"charging": {
|
|
"eyebrow": "ŁADOWANIE I MAPA",
|
|
"title": "Ładowarki w pobliżu",
|
|
"tabs": {
|
|
"public": "Ładowarki publiczne",
|
|
"home": "Ładowarki domowe"
|
|
},
|
|
"liveMap": "Mapa na żywo",
|
|
"youAreHere": "Tu jesteś",
|
|
"session": {
|
|
"chargingNow": "Ładowanie w toku",
|
|
"rate": "Moc",
|
|
"added": "Dodano",
|
|
"cost": "Koszt",
|
|
"done": "Koniec",
|
|
"stop": "Zatrzymaj ładowanie",
|
|
"idle": "Brak ładowania",
|
|
"idleHint": "Podłącz na stacji, aby rozpocząć sesję."
|
|
},
|
|
"stations": {
|
|
"heading": "W pobliżu",
|
|
"homeHeading": "Twoje ładowarki",
|
|
"noControlHint": "Włącz tryb Own lub Proxy CSMS w Ustawienia → Integracje, aby sterować domową ładowarką.",
|
|
"count": {
|
|
"one": "{n} stacja",
|
|
"few": "{n} stacje",
|
|
"many": "{n} stacji",
|
|
"other": "{n} stacji"
|
|
},
|
|
"free": "{avail} z {total} wolnych",
|
|
"full": "Zajęte",
|
|
"offPeak": "poza szczytem",
|
|
"homeCharger": "Ładowarka domowa"
|
|
}
|
|
},
|
|
"settings": {
|
|
"tabs": {
|
|
"personal": "Ustawienia osobiste",
|
|
"integrations": "Integracje"
|
|
},
|
|
"title": "Ustawienia",
|
|
"account": {
|
|
"title": "Konto",
|
|
"name": "Imię i nazwisko",
|
|
"nameSaved": "Zapisano imię i nazwisko.",
|
|
"email": "E-mail",
|
|
"verified": "Zweryfikowany",
|
|
"notVerified": "Niezweryfikowany",
|
|
"sending": "Wysyłanie…",
|
|
"resendVerification": "Wyślij ponownie e-mail weryfikacyjny",
|
|
"verificationRequested": "Zamówiono e-mail weryfikacyjny.",
|
|
"changePassword": "Zmień hasło",
|
|
"currentPassword": "Obecne hasło",
|
|
"newPassword": "Nowe hasło (min. 8)",
|
|
"confirmNewPassword": "Potwierdź nowe hasło",
|
|
"tooShort": "Nowe hasło musi mieć co najmniej 8 znaków.",
|
|
"mismatch": "Nowe hasło i potwierdzenie nie są takie same.",
|
|
"passwordUpdated": "Hasło zaktualizowane.",
|
|
"updating": "Aktualizowanie…",
|
|
"updatePassword": "Zaktualizuj hasło"
|
|
},
|
|
"appearance": {
|
|
"title": "Wygląd",
|
|
"theme": "Motyw",
|
|
"themeLight": "Jasny",
|
|
"themeDark": "Ciemny",
|
|
"themeSystem": "Systemowy",
|
|
"language": "Język",
|
|
"languageHint": "Tekst aplikacji oraz nazwy miesięcy i dni.",
|
|
"languageFallbackHint": "Ten język nie jest jeszcze przetłumaczony — tekst aplikacji pozostanie po angielsku.",
|
|
"region": "Region",
|
|
"regionHint": "Format liczb i waluty.",
|
|
"currency": "Waluta",
|
|
"currencyHint": "Przykład: {example}. Kwoty są tylko wyświetlane — nic nie jest przeliczane.",
|
|
"dateFormat": "Format daty",
|
|
"dateHint": "Przykład: {example}",
|
|
"fontSize": "Rozmiar czcionki",
|
|
"fontSmall": "Mała",
|
|
"fontMedium": "Średnia",
|
|
"fontLarge": "Duża"
|
|
},
|
|
"profile": {
|
|
"title": "Profil",
|
|
"working": "Przetwarzanie…",
|
|
"uploadPhoto": "Prześlij zdjęcie",
|
|
"remove": "Usuń",
|
|
"bio": "O mnie",
|
|
"bioHint": "Krótka notatka widoczna dla innych osób w Twoim gospodarstwie domowym.",
|
|
"bioSaved": "Zapisano opis.",
|
|
"saveBio": "Zapisz opis"
|
|
},
|
|
"security": {
|
|
"title": "Bezpieczeństwo",
|
|
"checkingDevice": "Sprawdzanie urządzenia…",
|
|
"biometricSignIn": "Logowanie biometryczne",
|
|
"biometricAvailable": "Zaloguj się za pomocą {method} zamiast hasła.",
|
|
"biometricUnavailable": "Na tym urządzeniu nie zarejestrowano biometrii.",
|
|
"methodFaceOrFingerprint": "twarzy lub odcisku palca",
|
|
"methodFace": "rozpoznawania twarzy",
|
|
"methodFingerprint": "odcisku palca",
|
|
"methodBiometrics": "biometrii",
|
|
"turnedOff": "Logowanie biometryczne wyłączone",
|
|
"enabled": "Logowanie biometryczne włączone",
|
|
"couldNotEnable": "Nie udało się włączyć: {error}",
|
|
"confirmPassword": "Potwierdź hasło",
|
|
"password": "Hasło"
|
|
},
|
|
"org": {
|
|
"title": "Organizacja",
|
|
"titleAll": "Organizacje",
|
|
"subtitleOwn": "Organizacja, którą administrujesz",
|
|
"subtitleNone": "Utwórz ją, aby zarządzać własnym zespołem",
|
|
"subtitleAll": "Podmioty, do których należą użytkownicy",
|
|
"nameLabel": "Nazwa organizacji",
|
|
"namePlaceholder": "Acme Fleet",
|
|
"newOrg": "Nowa organizacja",
|
|
"create": "Utwórz organizację",
|
|
"createHint": "Zostaniesz jej administratorem i będziesz móc dodawać użytkowników oraz nimi zarządzać.",
|
|
"rename": "Zmień nazwę",
|
|
"delete": "Usuń",
|
|
"deleteTitle": "Usunąć organizację?",
|
|
"empty": "Brak organizacji.",
|
|
"confirmDelete": "Usunąć organizację „{name}”? Tego nie można cofnąć.",
|
|
"confirmDeleteOwn": "Usunąć Twoją organizację „{name}”? Zostaniesz z niej usunięty i staniesz się zwykłym użytkownikiem. Tego nie można cofnąć."
|
|
},
|
|
"privacy": {
|
|
"title": "Prywatność i bezpieczeństwo",
|
|
"body": "Uwierzytelnianie dwuskładnikowe nie jest jeszcze dostępne. Sesje opierają się na tokenach wydawanych przez serwer, które wygasają samoczynnie, więc wylogowanie kończy tylko sesję na tym urządzeniu. Aby wylogować wszystkie urządzenia, zmień hasło powyżej.",
|
|
"signOut": "Wyloguj się"
|
|
},
|
|
"danger": {
|
|
"title": "Strefa niebezpieczna",
|
|
"body": "Usunięcie konta usuwa Twój login i profil. Nie usuwa samochodów ani historii serwisowej współdzielonych w gospodarstwie domowym. Obowiązuje 3-dniowy okres karencji, zanim usunięcie stanie się ostateczne — do tego czasu możesz je anulować.",
|
|
"deleteAccount": "Usuń moje konto",
|
|
"typeToConfirm": "Wpisz {email}, aby potwierdzić",
|
|
"typeEmailPrompt": "Wpisz swój e-mail, aby potwierdzić.",
|
|
"requesting": "Wysyłanie żądania…",
|
|
"requestDeletion": "Zażądaj usunięcia",
|
|
"requestedOn": "Żądanie usunięcia konta złożono {date}. {tail}",
|
|
"cooldownPassed": "Okres karencji minął. Możesz teraz dokończyć usuwanie.",
|
|
"canStillCancel": "Nadal możesz je anulować — stanie się ostateczne po 3-dniowym okresie karencji.",
|
|
"cancelRequest": "Anuluj żądanie usunięcia",
|
|
"permanentlyDelete": "Usuń trwale",
|
|
"finalizeTitle": "Usunąć konto?",
|
|
"finalizeBody": "To trwale usunie Twoje konto. Tej operacji nie można cofnąć.",
|
|
"delete": "Usuń"
|
|
}
|
|
},
|
|
"status": {
|
|
"noData": "Brak danych",
|
|
"serviceOverdueDays": "Serwis zaległy {days} dni",
|
|
"dueInDays": "Termin za {days} dni",
|
|
"okDays": "OK · {days} dni",
|
|
"noKm": "Brak przebiegu",
|
|
"serviceOverdueKm": "Serwis zaległy {km} km",
|
|
"inKm": "Za {km} km",
|
|
"kmLeft": "Pozostało {km} km",
|
|
"expiredAgo": "Wygasło {days} dni temu",
|
|
"expiresToday": "Wygasa dzisiaj",
|
|
"renewInDays": "Odnowienie za {days} dni",
|
|
"validDays": "Ważne · {days} dni",
|
|
"noExpiry": "Bezterminowe",
|
|
"done": "Gotowe",
|
|
"noTrigger": "Brak wyzwalacza",
|
|
"overdue": "Zaległe",
|
|
"overdueBy": "Zaległe {parts}",
|
|
"dueIn": "Termin za {parts}",
|
|
"upcoming": "Nadchodzące",
|
|
"today": "dzisiaj",
|
|
"days": "{days} dni",
|
|
"km": "{km} km",
|
|
"warrantyExpiredAgo": "Gwarancja wygasła {days} dni temu",
|
|
"warrantyEndsIn": "Gwarancja kończy się za {days} dni",
|
|
"underWarranty": "Na gwarancji · {days} dni"
|
|
}
|
|
} |