diff --git a/client/src/api/client.ts b/client/src/api/client.ts index 4484301..cd97c3e 100644 --- a/client/src/api/client.ts +++ b/client/src/api/client.ts @@ -51,7 +51,7 @@ export const authApi = { login: (data: { email: string; password: string }) => apiClient.post('/auth/login', data).then(r => r.data), verifyMfaLogin: (data: { mfa_token: string; code: string }) => apiClient.post('/auth/mfa/verify-login', data).then(r => r.data), mfaSetup: () => apiClient.post('/auth/mfa/setup', {}).then(r => r.data), - mfaEnable: (data: { code: string }) => apiClient.post('/auth/mfa/enable', data).then(r => r.data), + mfaEnable: (data: { code: string }) => apiClient.post('/auth/mfa/enable', data).then(r => r.data as { success: boolean; mfa_enabled: boolean; backup_codes?: string[] }), mfaDisable: (data: { password: string; code: string }) => apiClient.post('/auth/mfa/disable', data).then(r => r.data), me: () => apiClient.get('/auth/me').then(r => r.data), updateMapsKey: (key: string | null) => apiClient.put('/auth/me/maps-key', { maps_api_key: key }).then(r => r.data), diff --git a/client/src/i18n/translations/ar.ts b/client/src/i18n/translations/ar.ts index b80fc68..7449336 100644 --- a/client/src/i18n/translations/ar.ts +++ b/client/src/i18n/translations/ar.ts @@ -252,6 +252,13 @@ const ar: Record = { 'settings.mfa.title': 'المصادقة الثنائية (2FA)', 'settings.mfa.description': 'تضيف خطوة ثانية عند تسجيل الدخول. استخدم تطبيق مصادقة (Google Authenticator، Authy، إلخ).', 'settings.mfa.requiredByPolicy': 'المسؤول يتطلب المصادقة الثنائية. اضبط تطبيق المصادقة أدناه قبل المتابعة.', + 'settings.mfa.backupTitle': 'رموز النسخ الاحتياطي', + 'settings.mfa.backupDescription': 'استخدم هذه الرموز لمرة واحدة إذا فقدت الوصول إلى تطبيق المصادقة.', + 'settings.mfa.backupWarning': 'احفظ هذه الرموز الآن. كل رمز يمكن استخدامه مرة واحدة فقط.', + 'settings.mfa.backupCopy': 'نسخ الرموز', + 'settings.mfa.backupDownload': 'تنزيل TXT', + 'settings.mfa.backupPrint': 'طباعة / PDF', + 'settings.mfa.backupCopied': 'تم نسخ رموز النسخ الاحتياطي', 'settings.mfa.enabled': 'المصادقة الثنائية مفعّلة على حسابك.', 'settings.mfa.disabled': 'المصادقة الثنائية غير مفعّلة.', 'settings.mfa.setup': 'إعداد المصادقة', diff --git a/client/src/i18n/translations/br.ts b/client/src/i18n/translations/br.ts index bd2590a..f00adb9 100644 --- a/client/src/i18n/translations/br.ts +++ b/client/src/i18n/translations/br.ts @@ -222,6 +222,13 @@ const br: Record = { 'settings.mfa.title': 'Autenticação em duas etapas (2FA)', 'settings.mfa.description': 'Adiciona uma segunda etapa ao entrar com e-mail e senha. Use um app autenticador (Google Authenticator, Authy, etc.).', 'settings.mfa.requiredByPolicy': 'O administrador exige autenticação em dois fatores. Configure um app autenticador abaixo antes de continuar.', + 'settings.mfa.backupTitle': 'Códigos de backup', + 'settings.mfa.backupDescription': 'Use estes códigos únicos se perder acesso ao app autenticador.', + 'settings.mfa.backupWarning': 'Salve estes códigos agora. Cada código pode ser usado apenas uma vez.', + 'settings.mfa.backupCopy': 'Copiar códigos', + 'settings.mfa.backupDownload': 'Baixar TXT', + 'settings.mfa.backupPrint': 'Imprimir / PDF', + 'settings.mfa.backupCopied': 'Códigos de backup copiados', 'settings.mfa.enabled': 'O 2FA está ativado na sua conta.', 'settings.mfa.disabled': 'O 2FA não está ativado.', 'settings.mfa.setup': 'Configurar autenticador', diff --git a/client/src/i18n/translations/cs.ts b/client/src/i18n/translations/cs.ts index 5121779..856098f 100644 --- a/client/src/i18n/translations/cs.ts +++ b/client/src/i18n/translations/cs.ts @@ -1,1393 +1,1400 @@ -const cs: Record = { - // Společné (Common) - 'common.save': 'Uložit', - 'common.cancel': 'Zrušit', - 'common.delete': 'Smazat', - 'common.edit': 'Upravit', - 'common.add': 'Přidat', - 'common.loading': 'Načítání...', - 'common.error': 'Chyba', - 'common.back': 'Zpět', - 'common.all': 'Vše', - 'common.close': 'Zavřít', - 'common.open': 'Otevřít', - 'common.upload': 'Nahrát', - 'common.search': 'Hledat', - 'common.confirm': 'Potvrdit', - 'common.ok': 'OK', - 'common.yes': 'Ano', - 'common.no': 'Ne', - 'common.or': 'nebo', - 'common.none': 'Žádné', - 'common.date': 'Datum', - 'common.rename': 'Přejmenovat', - 'common.name': 'Jméno', - 'common.email': 'E-mail', - 'common.password': 'Heslo', - 'common.saving': 'Ukládání...', - 'common.update': 'Aktualizovat', - 'common.change': 'Změnit', - 'common.uploading': 'Nahrávání…', - 'common.backToPlanning': 'Zpět k plánování', - 'common.reset': 'Resetovat', - - // Navigační lišta (Navbar) - 'nav.trip': 'Cesta', - 'nav.share': 'Sdílet', - 'nav.settings': 'Nastavení', - 'nav.admin': 'Administrace', - 'nav.logout': 'Odhlásit se', - 'nav.lightMode': 'Světlý režim', - 'nav.darkMode': 'Tmavý režim', - 'nav.autoMode': 'Automatický režim', - 'nav.administrator': 'Administrátor', - 'nav.myTrips': 'Moje cesty', - - // Přehled (Dashboard) - 'dashboard.title': 'Moje cesty', - 'dashboard.subtitle.loading': 'Načítání cest...', - 'dashboard.subtitle.trips': '{count} cest ({archived} archivováno)', - 'dashboard.subtitle.empty': 'Začněte svou první cestu', - 'dashboard.subtitle.activeOne': '{count} aktivní cesta', - 'dashboard.subtitle.activeMany': '{count} aktivních cest', - 'dashboard.subtitle.archivedSuffix': ' · {count} archivováno', - 'dashboard.newTrip': 'Nová cesta', - 'dashboard.gridView': 'Mřížka', - 'dashboard.listView': 'Seznam', - 'dashboard.currency': 'Měna', - 'dashboard.timezone': 'Časová pásma', - 'dashboard.localTime': 'Místní čas', - 'dashboard.timezoneCustomTitle': 'Vlastní pásmo', - 'dashboard.timezoneCustomLabelPlaceholder': 'Popisek (volitelné)', - 'dashboard.timezoneCustomTzPlaceholder': 'např. America/New_York', - 'dashboard.timezoneCustomAdd': 'Přidat', - 'dashboard.timezoneCustomErrorEmpty': 'Zadejte identifikátor pásma', - 'dashboard.timezoneCustomErrorInvalid': 'Neplatné pásmo. Použijte formát jako např. Europe/Prague', - 'dashboard.timezoneCustomErrorDuplicate': 'Již bylo přidáno', - 'dashboard.emptyTitle': 'Zatím žádné cesty', - 'dashboard.emptyText': 'Vytvořte svou první cestu a začněte plánovat!', - 'dashboard.emptyButton': 'Vytvořit první cestu', - 'dashboard.nextTrip': 'Další cesta', - 'dashboard.shared': 'Sdílené', - 'dashboard.sharedBy': 'Sdílí {name}', - 'dashboard.days': 'Dní', - 'dashboard.places': 'Míst', - 'dashboard.archive': 'Archivovat', - 'dashboard.restore': 'Obnovit', - 'dashboard.archived': 'Archivováno', - 'dashboard.status.ongoing': 'Probíhající', - 'dashboard.status.today': 'Dnes', - 'dashboard.status.tomorrow': 'Zítra', - 'dashboard.status.past': 'Proběhlé', - 'dashboard.status.daysLeft': 'zbývá {count} dní', - 'dashboard.toast.loadError': 'Nepodařilo se načíst cesty', - 'dashboard.toast.created': 'Cesta byla úspěšně vytvořena!', - 'dashboard.toast.createError': 'Nepodařilo se vytvořit cestu', - 'dashboard.toast.updated': 'Cesta byla aktualizována!', - 'dashboard.toast.updateError': 'Nepodařilo se aktualizovat cestu', - 'dashboard.toast.deleted': 'Cesta byla smazána', - 'dashboard.toast.deleteError': 'Nepodařilo se smazat cestu', - 'dashboard.toast.archived': 'Cesta byla archivována', - 'dashboard.toast.archiveError': 'Nepodařilo se archivovat cestu', - 'dashboard.toast.restored': 'Cesta byla obnovena', - 'dashboard.toast.restoreError': 'Nepodařilo se obnovit cestu', - 'dashboard.confirm.delete': 'Smazat cestu „{title}“? Všechna místa a plány budou trvale smazány.', - 'dashboard.editTrip': 'Upravit cestu', - 'dashboard.createTrip': 'Vytvořit novou cestu', - 'dashboard.tripTitle': 'Název', - 'dashboard.tripTitlePlaceholder': 'např. Léto v Japonsku', - 'dashboard.tripDescription': 'Popis', - 'dashboard.tripDescriptionPlaceholder': 'O čem je tato cesta?', - 'dashboard.startDate': 'Datum začátku', - 'dashboard.endDate': 'Datum konce', - 'dashboard.noDateHint': 'Datum nezadáno – výchozí délka nastavena na 7 dní. Toto lze kdykoli změnit.', - 'dashboard.coverImage': 'Úvodní obrázek', - 'dashboard.addCoverImage': 'Vybrat úvodní obrázek (nebo přetáhnout sem)', - 'dashboard.addMembers': 'Spolucestující', - 'dashboard.addMember': 'Přidat člena', - 'dashboard.coverSaved': 'Úvodní obrázek uložen', - 'dashboard.coverUploadError': 'Nahrávání se nezdařilo', - 'dashboard.coverRemoveError': 'Odstranění se nezdařilo', - 'dashboard.titleRequired': 'Název je povinný', - 'dashboard.endDateError': 'Datum konce musí být po datu začátku', - - // Nastavení (Settings) - 'settings.title': 'Nastavení', - 'settings.subtitle': 'Upravte své osobní nastavení', - 'settings.map': 'Mapy', - 'settings.mapTemplate': 'Šablona mapy', - 'settings.mapTemplatePlaceholder.select': 'Vyberte šablonu...', - 'settings.mapDefaultHint': 'Ponechte prázdné pro OpenStreetMap (výchozí)', - 'settings.mapTemplatePlaceholder': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - 'settings.mapHint': 'URL šablony pro mapové dlaždice', - 'settings.latitude': 'Zeměpisná šířka', - 'settings.longitude': 'Zeměpisná délka', - 'settings.saveMap': 'Uložit nastavení mapy', - 'settings.apiKeys': 'API klíče', - 'settings.mapsKey': 'Google Maps API klíč', - 'settings.mapsKeyHint': 'Pro vyhledávání míst. Vyžaduje Places API (New). Získáte na console.cloud.google.com', - 'settings.weatherKey': 'OpenWeatherMap API klíč', - 'settings.weatherKeyHint': 'Pro předpověď počasí. Zdarma na openweathermap.org/api', - 'settings.keyPlaceholder': 'Vložte klíč...', - 'settings.configured': 'Nastaveno', - 'settings.saveKeys': 'Uložit klíče', - 'settings.display': 'Zobrazení', - 'settings.colorMode': 'Barevné schéma', - 'settings.light': 'Světlé', - 'settings.dark': 'Tmavé', - 'settings.auto': 'Automatické', - 'settings.language': 'Jazyk', - 'settings.temperature': 'Jednotky teploty', - 'settings.timeFormat': 'Formát času', - 'settings.routeCalculation': 'Výpočet trasy', - 'settings.blurBookingCodes': 'Skrýt rezervační kódy', - 'settings.notifications': 'Oznámení', - 'settings.notifyTripInvite': 'Pozvánky na cesty', - 'settings.notifyBookingChange': 'Změny rezervací', - 'settings.notifyTripReminder': 'Připomínky cest', - 'settings.notifyVacayInvite': 'Pozvánky k propojení Vacay', - 'settings.notifyPhotosShared': 'Sdílené fotky (Immich)', - 'settings.notifyCollabMessage': 'Zprávy v chatu (Collab)', - 'settings.notifyPackingTagged': 'Seznam balení: přiřazení', - 'settings.notifyWebhook': 'Webhook oznámení', - 'settings.on': 'Zapnuto', - 'settings.off': 'Vypnuto', - 'settings.mcp.title': 'Konfigurace MCP', - 'settings.mcp.endpoint': 'MCP endpoint', - 'settings.mcp.clientConfig': 'Konfigurace klienta', - 'settings.mcp.clientConfigHint': 'Nahraďte API tokenem ze seznamu níže. Cestu k npx může být nutné upravit pro váš systém (např. C:\\PROGRA~1\\nodejs\\npx.cmd ve Windows).', - 'settings.mcp.copy': 'Kopírovat', - 'settings.mcp.copied': 'Zkopírováno!', - 'settings.mcp.apiTokens': 'API tokeny', - 'settings.mcp.createToken': 'Vytvořit nový token', - 'settings.mcp.noTokens': 'Zatím žádné tokeny. Vytvořte jeden pro připojení MCP klientů.', - 'settings.mcp.tokenCreatedAt': 'Vytvořen', - 'settings.mcp.tokenUsedAt': 'Použit', - 'settings.mcp.deleteTokenTitle': 'Smazat token', - 'settings.mcp.deleteTokenMessage': 'Tento token přestane okamžitě fungovat. Všichni MCP klienti, kteří ho používají, ztratí přístup.', - 'settings.mcp.modal.createTitle': 'Vytvořit API token', - 'settings.mcp.modal.tokenName': 'Název tokenu', - 'settings.mcp.modal.tokenNamePlaceholder': 'např. Claude Desktop, Pracovní notebook', - 'settings.mcp.modal.creating': 'Vytváření…', - 'settings.mcp.modal.create': 'Vytvořit token', - 'settings.mcp.modal.createdTitle': 'Token vytvořen', - 'settings.mcp.modal.createdWarning': 'Tento token bude zobrazen pouze jednou. Zkopírujte a uložte ho nyní — nelze ho obnovit.', - 'settings.mcp.modal.done': 'Hotovo', - 'settings.mcp.toast.created': 'Token vytvořen', - 'settings.mcp.toast.createError': 'Nepodařilo se vytvořit token', - 'settings.mcp.toast.deleted': 'Token smazán', - 'settings.mcp.toast.deleteError': 'Nepodařilo se smazat token', - 'settings.account': 'Účet', - 'settings.username': 'Uživatelské jméno', - 'settings.email': 'E-mail', - 'settings.role': 'Role', - 'settings.roleAdmin': 'Administrátor', - 'settings.oidcLinked': 'Propojeno přes', - 'settings.changePassword': 'Změnit heslo', - 'settings.currentPassword': 'Současné heslo', - 'settings.currentPasswordRequired': 'Současné heslo je vyžadováno', - 'settings.newPassword': 'Nové heslo', - 'settings.confirmPassword': 'Potvrdit nové heslo', - 'settings.updatePassword': 'Aktualizovat heslo', - 'settings.passwordRequired': 'Zadejte prosím současné i nové heslo', - 'settings.passwordTooShort': 'Heslo musí mít alespoň 8 znaků', - 'settings.passwordMismatch': 'Hesla se neshodují', - 'settings.passwordWeak': 'Heslo musí obsahovat velké a malé písmeno a číslici', - 'settings.passwordChanged': 'Heslo bylo úspěšně změněno', - 'settings.deleteAccount': 'Smazat účet', - 'settings.deleteAccountTitle': 'Smazat váš účet?', - 'settings.deleteAccountWarning': 'Váš účet a všechny vaše cesty, místa a soubory budou trvale smazány. Tuto akci nelze vrátit.', - 'settings.deleteAccountConfirm': 'Smazat natrvalo', - 'settings.deleteBlockedTitle': 'Účet nelze smazat', - 'settings.deleteBlockedMessage': 'Jste jediným administrátorem. Před smazáním svého účtu předejte roli administrátora jinému uživateli.', - 'settings.roleUser': 'Uživatel', - 'settings.saveProfile': 'Uložit profil', - 'settings.toast.mapSaved': 'Nastavení map uloženo', - 'settings.toast.keysSaved': 'API klíče uloženy', - 'settings.toast.displaySaved': 'Nastavení zobrazení uloženo', - 'settings.toast.profileSaved': 'Profil byl uložen', - 'settings.uploadAvatar': 'Nahrát profilový obrázek', - 'settings.removeAvatar': 'Odebrat profilový obrázek', - 'settings.avatarUploaded': 'Profilový obrázek byl aktualizován', - 'settings.avatarRemoved': 'Profilový obrázek byl odstraněn', - 'settings.avatarError': 'Nahrávání se nezdařilo', - 'settings.mfa.title': 'Dvoufaktorové ověření (2FA)', - 'settings.mfa.description': 'Přidá druhý stupeň zabezpečení při přihlašování e-mailem a heslem. Použijte aplikaci (Google Authenticator, Authy apod.).', - 'settings.mfa.requiredByPolicy': 'Správce vyžaduje dvoufázové ověření. Nejdřív níže nastavte aplikaci autentikátoru.', - 'settings.mfa.enabled': '2FA je pro váš účet aktivní.', - 'settings.mfa.disabled': '2FA není aktivní.', - 'settings.mfa.setup': 'Nastavit autentizační aplikaci', - 'settings.mfa.scanQr': 'Naskenujte tento QR kód ve vaší aplikaci nebo zadejte kód ručně.', - 'settings.mfa.secretLabel': 'Tajný klíč (pro ruční zadání)', - 'settings.mfa.codePlaceholder': '6místný kód', - 'settings.mfa.enable': 'Zapnout 2FA', - 'settings.mfa.cancelSetup': 'Zrušit', - 'settings.mfa.disableTitle': 'Vypnout 2FA', - 'settings.mfa.disableHint': 'Zadejte své heslo k účtu a aktuální kód z aplikace.', - 'settings.mfa.disable': 'Vypnout 2FA', - 'settings.mfa.toastEnabled': 'Dvoufaktorové ověření bylo zapnuto', - 'settings.mfa.toastDisabled': 'Dvoufaktorové ověření bylo vypnuto', - 'settings.mfa.demoBlocked': 'Není k dispozici v demo režimu', - 'admin.smtp.title': 'E-mail a oznámení', - 'admin.smtp.hint': 'Konfigurace SMTP pro e-mailová oznámení. Volitelně: Webhook URL pro Discord, Slack apod.', - 'admin.smtp.testButton': 'Odeslat testovací e-mail', - 'admin.smtp.testSuccess': 'Testovací e-mail byl úspěšně odeslán', - 'admin.smtp.testFailed': 'Odeslání testovacího e-mailu se nezdařilo', - 'dayplan.icsTooltip': 'Exportovat kalendář (ICS)', - 'share.linkTitle': 'Veřejný odkaz', - 'share.linkHint': 'Vytvořte odkaz, kterým si může kdokoli prohlédnout tuto cestu bez přihlášení. Pouze pro čtení — úpravy nejsou možné.', - 'share.createLink': 'Vytvořit odkaz', - 'share.deleteLink': 'Smazat odkaz', - 'share.createError': 'Nepodařilo se vytvořit odkaz', - 'common.copy': 'Kopírovat', - 'common.copied': 'Zkopírováno', - 'share.permMap': 'Mapa a plán', - 'share.permBookings': 'Rezervace', - 'share.permPacking': 'Balení', - 'shared.expired': 'Odkaz vypršel nebo je neplatný', - 'shared.expiredHint': 'Tento sdílený odkaz na cestu již není aktivní.', - 'shared.readOnly': 'Sdílené zobrazení – pouze pro čtení', - 'shared.tabPlan': 'Plán', - 'shared.tabBookings': 'Rezervace', - 'shared.tabPacking': 'Balení', - 'shared.tabBudget': 'Rozpočet', - 'shared.tabChat': 'Chat', - 'shared.days': 'dní', - 'shared.places': 'míst', - 'shared.other': 'Ostatní', - 'shared.totalBudget': 'Celkový rozpočet', - 'shared.messages': 'zpráv', - 'shared.sharedVia': 'Sdíleno přes', - 'shared.confirmed': 'Potvrzeno', - 'shared.pending': 'Čeká na potvrzení', - 'share.permBudget': 'Rozpočet', - 'share.permCollab': 'Chat', - - // Přihlášení (Login) - 'login.error': 'Přihlášení se nezdařilo. Zkontrolujte prosím své údaje.', - 'login.tagline': 'Vaše cesty.\nVáš plán.', - 'login.description': 'Plánujte cesty společně s interaktivními mapami, rozpočty a synchronizací v reálném čase.', - 'login.features.maps': 'Interaktivní mapy', - 'login.features.mapsDesc': 'Google Places, trasy a shlukování bodů', - 'login.features.realtime': 'Synchronizace v reálném čase', - 'login.features.realtimeDesc': 'Plánujte společně přes WebSocket', - 'login.features.budget': 'Sledování rozpočtu', - 'login.features.budgetDesc': 'Kategorie, grafy a náklady na osobu', - 'login.features.collab': 'Spolupráce', - 'login.features.collabDesc': 'Více uživatelů se sdílenými cestami', - 'login.features.packing': 'Seznamy věcí', - 'login.features.packingDesc': 'Kategorie, pokrok v balení a návrhy', - 'login.features.bookings': 'Rezervace', - 'login.features.bookingsDesc': 'Lety, hotely, restaurace a další', - 'login.features.files': 'Dokumenty', - 'login.features.filesDesc': 'Nahrávejte a spravujte dokumenty', - 'login.features.routes': 'Chytré trasy', - 'login.features.routesDesc': 'Automatická optimalizace a export do Google Maps', - 'login.selfHosted': 'Self-hosted · Open Source · Vaše data zůstávají u vás', - 'login.title': 'Přihlásit se', - 'login.subtitle': 'Vítejte zpět', - 'login.signingIn': 'Přihlašování…', - 'login.signIn': 'Přihlásit se', - 'login.createAdmin': 'Vytvořit účet administrátora', - 'login.createAdminHint': 'Nastavte první administrátorský účet pro TREK.', - 'login.createAccount': 'Vytvořit účet', - 'login.createAccountHint': 'Zaregistrujte si nový účet.', - 'login.creating': 'Vytváření…', - 'login.noAccount': 'Nemáte účet?', - 'login.hasAccount': 'Již máte účet?', - 'login.register': 'Registrovat se', - 'login.emailPlaceholder': 'vas@email.cz', - 'login.username': 'Uživatelské jméno', - 'login.oidc.registrationDisabled': 'Registrace je zakázána. Kontaktujte svého administrátora.', - 'login.oidc.noEmail': 'Od poskytovatele nebyl přijat žádný e-mail.', - 'login.oidc.tokenFailed': 'Ověření se nezdařilo.', - 'login.oidc.invalidState': 'Neplatná relace. Zkuste to prosím znovu.', - 'login.demoFailed': 'Přihlášení do dema se nezdařilo', - 'login.oidcSignIn': 'Přihlásit se přes {name}', - 'login.oidcOnly': 'Ověřování heslem je zakázáno. Přihlaste se prosím přes SSO poskytovatele.', - 'login.demoHint': 'Vyzkoušejte demo – registrace není nutná', - 'login.mfaTitle': 'Dvoufaktorové ověření', - 'login.mfaSubtitle': 'Zadejte 6místný kód z vaší autentizační aplikace.', - 'login.mfaCodeLabel': 'Ověřovací kód', - 'login.mfaCodeRequired': 'Zadejte kód z aplikace.', - 'login.mfaHint': 'Otevřete Google Authenticator, Authy nebo jinou TOTP aplikaci.', - 'login.mfaBack': '← Zpět k přihlášení', - 'login.mfaVerify': 'Ověřit', - - // Registrace (Register) - 'register.passwordMismatch': 'Hesla se neshodují', - 'register.passwordTooShort': 'Heslo musí mít alespoň 6 znaků', - 'register.failed': 'Registrace se nezdařila', - 'register.getStarted': 'Začínáme', - 'register.subtitle': 'Vytvořte si účet a začněte plánovat svou vysněnou cestu.', - 'register.feature1': 'Neomezené plány cest', - 'register.feature2': 'Zobrazení na interaktivní mapě', - 'register.feature3': 'Správa míst a kategorií', - 'register.feature4': 'Sledování rezervací', - 'register.feature5': 'Vytváření seznamů věcí', - 'register.feature6': 'Ukládání fotek a souborů', - 'register.createAccount': 'Vytvořit účet', - 'register.startPlanning': 'Začít plánovat', - 'register.minChars': 'Min. 6 znaků', - 'register.confirmPassword': 'Potvrdit heslo', - 'register.repeatPassword': 'Heslo znovu', - 'register.registering': 'Registrace...', - 'register.register': 'Registrovat se', - 'register.hasAccount': 'Již máte účet?', - 'register.signIn': 'Přihlásit se', - - // Administrace (Admin) - 'admin.title': 'Administrace', - 'admin.subtitle': 'Správa uživatelů a systémová nastavení', - 'admin.tabs.users': 'Uživatelé', - 'admin.tabs.categories': 'Kategorie', - 'admin.tabs.backup': 'Zálohování', - 'admin.stats.users': 'Uživatelé', - 'admin.stats.trips': 'Cesty', - 'admin.stats.places': 'Místa', - 'admin.stats.photos': 'Fotky', - 'admin.stats.files': 'Soubory', - 'admin.table.user': 'Uživatel', - 'admin.table.email': 'E-mail', - 'admin.table.role': 'Role', - 'admin.table.created': 'Vytvořeno', - 'admin.table.lastLogin': 'Poslední přihlášení', - 'admin.table.actions': 'Akce', - 'admin.you': '(Vy)', - 'admin.editUser': 'Upravit uživatele', - 'admin.newPassword': 'Nové heslo', - 'admin.newPasswordHint': 'Ponechte prázdné pro zachování současného hesla', - 'admin.deleteUser': 'Smazat uživatele „{name}“? Všechny jeho cesty budou trvale smazány.', - 'admin.deleteUserTitle': 'Smazat uživatele', - 'admin.newPasswordPlaceholder': 'Zadejte nové heslo…', - 'admin.toast.loadError': 'Nepodařilo se načíst data administrace', - 'admin.toast.userUpdated': 'Uživatel byl aktualizován', - 'admin.toast.updateError': 'Aktualizace se nezdařila', - 'admin.toast.userDeleted': 'Uživatel byl smazán', - 'admin.toast.deleteError': 'Smazání se nezdařilo', - 'admin.toast.cannotDeleteSelf': 'Nemůžete smazat svůj vlastní účet', - 'admin.toast.userCreated': 'Uživatel byl vytvořen', - 'admin.toast.createError': 'Nepodařilo se vytvořit uživatele', - 'admin.toast.fieldsRequired': 'Uživatelské jméno, e-mail a heslo jsou povinné', - 'admin.createUser': 'Vytvořit uživatele', - 'admin.invite.title': 'Pozvánky', - 'admin.invite.subtitle': 'Vytvářejte jednorázové registrační odkazy', - 'admin.invite.create': 'Vytvořit odkaz', - 'admin.invite.createAndCopy': 'Vytvořit a zkopírovat', - 'admin.invite.empty': 'Zatím nebyly vytvořeny žádné pozvánky', - 'admin.invite.maxUses': 'Max. použití', - 'admin.invite.expiry': 'Vyprší za', - 'admin.invite.uses': 'použito', - 'admin.invite.expiresAt': 'vyprší', - 'admin.invite.createdBy': 'vytvořil', - 'admin.invite.active': 'Aktivní', - 'admin.invite.expired': 'Expirované', - 'admin.invite.usedUp': 'Využito', - 'admin.invite.copied': 'Odkaz byl zkopírován do schránky', - 'admin.invite.copyLink': 'Kopírovat odkaz', - 'admin.invite.deleted': 'Pozvánka smazána', - 'admin.invite.createError': 'Nepodařilo se vytvořit pozvánku', - 'admin.invite.deleteError': 'Nepodařilo se smazat pozvánku', - 'admin.tabs.settings': 'Nastavení', - 'admin.allowRegistration': 'Povolit registraci', - 'admin.allowRegistrationHint': 'Noví uživatelé se mohou sami registrovat', - 'admin.requireMfa': 'Vyžadovat dvoufázové ověření (2FA)', - 'admin.requireMfaHint': 'Uživatelé bez 2FA musí dokončit nastavení v Nastavení před použitím aplikace.', - 'admin.apiKeys': 'API klíče', - 'admin.apiKeysHint': 'Volitelné. Povoluje rozšířená data o místech (fotky, počasí).', - 'admin.mapsKey': 'Google Maps API klíč', - 'admin.mapsKeyHint': 'Povinné pro hledání míst. Získáte na console.cloud.google.com', - 'admin.mapsKeyHintLong': 'Bez API klíče se pro hledání používá OpenStreetMap. S Google klíčem lze načítat fotky, hodnocení a otevírací dobu.', - 'admin.recommended': 'Doporučeno', - 'admin.weatherKey': 'OpenWeatherMap API klíč', - 'admin.weatherKeyHint': 'Pro data o počasí. Zdarma na openweathermap.org', - 'admin.validateKey': 'Testovat', - 'admin.keyValid': 'Připojeno', - 'admin.keyInvalid': 'Neplatný', - 'admin.keySaved': 'API klíče byly uloženy', - 'admin.oidcTitle': 'Jednotné přihlášení (OIDC)', - 'admin.oidcSubtitle': 'Povolit přihlášení přes externí poskytovatele (Google, Apple, Authentik, Keycloak).', - 'admin.oidcDisplayName': 'Zobrazované jméno', - 'admin.oidcIssuer': 'URL vydavatele (Issuer)', - 'admin.oidcIssuerHint': 'OpenID Connect Issuer URL, např. https://accounts.google.com', - 'admin.oidcSaved': 'Konfigurace OIDC uložena', - 'admin.oidcOnlyMode': 'Zakázat ověřování heslem', - 'admin.oidcOnlyModeHint': 'Pokud je zapnuto, je povolen pouze SSO login. Registrace i přihlášení heslem budou zablokovány.', - - // Typy souborů (File Types) - 'admin.fileTypes': 'Povolené typy souborů', - 'admin.fileTypesHint': 'Nastavte, které typy souborů mohou uživatelé nahrávat.', - 'admin.fileTypesFormat': 'Přípony oddělené čárkou (např. jpg,png,pdf,doc). Použijte * pro všechny typy.', - 'admin.fileTypesSaved': 'Nastavení souborů uloženo', - - // Šablony balení (Packing Templates) - 'admin.bagTracking.title': 'Sledování zavazadel', - 'admin.bagTracking.subtitle': 'Povolit váhu a přiřazení k zavazadlům u položek balení', - 'admin.tabs.config': 'Konfigurace', - 'admin.tabs.templates': 'Šablony seznamů', - 'admin.packingTemplates.title': 'Šablony pro balení', - 'admin.packingTemplates.subtitle': 'Vytvářejte opakovaně použitelné seznamy pro své cesty', - 'admin.packingTemplates.create': 'Nová šablona', - 'admin.packingTemplates.namePlaceholder': 'Název šablony (např. Dovolená u moře)', - 'admin.packingTemplates.empty': 'Zatím nejsou vytvořeny žádné šablony', - 'admin.packingTemplates.items': 'položek', - 'admin.packingTemplates.categories': 'kategorií', - 'admin.packingTemplates.itemName': 'Název položky', - 'admin.packingTemplates.itemCategory': 'Kategorie', - 'admin.packingTemplates.categoryName': 'Název kategorie (např. Oblečení)', - 'admin.packingTemplates.addCategory': 'Přidat kategorii', - 'admin.packingTemplates.created': 'Šablona vytvořena', - 'admin.packingTemplates.deleted': 'Šablona smazána', - 'admin.packingTemplates.loadError': 'Nepodařilo se načíst šablony', - 'admin.packingTemplates.createError': 'Nepodařilo se vytvořit šablonu', - 'admin.packingTemplates.deleteError': 'Nepodařilo se smazat šablonu', - 'admin.packingTemplates.saveError': 'Uložení se nezdařilo', - - // Doplňky (Addons) - 'admin.tabs.addons': 'Doplňky', - 'admin.addons.title': 'Doplňky', - 'admin.addons.subtitle': 'Zapněte nebo vypněte funkce a přizpůsobte si TREK.', - 'admin.addons.catalog.memories.name': 'Fotky (Immich)', - 'admin.addons.catalog.memories.description': 'Sdílejte cestovní fotky přes vaši instanci Immich', - 'admin.addons.catalog.packing.name': 'Balení', - 'admin.addons.catalog.packing.description': 'Seznamy věcí pro přípravu na cestu', - 'admin.addons.catalog.budget.name': 'Rozpočet', - 'admin.addons.catalog.budget.description': 'Sledování výdajů a plánování rozpočtu cesty', - 'admin.addons.catalog.documents.name': 'Dokumenty', - 'admin.addons.catalog.documents.description': 'Ukládání a správa cestovních dokladů', - 'admin.addons.catalog.vacay.name': 'Dovolená (Vacay)', - 'admin.addons.catalog.vacay.description': 'Osobní plánovač dovolené s kalendářem', - 'admin.addons.catalog.atlas.name': 'Atlas', - 'admin.addons.catalog.atlas.description': 'Mapa světa s navštívenými zeměmi a statistikami', - 'admin.addons.catalog.collab.name': 'Spolupráce', - 'admin.addons.catalog.collab.description': 'Poznámky v reálném čase, hlasování a chat pro plánování', - 'admin.addons.enabled': 'Povoleno', - 'admin.addons.disabled': 'Zakázáno', - 'admin.addons.type.trip': 'Cesta', - 'admin.addons.type.global': 'Globální', - 'admin.addons.type.integration': 'Integrace', - 'admin.addons.tripHint': 'Dostupné jako karta v rámci každé cesty', - 'admin.addons.globalHint': 'Dostupné jako samostatná sekce v hlavní navigaci', - 'admin.addons.integrationHint': 'Backendové služby a API integrace bez vlastní stránky', - 'admin.addons.toast.updated': 'Doplněk byl aktualizován', - 'admin.addons.toast.error': 'Aktualizace doplňku se nezdařila', - 'admin.addons.noAddons': 'Žádné doplňky nejsou k dispozici', - 'admin.addons.catalog.memories.name': 'Fotky (Immich)', - 'admin.addons.catalog.memories.description': 'Sdílejte cestovní fotky přes vaši instanci Immich', - 'admin.addons.catalog.mcp.name': 'MCP', - 'admin.addons.catalog.mcp.description': 'Model Context Protocol pro integraci AI asistentů', - 'admin.addons.subtitleBefore': 'Zapněte nebo vypněte funkce a přizpůsobte si ', - 'admin.addons.subtitleAfter': '.', - - 'admin.tabs.audit': 'Auditní protokol', - - 'admin.audit.subtitle': 'Bezpečnostní a administrátorské události (zálohy, uživatelé, 2FA, nastavení).', - 'admin.audit.empty': 'Zatím žádné záznamy auditu.', - 'admin.audit.refresh': 'Obnovit', - 'admin.audit.loadMore': 'Načíst další', - 'admin.audit.showing': '{count} načteno · {total} celkem', - 'admin.audit.col.time': 'Čas', - 'admin.audit.col.user': 'Uživatel', - 'admin.audit.col.action': 'Akce', - 'admin.audit.col.resource': 'Zdroj', - 'admin.audit.col.ip': 'IP', - 'admin.audit.col.details': 'Detaily', - - // MCP Tokens - 'admin.tabs.mcpTokens': 'MCP tokeny', - 'admin.mcpTokens.title': 'MCP tokeny', - 'admin.mcpTokens.subtitle': 'Správa API tokenů všech uživatelů', - 'admin.mcpTokens.owner': 'Vlastník', - 'admin.mcpTokens.tokenName': 'Název tokenu', - 'admin.mcpTokens.created': 'Vytvořen', - 'admin.mcpTokens.lastUsed': 'Naposledy použit', - 'admin.mcpTokens.never': 'Nikdy', - 'admin.mcpTokens.empty': 'Zatím nebyly vytvořeny žádné MCP tokeny', - 'admin.mcpTokens.deleteTitle': 'Smazat token', - 'admin.mcpTokens.deleteMessage': 'Tento token bude okamžitě zneplatněn. Uživatel ztratí MCP přístup přes tento token.', - 'admin.mcpTokens.deleteSuccess': 'Token smazán', - 'admin.mcpTokens.deleteError': 'Nepodařilo se smazat token', - 'admin.mcpTokens.loadError': 'Nepodařilo se načíst tokeny', - - // GitHub - 'admin.tabs.github': 'GitHub', - 'admin.github.title': 'Historie verzí', - 'admin.github.subtitle': 'Nejnovější aktualizace z {repo}', - 'admin.github.latest': 'Nejnovější', - 'admin.github.prerelease': 'Předběžná verze', - 'admin.github.showDetails': 'Zobrazit podrobnosti', - 'admin.github.hideDetails': 'Skrýt podrobnosti', - 'admin.github.loadMore': 'Načíst další', - 'admin.github.loading': 'Načítání...', - 'admin.github.error': 'Nepodařilo se načíst verze', - 'admin.github.by': 'od', - 'admin.github.support': 'Pomáhá udržovat vývoj TREK', - - // Počasí (Weather) - 'admin.weather.title': 'Data o počasí', - 'admin.weather.badge': 'Od 24. března 2026', - 'admin.weather.description': 'TREK používá Open-Meteo jako zdroj dat. Je to bezplatná open-source služba – není vyžadován API klíč.', - 'admin.weather.forecast': 'Předpověď na 16 dní', - 'admin.weather.forecastDesc': 'Dříve 5 dní (OpenWeatherMap)', - 'admin.weather.climate': 'Historická klimatická data', - 'admin.weather.climateDesc': 'Průměry za posledních 85 let pro dny mimo 16denní předpověď', - 'admin.weather.requests': '10 000 požadavků denně', - 'admin.weather.requestsDesc': 'Zdarma, bez nutnosti klíče', - 'admin.weather.locationHint': 'Počasí se určuje podle prvního místa se souřadnicemi v daném dni.', - - // Aktualizace (Updates) - 'admin.update.available': 'Dostupná aktualizace', - 'admin.update.text': 'TREK {version} je k dispozici. Aktuálně používáte verzi {current}.', - 'admin.update.button': 'Zobrazit na GitHubu', - 'admin.update.install': 'Instalovat aktualizaci', - 'admin.update.confirmTitle': 'Instalovat aktualizaci?', - 'admin.update.confirmText': 'TREK bude aktualizován z verze {current} na {version}. Server se poté automaticky restartuje.', - 'admin.update.dataInfo': 'Všechna vaše data (cesty, uživatelé, API klíče, soubory) budou zachována.', - 'admin.update.warning': 'Aplikace bude během restartu krátce nedostupná.', - 'admin.update.confirm': 'Aktualizovat nyní', - 'admin.update.installing': 'Aktualizace probíhá…', - 'admin.update.success': 'Aktualizace byla nainstalována! Server se restartuje…', - 'admin.update.failed': 'Aktualizace se nezdařila', - 'admin.update.backupHint': 'Před aktualizací doporučujeme vytvořit zálohu.', - 'admin.update.backupLink': 'Přejít na zálohování', - 'admin.update.howTo': 'Jak aktualizovat', - 'admin.update.dockerText': 'Váš TREK běží v Dockeru. Pro aktualizaci na verzi {version} spusťte na svém serveru tyto příkazy:', - 'admin.update.reloadHint': 'Prosím obnovte stránku za několik sekund.', - - // Vacay doplněk - 'vacay.subtitle': 'Plánování a správa dovolené', - 'vacay.settings': 'Nastavení', - 'vacay.year': 'Rok', - 'vacay.addYear': 'Přidat rok', - 'vacay.removeYear': 'Odebrat rok', - 'vacay.removeYearConfirm': 'Odebrat rok {year}?', - 'vacay.removeYearHint': 'Všechny záznamy o dovolené a firemní svátky pro tento rok budou trvale smazány.', - 'vacay.remove': 'Odebrat', - 'vacay.persons': 'Osoby', - 'vacay.noPersons': 'Žádné osoby nebyly přidány', - 'vacay.addPerson': 'Přidat osobu', - 'vacay.editPerson': 'Upravit osobu', - 'vacay.removePerson': 'Odebrat osobu', - 'vacay.removePersonConfirm': 'Odebrat osobu {name}?', - 'vacay.removePersonHint': 'Všechny záznamy dovolené pro tuto osobu budou trvale smazány.', - 'vacay.personName': 'Jméno', - 'vacay.personNamePlaceholder': 'Zadejte jméno', - 'vacay.color': 'Barva', - 'vacay.add': 'Přidat', - 'vacay.legend': 'Legenda', - 'vacay.publicHoliday': 'Státní svátek', - 'vacay.companyHoliday': 'Firemní volno', - 'vacay.weekend': 'Víkend', - 'vacay.modeVacation': 'Dovolená', - 'vacay.modeCompany': 'Firemní volno', - 'vacay.entitlement': 'Nárok', - 'vacay.entitlementDays': 'Dní', - 'vacay.used': 'Vyčerpáno', - 'vacay.remaining': 'Zbývá', - 'vacay.carriedOver': 'z roku {year}', - 'vacay.blockWeekends': 'Blokovat víkendy', - 'vacay.blockWeekendsHint': 'Zamezit zadávání dovolené na víkendové dny', - 'vacay.mon': 'Po', - 'vacay.tue': 'Út', - 'vacay.wed': 'St', - 'vacay.thu': 'Čt', - 'vacay.fri': 'Pá', - 'vacay.sat': 'So', - 'vacay.sun': 'Ne', - 'vacay.weekendDays': 'Víkendové dny', - 'vacay.publicHolidays': 'Státní svátky', - 'vacay.publicHolidaysHint': 'Zobrazit státní svátky v kalendáři', - 'vacay.selectCountry': 'Vyberte zemi', - 'vacay.selectRegion': 'Vyberte region (volitelné)', - 'vacay.addCalendar': 'Přidat kalendář', - 'vacay.calendarLabel': 'Popisek (volitelné)', - 'vacay.calendarColor': 'Barva', - 'vacay.noCalendars': 'Zatím nebyly přidány žádné svátkové kalendáře', - 'vacay.companyHolidays': 'Firemní volno', - 'vacay.companyHolidaysHint': 'Povolit označování dnů celofiremního volna', - 'vacay.companyHolidaysNoDeduct': 'Firemní volno se nezapočítává do nároku na dovolenou.', - 'vacay.carryOver': 'Převod dovolené', - 'vacay.carryOverHint': 'Automaticky převádět zbývající dny do dalšího roku', - 'vacay.sharing': 'Sdílení', - 'vacay.sharingHint': 'Sdílejte svůj plán dovolené s ostatními uživateli TREK', - 'vacay.owner': 'Vlastník', - 'vacay.shareEmailPlaceholder': 'E-mail uživatele TREK', - 'vacay.shareSuccess': 'Plán byl úspěšně sdílen', - 'vacay.shareError': 'Nepodařilo se sdílet plán', - 'vacay.dissolve': 'Zrušit propojení', - 'vacay.dissolveHint': 'Znovu oddělit kalendáře. Vaše záznamy zůstanou zachovány.', - 'vacay.dissolveAction': 'Oddělit', - 'vacay.dissolved': 'Kalendáře byly odděleny', - 'vacay.fusedWith': 'Propojeno s', - 'vacay.you': 'vy', - 'vacay.noData': 'Žádná data', - 'vacay.changeColor': 'Změnit barvu', - 'vacay.inviteUser': 'Pozvat uživatele', - 'vacay.inviteHint': 'Pozvěte jiného uživatele TREK ke sdílení společného kalendáře dovolených.', - 'vacay.selectUser': 'Vyberte uživatele', - 'vacay.sendInvite': 'Odeslat pozvánku', - 'vacay.inviteSent': 'Pozvánka odeslána', - 'vacay.inviteError': 'Nepodařilo se odeslat pozvánku', - 'vacay.pending': 'čeká na vyřízení', - 'vacay.noUsersAvailable': 'Žádní uživatelé nejsou k dispozici', - 'vacay.accept': 'Přijmout', - 'vacay.decline': 'Odmítnout', - 'vacay.acceptFusion': 'Přijmout a propojit', - 'vacay.inviteTitle': 'Žádost o propojení', - 'vacay.inviteWantsToFuse': 'vás zve ke sdílení kalendáře dovolených.', - 'vacay.fuseInfo1': 'Oba uvidíte všechny záznamy v jednom sdíleném kalendáři.', - 'vacay.fuseInfo2': 'Obě strany mohou vytvářet a upravovat záznamy tomu druhému.', - 'vacay.fuseInfo3': 'Obě strany mohou měnit nároky na dovolenou.', - 'vacay.fuseInfo4': 'Nastavení (svátky, firemní volno) jsou sdílená.', - 'vacay.fuseInfo5': 'Propojení lze kdykoli zrušit bez ztráty dat.', - - // Atlas doplněk - 'atlas.subtitle': 'Vaše stopa ve světě', - 'atlas.countries': 'Země', - 'atlas.trips': 'Cesty', - 'atlas.places': 'Místa', - 'atlas.unmark': 'Odebrat', - 'atlas.confirmMark': 'Označit tuto zemi jako navštívenou?', - 'atlas.confirmUnmark': 'Odebrat tuto zemi ze seznamu navštívených?', - 'atlas.markVisited': 'Označit jako navštívené', - 'atlas.markVisitedHint': 'Přidat tuto zemi do seznamu navštívených', - 'atlas.addToBucket': 'Přidat do seznamu přání (Bucket list)', - 'atlas.addPoi': 'Přidat místo', - 'atlas.bucketNamePlaceholder': 'Název (země, město, místo...)', - 'atlas.month': 'Měsíc', - 'atlas.addToBucketHint': 'Uložit jako místo, které chcete navštívit', - 'atlas.bucketWhen': 'Kdy plánujete návštěvu?', - 'atlas.statsTab': 'Statistiky', - 'atlas.bucketTab': 'Bucket List', - 'atlas.addBucket': 'Přidat na Bucket List', - 'atlas.bucketNamePlaceholder': 'Místo nebo destinace...', - 'atlas.bucketNotesPlaceholder': 'Poznámky (volitelné)', - 'atlas.bucketEmpty': 'Váš seznam přání je prázdný', - 'atlas.bucketEmptyHint': 'Přidejte místa, která sníte navštívit', - 'atlas.days': 'Dní', - 'atlas.visitedCountries': 'Navštívené země', - 'atlas.cities': 'Města', - 'atlas.noData': 'Zatím žádná cestovatelská data', - 'atlas.noDataHint': 'Vytvořte cestu a přidejte místa, abyste viděli svou mapu světa', - 'atlas.lastTrip': 'Poslední cesta', - 'atlas.nextTrip': 'Další cesta', - 'atlas.daysLeft': 'dní zbývá', - 'atlas.streak': 'Série', - 'atlas.year': 'rok', - 'atlas.years': 'roky/let', - 'atlas.yearInRow': 'rok v řadě', - 'atlas.yearsInRow': 'let v řadě', - 'atlas.tripIn': 'cesta v roce', - 'atlas.tripsIn': 'cest v roce', - 'atlas.since': 'od', - 'atlas.europe': 'Evropa', - 'atlas.asia': 'Asie', - 'atlas.northAmerica': 'S. Amerika', - 'atlas.southAmerica': 'J. Amerika', - 'atlas.africa': 'Afrika', - 'atlas.oceania': 'Oceánie', - 'atlas.other': 'Ostatní', - 'atlas.firstVisit': 'První cesta', - 'atlas.lastVisitLabel': 'Poslední cesta', - 'atlas.tripSingular': 'Cesta', - 'atlas.tripPlural': 'Cesty', - 'atlas.placeVisited': 'Navštívené místo', - 'atlas.placesVisited': 'Navštívená místa', - - // Plánovač cesty (Trip Planner) - 'trip.tabs.plan': 'Plán', - 'trip.tabs.reservations': 'Rezervace', - 'trip.tabs.reservationsShort': 'Rez.', - 'trip.tabs.packing': 'Seznam věcí', - 'trip.tabs.packingShort': 'Balení', - 'trip.tabs.budget': 'Rozpočet', - 'trip.tabs.files': 'Soubory', - 'trip.loading': 'Načítání cesty...', - 'trip.mobilePlan': 'Plán', - 'trip.mobilePlaces': 'Místa', - 'trip.toast.placeUpdated': 'Místo bylo aktualizováno', - 'trip.toast.placeAdded': 'Místo bylo přidáno', - 'trip.toast.placeDeleted': 'Místo bylo smazáno', - 'trip.toast.selectDay': 'Prosím nejdříve vyberte den', - 'trip.toast.assignedToDay': 'Místo bylo přiřazeno ke dni', - 'trip.toast.reorderError': 'Nepodařilo se změnit pořadí', - 'trip.toast.reservationUpdated': 'Rezervace aktualizována', - 'trip.toast.reservationAdded': 'Rezervace přidána', - 'trip.toast.deleted': 'Smazáno', - 'trip.confirm.deletePlace': 'Opravdu chcete toto místo smazat?', - - // Denní plán (Day Plan) - 'dayplan.emptyDay': 'Na tento den nejsou naplánována žádná místa', - 'dayplan.addNote': 'Přidat poznámku', - 'dayplan.editNote': 'Upravit poznámku', - 'dayplan.noteAdd': 'Přidat poznámku', - 'dayplan.noteEdit': 'Upravit poznámku', - 'dayplan.noteTitle': 'Poznámka', - 'dayplan.noteSubtitle': 'Poznámka ke dni', - 'dayplan.totalCost': 'Celkové náklady', - 'dayplan.days': 'Dny', - 'dayplan.dayN': 'Den {n}', - 'dayplan.calculating': 'Počítání...', - 'dayplan.route': 'Trasa', - 'dayplan.optimize': 'Optimalizovat', - 'dayplan.optimized': 'Trasa optimalizována', - 'dayplan.routeError': 'Nepodařilo se vypočítat trasu', - 'dayplan.toast.needTwoPlaces': 'Pro optimalizaci trasy jsou potřeba alespoň dvě místa', - 'dayplan.toast.routeOptimized': 'Trasa byla optimalizována', - 'dayplan.toast.noGeoPlaces': 'Nebyla nalezena žádná místa se souřadnicemi pro výpočet trasy', - 'dayplan.confirmed': 'Potvrzeno', - 'dayplan.pendingRes': 'Čeká na potvrzení', - 'dayplan.pdf': 'PDF', - 'dayplan.pdfTooltip': 'Exportovat denní plán do PDF', - 'dayplan.pdfError': 'Export do PDF se nezdařil', - 'dayplan.cannotReorderTransport': 'Rezervace s pevným časem nelze přeuspořádat', - 'dayplan.confirmRemoveTimeTitle': 'Odebrat čas?', - 'dayplan.confirmRemoveTimeBody': 'Toto místo má pevný čas ({time}). Přesunutím se čas odebere a povolí se volné řazení.', - 'dayplan.confirmRemoveTimeAction': 'Odebrat čas a přesunout', - 'dayplan.cannotDropOnTimed': 'Položky nelze umístit mezi záznamy s pevným časem', - 'dayplan.cannotBreakChronology': 'Toto by porušilo chronologické pořadí naplánovaných položek a rezervací', - - // Boční panel míst (Places Sidebar) - 'places.addPlace': 'Přidat místo/aktivitu', - 'places.importGpx': 'Importovat GPX', - 'places.gpxImported': '{count} míst importováno z GPX', - 'places.urlResolved': 'Místo importováno z URL', - 'places.gpxError': 'Import GPX se nezdařil', - 'places.assignToDay': 'Přidat do kterého dne?', - 'places.all': 'Vše', - 'places.unplanned': 'Nezařazené', - 'places.search': 'Hledat místa...', - 'places.allCategories': 'Všechny kategorie', - 'places.categoriesSelected': 'kategorií', - 'places.clearFilter': 'Vymazat filtr', - 'places.count': '{count} míst', - 'places.countSingular': '1 místo', - 'places.allPlanned': 'Všechna místa jsou naplánována', - 'places.noneFound': 'Žádná místa nebyla nalezena', - 'places.editPlace': 'Upravit místo', - 'places.formName': 'Název', - 'places.formNamePlaceholder': 'např. Eiffelova věž', - 'places.formDescription': 'Popis', - 'places.formDescriptionPlaceholder': 'Krátký popis...', - 'places.formAddress': 'Adresa', - 'places.formAddressPlaceholder': 'Ulice, město, země', - 'places.formLat': 'Zeměpisná šířka', - 'places.formLng': 'Zeměpisná délka', - 'places.formCategory': 'Kategorie', - 'places.noCategory': 'Bez kategorie', - 'places.categoryNamePlaceholder': 'Název kategorie', - 'places.formTime': 'Čas', - 'places.startTime': 'Od', - 'places.endTime': 'Do', - 'places.endTimeBeforeStart': 'Čas konce je před časem začátku', - 'places.timeCollision': 'Časový překryv s:', - 'places.formWebsite': 'Webové stránky', - 'places.formNotesPlaceholder': 'Osobní poznámky...', - 'places.formReservation': 'Rezervace', - 'places.reservationNotesPlaceholder': 'Poznámky k rezervaci, potvrzovací kód...', - 'places.mapsSearchPlaceholder': 'Hledat místa...', - 'places.mapsSearchError': 'Hledání místa se nezdařilo.', - 'places.osmHint': 'Používáte hledání přes OpenStreetMap (bez fotek a hodnocení). Pro plné detaily přidejte Google API klíč v nastavení.', - 'places.osmActive': 'Hledání přes OpenStreetMap.', - 'places.categoryCreateError': 'Nepodařilo se vytvořit kategorii', - 'places.nameRequired': 'Prosím zadejte název', - 'places.saveError': 'Uložení se nezdařilo', - - // Inspektor míst (Place Inspector) - 'inspector.opened': 'Otevřeno', - 'inspector.closed': 'Zavřeno', - 'inspector.openingHours': 'Otevírací doba', - 'inspector.showHours': 'Zobrazit otevírací dobu', - 'inspector.files': 'Soubory', - 'inspector.filesCount': '{count} souborů', - 'inspector.removeFromDay': 'Odebrat ze dne', - 'inspector.addToDay': 'Přidat ke dni', - 'inspector.confirmedRes': 'Potvrzená rezervace', - 'inspector.pendingRes': 'Čekající rezervace', - 'inspector.google': 'Otevřít v Google Mapách', - 'inspector.website': 'Otevřít webové stránky', - 'inspector.addRes': 'Rezervace', - 'inspector.editRes': 'Upravit rezervaci', - 'inspector.participants': 'Účastníci', - - // Rezervace (Reservations) - 'reservations.title': 'Rezervace', - 'reservations.empty': 'Zatím žádné rezervace', - 'reservations.emptyHint': 'Přidejte rezervace letů, hotelů a dalších', - 'reservations.add': 'Přidat rezervaci', - 'reservations.addManual': 'Ruční rezervace', - 'reservations.placeHint': 'Tip: Rezervace je nejlepší vytvářet přímo z místa – propojí se tak s denním plánem.', - 'reservations.confirmed': 'Potvrzeno', - 'reservations.pending': 'Čeká na potvrzení', - 'reservations.summary': '{confirmed} potvrzených, {pending} čekajících', - 'reservations.fromPlan': 'Z plánu', - 'reservations.showFiles': 'Zobrazit soubory', - 'reservations.editTitle': 'Upravit rezervaci', - 'reservations.status': 'Stav', - 'reservations.datetime': 'Datum a čas', - 'reservations.startTime': 'Čas začátku', - 'reservations.endTime': 'Čas konce', - 'reservations.date': 'Datum', - 'reservations.time': 'Čas', - 'reservations.timeAlt': 'Čas (alternativní, např. 19:30)', - 'reservations.notes': 'Poznámky', - 'reservations.notesPlaceholder': 'Další poznámky...', - 'reservations.meta.airline': 'Letecká společnost', - 'reservations.meta.flightNumber': 'Číslo letu', - 'reservations.meta.from': 'Z', - 'reservations.meta.to': 'Do', - 'reservations.meta.trainNumber': 'Číslo vlaku', - 'reservations.meta.platform': 'Nástupiště', - 'reservations.meta.seat': 'Sedadlo', - 'reservations.meta.checkIn': 'Check-in', - 'reservations.meta.checkOut': 'Check-out', - 'reservations.meta.linkAccommodation': 'Ubytování', - 'reservations.meta.pickAccommodation': 'Propojit s ubytováním', - 'reservations.meta.noAccommodation': 'Nic', - 'reservations.meta.hotelPlace': 'Ubytování', - 'reservations.meta.pickHotel': 'Vybrat ubytování', - 'reservations.meta.fromDay': 'Od dne', - 'reservations.meta.toDay': 'Do dne', - 'reservations.meta.selectDay': 'Vyberte den', - 'reservations.type.flight': 'Let', - 'reservations.type.hotel': 'Ubytování', - 'reservations.type.restaurant': 'Restaurace', - 'reservations.type.train': 'Vlak', - 'reservations.type.car': 'Pronájem auta', - 'reservations.type.cruise': 'Plavba', - 'reservations.type.event': 'Událost', - 'reservations.type.tour': 'Prohlídka', - 'reservations.type.other': 'Jiné', - 'reservations.confirm.delete': 'Opravdu chcete smazat rezervaci „{name}”?', - 'reservations.confirm.deleteTitle': 'Smazat rezervaci?', - 'reservations.confirm.deleteBody': '„{name}” bude trvale smazána.', - 'reservations.toast.updated': 'Rezervace aktualizována', - 'reservations.toast.removed': 'Rezervace smazána', - 'reservations.toast.fileUploaded': 'Soubor byl nahrán', - 'reservations.toast.uploadError': 'Nahrávání se nezdařilo', - 'reservations.newTitle': 'Nová rezervace', - 'reservations.bookingType': 'Typ rezervace', - 'reservations.titleLabel': 'Název', - 'reservations.titlePlaceholder': 'např. Let LH123, Hotel Adlon...', - 'reservations.locationAddress': 'Místo / Adresa', - 'reservations.locationPlaceholder': 'Adresa, letiště, hotel...', - 'reservations.confirmationCode': 'Rezervační kód', - 'reservations.confirmationPlaceholder': 'např. ABC12345', - 'reservations.day': 'Den', - 'reservations.noDay': 'Žádný den', - 'reservations.place': 'Místo', - 'reservations.noPlace': 'Žádné místo', - 'reservations.pendingSave': 'bude uloženo…', - 'reservations.uploading': 'Nahrávání...', - 'reservations.attachFile': 'Přiložit soubor', - 'reservations.linkExisting': 'Propojit stávající soubor', - 'reservations.toast.saveError': 'Uložení se nezdařilo', - 'reservations.toast.updateError': 'Aktualizace se nezdařila', - 'reservations.toast.deleteError': 'Smazání se nezdařilo', - 'reservations.confirm.remove': 'Odstranit rezervaci pro „{name}”?', - 'reservations.linkAssignment': 'Propojit s přiřazením dne', - 'reservations.pickAssignment': 'Vyberte přiřazení z vašeho plánu...', - 'reservations.noAssignment': 'Bez propojení (samostatné)', - - // Rozpočet (Budget) - 'budget.title': 'Rozpočet', - 'budget.emptyTitle': 'Zatím nebyl vytvořen žádný rozpočet', - 'budget.emptyText': 'Vytvořte kategorie a položky pro plánování cestovního rozpočtu', - 'budget.emptyPlaceholder': 'Zadejte název kategorie...', - 'budget.createCategory': 'Vytvořit kategorii', - 'budget.category': 'Kategorie', - 'budget.categoryName': 'Název kategorie', - 'budget.table.name': 'Název', - 'budget.table.total': 'Celkem', - 'budget.table.persons': 'Osoby', - 'budget.table.days': 'Dní', - 'budget.table.perPerson': 'Na osobu', - 'budget.table.perDay': 'Za den', - 'budget.table.perPersonDay': 'Os. / den', - 'budget.table.note': 'Poznámka', - 'budget.newEntry': 'Nová položka', - 'budget.defaultEntry': 'Nová položka', - 'budget.defaultCategory': 'Nová kategorie', - 'budget.total': 'Celkem', - 'budget.totalBudget': 'Celkový rozpočet', - 'budget.byCategory': 'Podle kategorie', - 'budget.editTooltip': 'Klikněte pro úpravu', - 'budget.confirm.deleteCategory': 'Opravdu chcete smazat kategorii „{name}” s {count} položkami?', - 'budget.deleteCategory': 'Smazat kategorii', - 'budget.perPerson': 'Na osobu', - 'budget.paid': 'Zaplaceno', - 'budget.open': 'Nezaplaceno', - 'budget.noMembers': 'Žádní členové nebyli přiřazeni', - 'budget.settlement': 'Vyúčtování', - 'budget.settlementInfo': 'Klikněte na avatar člena u rozpočtové položky pro zelené označení – to znamená, že zaplatil. Vyúčtování pak ukazuje, kdo komu a kolik dluží.', - 'budget.netBalances': 'Čisté zůstatky', - - // Soubory (Files) - 'files.title': 'Soubory', - 'files.count': '{count} souborů', - 'files.countSingular': '1 soubor', - 'files.uploaded': '{count} nahráno', - 'files.uploadError': 'Nahrávání se nezdařilo', - 'files.dropzone': 'Přetáhněte soubory sem', - 'files.dropzoneHint': 'nebo klikněte pro výběr', - 'files.allowedTypes': 'Obrázky, PDF, DOC, DOCX, XLS, XLSX, TXT, CSV · Max 50 MB', - 'files.uploading': 'Nahrávání...', - 'files.filterAll': 'Vše', - 'files.filterPdf': 'PDF', - 'files.filterImages': 'Obrázky', - 'files.filterDocs': 'Dokumenty', - 'files.filterCollab': 'Poznámky spolupráce', - 'files.sourceCollab': 'Z poznámek spolupráce', - 'files.empty': 'Zatím žádné soubory', - 'files.emptyHint': 'Nahrajte soubory k vaší cestě', - 'files.openTab': 'Otevřít v nové kartě', - 'files.confirm.delete': 'Opravdu chcete smazat tento soubor?', - 'files.toast.deleted': 'Soubor byl smazán', - 'files.toast.deleteError': 'Nepodařilo se smazat soubor', - 'files.sourcePlan': 'Denní plán', - 'files.sourceBooking': 'Rezervace', - 'files.attach': 'Přiložit', - 'files.pasteHint': 'Můžete také vložit obrázek ze schránky (Ctrl+V)', - 'files.trash': 'Koš', - 'files.trashEmpty': 'Koš je prázdný', - 'files.emptyTrash': 'Vysypat koš', - 'files.restore': 'Obnovit', - 'files.star': 'Označit hvězdičkou', - 'files.unstar': 'Odebrat hvězdičku', - 'files.assign': 'Přiřadit', - 'files.assignTitle': 'Přiřadit soubor', - 'files.assignPlace': 'Místo', - 'files.assignBooking': 'Rezervace', - 'files.unassigned': 'Nepřiřazeno', - 'files.unlink': 'Zrušit propojení', - 'files.toast.trashed': 'Přesunuto do koše', - 'files.toast.restored': 'Soubor byl obnoven', - 'files.toast.trashEmptied': 'Koš byl vysypán', - 'files.toast.assigned': 'Soubor byl přiřazen', - 'files.toast.assignError': 'Přiřazení se nezdařilo', - 'files.toast.restoreError': 'Obnovení se nezdařilo', - 'files.confirm.permanentDelete': 'Trvale smazat tento soubor? Tuto akci nelze vrátit.', - 'files.confirm.emptyTrash': 'Trvale smazat všechny soubory v koši? Tuto akci nelze vrátit.', - 'files.noteLabel': 'Poznámka', - 'files.notePlaceholder': 'Přidat poznámku...', - - // Balení (Packing) - 'packing.title': 'Seznam věcí', - 'packing.empty': 'Seznam věcí je prázdný', - 'packing.import': 'Importovat', - 'packing.importTitle': 'Importovat seznam', - 'packing.importHint': 'Jedna položka na řádek. Formát: Kategorie, Název, Váha v g (volitelné), Zavazadlo (volitelné), checked/unchecked (volitelné)', - 'packing.importPlaceholder': 'Hygiena, Zubní kartáček\nOblečení, Trička, 200\nDokumenty, Pas, , Příruční zavazadlo\nElektronika, Nabíječka, 50, Kufr, checked', - 'packing.importCsv': 'Načíst CSV/TXT', - 'packing.importAction': 'Importovat {count}', - 'packing.importSuccess': '{count} položek importováno', - 'packing.importError': 'Import se nezdařil', - 'packing.importEmpty': 'Žádné položky k importu', - 'packing.progress': '{packed} z {total} zabaleno ({percent} %)', - 'packing.clearChecked': 'Odstranit {count} hotových', - 'packing.clearCheckedShort': 'Odstranit {count}', - 'packing.suggestions': 'Návrhy', - 'packing.suggestionsTitle': 'Přidat návrhy', - 'packing.allSuggested': 'Všechny návrhy byly přidány', - 'packing.allPacked': 'Vše je zabaleno!', - 'packing.addPlaceholder': 'Přidat novou položku...', - 'packing.categoryPlaceholder': 'Kategorie...', - 'packing.filterAll': 'Vše', - 'packing.filterOpen': 'K zabalení', - 'packing.filterDone': 'Hotovo', - 'packing.emptyTitle': 'Seznam věcí je prázdný', - 'packing.emptyHint': 'Přidejte položky nebo použijte návrhy', - 'packing.emptyFiltered': 'Žádné položky neodpovídají filtru', - 'packing.menuRename': 'Přejmenovat', - 'packing.menuCheckAll': 'Označit vše', - 'packing.menuUncheckAll': 'Odznačit vše', - 'packing.menuDeleteCat': 'Smazat kategorii', - 'packing.assignUser': 'Přiřadit uživateli', - 'packing.noMembers': 'Žádní členové cesty', - 'packing.addItem': 'Přidat položku', - 'packing.addItemPlaceholder': 'Název položky...', - 'packing.addCategory': 'Přidat kategorii', - 'packing.newCategoryPlaceholder': 'Název kategorie (např. Oblečení)', - 'packing.applyTemplate': 'Použít šablonu', - 'packing.template': 'Šablona', - 'packing.templateApplied': '{count} položek přidáno ze šablony', - 'packing.templateError': 'Šablonu se nepodařilo použít', - 'packing.bags': 'Zavazadla', - 'packing.noBag': 'Nepřiřazeno', - 'packing.totalWeight': 'Celková váha', - 'packing.bagName': 'Název zavazadla...', - 'packing.addBag': 'Přidat zavazadlo', - 'packing.changeCategory': 'Změnit kategorii', - 'packing.confirm.clearChecked': 'Opravdu chcete odstranit {count} zabalených položek?', - 'packing.confirm.deleteCat': 'Opravdu chcete smazat kategorii „{name}" s {count} položkami?', - 'packing.defaultCategory': 'Ostatní', - 'packing.toast.saveError': 'Uložení se nezdařilo', - 'packing.toast.deleteError': 'Smazání se nezdařilo', - 'packing.toast.renameError': 'Přejmenování se nezdařilo', - 'packing.toast.addError': 'Přidání se nezdařilo', - - // Návrhy balení (Packing suggestions) - 'packing.suggestions.items': [ - { name: 'Pas', category: 'Dokumenty' }, - { name: 'Občanský průkaz', category: 'Dokumenty' }, - { name: 'Cestovní pojištění', category: 'Dokumenty' }, - { name: 'Letenky', category: 'Dokumenty' }, - { name: 'Platební karta', category: 'Finance' }, - { name: 'Hotovost', category: 'Finance' }, - { name: 'Víza', category: 'Dokumenty' }, - { name: 'Trička', category: 'Oblečení' }, - { name: 'Kalhoty', category: 'Oblečení' }, - { name: 'Spodní prádlo', category: 'Oblečení' }, - { name: 'Ponožky', category: 'Oblečení' }, - { name: 'Bunda', category: 'Oblečení' }, - { name: 'Pyžamo', category: 'Oblečení' }, - { name: 'Plavky', category: 'Oblečení' }, - { name: 'Pláštěnka', category: 'Oblečení' }, - { name: 'Pohodlné boty', category: 'Oblečení' }, - { name: 'Zubní kartáček', category: 'Hygiena' }, - { name: 'Zubní pasta', category: 'Hygiena' }, - { name: 'Šampón', category: 'Hygiena' }, - { name: 'Deodorant', category: 'Hygiena' }, - { name: 'Opalovací krém', category: 'Hygiena' }, - { name: 'Holicí strojek', category: 'Hygiena' }, - { name: 'Nabíječka', category: 'Elektronika' }, - { name: 'Powerbanka', category: 'Elektronika' }, - { name: 'Sluchátka', category: 'Elektronika' }, - { name: 'Cestovní adaptér', category: 'Elektronika' }, - { name: 'Fotoaparát', category: 'Elektronika' }, - { name: 'Léky proti bolesti', category: 'Zdraví' }, - { name: 'Náplasti', category: 'Zdraví' }, - { name: 'Dezinfekce', category: 'Zdraví' }, - ], - - // Členové / Sdílení (Members) - 'members.shareTrip': 'Sdílet cestu', - 'members.inviteUser': 'Pozvat uživatele', - 'members.selectUser': 'Vyberte uživatele…', - 'members.invite': 'Pozvat', - 'members.allHaveAccess': 'Všichni uživatelé již mají přístup.', - 'members.access': 'Přístup', - 'members.person': 'osoba', - 'members.persons': 'osob', - 'members.you': 'vy', - 'members.owner': 'Vlastník', - 'members.leaveTrip': 'Opustit cestu', - 'members.removeAccess': 'Odebrat přístup', - 'members.confirmLeave': 'Opustit cestu? Ztratíte přístup.', - 'members.confirmRemove': 'Odebrat přístup tomuto uživateli?', - 'members.loadError': 'Nepodařilo se načíst členy', - 'members.added': 'přidán/a', - 'members.addError': 'Nepodařilo se přidat', - 'members.removed': 'Člen odebrán', - 'members.removeError': 'Nepodařilo se odebrat', - - // Kategorie (Admin) - 'categories.title': 'Kategorie', - 'categories.subtitle': 'Správa kategorií pro místa', - 'categories.new': 'Nová kategorie', - 'categories.empty': 'Zatím žádné kategorie', - 'categories.namePlaceholder': 'Název kategorie', - 'categories.icon': 'Ikona', - 'categories.color': 'Barva', - 'categories.customColor': 'Vybrat vlastní barvu', - 'categories.preview': 'Náhled', - 'categories.defaultName': 'Kategorie', - 'categories.update': 'Aktualizovat', - 'categories.create': 'Vytvořit', - 'categories.confirm.delete': 'Smazat kategorii? Místa v této kategorii nebudou smazána.', - 'categories.toast.loadError': 'Nepodařilo se načíst kategorie', - 'categories.toast.nameRequired': 'Prosím zadejte název', - 'categories.toast.updated': 'Kategorie aktualizována', - 'categories.toast.created': 'Kategorie vytvořena', - 'categories.toast.saveError': 'Uložení se nezdařilo', - 'categories.toast.deleted': 'Kategorie smazána', - 'categories.toast.deleteError': 'Smazání se nezdařilo', - - // Zálohování (Backup) - 'backup.title': 'Záloha dat', - 'backup.subtitle': 'Databáze a všechny nahrané soubory', - 'backup.refresh': 'Obnovit', - 'backup.upload': 'Nahrát zálohu', - 'backup.uploading': 'Nahrávání…', - 'backup.create': 'Vytvořit zálohu', - 'backup.creating': 'Vytváření…', - 'backup.empty': 'Zatím žádné zálohy', - 'backup.createFirst': 'Vytvořit první zálohu', - 'backup.download': 'Stáhnout', - 'backup.restore': 'Obnovit', - 'backup.confirm.restore': 'Obnovit zálohu „{name}"?\n\nVšechna aktuální data budou nahrazena zálohou.', - 'backup.confirm.uploadRestore': 'Nahrát a obnovit zálohu „{name}"?\n\nVšechna aktuální data budou přepsána.', - 'backup.confirm.delete': 'Smazat zálohu „{name}"?', - 'backup.toast.loadError': 'Nepodařilo se načíst zálohy', - 'backup.toast.created': 'Záloha byla úspěšně vytvořena', - 'backup.toast.createError': 'Nepodařilo se vytvořit zálohu', - 'backup.toast.restored': 'Záloha obnovena. Stránka se znovu načte…', - 'backup.toast.restoreError': 'Obnovení se nezdařilo', - 'backup.toast.uploadError': 'Nahrávání se nezdařilo', - 'backup.toast.deleted': 'Záloha smazána', - 'backup.toast.deleteError': 'Smazání se nezdařilo', - 'backup.toast.downloadError': 'Stahování se nezdařilo', - 'backup.toast.settingsSaved': 'Nastavení automatického zálohování uloženo', - 'backup.toast.settingsError': 'Nepodařilo se uložit nastavení', - 'backup.auto.title': 'Automatické zálohování', - 'backup.auto.subtitle': 'Automatické zálohování podle plánu', - 'backup.auto.enable': 'Povolit automatické zálohování', - 'backup.auto.enableHint': 'Zálohy budou vytvářeny automaticky podle zvoleného plánu', - 'backup.auto.interval': 'Interval', - 'backup.auto.hour': 'Spustit v hodinu', - 'backup.auto.hourHint': 'Místní čas serveru (formát {format})', - 'backup.auto.dayOfWeek': 'Den v týdnu', - 'backup.auto.dayOfMonth': 'Den v měsíci', - 'backup.auto.dayOfMonthHint': 'Omezeno na 1–28 pro kompatibilitu se všemi měsíci', - 'backup.auto.scheduleSummary': 'Plán', - 'backup.auto.summaryDaily': 'Každý den v {hour}:00', - 'backup.auto.summaryWeekly': 'Každý {day} v {hour}:00', - 'backup.auto.summaryMonthly': '{day}. každého měsíce v {hour}:00', - 'backup.auto.envLocked': 'Docker', - 'backup.auto.envLockedHint': 'Automatické zálohování je konfigurováno přes Docker proměnné prostředí. Pro změnu nastavení aktualizujte docker-compose.yml a restartujte kontejner.', - 'backup.auto.copyEnv': 'Zkopírovat Docker proměnné', - 'backup.auto.envCopied': 'Docker proměnné prostředí zkopírovány do schránky', - 'backup.auto.keepLabel': 'Smazat staré zálohy po', - 'backup.dow.sunday': 'Ne', - 'backup.dow.monday': 'Po', - 'backup.dow.tuesday': 'Út', - 'backup.dow.wednesday': 'St', - 'backup.dow.thursday': 'Čt', - 'backup.dow.friday': 'Pá', - 'backup.dow.saturday': 'So', - 'backup.interval.hourly': 'Každou hodinu', - 'backup.interval.daily': 'Denně', - 'backup.interval.weekly': 'Týdně', - 'backup.interval.monthly': 'Měsíčně', - 'backup.keep.1day': '1 den', - 'backup.keep.3days': '3 dny', - 'backup.keep.7days': '7 dní', - 'backup.keep.14days': '14 dní', - 'backup.keep.30days': '30 dní', - 'backup.keep.forever': 'Uchovávat navždy', - - // Fotky - 'photos.allDays': 'Všechny dny', - 'photos.noPhotos': 'Zatím žádné fotky', - 'photos.uploadHint': 'Nahrajte své cestovní fotky', - 'photos.clickToSelect': 'nebo klikněte pro výběr', - 'photos.linkPlace': 'Propojit s místem', - 'photos.noPlace': 'Žádné místo', - 'photos.uploadN': 'Nahrát {n} fotek', - - // Obnovení zálohy - 'backup.restoreConfirmTitle': 'Obnovit zálohu?', - 'backup.restoreWarning': 'Všechna aktuální data (cesty, místa, uživatelé, nahrané soubory) budou trvale nahrazena zálohou. Tuto akci nelze vrátit.', - 'backup.restoreTip': 'Tip: Před obnovením vytvořte zálohu aktuálního stavu.', - 'backup.restoreConfirm': 'Ano, obnovit', - - // PDF - 'pdf.travelPlan': 'Cestovní plán', - 'pdf.planned': 'Naplánováno', - 'pdf.costLabel': 'Náklady EUR', - 'pdf.preview': 'Náhled PDF', - 'pdf.saveAsPdf': 'Uložit jako PDF', - - // Plánovač (Planner) - 'planner.places': 'Místa', - 'planner.bookings': 'Rezervace', - 'planner.packingList': 'Seznam věcí', - 'planner.documents': 'Dokumenty', - 'planner.dayPlan': 'Denní plán', - 'planner.reservations': 'Rezervace', - 'planner.minTwoPlaces': 'Potřebujete alespoň 2 místa se souřadnicemi', - 'planner.noGeoPlaces': 'Žádná místa se souřadnicemi nejsou k dispozici', - 'planner.routeCalculated': 'Trasa vypočtena', - 'planner.routeCalcFailed': 'Trasu se nepodařilo vypočítat', - 'planner.routeError': 'Chyba při výpočtu trasy', - 'planner.routeOptimized': 'Trasa optimalizována', - 'planner.reservationUpdated': 'Rezervace aktualizována', - 'planner.reservationAdded': 'Rezervace přidána', - 'planner.confirmDeleteReservation': 'Smazat rezervaci?', - 'planner.reservationDeleted': 'Rezervace smazána', - 'planner.days': 'Dny', - 'planner.allPlaces': 'Všechna místa', - 'planner.totalPlaces': 'Celkem {n} míst', - 'planner.noDaysPlanned': 'Zatím nejsou naplánovány žádné dny', - 'planner.editTrip': 'Upravit cestu \u2192', - 'planner.placeOne': '1 místo', - 'planner.placeN': '{n} míst', - 'planner.addNote': 'Přidat poznámku', - 'planner.noEntries': 'Pro tento den nejsou žádné záznamy', - 'planner.addPlace': 'Přidat místo/aktivitu', - 'planner.addPlaceShort': '+ Přidat místo/aktivitu', - 'planner.resPending': 'Rezervace čeká · ', - 'planner.resConfirmed': 'Rezervace potvrzena · ', - 'planner.notePlaceholder': 'Poznámka\u2026', - 'planner.noteTimePlaceholder': 'Čas (volitelné)', - 'planner.noteExamplePlaceholder': 'např. S3 ve 14:30 z hlavního nádraží, trajekt z přístaviště 7, přestávka na oběd\u2026', - 'planner.totalCost': 'Celkové náklady', - 'planner.searchPlaces': 'Hledat místa\u2026', - 'planner.allCategories': 'Všechny kategorie', - 'planner.noPlacesFound': 'Žádná místa nenalezena', - 'planner.addFirstPlace': 'Přidat první místo', - 'planner.noReservations': 'Žádné rezervace', - 'planner.addFirstReservation': 'Přidat první rezervaci', - 'planner.new': 'Nový', - 'planner.addToDay': '+ Den', - 'planner.calculating': 'Počítání\u2026', - 'planner.route': 'Trasa', - 'planner.optimize': 'Optimalizovat', - 'planner.openGoogleMaps': 'Otevřít v Google Mapách', - 'planner.selectDayHint': 'Vyberte den ze seznamu vlevo pro zobrazení denního plánu', - 'planner.noPlacesForDay': 'Zatím žádná místa pro tento den', - 'planner.addPlacesLink': 'Přidat místa \u2192', - 'planner.minTotal': 'min. celkem', - 'planner.noReservation': 'Žádná rezervace', - 'planner.removeFromDay': 'Odebrat ze dne', - 'planner.addToThisDay': 'Přidat ke dni', - 'planner.overview': 'Přehled', - 'planner.noDays': 'Zatím žádné dny', - 'planner.editTripToAddDays': 'Upravte cestu pro přidání dnů', - 'planner.dayCount': '{n} dní', - 'planner.clickToUnlock': 'Klikněte pro odemčení', - 'planner.keepPosition': 'Zachovat pozici při optimalizaci trasy', - 'planner.dayDetails': 'Podrobnosti dne', - 'planner.dayN': 'Den {n}', - - // Statistiky (Dashboard Stats) - 'stats.countries': 'Země', - 'stats.cities': 'Města', - 'stats.trips': 'Cesty', - 'stats.places': 'Místa', - 'stats.worldProgress': 'Průzkum světa', - 'stats.visited': 'navštíveno', - 'stats.remaining': 'zbývá', - 'stats.visitedCountries': 'Navštívené země', - - // Detail dne (Day Detail Panel) - 'day.precipProb': 'Pravděpodobnost srážek', - 'day.precipitation': 'Srážky', - 'day.wind': 'Vítr', - 'day.sunrise': 'Východ slunce', - 'day.sunset': 'Západ slunce', - 'day.hourlyForecast': 'Hodinová předpověď', - 'day.climateHint': 'Historické průměry — reálná předpověď je k dispozici do 16 dnů od tohoto data.', - 'day.noWeather': 'Nejsou k dispozici žádná data o počasí. Přidejte místo se souřadnicemi.', - 'day.overview': 'Denní přehled', - 'day.accommodation': 'Ubytování', - 'day.addAccommodation': 'Přidat ubytování', - 'day.hotelDayRange': 'Použít na dny', - 'day.noPlacesForHotel': 'Nejprve přidejte místa ke své cestě', - 'day.allDays': 'Vše', - 'day.checkIn': 'Check-in', - 'day.checkOut': 'Check-out', - 'day.confirmation': 'Potvrzení', - 'day.editAccommodation': 'Upravit ubytování', - 'day.reservations': 'Rezervace', - - // Fotky / Immich - 'memories.title': 'Fotky', - 'memories.notConnected': 'Immich není připojen', - 'memories.notConnectedHint': 'Připojte svoji instanci Immich v Nastavení, abyste zde viděli fotky z cest.', - 'memories.noDates': 'Přidejte data k cestě pro načtení fotek.', - 'memories.noPhotos': 'Nenalezeny žádné fotky', - 'memories.noPhotosHint': 'V Immich nebyly nalezeny žádné fotky pro období této cesty.', - 'memories.photosFound': 'fotek', - 'memories.fromOthers': 'od ostatních', - 'memories.sharePhotos': 'Sdílet fotky', - 'memories.sharing': 'Sdílení', - 'memories.reviewTitle': 'Zkontrolujte své fotky', - 'memories.reviewHint': 'Klikněte na fotky pro vyloučení ze sdílení.', - 'memories.shareCount': 'Sdílet {count} fotek', - 'memories.immichUrl': 'URL serveru Immich', - 'memories.immichApiKey': 'API klíč', - 'memories.testConnection': 'Otestovat připojení', - 'memories.connected': 'Připojeno', - 'memories.disconnected': 'Nepřipojeno', - 'memories.connectionSuccess': 'Připojeno k Immich', - 'memories.connectionError': 'Nepodařilo se připojit k Immich', - 'memories.saved': 'Nastavení Immich uloženo', - 'memories.addPhotos': 'Přidat fotky', - 'memories.selectPhotos': 'Vybrat fotky z Immich', - 'memories.selectHint': 'Klepněte na fotky pro jejich výběr.', - 'memories.selected': 'vybráno', - 'memories.addSelected': 'Přidat {count} fotek', - 'memories.alreadyAdded': 'Přidáno', - 'memories.private': 'Soukromé', - 'memories.stopSharing': 'Zastavit sdílení', - 'memories.oldest': 'Nejstarší', - 'memories.newest': 'Nejnovější', - 'memories.allLocations': 'Všechna místa', - 'memories.tripDates': 'Data cesty', - 'memories.allPhotos': 'Všechny fotky', - 'memories.confirmShareTitle': 'Sdílet se členy cesty?', - 'memories.confirmShareHint': '{count} fotek bude viditelných pro všechny členy této cesty. Jednotlivé fotky můžete později nastavit jako soukromé.', - 'memories.confirmShareButton': 'Sdílet fotky', - - // Spolupráce (Collab) - 'collab.tabs.chat': 'Chat', - 'collab.tabs.notes': 'Poznámky', - 'collab.tabs.polls': 'Hlasování', - 'collab.whatsNext.title': 'Co následuje', - 'collab.whatsNext.today': 'Dnes', - 'collab.whatsNext.tomorrow': 'Zítra', - 'collab.whatsNext.empty': 'Žádné nadcházející aktivity', - 'collab.whatsNext.until': 'do', - 'collab.whatsNext.emptyHint': 'Aktivity s časem se zde zobrazí', - 'collab.chat.send': 'Odeslat', - 'collab.chat.placeholder': 'Napište zprávu...', - 'collab.chat.empty': 'Začněte konverzaci', - 'collab.chat.emptyHint': 'Zprávy jsou sdíleny se všemi členy cesty', - 'collab.chat.emptyDesc': 'Sdílejte nápady, plány a novinky se svou cestovatelskou skupinou', - 'collab.chat.today': 'Dnes', - 'collab.chat.yesterday': 'Včera', - 'collab.chat.deletedMessage': 'smazal zprávu', - 'collab.chat.loadMore': 'Načíst starší zprávy', - 'collab.chat.justNow': 'právě teď', - 'collab.chat.minutesAgo': 'před {n} min', - 'collab.chat.hoursAgo': 'před {n} h', - 'collab.notes.title': 'Poznámky', - 'collab.notes.new': 'Nová poznámka', - 'collab.notes.empty': 'Zatím žádné poznámky', - 'collab.notes.emptyHint': 'Začněte zapisovat nápady a plány', - 'collab.notes.all': 'Vše', - 'collab.notes.titlePlaceholder': 'Poznámka...', - 'collab.notes.noCategory': 'Bez kategorie', - 'collab.notes.color': 'Barva', - 'collab.notes.save': 'Uložit', - 'collab.notes.cancel': 'Zrušit', - 'collab.notes.edit': 'Upravit', - 'collab.notes.delete': 'Smazat', - 'collab.notes.pin': 'Připnout', - 'collab.notes.unpin': 'Odepnout', - 'collab.notes.daysAgo': 'před {n} dny', - 'collab.notes.categorySettings': 'Spravovat kategorie', - 'collab.notes.create': 'Vytvořit', - 'collab.notes.website': 'Webové stránky', - 'collab.notes.websitePlaceholder': 'https://...', - 'collab.notes.attachFiles': 'Přiložit soubory', - 'collab.notes.noCategoriesYet': 'Zatím žádné kategorie', - 'collab.notes.emptyDesc': 'Vytvořte poznámku a začněte', - 'collab.notes.contentPlaceholder': 'Napište něco...', - 'collab.notes.categoryPlaceholder': 'Kategorie', - 'collab.notes.newCategory': 'Nová kategorie...', - 'collab.notes.category': 'Kategorie', - 'collab.polls.title': 'Hlasování', - 'collab.polls.new': 'Nové hlasování', - 'collab.polls.empty': 'Zatím žádná hlasování', - 'collab.polls.emptyHint': 'Zeptejte se skupiny a hlasujte společně', - 'collab.polls.question': 'Otázka', - 'collab.polls.questionPlaceholder': 'Co bychom měli dělat?', - 'collab.polls.addOption': '+ Přidat možnost', - 'collab.polls.optionPlaceholder': 'Možnost {n}', - 'collab.polls.create': 'Vytvořit hlasování', - 'collab.polls.close': 'Uzavřít', - 'collab.polls.closed': 'Uzavřeno', - 'collab.polls.votes': '{n} hlasů', - 'collab.polls.vote': '{n} hlas', - 'collab.polls.multipleChoice': 'Více možností', - 'collab.polls.multiChoice': 'Více možností', - 'collab.polls.deadline': 'Termín', - 'collab.polls.option': 'Možnost', - 'collab.polls.options': 'Možnosti', - 'collab.polls.delete': 'Smazat', - 'collab.polls.closedSection': 'Uzavřené', -} - -export default cs +const cs: Record = { + // Společné (Common) + 'common.save': 'Uložit', + 'common.cancel': 'Zrušit', + 'common.delete': 'Smazat', + 'common.edit': 'Upravit', + 'common.add': 'Přidat', + 'common.loading': 'Načítání...', + 'common.error': 'Chyba', + 'common.back': 'Zpět', + 'common.all': 'Vše', + 'common.close': 'Zavřít', + 'common.open': 'Otevřít', + 'common.upload': 'Nahrát', + 'common.search': 'Hledat', + 'common.confirm': 'Potvrdit', + 'common.ok': 'OK', + 'common.yes': 'Ano', + 'common.no': 'Ne', + 'common.or': 'nebo', + 'common.none': 'Žádné', + 'common.date': 'Datum', + 'common.rename': 'Přejmenovat', + 'common.name': 'Jméno', + 'common.email': 'E-mail', + 'common.password': 'Heslo', + 'common.saving': 'Ukládání...', + 'common.update': 'Aktualizovat', + 'common.change': 'Změnit', + 'common.uploading': 'Nahrávání…', + 'common.backToPlanning': 'Zpět k plánování', + 'common.reset': 'Resetovat', + + // Navigační lišta (Navbar) + 'nav.trip': 'Cesta', + 'nav.share': 'Sdílet', + 'nav.settings': 'Nastavení', + 'nav.admin': 'Administrace', + 'nav.logout': 'Odhlásit se', + 'nav.lightMode': 'Světlý režim', + 'nav.darkMode': 'Tmavý režim', + 'nav.autoMode': 'Automatický režim', + 'nav.administrator': 'Administrátor', + 'nav.myTrips': 'Moje cesty', + + // Přehled (Dashboard) + 'dashboard.title': 'Moje cesty', + 'dashboard.subtitle.loading': 'Načítání cest...', + 'dashboard.subtitle.trips': '{count} cest ({archived} archivováno)', + 'dashboard.subtitle.empty': 'Začněte svou první cestu', + 'dashboard.subtitle.activeOne': '{count} aktivní cesta', + 'dashboard.subtitle.activeMany': '{count} aktivních cest', + 'dashboard.subtitle.archivedSuffix': ' · {count} archivováno', + 'dashboard.newTrip': 'Nová cesta', + 'dashboard.gridView': 'Mřížka', + 'dashboard.listView': 'Seznam', + 'dashboard.currency': 'Měna', + 'dashboard.timezone': 'Časová pásma', + 'dashboard.localTime': 'Místní čas', + 'dashboard.timezoneCustomTitle': 'Vlastní pásmo', + 'dashboard.timezoneCustomLabelPlaceholder': 'Popisek (volitelné)', + 'dashboard.timezoneCustomTzPlaceholder': 'např. America/New_York', + 'dashboard.timezoneCustomAdd': 'Přidat', + 'dashboard.timezoneCustomErrorEmpty': 'Zadejte identifikátor pásma', + 'dashboard.timezoneCustomErrorInvalid': 'Neplatné pásmo. Použijte formát jako např. Europe/Prague', + 'dashboard.timezoneCustomErrorDuplicate': 'Již bylo přidáno', + 'dashboard.emptyTitle': 'Zatím žádné cesty', + 'dashboard.emptyText': 'Vytvořte svou první cestu a začněte plánovat!', + 'dashboard.emptyButton': 'Vytvořit první cestu', + 'dashboard.nextTrip': 'Další cesta', + 'dashboard.shared': 'Sdílené', + 'dashboard.sharedBy': 'Sdílí {name}', + 'dashboard.days': 'Dní', + 'dashboard.places': 'Míst', + 'dashboard.archive': 'Archivovat', + 'dashboard.restore': 'Obnovit', + 'dashboard.archived': 'Archivováno', + 'dashboard.status.ongoing': 'Probíhající', + 'dashboard.status.today': 'Dnes', + 'dashboard.status.tomorrow': 'Zítra', + 'dashboard.status.past': 'Proběhlé', + 'dashboard.status.daysLeft': 'zbývá {count} dní', + 'dashboard.toast.loadError': 'Nepodařilo se načíst cesty', + 'dashboard.toast.created': 'Cesta byla úspěšně vytvořena!', + 'dashboard.toast.createError': 'Nepodařilo se vytvořit cestu', + 'dashboard.toast.updated': 'Cesta byla aktualizována!', + 'dashboard.toast.updateError': 'Nepodařilo se aktualizovat cestu', + 'dashboard.toast.deleted': 'Cesta byla smazána', + 'dashboard.toast.deleteError': 'Nepodařilo se smazat cestu', + 'dashboard.toast.archived': 'Cesta byla archivována', + 'dashboard.toast.archiveError': 'Nepodařilo se archivovat cestu', + 'dashboard.toast.restored': 'Cesta byla obnovena', + 'dashboard.toast.restoreError': 'Nepodařilo se obnovit cestu', + 'dashboard.confirm.delete': 'Smazat cestu „{title}“? Všechna místa a plány budou trvale smazány.', + 'dashboard.editTrip': 'Upravit cestu', + 'dashboard.createTrip': 'Vytvořit novou cestu', + 'dashboard.tripTitle': 'Název', + 'dashboard.tripTitlePlaceholder': 'např. Léto v Japonsku', + 'dashboard.tripDescription': 'Popis', + 'dashboard.tripDescriptionPlaceholder': 'O čem je tato cesta?', + 'dashboard.startDate': 'Datum začátku', + 'dashboard.endDate': 'Datum konce', + 'dashboard.noDateHint': 'Datum nezadáno – výchozí délka nastavena na 7 dní. Toto lze kdykoli změnit.', + 'dashboard.coverImage': 'Úvodní obrázek', + 'dashboard.addCoverImage': 'Vybrat úvodní obrázek (nebo přetáhnout sem)', + 'dashboard.addMembers': 'Spolucestující', + 'dashboard.addMember': 'Přidat člena', + 'dashboard.coverSaved': 'Úvodní obrázek uložen', + 'dashboard.coverUploadError': 'Nahrávání se nezdařilo', + 'dashboard.coverRemoveError': 'Odstranění se nezdařilo', + 'dashboard.titleRequired': 'Název je povinný', + 'dashboard.endDateError': 'Datum konce musí být po datu začátku', + + // Nastavení (Settings) + 'settings.title': 'Nastavení', + 'settings.subtitle': 'Upravte své osobní nastavení', + 'settings.map': 'Mapy', + 'settings.mapTemplate': 'Šablona mapy', + 'settings.mapTemplatePlaceholder.select': 'Vyberte šablonu...', + 'settings.mapDefaultHint': 'Ponechte prázdné pro OpenStreetMap (výchozí)', + 'settings.mapTemplatePlaceholder': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + 'settings.mapHint': 'URL šablony pro mapové dlaždice', + 'settings.latitude': 'Zeměpisná šířka', + 'settings.longitude': 'Zeměpisná délka', + 'settings.saveMap': 'Uložit nastavení mapy', + 'settings.apiKeys': 'API klíče', + 'settings.mapsKey': 'Google Maps API klíč', + 'settings.mapsKeyHint': 'Pro vyhledávání míst. Vyžaduje Places API (New). Získáte na console.cloud.google.com', + 'settings.weatherKey': 'OpenWeatherMap API klíč', + 'settings.weatherKeyHint': 'Pro předpověď počasí. Zdarma na openweathermap.org/api', + 'settings.keyPlaceholder': 'Vložte klíč...', + 'settings.configured': 'Nastaveno', + 'settings.saveKeys': 'Uložit klíče', + 'settings.display': 'Zobrazení', + 'settings.colorMode': 'Barevné schéma', + 'settings.light': 'Světlé', + 'settings.dark': 'Tmavé', + 'settings.auto': 'Automatické', + 'settings.language': 'Jazyk', + 'settings.temperature': 'Jednotky teploty', + 'settings.timeFormat': 'Formát času', + 'settings.routeCalculation': 'Výpočet trasy', + 'settings.blurBookingCodes': 'Skrýt rezervační kódy', + 'settings.notifications': 'Oznámení', + 'settings.notifyTripInvite': 'Pozvánky na cesty', + 'settings.notifyBookingChange': 'Změny rezervací', + 'settings.notifyTripReminder': 'Připomínky cest', + 'settings.notifyVacayInvite': 'Pozvánky k propojení Vacay', + 'settings.notifyPhotosShared': 'Sdílené fotky (Immich)', + 'settings.notifyCollabMessage': 'Zprávy v chatu (Collab)', + 'settings.notifyPackingTagged': 'Seznam balení: přiřazení', + 'settings.notifyWebhook': 'Webhook oznámení', + 'settings.on': 'Zapnuto', + 'settings.off': 'Vypnuto', + 'settings.mcp.title': 'Konfigurace MCP', + 'settings.mcp.endpoint': 'MCP endpoint', + 'settings.mcp.clientConfig': 'Konfigurace klienta', + 'settings.mcp.clientConfigHint': 'Nahraďte API tokenem ze seznamu níže. Cestu k npx může být nutné upravit pro váš systém (např. C:\\PROGRA~1\\nodejs\\npx.cmd ve Windows).', + 'settings.mcp.copy': 'Kopírovat', + 'settings.mcp.copied': 'Zkopírováno!', + 'settings.mcp.apiTokens': 'API tokeny', + 'settings.mcp.createToken': 'Vytvořit nový token', + 'settings.mcp.noTokens': 'Zatím žádné tokeny. Vytvořte jeden pro připojení MCP klientů.', + 'settings.mcp.tokenCreatedAt': 'Vytvořen', + 'settings.mcp.tokenUsedAt': 'Použit', + 'settings.mcp.deleteTokenTitle': 'Smazat token', + 'settings.mcp.deleteTokenMessage': 'Tento token přestane okamžitě fungovat. Všichni MCP klienti, kteří ho používají, ztratí přístup.', + 'settings.mcp.modal.createTitle': 'Vytvořit API token', + 'settings.mcp.modal.tokenName': 'Název tokenu', + 'settings.mcp.modal.tokenNamePlaceholder': 'např. Claude Desktop, Pracovní notebook', + 'settings.mcp.modal.creating': 'Vytváření…', + 'settings.mcp.modal.create': 'Vytvořit token', + 'settings.mcp.modal.createdTitle': 'Token vytvořen', + 'settings.mcp.modal.createdWarning': 'Tento token bude zobrazen pouze jednou. Zkopírujte a uložte ho nyní — nelze ho obnovit.', + 'settings.mcp.modal.done': 'Hotovo', + 'settings.mcp.toast.created': 'Token vytvořen', + 'settings.mcp.toast.createError': 'Nepodařilo se vytvořit token', + 'settings.mcp.toast.deleted': 'Token smazán', + 'settings.mcp.toast.deleteError': 'Nepodařilo se smazat token', + 'settings.account': 'Účet', + 'settings.username': 'Uživatelské jméno', + 'settings.email': 'E-mail', + 'settings.role': 'Role', + 'settings.roleAdmin': 'Administrátor', + 'settings.oidcLinked': 'Propojeno přes', + 'settings.changePassword': 'Změnit heslo', + 'settings.currentPassword': 'Současné heslo', + 'settings.currentPasswordRequired': 'Současné heslo je vyžadováno', + 'settings.newPassword': 'Nové heslo', + 'settings.confirmPassword': 'Potvrdit nové heslo', + 'settings.updatePassword': 'Aktualizovat heslo', + 'settings.passwordRequired': 'Zadejte prosím současné i nové heslo', + 'settings.passwordTooShort': 'Heslo musí mít alespoň 8 znaků', + 'settings.passwordMismatch': 'Hesla se neshodují', + 'settings.passwordWeak': 'Heslo musí obsahovat velké a malé písmeno a číslici', + 'settings.passwordChanged': 'Heslo bylo úspěšně změněno', + 'settings.deleteAccount': 'Smazat účet', + 'settings.deleteAccountTitle': 'Smazat váš účet?', + 'settings.deleteAccountWarning': 'Váš účet a všechny vaše cesty, místa a soubory budou trvale smazány. Tuto akci nelze vrátit.', + 'settings.deleteAccountConfirm': 'Smazat natrvalo', + 'settings.deleteBlockedTitle': 'Účet nelze smazat', + 'settings.deleteBlockedMessage': 'Jste jediným administrátorem. Před smazáním svého účtu předejte roli administrátora jinému uživateli.', + 'settings.roleUser': 'Uživatel', + 'settings.saveProfile': 'Uložit profil', + 'settings.toast.mapSaved': 'Nastavení map uloženo', + 'settings.toast.keysSaved': 'API klíče uloženy', + 'settings.toast.displaySaved': 'Nastavení zobrazení uloženo', + 'settings.toast.profileSaved': 'Profil byl uložen', + 'settings.uploadAvatar': 'Nahrát profilový obrázek', + 'settings.removeAvatar': 'Odebrat profilový obrázek', + 'settings.avatarUploaded': 'Profilový obrázek byl aktualizován', + 'settings.avatarRemoved': 'Profilový obrázek byl odstraněn', + 'settings.avatarError': 'Nahrávání se nezdařilo', + 'settings.mfa.title': 'Dvoufaktorové ověření (2FA)', + 'settings.mfa.description': 'Přidá druhý stupeň zabezpečení při přihlašování e-mailem a heslem. Použijte aplikaci (Google Authenticator, Authy apod.).', + 'settings.mfa.requiredByPolicy': 'Správce vyžaduje dvoufázové ověření. Nejdřív níže nastavte aplikaci autentikátoru.', + 'settings.mfa.backupTitle': 'Záložní kódy', + 'settings.mfa.backupDescription': 'Použijte tyto jednorázové kódy, pokud ztratíte přístup k autentizační aplikaci.', + 'settings.mfa.backupWarning': 'Uložte si je hned. Každý kód lze použít pouze jednou.', + 'settings.mfa.backupCopy': 'Kopírovat kódy', + 'settings.mfa.backupDownload': 'Stáhnout TXT', + 'settings.mfa.backupPrint': 'Tisk / PDF', + 'settings.mfa.backupCopied': 'Záložní kódy zkopírovány', + 'settings.mfa.enabled': '2FA je pro váš účet aktivní.', + 'settings.mfa.disabled': '2FA není aktivní.', + 'settings.mfa.setup': 'Nastavit autentizační aplikaci', + 'settings.mfa.scanQr': 'Naskenujte tento QR kód ve vaší aplikaci nebo zadejte kód ručně.', + 'settings.mfa.secretLabel': 'Tajný klíč (pro ruční zadání)', + 'settings.mfa.codePlaceholder': '6místný kód', + 'settings.mfa.enable': 'Zapnout 2FA', + 'settings.mfa.cancelSetup': 'Zrušit', + 'settings.mfa.disableTitle': 'Vypnout 2FA', + 'settings.mfa.disableHint': 'Zadejte své heslo k účtu a aktuální kód z aplikace.', + 'settings.mfa.disable': 'Vypnout 2FA', + 'settings.mfa.toastEnabled': 'Dvoufaktorové ověření bylo zapnuto', + 'settings.mfa.toastDisabled': 'Dvoufaktorové ověření bylo vypnuto', + 'settings.mfa.demoBlocked': 'Není k dispozici v demo režimu', + 'admin.smtp.title': 'E-mail a oznámení', + 'admin.smtp.hint': 'Konfigurace SMTP pro e-mailová oznámení. Volitelně: Webhook URL pro Discord, Slack apod.', + 'admin.smtp.testButton': 'Odeslat testovací e-mail', + 'admin.smtp.testSuccess': 'Testovací e-mail byl úspěšně odeslán', + 'admin.smtp.testFailed': 'Odeslání testovacího e-mailu se nezdařilo', + 'dayplan.icsTooltip': 'Exportovat kalendář (ICS)', + 'share.linkTitle': 'Veřejný odkaz', + 'share.linkHint': 'Vytvořte odkaz, kterým si může kdokoli prohlédnout tuto cestu bez přihlášení. Pouze pro čtení — úpravy nejsou možné.', + 'share.createLink': 'Vytvořit odkaz', + 'share.deleteLink': 'Smazat odkaz', + 'share.createError': 'Nepodařilo se vytvořit odkaz', + 'common.copy': 'Kopírovat', + 'common.copied': 'Zkopírováno', + 'share.permMap': 'Mapa a plán', + 'share.permBookings': 'Rezervace', + 'share.permPacking': 'Balení', + 'shared.expired': 'Odkaz vypršel nebo je neplatný', + 'shared.expiredHint': 'Tento sdílený odkaz na cestu již není aktivní.', + 'shared.readOnly': 'Sdílené zobrazení – pouze pro čtení', + 'shared.tabPlan': 'Plán', + 'shared.tabBookings': 'Rezervace', + 'shared.tabPacking': 'Balení', + 'shared.tabBudget': 'Rozpočet', + 'shared.tabChat': 'Chat', + 'shared.days': 'dní', + 'shared.places': 'míst', + 'shared.other': 'Ostatní', + 'shared.totalBudget': 'Celkový rozpočet', + 'shared.messages': 'zpráv', + 'shared.sharedVia': 'Sdíleno přes', + 'shared.confirmed': 'Potvrzeno', + 'shared.pending': 'Čeká na potvrzení', + 'share.permBudget': 'Rozpočet', + 'share.permCollab': 'Chat', + + // Přihlášení (Login) + 'login.error': 'Přihlášení se nezdařilo. Zkontrolujte prosím své údaje.', + 'login.tagline': 'Vaše cesty.\nVáš plán.', + 'login.description': 'Plánujte cesty společně s interaktivními mapami, rozpočty a synchronizací v reálném čase.', + 'login.features.maps': 'Interaktivní mapy', + 'login.features.mapsDesc': 'Google Places, trasy a shlukování bodů', + 'login.features.realtime': 'Synchronizace v reálném čase', + 'login.features.realtimeDesc': 'Plánujte společně přes WebSocket', + 'login.features.budget': 'Sledování rozpočtu', + 'login.features.budgetDesc': 'Kategorie, grafy a náklady na osobu', + 'login.features.collab': 'Spolupráce', + 'login.features.collabDesc': 'Více uživatelů se sdílenými cestami', + 'login.features.packing': 'Seznamy věcí', + 'login.features.packingDesc': 'Kategorie, pokrok v balení a návrhy', + 'login.features.bookings': 'Rezervace', + 'login.features.bookingsDesc': 'Lety, hotely, restaurace a další', + 'login.features.files': 'Dokumenty', + 'login.features.filesDesc': 'Nahrávejte a spravujte dokumenty', + 'login.features.routes': 'Chytré trasy', + 'login.features.routesDesc': 'Automatická optimalizace a export do Google Maps', + 'login.selfHosted': 'Self-hosted · Open Source · Vaše data zůstávají u vás', + 'login.title': 'Přihlásit se', + 'login.subtitle': 'Vítejte zpět', + 'login.signingIn': 'Přihlašování…', + 'login.signIn': 'Přihlásit se', + 'login.createAdmin': 'Vytvořit účet administrátora', + 'login.createAdminHint': 'Nastavte první administrátorský účet pro TREK.', + 'login.createAccount': 'Vytvořit účet', + 'login.createAccountHint': 'Zaregistrujte si nový účet.', + 'login.creating': 'Vytváření…', + 'login.noAccount': 'Nemáte účet?', + 'login.hasAccount': 'Již máte účet?', + 'login.register': 'Registrovat se', + 'login.emailPlaceholder': 'vas@email.cz', + 'login.username': 'Uživatelské jméno', + 'login.oidc.registrationDisabled': 'Registrace je zakázána. Kontaktujte svého administrátora.', + 'login.oidc.noEmail': 'Od poskytovatele nebyl přijat žádný e-mail.', + 'login.oidc.tokenFailed': 'Ověření se nezdařilo.', + 'login.oidc.invalidState': 'Neplatná relace. Zkuste to prosím znovu.', + 'login.demoFailed': 'Přihlášení do dema se nezdařilo', + 'login.oidcSignIn': 'Přihlásit se přes {name}', + 'login.oidcOnly': 'Ověřování heslem je zakázáno. Přihlaste se prosím přes SSO poskytovatele.', + 'login.demoHint': 'Vyzkoušejte demo – registrace není nutná', + 'login.mfaTitle': 'Dvoufaktorové ověření', + 'login.mfaSubtitle': 'Zadejte 6místný kód z vaší autentizační aplikace.', + 'login.mfaCodeLabel': 'Ověřovací kód', + 'login.mfaCodeRequired': 'Zadejte kód z aplikace.', + 'login.mfaHint': 'Otevřete Google Authenticator, Authy nebo jinou TOTP aplikaci.', + 'login.mfaBack': '← Zpět k přihlášení', + 'login.mfaVerify': 'Ověřit', + + // Registrace (Register) + 'register.passwordMismatch': 'Hesla se neshodují', + 'register.passwordTooShort': 'Heslo musí mít alespoň 6 znaků', + 'register.failed': 'Registrace se nezdařila', + 'register.getStarted': 'Začínáme', + 'register.subtitle': 'Vytvořte si účet a začněte plánovat svou vysněnou cestu.', + 'register.feature1': 'Neomezené plány cest', + 'register.feature2': 'Zobrazení na interaktivní mapě', + 'register.feature3': 'Správa míst a kategorií', + 'register.feature4': 'Sledování rezervací', + 'register.feature5': 'Vytváření seznamů věcí', + 'register.feature6': 'Ukládání fotek a souborů', + 'register.createAccount': 'Vytvořit účet', + 'register.startPlanning': 'Začít plánovat', + 'register.minChars': 'Min. 6 znaků', + 'register.confirmPassword': 'Potvrdit heslo', + 'register.repeatPassword': 'Heslo znovu', + 'register.registering': 'Registrace...', + 'register.register': 'Registrovat se', + 'register.hasAccount': 'Již máte účet?', + 'register.signIn': 'Přihlásit se', + + // Administrace (Admin) + 'admin.title': 'Administrace', + 'admin.subtitle': 'Správa uživatelů a systémová nastavení', + 'admin.tabs.users': 'Uživatelé', + 'admin.tabs.categories': 'Kategorie', + 'admin.tabs.backup': 'Zálohování', + 'admin.stats.users': 'Uživatelé', + 'admin.stats.trips': 'Cesty', + 'admin.stats.places': 'Místa', + 'admin.stats.photos': 'Fotky', + 'admin.stats.files': 'Soubory', + 'admin.table.user': 'Uživatel', + 'admin.table.email': 'E-mail', + 'admin.table.role': 'Role', + 'admin.table.created': 'Vytvořeno', + 'admin.table.lastLogin': 'Poslední přihlášení', + 'admin.table.actions': 'Akce', + 'admin.you': '(Vy)', + 'admin.editUser': 'Upravit uživatele', + 'admin.newPassword': 'Nové heslo', + 'admin.newPasswordHint': 'Ponechte prázdné pro zachování současného hesla', + 'admin.deleteUser': 'Smazat uživatele „{name}“? Všechny jeho cesty budou trvale smazány.', + 'admin.deleteUserTitle': 'Smazat uživatele', + 'admin.newPasswordPlaceholder': 'Zadejte nové heslo…', + 'admin.toast.loadError': 'Nepodařilo se načíst data administrace', + 'admin.toast.userUpdated': 'Uživatel byl aktualizován', + 'admin.toast.updateError': 'Aktualizace se nezdařila', + 'admin.toast.userDeleted': 'Uživatel byl smazán', + 'admin.toast.deleteError': 'Smazání se nezdařilo', + 'admin.toast.cannotDeleteSelf': 'Nemůžete smazat svůj vlastní účet', + 'admin.toast.userCreated': 'Uživatel byl vytvořen', + 'admin.toast.createError': 'Nepodařilo se vytvořit uživatele', + 'admin.toast.fieldsRequired': 'Uživatelské jméno, e-mail a heslo jsou povinné', + 'admin.createUser': 'Vytvořit uživatele', + 'admin.invite.title': 'Pozvánky', + 'admin.invite.subtitle': 'Vytvářejte jednorázové registrační odkazy', + 'admin.invite.create': 'Vytvořit odkaz', + 'admin.invite.createAndCopy': 'Vytvořit a zkopírovat', + 'admin.invite.empty': 'Zatím nebyly vytvořeny žádné pozvánky', + 'admin.invite.maxUses': 'Max. použití', + 'admin.invite.expiry': 'Vyprší za', + 'admin.invite.uses': 'použito', + 'admin.invite.expiresAt': 'vyprší', + 'admin.invite.createdBy': 'vytvořil', + 'admin.invite.active': 'Aktivní', + 'admin.invite.expired': 'Expirované', + 'admin.invite.usedUp': 'Využito', + 'admin.invite.copied': 'Odkaz byl zkopírován do schránky', + 'admin.invite.copyLink': 'Kopírovat odkaz', + 'admin.invite.deleted': 'Pozvánka smazána', + 'admin.invite.createError': 'Nepodařilo se vytvořit pozvánku', + 'admin.invite.deleteError': 'Nepodařilo se smazat pozvánku', + 'admin.tabs.settings': 'Nastavení', + 'admin.allowRegistration': 'Povolit registraci', + 'admin.allowRegistrationHint': 'Noví uživatelé se mohou sami registrovat', + 'admin.requireMfa': 'Vyžadovat dvoufázové ověření (2FA)', + 'admin.requireMfaHint': 'Uživatelé bez 2FA musí dokončit nastavení v Nastavení před použitím aplikace.', + 'admin.apiKeys': 'API klíče', + 'admin.apiKeysHint': 'Volitelné. Povoluje rozšířená data o místech (fotky, počasí).', + 'admin.mapsKey': 'Google Maps API klíč', + 'admin.mapsKeyHint': 'Povinné pro hledání míst. Získáte na console.cloud.google.com', + 'admin.mapsKeyHintLong': 'Bez API klíče se pro hledání používá OpenStreetMap. S Google klíčem lze načítat fotky, hodnocení a otevírací dobu.', + 'admin.recommended': 'Doporučeno', + 'admin.weatherKey': 'OpenWeatherMap API klíč', + 'admin.weatherKeyHint': 'Pro data o počasí. Zdarma na openweathermap.org', + 'admin.validateKey': 'Testovat', + 'admin.keyValid': 'Připojeno', + 'admin.keyInvalid': 'Neplatný', + 'admin.keySaved': 'API klíče byly uloženy', + 'admin.oidcTitle': 'Jednotné přihlášení (OIDC)', + 'admin.oidcSubtitle': 'Povolit přihlášení přes externí poskytovatele (Google, Apple, Authentik, Keycloak).', + 'admin.oidcDisplayName': 'Zobrazované jméno', + 'admin.oidcIssuer': 'URL vydavatele (Issuer)', + 'admin.oidcIssuerHint': 'OpenID Connect Issuer URL, např. https://accounts.google.com', + 'admin.oidcSaved': 'Konfigurace OIDC uložena', + 'admin.oidcOnlyMode': 'Zakázat ověřování heslem', + 'admin.oidcOnlyModeHint': 'Pokud je zapnuto, je povolen pouze SSO login. Registrace i přihlášení heslem budou zablokovány.', + + // Typy souborů (File Types) + 'admin.fileTypes': 'Povolené typy souborů', + 'admin.fileTypesHint': 'Nastavte, které typy souborů mohou uživatelé nahrávat.', + 'admin.fileTypesFormat': 'Přípony oddělené čárkou (např. jpg,png,pdf,doc). Použijte * pro všechny typy.', + 'admin.fileTypesSaved': 'Nastavení souborů uloženo', + + // Šablony balení (Packing Templates) + 'admin.bagTracking.title': 'Sledování zavazadel', + 'admin.bagTracking.subtitle': 'Povolit váhu a přiřazení k zavazadlům u položek balení', + 'admin.tabs.config': 'Konfigurace', + 'admin.tabs.templates': 'Šablony seznamů', + 'admin.packingTemplates.title': 'Šablony pro balení', + 'admin.packingTemplates.subtitle': 'Vytvářejte opakovaně použitelné seznamy pro své cesty', + 'admin.packingTemplates.create': 'Nová šablona', + 'admin.packingTemplates.namePlaceholder': 'Název šablony (např. Dovolená u moře)', + 'admin.packingTemplates.empty': 'Zatím nejsou vytvořeny žádné šablony', + 'admin.packingTemplates.items': 'položek', + 'admin.packingTemplates.categories': 'kategorií', + 'admin.packingTemplates.itemName': 'Název položky', + 'admin.packingTemplates.itemCategory': 'Kategorie', + 'admin.packingTemplates.categoryName': 'Název kategorie (např. Oblečení)', + 'admin.packingTemplates.addCategory': 'Přidat kategorii', + 'admin.packingTemplates.created': 'Šablona vytvořena', + 'admin.packingTemplates.deleted': 'Šablona smazána', + 'admin.packingTemplates.loadError': 'Nepodařilo se načíst šablony', + 'admin.packingTemplates.createError': 'Nepodařilo se vytvořit šablonu', + 'admin.packingTemplates.deleteError': 'Nepodařilo se smazat šablonu', + 'admin.packingTemplates.saveError': 'Uložení se nezdařilo', + + // Doplňky (Addons) + 'admin.tabs.addons': 'Doplňky', + 'admin.addons.title': 'Doplňky', + 'admin.addons.subtitle': 'Zapněte nebo vypněte funkce a přizpůsobte si TREK.', + 'admin.addons.catalog.memories.name': 'Fotky (Immich)', + 'admin.addons.catalog.memories.description': 'Sdílejte cestovní fotky přes vaši instanci Immich', + 'admin.addons.catalog.packing.name': 'Balení', + 'admin.addons.catalog.packing.description': 'Seznamy věcí pro přípravu na cestu', + 'admin.addons.catalog.budget.name': 'Rozpočet', + 'admin.addons.catalog.budget.description': 'Sledování výdajů a plánování rozpočtu cesty', + 'admin.addons.catalog.documents.name': 'Dokumenty', + 'admin.addons.catalog.documents.description': 'Ukládání a správa cestovních dokladů', + 'admin.addons.catalog.vacay.name': 'Dovolená (Vacay)', + 'admin.addons.catalog.vacay.description': 'Osobní plánovač dovolené s kalendářem', + 'admin.addons.catalog.atlas.name': 'Atlas', + 'admin.addons.catalog.atlas.description': 'Mapa světa s navštívenými zeměmi a statistikami', + 'admin.addons.catalog.collab.name': 'Spolupráce', + 'admin.addons.catalog.collab.description': 'Poznámky v reálném čase, hlasování a chat pro plánování', + 'admin.addons.enabled': 'Povoleno', + 'admin.addons.disabled': 'Zakázáno', + 'admin.addons.type.trip': 'Cesta', + 'admin.addons.type.global': 'Globální', + 'admin.addons.type.integration': 'Integrace', + 'admin.addons.tripHint': 'Dostupné jako karta v rámci každé cesty', + 'admin.addons.globalHint': 'Dostupné jako samostatná sekce v hlavní navigaci', + 'admin.addons.integrationHint': 'Backendové služby a API integrace bez vlastní stránky', + 'admin.addons.toast.updated': 'Doplněk byl aktualizován', + 'admin.addons.toast.error': 'Aktualizace doplňku se nezdařila', + 'admin.addons.noAddons': 'Žádné doplňky nejsou k dispozici', + 'admin.addons.catalog.memories.name': 'Fotky (Immich)', + 'admin.addons.catalog.memories.description': 'Sdílejte cestovní fotky přes vaši instanci Immich', + 'admin.addons.catalog.mcp.name': 'MCP', + 'admin.addons.catalog.mcp.description': 'Model Context Protocol pro integraci AI asistentů', + 'admin.addons.subtitleBefore': 'Zapněte nebo vypněte funkce a přizpůsobte si ', + 'admin.addons.subtitleAfter': '.', + + 'admin.tabs.audit': 'Auditní protokol', + + 'admin.audit.subtitle': 'Bezpečnostní a administrátorské události (zálohy, uživatelé, 2FA, nastavení).', + 'admin.audit.empty': 'Zatím žádné záznamy auditu.', + 'admin.audit.refresh': 'Obnovit', + 'admin.audit.loadMore': 'Načíst další', + 'admin.audit.showing': '{count} načteno · {total} celkem', + 'admin.audit.col.time': 'Čas', + 'admin.audit.col.user': 'Uživatel', + 'admin.audit.col.action': 'Akce', + 'admin.audit.col.resource': 'Zdroj', + 'admin.audit.col.ip': 'IP', + 'admin.audit.col.details': 'Detaily', + + // MCP Tokens + 'admin.tabs.mcpTokens': 'MCP tokeny', + 'admin.mcpTokens.title': 'MCP tokeny', + 'admin.mcpTokens.subtitle': 'Správa API tokenů všech uživatelů', + 'admin.mcpTokens.owner': 'Vlastník', + 'admin.mcpTokens.tokenName': 'Název tokenu', + 'admin.mcpTokens.created': 'Vytvořen', + 'admin.mcpTokens.lastUsed': 'Naposledy použit', + 'admin.mcpTokens.never': 'Nikdy', + 'admin.mcpTokens.empty': 'Zatím nebyly vytvořeny žádné MCP tokeny', + 'admin.mcpTokens.deleteTitle': 'Smazat token', + 'admin.mcpTokens.deleteMessage': 'Tento token bude okamžitě zneplatněn. Uživatel ztratí MCP přístup přes tento token.', + 'admin.mcpTokens.deleteSuccess': 'Token smazán', + 'admin.mcpTokens.deleteError': 'Nepodařilo se smazat token', + 'admin.mcpTokens.loadError': 'Nepodařilo se načíst tokeny', + + // GitHub + 'admin.tabs.github': 'GitHub', + 'admin.github.title': 'Historie verzí', + 'admin.github.subtitle': 'Nejnovější aktualizace z {repo}', + 'admin.github.latest': 'Nejnovější', + 'admin.github.prerelease': 'Předběžná verze', + 'admin.github.showDetails': 'Zobrazit podrobnosti', + 'admin.github.hideDetails': 'Skrýt podrobnosti', + 'admin.github.loadMore': 'Načíst další', + 'admin.github.loading': 'Načítání...', + 'admin.github.error': 'Nepodařilo se načíst verze', + 'admin.github.by': 'od', + 'admin.github.support': 'Pomáhá udržovat vývoj TREK', + + // Počasí (Weather) + 'admin.weather.title': 'Data o počasí', + 'admin.weather.badge': 'Od 24. března 2026', + 'admin.weather.description': 'TREK používá Open-Meteo jako zdroj dat. Je to bezplatná open-source služba – není vyžadován API klíč.', + 'admin.weather.forecast': 'Předpověď na 16 dní', + 'admin.weather.forecastDesc': 'Dříve 5 dní (OpenWeatherMap)', + 'admin.weather.climate': 'Historická klimatická data', + 'admin.weather.climateDesc': 'Průměry za posledních 85 let pro dny mimo 16denní předpověď', + 'admin.weather.requests': '10 000 požadavků denně', + 'admin.weather.requestsDesc': 'Zdarma, bez nutnosti klíče', + 'admin.weather.locationHint': 'Počasí se určuje podle prvního místa se souřadnicemi v daném dni.', + + // Aktualizace (Updates) + 'admin.update.available': 'Dostupná aktualizace', + 'admin.update.text': 'TREK {version} je k dispozici. Aktuálně používáte verzi {current}.', + 'admin.update.button': 'Zobrazit na GitHubu', + 'admin.update.install': 'Instalovat aktualizaci', + 'admin.update.confirmTitle': 'Instalovat aktualizaci?', + 'admin.update.confirmText': 'TREK bude aktualizován z verze {current} na {version}. Server se poté automaticky restartuje.', + 'admin.update.dataInfo': 'Všechna vaše data (cesty, uživatelé, API klíče, soubory) budou zachována.', + 'admin.update.warning': 'Aplikace bude během restartu krátce nedostupná.', + 'admin.update.confirm': 'Aktualizovat nyní', + 'admin.update.installing': 'Aktualizace probíhá…', + 'admin.update.success': 'Aktualizace byla nainstalována! Server se restartuje…', + 'admin.update.failed': 'Aktualizace se nezdařila', + 'admin.update.backupHint': 'Před aktualizací doporučujeme vytvořit zálohu.', + 'admin.update.backupLink': 'Přejít na zálohování', + 'admin.update.howTo': 'Jak aktualizovat', + 'admin.update.dockerText': 'Váš TREK běží v Dockeru. Pro aktualizaci na verzi {version} spusťte na svém serveru tyto příkazy:', + 'admin.update.reloadHint': 'Prosím obnovte stránku za několik sekund.', + + // Vacay doplněk + 'vacay.subtitle': 'Plánování a správa dovolené', + 'vacay.settings': 'Nastavení', + 'vacay.year': 'Rok', + 'vacay.addYear': 'Přidat rok', + 'vacay.removeYear': 'Odebrat rok', + 'vacay.removeYearConfirm': 'Odebrat rok {year}?', + 'vacay.removeYearHint': 'Všechny záznamy o dovolené a firemní svátky pro tento rok budou trvale smazány.', + 'vacay.remove': 'Odebrat', + 'vacay.persons': 'Osoby', + 'vacay.noPersons': 'Žádné osoby nebyly přidány', + 'vacay.addPerson': 'Přidat osobu', + 'vacay.editPerson': 'Upravit osobu', + 'vacay.removePerson': 'Odebrat osobu', + 'vacay.removePersonConfirm': 'Odebrat osobu {name}?', + 'vacay.removePersonHint': 'Všechny záznamy dovolené pro tuto osobu budou trvale smazány.', + 'vacay.personName': 'Jméno', + 'vacay.personNamePlaceholder': 'Zadejte jméno', + 'vacay.color': 'Barva', + 'vacay.add': 'Přidat', + 'vacay.legend': 'Legenda', + 'vacay.publicHoliday': 'Státní svátek', + 'vacay.companyHoliday': 'Firemní volno', + 'vacay.weekend': 'Víkend', + 'vacay.modeVacation': 'Dovolená', + 'vacay.modeCompany': 'Firemní volno', + 'vacay.entitlement': 'Nárok', + 'vacay.entitlementDays': 'Dní', + 'vacay.used': 'Vyčerpáno', + 'vacay.remaining': 'Zbývá', + 'vacay.carriedOver': 'z roku {year}', + 'vacay.blockWeekends': 'Blokovat víkendy', + 'vacay.blockWeekendsHint': 'Zamezit zadávání dovolené na víkendové dny', + 'vacay.mon': 'Po', + 'vacay.tue': 'Út', + 'vacay.wed': 'St', + 'vacay.thu': 'Čt', + 'vacay.fri': 'Pá', + 'vacay.sat': 'So', + 'vacay.sun': 'Ne', + 'vacay.weekendDays': 'Víkendové dny', + 'vacay.publicHolidays': 'Státní svátky', + 'vacay.publicHolidaysHint': 'Zobrazit státní svátky v kalendáři', + 'vacay.selectCountry': 'Vyberte zemi', + 'vacay.selectRegion': 'Vyberte region (volitelné)', + 'vacay.addCalendar': 'Přidat kalendář', + 'vacay.calendarLabel': 'Popisek (volitelné)', + 'vacay.calendarColor': 'Barva', + 'vacay.noCalendars': 'Zatím nebyly přidány žádné svátkové kalendáře', + 'vacay.companyHolidays': 'Firemní volno', + 'vacay.companyHolidaysHint': 'Povolit označování dnů celofiremního volna', + 'vacay.companyHolidaysNoDeduct': 'Firemní volno se nezapočítává do nároku na dovolenou.', + 'vacay.carryOver': 'Převod dovolené', + 'vacay.carryOverHint': 'Automaticky převádět zbývající dny do dalšího roku', + 'vacay.sharing': 'Sdílení', + 'vacay.sharingHint': 'Sdílejte svůj plán dovolené s ostatními uživateli TREK', + 'vacay.owner': 'Vlastník', + 'vacay.shareEmailPlaceholder': 'E-mail uživatele TREK', + 'vacay.shareSuccess': 'Plán byl úspěšně sdílen', + 'vacay.shareError': 'Nepodařilo se sdílet plán', + 'vacay.dissolve': 'Zrušit propojení', + 'vacay.dissolveHint': 'Znovu oddělit kalendáře. Vaše záznamy zůstanou zachovány.', + 'vacay.dissolveAction': 'Oddělit', + 'vacay.dissolved': 'Kalendáře byly odděleny', + 'vacay.fusedWith': 'Propojeno s', + 'vacay.you': 'vy', + 'vacay.noData': 'Žádná data', + 'vacay.changeColor': 'Změnit barvu', + 'vacay.inviteUser': 'Pozvat uživatele', + 'vacay.inviteHint': 'Pozvěte jiného uživatele TREK ke sdílení společného kalendáře dovolených.', + 'vacay.selectUser': 'Vyberte uživatele', + 'vacay.sendInvite': 'Odeslat pozvánku', + 'vacay.inviteSent': 'Pozvánka odeslána', + 'vacay.inviteError': 'Nepodařilo se odeslat pozvánku', + 'vacay.pending': 'čeká na vyřízení', + 'vacay.noUsersAvailable': 'Žádní uživatelé nejsou k dispozici', + 'vacay.accept': 'Přijmout', + 'vacay.decline': 'Odmítnout', + 'vacay.acceptFusion': 'Přijmout a propojit', + 'vacay.inviteTitle': 'Žádost o propojení', + 'vacay.inviteWantsToFuse': 'vás zve ke sdílení kalendáře dovolených.', + 'vacay.fuseInfo1': 'Oba uvidíte všechny záznamy v jednom sdíleném kalendáři.', + 'vacay.fuseInfo2': 'Obě strany mohou vytvářet a upravovat záznamy tomu druhému.', + 'vacay.fuseInfo3': 'Obě strany mohou měnit nároky na dovolenou.', + 'vacay.fuseInfo4': 'Nastavení (svátky, firemní volno) jsou sdílená.', + 'vacay.fuseInfo5': 'Propojení lze kdykoli zrušit bez ztráty dat.', + + // Atlas doplněk + 'atlas.subtitle': 'Vaše stopa ve světě', + 'atlas.countries': 'Země', + 'atlas.trips': 'Cesty', + 'atlas.places': 'Místa', + 'atlas.unmark': 'Odebrat', + 'atlas.confirmMark': 'Označit tuto zemi jako navštívenou?', + 'atlas.confirmUnmark': 'Odebrat tuto zemi ze seznamu navštívených?', + 'atlas.markVisited': 'Označit jako navštívené', + 'atlas.markVisitedHint': 'Přidat tuto zemi do seznamu navštívených', + 'atlas.addToBucket': 'Přidat do seznamu přání (Bucket list)', + 'atlas.addPoi': 'Přidat místo', + 'atlas.bucketNamePlaceholder': 'Název (země, město, místo...)', + 'atlas.month': 'Měsíc', + 'atlas.addToBucketHint': 'Uložit jako místo, které chcete navštívit', + 'atlas.bucketWhen': 'Kdy plánujete návštěvu?', + 'atlas.statsTab': 'Statistiky', + 'atlas.bucketTab': 'Bucket List', + 'atlas.addBucket': 'Přidat na Bucket List', + 'atlas.bucketNamePlaceholder': 'Místo nebo destinace...', + 'atlas.bucketNotesPlaceholder': 'Poznámky (volitelné)', + 'atlas.bucketEmpty': 'Váš seznam přání je prázdný', + 'atlas.bucketEmptyHint': 'Přidejte místa, která sníte navštívit', + 'atlas.days': 'Dní', + 'atlas.visitedCountries': 'Navštívené země', + 'atlas.cities': 'Města', + 'atlas.noData': 'Zatím žádná cestovatelská data', + 'atlas.noDataHint': 'Vytvořte cestu a přidejte místa, abyste viděli svou mapu světa', + 'atlas.lastTrip': 'Poslední cesta', + 'atlas.nextTrip': 'Další cesta', + 'atlas.daysLeft': 'dní zbývá', + 'atlas.streak': 'Série', + 'atlas.year': 'rok', + 'atlas.years': 'roky/let', + 'atlas.yearInRow': 'rok v řadě', + 'atlas.yearsInRow': 'let v řadě', + 'atlas.tripIn': 'cesta v roce', + 'atlas.tripsIn': 'cest v roce', + 'atlas.since': 'od', + 'atlas.europe': 'Evropa', + 'atlas.asia': 'Asie', + 'atlas.northAmerica': 'S. Amerika', + 'atlas.southAmerica': 'J. Amerika', + 'atlas.africa': 'Afrika', + 'atlas.oceania': 'Oceánie', + 'atlas.other': 'Ostatní', + 'atlas.firstVisit': 'První cesta', + 'atlas.lastVisitLabel': 'Poslední cesta', + 'atlas.tripSingular': 'Cesta', + 'atlas.tripPlural': 'Cesty', + 'atlas.placeVisited': 'Navštívené místo', + 'atlas.placesVisited': 'Navštívená místa', + + // Plánovač cesty (Trip Planner) + 'trip.tabs.plan': 'Plán', + 'trip.tabs.reservations': 'Rezervace', + 'trip.tabs.reservationsShort': 'Rez.', + 'trip.tabs.packing': 'Seznam věcí', + 'trip.tabs.packingShort': 'Balení', + 'trip.tabs.budget': 'Rozpočet', + 'trip.tabs.files': 'Soubory', + 'trip.loading': 'Načítání cesty...', + 'trip.mobilePlan': 'Plán', + 'trip.mobilePlaces': 'Místa', + 'trip.toast.placeUpdated': 'Místo bylo aktualizováno', + 'trip.toast.placeAdded': 'Místo bylo přidáno', + 'trip.toast.placeDeleted': 'Místo bylo smazáno', + 'trip.toast.selectDay': 'Prosím nejdříve vyberte den', + 'trip.toast.assignedToDay': 'Místo bylo přiřazeno ke dni', + 'trip.toast.reorderError': 'Nepodařilo se změnit pořadí', + 'trip.toast.reservationUpdated': 'Rezervace aktualizována', + 'trip.toast.reservationAdded': 'Rezervace přidána', + 'trip.toast.deleted': 'Smazáno', + 'trip.confirm.deletePlace': 'Opravdu chcete toto místo smazat?', + + // Denní plán (Day Plan) + 'dayplan.emptyDay': 'Na tento den nejsou naplánována žádná místa', + 'dayplan.addNote': 'Přidat poznámku', + 'dayplan.editNote': 'Upravit poznámku', + 'dayplan.noteAdd': 'Přidat poznámku', + 'dayplan.noteEdit': 'Upravit poznámku', + 'dayplan.noteTitle': 'Poznámka', + 'dayplan.noteSubtitle': 'Poznámka ke dni', + 'dayplan.totalCost': 'Celkové náklady', + 'dayplan.days': 'Dny', + 'dayplan.dayN': 'Den {n}', + 'dayplan.calculating': 'Počítání...', + 'dayplan.route': 'Trasa', + 'dayplan.optimize': 'Optimalizovat', + 'dayplan.optimized': 'Trasa optimalizována', + 'dayplan.routeError': 'Nepodařilo se vypočítat trasu', + 'dayplan.toast.needTwoPlaces': 'Pro optimalizaci trasy jsou potřeba alespoň dvě místa', + 'dayplan.toast.routeOptimized': 'Trasa byla optimalizována', + 'dayplan.toast.noGeoPlaces': 'Nebyla nalezena žádná místa se souřadnicemi pro výpočet trasy', + 'dayplan.confirmed': 'Potvrzeno', + 'dayplan.pendingRes': 'Čeká na potvrzení', + 'dayplan.pdf': 'PDF', + 'dayplan.pdfTooltip': 'Exportovat denní plán do PDF', + 'dayplan.pdfError': 'Export do PDF se nezdařil', + 'dayplan.cannotReorderTransport': 'Rezervace s pevným časem nelze přeuspořádat', + 'dayplan.confirmRemoveTimeTitle': 'Odebrat čas?', + 'dayplan.confirmRemoveTimeBody': 'Toto místo má pevný čas ({time}). Přesunutím se čas odebere a povolí se volné řazení.', + 'dayplan.confirmRemoveTimeAction': 'Odebrat čas a přesunout', + 'dayplan.cannotDropOnTimed': 'Položky nelze umístit mezi záznamy s pevným časem', + 'dayplan.cannotBreakChronology': 'Toto by porušilo chronologické pořadí naplánovaných položek a rezervací', + + // Boční panel míst (Places Sidebar) + 'places.addPlace': 'Přidat místo/aktivitu', + 'places.importGpx': 'Importovat GPX', + 'places.gpxImported': '{count} míst importováno z GPX', + 'places.urlResolved': 'Místo importováno z URL', + 'places.gpxError': 'Import GPX se nezdařil', + 'places.assignToDay': 'Přidat do kterého dne?', + 'places.all': 'Vše', + 'places.unplanned': 'Nezařazené', + 'places.search': 'Hledat místa...', + 'places.allCategories': 'Všechny kategorie', + 'places.categoriesSelected': 'kategorií', + 'places.clearFilter': 'Vymazat filtr', + 'places.count': '{count} míst', + 'places.countSingular': '1 místo', + 'places.allPlanned': 'Všechna místa jsou naplánována', + 'places.noneFound': 'Žádná místa nebyla nalezena', + 'places.editPlace': 'Upravit místo', + 'places.formName': 'Název', + 'places.formNamePlaceholder': 'např. Eiffelova věž', + 'places.formDescription': 'Popis', + 'places.formDescriptionPlaceholder': 'Krátký popis...', + 'places.formAddress': 'Adresa', + 'places.formAddressPlaceholder': 'Ulice, město, země', + 'places.formLat': 'Zeměpisná šířka', + 'places.formLng': 'Zeměpisná délka', + 'places.formCategory': 'Kategorie', + 'places.noCategory': 'Bez kategorie', + 'places.categoryNamePlaceholder': 'Název kategorie', + 'places.formTime': 'Čas', + 'places.startTime': 'Od', + 'places.endTime': 'Do', + 'places.endTimeBeforeStart': 'Čas konce je před časem začátku', + 'places.timeCollision': 'Časový překryv s:', + 'places.formWebsite': 'Webové stránky', + 'places.formNotesPlaceholder': 'Osobní poznámky...', + 'places.formReservation': 'Rezervace', + 'places.reservationNotesPlaceholder': 'Poznámky k rezervaci, potvrzovací kód...', + 'places.mapsSearchPlaceholder': 'Hledat místa...', + 'places.mapsSearchError': 'Hledání místa se nezdařilo.', + 'places.osmHint': 'Používáte hledání přes OpenStreetMap (bez fotek a hodnocení). Pro plné detaily přidejte Google API klíč v nastavení.', + 'places.osmActive': 'Hledání přes OpenStreetMap.', + 'places.categoryCreateError': 'Nepodařilo se vytvořit kategorii', + 'places.nameRequired': 'Prosím zadejte název', + 'places.saveError': 'Uložení se nezdařilo', + + // Inspektor míst (Place Inspector) + 'inspector.opened': 'Otevřeno', + 'inspector.closed': 'Zavřeno', + 'inspector.openingHours': 'Otevírací doba', + 'inspector.showHours': 'Zobrazit otevírací dobu', + 'inspector.files': 'Soubory', + 'inspector.filesCount': '{count} souborů', + 'inspector.removeFromDay': 'Odebrat ze dne', + 'inspector.addToDay': 'Přidat ke dni', + 'inspector.confirmedRes': 'Potvrzená rezervace', + 'inspector.pendingRes': 'Čekající rezervace', + 'inspector.google': 'Otevřít v Google Mapách', + 'inspector.website': 'Otevřít webové stránky', + 'inspector.addRes': 'Rezervace', + 'inspector.editRes': 'Upravit rezervaci', + 'inspector.participants': 'Účastníci', + + // Rezervace (Reservations) + 'reservations.title': 'Rezervace', + 'reservations.empty': 'Zatím žádné rezervace', + 'reservations.emptyHint': 'Přidejte rezervace letů, hotelů a dalších', + 'reservations.add': 'Přidat rezervaci', + 'reservations.addManual': 'Ruční rezervace', + 'reservations.placeHint': 'Tip: Rezervace je nejlepší vytvářet přímo z místa – propojí se tak s denním plánem.', + 'reservations.confirmed': 'Potvrzeno', + 'reservations.pending': 'Čeká na potvrzení', + 'reservations.summary': '{confirmed} potvrzených, {pending} čekajících', + 'reservations.fromPlan': 'Z plánu', + 'reservations.showFiles': 'Zobrazit soubory', + 'reservations.editTitle': 'Upravit rezervaci', + 'reservations.status': 'Stav', + 'reservations.datetime': 'Datum a čas', + 'reservations.startTime': 'Čas začátku', + 'reservations.endTime': 'Čas konce', + 'reservations.date': 'Datum', + 'reservations.time': 'Čas', + 'reservations.timeAlt': 'Čas (alternativní, např. 19:30)', + 'reservations.notes': 'Poznámky', + 'reservations.notesPlaceholder': 'Další poznámky...', + 'reservations.meta.airline': 'Letecká společnost', + 'reservations.meta.flightNumber': 'Číslo letu', + 'reservations.meta.from': 'Z', + 'reservations.meta.to': 'Do', + 'reservations.meta.trainNumber': 'Číslo vlaku', + 'reservations.meta.platform': 'Nástupiště', + 'reservations.meta.seat': 'Sedadlo', + 'reservations.meta.checkIn': 'Check-in', + 'reservations.meta.checkOut': 'Check-out', + 'reservations.meta.linkAccommodation': 'Ubytování', + 'reservations.meta.pickAccommodation': 'Propojit s ubytováním', + 'reservations.meta.noAccommodation': 'Nic', + 'reservations.meta.hotelPlace': 'Ubytování', + 'reservations.meta.pickHotel': 'Vybrat ubytování', + 'reservations.meta.fromDay': 'Od dne', + 'reservations.meta.toDay': 'Do dne', + 'reservations.meta.selectDay': 'Vyberte den', + 'reservations.type.flight': 'Let', + 'reservations.type.hotel': 'Ubytování', + 'reservations.type.restaurant': 'Restaurace', + 'reservations.type.train': 'Vlak', + 'reservations.type.car': 'Pronájem auta', + 'reservations.type.cruise': 'Plavba', + 'reservations.type.event': 'Událost', + 'reservations.type.tour': 'Prohlídka', + 'reservations.type.other': 'Jiné', + 'reservations.confirm.delete': 'Opravdu chcete smazat rezervaci „{name}”?', + 'reservations.confirm.deleteTitle': 'Smazat rezervaci?', + 'reservations.confirm.deleteBody': '„{name}” bude trvale smazána.', + 'reservations.toast.updated': 'Rezervace aktualizována', + 'reservations.toast.removed': 'Rezervace smazána', + 'reservations.toast.fileUploaded': 'Soubor byl nahrán', + 'reservations.toast.uploadError': 'Nahrávání se nezdařilo', + 'reservations.newTitle': 'Nová rezervace', + 'reservations.bookingType': 'Typ rezervace', + 'reservations.titleLabel': 'Název', + 'reservations.titlePlaceholder': 'např. Let LH123, Hotel Adlon...', + 'reservations.locationAddress': 'Místo / Adresa', + 'reservations.locationPlaceholder': 'Adresa, letiště, hotel...', + 'reservations.confirmationCode': 'Rezervační kód', + 'reservations.confirmationPlaceholder': 'např. ABC12345', + 'reservations.day': 'Den', + 'reservations.noDay': 'Žádný den', + 'reservations.place': 'Místo', + 'reservations.noPlace': 'Žádné místo', + 'reservations.pendingSave': 'bude uloženo…', + 'reservations.uploading': 'Nahrávání...', + 'reservations.attachFile': 'Přiložit soubor', + 'reservations.linkExisting': 'Propojit stávající soubor', + 'reservations.toast.saveError': 'Uložení se nezdařilo', + 'reservations.toast.updateError': 'Aktualizace se nezdařila', + 'reservations.toast.deleteError': 'Smazání se nezdařilo', + 'reservations.confirm.remove': 'Odstranit rezervaci pro „{name}”?', + 'reservations.linkAssignment': 'Propojit s přiřazením dne', + 'reservations.pickAssignment': 'Vyberte přiřazení z vašeho plánu...', + 'reservations.noAssignment': 'Bez propojení (samostatné)', + + // Rozpočet (Budget) + 'budget.title': 'Rozpočet', + 'budget.emptyTitle': 'Zatím nebyl vytvořen žádný rozpočet', + 'budget.emptyText': 'Vytvořte kategorie a položky pro plánování cestovního rozpočtu', + 'budget.emptyPlaceholder': 'Zadejte název kategorie...', + 'budget.createCategory': 'Vytvořit kategorii', + 'budget.category': 'Kategorie', + 'budget.categoryName': 'Název kategorie', + 'budget.table.name': 'Název', + 'budget.table.total': 'Celkem', + 'budget.table.persons': 'Osoby', + 'budget.table.days': 'Dní', + 'budget.table.perPerson': 'Na osobu', + 'budget.table.perDay': 'Za den', + 'budget.table.perPersonDay': 'Os. / den', + 'budget.table.note': 'Poznámka', + 'budget.newEntry': 'Nová položka', + 'budget.defaultEntry': 'Nová položka', + 'budget.defaultCategory': 'Nová kategorie', + 'budget.total': 'Celkem', + 'budget.totalBudget': 'Celkový rozpočet', + 'budget.byCategory': 'Podle kategorie', + 'budget.editTooltip': 'Klikněte pro úpravu', + 'budget.confirm.deleteCategory': 'Opravdu chcete smazat kategorii „{name}” s {count} položkami?', + 'budget.deleteCategory': 'Smazat kategorii', + 'budget.perPerson': 'Na osobu', + 'budget.paid': 'Zaplaceno', + 'budget.open': 'Nezaplaceno', + 'budget.noMembers': 'Žádní členové nebyli přiřazeni', + 'budget.settlement': 'Vyúčtování', + 'budget.settlementInfo': 'Klikněte na avatar člena u rozpočtové položky pro zelené označení – to znamená, že zaplatil. Vyúčtování pak ukazuje, kdo komu a kolik dluží.', + 'budget.netBalances': 'Čisté zůstatky', + + // Soubory (Files) + 'files.title': 'Soubory', + 'files.count': '{count} souborů', + 'files.countSingular': '1 soubor', + 'files.uploaded': '{count} nahráno', + 'files.uploadError': 'Nahrávání se nezdařilo', + 'files.dropzone': 'Přetáhněte soubory sem', + 'files.dropzoneHint': 'nebo klikněte pro výběr', + 'files.allowedTypes': 'Obrázky, PDF, DOC, DOCX, XLS, XLSX, TXT, CSV · Max 50 MB', + 'files.uploading': 'Nahrávání...', + 'files.filterAll': 'Vše', + 'files.filterPdf': 'PDF', + 'files.filterImages': 'Obrázky', + 'files.filterDocs': 'Dokumenty', + 'files.filterCollab': 'Poznámky spolupráce', + 'files.sourceCollab': 'Z poznámek spolupráce', + 'files.empty': 'Zatím žádné soubory', + 'files.emptyHint': 'Nahrajte soubory k vaší cestě', + 'files.openTab': 'Otevřít v nové kartě', + 'files.confirm.delete': 'Opravdu chcete smazat tento soubor?', + 'files.toast.deleted': 'Soubor byl smazán', + 'files.toast.deleteError': 'Nepodařilo se smazat soubor', + 'files.sourcePlan': 'Denní plán', + 'files.sourceBooking': 'Rezervace', + 'files.attach': 'Přiložit', + 'files.pasteHint': 'Můžete také vložit obrázek ze schránky (Ctrl+V)', + 'files.trash': 'Koš', + 'files.trashEmpty': 'Koš je prázdný', + 'files.emptyTrash': 'Vysypat koš', + 'files.restore': 'Obnovit', + 'files.star': 'Označit hvězdičkou', + 'files.unstar': 'Odebrat hvězdičku', + 'files.assign': 'Přiřadit', + 'files.assignTitle': 'Přiřadit soubor', + 'files.assignPlace': 'Místo', + 'files.assignBooking': 'Rezervace', + 'files.unassigned': 'Nepřiřazeno', + 'files.unlink': 'Zrušit propojení', + 'files.toast.trashed': 'Přesunuto do koše', + 'files.toast.restored': 'Soubor byl obnoven', + 'files.toast.trashEmptied': 'Koš byl vysypán', + 'files.toast.assigned': 'Soubor byl přiřazen', + 'files.toast.assignError': 'Přiřazení se nezdařilo', + 'files.toast.restoreError': 'Obnovení se nezdařilo', + 'files.confirm.permanentDelete': 'Trvale smazat tento soubor? Tuto akci nelze vrátit.', + 'files.confirm.emptyTrash': 'Trvale smazat všechny soubory v koši? Tuto akci nelze vrátit.', + 'files.noteLabel': 'Poznámka', + 'files.notePlaceholder': 'Přidat poznámku...', + + // Balení (Packing) + 'packing.title': 'Seznam věcí', + 'packing.empty': 'Seznam věcí je prázdný', + 'packing.import': 'Importovat', + 'packing.importTitle': 'Importovat seznam', + 'packing.importHint': 'Jedna položka na řádek. Formát: Kategorie, Název, Váha v g (volitelné), Zavazadlo (volitelné), checked/unchecked (volitelné)', + 'packing.importPlaceholder': 'Hygiena, Zubní kartáček\nOblečení, Trička, 200\nDokumenty, Pas, , Příruční zavazadlo\nElektronika, Nabíječka, 50, Kufr, checked', + 'packing.importCsv': 'Načíst CSV/TXT', + 'packing.importAction': 'Importovat {count}', + 'packing.importSuccess': '{count} položek importováno', + 'packing.importError': 'Import se nezdařil', + 'packing.importEmpty': 'Žádné položky k importu', + 'packing.progress': '{packed} z {total} zabaleno ({percent} %)', + 'packing.clearChecked': 'Odstranit {count} hotových', + 'packing.clearCheckedShort': 'Odstranit {count}', + 'packing.suggestions': 'Návrhy', + 'packing.suggestionsTitle': 'Přidat návrhy', + 'packing.allSuggested': 'Všechny návrhy byly přidány', + 'packing.allPacked': 'Vše je zabaleno!', + 'packing.addPlaceholder': 'Přidat novou položku...', + 'packing.categoryPlaceholder': 'Kategorie...', + 'packing.filterAll': 'Vše', + 'packing.filterOpen': 'K zabalení', + 'packing.filterDone': 'Hotovo', + 'packing.emptyTitle': 'Seznam věcí je prázdný', + 'packing.emptyHint': 'Přidejte položky nebo použijte návrhy', + 'packing.emptyFiltered': 'Žádné položky neodpovídají filtru', + 'packing.menuRename': 'Přejmenovat', + 'packing.menuCheckAll': 'Označit vše', + 'packing.menuUncheckAll': 'Odznačit vše', + 'packing.menuDeleteCat': 'Smazat kategorii', + 'packing.assignUser': 'Přiřadit uživateli', + 'packing.noMembers': 'Žádní členové cesty', + 'packing.addItem': 'Přidat položku', + 'packing.addItemPlaceholder': 'Název položky...', + 'packing.addCategory': 'Přidat kategorii', + 'packing.newCategoryPlaceholder': 'Název kategorie (např. Oblečení)', + 'packing.applyTemplate': 'Použít šablonu', + 'packing.template': 'Šablona', + 'packing.templateApplied': '{count} položek přidáno ze šablony', + 'packing.templateError': 'Šablonu se nepodařilo použít', + 'packing.bags': 'Zavazadla', + 'packing.noBag': 'Nepřiřazeno', + 'packing.totalWeight': 'Celková váha', + 'packing.bagName': 'Název zavazadla...', + 'packing.addBag': 'Přidat zavazadlo', + 'packing.changeCategory': 'Změnit kategorii', + 'packing.confirm.clearChecked': 'Opravdu chcete odstranit {count} zabalených položek?', + 'packing.confirm.deleteCat': 'Opravdu chcete smazat kategorii „{name}" s {count} položkami?', + 'packing.defaultCategory': 'Ostatní', + 'packing.toast.saveError': 'Uložení se nezdařilo', + 'packing.toast.deleteError': 'Smazání se nezdařilo', + 'packing.toast.renameError': 'Přejmenování se nezdařilo', + 'packing.toast.addError': 'Přidání se nezdařilo', + + // Návrhy balení (Packing suggestions) + 'packing.suggestions.items': [ + { name: 'Pas', category: 'Dokumenty' }, + { name: 'Občanský průkaz', category: 'Dokumenty' }, + { name: 'Cestovní pojištění', category: 'Dokumenty' }, + { name: 'Letenky', category: 'Dokumenty' }, + { name: 'Platební karta', category: 'Finance' }, + { name: 'Hotovost', category: 'Finance' }, + { name: 'Víza', category: 'Dokumenty' }, + { name: 'Trička', category: 'Oblečení' }, + { name: 'Kalhoty', category: 'Oblečení' }, + { name: 'Spodní prádlo', category: 'Oblečení' }, + { name: 'Ponožky', category: 'Oblečení' }, + { name: 'Bunda', category: 'Oblečení' }, + { name: 'Pyžamo', category: 'Oblečení' }, + { name: 'Plavky', category: 'Oblečení' }, + { name: 'Pláštěnka', category: 'Oblečení' }, + { name: 'Pohodlné boty', category: 'Oblečení' }, + { name: 'Zubní kartáček', category: 'Hygiena' }, + { name: 'Zubní pasta', category: 'Hygiena' }, + { name: 'Šampón', category: 'Hygiena' }, + { name: 'Deodorant', category: 'Hygiena' }, + { name: 'Opalovací krém', category: 'Hygiena' }, + { name: 'Holicí strojek', category: 'Hygiena' }, + { name: 'Nabíječka', category: 'Elektronika' }, + { name: 'Powerbanka', category: 'Elektronika' }, + { name: 'Sluchátka', category: 'Elektronika' }, + { name: 'Cestovní adaptér', category: 'Elektronika' }, + { name: 'Fotoaparát', category: 'Elektronika' }, + { name: 'Léky proti bolesti', category: 'Zdraví' }, + { name: 'Náplasti', category: 'Zdraví' }, + { name: 'Dezinfekce', category: 'Zdraví' }, + ], + + // Členové / Sdílení (Members) + 'members.shareTrip': 'Sdílet cestu', + 'members.inviteUser': 'Pozvat uživatele', + 'members.selectUser': 'Vyberte uživatele…', + 'members.invite': 'Pozvat', + 'members.allHaveAccess': 'Všichni uživatelé již mají přístup.', + 'members.access': 'Přístup', + 'members.person': 'osoba', + 'members.persons': 'osob', + 'members.you': 'vy', + 'members.owner': 'Vlastník', + 'members.leaveTrip': 'Opustit cestu', + 'members.removeAccess': 'Odebrat přístup', + 'members.confirmLeave': 'Opustit cestu? Ztratíte přístup.', + 'members.confirmRemove': 'Odebrat přístup tomuto uživateli?', + 'members.loadError': 'Nepodařilo se načíst členy', + 'members.added': 'přidán/a', + 'members.addError': 'Nepodařilo se přidat', + 'members.removed': 'Člen odebrán', + 'members.removeError': 'Nepodařilo se odebrat', + + // Kategorie (Admin) + 'categories.title': 'Kategorie', + 'categories.subtitle': 'Správa kategorií pro místa', + 'categories.new': 'Nová kategorie', + 'categories.empty': 'Zatím žádné kategorie', + 'categories.namePlaceholder': 'Název kategorie', + 'categories.icon': 'Ikona', + 'categories.color': 'Barva', + 'categories.customColor': 'Vybrat vlastní barvu', + 'categories.preview': 'Náhled', + 'categories.defaultName': 'Kategorie', + 'categories.update': 'Aktualizovat', + 'categories.create': 'Vytvořit', + 'categories.confirm.delete': 'Smazat kategorii? Místa v této kategorii nebudou smazána.', + 'categories.toast.loadError': 'Nepodařilo se načíst kategorie', + 'categories.toast.nameRequired': 'Prosím zadejte název', + 'categories.toast.updated': 'Kategorie aktualizována', + 'categories.toast.created': 'Kategorie vytvořena', + 'categories.toast.saveError': 'Uložení se nezdařilo', + 'categories.toast.deleted': 'Kategorie smazána', + 'categories.toast.deleteError': 'Smazání se nezdařilo', + + // Zálohování (Backup) + 'backup.title': 'Záloha dat', + 'backup.subtitle': 'Databáze a všechny nahrané soubory', + 'backup.refresh': 'Obnovit', + 'backup.upload': 'Nahrát zálohu', + 'backup.uploading': 'Nahrávání…', + 'backup.create': 'Vytvořit zálohu', + 'backup.creating': 'Vytváření…', + 'backup.empty': 'Zatím žádné zálohy', + 'backup.createFirst': 'Vytvořit první zálohu', + 'backup.download': 'Stáhnout', + 'backup.restore': 'Obnovit', + 'backup.confirm.restore': 'Obnovit zálohu „{name}"?\n\nVšechna aktuální data budou nahrazena zálohou.', + 'backup.confirm.uploadRestore': 'Nahrát a obnovit zálohu „{name}"?\n\nVšechna aktuální data budou přepsána.', + 'backup.confirm.delete': 'Smazat zálohu „{name}"?', + 'backup.toast.loadError': 'Nepodařilo se načíst zálohy', + 'backup.toast.created': 'Záloha byla úspěšně vytvořena', + 'backup.toast.createError': 'Nepodařilo se vytvořit zálohu', + 'backup.toast.restored': 'Záloha obnovena. Stránka se znovu načte…', + 'backup.toast.restoreError': 'Obnovení se nezdařilo', + 'backup.toast.uploadError': 'Nahrávání se nezdařilo', + 'backup.toast.deleted': 'Záloha smazána', + 'backup.toast.deleteError': 'Smazání se nezdařilo', + 'backup.toast.downloadError': 'Stahování se nezdařilo', + 'backup.toast.settingsSaved': 'Nastavení automatického zálohování uloženo', + 'backup.toast.settingsError': 'Nepodařilo se uložit nastavení', + 'backup.auto.title': 'Automatické zálohování', + 'backup.auto.subtitle': 'Automatické zálohování podle plánu', + 'backup.auto.enable': 'Povolit automatické zálohování', + 'backup.auto.enableHint': 'Zálohy budou vytvářeny automaticky podle zvoleného plánu', + 'backup.auto.interval': 'Interval', + 'backup.auto.hour': 'Spustit v hodinu', + 'backup.auto.hourHint': 'Místní čas serveru (formát {format})', + 'backup.auto.dayOfWeek': 'Den v týdnu', + 'backup.auto.dayOfMonth': 'Den v měsíci', + 'backup.auto.dayOfMonthHint': 'Omezeno na 1–28 pro kompatibilitu se všemi měsíci', + 'backup.auto.scheduleSummary': 'Plán', + 'backup.auto.summaryDaily': 'Každý den v {hour}:00', + 'backup.auto.summaryWeekly': 'Každý {day} v {hour}:00', + 'backup.auto.summaryMonthly': '{day}. každého měsíce v {hour}:00', + 'backup.auto.envLocked': 'Docker', + 'backup.auto.envLockedHint': 'Automatické zálohování je konfigurováno přes Docker proměnné prostředí. Pro změnu nastavení aktualizujte docker-compose.yml a restartujte kontejner.', + 'backup.auto.copyEnv': 'Zkopírovat Docker proměnné', + 'backup.auto.envCopied': 'Docker proměnné prostředí zkopírovány do schránky', + 'backup.auto.keepLabel': 'Smazat staré zálohy po', + 'backup.dow.sunday': 'Ne', + 'backup.dow.monday': 'Po', + 'backup.dow.tuesday': 'Út', + 'backup.dow.wednesday': 'St', + 'backup.dow.thursday': 'Čt', + 'backup.dow.friday': 'Pá', + 'backup.dow.saturday': 'So', + 'backup.interval.hourly': 'Každou hodinu', + 'backup.interval.daily': 'Denně', + 'backup.interval.weekly': 'Týdně', + 'backup.interval.monthly': 'Měsíčně', + 'backup.keep.1day': '1 den', + 'backup.keep.3days': '3 dny', + 'backup.keep.7days': '7 dní', + 'backup.keep.14days': '14 dní', + 'backup.keep.30days': '30 dní', + 'backup.keep.forever': 'Uchovávat navždy', + + // Fotky + 'photos.allDays': 'Všechny dny', + 'photos.noPhotos': 'Zatím žádné fotky', + 'photos.uploadHint': 'Nahrajte své cestovní fotky', + 'photos.clickToSelect': 'nebo klikněte pro výběr', + 'photos.linkPlace': 'Propojit s místem', + 'photos.noPlace': 'Žádné místo', + 'photos.uploadN': 'Nahrát {n} fotek', + + // Obnovení zálohy + 'backup.restoreConfirmTitle': 'Obnovit zálohu?', + 'backup.restoreWarning': 'Všechna aktuální data (cesty, místa, uživatelé, nahrané soubory) budou trvale nahrazena zálohou. Tuto akci nelze vrátit.', + 'backup.restoreTip': 'Tip: Před obnovením vytvořte zálohu aktuálního stavu.', + 'backup.restoreConfirm': 'Ano, obnovit', + + // PDF + 'pdf.travelPlan': 'Cestovní plán', + 'pdf.planned': 'Naplánováno', + 'pdf.costLabel': 'Náklady EUR', + 'pdf.preview': 'Náhled PDF', + 'pdf.saveAsPdf': 'Uložit jako PDF', + + // Plánovač (Planner) + 'planner.places': 'Místa', + 'planner.bookings': 'Rezervace', + 'planner.packingList': 'Seznam věcí', + 'planner.documents': 'Dokumenty', + 'planner.dayPlan': 'Denní plán', + 'planner.reservations': 'Rezervace', + 'planner.minTwoPlaces': 'Potřebujete alespoň 2 místa se souřadnicemi', + 'planner.noGeoPlaces': 'Žádná místa se souřadnicemi nejsou k dispozici', + 'planner.routeCalculated': 'Trasa vypočtena', + 'planner.routeCalcFailed': 'Trasu se nepodařilo vypočítat', + 'planner.routeError': 'Chyba při výpočtu trasy', + 'planner.routeOptimized': 'Trasa optimalizována', + 'planner.reservationUpdated': 'Rezervace aktualizována', + 'planner.reservationAdded': 'Rezervace přidána', + 'planner.confirmDeleteReservation': 'Smazat rezervaci?', + 'planner.reservationDeleted': 'Rezervace smazána', + 'planner.days': 'Dny', + 'planner.allPlaces': 'Všechna místa', + 'planner.totalPlaces': 'Celkem {n} míst', + 'planner.noDaysPlanned': 'Zatím nejsou naplánovány žádné dny', + 'planner.editTrip': 'Upravit cestu \u2192', + 'planner.placeOne': '1 místo', + 'planner.placeN': '{n} míst', + 'planner.addNote': 'Přidat poznámku', + 'planner.noEntries': 'Pro tento den nejsou žádné záznamy', + 'planner.addPlace': 'Přidat místo/aktivitu', + 'planner.addPlaceShort': '+ Přidat místo/aktivitu', + 'planner.resPending': 'Rezervace čeká · ', + 'planner.resConfirmed': 'Rezervace potvrzena · ', + 'planner.notePlaceholder': 'Poznámka\u2026', + 'planner.noteTimePlaceholder': 'Čas (volitelné)', + 'planner.noteExamplePlaceholder': 'např. S3 ve 14:30 z hlavního nádraží, trajekt z přístaviště 7, přestávka na oběd\u2026', + 'planner.totalCost': 'Celkové náklady', + 'planner.searchPlaces': 'Hledat místa\u2026', + 'planner.allCategories': 'Všechny kategorie', + 'planner.noPlacesFound': 'Žádná místa nenalezena', + 'planner.addFirstPlace': 'Přidat první místo', + 'planner.noReservations': 'Žádné rezervace', + 'planner.addFirstReservation': 'Přidat první rezervaci', + 'planner.new': 'Nový', + 'planner.addToDay': '+ Den', + 'planner.calculating': 'Počítání\u2026', + 'planner.route': 'Trasa', + 'planner.optimize': 'Optimalizovat', + 'planner.openGoogleMaps': 'Otevřít v Google Mapách', + 'planner.selectDayHint': 'Vyberte den ze seznamu vlevo pro zobrazení denního plánu', + 'planner.noPlacesForDay': 'Zatím žádná místa pro tento den', + 'planner.addPlacesLink': 'Přidat místa \u2192', + 'planner.minTotal': 'min. celkem', + 'planner.noReservation': 'Žádná rezervace', + 'planner.removeFromDay': 'Odebrat ze dne', + 'planner.addToThisDay': 'Přidat ke dni', + 'planner.overview': 'Přehled', + 'planner.noDays': 'Zatím žádné dny', + 'planner.editTripToAddDays': 'Upravte cestu pro přidání dnů', + 'planner.dayCount': '{n} dní', + 'planner.clickToUnlock': 'Klikněte pro odemčení', + 'planner.keepPosition': 'Zachovat pozici při optimalizaci trasy', + 'planner.dayDetails': 'Podrobnosti dne', + 'planner.dayN': 'Den {n}', + + // Statistiky (Dashboard Stats) + 'stats.countries': 'Země', + 'stats.cities': 'Města', + 'stats.trips': 'Cesty', + 'stats.places': 'Místa', + 'stats.worldProgress': 'Průzkum světa', + 'stats.visited': 'navštíveno', + 'stats.remaining': 'zbývá', + 'stats.visitedCountries': 'Navštívené země', + + // Detail dne (Day Detail Panel) + 'day.precipProb': 'Pravděpodobnost srážek', + 'day.precipitation': 'Srážky', + 'day.wind': 'Vítr', + 'day.sunrise': 'Východ slunce', + 'day.sunset': 'Západ slunce', + 'day.hourlyForecast': 'Hodinová předpověď', + 'day.climateHint': 'Historické průměry — reálná předpověď je k dispozici do 16 dnů od tohoto data.', + 'day.noWeather': 'Nejsou k dispozici žádná data o počasí. Přidejte místo se souřadnicemi.', + 'day.overview': 'Denní přehled', + 'day.accommodation': 'Ubytování', + 'day.addAccommodation': 'Přidat ubytování', + 'day.hotelDayRange': 'Použít na dny', + 'day.noPlacesForHotel': 'Nejprve přidejte místa ke své cestě', + 'day.allDays': 'Vše', + 'day.checkIn': 'Check-in', + 'day.checkOut': 'Check-out', + 'day.confirmation': 'Potvrzení', + 'day.editAccommodation': 'Upravit ubytování', + 'day.reservations': 'Rezervace', + + // Fotky / Immich + 'memories.title': 'Fotky', + 'memories.notConnected': 'Immich není připojen', + 'memories.notConnectedHint': 'Připojte svoji instanci Immich v Nastavení, abyste zde viděli fotky z cest.', + 'memories.noDates': 'Přidejte data k cestě pro načtení fotek.', + 'memories.noPhotos': 'Nenalezeny žádné fotky', + 'memories.noPhotosHint': 'V Immich nebyly nalezeny žádné fotky pro období této cesty.', + 'memories.photosFound': 'fotek', + 'memories.fromOthers': 'od ostatních', + 'memories.sharePhotos': 'Sdílet fotky', + 'memories.sharing': 'Sdílení', + 'memories.reviewTitle': 'Zkontrolujte své fotky', + 'memories.reviewHint': 'Klikněte na fotky pro vyloučení ze sdílení.', + 'memories.shareCount': 'Sdílet {count} fotek', + 'memories.immichUrl': 'URL serveru Immich', + 'memories.immichApiKey': 'API klíč', + 'memories.testConnection': 'Otestovat připojení', + 'memories.connected': 'Připojeno', + 'memories.disconnected': 'Nepřipojeno', + 'memories.connectionSuccess': 'Připojeno k Immich', + 'memories.connectionError': 'Nepodařilo se připojit k Immich', + 'memories.saved': 'Nastavení Immich uloženo', + 'memories.addPhotos': 'Přidat fotky', + 'memories.selectPhotos': 'Vybrat fotky z Immich', + 'memories.selectHint': 'Klepněte na fotky pro jejich výběr.', + 'memories.selected': 'vybráno', + 'memories.addSelected': 'Přidat {count} fotek', + 'memories.alreadyAdded': 'Přidáno', + 'memories.private': 'Soukromé', + 'memories.stopSharing': 'Zastavit sdílení', + 'memories.oldest': 'Nejstarší', + 'memories.newest': 'Nejnovější', + 'memories.allLocations': 'Všechna místa', + 'memories.tripDates': 'Data cesty', + 'memories.allPhotos': 'Všechny fotky', + 'memories.confirmShareTitle': 'Sdílet se členy cesty?', + 'memories.confirmShareHint': '{count} fotek bude viditelných pro všechny členy této cesty. Jednotlivé fotky můžete později nastavit jako soukromé.', + 'memories.confirmShareButton': 'Sdílet fotky', + + // Spolupráce (Collab) + 'collab.tabs.chat': 'Chat', + 'collab.tabs.notes': 'Poznámky', + 'collab.tabs.polls': 'Hlasování', + 'collab.whatsNext.title': 'Co následuje', + 'collab.whatsNext.today': 'Dnes', + 'collab.whatsNext.tomorrow': 'Zítra', + 'collab.whatsNext.empty': 'Žádné nadcházející aktivity', + 'collab.whatsNext.until': 'do', + 'collab.whatsNext.emptyHint': 'Aktivity s časem se zde zobrazí', + 'collab.chat.send': 'Odeslat', + 'collab.chat.placeholder': 'Napište zprávu...', + 'collab.chat.empty': 'Začněte konverzaci', + 'collab.chat.emptyHint': 'Zprávy jsou sdíleny se všemi členy cesty', + 'collab.chat.emptyDesc': 'Sdílejte nápady, plány a novinky se svou cestovatelskou skupinou', + 'collab.chat.today': 'Dnes', + 'collab.chat.yesterday': 'Včera', + 'collab.chat.deletedMessage': 'smazal zprávu', + 'collab.chat.loadMore': 'Načíst starší zprávy', + 'collab.chat.justNow': 'právě teď', + 'collab.chat.minutesAgo': 'před {n} min', + 'collab.chat.hoursAgo': 'před {n} h', + 'collab.notes.title': 'Poznámky', + 'collab.notes.new': 'Nová poznámka', + 'collab.notes.empty': 'Zatím žádné poznámky', + 'collab.notes.emptyHint': 'Začněte zapisovat nápady a plány', + 'collab.notes.all': 'Vše', + 'collab.notes.titlePlaceholder': 'Poznámka...', + 'collab.notes.noCategory': 'Bez kategorie', + 'collab.notes.color': 'Barva', + 'collab.notes.save': 'Uložit', + 'collab.notes.cancel': 'Zrušit', + 'collab.notes.edit': 'Upravit', + 'collab.notes.delete': 'Smazat', + 'collab.notes.pin': 'Připnout', + 'collab.notes.unpin': 'Odepnout', + 'collab.notes.daysAgo': 'před {n} dny', + 'collab.notes.categorySettings': 'Spravovat kategorie', + 'collab.notes.create': 'Vytvořit', + 'collab.notes.website': 'Webové stránky', + 'collab.notes.websitePlaceholder': 'https://...', + 'collab.notes.attachFiles': 'Přiložit soubory', + 'collab.notes.noCategoriesYet': 'Zatím žádné kategorie', + 'collab.notes.emptyDesc': 'Vytvořte poznámku a začněte', + 'collab.notes.contentPlaceholder': 'Napište něco...', + 'collab.notes.categoryPlaceholder': 'Kategorie', + 'collab.notes.newCategory': 'Nová kategorie...', + 'collab.notes.category': 'Kategorie', + 'collab.polls.title': 'Hlasování', + 'collab.polls.new': 'Nové hlasování', + 'collab.polls.empty': 'Zatím žádná hlasování', + 'collab.polls.emptyHint': 'Zeptejte se skupiny a hlasujte společně', + 'collab.polls.question': 'Otázka', + 'collab.polls.questionPlaceholder': 'Co bychom měli dělat?', + 'collab.polls.addOption': '+ Přidat možnost', + 'collab.polls.optionPlaceholder': 'Možnost {n}', + 'collab.polls.create': 'Vytvořit hlasování', + 'collab.polls.close': 'Uzavřít', + 'collab.polls.closed': 'Uzavřeno', + 'collab.polls.votes': '{n} hlasů', + 'collab.polls.vote': '{n} hlas', + 'collab.polls.multipleChoice': 'Více možností', + 'collab.polls.multiChoice': 'Více možností', + 'collab.polls.deadline': 'Termín', + 'collab.polls.option': 'Možnost', + 'collab.polls.options': 'Možnosti', + 'collab.polls.delete': 'Smazat', + 'collab.polls.closedSection': 'Uzavřené', +} + +export default cs diff --git a/client/src/i18n/translations/de.ts b/client/src/i18n/translations/de.ts index ee5b181..341a36d 100644 --- a/client/src/i18n/translations/de.ts +++ b/client/src/i18n/translations/de.ts @@ -247,6 +247,13 @@ const de: Record = { 'settings.mfa.title': 'Zwei-Faktor-Authentifizierung (2FA)', 'settings.mfa.description': 'Zusätzlicher Schritt bei der Anmeldung mit E-Mail und Passwort. Nutze eine Authenticator-App (Google Authenticator, Authy, …).', 'settings.mfa.requiredByPolicy': 'Dein Administrator verlangt Zwei-Faktor-Authentifizierung. Richte unten eine Authenticator-App ein, bevor du fortfährst.', + 'settings.mfa.backupTitle': 'Backup-Codes', + 'settings.mfa.backupDescription': 'Verwende diese Einmal-Codes, wenn du keinen Zugriff mehr auf deine Authenticator-App hast.', + 'settings.mfa.backupWarning': 'Jetzt speichern. Jeder Code kann nur einmal verwendet werden.', + 'settings.mfa.backupCopy': 'Codes kopieren', + 'settings.mfa.backupDownload': 'TXT herunterladen', + 'settings.mfa.backupPrint': 'Drucken / PDF', + 'settings.mfa.backupCopied': 'Backup-Codes kopiert', 'settings.mfa.enabled': '2FA ist für dein Konto aktiv.', 'settings.mfa.disabled': '2FA ist nicht aktiviert.', 'settings.mfa.setup': 'Authenticator einrichten', diff --git a/client/src/i18n/translations/en.ts b/client/src/i18n/translations/en.ts index 6e4ab53..ea8ebe3 100644 --- a/client/src/i18n/translations/en.ts +++ b/client/src/i18n/translations/en.ts @@ -247,6 +247,13 @@ const en: Record = { 'settings.mfa.title': 'Two-factor authentication (2FA)', 'settings.mfa.description': 'Adds a second step when you sign in with email and password. Use an authenticator app (Google Authenticator, Authy, etc.).', 'settings.mfa.requiredByPolicy': 'Your administrator requires two-factor authentication. Set up an authenticator app below before continuing.', + 'settings.mfa.backupTitle': 'Backup codes', + 'settings.mfa.backupDescription': 'Use these one-time backup codes if you lose access to your authenticator app.', + 'settings.mfa.backupWarning': 'Save these codes now. Each code can only be used once.', + 'settings.mfa.backupCopy': 'Copy codes', + 'settings.mfa.backupDownload': 'Download TXT', + 'settings.mfa.backupPrint': 'Print / PDF', + 'settings.mfa.backupCopied': 'Backup codes copied', 'settings.mfa.enabled': '2FA is enabled on your account.', 'settings.mfa.disabled': '2FA is not enabled.', 'settings.mfa.setup': 'Set up authenticator', diff --git a/client/src/i18n/translations/es.ts b/client/src/i18n/translations/es.ts index 7d397dd..f1b0e1e 100644 --- a/client/src/i18n/translations/es.ts +++ b/client/src/i18n/translations/es.ts @@ -237,6 +237,13 @@ const es: Record = { 'settings.mfa.title': 'Autenticación de dos factores (2FA)', 'settings.mfa.description': 'Añade un segundo paso al iniciar sesión. Usa una app de autenticación (Google Authenticator, Authy, etc.).', 'settings.mfa.requiredByPolicy': 'Tu administrador exige autenticación en dos factores. Configura una app de autenticación abajo antes de continuar.', + 'settings.mfa.backupTitle': 'Códigos de respaldo', + 'settings.mfa.backupDescription': 'Usa estos códigos de un solo uso si pierdes acceso a tu app autenticadora.', + 'settings.mfa.backupWarning': 'Guárdalos ahora. Cada código solo se puede usar una vez.', + 'settings.mfa.backupCopy': 'Copiar códigos', + 'settings.mfa.backupDownload': 'Descargar TXT', + 'settings.mfa.backupPrint': 'Imprimir / PDF', + 'settings.mfa.backupCopied': 'Códigos de respaldo copiados', 'settings.mfa.enabled': '2FA está activado en tu cuenta.', 'settings.mfa.disabled': '2FA no está activado.', 'settings.mfa.setup': 'Configurar autenticador', diff --git a/client/src/i18n/translations/fr.ts b/client/src/i18n/translations/fr.ts index f1a2b7b..6ff7793 100644 --- a/client/src/i18n/translations/fr.ts +++ b/client/src/i18n/translations/fr.ts @@ -238,6 +238,13 @@ const fr: Record = { 'settings.mfa.title': 'Authentification à deux facteurs (2FA)', 'settings.mfa.description': 'Ajoute une étape supplémentaire lors de la connexion. Utilisez une application d\'authentification (Google Authenticator, Authy, etc.).', 'settings.mfa.requiredByPolicy': 'Votre administrateur exige l\'authentification à deux facteurs. Configurez une application d\'authentification ci-dessous avant de continuer.', + 'settings.mfa.backupTitle': 'Codes de secours', + 'settings.mfa.backupDescription': 'Utilisez ces codes à usage unique si vous perdez l\'accès à votre application d\'authentification.', + 'settings.mfa.backupWarning': 'Enregistrez ces codes maintenant. Chaque code n\'est utilisable qu\'une seule fois.', + 'settings.mfa.backupCopy': 'Copier les codes', + 'settings.mfa.backupDownload': 'Télécharger TXT', + 'settings.mfa.backupPrint': 'Imprimer / PDF', + 'settings.mfa.backupCopied': 'Codes de secours copiés', 'settings.mfa.enabled': '2FA est activé sur votre compte.', 'settings.mfa.disabled': '2FA n\'est pas activé.', 'settings.mfa.setup': 'Configurer l\'authentificateur', diff --git a/client/src/i18n/translations/hu.ts b/client/src/i18n/translations/hu.ts index 3766b21..ca68de1 100644 --- a/client/src/i18n/translations/hu.ts +++ b/client/src/i18n/translations/hu.ts @@ -213,6 +213,13 @@ const hu: Record = { 'settings.mfa.title': 'Kétfaktoros hitelesítés (2FA)', 'settings.mfa.description': 'Egy második lépést ad a bejelentkezéshez e-mail és jelszó használatakor. Használj hitelesítő alkalmazást (Google Authenticator, Authy stb.).', 'settings.mfa.requiredByPolicy': 'A rendszergazda kétlépcsős hitelesítést ír elő. Állíts be hitelesítő alkalmazást lent, mielőtt továbblépnél.', + 'settings.mfa.backupTitle': 'Tartalék kódok', + 'settings.mfa.backupDescription': 'Használd ezeket az egyszer használatos kódokat, ha elveszíted a hozzáférést a hitelesítő alkalmazásodhoz.', + 'settings.mfa.backupWarning': 'Mentsd el ezeket most. Minden kód csak egyszer használható.', + 'settings.mfa.backupCopy': 'Kódok másolása', + 'settings.mfa.backupDownload': 'TXT letöltése', + 'settings.mfa.backupPrint': 'Nyomtatás / PDF', + 'settings.mfa.backupCopied': 'Tartalék kódok másolva', 'settings.mfa.enabled': '2FA engedélyezve van a fiókodban.', 'settings.mfa.disabled': '2FA nincs engedélyezve.', 'settings.mfa.setup': 'Hitelesítő beállítása', @@ -656,7 +663,6 @@ const hu: Record = { 'atlas.statsTab': 'Statisztikák', 'atlas.bucketTab': 'Bakancslista', 'atlas.addBucket': 'Hozzáadás a bakancslistához', - 'atlas.bucketNamePlaceholder': 'Hely vagy úti cél...', 'atlas.bucketNotesPlaceholder': 'Jegyzetek (opcionális)', 'atlas.bucketEmpty': 'A bakancslistád üres', 'atlas.bucketEmptyHint': 'Adj hozzá helyeket, ahová álmodsz eljutni', diff --git a/client/src/i18n/translations/it.ts b/client/src/i18n/translations/it.ts index 593a957..a7ae949 100644 --- a/client/src/i18n/translations/it.ts +++ b/client/src/i18n/translations/it.ts @@ -1,1388 +1,1395 @@ -const it: Record = { - // Common - 'common.save': 'Salva', - 'common.cancel': 'Annulla', - 'common.delete': 'Elimina', - 'common.edit': 'Modifica', - 'common.add': 'Aggiungi', - 'common.loading': 'Caricamento...', - 'common.error': 'Errore', - 'common.back': 'Indietro', - 'common.all': 'Tutti', - 'common.close': 'Chiudi', - 'common.open': 'Apri', - 'common.upload': 'Carica', - 'common.search': 'Cerca', - 'common.confirm': 'Conferma', - 'common.ok': 'OK', - 'common.yes': 'Sì', - 'common.no': 'No', - 'common.or': 'o', - 'common.none': 'Nessuno', - 'common.date': 'Data', - 'common.rename': 'Rinomina', - 'common.name': 'Nome', - 'common.email': 'Email', - 'common.password': 'Password', - 'common.saving': 'Salvataggio...', - 'common.update': 'Aggiorna', - 'common.change': 'Cambia', - 'common.uploading': 'Caricamento…', - 'common.backToPlanning': 'Torna al Programma', - 'common.reset': 'Reimposta', - - // Navbar - 'nav.trip': 'Viaggio', - 'nav.share': 'Condividi', - 'nav.settings': 'Impostazioni', - 'nav.admin': 'Amministrazione', - 'nav.logout': 'Esci', - 'nav.lightMode': 'Modalità chiara', - 'nav.darkMode': 'Modalità scura', - 'nav.autoMode': 'Modalità automatica', - 'nav.administrator': 'Amministratore', - - // Dashboard - 'dashboard.title': 'I miei Viaggi', - 'dashboard.subtitle.loading': 'Caricamento viaggi...', - 'dashboard.subtitle.trips': '{count} viaggi ({archived} archiviati)', - 'dashboard.subtitle.empty': 'Inizia il tuo primo viaggio', - 'dashboard.subtitle.activeOne': '{count} viaggio attivo', - 'dashboard.subtitle.activeMany': '{count} viaggi attivi', - 'dashboard.subtitle.archivedSuffix': ' · {count} archiviati', - 'dashboard.newTrip': 'Nuovo Viaggio', - 'dashboard.gridView': 'Vista a griglia', - 'dashboard.listView': 'Vista a lista', - 'dashboard.currency': 'Valuta', - 'dashboard.timezone': 'Fusi orari', - 'dashboard.localTime': 'Locale', - 'dashboard.timezoneCustomTitle': 'Fuso orario personalizzato', - 'dashboard.timezoneCustomLabelPlaceholder': 'Etichetta (opzionale)', - 'dashboard.timezoneCustomTzPlaceholder': 'es. Europe/Rome', - 'dashboard.timezoneCustomAdd': 'Aggiungi', - 'dashboard.timezoneCustomErrorEmpty': 'Inserisci un identificatore di fuso orario', - 'dashboard.timezoneCustomErrorInvalid': 'Fuso orario non valido. Usa formati come Europe/Rome', - 'dashboard.timezoneCustomErrorDuplicate': 'Già aggiunto', - 'dashboard.emptyTitle': 'Ancora nessun viaggio', - 'dashboard.emptyText': 'Crea il tuo primo viaggio e inizia a programmare!', - 'dashboard.emptyButton': 'Crea il primo viaggio', - 'dashboard.nextTrip': 'Prossimo Viaggio', - 'dashboard.shared': 'Condiviso', - 'dashboard.sharedBy': 'Condiviso da {name}', - 'dashboard.days': 'Giorni', - 'dashboard.places': 'Luoghi', - 'dashboard.archive': 'Archivia', - 'dashboard.restore': 'Ripristina', - 'dashboard.archived': 'Archiviati', - 'dashboard.status.ongoing': 'In corso', - 'dashboard.status.today': 'Oggi', - 'dashboard.status.tomorrow': 'Domani', - 'dashboard.status.past': 'Passato', - 'dashboard.status.daysLeft': '-{count} giorni', - 'dashboard.toast.loadError': 'Impossibile caricare i viaggi', - 'dashboard.toast.created': 'Viaggio creato con successo!', - 'dashboard.toast.createError': 'Impossibile creare il viaggio', - 'dashboard.toast.updated': 'Viaggio aggiornato!', - 'dashboard.toast.updateError': 'Impossibile aggiornare il viaggio', - 'dashboard.toast.deleted': 'Viaggio eliminato', - 'dashboard.toast.deleteError': 'Impossibile eliminare il viaggio', - 'dashboard.toast.archived': 'Viaggio archiviato', - 'dashboard.toast.archiveError': 'Impossibile archiviare il viaggio', - 'dashboard.toast.restored': 'Viaggio ripristinato', - 'dashboard.toast.restoreError': 'Impossibile ripristinare il viaggio', - 'dashboard.confirm.delete': 'Eliminare il viaggio "{title}"? Tutti i luoghi e i programmi verranno eliminati in modo permanente.', - 'dashboard.editTrip': 'Modifica Viaggio', - 'dashboard.createTrip': 'Crea Nuovo Viaggio', - 'dashboard.tripTitle': 'Titolo', - 'dashboard.tripTitlePlaceholder': 'es. Estate in Giappone', - 'dashboard.tripDescription': 'Descrizione', - 'dashboard.tripDescriptionPlaceholder': 'Di cosa tratta questo viaggio?', - 'dashboard.startDate': 'Data di inizio', - 'dashboard.endDate': 'Data di fine', - 'dashboard.noDateHint': 'Nessuna data impostata — verranno creati 7 giorni predefiniti. Puoi cambiarlo in qualsiasi momento.', - 'dashboard.coverImage': 'Immagine di copertina', - 'dashboard.addCoverImage': 'Aggiungi immagine di copertina (o trascinala qui)', - 'dashboard.addMembers': 'Compagni di viaggio', - 'dashboard.addMember': 'Aggiungi membro', - 'dashboard.coverSaved': 'Immagine di copertina salvata', - 'dashboard.coverUploadError': 'Impossibile caricare', - 'dashboard.coverRemoveError': 'Impossibile rimuovere', - 'dashboard.titleRequired': 'Il titolo è obbligatorio', - 'dashboard.endDateError': 'La data di fine deve essere successiva alla data di inizio', - - // Settings - 'settings.title': 'Impostazioni', - 'settings.subtitle': 'Configura le tue impostazioni personali', - 'settings.map': 'Mappa', - 'settings.mapTemplate': 'Modello Mappa', - 'settings.mapTemplatePlaceholder.select': 'Seleziona modello...', - 'settings.mapDefaultHint': 'Lascia vuoto per OpenStreetMap (predefinito)', - 'settings.mapTemplatePlaceholder': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - 'settings.mapHint': 'Modello URL per i tile della mappa', - 'settings.latitude': 'Latitudine', - 'settings.longitude': 'Longitudine', - 'settings.saveMap': 'Salva Mappa', - 'settings.apiKeys': 'Chiavi API', - 'settings.mapsKey': 'Chiave API Google Maps', - 'settings.mapsKeyHint': 'Per la ricerca dei luoghi. Richiede Places API (New). Ottienila su console.cloud.google.com', - 'settings.weatherKey': 'Chiave API OpenWeatherMap', - 'settings.weatherKeyHint': 'Per i dati meteo. Gratuita su openweathermap.org/api', - 'settings.keyPlaceholder': 'Inserisci la chiave...', - 'settings.configured': 'Configurata', - 'settings.saveKeys': 'Salva Chiavi', - 'settings.display': 'Visualizzazione', - 'settings.colorMode': 'Modalità Colore', - 'settings.light': 'Chiara', - 'settings.dark': 'Scura', - 'settings.auto': 'Automatica', - 'settings.language': 'Lingua', - 'settings.temperature': 'Unità di Temperatura', - 'settings.timeFormat': 'Formato Ora', - 'settings.routeCalculation': 'Calcolo Percorso', - 'settings.blurBookingCodes': 'Nascondi codici di prenotazione', - 'settings.notifications': 'Notifiche', - 'settings.notifyTripInvite': 'Inviti di viaggio', - 'settings.notifyBookingChange': 'Modifiche alle prenotazioni', - 'settings.notifyTripReminder': 'Promemoria di viaggio', - 'settings.notifyVacayInvite': 'Inviti fusione Vacay', - 'settings.notifyPhotosShared': 'Foto condivise (Immich)', - 'settings.notifyCollabMessage': 'Messaggi chat (Collab)', - 'settings.notifyPackingTagged': 'Lista valigia: assegnazioni', - 'settings.notifyWebhook': 'Notifiche webhook', - 'settings.on': 'On', - 'settings.off': 'Off', - 'settings.mcp.title': 'Configurazione MCP', - 'settings.mcp.endpoint': 'Endpoint MCP', - 'settings.mcp.clientConfig': 'Configurazione client', - 'settings.mcp.clientConfigHint': 'Sostituisci con un token API dalla lista sottostante. Il percorso di npx potrebbe dover essere adattato per il tuo sistema (es. C:\\PROGRA~1\\nodejs\\npx.cmd su Windows).', - 'settings.mcp.copy': 'Copia', - 'settings.mcp.copied': 'Copiato!', - 'settings.mcp.apiTokens': 'Token API', - 'settings.mcp.createToken': 'Crea nuovo token', - 'settings.mcp.noTokens': 'Nessun token ancora. Creane uno per connettere i client MCP.', - 'settings.mcp.tokenCreatedAt': 'Creato', - 'settings.mcp.tokenUsedAt': 'Utilizzato', - 'settings.mcp.deleteTokenTitle': 'Elimina token', - 'settings.mcp.deleteTokenMessage': 'Questo token smetterà di funzionare immediatamente. Qualsiasi client MCP che lo utilizza perderà l\'accesso.', - 'settings.mcp.modal.createTitle': 'Crea token API', - 'settings.mcp.modal.tokenName': 'Nome del token', - 'settings.mcp.modal.tokenNamePlaceholder': 'es. Claude Desktop, Laptop di lavoro', - 'settings.mcp.modal.creating': 'Creazione…', - 'settings.mcp.modal.create': 'Crea token', - 'settings.mcp.modal.createdTitle': 'Token creato', - 'settings.mcp.modal.createdWarning': 'Questo token verrà mostrato solo una volta. Copialo e salvalo ora — non può essere recuperato.', - 'settings.mcp.modal.done': 'Fatto', - 'settings.mcp.toast.created': 'Token creato', - 'settings.mcp.toast.createError': 'Impossibile creare il token', - 'settings.mcp.toast.deleted': 'Token eliminato', - 'settings.mcp.toast.deleteError': 'Impossibile eliminare il token', - 'settings.account': 'Account', - 'settings.username': 'Username', - 'settings.email': 'Email', - 'settings.role': 'Ruolo', - 'settings.roleAdmin': 'Amministratore', - 'settings.oidcLinked': 'Collegato con', - 'settings.changePassword': 'Cambia Password', - 'settings.currentPassword': 'Password attuale', - 'settings.currentPasswordRequired': 'La password attuale è obbligatoria', - 'settings.newPassword': 'Nuova password', - 'settings.confirmPassword': 'Conferma nuova password', - 'settings.updatePassword': 'Aggiorna password', - 'settings.passwordRequired': 'Inserisci la password attuale e quella nuova', - 'settings.passwordTooShort': 'La password deve contenere almeno 8 caratteri', - 'settings.passwordMismatch': 'Le password non corrispondono', - 'settings.passwordWeak': 'La password deve contenere lettere maiuscole, minuscole e un numero', - 'settings.passwordChanged': 'Password cambiata con successo', - 'settings.deleteAccount': 'Elimina account', - 'settings.deleteAccountTitle': 'Eliminare il tuo account?', - 'settings.deleteAccountWarning': 'Il tuo account e tutti i tuoi viaggi, luoghi e file verranno eliminati in modo permanente. Questa azione non può essere annullata.', - 'settings.deleteAccountConfirm': 'Elimina in modo permanente', - 'settings.deleteBlockedTitle': 'Eliminazione impossibile', - 'settings.deleteBlockedMessage': 'Sei l\'unico amministratore. Promuovi un altro utente ad amministratore prima di eliminare il tuo account.', - 'settings.roleUser': 'Utente', - 'settings.saveProfile': 'Salva Profillo', - 'settings.toast.mapSaved': 'Impostazioni mappa salvate', - 'settings.toast.keysSaved': 'Chiavi API salvate', - 'settings.toast.displaySaved': 'Impostazioni di visualizzazione salvate', - 'settings.toast.profileSaved': 'Profilo salvato', - 'settings.uploadAvatar': 'Carica Immagine del Profilo', - 'settings.removeAvatar': 'Rimuovi Immagine del Profilo', - 'settings.avatarUploaded': 'Immagine del profilo aggiornata', - 'settings.avatarRemoved': 'Immagine del profilo rimossa', - 'settings.avatarError': 'Impossibile caricare', - 'settings.mfa.title': 'Autenticazione a due fattori (2FA)', - 'settings.mfa.description': 'Aggiunge un secondo passaggio quando accedi con email e password. Usa un\'app authenticator (Google Authenticator, Authy, ecc.).', - 'settings.mfa.requiredByPolicy': 'L\'amministratore richiede l\'autenticazione a due fattori. Configura un\'app authenticator qui sotto prima di continuare.', - 'settings.mfa.enabled': 'La 2FA è abilitata sul tuo account.', - 'settings.mfa.disabled': 'La 2FA non è abilitata.', - 'settings.mfa.setup': 'Configura authenticator', - 'settings.mfa.scanQr': 'Scansiona questo codice QR con la tua app, o inserisci il segreto manualmente.', - 'settings.mfa.secretLabel': 'Chiave segreta (inserimento manuale)', - 'settings.mfa.codePlaceholder': 'Codice a 6 cifre', - 'settings.mfa.enable': 'Abilita 2FA', - 'settings.mfa.cancelSetup': 'Annulla', - 'settings.mfa.disableTitle': 'Disabilita 2FA', - 'settings.mfa.disableHint': 'Inserisci la password del tuo account e un codice attuale dal tuo authenticator.', - 'settings.mfa.disable': 'Disabilita 2FA', - 'settings.mfa.toastEnabled': 'Autenticazione a due fattori abilitata', - 'settings.mfa.toastDisabled': 'Autenticazione a due fattori disabilitata', - 'settings.mfa.demoBlocked': 'Non disponibile in modalità demo', - 'admin.smtp.title': 'Email e notifiche', - 'admin.smtp.hint': 'Configurazione SMTP per le notifiche via email. Opzionale: URL webhook per Discord, Slack, ecc.', - 'admin.smtp.testButton': 'Invia email di prova', - 'admin.smtp.testSuccess': 'Email di prova inviata con successo', - 'admin.smtp.testFailed': 'Invio email di prova fallito', - 'dayplan.icsTooltip': 'Esporta calendario (ICS)', - 'share.linkTitle': 'Link pubblico', - 'share.linkHint': 'Crea un link che chiunque può usare per visualizzare questo viaggio senza accedere. Solo lettura — nessuna modifica possibile.', - 'share.createLink': 'Crea link', - 'share.deleteLink': 'Elimina link', - 'share.createError': 'Impossibile creare il link', - 'common.copy': 'Copia', - 'common.copied': 'Copiato', - 'share.permMap': 'Mappa e programma', - 'share.permBookings': 'Prenotazioni', - 'share.permPacking': 'Valigia', - 'shared.expired': 'Link scaduto o non valido', - 'shared.expiredHint': 'Questo link di viaggio condiviso non è più attivo.', - 'shared.readOnly': 'Vista in sola lettura', - 'shared.tabPlan': 'Programma', - 'shared.tabBookings': 'Prenotazioni', - 'shared.tabPacking': 'Valigia', - 'shared.tabBudget': 'Budget', - 'shared.tabChat': 'Chat', - 'shared.days': 'giorni', - 'shared.places': 'luoghi', - 'shared.other': 'Altro', - 'shared.totalBudget': 'Budget totale', - 'shared.messages': 'messaggi', - 'shared.sharedVia': 'Condiviso tramite', - 'shared.confirmed': 'Confermato', - 'shared.pending': 'In attesa', - 'share.permBudget': 'Budget', - 'share.permCollab': 'Chat', - - // Login - 'login.error': 'Accesso fallito. Controlla le tue credenziali.', - 'login.tagline': 'I tuoi viaggi.\nIl tuo programma.', - 'login.description': 'Programma viaggi in collaborazione con mappe interattive, budget e sincronizzazione in tempo reale.', - 'login.features.maps': 'Mappe Interattive', - 'login.features.mapsDesc': 'Google Places, percorsi e clustering', - 'login.features.realtime': 'Sincronizzazione in tempo reale', - 'login.features.realtimeDesc': 'Programmate insieme tramite WebSocket', - 'login.features.budget': 'Tracciamento Budget', - 'login.features.budgetDesc': 'Categorie, grafici e costi per persona', - 'login.features.collab': 'Collaborazione', - 'login.features.collabDesc': 'Multi-utente con viaggi condivisi', - 'login.features.packing': 'Lista Valigia', - 'login.features.packingDesc': 'Categorie, progressi e suggerimenti', - 'login.features.bookings': 'Prenotazioni', - 'login.features.bookingsDesc': 'Voli, alloggi, ristoranti e altro', - 'login.features.files': 'Documenti', - 'login.features.filesDesc': 'Carica e gestisci i documenti', - 'login.features.routes': 'Percorsi Intelligenti', - 'login.features.routesDesc': 'Ottimizzazione automatica ed esportazione su Google Maps', - 'login.selfHosted': 'Self-hosted · Open Source · Your data stays yours', - 'login.title': 'Accedi', - 'login.subtitle': 'Bentornato', - 'login.signingIn': 'Accesso in corso…', - 'login.signIn': 'Accedi', - 'login.createAdmin': 'Crea Account Amministratore', - 'login.createAdminHint': 'Imposta il primo account amministratore per TREK.', - 'login.createAccount': 'Crea Account', - 'login.createAccountHint': 'Registra un nuovo account.', - 'login.creating': 'Creazione in corso…', - 'login.noAccount': "Non hai un account?", - 'login.hasAccount': 'Hai già un account?', - 'login.register': 'Registrati', - 'login.emailPlaceholder': 'tua@email.com', - 'login.username': 'Username', - 'login.oidc.registrationDisabled': 'La registrazione è disabilitata. Contatta il tuo amministratore.', - 'login.oidc.noEmail': 'Nessuna email ricevuta dal provider.', - 'login.oidc.tokenFailed': 'Autenticazione fallita.', - 'login.oidc.invalidState': 'Sessione non valida. Riprova.', - 'login.demoFailed': 'Accesso demo fallito', - 'login.oidcSignIn': 'Accedi con {name}', - 'login.oidcOnly': 'L\'autenticazione tramite password è disabilitata. Accedi utilizzando il tuo provider SSO.', - 'login.demoHint': 'Prova la demo — nessuna registrazione necessaria', - 'login.mfaTitle': 'Autenticazione a due fattori', - 'login.mfaSubtitle': 'Inserisci il codice a 6 cifre dalla tua app authenticator.', - 'login.mfaCodeLabel': 'Codice di verifica', - 'login.mfaCodeRequired': 'Inserisci il codice dalla tua app authenticator.', - 'login.mfaHint': 'Apri Google Authenticator, Authy o un\'altra app TOTP.', - 'login.mfaBack': '← Torna all\'accesso', - 'login.mfaVerify': 'Verifica', - - // Register - 'register.passwordMismatch': 'Le password non corrispondono', - 'register.passwordTooShort': 'La password deve contenere almeno 6 caratteri', - 'register.failed': 'Registrazione fallita', - 'register.getStarted': 'Inizia', - 'register.subtitle': 'Crea un account e inizia a programmare i viaggi dei tuoi sogni.', - 'register.feature1': 'Piani di viaggio illimitati', - 'register.feature2': 'Vista mappa interattiva', - 'register.feature3': 'Gestisci luoghi e categorie', - 'register.feature4': 'Traccia le prenotazioni', - 'register.feature5': 'Crea liste per la valigia', - 'register.feature6': 'Archivia foto e file', - 'register.createAccount': 'Crea Account', - 'register.startPlanning': 'Inizia a programmare il tuo viaggio', - 'register.minChars': 'Min. 6 caratteri', - 'register.confirmPassword': 'Conferma Password', - 'register.repeatPassword': 'Ripeti password', - 'register.registering': 'Registrazione in corso...', - 'register.register': 'Registrati', - 'register.hasAccount': 'Hai già un account?', - 'register.signIn': 'Accedi', - - // Admin - 'admin.title': 'Amministrazione', - 'admin.subtitle': 'Gestione utenti e impostazioni di sistema', - 'admin.tabs.users': 'Utenti', - 'admin.tabs.categories': 'Categorie', - 'admin.tabs.backup': 'Backup', - 'admin.stats.users': 'Utenti', - 'admin.stats.trips': 'Viaggi', - 'admin.stats.places': 'Luoghi', - 'admin.stats.photos': 'Foto', - 'admin.stats.files': 'File', - 'admin.table.user': 'Utente', - 'admin.table.email': 'Email', - 'admin.table.role': 'Ruolo', - 'admin.table.created': 'Creato', - 'admin.table.lastLogin': 'Ultimo Accesso', - 'admin.table.actions': 'Azioni', - 'admin.you': '(Tu)', - 'admin.editUser': 'Modifica Utente', - 'admin.newPassword': 'Nuova Password', - 'admin.newPasswordHint': 'Lascia vuoto per mantenere la password attuale', - 'admin.deleteUser': 'Eliminare l\'utente "{name}"? Tutti i viaggi verranno eliminati in modo permanente.', - 'admin.deleteUserTitle': 'Elimina utente', - 'admin.newPasswordPlaceholder': 'Inserisci nuova password…', - 'admin.toast.loadError': 'Impossibile caricare i dati di amministrazione', - 'admin.toast.userUpdated': 'Utente aggiornato', - 'admin.toast.updateError': 'Impossibile aggiornare', - 'admin.toast.userDeleted': 'Utente eliminato', - 'admin.toast.deleteError': 'Impossibile eliminare', - 'admin.toast.cannotDeleteSelf': 'Impossibile eliminare il proprio account', - 'admin.toast.userCreated': 'Utente creato', - 'admin.toast.createError': 'Impossibile creare l\'utente', - 'admin.toast.fieldsRequired': 'Username, email e password sono obbligatori', - 'admin.createUser': 'Crea Utente', - 'admin.invite.title': 'Link di Invito', - 'admin.invite.subtitle': 'Crea link di registrazione monouso', - 'admin.invite.create': 'Crea Link', - 'admin.invite.createAndCopy': 'Crea & Copia', - 'admin.invite.empty': 'Nessun link di invito ancora creato', - 'admin.invite.maxUses': 'Usi Max.', - 'admin.invite.expiry': 'Scade tra', - 'admin.invite.uses': 'usato', - 'admin.invite.expiresAt': 'scade', - 'admin.invite.createdBy': 'da', - 'admin.invite.active': 'Attivo', - 'admin.invite.expired': 'Scaduto', - 'admin.invite.usedUp': 'Esaurito', - 'admin.invite.copied': 'Link di invito copiato negli appunti', - 'admin.invite.copyLink': 'Copia link', - 'admin.invite.deleted': 'Link di invito eliminato', - 'admin.invite.createError': 'Impossibile creare il link di invito', - 'admin.invite.deleteError': 'Impossibile eliminare il link di invito', - 'admin.tabs.settings': 'Impostazioni', - 'admin.allowRegistration': 'Consenti Registrazione', - 'admin.allowRegistrationHint': 'I nuovi utenti possono registrarsi autonomamente', - 'admin.requireMfa': 'Richiedi autenticazione a due fattori (2FA)', - 'admin.requireMfaHint': 'Gli utenti senza 2FA devono completare la configurazione in Impostazioni prima di usare l\'app.', - 'admin.apiKeys': 'Chiavi API', - 'admin.apiKeysHint': 'Opzionale. Abilita dati estesi per i luoghi come foto e meteo.', - 'admin.mapsKey': 'Chiave API Google Maps', - 'admin.mapsKeyHint': 'Richiesta per la ricerca dei luoghi. Ottienila su console.cloud.google.com', - 'admin.mapsKeyHintLong': 'Senza una chiave API, OpenStreetMap viene utilizzato per la ricerca dei luoghi. Con una chiave API di Google, è possibile caricare anche foto, valutazioni e orari di apertura. Ottienine una su console.cloud.google.com.', - 'admin.recommended': 'Consigliato', - 'admin.weatherKey': 'Chiave API OpenWeatherMap', - 'admin.weatherKeyHint': 'Per i dati meteo. Gratuita su openweathermap.org', - 'admin.validateKey': 'Testa', - 'admin.keyValid': 'Connessa', - 'admin.keyInvalid': 'Non valida', - 'admin.keySaved': 'Chiavi API salvate', - 'admin.oidcTitle': 'Single Sign-On (OIDC)', - 'admin.oidcSubtitle': 'Consenti l\'accesso tramite provider esterni come Google, Apple, Authentik o Keycloak.', - 'admin.oidcDisplayName': 'Nome Visualizzato', - 'admin.oidcIssuer': 'URL Emittente', - 'admin.oidcIssuerHint': 'L\'URL dell\'Emittente OpenID Connect del provider. es. https://accounts.google.com', - 'admin.oidcSaved': 'Configurazione OIDC salvata', - 'admin.oidcOnlyMode': 'Disabilita autenticazione con password', - 'admin.oidcOnlyModeHint': 'Se abilitato, è consentito solo l\'accesso SSO. L\'accesso basato su password e la registrazione sono bloccati.', - - // File Types - 'admin.fileTypes': 'Tipi di File Consentiti', - 'admin.fileTypesHint': 'Configura quali tipi di file gli utenti possono caricare.', - 'admin.fileTypesFormat': 'Estensioni separate da virgola (es. jpg,png,pdf,doc). Usa * per consentire tutti i tipi.', - 'admin.fileTypesSaved': 'Impostazioni dei tipi di file salvate', - // Packing Templates & Bag Tracking - 'admin.bagTracking.title': 'Tracciamento valigia', - 'admin.bagTracking.subtitle': 'Abilita il peso e l\'assegnazione della valigia per gli elementi della lista valigia', - 'admin.tabs.config': 'Configurazione', - 'admin.tabs.templates': 'Modelli lista valigia', - 'admin.packingTemplates.title': 'Modelli lista valigia', - 'admin.packingTemplates.subtitle': 'Crea liste valigia riutilizzabili per i tuoi viaggi', - 'admin.packingTemplates.create': 'Nuovo modello', - 'admin.packingTemplates.namePlaceholder': 'Nome modello (es. Vacanza al mare)', - 'admin.packingTemplates.empty': 'Ancora nessun modello creato', - 'admin.packingTemplates.items': 'elementi', - 'admin.packingTemplates.categories': 'categorie', - 'admin.packingTemplates.itemName': 'Nome elemento', - 'admin.packingTemplates.itemCategory': 'Categoria', - 'admin.packingTemplates.categoryName': 'Nome categoria (es. Abbigliamento)', - 'admin.packingTemplates.addCategory': 'Aggiungi categoria', - 'admin.packingTemplates.created': 'Modello creato', - 'admin.packingTemplates.deleted': 'Modello eliminato', - 'admin.packingTemplates.loadError': 'Impossibile caricare i modelli', - 'admin.packingTemplates.createError': 'Impossibile creare il modello', - 'admin.packingTemplates.deleteError': 'Impossibile eliminare il modello', - 'admin.packingTemplates.saveError': 'Impossibile salvare', - - // Addons - 'admin.tabs.addons': 'Moduli', - 'admin.addons.title': 'Moduli', - 'admin.addons.subtitle': 'Abilita o disabilita le funzionalità per personalizzare la tua esperienza TREK.', - 'admin.addons.catalog.packing.name': 'Lista valigia', - 'admin.addons.catalog.packing.description': 'Checklist per preparare la valigia per ogni viaggio', - 'admin.addons.catalog.budget.name': 'Budget', - 'admin.addons.catalog.budget.description': 'Tieni traccia delle spese e pianifica il budget del tuo viaggio', - 'admin.addons.catalog.documents.name': 'Documenti', - 'admin.addons.catalog.documents.description': 'Archivia e gestisci i documenti di viaggio', - 'admin.addons.catalog.vacay.name': 'Ferie', - 'admin.addons.catalog.vacay.description': 'Pianificatore personale delle ferie con vista calendario', - 'admin.addons.catalog.atlas.name': 'Atlante', - 'admin.addons.catalog.atlas.description': 'Mappa del mondo con paesi visitati e statistiche di viaggio', - 'admin.addons.catalog.collab.name': 'Collaborazione', - 'admin.addons.catalog.collab.description': 'Note, sondaggi e chat in tempo reale per la pianificazione del viaggio', - 'admin.addons.catalog.memories.name': 'Foto (Immich)', - 'admin.addons.catalog.memories.description': 'Condividi le foto del viaggio tramite la tua istanza Immich', - 'admin.addons.catalog.mcp.name': 'MCP', - 'admin.addons.catalog.mcp.description': 'Model Context Protocol per l\'integrazione di assistenti AI', - 'admin.addons.subtitleBefore': 'Abilita o disabilita le funzionalità per personalizzare la tua ', - 'admin.addons.subtitleAfter': ' esperienza.', - 'admin.addons.enabled': 'Abilitato', - 'admin.addons.disabled': 'Disabilitato', - 'admin.addons.type.trip': 'Viaggio', - 'admin.addons.type.global': 'Globale', - 'admin.addons.type.integration': 'Integrazione', - 'admin.addons.tripHint': 'Disponibile come scheda all\'interno di ciascun viaggio', - 'admin.addons.globalHint': 'Disponibile come sezione autonoma nella navigazione principale', - 'admin.addons.integrationHint': 'Servizi backend e integrazioni API senza pagina dedicata', - 'admin.addons.toast.updated': 'Modulo aggiornato', - 'admin.addons.toast.error': 'Impossibile aggiornare il modulo', - 'admin.addons.noAddons': 'Nessun modulo disponibile', - - // Weather info - 'admin.weather.title': 'Dati meteo', - 'admin.weather.badge': 'Dal 24 marzo 2026', - 'admin.weather.description': 'TREK utilizza Open-Meteo come fonte dei dati meteo. Open-Meteo è un servizio meteo gratuito e open-source — non è richiesta alcuna chiave API.', - 'admin.weather.forecast': 'Previsioni a 16 giorni', - 'admin.weather.forecastDesc': 'In precedenza 5 giorni (OpenWeatherMap)', - 'admin.weather.climate': 'Dati climatici storici', - 'admin.weather.climateDesc': 'Medie degli ultimi 85 anni per i giorni oltre le previsioni a 16 giorni', - 'admin.weather.requests': '10.000 richieste / giorno', - 'admin.weather.requestsDesc': 'Gratis, nessuna chiave API richiesta', - 'admin.weather.locationHint': 'Il meteo si basa sul primo luogo con coordinate di ogni giorno. Se a un giorno non è assegnato alcun luogo, viene utilizzato come riferimento un qualsiasi luogo dell\'elenco.', - - 'admin.tabs.audit': 'Log di audit', - - 'admin.audit.subtitle': 'Eventi sensibili di sicurezza e amministrazione (backup, utenti, 2FA, impostazioni).', - 'admin.audit.empty': 'Nessuna voce di audit.', - 'admin.audit.refresh': 'Aggiorna', - 'admin.audit.loadMore': 'Carica altro', - 'admin.audit.showing': '{count} caricati · {total} totali', - 'admin.audit.col.time': 'Ora', - 'admin.audit.col.user': 'Utente', - 'admin.audit.col.action': 'Azione', - 'admin.audit.col.resource': 'Risorsa', - 'admin.audit.col.ip': 'IP', - 'admin.audit.col.details': 'Dettagli', - - // MCP Tokens - 'admin.tabs.mcpTokens': 'Token MCP', - 'admin.mcpTokens.title': 'Token MCP', - 'admin.mcpTokens.subtitle': 'Gestisci i token API di tutti gli utenti', - 'admin.mcpTokens.owner': 'Proprietario', - 'admin.mcpTokens.tokenName': 'Nome token', - 'admin.mcpTokens.created': 'Creato', - 'admin.mcpTokens.lastUsed': 'Ultimo utilizzo', - 'admin.mcpTokens.never': 'Mai', - 'admin.mcpTokens.empty': 'Non sono ancora stati creati token MCP', - 'admin.mcpTokens.deleteTitle': 'Elimina token', - 'admin.mcpTokens.deleteMessage': 'Questo token verrà revocato immediatamente. L\'utente perderà l\'accesso MCP tramite questo token.', - 'admin.mcpTokens.deleteSuccess': 'Token eliminato', - 'admin.mcpTokens.deleteError': 'Impossibile eliminare il token', - 'admin.mcpTokens.loadError': 'Impossibile caricare i token', - - // GitHub - 'admin.tabs.github': 'GitHub', - 'admin.github.title': 'Cronologia rilasci', - 'admin.github.subtitle': 'Ultimi aggiornamenti da {repo}', - 'admin.github.latest': 'Ultimo', - 'admin.github.prerelease': 'Pre-release', - 'admin.github.showDetails': 'Mostra dettagli', - 'admin.github.hideDetails': 'Nascondi dettagli', - 'admin.github.loadMore': 'Carica altro', - 'admin.github.loading': 'Caricamento...', - 'admin.github.error': 'Impossibile caricare i rilasci', - 'admin.github.by': 'da', - 'admin.github.support': 'Mi aiuta a continuare a sviluppare TREK', - - 'admin.update.available': 'Aggiornamento disponibile', - 'admin.update.text': 'TREK {version} è disponibile. Stai eseguendo {current}.', - 'admin.update.button': 'Vedi su GitHub', - 'admin.update.install': 'Installa aggiornamento', - 'admin.update.confirmTitle': 'Installare l\'aggiornamento?', - 'admin.update.confirmText': 'TREK verrà aggiornato da {current} a {version}. Il server si riavvierà automaticamente in seguito.', - 'admin.update.dataInfo': 'Tutti i tuoi dati (viaggi, utenti, chiavi API, caricamenti, Ferie, Atlante, budget) saranno preservati.', - 'admin.update.warning': 'L\'app sarà temporaneamente non disponibile durante il riavvio.', - 'admin.update.confirm': 'Aggiorna ora', - 'admin.update.installing': 'Aggiornamento in corso…', - 'admin.update.success': 'Aggiornamento installato! Il server si sta riavviando…', - 'admin.update.failed': 'Aggiornamento non riuscito', - 'admin.update.backupHint': 'Ti consigliamo di creare un backup prima di aggiornare.', - 'admin.update.backupLink': 'Vai a Backup', - 'admin.update.howTo': 'Come aggiornare', - 'admin.update.dockerText': 'La tua istanza TREK è in esecuzione in Docker. Per aggiornare alla versione {version}, esegui i seguenti comandi sul tuo server:', - 'admin.update.reloadHint': 'Ricarica la pagina tra qualche secondo.', - - // Vacay addon - 'vacay.subtitle': 'Pianifica e gestisci i giorni di ferie', - 'vacay.settings': 'Impostazioni', - 'vacay.year': 'Anno', - 'vacay.addYear': 'Aggiungi anno', - 'vacay.removeYear': 'Rimuovi anno', - 'vacay.removeYearConfirm': 'Rimuovere {year}?', - 'vacay.removeYearHint': 'Tutte le voci delle ferie e le ferie aziendali di questo anno verranno eliminate in modo permanente.', - 'vacay.remove': 'Rimuovi', - 'vacay.persons': 'Persone', - 'vacay.noPersons': 'Nessuna persona aggiunta', - 'vacay.addPerson': 'Aggiungi persona', - 'vacay.editPerson': 'Modifica persona', - 'vacay.removePerson': 'Rimuovi persona', - 'vacay.removePersonConfirm': 'Rimuovere {name}?', - 'vacay.removePersonHint': 'Tutte le voci delle ferie per questa persona verranno eliminate in modo permanente.', - 'vacay.personName': 'Nome', - 'vacay.personNamePlaceholder': 'Inserisci nome', - 'vacay.color': 'Colore', - 'vacay.add': 'Aggiungi', - 'vacay.legend': 'Legenda', - 'vacay.publicHoliday': 'Festività pubblica', - 'vacay.companyHoliday': 'Ferie aziendali', - 'vacay.weekend': 'Weekend', - 'vacay.modeVacation': 'Ferie', - 'vacay.modeCompany': 'Ferie aziendali', - 'vacay.entitlement': 'Disponibilità', - 'vacay.entitlementDays': 'Giorni', - 'vacay.used': 'Usati', - 'vacay.remaining': 'Rimanenti', - 'vacay.carriedOver': 'dal {year}', - 'vacay.blockWeekends': 'Blocca weekend', - 'vacay.blockWeekendsHint': 'Impedisci le voci ferie nei giorni del weekend', - 'vacay.weekendDays': 'Giorni del weekend', - 'vacay.mon': 'Lun', - 'vacay.tue': 'Mar', - 'vacay.wed': 'Mer', - 'vacay.thu': 'Gio', - 'vacay.fri': 'Ven', - 'vacay.sat': 'Sab', - 'vacay.sun': 'Dom', - 'vacay.publicHolidays': 'Festività pubbliche', - 'vacay.publicHolidaysHint': 'Segna le festività pubbliche nel calendario', - 'vacay.selectCountry': 'Seleziona paese', - 'vacay.selectRegion': 'Seleziona regione (opzionale)', - 'vacay.addCalendar': 'Aggiungi calendario', - 'vacay.calendarLabel': 'Etichetta (opzionale)', - 'vacay.calendarColor': 'Colore', - 'vacay.noCalendars': 'Ancora nessun calendario delle festività aggiunto', - 'vacay.companyHolidays': 'Ferie aziendali', - 'vacay.companyHolidaysHint': 'Consenti di segnare giorni di ferie aziendali', - 'vacay.companyHolidaysNoDeduct': 'Le ferie aziendali non vengono conteggiate nei giorni di ferie.', - 'vacay.carryOver': 'Riporto', - 'vacay.carryOverHint': 'Riporta automaticamente i giorni di ferie rimanenti all\'anno successivo', - 'vacay.sharing': 'Condivisione', - 'vacay.sharingHint': 'Condividi il tuo piano ferie con altri utenti TREK', - 'vacay.owner': 'Proprietario', - 'vacay.shareEmailPlaceholder': 'Email dell\'utente TREK', - 'vacay.shareSuccess': 'Piano condiviso con successo', - 'vacay.shareError': 'Impossibile condividere il piano', - 'vacay.dissolve': 'Sciogli unione', - 'vacay.dissolveHint': 'Separa di nuovo i calendari. Le tue voci verranno mantenute.', - 'vacay.dissolveAction': 'Sciogli', - 'vacay.dissolved': 'Calendario separato', - 'vacay.fusedWith': 'Unito con', - 'vacay.you': 'tu', - 'vacay.noData': 'Nessun dato', - 'vacay.changeColor': 'Cambia colore', - 'vacay.inviteUser': 'Invita utente', - 'vacay.inviteHint': 'Invita un altro utente TREK a condividere un calendario ferie combinato.', - 'vacay.selectUser': 'Seleziona utente', - 'vacay.sendInvite': 'Invia invito', - 'vacay.inviteSent': 'Invito inviato', - 'vacay.inviteError': 'Impossibile inviare l\'invito', - 'vacay.pending': 'in attesa', - 'vacay.noUsersAvailable': 'Nessun utente disponibile', - 'vacay.accept': 'Accetta', - 'vacay.decline': 'Rifiuta', - 'vacay.acceptFusion': 'Accetta e unisci', - 'vacay.inviteTitle': 'Richiesta di unione', - 'vacay.inviteWantsToFuse': 'vuole condividere con te un calendario ferie.', - 'vacay.fuseInfo1': 'Entrambi vedrete tutte le voci ferie in un unico calendario condiviso.', - 'vacay.fuseInfo2': 'Entrambe le parti possono creare e modificare le voci reciproche.', - 'vacay.fuseInfo3': 'Entrambe le parti possono eliminare le voci e modificare le disponibilità ferie.', - 'vacay.fuseInfo4': 'Le impostazioni come festività pubbliche e ferie aziendali sono condivise.', - 'vacay.fuseInfo5': 'L\'unione può essere sciolta in qualsiasi momento da una delle due parti. Le tue voci verranno preservate.', - 'nav.myTrips': 'I miei viaggi', - - // Atlas addon - 'atlas.subtitle': 'La tua impronta di viaggio nel mondo', - 'atlas.countries': 'Paesi', - 'atlas.trips': 'Viaggi', - 'atlas.places': 'Luoghi', - 'atlas.unmark': 'Rimuovi', - 'atlas.confirmMark': 'Segnare questo paese come visitato?', - 'atlas.confirmUnmark': 'Rimuovere questo paese dalla tua lista dei visitati?', - 'atlas.markVisited': 'Segna come visitato', - 'atlas.markVisitedHint': 'Aggiungi questo paese alla tua lista dei visitati', - 'atlas.addToBucket': 'Aggiungi alla lista desideri', - 'atlas.addPoi': 'Aggiungi luogo', - 'atlas.bucketNamePlaceholder': 'Nome (paese, città, luogo...)', - 'atlas.month': 'Mese', - 'atlas.addToBucketHint': 'Salvalo come luogo che vuoi visitare', - 'atlas.bucketWhen': 'Quando pensi di visitarlo?', - 'atlas.statsTab': 'Statistiche', - 'atlas.bucketTab': 'Lista desideri', - 'atlas.addBucket': 'Aggiungi alla lista desideri', - 'atlas.bucketNamePlaceholder': 'Luogo o destinazione...', - 'atlas.bucketNotesPlaceholder': 'Note (opzionale)', - 'atlas.bucketEmpty': 'La tua lista desideri è vuota', - 'atlas.bucketEmptyHint': 'Aggiungi luoghi che sogni di visitare', - 'atlas.days': 'Giorni', - 'atlas.visitedCountries': 'Paesi visitati', - 'atlas.cities': 'Città', - 'atlas.noData': 'Ancora nessun dato di viaggio', - 'atlas.noDataHint': 'Crea un viaggio e aggiungi luoghi per vedere la tua mappa del mondo', - 'atlas.lastTrip': 'Ultimo viaggio', - 'atlas.nextTrip': 'Prossimo viaggio', - 'atlas.daysLeft': 'giorni rimasti', - 'atlas.streak': 'Serie', - 'atlas.year': 'anno', - 'atlas.years': 'anni', - 'atlas.yearInRow': 'anno consecutivo', - 'atlas.yearsInRow': 'anni consecutivi', - 'atlas.tripIn': 'viaggio in', - 'atlas.tripsIn': 'viaggi in', - 'atlas.since': 'dal', - 'atlas.europe': 'Europa', - 'atlas.asia': 'Asia', - 'atlas.northAmerica': 'Nord America', - 'atlas.southAmerica': 'Sud America', - 'atlas.africa': 'Africa', - 'atlas.oceania': 'Oceania', - 'atlas.other': 'Altro', - 'atlas.firstVisit': 'Primo viaggio', - 'atlas.lastVisitLabel': 'Ultimo viaggio', - 'atlas.tripSingular': 'Viaggio', - 'atlas.tripPlural': 'Viaggi', - 'atlas.placeVisited': 'Luogo visitato', - 'atlas.placesVisited': 'Luoghi visitati', - - // Trip Planner - 'trip.tabs.plan': 'Programma', - 'trip.tabs.reservations': 'Prenotazioni', - 'trip.tabs.reservationsShort': 'Pren.', - 'trip.tabs.packing': 'Lista valigia', - 'trip.tabs.packingShort': 'Valigia', - 'trip.tabs.budget': 'Budget', - 'trip.tabs.files': 'File', - 'trip.loading': 'Caricamento viaggio...', - 'trip.mobilePlan': 'Programma', - 'trip.mobilePlaces': 'Luoghi', - 'trip.toast.placeUpdated': 'Luogo aggiornato', - 'trip.toast.placeAdded': 'Luogo aggiunto', - 'trip.toast.placeDeleted': 'Luogo eliminato', - 'trip.toast.selectDay': 'Seleziona prima un giorno', - 'trip.toast.assignedToDay': 'Luogo assegnato al giorno', - 'trip.toast.reorderError': 'Impossibile riordinare', - 'trip.toast.reservationUpdated': 'Prenotazione aggiornata', - 'trip.toast.reservationAdded': 'Prenotazione aggiunta', - 'trip.toast.deleted': 'Eliminato', - 'trip.confirm.deletePlace': 'Sei sicuro di voler eliminare questo luogo?', - - // Day Plan Sidebar - 'dayplan.emptyDay': 'Nessun luogo programmato per questo giorno', - 'dayplan.addNote': 'Aggiungi nota', - 'dayplan.editNote': 'Modifica nota', - 'dayplan.noteAdd': 'Aggiungi nota', - 'dayplan.noteEdit': 'Modifica nota', - 'dayplan.noteTitle': 'Nota', - 'dayplan.noteSubtitle': 'Nota giornaliera', - 'dayplan.totalCost': 'Costo totale', - 'dayplan.days': 'Giorni', - 'dayplan.dayN': 'Giorno {n}', - 'dayplan.calculating': 'Calcolo in corso...', - 'dayplan.route': 'Percorso', - 'dayplan.optimize': 'Ottimizza', - 'dayplan.optimized': 'Percorso ottimizzato', - 'dayplan.routeError': 'Impossibile calcolare il percorso', - 'dayplan.toast.needTwoPlaces': 'Servono almeno due luoghi per l\'ottimizzazione del percorso', - 'dayplan.toast.routeOptimized': 'Percorso ottimizzato', - 'dayplan.toast.noGeoPlaces': 'Nessun luogo con coordinate trovato per il calcolo del percorso', - 'dayplan.confirmed': 'Confermata', - 'dayplan.pendingRes': 'In attesa', - 'dayplan.pdf': 'PDF', - 'dayplan.pdfTooltip': 'Esporta il programma del giorno come PDF', - 'dayplan.pdfError': 'Impossibile esportare il PDF', - 'dayplan.cannotReorderTransport': 'Le prenotazioni con un orario fisso non possono essere riordinate', - 'dayplan.confirmRemoveTimeTitle': 'Rimuovere l\'orario?', - 'dayplan.confirmRemoveTimeBody': 'Questo luogo ha un orario fisso ({time}). Spostarlo rimuoverà l\'orario e consentirà l\'ordinamento libero.', - 'dayplan.confirmRemoveTimeAction': 'Rimuovi orario e sposta', - 'dayplan.cannotDropOnTimed': 'Gli elementi non possono essere posizionati tra voci con orario fisso', - 'dayplan.cannotBreakChronology': 'Ciò interromperebbe l\'ordine cronologico degli elementi e delle prenotazioni pianificati', - - // Places Sidebar - 'places.addPlace': 'Aggiungi Luogo/Attività', - 'places.importGpx': 'Importa GPX', - 'places.gpxImported': '{count} luoghi importati da GPX', - 'places.urlResolved': 'Luogo importato dall\'URL', - 'places.gpxError': 'Importazione GPX non riuscita', - 'places.assignToDay': 'A quale giorno aggiungere?', - 'places.all': 'Tutti', - 'places.unplanned': 'Non pianificati', - 'places.search': 'Cerca luoghi...', - 'places.allCategories': 'Tutte le categorie', - 'places.categoriesSelected': 'categorie', - 'places.clearFilter': 'Cancella filtro', - 'places.count': '{count} luoghi', - 'places.countSingular': '1 luogo', - 'places.allPlanned': 'Tutti i luoghi sono programmati', - 'places.noneFound': 'Nessun luogo trovato', - 'places.editPlace': 'Modifica luogo', - 'places.formName': 'Nome', - 'places.formNamePlaceholder': 'es. Torre Eiffel', - 'places.formDescription': 'Descrizione', - 'places.formDescriptionPlaceholder': 'Breve descrizione...', - 'places.formAddress': 'Indirizzo', - 'places.formAddressPlaceholder': 'Via, Città, Paese', - 'places.formLat': 'Latitudine (es. 48.8566)', - 'places.formLng': 'Longitudine (es. 2.3522)', - 'places.formCategory': 'Categoria', - 'places.noCategory': 'Nessuna categoria', - 'places.categoryNamePlaceholder': 'Nome categoria', - 'places.formTime': 'Ora', - 'places.startTime': 'Inizio', - 'places.endTime': 'Fine', - 'places.endTimeBeforeStart': 'L\'ora di fine è precedente all\'ora di inizio', - 'places.timeCollision': 'Sovrapposizione di orario con:', - 'places.formWebsite': 'Sito web', - 'places.formNotesPlaceholder': 'Note personali...', - 'places.formReservation': 'Prenotazione', - 'places.reservationNotesPlaceholder': 'Note della prenotazione, numero di conferma...', - 'places.mapsSearchPlaceholder': 'Cerca luoghi...', - 'places.mapsSearchError': 'Impossibile cercare i luoghi.', - 'places.osmHint': 'Uso della ricerca OpenStreetMap (senza foto, orari di apertura o valutazioni). Aggiungi una chiave API Google nelle impostazioni per i dettagli completi.', - 'places.osmActive': 'Ricerca tramite OpenStreetMap (senza foto, valutazioni o orari di apertura). Aggiungi una chiave API Google nelle Impostazioni per dati avanzati.', - 'places.categoryCreateError': 'Impossibile creare la categoria', - 'places.nameRequired': 'Inserisci un nome', - 'places.saveError': 'Impossibile salvare', - // Place Inspector - 'inspector.opened': 'Aperto', - 'inspector.closed': 'Chiuso', - 'inspector.openingHours': 'Orari di apertura', - 'inspector.showHours': 'Mostra orari di apertura', - 'inspector.files': 'File', - 'inspector.filesCount': '{count} file', - 'inspector.removeFromDay': 'Rimuovi dal giorno', - 'inspector.addToDay': 'Aggiungi al giorno', - 'inspector.confirmedRes': 'Prenotazione confermata', - 'inspector.pendingRes': 'Prenotazione in attesa', - 'inspector.google': 'Apri in Google Maps', - 'inspector.website': 'Apri sito web', - 'inspector.addRes': 'Prenotazione', - 'inspector.editRes': 'Modifica prenotazione', - 'inspector.participants': 'Partecipanti', - - // Reservations - 'reservations.title': 'Prenotazioni', - 'reservations.empty': 'Ancora nessuna prenotazione', - 'reservations.emptyHint': 'Aggiungi prenotazioni per voli, alloggi e altro', - 'reservations.add': 'Aggiungi prenotazione', - 'reservations.addManual': 'Prenotazione manuale', - 'reservations.placeHint': 'Suggerimento: è meglio creare le prenotazioni direttamente da un luogo per collegarle al tuo programma del giorno.', - 'reservations.confirmed': 'Confermata', - 'reservations.pending': 'In attesa', - 'reservations.summary': '{confirmed} confermate, {pending} in attesa', - 'reservations.fromPlan': 'Dal programma', - 'reservations.showFiles': 'Mostra file', - 'reservations.editTitle': 'Modifica prenotazione', - 'reservations.status': 'Stato', - 'reservations.datetime': 'Data e ora', - 'reservations.startTime': 'Ora di inizio', - 'reservations.endTime': 'Ora di fine', - 'reservations.date': 'Data', - 'reservations.time': 'Ora', - 'reservations.timeAlt': 'Ora (alternativa, es. 19:30)', - 'reservations.notes': 'Note', - 'reservations.notesPlaceholder': 'Note aggiuntive...', - 'reservations.meta.airline': 'Compagnia aerea', - 'reservations.meta.flightNumber': 'N. volo', - 'reservations.meta.from': 'Da', - 'reservations.meta.to': 'A', - 'reservations.meta.trainNumber': 'N. treno', - 'reservations.meta.platform': 'Binario', - 'reservations.meta.seat': 'Posto', - 'reservations.meta.checkIn': 'Check-in', - 'reservations.meta.checkOut': 'Check-out', - 'reservations.meta.linkAccommodation': 'Alloggio', - 'reservations.meta.pickAccommodation': 'Collega a un alloggio', - 'reservations.meta.noAccommodation': 'Nessuno', - 'reservations.meta.hotelPlace': 'Alloggio', - 'reservations.meta.pickHotel': 'Seleziona alloggio', - 'reservations.meta.fromDay': 'Da', - 'reservations.meta.toDay': 'A', - 'reservations.meta.selectDay': 'Seleziona giorno', - 'reservations.type.flight': 'Volo', - 'reservations.type.hotel': 'Alloggio', - 'reservations.type.restaurant': 'Ristorante', - 'reservations.type.train': 'Treno', - 'reservations.type.car': 'Auto a noleggio', - 'reservations.type.cruise': 'Crociera', - 'reservations.type.event': 'Evento', - 'reservations.type.tour': 'Tour', - 'reservations.type.other': 'Altro', - 'reservations.confirm.delete': 'Sei sicuro di voler eliminare la prenotazione "{name}"?', - 'reservations.confirm.deleteTitle': 'Eliminare la prenotazione?', - 'reservations.confirm.deleteBody': '"{name}" verrà eliminato in modo permanente.', - 'reservations.toast.updated': 'Prenotazione aggiornata', - 'reservations.toast.removed': 'Prenotazione eliminata', - 'reservations.toast.fileUploaded': 'File caricato', - 'reservations.toast.uploadError': 'Impossibile caricare', - 'reservations.newTitle': 'Nuova prenotazione', - 'reservations.bookingType': 'Tipo di prenotazione', - 'reservations.titleLabel': 'Titolo', - 'reservations.titlePlaceholder': 'es. Lufthansa LH123, Hotel Adlon, ...', - 'reservations.locationAddress': 'Posizione / Indirizzo', - 'reservations.locationPlaceholder': 'Indirizzo, aeroporto, hotel...', - 'reservations.confirmationCode': 'Codice prenotazione', - 'reservations.confirmationPlaceholder': 'es. ABC12345', - 'reservations.day': 'Giorno', - 'reservations.noDay': 'Nessun giorno', - 'reservations.place': 'Luogo', - 'reservations.noPlace': 'Nessun luogo', - 'reservations.pendingSave': 'verrà salvato…', - 'reservations.uploading': 'Caricamento...', - 'reservations.attachFile': 'Allega file', - 'reservations.linkExisting': 'Collega file esistente', - 'reservations.toast.saveError': 'Impossibile salvare', - 'reservations.toast.updateError': 'Impossibile aggiornare', - 'reservations.toast.deleteError': 'Impossibile eliminare', - 'reservations.confirm.remove': 'Rimuovere la prenotazione per "{name}"?', - 'reservations.linkAssignment': 'Collega all\'assegnazione del giorno', - 'reservations.pickAssignment': 'Seleziona un\'assegnazione dal tuo programma...', - 'reservations.noAssignment': 'Nessun collegamento (autonomo)', - - // Budget - 'budget.title': 'Budget', - 'budget.emptyTitle': 'Ancora nessun budget creato', - 'budget.emptyText': 'Crea categorie e voci per pianificare il budget del tuo viaggio', - 'budget.emptyPlaceholder': 'Inserisci nome categoria...', - 'budget.createCategory': 'Crea categoria', - 'budget.category': 'Categoria', - 'budget.categoryName': 'Nome categoria', - 'budget.table.name': 'Nome', - 'budget.table.total': 'Totale', - 'budget.table.persons': 'Persone', - 'budget.table.days': 'Giorni', - 'budget.table.perPerson': 'Per persona', - 'budget.table.perDay': 'Per giorno', - 'budget.table.perPersonDay': 'P. p / gio.', - 'budget.table.note': 'Nota', - 'budget.newEntry': 'Nuova voce', - 'budget.defaultEntry': 'Nuova voce', - 'budget.defaultCategory': 'Nuova categoria', - 'budget.total': 'Totale', - 'budget.totalBudget': 'Budget totale', - 'budget.byCategory': 'Per categoria', - 'budget.editTooltip': 'Clicca per modificare', - 'budget.confirm.deleteCategory': 'Sei sicuro di voler eliminare la categoria "{name}" con {count} voci?', - 'budget.deleteCategory': 'Elimina categoria', - 'budget.perPerson': 'Per persona', - 'budget.paid': 'Pagato', - 'budget.open': 'Aperto', - 'budget.noMembers': 'Nessun membro assegnato', - 'budget.settlement': 'Regolamento', - 'budget.settlementInfo': 'Clicca sull\'avatar di un membro su una voce di budget per contrassegnarlo in verde — significa che ha pagato. Il regolamento mostra poi chi deve quanto a chi.', - 'budget.netBalances': 'Saldi netti', - - // Files - 'files.title': 'File', - 'files.count': '{count} file', - 'files.countSingular': '1 file', - 'files.uploaded': '{count} caricati', - 'files.uploadError': 'Caricamento non riuscito', - 'files.dropzone': 'Trascina qui i file', - 'files.dropzoneHint': 'oppure clicca per sfogliare', - 'files.allowedTypes': 'Immagini, PDF, DOC, DOCX, XLS, XLSX, TXT, CSV · Max 50 MB', - 'files.uploading': 'Caricamento...', - 'files.filterAll': 'Tutti', - 'files.filterPdf': 'PDF', - 'files.filterImages': 'Immagini', - 'files.filterDocs': 'Documenti', - 'files.filterCollab': 'Note Collaborazione', - 'files.sourceCollab': 'Da Note Collaborazione', - 'files.empty': 'Ancora nessun file', - 'files.emptyHint': 'Carica file per allegarli al tuo viaggio', - 'files.openTab': 'Apri in una nuova scheda', - 'files.confirm.delete': 'Sei sicuro di voler eliminare questo file?', - 'files.toast.deleted': 'File eliminato', - 'files.toast.deleteError': 'Impossibile eliminare il file', - 'files.sourcePlan': 'Programma giornaliero', - 'files.sourceBooking': 'Prenotazione', - 'files.attach': 'Allega', - 'files.pasteHint': 'Puoi anche incollare immagini dagli appunti (Ctrl+V)', - 'files.trash': 'Cestino', - 'files.trashEmpty': 'Il cestino è vuoto', - 'files.emptyTrash': 'Svuota cestino', - 'files.restore': 'Ripristina', - 'files.star': 'Aggiungi ai preferiti', - 'files.unstar': 'Rimuovi dai preferiti', - 'files.assign': 'Assegna', - 'files.assignTitle': 'Assegna file', - 'files.assignPlace': 'Luogo', - 'files.assignBooking': 'Prenotazione', - 'files.unassigned': 'Non assegnato', - 'files.unlink': 'Rimuovi collegamento', - 'files.toast.trashed': 'Spostato nel cestino', - 'files.toast.restored': 'File ripristinato', - 'files.toast.trashEmptied': 'Cestino svuotato', - 'files.toast.assigned': 'File assegnato', - 'files.toast.assignError': 'Assegnazione fallita', - 'files.toast.restoreError': 'Ripristino fallito', - 'files.confirm.permanentDelete': 'Eliminare questo file in modo permanente? Questa operazione non può essere annullata.', - 'files.confirm.emptyTrash': 'Eliminare in modo permanente tutti i file nel cestino? Questa operazione non può essere annullata.', - 'files.noteLabel': 'Nota', - 'files.notePlaceholder': 'Aggiungi una nota...', - - // Packing - 'packing.title': 'Lista valigia', - 'packing.empty': 'La lista valigia è vuota', - 'packing.import': 'Importa', - 'packing.importTitle': 'Importa lista valigia', - 'packing.importHint': 'Un elemento per riga. Formato: Categoria, Nome, Peso in g (opzionale), Borsa (opzionale), checked/unchecked (opzionale)', - 'packing.importPlaceholder': 'Igiene, Spazzolino\nAbbigliamento, Magliette, 200\nDocumenti, Passaporto, , Bagaglio a mano\nElettronica, Caricabatterie, 50, Valigia, checked', - 'packing.importCsv': 'Carica CSV/TXT', - 'packing.importAction': 'Importa {count}', - 'packing.importSuccess': '{count} elementi importati', - 'packing.importError': 'Importazione non riuscita', - 'packing.importEmpty': 'Nessun elemento da importare', - 'packing.progress': '{packed} di {total} in valigia ({percent}%)', - 'packing.clearChecked': 'Rimuovi {count} spuntati', - 'packing.clearCheckedShort': 'Rimuovi {count}', - 'packing.suggestions': 'Suggerimenti', - 'packing.suggestionsTitle': 'Aggiungi suggerimenti', - 'packing.allSuggested': 'Tutti i suggerimenti aggiunti', - 'packing.allPacked': 'Tutto in valigia!', - 'packing.addPlaceholder': 'Aggiungi nuovo elemento...', - 'packing.categoryPlaceholder': 'Categoria...', - 'packing.filterAll': 'Tutti', - 'packing.filterOpen': 'Da fare', - 'packing.filterDone': 'Fatto', - 'packing.emptyTitle': 'La lista valigia è vuota', - 'packing.emptyHint': 'Aggiungi elementi o usa i suggerimenti', - 'packing.emptyFiltered': 'Nessun elemento corrisponde a questo filtro', - 'packing.menuRename': 'Rinomina', - 'packing.menuCheckAll': 'Seleziona tutti', - 'packing.menuUncheckAll': 'Deseleziona tutti', - 'packing.menuDeleteCat': 'Elimina categoria', - 'packing.assignUser': 'Assegna utente', - 'packing.noMembers': 'Nessun membro del viaggio', - 'packing.addItem': 'Aggiungi elemento', - 'packing.addItemPlaceholder': 'Nome elemento...', - 'packing.addCategory': 'Aggiungi categoria', - 'packing.newCategoryPlaceholder': 'Nome categoria (es. Abbigliamento)', - 'packing.applyTemplate': 'Applica modello', - 'packing.template': 'Modello', - 'packing.templateApplied': '{count} elementi aggiunti dal modello', - 'packing.templateError': 'Impossibile applicare il modello', - 'packing.bags': 'Valigie', - 'packing.noBag': 'Non assegnato', - 'packing.totalWeight': 'Peso totale', - 'packing.bagName': 'Nome valigia...', - 'packing.addBag': 'Aggiungi valigia', - 'packing.changeCategory': 'Cambia categoria', - 'packing.confirm.clearChecked': 'Sei sicuro di voler rimuovere {count} elementi spuntati?', - 'packing.confirm.deleteCat': 'Sei sicuro di voler eliminare la categoria "{name}" con {count} elementi?', - 'packing.defaultCategory': 'Altro', - 'packing.toast.saveError': 'Impossibile salvare', - 'packing.toast.deleteError': 'Impossibile eliminare', - 'packing.toast.renameError': 'Impossibile rinominare', - 'packing.toast.addError': 'Impossibile aggiungere', - - // Packing suggestions - 'packing.suggestions.items': [ - { name: 'Passaporto', category: 'Documenti' }, - { name: 'Carta d\'identità', category: 'Documenti' }, - { name: 'Assicurazione di viaggio', category: 'Documenti' }, - { name: 'Biglietti aerei', category: 'Documenti' }, - { name: 'Carta di credito', category: 'Finanze' }, - { name: 'Contanti', category: 'Finanze' }, - { name: 'Visto', category: 'Documenti' }, - { name: 'Magliette', category: 'Abbigliamento' }, - { name: 'Pantaloni', category: 'Abbigliamento' }, - { name: 'Intimo', category: 'Abbigliamento' }, - { name: 'Calzini', category: 'Abbigliamento' }, - { name: 'Giacca', category: 'Abbigliamento' }, - { name: 'Pigiama', category: 'Abbigliamento' }, - { name: 'Costume da bagno', category: 'Abbigliamento' }, - { name: 'Giacca a vento', category: 'Abbigliamento' }, - { name: 'Scarpe comode', category: 'Abbigliamento' }, - { name: 'Spazzolino da denti', category: 'Igiene personale' }, - { name: 'Dentifricio', category: 'Igiene personale' }, - { name: 'Shampoo', category: 'Igiene personale' }, - { name: 'Deodorante', category: 'Igiene personale' }, - { name: 'Crema solare', category: 'Igiene personale' }, - { name: 'Rasoio', category: 'Igiene personale' }, - { name: 'Caricabatterie', category: 'Elettronica' }, - { name: 'Power bank', category: 'Elettronica' }, - { name: 'Cuffie', category: 'Elettronica' }, - { name: 'Adattatore da viaggio', category: 'Elettronica' }, - { name: 'Macchina fotografica', category: 'Elettronica' }, - { name: 'Antidolorifici', category: 'Salute' }, - { name: 'Cerotti', category: 'Salute' }, - { name: 'Disinfettante', category: 'Salute' }, - ], - - // Members / Sharing - 'members.shareTrip': 'Condividi viaggio', - 'members.inviteUser': 'Invita utente', - 'members.selectUser': 'Seleziona utente...', - 'members.invite': 'Invita', - 'members.allHaveAccess': 'Tutti gli utenti hanno già accesso.', - 'members.access': 'Accesso', - 'members.person': 'persona', - 'members.persons': 'persone', - 'members.you': 'tu', - 'members.owner': 'Proprietario', - 'members.leaveTrip': 'Abbandona viaggio', - 'members.removeAccess': 'Rimuovi accesso', - 'members.confirmLeave': 'Abbandonare il viaggio? Perderai l\'accesso.', - 'members.confirmRemove': 'Rimuovere l\'accesso per questo utente?', - 'members.loadError': 'Impossibile caricare i membri', - 'members.added': 'aggiunto', - 'members.addError': 'Impossibile aggiungere', - 'members.removed': 'Membro rimosso', - 'members.removeError': 'Impossibile rimuovere', - - // Categories (Admin) - 'categories.title': 'Categorie', - 'categories.subtitle': 'Gestisci le categorie per i luoghi', - 'categories.new': 'Nuova categoria', - 'categories.empty': 'Ancora nessuna categoria', - 'categories.namePlaceholder': 'Nome categoria', - 'categories.icon': 'Icona', - 'categories.color': 'Colore', - 'categories.customColor': 'Scegli colore personalizzato', - 'categories.preview': 'Anteprima', - 'categories.defaultName': 'Categoria', - 'categories.update': 'Aggiorna', - 'categories.create': 'Crea', - 'categories.confirm.delete': 'Eliminare la categoria? I luoghi in questa categoria non verranno eliminati.', - 'categories.toast.loadError': 'Impossibile caricare le categorie', - 'categories.toast.nameRequired': 'Inserisci un nome', - 'categories.toast.updated': 'Categoria aggiornata', - 'categories.toast.created': 'Categoria creata', - 'categories.toast.saveError': 'Impossibile salvare', - 'categories.toast.deleted': 'Categoria eliminata', - 'categories.toast.deleteError': 'Impossibile eliminare', - - // Backup (Admin) - 'backup.title': 'Backup dati', - 'backup.subtitle': 'Database e tutti i file caricati', - 'backup.refresh': 'Aggiorna', - 'backup.upload': 'Carica backup', - 'backup.uploading': 'Caricamento...', - 'backup.create': 'Crea backup', - 'backup.creating': 'Creazione...', - 'backup.empty': 'Ancora nessun backup', - 'backup.createFirst': 'Crea primo backup', - 'backup.download': 'Scarica', - 'backup.restore': 'Ripristina', - 'backup.confirm.restore': 'Ripristinare il backup "{name}"?\n\nTutti i dati attuali verranno sostituiti con il backup.', - 'backup.confirm.uploadRestore': 'Scaricare e ripristinare il file di backup "{name}"?\n\nTutti i dati attuali verranno sovrascritti.', - 'backup.confirm.delete': 'Eliminare il backup "{name}"?', - 'backup.toast.loadError': 'Impossibile caricare i backup', - 'backup.toast.created': 'Backup creato con successo', - 'backup.toast.createError': 'Impossibile creare il backup', - 'backup.toast.restored': 'Backup ripristinato. La pagina verrà ricaricata...', - 'backup.toast.restoreError': 'Impossibile ripristinare', - 'backup.toast.uploadError': 'Impossibile caricare', - 'backup.toast.deleted': 'Backup eliminato', - 'backup.toast.deleteError': 'Impossibile eliminare', - 'backup.toast.downloadError': 'Download non riuscito', - 'backup.toast.settingsSaved': 'Impostazioni auto-backup salvate', - 'backup.toast.settingsError': 'Impossibile salvare le impostazioni', - 'backup.auto.title': 'Auto-Backup', - 'backup.auto.subtitle': 'Backup automatico pianificato', - 'backup.auto.enable': 'Abilita auto-backup', - 'backup.auto.enableHint': 'I backup verranno creati automaticamente in base alla pianificazione scelta', - 'backup.auto.interval': 'Intervallo', - 'backup.auto.hour': 'Esegui all\'ora', - 'backup.auto.hourHint': 'Ora locale del server (formato {format})', - 'backup.auto.dayOfWeek': 'Giorno della settimana', - 'backup.auto.dayOfMonth': 'Giorno del mese', - 'backup.auto.dayOfMonthHint': 'Limitato a 1–28 per compatibilità con tutti i mesi', - 'backup.auto.scheduleSummary': 'Pianificazione', - 'backup.auto.summaryDaily': 'Ogni giorno alle {hour}:00', - 'backup.auto.summaryWeekly': 'Ogni {day} alle {hour}:00', - 'backup.auto.summaryMonthly': 'Giorno {day} di ogni mese alle {hour}:00', - 'backup.auto.envLocked': 'Docker', - 'backup.auto.envLockedHint': 'L\'auto-backup è configurato tramite variabili d\'ambiente Docker. Per modificare queste impostazioni, aggiorna il tuo docker-compose.yml e riavvia il container.', - 'backup.auto.copyEnv': 'Copia variabili env Docker', - 'backup.auto.envCopied': 'Variabili env Docker copiate negli appunti', - 'backup.auto.keepLabel': 'Elimina i vecchi backup dopo', - 'backup.dow.sunday': 'Dom', - 'backup.dow.monday': 'Lun', - 'backup.dow.tuesday': 'Mar', - 'backup.dow.wednesday': 'Mer', - 'backup.dow.thursday': 'Gio', - 'backup.dow.friday': 'Ven', - 'backup.dow.saturday': 'Sab', - 'backup.interval.hourly': 'Ogni ora', - 'backup.interval.daily': 'Giornaliero', - 'backup.interval.weekly': 'Settimanale', - 'backup.interval.monthly': 'Mensile', - 'backup.keep.1day': '1 giorno', - 'backup.keep.3days': '3 giorni', - 'backup.keep.7days': '7 giorni', - 'backup.keep.14days': '14 giorni', - 'backup.keep.30days': '30 giorni', - 'backup.keep.forever': 'Conserva per sempre', - - // Photos - 'photos.allDays': 'Tutti i giorni', - 'photos.noPhotos': 'Ancora nessuna foto', - 'photos.uploadHint': 'Carica le foto del tuo viaggio', - 'photos.clickToSelect': 'o clicca per selezionare', - 'photos.linkPlace': 'Collega luogo', - 'photos.noPlace': 'Nessun luogo', - 'photos.uploadN': 'Caricamento di {n} foto', - - // Backup restore modal - 'backup.restoreConfirmTitle': 'Ripristinare il backup?', - 'backup.restoreWarning': 'Tutti i dati attuali (viaggi, luoghi, utenti, caricamenti) verranno sostituiti in modo permanente dal backup. Questa azione non può essere annullata.', - 'backup.restoreTip': 'Suggerimento: Crea un backup dello stato attuale prima di ripristinare.', - 'backup.restoreConfirm': 'Sì, ripristina', - - // PDF - 'pdf.travelPlan': 'Programma di viaggio', - 'pdf.planned': 'Programmato', - 'pdf.costLabel': 'Costo EUR', - 'pdf.preview': 'Anteprima PDF', - 'pdf.saveAsPdf': 'Salva come PDF', - - // Planner - 'planner.places': 'Luoghi', - 'planner.bookings': 'Prenotazioni', - 'planner.packingList': 'Lista valigia', - 'planner.documents': 'Documenti', - 'planner.dayPlan': 'Programma giornaliero', - 'planner.reservations': 'Prenotazioni', - 'planner.minTwoPlaces': 'Servono almeno 2 luoghi con coordinate', - 'planner.noGeoPlaces': 'Nessun luogo con coordinate disponibile', - 'planner.routeCalculated': 'Percorso calcolato', - 'planner.routeCalcFailed': 'Il percorso non è stato calcolato', - 'planner.routeError': 'Errore nel calcolo del percorso', - 'planner.routeOptimized': 'Percorso ottimizzato', - 'planner.reservationUpdated': 'Prenotazione aggiornata', - 'planner.reservationAdded': 'Prenotazione aggiunta', - 'planner.confirmDeleteReservation': 'Eliminare la prenotazione?', - 'planner.reservationDeleted': 'Prenotazione eliminata', - 'planner.days': 'Giorni', - 'planner.allPlaces': 'Tutti i luoghi', - 'planner.totalPlaces': '{n} luoghi in totale', - 'planner.noDaysPlanned': 'Nessun giorno ancora programmato', - 'planner.editTrip': 'Modifica viaggio \u2192', - 'planner.placeOne': '1 luogo', - 'planner.placeN': '{n} luoghi', - 'planner.addNote': 'Aggiungi nota', - 'planner.noEntries': 'Nessuna voce per questo giorno', - 'planner.addPlace': 'Aggiungi luogo/attività', - 'planner.addPlaceShort': '+ Aggiungi luogo/attività', - 'planner.resPending': 'Prenotazione in attesa \u00B7 ', - 'planner.resConfirmed': 'Prenotazione confermata \u00B7 ', - 'planner.notePlaceholder': 'Nota\u2026', - 'planner.noteTimePlaceholder': 'Ora (opzionale)', - 'planner.noteExamplePlaceholder': 'es. S3 alle 14:30 dalla stazione centrale, traghetto dal molo 7, pausa pranzo\u2026', - 'planner.totalCost': 'Costo totale', - 'planner.searchPlaces': 'Cerca luoghi\u2026', - 'planner.allCategories': 'Tutte le categorie', - 'planner.noPlacesFound': 'Nessun luogo trovato', - 'planner.addFirstPlace': 'Aggiungi primo luogo', - 'planner.noReservations': 'Nessuna prenotazione', - 'planner.addFirstReservation': 'Aggiungi prima prenotazione', - 'planner.new': 'Nuovo', - 'planner.addToDay': '+ Giorno', - 'planner.calculating': 'Calcolo in corso\u2026', - 'planner.route': 'Percorso', - 'planner.optimize': 'Ottimizza', - 'planner.openGoogleMaps': 'Apri in Google Maps', - 'planner.selectDayHint': 'Seleziona un giorno dall\'elenco a sinistra per vedere il programma', - 'planner.noPlacesForDay': 'Ancora nessun luogo per questo giorno', - 'planner.addPlacesLink': 'Aggiungi luoghi \u2192', - 'planner.minTotal': 'min. totali', - 'planner.noReservation': 'Nessuna prenotazione', - 'planner.removeFromDay': 'Rimuovi dal giorno', - 'planner.addToThisDay': 'Aggiungi al giorno', - 'planner.overview': 'Panoramica', - 'planner.noDays': 'Ancora nessun giorno', - 'planner.editTripToAddDays': 'Modifica viaggio per aggiungere giorni', - 'planner.dayCount': '{n} Giorni', - 'planner.clickToUnlock': 'Clicca per sbloccare', - 'planner.keepPosition': 'Mantieni la posizione durante l\'ottimizzazione del percorso', - 'planner.dayDetails': 'Dettagli del giorno', - 'planner.dayN': 'Giorno {n}', - - // Dashboard Stats - 'stats.countries': 'Paesi', - 'stats.cities': 'Città', - 'stats.trips': 'Viaggi', - 'stats.places': 'Luoghi', - 'stats.worldProgress': 'Progresso nel mondo', - 'stats.visited': 'visitati', - 'stats.remaining': 'rimanenti', - 'stats.visitedCountries': 'Paesi visitati', - - // Day Detail Panel - 'day.precipProb': 'Probabilità di pioggia', - 'day.precipitation': 'Precipitazioni', - 'day.wind': 'Vento', - 'day.sunrise': 'Alba', - 'day.sunset': 'Tramonto', - 'day.hourlyForecast': 'Previsione oraria', - 'day.climateHint': 'Medie storiche \u2014 previsioni reali disponibili entro 16 giorni da questa data.', - 'day.noWeather': 'Nessun dato meteo disponibile. Aggiungi un luogo con coordinate.', - 'day.overview': 'Panoramica giornaliera', - 'day.accommodation': 'Alloggio', - 'day.addAccommodation': 'Aggiungi alloggio', - 'day.hotelDayRange': 'Applica ai giorni', - 'day.noPlacesForHotel': 'Aggiungi prima i luoghi al tuo viaggio', - 'day.allDays': 'Tutti', - 'day.checkIn': 'Check-in', - 'day.checkOut': 'Check-out', - 'day.confirmation': 'Conferma', - 'day.editAccommodation': 'Modifica alloggio', - 'day.reservations': 'Prenotazioni', - - // Photos / Immich - 'memories.title': 'Foto', - 'memories.notConnected': 'Immich non connesso', - 'memories.notConnectedHint': 'Connetti la tua istanza Immich nelle Impostazioni per vedere qui le foto del tuo viaggio.', - 'memories.noDates': 'Aggiungi le date al tuo viaggio per caricare le foto.', - 'memories.noPhotos': 'Nessuna foto trovata', - 'memories.noPhotosHint': 'Nessuna foto trovata in Immich per l\'intervallo di date di questo viaggio.', - 'memories.photosFound': 'foto', - 'memories.fromOthers': 'da altri', - 'memories.sharePhotos': 'Condividi foto', - 'memories.sharing': 'Condivisione', - 'memories.reviewTitle': 'Rivedi le tue foto', - 'memories.reviewHint': 'Clicca sulle foto per escluderle dalla condivisione.', - 'memories.shareCount': 'Condividi {count} foto', - 'memories.immichUrl': 'URL Server Immich', - 'memories.immichApiKey': 'Chiave API', - 'memories.testConnection': 'Test connessione', - 'memories.connected': 'Connesso', - 'memories.disconnected': 'Non connesso', - 'memories.connectionSuccess': 'Connesso a Immich', - 'memories.connectionError': 'Impossibile connettersi a Immich', - 'memories.saved': 'Impostazioni Immich salvate', - 'memories.addPhotos': 'Aggiungi foto', - 'memories.selectPhotos': 'Seleziona foto da Immich', - 'memories.selectHint': 'Tocca le foto per selezionarle.', - 'memories.selected': 'selezionate', - 'memories.addSelected': 'Aggiungi {count} foto', - 'memories.alreadyAdded': 'Aggiunta', - 'memories.private': 'Privato', - 'memories.stopSharing': 'Interrompi condivisione', - 'memories.oldest': 'Prima le più vecchie', - 'memories.newest': 'Prima le più recenti', - 'memories.allLocations': 'Tutte le posizioni', - 'memories.tripDates': 'Date del viaggio', - 'memories.allPhotos': 'Tutte le foto', - 'memories.confirmShareTitle': 'Condividere con i membri del viaggio?', - 'memories.confirmShareHint': '{count} foto saranno visibili a tutti i membri di questo viaggio. Potrai rendere private le singole foto in seguito.', - 'memories.confirmShareButton': 'Condividi foto', - - // Collab Addon - 'collab.tabs.chat': 'Chat', - 'collab.tabs.notes': 'Note', - 'collab.tabs.polls': 'Sondaggi', - 'collab.whatsNext.title': "Cosa c'è dopo", - 'collab.whatsNext.today': 'Oggi', - 'collab.whatsNext.tomorrow': 'Domani', - 'collab.whatsNext.empty': 'Nessuna attività imminente', - 'collab.whatsNext.until': 'a', - 'collab.whatsNext.emptyHint': 'Le attività con orari appariranno qui', - 'collab.chat.send': 'Invia', - 'collab.chat.placeholder': 'Scrivi un messaggio...', - 'collab.chat.empty': 'Inizia la conversazione', - 'collab.chat.emptyHint': 'I messaggi sono condivisi con tutti i membri del viaggio', - 'collab.chat.emptyDesc': 'Condividi idee, programmi e aggiornamenti con il tuo gruppo di viaggio', - 'collab.chat.today': 'Oggi', - 'collab.chat.yesterday': 'Ieri', - 'collab.chat.deletedMessage': 'ha eliminato un messaggio', - 'collab.chat.loadMore': 'Carica messaggi precedenti', - 'collab.chat.justNow': 'ora', - 'collab.chat.minutesAgo': '{n}m fa', - 'collab.chat.hoursAgo': '{n}h fa', - 'collab.notes.title': 'Note', - 'collab.notes.new': 'Nuova nota', - 'collab.notes.empty': 'Ancora nessuna nota', - 'collab.notes.emptyHint': 'Inizia a raccogliere idee e programmi', - 'collab.notes.all': 'Tutte', - 'collab.notes.titlePlaceholder': 'Titolo della nota', - 'collab.notes.contentPlaceholder': 'Scrivi qualcosa...', - 'collab.notes.categoryPlaceholder': 'Categoria', - 'collab.notes.newCategory': 'Nuova categoria...', - 'collab.notes.category': 'Categoria', - 'collab.notes.noCategory': 'Nessuna categoria', - 'collab.notes.color': 'Colore', - 'collab.notes.save': 'Salva', - 'collab.notes.cancel': 'Annulla', - 'collab.notes.edit': 'Modifica', - 'collab.notes.delete': 'Elimina', - 'collab.notes.pin': 'Fissa', - 'collab.notes.unpin': 'Rimuovi', - 'collab.notes.daysAgo': '{n}g fa', - 'collab.notes.categorySettings': 'Gestisci categorie', - 'collab.notes.create': 'Crea', - 'collab.notes.website': 'Sito web', - 'collab.notes.websitePlaceholder': 'https://...', - 'collab.notes.attachFiles': 'Allega file', - 'collab.notes.noCategoriesYet': 'Ancora nessuna categoria', - 'collab.notes.emptyDesc': 'Crea una nota per iniziare', - 'collab.polls.title': 'Sondaggi', - 'collab.polls.new': 'Nuovo sondaggio', - 'collab.polls.empty': 'Ancora nessun sondaggio', - 'collab.polls.emptyHint': 'Chiedi al gruppo e votate insieme', - 'collab.polls.question': 'Domanda', - 'collab.polls.questionPlaceholder': 'Cosa dovremmo fare?', - 'collab.polls.addOption': '+ Aggiungi opzione', - 'collab.polls.optionPlaceholder': 'Opzione {n}', - 'collab.polls.create': 'Crea sondaggio', - 'collab.polls.close': 'Chiudi', - 'collab.polls.closed': 'Chiuso', - 'collab.polls.votes': '{n} voti', - 'collab.polls.vote': '{n} voto', - 'collab.polls.multipleChoice': 'Scelta multipla', - 'collab.polls.multiChoice': 'Scelta multipla', - 'collab.polls.deadline': 'Scadenza', - 'collab.polls.option': 'Opzione', - 'collab.polls.options': 'Opzioni', - 'collab.polls.delete': 'Elimina', - 'collab.polls.closedSection': 'Chiusi', -} - +const it: Record = { + // Common + 'common.save': 'Salva', + 'common.cancel': 'Annulla', + 'common.delete': 'Elimina', + 'common.edit': 'Modifica', + 'common.add': 'Aggiungi', + 'common.loading': 'Caricamento...', + 'common.error': 'Errore', + 'common.back': 'Indietro', + 'common.all': 'Tutti', + 'common.close': 'Chiudi', + 'common.open': 'Apri', + 'common.upload': 'Carica', + 'common.search': 'Cerca', + 'common.confirm': 'Conferma', + 'common.ok': 'OK', + 'common.yes': 'Sì', + 'common.no': 'No', + 'common.or': 'o', + 'common.none': 'Nessuno', + 'common.date': 'Data', + 'common.rename': 'Rinomina', + 'common.name': 'Nome', + 'common.email': 'Email', + 'common.password': 'Password', + 'common.saving': 'Salvataggio...', + 'common.update': 'Aggiorna', + 'common.change': 'Cambia', + 'common.uploading': 'Caricamento…', + 'common.backToPlanning': 'Torna al Programma', + 'common.reset': 'Reimposta', + + // Navbar + 'nav.trip': 'Viaggio', + 'nav.share': 'Condividi', + 'nav.settings': 'Impostazioni', + 'nav.admin': 'Amministrazione', + 'nav.logout': 'Esci', + 'nav.lightMode': 'Modalità chiara', + 'nav.darkMode': 'Modalità scura', + 'nav.autoMode': 'Modalità automatica', + 'nav.administrator': 'Amministratore', + + // Dashboard + 'dashboard.title': 'I miei Viaggi', + 'dashboard.subtitle.loading': 'Caricamento viaggi...', + 'dashboard.subtitle.trips': '{count} viaggi ({archived} archiviati)', + 'dashboard.subtitle.empty': 'Inizia il tuo primo viaggio', + 'dashboard.subtitle.activeOne': '{count} viaggio attivo', + 'dashboard.subtitle.activeMany': '{count} viaggi attivi', + 'dashboard.subtitle.archivedSuffix': ' · {count} archiviati', + 'dashboard.newTrip': 'Nuovo Viaggio', + 'dashboard.gridView': 'Vista a griglia', + 'dashboard.listView': 'Vista a lista', + 'dashboard.currency': 'Valuta', + 'dashboard.timezone': 'Fusi orari', + 'dashboard.localTime': 'Locale', + 'dashboard.timezoneCustomTitle': 'Fuso orario personalizzato', + 'dashboard.timezoneCustomLabelPlaceholder': 'Etichetta (opzionale)', + 'dashboard.timezoneCustomTzPlaceholder': 'es. Europe/Rome', + 'dashboard.timezoneCustomAdd': 'Aggiungi', + 'dashboard.timezoneCustomErrorEmpty': 'Inserisci un identificatore di fuso orario', + 'dashboard.timezoneCustomErrorInvalid': 'Fuso orario non valido. Usa formati come Europe/Rome', + 'dashboard.timezoneCustomErrorDuplicate': 'Già aggiunto', + 'dashboard.emptyTitle': 'Ancora nessun viaggio', + 'dashboard.emptyText': 'Crea il tuo primo viaggio e inizia a programmare!', + 'dashboard.emptyButton': 'Crea il primo viaggio', + 'dashboard.nextTrip': 'Prossimo Viaggio', + 'dashboard.shared': 'Condiviso', + 'dashboard.sharedBy': 'Condiviso da {name}', + 'dashboard.days': 'Giorni', + 'dashboard.places': 'Luoghi', + 'dashboard.archive': 'Archivia', + 'dashboard.restore': 'Ripristina', + 'dashboard.archived': 'Archiviati', + 'dashboard.status.ongoing': 'In corso', + 'dashboard.status.today': 'Oggi', + 'dashboard.status.tomorrow': 'Domani', + 'dashboard.status.past': 'Passato', + 'dashboard.status.daysLeft': '-{count} giorni', + 'dashboard.toast.loadError': 'Impossibile caricare i viaggi', + 'dashboard.toast.created': 'Viaggio creato con successo!', + 'dashboard.toast.createError': 'Impossibile creare il viaggio', + 'dashboard.toast.updated': 'Viaggio aggiornato!', + 'dashboard.toast.updateError': 'Impossibile aggiornare il viaggio', + 'dashboard.toast.deleted': 'Viaggio eliminato', + 'dashboard.toast.deleteError': 'Impossibile eliminare il viaggio', + 'dashboard.toast.archived': 'Viaggio archiviato', + 'dashboard.toast.archiveError': 'Impossibile archiviare il viaggio', + 'dashboard.toast.restored': 'Viaggio ripristinato', + 'dashboard.toast.restoreError': 'Impossibile ripristinare il viaggio', + 'dashboard.confirm.delete': 'Eliminare il viaggio "{title}"? Tutti i luoghi e i programmi verranno eliminati in modo permanente.', + 'dashboard.editTrip': 'Modifica Viaggio', + 'dashboard.createTrip': 'Crea Nuovo Viaggio', + 'dashboard.tripTitle': 'Titolo', + 'dashboard.tripTitlePlaceholder': 'es. Estate in Giappone', + 'dashboard.tripDescription': 'Descrizione', + 'dashboard.tripDescriptionPlaceholder': 'Di cosa tratta questo viaggio?', + 'dashboard.startDate': 'Data di inizio', + 'dashboard.endDate': 'Data di fine', + 'dashboard.noDateHint': 'Nessuna data impostata — verranno creati 7 giorni predefiniti. Puoi cambiarlo in qualsiasi momento.', + 'dashboard.coverImage': 'Immagine di copertina', + 'dashboard.addCoverImage': 'Aggiungi immagine di copertina (o trascinala qui)', + 'dashboard.addMembers': 'Compagni di viaggio', + 'dashboard.addMember': 'Aggiungi membro', + 'dashboard.coverSaved': 'Immagine di copertina salvata', + 'dashboard.coverUploadError': 'Impossibile caricare', + 'dashboard.coverRemoveError': 'Impossibile rimuovere', + 'dashboard.titleRequired': 'Il titolo è obbligatorio', + 'dashboard.endDateError': 'La data di fine deve essere successiva alla data di inizio', + + // Settings + 'settings.title': 'Impostazioni', + 'settings.subtitle': 'Configura le tue impostazioni personali', + 'settings.map': 'Mappa', + 'settings.mapTemplate': 'Modello Mappa', + 'settings.mapTemplatePlaceholder.select': 'Seleziona modello...', + 'settings.mapDefaultHint': 'Lascia vuoto per OpenStreetMap (predefinito)', + 'settings.mapTemplatePlaceholder': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + 'settings.mapHint': 'Modello URL per i tile della mappa', + 'settings.latitude': 'Latitudine', + 'settings.longitude': 'Longitudine', + 'settings.saveMap': 'Salva Mappa', + 'settings.apiKeys': 'Chiavi API', + 'settings.mapsKey': 'Chiave API Google Maps', + 'settings.mapsKeyHint': 'Per la ricerca dei luoghi. Richiede Places API (New). Ottienila su console.cloud.google.com', + 'settings.weatherKey': 'Chiave API OpenWeatherMap', + 'settings.weatherKeyHint': 'Per i dati meteo. Gratuita su openweathermap.org/api', + 'settings.keyPlaceholder': 'Inserisci la chiave...', + 'settings.configured': 'Configurata', + 'settings.saveKeys': 'Salva Chiavi', + 'settings.display': 'Visualizzazione', + 'settings.colorMode': 'Modalità Colore', + 'settings.light': 'Chiara', + 'settings.dark': 'Scura', + 'settings.auto': 'Automatica', + 'settings.language': 'Lingua', + 'settings.temperature': 'Unità di Temperatura', + 'settings.timeFormat': 'Formato Ora', + 'settings.routeCalculation': 'Calcolo Percorso', + 'settings.blurBookingCodes': 'Nascondi codici di prenotazione', + 'settings.notifications': 'Notifiche', + 'settings.notifyTripInvite': 'Inviti di viaggio', + 'settings.notifyBookingChange': 'Modifiche alle prenotazioni', + 'settings.notifyTripReminder': 'Promemoria di viaggio', + 'settings.notifyVacayInvite': 'Inviti fusione Vacay', + 'settings.notifyPhotosShared': 'Foto condivise (Immich)', + 'settings.notifyCollabMessage': 'Messaggi chat (Collab)', + 'settings.notifyPackingTagged': 'Lista valigia: assegnazioni', + 'settings.notifyWebhook': 'Notifiche webhook', + 'settings.on': 'On', + 'settings.off': 'Off', + 'settings.mcp.title': 'Configurazione MCP', + 'settings.mcp.endpoint': 'Endpoint MCP', + 'settings.mcp.clientConfig': 'Configurazione client', + 'settings.mcp.clientConfigHint': 'Sostituisci con un token API dalla lista sottostante. Il percorso di npx potrebbe dover essere adattato per il tuo sistema (es. C:\\PROGRA~1\\nodejs\\npx.cmd su Windows).', + 'settings.mcp.copy': 'Copia', + 'settings.mcp.copied': 'Copiato!', + 'settings.mcp.apiTokens': 'Token API', + 'settings.mcp.createToken': 'Crea nuovo token', + 'settings.mcp.noTokens': 'Nessun token ancora. Creane uno per connettere i client MCP.', + 'settings.mcp.tokenCreatedAt': 'Creato', + 'settings.mcp.tokenUsedAt': 'Utilizzato', + 'settings.mcp.deleteTokenTitle': 'Elimina token', + 'settings.mcp.deleteTokenMessage': 'Questo token smetterà di funzionare immediatamente. Qualsiasi client MCP che lo utilizza perderà l\'accesso.', + 'settings.mcp.modal.createTitle': 'Crea token API', + 'settings.mcp.modal.tokenName': 'Nome del token', + 'settings.mcp.modal.tokenNamePlaceholder': 'es. Claude Desktop, Laptop di lavoro', + 'settings.mcp.modal.creating': 'Creazione…', + 'settings.mcp.modal.create': 'Crea token', + 'settings.mcp.modal.createdTitle': 'Token creato', + 'settings.mcp.modal.createdWarning': 'Questo token verrà mostrato solo una volta. Copialo e salvalo ora — non può essere recuperato.', + 'settings.mcp.modal.done': 'Fatto', + 'settings.mcp.toast.created': 'Token creato', + 'settings.mcp.toast.createError': 'Impossibile creare il token', + 'settings.mcp.toast.deleted': 'Token eliminato', + 'settings.mcp.toast.deleteError': 'Impossibile eliminare il token', + 'settings.account': 'Account', + 'settings.username': 'Username', + 'settings.email': 'Email', + 'settings.role': 'Ruolo', + 'settings.roleAdmin': 'Amministratore', + 'settings.oidcLinked': 'Collegato con', + 'settings.changePassword': 'Cambia Password', + 'settings.currentPassword': 'Password attuale', + 'settings.currentPasswordRequired': 'La password attuale è obbligatoria', + 'settings.newPassword': 'Nuova password', + 'settings.confirmPassword': 'Conferma nuova password', + 'settings.updatePassword': 'Aggiorna password', + 'settings.passwordRequired': 'Inserisci la password attuale e quella nuova', + 'settings.passwordTooShort': 'La password deve contenere almeno 8 caratteri', + 'settings.passwordMismatch': 'Le password non corrispondono', + 'settings.passwordWeak': 'La password deve contenere lettere maiuscole, minuscole e un numero', + 'settings.passwordChanged': 'Password cambiata con successo', + 'settings.deleteAccount': 'Elimina account', + 'settings.deleteAccountTitle': 'Eliminare il tuo account?', + 'settings.deleteAccountWarning': 'Il tuo account e tutti i tuoi viaggi, luoghi e file verranno eliminati in modo permanente. Questa azione non può essere annullata.', + 'settings.deleteAccountConfirm': 'Elimina in modo permanente', + 'settings.deleteBlockedTitle': 'Eliminazione impossibile', + 'settings.deleteBlockedMessage': 'Sei l\'unico amministratore. Promuovi un altro utente ad amministratore prima di eliminare il tuo account.', + 'settings.roleUser': 'Utente', + 'settings.saveProfile': 'Salva Profillo', + 'settings.toast.mapSaved': 'Impostazioni mappa salvate', + 'settings.toast.keysSaved': 'Chiavi API salvate', + 'settings.toast.displaySaved': 'Impostazioni di visualizzazione salvate', + 'settings.toast.profileSaved': 'Profilo salvato', + 'settings.uploadAvatar': 'Carica Immagine del Profilo', + 'settings.removeAvatar': 'Rimuovi Immagine del Profilo', + 'settings.avatarUploaded': 'Immagine del profilo aggiornata', + 'settings.avatarRemoved': 'Immagine del profilo rimossa', + 'settings.avatarError': 'Impossibile caricare', + 'settings.mfa.title': 'Autenticazione a due fattori (2FA)', + 'settings.mfa.description': 'Aggiunge un secondo passaggio quando accedi con email e password. Usa un\'app authenticator (Google Authenticator, Authy, ecc.).', + 'settings.mfa.requiredByPolicy': 'L\'amministratore richiede l\'autenticazione a due fattori. Configura un\'app authenticator qui sotto prima di continuare.', + 'settings.mfa.backupTitle': 'Codici di backup', + 'settings.mfa.backupDescription': 'Usa questi codici monouso se perdi l\'accesso alla tua app authenticator.', + 'settings.mfa.backupWarning': 'Salvali adesso. Ogni codice può essere usato una sola volta.', + 'settings.mfa.backupCopy': 'Copia codici', + 'settings.mfa.backupDownload': 'Scarica TXT', + 'settings.mfa.backupPrint': 'Stampa / PDF', + 'settings.mfa.backupCopied': 'Codici di backup copiati', + 'settings.mfa.enabled': 'La 2FA è abilitata sul tuo account.', + 'settings.mfa.disabled': 'La 2FA non è abilitata.', + 'settings.mfa.setup': 'Configura authenticator', + 'settings.mfa.scanQr': 'Scansiona questo codice QR con la tua app, o inserisci il segreto manualmente.', + 'settings.mfa.secretLabel': 'Chiave segreta (inserimento manuale)', + 'settings.mfa.codePlaceholder': 'Codice a 6 cifre', + 'settings.mfa.enable': 'Abilita 2FA', + 'settings.mfa.cancelSetup': 'Annulla', + 'settings.mfa.disableTitle': 'Disabilita 2FA', + 'settings.mfa.disableHint': 'Inserisci la password del tuo account e un codice attuale dal tuo authenticator.', + 'settings.mfa.disable': 'Disabilita 2FA', + 'settings.mfa.toastEnabled': 'Autenticazione a due fattori abilitata', + 'settings.mfa.toastDisabled': 'Autenticazione a due fattori disabilitata', + 'settings.mfa.demoBlocked': 'Non disponibile in modalità demo', + 'admin.smtp.title': 'Email e notifiche', + 'admin.smtp.hint': 'Configurazione SMTP per le notifiche via email. Opzionale: URL webhook per Discord, Slack, ecc.', + 'admin.smtp.testButton': 'Invia email di prova', + 'admin.smtp.testSuccess': 'Email di prova inviata con successo', + 'admin.smtp.testFailed': 'Invio email di prova fallito', + 'dayplan.icsTooltip': 'Esporta calendario (ICS)', + 'share.linkTitle': 'Link pubblico', + 'share.linkHint': 'Crea un link che chiunque può usare per visualizzare questo viaggio senza accedere. Solo lettura — nessuna modifica possibile.', + 'share.createLink': 'Crea link', + 'share.deleteLink': 'Elimina link', + 'share.createError': 'Impossibile creare il link', + 'common.copy': 'Copia', + 'common.copied': 'Copiato', + 'share.permMap': 'Mappa e programma', + 'share.permBookings': 'Prenotazioni', + 'share.permPacking': 'Valigia', + 'shared.expired': 'Link scaduto o non valido', + 'shared.expiredHint': 'Questo link di viaggio condiviso non è più attivo.', + 'shared.readOnly': 'Vista in sola lettura', + 'shared.tabPlan': 'Programma', + 'shared.tabBookings': 'Prenotazioni', + 'shared.tabPacking': 'Valigia', + 'shared.tabBudget': 'Budget', + 'shared.tabChat': 'Chat', + 'shared.days': 'giorni', + 'shared.places': 'luoghi', + 'shared.other': 'Altro', + 'shared.totalBudget': 'Budget totale', + 'shared.messages': 'messaggi', + 'shared.sharedVia': 'Condiviso tramite', + 'shared.confirmed': 'Confermato', + 'shared.pending': 'In attesa', + 'share.permBudget': 'Budget', + 'share.permCollab': 'Chat', + + // Login + 'login.error': 'Accesso fallito. Controlla le tue credenziali.', + 'login.tagline': 'I tuoi viaggi.\nIl tuo programma.', + 'login.description': 'Programma viaggi in collaborazione con mappe interattive, budget e sincronizzazione in tempo reale.', + 'login.features.maps': 'Mappe Interattive', + 'login.features.mapsDesc': 'Google Places, percorsi e clustering', + 'login.features.realtime': 'Sincronizzazione in tempo reale', + 'login.features.realtimeDesc': 'Programmate insieme tramite WebSocket', + 'login.features.budget': 'Tracciamento Budget', + 'login.features.budgetDesc': 'Categorie, grafici e costi per persona', + 'login.features.collab': 'Collaborazione', + 'login.features.collabDesc': 'Multi-utente con viaggi condivisi', + 'login.features.packing': 'Lista Valigia', + 'login.features.packingDesc': 'Categorie, progressi e suggerimenti', + 'login.features.bookings': 'Prenotazioni', + 'login.features.bookingsDesc': 'Voli, alloggi, ristoranti e altro', + 'login.features.files': 'Documenti', + 'login.features.filesDesc': 'Carica e gestisci i documenti', + 'login.features.routes': 'Percorsi Intelligenti', + 'login.features.routesDesc': 'Ottimizzazione automatica ed esportazione su Google Maps', + 'login.selfHosted': 'Self-hosted · Open Source · Your data stays yours', + 'login.title': 'Accedi', + 'login.subtitle': 'Bentornato', + 'login.signingIn': 'Accesso in corso…', + 'login.signIn': 'Accedi', + 'login.createAdmin': 'Crea Account Amministratore', + 'login.createAdminHint': 'Imposta il primo account amministratore per TREK.', + 'login.createAccount': 'Crea Account', + 'login.createAccountHint': 'Registra un nuovo account.', + 'login.creating': 'Creazione in corso…', + 'login.noAccount': "Non hai un account?", + 'login.hasAccount': 'Hai già un account?', + 'login.register': 'Registrati', + 'login.emailPlaceholder': 'tua@email.com', + 'login.username': 'Username', + 'login.oidc.registrationDisabled': 'La registrazione è disabilitata. Contatta il tuo amministratore.', + 'login.oidc.noEmail': 'Nessuna email ricevuta dal provider.', + 'login.oidc.tokenFailed': 'Autenticazione fallita.', + 'login.oidc.invalidState': 'Sessione non valida. Riprova.', + 'login.demoFailed': 'Accesso demo fallito', + 'login.oidcSignIn': 'Accedi con {name}', + 'login.oidcOnly': 'L\'autenticazione tramite password è disabilitata. Accedi utilizzando il tuo provider SSO.', + 'login.demoHint': 'Prova la demo — nessuna registrazione necessaria', + 'login.mfaTitle': 'Autenticazione a due fattori', + 'login.mfaSubtitle': 'Inserisci il codice a 6 cifre dalla tua app authenticator.', + 'login.mfaCodeLabel': 'Codice di verifica', + 'login.mfaCodeRequired': 'Inserisci il codice dalla tua app authenticator.', + 'login.mfaHint': 'Apri Google Authenticator, Authy o un\'altra app TOTP.', + 'login.mfaBack': '← Torna all\'accesso', + 'login.mfaVerify': 'Verifica', + + // Register + 'register.passwordMismatch': 'Le password non corrispondono', + 'register.passwordTooShort': 'La password deve contenere almeno 6 caratteri', + 'register.failed': 'Registrazione fallita', + 'register.getStarted': 'Inizia', + 'register.subtitle': 'Crea un account e inizia a programmare i viaggi dei tuoi sogni.', + 'register.feature1': 'Piani di viaggio illimitati', + 'register.feature2': 'Vista mappa interattiva', + 'register.feature3': 'Gestisci luoghi e categorie', + 'register.feature4': 'Traccia le prenotazioni', + 'register.feature5': 'Crea liste per la valigia', + 'register.feature6': 'Archivia foto e file', + 'register.createAccount': 'Crea Account', + 'register.startPlanning': 'Inizia a programmare il tuo viaggio', + 'register.minChars': 'Min. 6 caratteri', + 'register.confirmPassword': 'Conferma Password', + 'register.repeatPassword': 'Ripeti password', + 'register.registering': 'Registrazione in corso...', + 'register.register': 'Registrati', + 'register.hasAccount': 'Hai già un account?', + 'register.signIn': 'Accedi', + + // Admin + 'admin.title': 'Amministrazione', + 'admin.subtitle': 'Gestione utenti e impostazioni di sistema', + 'admin.tabs.users': 'Utenti', + 'admin.tabs.categories': 'Categorie', + 'admin.tabs.backup': 'Backup', + 'admin.stats.users': 'Utenti', + 'admin.stats.trips': 'Viaggi', + 'admin.stats.places': 'Luoghi', + 'admin.stats.photos': 'Foto', + 'admin.stats.files': 'File', + 'admin.table.user': 'Utente', + 'admin.table.email': 'Email', + 'admin.table.role': 'Ruolo', + 'admin.table.created': 'Creato', + 'admin.table.lastLogin': 'Ultimo Accesso', + 'admin.table.actions': 'Azioni', + 'admin.you': '(Tu)', + 'admin.editUser': 'Modifica Utente', + 'admin.newPassword': 'Nuova Password', + 'admin.newPasswordHint': 'Lascia vuoto per mantenere la password attuale', + 'admin.deleteUser': 'Eliminare l\'utente "{name}"? Tutti i viaggi verranno eliminati in modo permanente.', + 'admin.deleteUserTitle': 'Elimina utente', + 'admin.newPasswordPlaceholder': 'Inserisci nuova password…', + 'admin.toast.loadError': 'Impossibile caricare i dati di amministrazione', + 'admin.toast.userUpdated': 'Utente aggiornato', + 'admin.toast.updateError': 'Impossibile aggiornare', + 'admin.toast.userDeleted': 'Utente eliminato', + 'admin.toast.deleteError': 'Impossibile eliminare', + 'admin.toast.cannotDeleteSelf': 'Impossibile eliminare il proprio account', + 'admin.toast.userCreated': 'Utente creato', + 'admin.toast.createError': 'Impossibile creare l\'utente', + 'admin.toast.fieldsRequired': 'Username, email e password sono obbligatori', + 'admin.createUser': 'Crea Utente', + 'admin.invite.title': 'Link di Invito', + 'admin.invite.subtitle': 'Crea link di registrazione monouso', + 'admin.invite.create': 'Crea Link', + 'admin.invite.createAndCopy': 'Crea & Copia', + 'admin.invite.empty': 'Nessun link di invito ancora creato', + 'admin.invite.maxUses': 'Usi Max.', + 'admin.invite.expiry': 'Scade tra', + 'admin.invite.uses': 'usato', + 'admin.invite.expiresAt': 'scade', + 'admin.invite.createdBy': 'da', + 'admin.invite.active': 'Attivo', + 'admin.invite.expired': 'Scaduto', + 'admin.invite.usedUp': 'Esaurito', + 'admin.invite.copied': 'Link di invito copiato negli appunti', + 'admin.invite.copyLink': 'Copia link', + 'admin.invite.deleted': 'Link di invito eliminato', + 'admin.invite.createError': 'Impossibile creare il link di invito', + 'admin.invite.deleteError': 'Impossibile eliminare il link di invito', + 'admin.tabs.settings': 'Impostazioni', + 'admin.allowRegistration': 'Consenti Registrazione', + 'admin.allowRegistrationHint': 'I nuovi utenti possono registrarsi autonomamente', + 'admin.requireMfa': 'Richiedi autenticazione a due fattori (2FA)', + 'admin.requireMfaHint': 'Gli utenti senza 2FA devono completare la configurazione in Impostazioni prima di usare l\'app.', + 'admin.apiKeys': 'Chiavi API', + 'admin.apiKeysHint': 'Opzionale. Abilita dati estesi per i luoghi come foto e meteo.', + 'admin.mapsKey': 'Chiave API Google Maps', + 'admin.mapsKeyHint': 'Richiesta per la ricerca dei luoghi. Ottienila su console.cloud.google.com', + 'admin.mapsKeyHintLong': 'Senza una chiave API, OpenStreetMap viene utilizzato per la ricerca dei luoghi. Con una chiave API di Google, è possibile caricare anche foto, valutazioni e orari di apertura. Ottienine una su console.cloud.google.com.', + 'admin.recommended': 'Consigliato', + 'admin.weatherKey': 'Chiave API OpenWeatherMap', + 'admin.weatherKeyHint': 'Per i dati meteo. Gratuita su openweathermap.org', + 'admin.validateKey': 'Testa', + 'admin.keyValid': 'Connessa', + 'admin.keyInvalid': 'Non valida', + 'admin.keySaved': 'Chiavi API salvate', + 'admin.oidcTitle': 'Single Sign-On (OIDC)', + 'admin.oidcSubtitle': 'Consenti l\'accesso tramite provider esterni come Google, Apple, Authentik o Keycloak.', + 'admin.oidcDisplayName': 'Nome Visualizzato', + 'admin.oidcIssuer': 'URL Emittente', + 'admin.oidcIssuerHint': 'L\'URL dell\'Emittente OpenID Connect del provider. es. https://accounts.google.com', + 'admin.oidcSaved': 'Configurazione OIDC salvata', + 'admin.oidcOnlyMode': 'Disabilita autenticazione con password', + 'admin.oidcOnlyModeHint': 'Se abilitato, è consentito solo l\'accesso SSO. L\'accesso basato su password e la registrazione sono bloccati.', + + // File Types + 'admin.fileTypes': 'Tipi di File Consentiti', + 'admin.fileTypesHint': 'Configura quali tipi di file gli utenti possono caricare.', + 'admin.fileTypesFormat': 'Estensioni separate da virgola (es. jpg,png,pdf,doc). Usa * per consentire tutti i tipi.', + 'admin.fileTypesSaved': 'Impostazioni dei tipi di file salvate', + // Packing Templates & Bag Tracking + 'admin.bagTracking.title': 'Tracciamento valigia', + 'admin.bagTracking.subtitle': 'Abilita il peso e l\'assegnazione della valigia per gli elementi della lista valigia', + 'admin.tabs.config': 'Configurazione', + 'admin.tabs.templates': 'Modelli lista valigia', + 'admin.packingTemplates.title': 'Modelli lista valigia', + 'admin.packingTemplates.subtitle': 'Crea liste valigia riutilizzabili per i tuoi viaggi', + 'admin.packingTemplates.create': 'Nuovo modello', + 'admin.packingTemplates.namePlaceholder': 'Nome modello (es. Vacanza al mare)', + 'admin.packingTemplates.empty': 'Ancora nessun modello creato', + 'admin.packingTemplates.items': 'elementi', + 'admin.packingTemplates.categories': 'categorie', + 'admin.packingTemplates.itemName': 'Nome elemento', + 'admin.packingTemplates.itemCategory': 'Categoria', + 'admin.packingTemplates.categoryName': 'Nome categoria (es. Abbigliamento)', + 'admin.packingTemplates.addCategory': 'Aggiungi categoria', + 'admin.packingTemplates.created': 'Modello creato', + 'admin.packingTemplates.deleted': 'Modello eliminato', + 'admin.packingTemplates.loadError': 'Impossibile caricare i modelli', + 'admin.packingTemplates.createError': 'Impossibile creare il modello', + 'admin.packingTemplates.deleteError': 'Impossibile eliminare il modello', + 'admin.packingTemplates.saveError': 'Impossibile salvare', + + // Addons + 'admin.tabs.addons': 'Moduli', + 'admin.addons.title': 'Moduli', + 'admin.addons.subtitle': 'Abilita o disabilita le funzionalità per personalizzare la tua esperienza TREK.', + 'admin.addons.catalog.packing.name': 'Lista valigia', + 'admin.addons.catalog.packing.description': 'Checklist per preparare la valigia per ogni viaggio', + 'admin.addons.catalog.budget.name': 'Budget', + 'admin.addons.catalog.budget.description': 'Tieni traccia delle spese e pianifica il budget del tuo viaggio', + 'admin.addons.catalog.documents.name': 'Documenti', + 'admin.addons.catalog.documents.description': 'Archivia e gestisci i documenti di viaggio', + 'admin.addons.catalog.vacay.name': 'Ferie', + 'admin.addons.catalog.vacay.description': 'Pianificatore personale delle ferie con vista calendario', + 'admin.addons.catalog.atlas.name': 'Atlante', + 'admin.addons.catalog.atlas.description': 'Mappa del mondo con paesi visitati e statistiche di viaggio', + 'admin.addons.catalog.collab.name': 'Collaborazione', + 'admin.addons.catalog.collab.description': 'Note, sondaggi e chat in tempo reale per la pianificazione del viaggio', + 'admin.addons.catalog.memories.name': 'Foto (Immich)', + 'admin.addons.catalog.memories.description': 'Condividi le foto del viaggio tramite la tua istanza Immich', + 'admin.addons.catalog.mcp.name': 'MCP', + 'admin.addons.catalog.mcp.description': 'Model Context Protocol per l\'integrazione di assistenti AI', + 'admin.addons.subtitleBefore': 'Abilita o disabilita le funzionalità per personalizzare la tua ', + 'admin.addons.subtitleAfter': ' esperienza.', + 'admin.addons.enabled': 'Abilitato', + 'admin.addons.disabled': 'Disabilitato', + 'admin.addons.type.trip': 'Viaggio', + 'admin.addons.type.global': 'Globale', + 'admin.addons.type.integration': 'Integrazione', + 'admin.addons.tripHint': 'Disponibile come scheda all\'interno di ciascun viaggio', + 'admin.addons.globalHint': 'Disponibile come sezione autonoma nella navigazione principale', + 'admin.addons.integrationHint': 'Servizi backend e integrazioni API senza pagina dedicata', + 'admin.addons.toast.updated': 'Modulo aggiornato', + 'admin.addons.toast.error': 'Impossibile aggiornare il modulo', + 'admin.addons.noAddons': 'Nessun modulo disponibile', + + // Weather info + 'admin.weather.title': 'Dati meteo', + 'admin.weather.badge': 'Dal 24 marzo 2026', + 'admin.weather.description': 'TREK utilizza Open-Meteo come fonte dei dati meteo. Open-Meteo è un servizio meteo gratuito e open-source — non è richiesta alcuna chiave API.', + 'admin.weather.forecast': 'Previsioni a 16 giorni', + 'admin.weather.forecastDesc': 'In precedenza 5 giorni (OpenWeatherMap)', + 'admin.weather.climate': 'Dati climatici storici', + 'admin.weather.climateDesc': 'Medie degli ultimi 85 anni per i giorni oltre le previsioni a 16 giorni', + 'admin.weather.requests': '10.000 richieste / giorno', + 'admin.weather.requestsDesc': 'Gratis, nessuna chiave API richiesta', + 'admin.weather.locationHint': 'Il meteo si basa sul primo luogo con coordinate di ogni giorno. Se a un giorno non è assegnato alcun luogo, viene utilizzato come riferimento un qualsiasi luogo dell\'elenco.', + + 'admin.tabs.audit': 'Log di audit', + + 'admin.audit.subtitle': 'Eventi sensibili di sicurezza e amministrazione (backup, utenti, 2FA, impostazioni).', + 'admin.audit.empty': 'Nessuna voce di audit.', + 'admin.audit.refresh': 'Aggiorna', + 'admin.audit.loadMore': 'Carica altro', + 'admin.audit.showing': '{count} caricati · {total} totali', + 'admin.audit.col.time': 'Ora', + 'admin.audit.col.user': 'Utente', + 'admin.audit.col.action': 'Azione', + 'admin.audit.col.resource': 'Risorsa', + 'admin.audit.col.ip': 'IP', + 'admin.audit.col.details': 'Dettagli', + + // MCP Tokens + 'admin.tabs.mcpTokens': 'Token MCP', + 'admin.mcpTokens.title': 'Token MCP', + 'admin.mcpTokens.subtitle': 'Gestisci i token API di tutti gli utenti', + 'admin.mcpTokens.owner': 'Proprietario', + 'admin.mcpTokens.tokenName': 'Nome token', + 'admin.mcpTokens.created': 'Creato', + 'admin.mcpTokens.lastUsed': 'Ultimo utilizzo', + 'admin.mcpTokens.never': 'Mai', + 'admin.mcpTokens.empty': 'Non sono ancora stati creati token MCP', + 'admin.mcpTokens.deleteTitle': 'Elimina token', + 'admin.mcpTokens.deleteMessage': 'Questo token verrà revocato immediatamente. L\'utente perderà l\'accesso MCP tramite questo token.', + 'admin.mcpTokens.deleteSuccess': 'Token eliminato', + 'admin.mcpTokens.deleteError': 'Impossibile eliminare il token', + 'admin.mcpTokens.loadError': 'Impossibile caricare i token', + + // GitHub + 'admin.tabs.github': 'GitHub', + 'admin.github.title': 'Cronologia rilasci', + 'admin.github.subtitle': 'Ultimi aggiornamenti da {repo}', + 'admin.github.latest': 'Ultimo', + 'admin.github.prerelease': 'Pre-release', + 'admin.github.showDetails': 'Mostra dettagli', + 'admin.github.hideDetails': 'Nascondi dettagli', + 'admin.github.loadMore': 'Carica altro', + 'admin.github.loading': 'Caricamento...', + 'admin.github.error': 'Impossibile caricare i rilasci', + 'admin.github.by': 'da', + 'admin.github.support': 'Mi aiuta a continuare a sviluppare TREK', + + 'admin.update.available': 'Aggiornamento disponibile', + 'admin.update.text': 'TREK {version} è disponibile. Stai eseguendo {current}.', + 'admin.update.button': 'Vedi su GitHub', + 'admin.update.install': 'Installa aggiornamento', + 'admin.update.confirmTitle': 'Installare l\'aggiornamento?', + 'admin.update.confirmText': 'TREK verrà aggiornato da {current} a {version}. Il server si riavvierà automaticamente in seguito.', + 'admin.update.dataInfo': 'Tutti i tuoi dati (viaggi, utenti, chiavi API, caricamenti, Ferie, Atlante, budget) saranno preservati.', + 'admin.update.warning': 'L\'app sarà temporaneamente non disponibile durante il riavvio.', + 'admin.update.confirm': 'Aggiorna ora', + 'admin.update.installing': 'Aggiornamento in corso…', + 'admin.update.success': 'Aggiornamento installato! Il server si sta riavviando…', + 'admin.update.failed': 'Aggiornamento non riuscito', + 'admin.update.backupHint': 'Ti consigliamo di creare un backup prima di aggiornare.', + 'admin.update.backupLink': 'Vai a Backup', + 'admin.update.howTo': 'Come aggiornare', + 'admin.update.dockerText': 'La tua istanza TREK è in esecuzione in Docker. Per aggiornare alla versione {version}, esegui i seguenti comandi sul tuo server:', + 'admin.update.reloadHint': 'Ricarica la pagina tra qualche secondo.', + + // Vacay addon + 'vacay.subtitle': 'Pianifica e gestisci i giorni di ferie', + 'vacay.settings': 'Impostazioni', + 'vacay.year': 'Anno', + 'vacay.addYear': 'Aggiungi anno', + 'vacay.removeYear': 'Rimuovi anno', + 'vacay.removeYearConfirm': 'Rimuovere {year}?', + 'vacay.removeYearHint': 'Tutte le voci delle ferie e le ferie aziendali di questo anno verranno eliminate in modo permanente.', + 'vacay.remove': 'Rimuovi', + 'vacay.persons': 'Persone', + 'vacay.noPersons': 'Nessuna persona aggiunta', + 'vacay.addPerson': 'Aggiungi persona', + 'vacay.editPerson': 'Modifica persona', + 'vacay.removePerson': 'Rimuovi persona', + 'vacay.removePersonConfirm': 'Rimuovere {name}?', + 'vacay.removePersonHint': 'Tutte le voci delle ferie per questa persona verranno eliminate in modo permanente.', + 'vacay.personName': 'Nome', + 'vacay.personNamePlaceholder': 'Inserisci nome', + 'vacay.color': 'Colore', + 'vacay.add': 'Aggiungi', + 'vacay.legend': 'Legenda', + 'vacay.publicHoliday': 'Festività pubblica', + 'vacay.companyHoliday': 'Ferie aziendali', + 'vacay.weekend': 'Weekend', + 'vacay.modeVacation': 'Ferie', + 'vacay.modeCompany': 'Ferie aziendali', + 'vacay.entitlement': 'Disponibilità', + 'vacay.entitlementDays': 'Giorni', + 'vacay.used': 'Usati', + 'vacay.remaining': 'Rimanenti', + 'vacay.carriedOver': 'dal {year}', + 'vacay.blockWeekends': 'Blocca weekend', + 'vacay.blockWeekendsHint': 'Impedisci le voci ferie nei giorni del weekend', + 'vacay.weekendDays': 'Giorni del weekend', + 'vacay.mon': 'Lun', + 'vacay.tue': 'Mar', + 'vacay.wed': 'Mer', + 'vacay.thu': 'Gio', + 'vacay.fri': 'Ven', + 'vacay.sat': 'Sab', + 'vacay.sun': 'Dom', + 'vacay.publicHolidays': 'Festività pubbliche', + 'vacay.publicHolidaysHint': 'Segna le festività pubbliche nel calendario', + 'vacay.selectCountry': 'Seleziona paese', + 'vacay.selectRegion': 'Seleziona regione (opzionale)', + 'vacay.addCalendar': 'Aggiungi calendario', + 'vacay.calendarLabel': 'Etichetta (opzionale)', + 'vacay.calendarColor': 'Colore', + 'vacay.noCalendars': 'Ancora nessun calendario delle festività aggiunto', + 'vacay.companyHolidays': 'Ferie aziendali', + 'vacay.companyHolidaysHint': 'Consenti di segnare giorni di ferie aziendali', + 'vacay.companyHolidaysNoDeduct': 'Le ferie aziendali non vengono conteggiate nei giorni di ferie.', + 'vacay.carryOver': 'Riporto', + 'vacay.carryOverHint': 'Riporta automaticamente i giorni di ferie rimanenti all\'anno successivo', + 'vacay.sharing': 'Condivisione', + 'vacay.sharingHint': 'Condividi il tuo piano ferie con altri utenti TREK', + 'vacay.owner': 'Proprietario', + 'vacay.shareEmailPlaceholder': 'Email dell\'utente TREK', + 'vacay.shareSuccess': 'Piano condiviso con successo', + 'vacay.shareError': 'Impossibile condividere il piano', + 'vacay.dissolve': 'Sciogli unione', + 'vacay.dissolveHint': 'Separa di nuovo i calendari. Le tue voci verranno mantenute.', + 'vacay.dissolveAction': 'Sciogli', + 'vacay.dissolved': 'Calendario separato', + 'vacay.fusedWith': 'Unito con', + 'vacay.you': 'tu', + 'vacay.noData': 'Nessun dato', + 'vacay.changeColor': 'Cambia colore', + 'vacay.inviteUser': 'Invita utente', + 'vacay.inviteHint': 'Invita un altro utente TREK a condividere un calendario ferie combinato.', + 'vacay.selectUser': 'Seleziona utente', + 'vacay.sendInvite': 'Invia invito', + 'vacay.inviteSent': 'Invito inviato', + 'vacay.inviteError': 'Impossibile inviare l\'invito', + 'vacay.pending': 'in attesa', + 'vacay.noUsersAvailable': 'Nessun utente disponibile', + 'vacay.accept': 'Accetta', + 'vacay.decline': 'Rifiuta', + 'vacay.acceptFusion': 'Accetta e unisci', + 'vacay.inviteTitle': 'Richiesta di unione', + 'vacay.inviteWantsToFuse': 'vuole condividere con te un calendario ferie.', + 'vacay.fuseInfo1': 'Entrambi vedrete tutte le voci ferie in un unico calendario condiviso.', + 'vacay.fuseInfo2': 'Entrambe le parti possono creare e modificare le voci reciproche.', + 'vacay.fuseInfo3': 'Entrambe le parti possono eliminare le voci e modificare le disponibilità ferie.', + 'vacay.fuseInfo4': 'Le impostazioni come festività pubbliche e ferie aziendali sono condivise.', + 'vacay.fuseInfo5': 'L\'unione può essere sciolta in qualsiasi momento da una delle due parti. Le tue voci verranno preservate.', + 'nav.myTrips': 'I miei viaggi', + + // Atlas addon + 'atlas.subtitle': 'La tua impronta di viaggio nel mondo', + 'atlas.countries': 'Paesi', + 'atlas.trips': 'Viaggi', + 'atlas.places': 'Luoghi', + 'atlas.unmark': 'Rimuovi', + 'atlas.confirmMark': 'Segnare questo paese come visitato?', + 'atlas.confirmUnmark': 'Rimuovere questo paese dalla tua lista dei visitati?', + 'atlas.markVisited': 'Segna come visitato', + 'atlas.markVisitedHint': 'Aggiungi questo paese alla tua lista dei visitati', + 'atlas.addToBucket': 'Aggiungi alla lista desideri', + 'atlas.addPoi': 'Aggiungi luogo', + 'atlas.bucketNamePlaceholder': 'Nome (paese, città, luogo...)', + 'atlas.month': 'Mese', + 'atlas.addToBucketHint': 'Salvalo come luogo che vuoi visitare', + 'atlas.bucketWhen': 'Quando pensi di visitarlo?', + 'atlas.statsTab': 'Statistiche', + 'atlas.bucketTab': 'Lista desideri', + 'atlas.addBucket': 'Aggiungi alla lista desideri', + 'atlas.bucketNamePlaceholder': 'Luogo o destinazione...', + 'atlas.bucketNotesPlaceholder': 'Note (opzionale)', + 'atlas.bucketEmpty': 'La tua lista desideri è vuota', + 'atlas.bucketEmptyHint': 'Aggiungi luoghi che sogni di visitare', + 'atlas.days': 'Giorni', + 'atlas.visitedCountries': 'Paesi visitati', + 'atlas.cities': 'Città', + 'atlas.noData': 'Ancora nessun dato di viaggio', + 'atlas.noDataHint': 'Crea un viaggio e aggiungi luoghi per vedere la tua mappa del mondo', + 'atlas.lastTrip': 'Ultimo viaggio', + 'atlas.nextTrip': 'Prossimo viaggio', + 'atlas.daysLeft': 'giorni rimasti', + 'atlas.streak': 'Serie', + 'atlas.year': 'anno', + 'atlas.years': 'anni', + 'atlas.yearInRow': 'anno consecutivo', + 'atlas.yearsInRow': 'anni consecutivi', + 'atlas.tripIn': 'viaggio in', + 'atlas.tripsIn': 'viaggi in', + 'atlas.since': 'dal', + 'atlas.europe': 'Europa', + 'atlas.asia': 'Asia', + 'atlas.northAmerica': 'Nord America', + 'atlas.southAmerica': 'Sud America', + 'atlas.africa': 'Africa', + 'atlas.oceania': 'Oceania', + 'atlas.other': 'Altro', + 'atlas.firstVisit': 'Primo viaggio', + 'atlas.lastVisitLabel': 'Ultimo viaggio', + 'atlas.tripSingular': 'Viaggio', + 'atlas.tripPlural': 'Viaggi', + 'atlas.placeVisited': 'Luogo visitato', + 'atlas.placesVisited': 'Luoghi visitati', + + // Trip Planner + 'trip.tabs.plan': 'Programma', + 'trip.tabs.reservations': 'Prenotazioni', + 'trip.tabs.reservationsShort': 'Pren.', + 'trip.tabs.packing': 'Lista valigia', + 'trip.tabs.packingShort': 'Valigia', + 'trip.tabs.budget': 'Budget', + 'trip.tabs.files': 'File', + 'trip.loading': 'Caricamento viaggio...', + 'trip.mobilePlan': 'Programma', + 'trip.mobilePlaces': 'Luoghi', + 'trip.toast.placeUpdated': 'Luogo aggiornato', + 'trip.toast.placeAdded': 'Luogo aggiunto', + 'trip.toast.placeDeleted': 'Luogo eliminato', + 'trip.toast.selectDay': 'Seleziona prima un giorno', + 'trip.toast.assignedToDay': 'Luogo assegnato al giorno', + 'trip.toast.reorderError': 'Impossibile riordinare', + 'trip.toast.reservationUpdated': 'Prenotazione aggiornata', + 'trip.toast.reservationAdded': 'Prenotazione aggiunta', + 'trip.toast.deleted': 'Eliminato', + 'trip.confirm.deletePlace': 'Sei sicuro di voler eliminare questo luogo?', + + // Day Plan Sidebar + 'dayplan.emptyDay': 'Nessun luogo programmato per questo giorno', + 'dayplan.addNote': 'Aggiungi nota', + 'dayplan.editNote': 'Modifica nota', + 'dayplan.noteAdd': 'Aggiungi nota', + 'dayplan.noteEdit': 'Modifica nota', + 'dayplan.noteTitle': 'Nota', + 'dayplan.noteSubtitle': 'Nota giornaliera', + 'dayplan.totalCost': 'Costo totale', + 'dayplan.days': 'Giorni', + 'dayplan.dayN': 'Giorno {n}', + 'dayplan.calculating': 'Calcolo in corso...', + 'dayplan.route': 'Percorso', + 'dayplan.optimize': 'Ottimizza', + 'dayplan.optimized': 'Percorso ottimizzato', + 'dayplan.routeError': 'Impossibile calcolare il percorso', + 'dayplan.toast.needTwoPlaces': 'Servono almeno due luoghi per l\'ottimizzazione del percorso', + 'dayplan.toast.routeOptimized': 'Percorso ottimizzato', + 'dayplan.toast.noGeoPlaces': 'Nessun luogo con coordinate trovato per il calcolo del percorso', + 'dayplan.confirmed': 'Confermata', + 'dayplan.pendingRes': 'In attesa', + 'dayplan.pdf': 'PDF', + 'dayplan.pdfTooltip': 'Esporta il programma del giorno come PDF', + 'dayplan.pdfError': 'Impossibile esportare il PDF', + 'dayplan.cannotReorderTransport': 'Le prenotazioni con un orario fisso non possono essere riordinate', + 'dayplan.confirmRemoveTimeTitle': 'Rimuovere l\'orario?', + 'dayplan.confirmRemoveTimeBody': 'Questo luogo ha un orario fisso ({time}). Spostarlo rimuoverà l\'orario e consentirà l\'ordinamento libero.', + 'dayplan.confirmRemoveTimeAction': 'Rimuovi orario e sposta', + 'dayplan.cannotDropOnTimed': 'Gli elementi non possono essere posizionati tra voci con orario fisso', + 'dayplan.cannotBreakChronology': 'Ciò interromperebbe l\'ordine cronologico degli elementi e delle prenotazioni pianificati', + + // Places Sidebar + 'places.addPlace': 'Aggiungi Luogo/Attività', + 'places.importGpx': 'Importa GPX', + 'places.gpxImported': '{count} luoghi importati da GPX', + 'places.urlResolved': 'Luogo importato dall\'URL', + 'places.gpxError': 'Importazione GPX non riuscita', + 'places.assignToDay': 'A quale giorno aggiungere?', + 'places.all': 'Tutti', + 'places.unplanned': 'Non pianificati', + 'places.search': 'Cerca luoghi...', + 'places.allCategories': 'Tutte le categorie', + 'places.categoriesSelected': 'categorie', + 'places.clearFilter': 'Cancella filtro', + 'places.count': '{count} luoghi', + 'places.countSingular': '1 luogo', + 'places.allPlanned': 'Tutti i luoghi sono programmati', + 'places.noneFound': 'Nessun luogo trovato', + 'places.editPlace': 'Modifica luogo', + 'places.formName': 'Nome', + 'places.formNamePlaceholder': 'es. Torre Eiffel', + 'places.formDescription': 'Descrizione', + 'places.formDescriptionPlaceholder': 'Breve descrizione...', + 'places.formAddress': 'Indirizzo', + 'places.formAddressPlaceholder': 'Via, Città, Paese', + 'places.formLat': 'Latitudine (es. 48.8566)', + 'places.formLng': 'Longitudine (es. 2.3522)', + 'places.formCategory': 'Categoria', + 'places.noCategory': 'Nessuna categoria', + 'places.categoryNamePlaceholder': 'Nome categoria', + 'places.formTime': 'Ora', + 'places.startTime': 'Inizio', + 'places.endTime': 'Fine', + 'places.endTimeBeforeStart': 'L\'ora di fine è precedente all\'ora di inizio', + 'places.timeCollision': 'Sovrapposizione di orario con:', + 'places.formWebsite': 'Sito web', + 'places.formNotesPlaceholder': 'Note personali...', + 'places.formReservation': 'Prenotazione', + 'places.reservationNotesPlaceholder': 'Note della prenotazione, numero di conferma...', + 'places.mapsSearchPlaceholder': 'Cerca luoghi...', + 'places.mapsSearchError': 'Impossibile cercare i luoghi.', + 'places.osmHint': 'Uso della ricerca OpenStreetMap (senza foto, orari di apertura o valutazioni). Aggiungi una chiave API Google nelle impostazioni per i dettagli completi.', + 'places.osmActive': 'Ricerca tramite OpenStreetMap (senza foto, valutazioni o orari di apertura). Aggiungi una chiave API Google nelle Impostazioni per dati avanzati.', + 'places.categoryCreateError': 'Impossibile creare la categoria', + 'places.nameRequired': 'Inserisci un nome', + 'places.saveError': 'Impossibile salvare', + // Place Inspector + 'inspector.opened': 'Aperto', + 'inspector.closed': 'Chiuso', + 'inspector.openingHours': 'Orari di apertura', + 'inspector.showHours': 'Mostra orari di apertura', + 'inspector.files': 'File', + 'inspector.filesCount': '{count} file', + 'inspector.removeFromDay': 'Rimuovi dal giorno', + 'inspector.addToDay': 'Aggiungi al giorno', + 'inspector.confirmedRes': 'Prenotazione confermata', + 'inspector.pendingRes': 'Prenotazione in attesa', + 'inspector.google': 'Apri in Google Maps', + 'inspector.website': 'Apri sito web', + 'inspector.addRes': 'Prenotazione', + 'inspector.editRes': 'Modifica prenotazione', + 'inspector.participants': 'Partecipanti', + + // Reservations + 'reservations.title': 'Prenotazioni', + 'reservations.empty': 'Ancora nessuna prenotazione', + 'reservations.emptyHint': 'Aggiungi prenotazioni per voli, alloggi e altro', + 'reservations.add': 'Aggiungi prenotazione', + 'reservations.addManual': 'Prenotazione manuale', + 'reservations.placeHint': 'Suggerimento: è meglio creare le prenotazioni direttamente da un luogo per collegarle al tuo programma del giorno.', + 'reservations.confirmed': 'Confermata', + 'reservations.pending': 'In attesa', + 'reservations.summary': '{confirmed} confermate, {pending} in attesa', + 'reservations.fromPlan': 'Dal programma', + 'reservations.showFiles': 'Mostra file', + 'reservations.editTitle': 'Modifica prenotazione', + 'reservations.status': 'Stato', + 'reservations.datetime': 'Data e ora', + 'reservations.startTime': 'Ora di inizio', + 'reservations.endTime': 'Ora di fine', + 'reservations.date': 'Data', + 'reservations.time': 'Ora', + 'reservations.timeAlt': 'Ora (alternativa, es. 19:30)', + 'reservations.notes': 'Note', + 'reservations.notesPlaceholder': 'Note aggiuntive...', + 'reservations.meta.airline': 'Compagnia aerea', + 'reservations.meta.flightNumber': 'N. volo', + 'reservations.meta.from': 'Da', + 'reservations.meta.to': 'A', + 'reservations.meta.trainNumber': 'N. treno', + 'reservations.meta.platform': 'Binario', + 'reservations.meta.seat': 'Posto', + 'reservations.meta.checkIn': 'Check-in', + 'reservations.meta.checkOut': 'Check-out', + 'reservations.meta.linkAccommodation': 'Alloggio', + 'reservations.meta.pickAccommodation': 'Collega a un alloggio', + 'reservations.meta.noAccommodation': 'Nessuno', + 'reservations.meta.hotelPlace': 'Alloggio', + 'reservations.meta.pickHotel': 'Seleziona alloggio', + 'reservations.meta.fromDay': 'Da', + 'reservations.meta.toDay': 'A', + 'reservations.meta.selectDay': 'Seleziona giorno', + 'reservations.type.flight': 'Volo', + 'reservations.type.hotel': 'Alloggio', + 'reservations.type.restaurant': 'Ristorante', + 'reservations.type.train': 'Treno', + 'reservations.type.car': 'Auto a noleggio', + 'reservations.type.cruise': 'Crociera', + 'reservations.type.event': 'Evento', + 'reservations.type.tour': 'Tour', + 'reservations.type.other': 'Altro', + 'reservations.confirm.delete': 'Sei sicuro di voler eliminare la prenotazione "{name}"?', + 'reservations.confirm.deleteTitle': 'Eliminare la prenotazione?', + 'reservations.confirm.deleteBody': '"{name}" verrà eliminato in modo permanente.', + 'reservations.toast.updated': 'Prenotazione aggiornata', + 'reservations.toast.removed': 'Prenotazione eliminata', + 'reservations.toast.fileUploaded': 'File caricato', + 'reservations.toast.uploadError': 'Impossibile caricare', + 'reservations.newTitle': 'Nuova prenotazione', + 'reservations.bookingType': 'Tipo di prenotazione', + 'reservations.titleLabel': 'Titolo', + 'reservations.titlePlaceholder': 'es. Lufthansa LH123, Hotel Adlon, ...', + 'reservations.locationAddress': 'Posizione / Indirizzo', + 'reservations.locationPlaceholder': 'Indirizzo, aeroporto, hotel...', + 'reservations.confirmationCode': 'Codice prenotazione', + 'reservations.confirmationPlaceholder': 'es. ABC12345', + 'reservations.day': 'Giorno', + 'reservations.noDay': 'Nessun giorno', + 'reservations.place': 'Luogo', + 'reservations.noPlace': 'Nessun luogo', + 'reservations.pendingSave': 'verrà salvato…', + 'reservations.uploading': 'Caricamento...', + 'reservations.attachFile': 'Allega file', + 'reservations.linkExisting': 'Collega file esistente', + 'reservations.toast.saveError': 'Impossibile salvare', + 'reservations.toast.updateError': 'Impossibile aggiornare', + 'reservations.toast.deleteError': 'Impossibile eliminare', + 'reservations.confirm.remove': 'Rimuovere la prenotazione per "{name}"?', + 'reservations.linkAssignment': 'Collega all\'assegnazione del giorno', + 'reservations.pickAssignment': 'Seleziona un\'assegnazione dal tuo programma...', + 'reservations.noAssignment': 'Nessun collegamento (autonomo)', + + // Budget + 'budget.title': 'Budget', + 'budget.emptyTitle': 'Ancora nessun budget creato', + 'budget.emptyText': 'Crea categorie e voci per pianificare il budget del tuo viaggio', + 'budget.emptyPlaceholder': 'Inserisci nome categoria...', + 'budget.createCategory': 'Crea categoria', + 'budget.category': 'Categoria', + 'budget.categoryName': 'Nome categoria', + 'budget.table.name': 'Nome', + 'budget.table.total': 'Totale', + 'budget.table.persons': 'Persone', + 'budget.table.days': 'Giorni', + 'budget.table.perPerson': 'Per persona', + 'budget.table.perDay': 'Per giorno', + 'budget.table.perPersonDay': 'P. p / gio.', + 'budget.table.note': 'Nota', + 'budget.newEntry': 'Nuova voce', + 'budget.defaultEntry': 'Nuova voce', + 'budget.defaultCategory': 'Nuova categoria', + 'budget.total': 'Totale', + 'budget.totalBudget': 'Budget totale', + 'budget.byCategory': 'Per categoria', + 'budget.editTooltip': 'Clicca per modificare', + 'budget.confirm.deleteCategory': 'Sei sicuro di voler eliminare la categoria "{name}" con {count} voci?', + 'budget.deleteCategory': 'Elimina categoria', + 'budget.perPerson': 'Per persona', + 'budget.paid': 'Pagato', + 'budget.open': 'Aperto', + 'budget.noMembers': 'Nessun membro assegnato', + 'budget.settlement': 'Regolamento', + 'budget.settlementInfo': 'Clicca sull\'avatar di un membro su una voce di budget per contrassegnarlo in verde — significa che ha pagato. Il regolamento mostra poi chi deve quanto a chi.', + 'budget.netBalances': 'Saldi netti', + + // Files + 'files.title': 'File', + 'files.count': '{count} file', + 'files.countSingular': '1 file', + 'files.uploaded': '{count} caricati', + 'files.uploadError': 'Caricamento non riuscito', + 'files.dropzone': 'Trascina qui i file', + 'files.dropzoneHint': 'oppure clicca per sfogliare', + 'files.allowedTypes': 'Immagini, PDF, DOC, DOCX, XLS, XLSX, TXT, CSV · Max 50 MB', + 'files.uploading': 'Caricamento...', + 'files.filterAll': 'Tutti', + 'files.filterPdf': 'PDF', + 'files.filterImages': 'Immagini', + 'files.filterDocs': 'Documenti', + 'files.filterCollab': 'Note Collaborazione', + 'files.sourceCollab': 'Da Note Collaborazione', + 'files.empty': 'Ancora nessun file', + 'files.emptyHint': 'Carica file per allegarli al tuo viaggio', + 'files.openTab': 'Apri in una nuova scheda', + 'files.confirm.delete': 'Sei sicuro di voler eliminare questo file?', + 'files.toast.deleted': 'File eliminato', + 'files.toast.deleteError': 'Impossibile eliminare il file', + 'files.sourcePlan': 'Programma giornaliero', + 'files.sourceBooking': 'Prenotazione', + 'files.attach': 'Allega', + 'files.pasteHint': 'Puoi anche incollare immagini dagli appunti (Ctrl+V)', + 'files.trash': 'Cestino', + 'files.trashEmpty': 'Il cestino è vuoto', + 'files.emptyTrash': 'Svuota cestino', + 'files.restore': 'Ripristina', + 'files.star': 'Aggiungi ai preferiti', + 'files.unstar': 'Rimuovi dai preferiti', + 'files.assign': 'Assegna', + 'files.assignTitle': 'Assegna file', + 'files.assignPlace': 'Luogo', + 'files.assignBooking': 'Prenotazione', + 'files.unassigned': 'Non assegnato', + 'files.unlink': 'Rimuovi collegamento', + 'files.toast.trashed': 'Spostato nel cestino', + 'files.toast.restored': 'File ripristinato', + 'files.toast.trashEmptied': 'Cestino svuotato', + 'files.toast.assigned': 'File assegnato', + 'files.toast.assignError': 'Assegnazione fallita', + 'files.toast.restoreError': 'Ripristino fallito', + 'files.confirm.permanentDelete': 'Eliminare questo file in modo permanente? Questa operazione non può essere annullata.', + 'files.confirm.emptyTrash': 'Eliminare in modo permanente tutti i file nel cestino? Questa operazione non può essere annullata.', + 'files.noteLabel': 'Nota', + 'files.notePlaceholder': 'Aggiungi una nota...', + + // Packing + 'packing.title': 'Lista valigia', + 'packing.empty': 'La lista valigia è vuota', + 'packing.import': 'Importa', + 'packing.importTitle': 'Importa lista valigia', + 'packing.importHint': 'Un elemento per riga. Formato: Categoria, Nome, Peso in g (opzionale), Borsa (opzionale), checked/unchecked (opzionale)', + 'packing.importPlaceholder': 'Igiene, Spazzolino\nAbbigliamento, Magliette, 200\nDocumenti, Passaporto, , Bagaglio a mano\nElettronica, Caricabatterie, 50, Valigia, checked', + 'packing.importCsv': 'Carica CSV/TXT', + 'packing.importAction': 'Importa {count}', + 'packing.importSuccess': '{count} elementi importati', + 'packing.importError': 'Importazione non riuscita', + 'packing.importEmpty': 'Nessun elemento da importare', + 'packing.progress': '{packed} di {total} in valigia ({percent}%)', + 'packing.clearChecked': 'Rimuovi {count} spuntati', + 'packing.clearCheckedShort': 'Rimuovi {count}', + 'packing.suggestions': 'Suggerimenti', + 'packing.suggestionsTitle': 'Aggiungi suggerimenti', + 'packing.allSuggested': 'Tutti i suggerimenti aggiunti', + 'packing.allPacked': 'Tutto in valigia!', + 'packing.addPlaceholder': 'Aggiungi nuovo elemento...', + 'packing.categoryPlaceholder': 'Categoria...', + 'packing.filterAll': 'Tutti', + 'packing.filterOpen': 'Da fare', + 'packing.filterDone': 'Fatto', + 'packing.emptyTitle': 'La lista valigia è vuota', + 'packing.emptyHint': 'Aggiungi elementi o usa i suggerimenti', + 'packing.emptyFiltered': 'Nessun elemento corrisponde a questo filtro', + 'packing.menuRename': 'Rinomina', + 'packing.menuCheckAll': 'Seleziona tutti', + 'packing.menuUncheckAll': 'Deseleziona tutti', + 'packing.menuDeleteCat': 'Elimina categoria', + 'packing.assignUser': 'Assegna utente', + 'packing.noMembers': 'Nessun membro del viaggio', + 'packing.addItem': 'Aggiungi elemento', + 'packing.addItemPlaceholder': 'Nome elemento...', + 'packing.addCategory': 'Aggiungi categoria', + 'packing.newCategoryPlaceholder': 'Nome categoria (es. Abbigliamento)', + 'packing.applyTemplate': 'Applica modello', + 'packing.template': 'Modello', + 'packing.templateApplied': '{count} elementi aggiunti dal modello', + 'packing.templateError': 'Impossibile applicare il modello', + 'packing.bags': 'Valigie', + 'packing.noBag': 'Non assegnato', + 'packing.totalWeight': 'Peso totale', + 'packing.bagName': 'Nome valigia...', + 'packing.addBag': 'Aggiungi valigia', + 'packing.changeCategory': 'Cambia categoria', + 'packing.confirm.clearChecked': 'Sei sicuro di voler rimuovere {count} elementi spuntati?', + 'packing.confirm.deleteCat': 'Sei sicuro di voler eliminare la categoria "{name}" con {count} elementi?', + 'packing.defaultCategory': 'Altro', + 'packing.toast.saveError': 'Impossibile salvare', + 'packing.toast.deleteError': 'Impossibile eliminare', + 'packing.toast.renameError': 'Impossibile rinominare', + 'packing.toast.addError': 'Impossibile aggiungere', + + // Packing suggestions + 'packing.suggestions.items': [ + { name: 'Passaporto', category: 'Documenti' }, + { name: 'Carta d\'identità', category: 'Documenti' }, + { name: 'Assicurazione di viaggio', category: 'Documenti' }, + { name: 'Biglietti aerei', category: 'Documenti' }, + { name: 'Carta di credito', category: 'Finanze' }, + { name: 'Contanti', category: 'Finanze' }, + { name: 'Visto', category: 'Documenti' }, + { name: 'Magliette', category: 'Abbigliamento' }, + { name: 'Pantaloni', category: 'Abbigliamento' }, + { name: 'Intimo', category: 'Abbigliamento' }, + { name: 'Calzini', category: 'Abbigliamento' }, + { name: 'Giacca', category: 'Abbigliamento' }, + { name: 'Pigiama', category: 'Abbigliamento' }, + { name: 'Costume da bagno', category: 'Abbigliamento' }, + { name: 'Giacca a vento', category: 'Abbigliamento' }, + { name: 'Scarpe comode', category: 'Abbigliamento' }, + { name: 'Spazzolino da denti', category: 'Igiene personale' }, + { name: 'Dentifricio', category: 'Igiene personale' }, + { name: 'Shampoo', category: 'Igiene personale' }, + { name: 'Deodorante', category: 'Igiene personale' }, + { name: 'Crema solare', category: 'Igiene personale' }, + { name: 'Rasoio', category: 'Igiene personale' }, + { name: 'Caricabatterie', category: 'Elettronica' }, + { name: 'Power bank', category: 'Elettronica' }, + { name: 'Cuffie', category: 'Elettronica' }, + { name: 'Adattatore da viaggio', category: 'Elettronica' }, + { name: 'Macchina fotografica', category: 'Elettronica' }, + { name: 'Antidolorifici', category: 'Salute' }, + { name: 'Cerotti', category: 'Salute' }, + { name: 'Disinfettante', category: 'Salute' }, + ], + + // Members / Sharing + 'members.shareTrip': 'Condividi viaggio', + 'members.inviteUser': 'Invita utente', + 'members.selectUser': 'Seleziona utente...', + 'members.invite': 'Invita', + 'members.allHaveAccess': 'Tutti gli utenti hanno già accesso.', + 'members.access': 'Accesso', + 'members.person': 'persona', + 'members.persons': 'persone', + 'members.you': 'tu', + 'members.owner': 'Proprietario', + 'members.leaveTrip': 'Abbandona viaggio', + 'members.removeAccess': 'Rimuovi accesso', + 'members.confirmLeave': 'Abbandonare il viaggio? Perderai l\'accesso.', + 'members.confirmRemove': 'Rimuovere l\'accesso per questo utente?', + 'members.loadError': 'Impossibile caricare i membri', + 'members.added': 'aggiunto', + 'members.addError': 'Impossibile aggiungere', + 'members.removed': 'Membro rimosso', + 'members.removeError': 'Impossibile rimuovere', + + // Categories (Admin) + 'categories.title': 'Categorie', + 'categories.subtitle': 'Gestisci le categorie per i luoghi', + 'categories.new': 'Nuova categoria', + 'categories.empty': 'Ancora nessuna categoria', + 'categories.namePlaceholder': 'Nome categoria', + 'categories.icon': 'Icona', + 'categories.color': 'Colore', + 'categories.customColor': 'Scegli colore personalizzato', + 'categories.preview': 'Anteprima', + 'categories.defaultName': 'Categoria', + 'categories.update': 'Aggiorna', + 'categories.create': 'Crea', + 'categories.confirm.delete': 'Eliminare la categoria? I luoghi in questa categoria non verranno eliminati.', + 'categories.toast.loadError': 'Impossibile caricare le categorie', + 'categories.toast.nameRequired': 'Inserisci un nome', + 'categories.toast.updated': 'Categoria aggiornata', + 'categories.toast.created': 'Categoria creata', + 'categories.toast.saveError': 'Impossibile salvare', + 'categories.toast.deleted': 'Categoria eliminata', + 'categories.toast.deleteError': 'Impossibile eliminare', + + // Backup (Admin) + 'backup.title': 'Backup dati', + 'backup.subtitle': 'Database e tutti i file caricati', + 'backup.refresh': 'Aggiorna', + 'backup.upload': 'Carica backup', + 'backup.uploading': 'Caricamento...', + 'backup.create': 'Crea backup', + 'backup.creating': 'Creazione...', + 'backup.empty': 'Ancora nessun backup', + 'backup.createFirst': 'Crea primo backup', + 'backup.download': 'Scarica', + 'backup.restore': 'Ripristina', + 'backup.confirm.restore': 'Ripristinare il backup "{name}"?\n\nTutti i dati attuali verranno sostituiti con il backup.', + 'backup.confirm.uploadRestore': 'Scaricare e ripristinare il file di backup "{name}"?\n\nTutti i dati attuali verranno sovrascritti.', + 'backup.confirm.delete': 'Eliminare il backup "{name}"?', + 'backup.toast.loadError': 'Impossibile caricare i backup', + 'backup.toast.created': 'Backup creato con successo', + 'backup.toast.createError': 'Impossibile creare il backup', + 'backup.toast.restored': 'Backup ripristinato. La pagina verrà ricaricata...', + 'backup.toast.restoreError': 'Impossibile ripristinare', + 'backup.toast.uploadError': 'Impossibile caricare', + 'backup.toast.deleted': 'Backup eliminato', + 'backup.toast.deleteError': 'Impossibile eliminare', + 'backup.toast.downloadError': 'Download non riuscito', + 'backup.toast.settingsSaved': 'Impostazioni auto-backup salvate', + 'backup.toast.settingsError': 'Impossibile salvare le impostazioni', + 'backup.auto.title': 'Auto-Backup', + 'backup.auto.subtitle': 'Backup automatico pianificato', + 'backup.auto.enable': 'Abilita auto-backup', + 'backup.auto.enableHint': 'I backup verranno creati automaticamente in base alla pianificazione scelta', + 'backup.auto.interval': 'Intervallo', + 'backup.auto.hour': 'Esegui all\'ora', + 'backup.auto.hourHint': 'Ora locale del server (formato {format})', + 'backup.auto.dayOfWeek': 'Giorno della settimana', + 'backup.auto.dayOfMonth': 'Giorno del mese', + 'backup.auto.dayOfMonthHint': 'Limitato a 1–28 per compatibilità con tutti i mesi', + 'backup.auto.scheduleSummary': 'Pianificazione', + 'backup.auto.summaryDaily': 'Ogni giorno alle {hour}:00', + 'backup.auto.summaryWeekly': 'Ogni {day} alle {hour}:00', + 'backup.auto.summaryMonthly': 'Giorno {day} di ogni mese alle {hour}:00', + 'backup.auto.envLocked': 'Docker', + 'backup.auto.envLockedHint': 'L\'auto-backup è configurato tramite variabili d\'ambiente Docker. Per modificare queste impostazioni, aggiorna il tuo docker-compose.yml e riavvia il container.', + 'backup.auto.copyEnv': 'Copia variabili env Docker', + 'backup.auto.envCopied': 'Variabili env Docker copiate negli appunti', + 'backup.auto.keepLabel': 'Elimina i vecchi backup dopo', + 'backup.dow.sunday': 'Dom', + 'backup.dow.monday': 'Lun', + 'backup.dow.tuesday': 'Mar', + 'backup.dow.wednesday': 'Mer', + 'backup.dow.thursday': 'Gio', + 'backup.dow.friday': 'Ven', + 'backup.dow.saturday': 'Sab', + 'backup.interval.hourly': 'Ogni ora', + 'backup.interval.daily': 'Giornaliero', + 'backup.interval.weekly': 'Settimanale', + 'backup.interval.monthly': 'Mensile', + 'backup.keep.1day': '1 giorno', + 'backup.keep.3days': '3 giorni', + 'backup.keep.7days': '7 giorni', + 'backup.keep.14days': '14 giorni', + 'backup.keep.30days': '30 giorni', + 'backup.keep.forever': 'Conserva per sempre', + + // Photos + 'photos.allDays': 'Tutti i giorni', + 'photos.noPhotos': 'Ancora nessuna foto', + 'photos.uploadHint': 'Carica le foto del tuo viaggio', + 'photos.clickToSelect': 'o clicca per selezionare', + 'photos.linkPlace': 'Collega luogo', + 'photos.noPlace': 'Nessun luogo', + 'photos.uploadN': 'Caricamento di {n} foto', + + // Backup restore modal + 'backup.restoreConfirmTitle': 'Ripristinare il backup?', + 'backup.restoreWarning': 'Tutti i dati attuali (viaggi, luoghi, utenti, caricamenti) verranno sostituiti in modo permanente dal backup. Questa azione non può essere annullata.', + 'backup.restoreTip': 'Suggerimento: Crea un backup dello stato attuale prima di ripristinare.', + 'backup.restoreConfirm': 'Sì, ripristina', + + // PDF + 'pdf.travelPlan': 'Programma di viaggio', + 'pdf.planned': 'Programmato', + 'pdf.costLabel': 'Costo EUR', + 'pdf.preview': 'Anteprima PDF', + 'pdf.saveAsPdf': 'Salva come PDF', + + // Planner + 'planner.places': 'Luoghi', + 'planner.bookings': 'Prenotazioni', + 'planner.packingList': 'Lista valigia', + 'planner.documents': 'Documenti', + 'planner.dayPlan': 'Programma giornaliero', + 'planner.reservations': 'Prenotazioni', + 'planner.minTwoPlaces': 'Servono almeno 2 luoghi con coordinate', + 'planner.noGeoPlaces': 'Nessun luogo con coordinate disponibile', + 'planner.routeCalculated': 'Percorso calcolato', + 'planner.routeCalcFailed': 'Il percorso non è stato calcolato', + 'planner.routeError': 'Errore nel calcolo del percorso', + 'planner.routeOptimized': 'Percorso ottimizzato', + 'planner.reservationUpdated': 'Prenotazione aggiornata', + 'planner.reservationAdded': 'Prenotazione aggiunta', + 'planner.confirmDeleteReservation': 'Eliminare la prenotazione?', + 'planner.reservationDeleted': 'Prenotazione eliminata', + 'planner.days': 'Giorni', + 'planner.allPlaces': 'Tutti i luoghi', + 'planner.totalPlaces': '{n} luoghi in totale', + 'planner.noDaysPlanned': 'Nessun giorno ancora programmato', + 'planner.editTrip': 'Modifica viaggio \u2192', + 'planner.placeOne': '1 luogo', + 'planner.placeN': '{n} luoghi', + 'planner.addNote': 'Aggiungi nota', + 'planner.noEntries': 'Nessuna voce per questo giorno', + 'planner.addPlace': 'Aggiungi luogo/attività', + 'planner.addPlaceShort': '+ Aggiungi luogo/attività', + 'planner.resPending': 'Prenotazione in attesa \u00B7 ', + 'planner.resConfirmed': 'Prenotazione confermata \u00B7 ', + 'planner.notePlaceholder': 'Nota\u2026', + 'planner.noteTimePlaceholder': 'Ora (opzionale)', + 'planner.noteExamplePlaceholder': 'es. S3 alle 14:30 dalla stazione centrale, traghetto dal molo 7, pausa pranzo\u2026', + 'planner.totalCost': 'Costo totale', + 'planner.searchPlaces': 'Cerca luoghi\u2026', + 'planner.allCategories': 'Tutte le categorie', + 'planner.noPlacesFound': 'Nessun luogo trovato', + 'planner.addFirstPlace': 'Aggiungi primo luogo', + 'planner.noReservations': 'Nessuna prenotazione', + 'planner.addFirstReservation': 'Aggiungi prima prenotazione', + 'planner.new': 'Nuovo', + 'planner.addToDay': '+ Giorno', + 'planner.calculating': 'Calcolo in corso\u2026', + 'planner.route': 'Percorso', + 'planner.optimize': 'Ottimizza', + 'planner.openGoogleMaps': 'Apri in Google Maps', + 'planner.selectDayHint': 'Seleziona un giorno dall\'elenco a sinistra per vedere il programma', + 'planner.noPlacesForDay': 'Ancora nessun luogo per questo giorno', + 'planner.addPlacesLink': 'Aggiungi luoghi \u2192', + 'planner.minTotal': 'min. totali', + 'planner.noReservation': 'Nessuna prenotazione', + 'planner.removeFromDay': 'Rimuovi dal giorno', + 'planner.addToThisDay': 'Aggiungi al giorno', + 'planner.overview': 'Panoramica', + 'planner.noDays': 'Ancora nessun giorno', + 'planner.editTripToAddDays': 'Modifica viaggio per aggiungere giorni', + 'planner.dayCount': '{n} Giorni', + 'planner.clickToUnlock': 'Clicca per sbloccare', + 'planner.keepPosition': 'Mantieni la posizione durante l\'ottimizzazione del percorso', + 'planner.dayDetails': 'Dettagli del giorno', + 'planner.dayN': 'Giorno {n}', + + // Dashboard Stats + 'stats.countries': 'Paesi', + 'stats.cities': 'Città', + 'stats.trips': 'Viaggi', + 'stats.places': 'Luoghi', + 'stats.worldProgress': 'Progresso nel mondo', + 'stats.visited': 'visitati', + 'stats.remaining': 'rimanenti', + 'stats.visitedCountries': 'Paesi visitati', + + // Day Detail Panel + 'day.precipProb': 'Probabilità di pioggia', + 'day.precipitation': 'Precipitazioni', + 'day.wind': 'Vento', + 'day.sunrise': 'Alba', + 'day.sunset': 'Tramonto', + 'day.hourlyForecast': 'Previsione oraria', + 'day.climateHint': 'Medie storiche \u2014 previsioni reali disponibili entro 16 giorni da questa data.', + 'day.noWeather': 'Nessun dato meteo disponibile. Aggiungi un luogo con coordinate.', + 'day.overview': 'Panoramica giornaliera', + 'day.accommodation': 'Alloggio', + 'day.addAccommodation': 'Aggiungi alloggio', + 'day.hotelDayRange': 'Applica ai giorni', + 'day.noPlacesForHotel': 'Aggiungi prima i luoghi al tuo viaggio', + 'day.allDays': 'Tutti', + 'day.checkIn': 'Check-in', + 'day.checkOut': 'Check-out', + 'day.confirmation': 'Conferma', + 'day.editAccommodation': 'Modifica alloggio', + 'day.reservations': 'Prenotazioni', + + // Photos / Immich + 'memories.title': 'Foto', + 'memories.notConnected': 'Immich non connesso', + 'memories.notConnectedHint': 'Connetti la tua istanza Immich nelle Impostazioni per vedere qui le foto del tuo viaggio.', + 'memories.noDates': 'Aggiungi le date al tuo viaggio per caricare le foto.', + 'memories.noPhotos': 'Nessuna foto trovata', + 'memories.noPhotosHint': 'Nessuna foto trovata in Immich per l\'intervallo di date di questo viaggio.', + 'memories.photosFound': 'foto', + 'memories.fromOthers': 'da altri', + 'memories.sharePhotos': 'Condividi foto', + 'memories.sharing': 'Condivisione', + 'memories.reviewTitle': 'Rivedi le tue foto', + 'memories.reviewHint': 'Clicca sulle foto per escluderle dalla condivisione.', + 'memories.shareCount': 'Condividi {count} foto', + 'memories.immichUrl': 'URL Server Immich', + 'memories.immichApiKey': 'Chiave API', + 'memories.testConnection': 'Test connessione', + 'memories.connected': 'Connesso', + 'memories.disconnected': 'Non connesso', + 'memories.connectionSuccess': 'Connesso a Immich', + 'memories.connectionError': 'Impossibile connettersi a Immich', + 'memories.saved': 'Impostazioni Immich salvate', + 'memories.addPhotos': 'Aggiungi foto', + 'memories.selectPhotos': 'Seleziona foto da Immich', + 'memories.selectHint': 'Tocca le foto per selezionarle.', + 'memories.selected': 'selezionate', + 'memories.addSelected': 'Aggiungi {count} foto', + 'memories.alreadyAdded': 'Aggiunta', + 'memories.private': 'Privato', + 'memories.stopSharing': 'Interrompi condivisione', + 'memories.oldest': 'Prima le più vecchie', + 'memories.newest': 'Prima le più recenti', + 'memories.allLocations': 'Tutte le posizioni', + 'memories.tripDates': 'Date del viaggio', + 'memories.allPhotos': 'Tutte le foto', + 'memories.confirmShareTitle': 'Condividere con i membri del viaggio?', + 'memories.confirmShareHint': '{count} foto saranno visibili a tutti i membri di questo viaggio. Potrai rendere private le singole foto in seguito.', + 'memories.confirmShareButton': 'Condividi foto', + + // Collab Addon + 'collab.tabs.chat': 'Chat', + 'collab.tabs.notes': 'Note', + 'collab.tabs.polls': 'Sondaggi', + 'collab.whatsNext.title': "Cosa c'è dopo", + 'collab.whatsNext.today': 'Oggi', + 'collab.whatsNext.tomorrow': 'Domani', + 'collab.whatsNext.empty': 'Nessuna attività imminente', + 'collab.whatsNext.until': 'a', + 'collab.whatsNext.emptyHint': 'Le attività con orari appariranno qui', + 'collab.chat.send': 'Invia', + 'collab.chat.placeholder': 'Scrivi un messaggio...', + 'collab.chat.empty': 'Inizia la conversazione', + 'collab.chat.emptyHint': 'I messaggi sono condivisi con tutti i membri del viaggio', + 'collab.chat.emptyDesc': 'Condividi idee, programmi e aggiornamenti con il tuo gruppo di viaggio', + 'collab.chat.today': 'Oggi', + 'collab.chat.yesterday': 'Ieri', + 'collab.chat.deletedMessage': 'ha eliminato un messaggio', + 'collab.chat.loadMore': 'Carica messaggi precedenti', + 'collab.chat.justNow': 'ora', + 'collab.chat.minutesAgo': '{n}m fa', + 'collab.chat.hoursAgo': '{n}h fa', + 'collab.notes.title': 'Note', + 'collab.notes.new': 'Nuova nota', + 'collab.notes.empty': 'Ancora nessuna nota', + 'collab.notes.emptyHint': 'Inizia a raccogliere idee e programmi', + 'collab.notes.all': 'Tutte', + 'collab.notes.titlePlaceholder': 'Titolo della nota', + 'collab.notes.contentPlaceholder': 'Scrivi qualcosa...', + 'collab.notes.categoryPlaceholder': 'Categoria', + 'collab.notes.newCategory': 'Nuova categoria...', + 'collab.notes.category': 'Categoria', + 'collab.notes.noCategory': 'Nessuna categoria', + 'collab.notes.color': 'Colore', + 'collab.notes.save': 'Salva', + 'collab.notes.cancel': 'Annulla', + 'collab.notes.edit': 'Modifica', + 'collab.notes.delete': 'Elimina', + 'collab.notes.pin': 'Fissa', + 'collab.notes.unpin': 'Rimuovi', + 'collab.notes.daysAgo': '{n}g fa', + 'collab.notes.categorySettings': 'Gestisci categorie', + 'collab.notes.create': 'Crea', + 'collab.notes.website': 'Sito web', + 'collab.notes.websitePlaceholder': 'https://...', + 'collab.notes.attachFiles': 'Allega file', + 'collab.notes.noCategoriesYet': 'Ancora nessuna categoria', + 'collab.notes.emptyDesc': 'Crea una nota per iniziare', + 'collab.polls.title': 'Sondaggi', + 'collab.polls.new': 'Nuovo sondaggio', + 'collab.polls.empty': 'Ancora nessun sondaggio', + 'collab.polls.emptyHint': 'Chiedi al gruppo e votate insieme', + 'collab.polls.question': 'Domanda', + 'collab.polls.questionPlaceholder': 'Cosa dovremmo fare?', + 'collab.polls.addOption': '+ Aggiungi opzione', + 'collab.polls.optionPlaceholder': 'Opzione {n}', + 'collab.polls.create': 'Crea sondaggio', + 'collab.polls.close': 'Chiudi', + 'collab.polls.closed': 'Chiuso', + 'collab.polls.votes': '{n} voti', + 'collab.polls.vote': '{n} voto', + 'collab.polls.multipleChoice': 'Scelta multipla', + 'collab.polls.multiChoice': 'Scelta multipla', + 'collab.polls.deadline': 'Scadenza', + 'collab.polls.option': 'Opzione', + 'collab.polls.options': 'Opzioni', + 'collab.polls.delete': 'Elimina', + 'collab.polls.closedSection': 'Chiusi', +} + export default it \ No newline at end of file diff --git a/client/src/i18n/translations/nl.ts b/client/src/i18n/translations/nl.ts index 3cfab24..43a657c 100644 --- a/client/src/i18n/translations/nl.ts +++ b/client/src/i18n/translations/nl.ts @@ -238,6 +238,13 @@ const nl: Record = { 'settings.mfa.title': 'Tweefactorauthenticatie (2FA)', 'settings.mfa.description': 'Voegt een tweede stap toe bij het inloggen. Gebruik een authenticator-app (Google Authenticator, Authy, etc.).', 'settings.mfa.requiredByPolicy': 'Je beheerder vereist tweestapsverificatie. Stel hieronder een authenticator-app in voordat je verdergaat.', + 'settings.mfa.backupTitle': 'Back-upcodes', + 'settings.mfa.backupDescription': 'Gebruik deze eenmalige codes als je geen toegang meer hebt tot je authenticator-app.', + 'settings.mfa.backupWarning': 'Sla deze codes nu op. Elke code kan maar een keer worden gebruikt.', + 'settings.mfa.backupCopy': 'Codes kopiëren', + 'settings.mfa.backupDownload': 'TXT downloaden', + 'settings.mfa.backupPrint': 'Afdrukken / PDF', + 'settings.mfa.backupCopied': 'Back-upcodes gekopieerd', 'settings.mfa.enabled': '2FA is ingeschakeld op je account.', 'settings.mfa.disabled': '2FA is niet ingeschakeld.', 'settings.mfa.setup': 'Authenticator instellen', diff --git a/client/src/i18n/translations/ru.ts b/client/src/i18n/translations/ru.ts index a46ec2c..15854e9 100644 --- a/client/src/i18n/translations/ru.ts +++ b/client/src/i18n/translations/ru.ts @@ -238,6 +238,13 @@ const ru: Record = { 'settings.mfa.title': 'Двухфакторная аутентификация (2FA)', 'settings.mfa.description': 'Добавляет второй шаг при входе. Используйте приложение-аутентификатор (Google Authenticator, Authy и др.).', 'settings.mfa.requiredByPolicy': 'Администратор требует двухфакторную аутентификацию. Настройте приложение-аутентификатор ниже, прежде чем продолжить.', + 'settings.mfa.backupTitle': 'Резервные коды', + 'settings.mfa.backupDescription': 'Используйте эти одноразовые коды, если потеряете доступ к приложению-аутентификатору.', + 'settings.mfa.backupWarning': 'Сохраните их сейчас. Каждый код можно использовать только один раз.', + 'settings.mfa.backupCopy': 'Скопировать коды', + 'settings.mfa.backupDownload': 'Скачать TXT', + 'settings.mfa.backupPrint': 'Печать / PDF', + 'settings.mfa.backupCopied': 'Резервные коды скопированы', 'settings.mfa.enabled': '2FA включена для вашего аккаунта.', 'settings.mfa.disabled': '2FA не включена.', 'settings.mfa.setup': 'Настроить аутентификатор', diff --git a/client/src/i18n/translations/zh.ts b/client/src/i18n/translations/zh.ts index c47c951..65c0540 100644 --- a/client/src/i18n/translations/zh.ts +++ b/client/src/i18n/translations/zh.ts @@ -238,6 +238,13 @@ const zh: Record = { 'settings.mfa.title': '双因素认证 (2FA)', 'settings.mfa.description': '登录时添加第二步验证。使用身份验证器应用(Google Authenticator、Authy 等)。', 'settings.mfa.requiredByPolicy': '管理员要求双因素身份验证。请先完成下方的身份验证器设置后再继续。', + 'settings.mfa.backupTitle': '备用代码', + 'settings.mfa.backupDescription': '如果你无法使用身份验证器应用,可使用这些一次性备用代码登录。', + 'settings.mfa.backupWarning': '请立即保存这些代码。每个代码只能使用一次。', + 'settings.mfa.backupCopy': '复制代码', + 'settings.mfa.backupDownload': '下载 TXT', + 'settings.mfa.backupPrint': '打印 / PDF', + 'settings.mfa.backupCopied': '备用代码已复制', 'settings.mfa.enabled': '您的账户已启用 2FA。', 'settings.mfa.disabled': '2FA 未启用。', 'settings.mfa.setup': '设置身份验证器', diff --git a/client/src/pages/LoginPage.tsx b/client/src/pages/LoginPage.tsx index d083339..7121dfd 100644 --- a/client/src/pages/LoginPage.tsx +++ b/client/src/pages/LoginPage.tsx @@ -544,11 +544,11 @@ export default function LoginPage(): React.ReactElement { ) => setMfaCode(e.target.value.replace(/\D/g, '').slice(0, 8))} - placeholder="000000" + onChange={(e: React.ChangeEvent) => setMfaCode(e.target.value.toUpperCase().slice(0, 24))} + placeholder="000000 or XXXX-XXXX" required style={inputBase} onFocus={(e: React.FocusEvent) => e.target.style.borderColor = '#111827'} diff --git a/client/src/pages/SettingsPage.tsx b/client/src/pages/SettingsPage.tsx index 358be36..98bae0f 100644 --- a/client/src/pages/SettingsPage.tsx +++ b/client/src/pages/SettingsPage.tsx @@ -6,7 +6,7 @@ import { SUPPORTED_LANGUAGES, useTranslation } from '../i18n' import Navbar from '../components/Layout/Navbar' import CustomSelect from '../components/shared/CustomSelect' import { useToast } from '../components/shared/Toast' -import { Save, Map, Palette, User, Moon, Sun, Monitor, Shield, Camera, Trash2, Lock, KeyRound, AlertTriangle, Terminal, Copy, Plus, Check } from 'lucide-react' +import { Save, Map, Palette, User, Moon, Sun, Monitor, Shield, Camera, Trash2, Lock, KeyRound, AlertTriangle, Copy, Download, Printer, Terminal, Plus, Check } from 'lucide-react' import { authApi, adminApi, notificationsApi } from '../api/client' import apiClient from '../api/client' import { useAddonStore } from '../store/addonStore' @@ -19,6 +19,7 @@ interface MapPreset { url: string } +const MFA_BACKUP_SESSION_KEY = 'trek_mfa_backup_codes_pending' interface McpToken { id: number name: string @@ -271,6 +272,67 @@ export default function SettingsPage(): React.ReactElement { !user?.mfa_enabled && (searchParams.get('mfa') === 'required' || appRequireMfa) + const [backupCodes, setBackupCodes] = useState(null) + + const backupCodesText = backupCodes?.join('\n') || '' + + // Restore backup codes panel after refresh (loadUser silent fix + sessionStorage) + useEffect(() => { + if (!user?.mfa_enabled || backupCodes) return + try { + const raw = sessionStorage.getItem(MFA_BACKUP_SESSION_KEY) + if (!raw) return + const parsed = JSON.parse(raw) as unknown + if (Array.isArray(parsed) && parsed.length > 0 && parsed.every((x) => typeof x === 'string')) { + setBackupCodes(parsed) + } + } catch { + sessionStorage.removeItem(MFA_BACKUP_SESSION_KEY) + } + }, [user?.mfa_enabled, backupCodes]) + + const dismissBackupCodes = (): void => { + sessionStorage.removeItem(MFA_BACKUP_SESSION_KEY) + setBackupCodes(null) + } + + const copyBackupCodes = async (): Promise => { + if (!backupCodesText) return + try { + await navigator.clipboard.writeText(backupCodesText) + toast.success(t('settings.mfa.backupCopied')) + } catch { + toast.error(t('common.error')) + } + } + + const downloadBackupCodes = (): void => { + if (!backupCodesText) return + const blob = new Blob([backupCodesText + '\n'], { type: 'text/plain;charset=utf-8' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = 'trek-mfa-backup-codes.txt' + document.body.appendChild(a) + a.click() + a.remove() + URL.revokeObjectURL(url) + } + + const printBackupCodes = (): void => { + if (!backupCodesText) return + const html = `TREK MFA Backup Codes + +

TREK MFA Backup Codes

${new Date().toLocaleString()}

${backupCodesText}
` + const w = window.open('', '_blank', 'width=900,height=700') + if (!w) return + w.document.open() + w.document.write(html) + w.document.close() + w.focus() + w.print() + } + useEffect(() => { setMapTileUrl(settings.map_tile_url || '') setDefaultLat(settings.default_lat || 48.8566) @@ -955,12 +1017,21 @@ export default function SettingsPage(): React.ReactElement { onClick={async () => { setMfaLoading(true) try { - await authApi.mfaEnable({ code: mfaSetupCode }) + const resp = await authApi.mfaEnable({ code: mfaSetupCode }) as { backup_codes?: string[] } toast.success(t('settings.mfa.toastEnabled')) setMfaQr(null) setMfaSecret(null) setMfaSetupCode('') - await loadUser() + const codes = resp.backup_codes || null + if (codes?.length) { + try { + sessionStorage.setItem(MFA_BACKUP_SESSION_KEY, JSON.stringify(codes)) + } catch { + /* ignore quota / private mode */ + } + } + setBackupCodes(codes) + await loadUser({ silent: true }) } catch (err: unknown) { toast.error(getApiErrorMessage(err, t('common.error'))) } finally { @@ -1012,7 +1083,9 @@ export default function SettingsPage(): React.ReactElement { toast.success(t('settings.mfa.toastDisabled')) setMfaDisablePwd('') setMfaDisableCode('') - await loadUser() + sessionStorage.removeItem(MFA_BACKUP_SESSION_KEY) + setBackupCodes(null) + await loadUser({ silent: true }) } catch (err: unknown) { toast.error(getApiErrorMessage(err, t('common.error'))) } finally { @@ -1025,6 +1098,29 @@ export default function SettingsPage(): React.ReactElement { )} + + {backupCodes && backupCodes.length > 0 && ( +
+

{t('settings.mfa.backupTitle')}

+

{t('settings.mfa.backupDescription')}

+
{backupCodesText}
+

{t('settings.mfa.backupWarning')}

+
+ + + + +
+
+ )} )} diff --git a/client/src/store/authStore.ts b/client/src/store/authStore.ts index b26eb14..472d2d9 100644 --- a/client/src/store/authStore.ts +++ b/client/src/store/authStore.ts @@ -31,7 +31,8 @@ interface AuthState { completeMfaLogin: (mfaToken: string, code: string) => Promise register: (username: string, email: string, password: string) => Promise logout: () => void - loadUser: () => Promise + /** Pass `{ silent: true }` to refresh the user without toggling global isLoading (avoids unmounting protected routes). */ + loadUser: (opts?: { silent?: boolean }) => Promise updateMapsKey: (key: string | null) => Promise updateApiKeys: (keys: Record) => Promise updateProfile: (profileData: Partial) => Promise @@ -133,13 +134,14 @@ export const useAuthStore = create((set, get) => ({ }) }, - loadUser: async () => { + loadUser: async (opts?: { silent?: boolean }) => { + const silent = !!opts?.silent const token = get().token if (!token) { - set({ isLoading: false }) + if (!silent) set({ isLoading: false }) return } - set({ isLoading: true }) + if (!silent) set({ isLoading: true }) try { const data = await authApi.me() set({ diff --git a/server/src/db/migrations.ts b/server/src/db/migrations.ts index 451c5f9..a9adf1e 100644 --- a/server/src/db/migrations.ts +++ b/server/src/db/migrations.ts @@ -394,6 +394,10 @@ function runMigrations(db: Database.Database): void { CREATE INDEX IF NOT EXISTS idx_audit_log_created ON audit_log(created_at DESC); `); }, + () => { + // MFA backup/recovery codes + try { db.exec('ALTER TABLE users ADD COLUMN mfa_backup_codes TEXT'); } catch {} + }, // MCP long-lived API tokens () => db.exec(` CREATE TABLE IF NOT EXISTS mcp_tokens ( diff --git a/server/src/db/schema.ts b/server/src/db/schema.ts index c3ebe23..c6a5d23 100644 --- a/server/src/db/schema.ts +++ b/server/src/db/schema.ts @@ -17,6 +17,7 @@ function createTables(db: Database.Database): void { last_login DATETIME, mfa_enabled INTEGER DEFAULT 0, mfa_secret TEXT, + mfa_backup_codes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 357dd64..a481738 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -4,6 +4,7 @@ import jwt from 'jsonwebtoken'; import multer from 'multer'; import path from 'path'; import fs from 'fs'; +import crypto from 'crypto'; import { v4 as uuid } from 'uuid'; import fetch from 'node-fetch'; import { authenticator } from 'otplib'; @@ -21,6 +22,35 @@ authenticator.options = { window: 1 }; const MFA_SETUP_TTL_MS = 15 * 60 * 1000; const mfaSetupPending = new Map(); +const MFA_BACKUP_CODE_COUNT = 10; + +function normalizeBackupCode(input: string): string { + return String(input || '').toUpperCase().replace(/[^A-Z0-9]/g, ''); +} + +function hashBackupCode(input: string): string { + return crypto.createHash('sha256').update(normalizeBackupCode(input)).digest('hex'); +} + +function generateBackupCodes(count = MFA_BACKUP_CODE_COUNT): string[] { + const codes: string[] = []; + while (codes.length < count) { + const raw = crypto.randomBytes(4).toString('hex').toUpperCase(); + const code = `${raw.slice(0, 4)}-${raw.slice(4)}`; + if (!codes.includes(code)) codes.push(code); + } + return codes; +} + +function parseBackupCodeHashes(raw: string | null | undefined): string[] { + if (!raw) return []; + try { + const parsed = JSON.parse(raw); + return Array.isArray(parsed) ? parsed.filter(v => typeof v === 'string') : []; + } catch { + return []; + } +} function getPendingMfaSecret(userId: number): string | null { const row = mfaSetupPending.get(userId); @@ -43,6 +73,7 @@ function stripUserForClient(user: User): Record { openweather_api_key: _o, unsplash_api_key: _u, mfa_secret: _mf, + mfa_backup_codes: _mbc, ...rest } = user; return { @@ -664,10 +695,20 @@ router.post('/mfa/verify-login', authLimiter, (req: Request, res: Response) => { return res.status(401).json({ error: 'Invalid session' }); } const secret = decryptMfaSecret(user.mfa_secret); - const tokenStr = String(code).replace(/\s/g, ''); - const ok = authenticator.verify({ token: tokenStr, secret }); - if (!ok) { - return res.status(401).json({ error: 'Invalid verification code' }); + const tokenStr = String(code).trim(); + const okTotp = authenticator.verify({ token: tokenStr.replace(/\s/g, ''), secret }); + if (!okTotp) { + const hashes = parseBackupCodeHashes(user.mfa_backup_codes); + const candidateHash = hashBackupCode(tokenStr); + const idx = hashes.findIndex(h => h === candidateHash); + if (idx === -1) { + return res.status(401).json({ error: 'Invalid verification code' }); + } + hashes.splice(idx, 1); + db.prepare('UPDATE users SET mfa_backup_codes = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run( + JSON.stringify(hashes), + user.id + ); } db.prepare('UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?').run(user.id); const sessionToken = generateToken(user); @@ -721,14 +762,17 @@ router.post('/mfa/enable', authenticate, (req: Request, res: Response) => { if (!ok) { return res.status(401).json({ error: 'Invalid verification code' }); } + const backupCodes = generateBackupCodes(); + const backupHashes = backupCodes.map(hashBackupCode); const enc = encryptMfaSecret(pending); - db.prepare('UPDATE users SET mfa_enabled = 1, mfa_secret = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run( + db.prepare('UPDATE users SET mfa_enabled = 1, mfa_secret = ?, mfa_backup_codes = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run( enc, + JSON.stringify(backupHashes), authReq.user.id ); mfaSetupPending.delete(authReq.user.id); writeAudit({ userId: authReq.user.id, action: 'user.mfa_enable', ip: getClientIp(req) }); - res.json({ success: true, mfa_enabled: true }); + res.json({ success: true, mfa_enabled: true, backup_codes: backupCodes }); }); router.post('/mfa/disable', authenticate, rateLimiter(5, RATE_LIMIT_WINDOW), (req: Request, res: Response) => { @@ -757,7 +801,7 @@ router.post('/mfa/disable', authenticate, rateLimiter(5, RATE_LIMIT_WINDOW), (re if (!ok) { return res.status(401).json({ error: 'Invalid verification code' }); } - db.prepare('UPDATE users SET mfa_enabled = 0, mfa_secret = NULL, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run( + db.prepare('UPDATE users SET mfa_enabled = 0, mfa_secret = NULL, mfa_backup_codes = NULL, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run( authReq.user.id ); mfaSetupPending.delete(authReq.user.id); diff --git a/server/src/types.ts b/server/src/types.ts index 495b8c4..7db6a71 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -15,6 +15,7 @@ export interface User { last_login?: string | null; mfa_enabled?: number | boolean; mfa_secret?: string | null; + mfa_backup_codes?: string | null; created_at?: string; updated_at?: string; }