diff --git a/client/src/App.css b/client/src/App.css index d88dc43..d7117df 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -2165,6 +2165,16 @@ html.scheme-dark .themed-select-option.is-selected { color: var(--app-text-subtle); } +.entry-count-badge { + background: rgba(255, 255, 255, 0.05); + color: var(--app-text-muted); + padding: 2px 6px; + border-radius: 4px; + font-weight: 500; + display: inline-flex; + align-items: center; +} + .entry-sign-badge { position: relative; display: inline-flex; diff --git a/client/src/components/LogbookDashboard.tsx b/client/src/components/LogbookDashboard.tsx index febad3a..d0ffde3 100644 --- a/client/src/components/LogbookDashboard.tsx +++ b/client/src/components/LogbookDashboard.tsx @@ -35,10 +35,14 @@ function sortLogbooks( ): DecryptedLogbook[] { const sorted = [...items] sorted.sort((a, b) => { - const cmp = - sortBy === 'name' - ? a.title.localeCompare(b.title, locale, { sensitivity: 'base' }) - : new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime() + let cmp = 0 + if (sortBy === 'name') { + cmp = a.title.localeCompare(b.title, locale, { sensitivity: 'base' }) + } else { + const timeA = a.lastTravelDate ? new Date(a.lastTravelDate).getTime() : new Date(a.updatedAt).getTime() + const timeB = b.lastTravelDate ? new Date(b.lastTravelDate).getTime() : new Date(b.updatedAt).getTime() + cmp = timeA - timeB + } return direction === 'asc' ? cmp : -cmp }) return sorted @@ -288,8 +292,12 @@ export default function LogbookDashboard({ onSelectLogbook, onLogout, onOpenProf {lb.isDemo && ( {t('demo.badge')} )} + + + {lb.entryCount ?? 0} + - {new Date(lb.updatedAt).toLocaleDateString(i18n.language, { + {new Date(lb.lastTravelDate || lb.updatedAt).toLocaleDateString(i18n.language, { year: 'numeric', month: 'short', day: 'numeric' diff --git a/client/src/i18n/locales/da.json b/client/src/i18n/locales/da.json index 6f17a43..0c2ea89 100644 --- a/client/src/i18n/locales/da.json +++ b/client/src/i18n/locales/da.json @@ -65,7 +65,7 @@ "copied": "Kopieret!", "copy_phrase": "Kopier nøgle", "enter_recovery": "Indtast gendannelsesnøglen", - "recovery_fallback_warning": "Din Passkey er blevet godkendt, men din enhed understøtter ikke hardwarebaseret nøgleudledning. Indtast din 12-ords gendannelseskode for at dekryptere din logbog.", + "recovery_fallback_warning": "Din Passkey er blevet godkendt, men din enhed understøtter ikke hardwarebaseret nøgleudledning. Indtast din 12-ords gendannelsesnøgle for at dekryptere din logbog.", "recovery_placeholder": "Indtast din gendannelseskode, der består af 12 ord adskilt af mellemrum...", "back": "Tilbage", "decrypting": "Afkodning...", @@ -78,7 +78,7 @@ "processing": "Behandler...", "help": "Hjælp", "setup_pin_title": "Opsæt lokal PIN-kode (valgfrit)", - "setup_pin_warning": "Da din enhed ikke understøtter direkte Passkey-nøgleafledning, ville du ellers være nødt til at indtaste din 12-ords-nøgle ved hver login på denne enhed. Opret en lokal PIN-kode for at undgå dette.", + "setup_pin_warning": "Da din enhed ikke understøtter direkte Passkey-nøgleafledning, ville du ellers være nødt til at indtaste din 12-ords-nøgle hver gang, du logger ind på denne enhed. Opret en lokal PIN-kode for at undgå dette.", "pin_placeholder": "F.eks. 123456", "pin_label": "Lokal PIN-kode (4–8 cifre)", "save_pin": "Gem PIN-kode og fortsæt", @@ -121,7 +121,7 @@ "update_desc": "En ny version af Kapteins Daagbok er klar. Opdater venligst for at få de seneste ændringer.", "update_now": "Opdater nu", "update_reloading": "Indlæser…", - "storage_persist_hint": "Browseren kan slette offline-data. Tillad permanent lagring, så din logbog forbliver beskyttet (i browserindstillingerne eller ved næste påmindelse)." + "storage_persist_hint": "Browseren kan slette offline-data. Tillad permanent lagring, så din logbog forbliver beskyttet (i browserindstillingerne eller ved næste meddelelse)." }, "sync": { "status_synced": "Synkroniseret", @@ -135,7 +135,7 @@ }, "vessel": { "title": "Skibsstamdata", - "name": "Yachtnavn", + "name": "Yachtens navn", "type": "Bådtype", "type_unset": "— ikke angivet —", "type_sailing": "Sejlbåd", @@ -148,12 +148,12 @@ "owner": "Ejeren", "charter": "Charterfirma", "registration": "Nummerplade/registreringsnummer", - "callsign": "Radiokaldesignal", + "callsign": "Kaldesignal", "atis": "ATIS-nr.", "mmsi": "MMSI-nummer", "save": "Gem skibsdata", "saving": "Gemmes...", - "saved": "Skibsdata gemt!", + "saved": "Skibsdata er gemt!", "loading": "Skibsdata indlæses...", "sails_list": "Sejl (eksisterende sejl)", "sails_help": "Indtast her de sejl, der er til rådighed på dit skib (f.eks. storsejl, genua, fok).", @@ -225,7 +225,7 @@ "sign_classic_or_passkey": "Valgfrit: klassisk underskrift eller Passkey-godkendelse øverst", "sign_crew_passkey_hint": "Medarbejdere med skriveadgang kan dele via Passkey", "sign_offline_hint": "Passkey-godkendelse kræver internetforbindelse — klassisk underskrift er mulig offline", - "sign_lock_notice": "Når logbogsindskriften er underskrevet, kan der ikke foretages ændringer (undtagen i fotos) uden at skipperen og besætningen skal underskrive igen.", + "sign_lock_notice": "Når logbogsindskriften er underskrevet, kan der ikke foretages ændringer (undtagen i fotos), uden at skipperen og besætningen skal underskrive igen.", "sign_lock_active": "Denne indtastning er underskrevet. Ændringer i logbogen (undtagen fotos) fjerner automatisk skipperens og besætningens underskrifter.", "sign_lock_warning_title": "Bekræft underskrift", "sign_lock_warning": "Når logbogsindførelsen er underskrevet, kan der ikke længere foretages ændringer (undtagen i fotos), uden at skipperen og besætningen skal underskrive igen.\n\nVil du fortsætte?", @@ -233,7 +233,7 @@ "sign_cancel": "Annuller", "sign_cleared_re_sign_title": "Underskrifter fjernet", "sign_cleared_re_sign": "Logbogsnotatet er blevet ændret. Skipperens og besætningens underskrifter er blevet fjernet. Underskriv venligst igen.", - "no_entries": "Der blev ikke fundet nogen logbogspost for denne yacht. Opret din første rejsedag!", + "no_entries": "Der blev ikke fundet nogen logbogsindlæg for denne yacht. Opret din første rejsedag!", "back_to_list": "Tilbage til tidsskriftlisten", "save": "Gem logbogsiden", "saving": "Gemmes...", @@ -244,7 +244,7 @@ "live_mode": "Live", "live_title": "Live-Journal", "live_loading": "Live-Journal indlæses...", - "live_retry": "Prøv igen", + "live_retry": "Prøve igen", "live_load_error": "Live-Journal kunne ikke indlæses.", "live_action_error": "Indlægget kunne ikke gemmes.", "live_open_editor": "Fuldstændig editor", @@ -312,7 +312,7 @@ "live_gps_error": "GPS-positionen kunne ikke fastslås.", "live_gps_start_hint": "Start altid din dagstur med at finde en position.", "live_event_generic": "Begivenhed", - "live_weather_btn": "Vejr", + "live_weather_btn": "Vejret", "live_weather_owm_btn": "OpenWeatherMap Hent vejrudsigt", "live_weather_owm_loading": "Vejret indlæses…", "live_weather_position_required": "For vejr fra OpenWeatherMap skal du først indtaste en position (knappen „Position“). Positionen må højst være 6 timer gammel.", @@ -335,7 +335,7 @@ "live_course_entry": "Kurs {{course}}", "live_fuel_entry": "Diesel +{{liters}} L", "live_water_entry": "Vand +{{liters}} L", - "live_auto_position": "Automatisk position", + "live_auto_position": "Automatisk placering", "live_undo_hint": "Indtastningen er gemt", "live_undo_btn": "Fortryd", "live_cancel": "Afbrydelse", @@ -359,7 +359,7 @@ "carry_over_tanks_title": "Skal data fra i går overføres?", "carry_over_tanks_confirm": "Skal starthavn, startmængder for ferskvand, brændstof og gråt vand fra den sidste rejsedag overføres?\n\nStarthavn: {{departure}}\nFerskvand: {{fw}} L\nBrændstof: {{fuel}} L\nGråt vand: {{greywater}} L", "carry_over_tanks_yes": "Anvend", - "carry_over_tanks_no": "Starte fra 0", + "carry_over_tanks_no": "Start fra 0", "event_title": "Kronologisk hændelseslog", "event_creator": "Indsendt af", "no_events": "Der er endnu ikke registreret nogen begivenheder for denne rejsedag.", @@ -413,7 +413,7 @@ "gps_quality_poor": "Svag GPS-modtagelse (±{{accuracy}} m) – sandsynligvis få satellitter. Prøv igen udendørs, eller kontroller positionen.", "gps_quality_unknown": "GPS-position overført (nøjagtighed ikke angivet af enheden).", "gps_live_intro_title": "Placering for Live-Log", - "gps_live_intro_body": "For at kunne registrere positioner automatisk og bruge GPS-knappen skal appen have adgang til din placering.\n\nTryk på „Tillad placering“ – bekræft tilladelsen i den næste dialogboks. Du kan til enhver tid indtaste en position manuelt under „Position“.", + "gps_live_intro_body": "For at kunne registrere positioner automatisk og bruge GPS-knappen skal appen have adgang til din placering.\n\nTryk på »Tillad placering« – bekræft tilladelsen i den næste dialogboks. Du kan til enhver tid indtaste en position manuelt under »Position«.", "gps_live_intro_allow": "Tillad adgang til placering", "gps_live_intro_later": "Senere", "gps_enable_in_settings_hint": "Adgang til din placering er blokeret. Du kan senere give tilladelse i browser- eller enhedsindstillingerne (hjemmeside/app → placering).", @@ -425,14 +425,14 @@ "motor_propulsion": "Maskinkørsel", "sails_picker_show_more": "Vis alle sejl", "sails_picker_show_less": "Vis færre", - "motor_hours": "Maskin timer (i alt)", + "motor_hours": "Maskin-timer (i alt)", "fuel_per_motor_hour": "Forbrug pr. maskintime", "event_distance": "Afstand (sm)", "export_csv": "CSV Download", "share_csv": "CSV del", "export_pdf": "PDF Download", "exporting_pdf": "PDF genereres...", - "ai_summary_title": "AI-opsummering", + "ai_summary_title": "AI-resumé", "ai_summary_read_only": "Oprettet af skipperen — kan kun læses af besætningen.", "ai_summary_empty": "Der findes endnu ikke noget resumé.", "ai_summary_generate": "Generer resumé", @@ -445,8 +445,8 @@ "ai_summary_error_forbidden": "Kun skipperen må generere AI-opsummeringer.", "ai_summary_offline": "AI-opsummeringen kræver en internetforbindelse. Du er i øjeblikket offline.", "photos_title": "Fotobilag", - "photo_caption_label": "Fotobeskrivelse / Etiket (valgfrit)", - "photo_caption_placeholder": "f.eks. sætte sejl nær havneindsejlingen", + "photo_caption_label": "Billedbeskrivelse / Etiket (valgfrit)", + "photo_caption_placeholder": "f.eks. sætte sejl tæt på havneindsejlingen", "photo_btn": "Tag/upload et billede", "photo_camera_btn": "Tag et billede", "photo_gallery_btn": "Vælg fra galleriet", @@ -476,7 +476,7 @@ "nmea_file_label": "NMEA-fil", "nmea_stats": "{{lines}} sæt genkendt · Typer: {{types}}", "nmea_warn_no_position": "Der blev ikke fundet nogen positionssæt — spor- og GPS-felter kan stå tomme.", - "nmea_warn_duplicate_file": "Denne NMEA-fil er allerede importeret. Hvis du importerer den samme fil igen, vil der blive tilføjet dobbelte logbogspost.", + "nmea_warn_duplicate_file": "Denne NMEA-fil er allerede importeret. Hvis du importerer den samme fil igen, vil der blive tilføjet dobbelte logposter.", "nmea_mode_label": "Oprette journalposter", "nmea_mode_interval": "Efter tidsinterval", "nmea_mode_change": "Ved væsentlige ændringer", @@ -495,7 +495,7 @@ "nmea_archive_question": "Skal råprotokollen arkiveres lokalt? (Kun på denne enhed, ikke synkroniseret.)", "nmea_archive_keep": "Arkivering", "nmea_archive_discard": "Afvis", - "nmea_archive_stored": "NMEA-arkiv: {{name}}", + "nmea_archive_stored": "NMEA-arkiveret: {{name}}", "nmea_archive_delete_confirm": "Skal den arkiverede NMEA-log fra denne enhed slettes?", "nmea_error_no_samples": "Der er ingen brugbare NMEA-sætninger i filen.", "nmea_error_parse": "NMEA-filen kunne ikke læses.", @@ -542,6 +542,9 @@ "delete_confirm": "Er du sikker på, at du vil slette denne logbog endeligt? Alle lokale data og serverkopier vil blive slettet.\n\nTip: Opret først en sikkerhedskopi (.daagbok) under Indstillinger → Sikkerhedskopiering og gendannelse, hvis du vil beholde dataene senere.", "no_logbooks": "Der blev ikke fundet nogen logbøger. Opret din første logbog for at komme i gang!", "loading": "Logbøger indlæses...", + "travel_days_count_zero": "Ingen rejsedage", + "travel_days_count_one": "1 rejsedag", + "travel_days_count_other": "{{count}} Rejsedage", "status_synced": "Synkroniseret", "status_local": "Kun lokal cache", "delete_btn": "Slet logbog", @@ -588,8 +591,8 @@ "identity_title": "Kontooplysninger", "username": "Brugernavn", "user_id": "Bruger-ID", - "copy_user_id": "Kopier bruger-ID", - "account_since": "Konto oprettet", + "copy_user_id": "Kopier bruger-id", + "account_since": "Konto oprettet siden", "prf_status": "Passkey-nøgleafledning (PRF)", "prf_active": "Aktiv", "prf_inactive": "Ikke indrettet", @@ -603,7 +606,7 @@ "remove_passkey_last_title": "Sidste Passkey", "remove_passkey_last_desc": "Det eneste Passkey kan ikke fjernes uden at miste adgangen til din konto. For at slette kontoen helt skal du bruge linket nederst på denne side.", "remove_passkey_failed": "Passkey kunne ikke fjernes.", - "remove_passkey_confirm_title": "Passkey skal fjernes?", + "remove_passkey_confirm_title": "Passkey fjernes?", "remove_passkey_confirm_desc": "Denne enhed kan derefter ikke længere logge ind med denne Passkey.", "remove_passkey_confirm_yes": "Fjern", "remove_passkey_confirm_no": "Annuller", @@ -620,7 +623,7 @@ "pin_save_failed": "PIN-koden kunne ikke gemmes.", "pin_mismatch": "PIN-koderne stemmer ikke overens.", "pin_length_error": "PIN-koden skal bestå af mindst 4 tegn.", - "pin_no_session": "Sessionen er udløbet — log ind igen.", + "pin_no_session": "Sessionen er udløbet — log venligst ind igen.", "remove_pin_confirm_title": "Skal PIN-koden fjernes?", "remove_pin_confirm_desc": "Du skal logge ind på denne enhed igen med Passkey eller gendannelsesnøglen.", "remove_pin_confirm_yes": "Fjern PIN-kode", @@ -640,7 +643,7 @@ "recovery_rotate_confirm_desc": "Den hidtidige 12-ords-nøgle bliver straks ugyldig. Sørg for at opbevare den nye nøgle sikkert, inden du fortsætter.", "recovery_rotate_confirm_yes": "Opret en ny nøgle", "recovery_rotate_confirm_no": "Annuller", - "recovery_rotate_new_warning": "VIGTIGT: Skriv disse 12 ord ned, og opbevar dem et sted, hvor du ikke har internetadgang. Den hidtidige gendannelseskode er nu ugyldig.", + "recovery_rotate_new_warning": "VIGTIGT: Skriv disse 12 ord ned, og opbevar dem offline. Den hidtidige gendannelseskode er nu ugyldig.", "recovery_rotate_failed": "Det var ikke muligt at oprette en gendannelsesnøgle.", "recovery_rotate_no_session": "Krypteringssessionen er udløbet — log venligst ud og log ind igen, og prøv derefter igen.", "device_title": "Dette apparat", @@ -653,7 +656,7 @@ "device_forget_confirm_title": "Skal hurtiglogin fjernes?", "device_forget_confirm_desc": "Kontoen fjernes fra listen over hurtiglogin på denne enhed. Din session og dine lokale logfiler bevares.", "device_forget_confirm_yes": "Fjern", - "device_forget_confirm_no": "Annuller", + "device_forget_confirm_no": "Afbryd", "passkey_label": "Navn til den nye Passkey (valgfrit)", "passkey_label_placeholder": "f.eks. MacBook, iPhone", "passkey_rename_btn": "Gem navn", @@ -665,7 +668,7 @@ "stats_logbooks": "Logbøger", "stats_account_since": "Konto siden", "stats_shared_logbooks": "Delte logbøger", - "appearance_title": "App & brugergrænseflade", + "appearance_title": "App & visning", "appearance_desc": "Designet og farveskemaet gælder for hele appen på denne enhed.", "theme_label": "Appens designstil", "theme_auto": "Automatisk (OS-genkendelse)", @@ -761,7 +764,7 @@ "title": "Besætningen på denne rejsedag", "subtitle": "Kan afvige fra standarden i logbogen. De efterfølgende rejsedage overtager dataene fra den foregående dag.", "day_skipper": "Skipperen denne dag", - "day_crew": "Besætningen denne dag", + "day_crew": "Besætningen den dag", "no_skipper": "Der er ikke valgt nogen skipper", "no_crew": "Der er ikke valgt noget hold" }, @@ -787,7 +790,7 @@ "save_member": "Gem medlem", "saved": "Skipper-profilen er gemt!", "loading": "Crew-filer indlæses...", - "delete_confirm": "Er du sikker på, at du vil fjerne dette medlem af holdet?" + "delete_confirm": "Er du sikker på, at du vil fjerne dette crew-medlem?" }, "deviation": { "title": "Afvigelsestabel (kompasafvigelse)", @@ -836,7 +839,7 @@ "invite_push_prompt_later": "Senere", "invite_push_prompt_success": "Push-beskeder er aktiveret på denne enhed.", "backup_title": "Sikkerhedskopiering og gendannelse", - "backup_desc": "Fuldstændig krypteret sikkerhedskopi af denne logbog (indlæg, fotos, lydnoter, GPS-ruter, besætning, skib). Beskyttet med en sikkerhedskodephrase — til gendannelse på denne eller en ny konto.", + "backup_desc": "Fuldstændig krypteret sikkerhedskopi af denne logbog (indlæg, fotos, lydnoter, GPS-spor, besætning, skib). Beskyttet med en sikkerhedskodephrase — til gendannelse på denne eller en ny konto.", "backup_export_title": "Opret sikkerhedskopi", "backup_export_desc": "Downloader alle lokale data som en komprimeret .daagbok-fil. Opbevar filen og adgangskoden separat og sikkert.", "backup_restore_title": "Gendan sikkerhedskopi", @@ -854,8 +857,8 @@ "backup_export_progress": "Pak filer {{current}} / {{total}}…", "backup_invalid_archive": "Filen er ikke et gyldigt sikkerhedskopieringsarkiv.", "backup_version_unsupported": "Gammelt backupformat (v1). Brug venligst en opdateret .daagbok-backup.", - "backup_import_size_confirm": "Denne sikkerhedskopi er ca. {{size}} stor. Gendannelsen kan tage længere tid på enheden og optage meget lagerplads. Vil du fortsætte?", - "backup_stat_voice": "{{count}} Stemmebeskeder", + "backup_import_size_confirm": "Denne sikkerhedskopi er ca. {{size}} MB stor. Gendannelsen kan tage længere tid på enheden og optage meget lagerplads. Vil du fortsætte?", + "backup_stat_voice": "{{count}} Stemme-noter", "backup_stat_size": "Ukomprimeret ca. {{size}}", "backup_preview_btn": "Kontroller indholdet", "backup_previewing": "Kontroller…", @@ -864,7 +867,7 @@ "backup_restore_success": "Logbogen „{{title}}“ er blevet gendannet.", "backup_restore_cancelled": "Gendannelsen blev afbrudt.", "backup_invalid_json": "Filen er ikke en gyldig JSON-fil.", - "backup_invalid_format": "Ukendt eller forældet backup-format.", + "backup_invalid_format": "Ukendt eller forældet backupformat.", "backup_not_owner": "Kun logbogens ejer kan oprette sikkerhedskopier.", "backup_not_authenticated": "Du skal logge ind for at gendanne en sikkerhedskopi.", "backup_id_conflict": "Der findes allerede en logbog med dette ID.", @@ -884,13 +887,13 @@ "pwa_title": "Progressiv webapp (PWA)", "pwa_body": "Kapteins Daagbok kører som en progressiv webapp i din browser og kan installeres på din enhed – på samme måde som en native app, men uden at skulle hentes fra en app-butik.", "storage_title": "Lokal lagring og synkronisering", - "storage_body": "Dine data gemmes midlertidigt lokalt på din enhed (IndexedDB). Når der er internetforbindelse, synkroniseres ændringerne med serveren. Du kan fortsætte med at arbejde, selvom der ikke er forbindelse; synkroniseringen foregår senere.", + "storage_body": "Dine data gemmes midlertidigt lokalt på din enhed (IndexedDB). Når der er internetforbindelse, synkroniseres ændringerne med serveren. Du kan fortsætte med at arbejde, selvom der ikke er forbindelse; synkroniseringen finder sted senere.", "free_title": "Gratis og uden reklamer", "free_body": "Kapteins Daagbok er gratis og indeholder ingen reklamer.", "liability_title": "Ansvarsfraskrivelse", - "liability_body": "Brugen sker på eget ansvar. Der påtages intet ansvar for skader, der opstår som følge af brugen af appen – herunder fejlbehæftede eller ufuldstændige logbogspostninger, datatab eller tekniske fejl.", + "liability_body": "Brugen sker på eget ansvar. Der påtages intet ansvar for skader, der opstår som følge af brugen af appen – herunder fejlagtige eller ufuldstændige logbogsindtastninger, datatab eller tekniske fejl.", "warranty_title": "Ingen garanti", - "warranty_body": "Der gives ingen garanti for tjenestens funktion, nøjagtighed eller tilgængelighed. Driften kan til enhver tid blive afbrudt, begrænset eller indstillet.", + "warranty_body": "Der gives ingen garanti for tjenestens funktion, nøjagtighed eller tilgængelighed. Driften kan til enhver tid afbrydes, begrænses eller indstilles.", "copyright": "© 2026 KnorrLabs, Markus F.J. Busche", "accept": "Accepter og fortsæt", "close": "Luk", @@ -912,11 +915,11 @@ "send": "Send", "sending": "Sendes…", "cancel": "Annuller", - "success": "Mange tak! Din feedback er blevet sendt.", + "success": "Mange tak! Din tilbagemelding er blevet sendt.", "error_send": "Feedback kunne ikke sendes. Prøv igen senere.", "error_invalid_email": "Indtast venligst en gyldig e-mailadresse.", "error_not_configured": "Feedback er ikke tilgængelig på denne server.", - "error_rate_limited": "Der er modtaget for mange feedback-beskeder på kort tid. Vent venligst et par minutter.", + "error_rate_limited": "Der er for mange feedback-beskeder på kort tid. Vent venligst et par minutter.", "error_spam": "Denne besked kunne ikke sendes. Omformuler den venligst." }, "demo": { @@ -932,13 +935,13 @@ "error_expired": "Denne invitation er udløbet (gyldig i 48 timer).", "error_invalid_token": "Invitationstoken er ugyldig.", "error_load_failed": "Det var ikke muligt at indlæse oplysninger om invitationen.", - "error_incomplete_session": "Sessionen er ufuldstændig — log venligst ind igen (bruger-ID mangler).", + "error_incomplete_session": "Sessionen er ufuldstændig — log ind igen (bruger-ID mangler).", "error_accept_failed": "Tilmeldingen mislykkedes.", "error_login_failed": "Passkey-login mislykkedes.", "error_username_missing": "Brugernavnet kunne ikke findes — log ind igen.", "error_register_failed": "Registreringen mislykkedes.", "loading_joining": "Tilmelding...", - "loading_checking": "Invitationen bliver behandlet...", + "loading_checking": "Invitationen bliver gennemgået...", "loading_unlocking": "Logbogen aktiveres og synkroniseres...", "loading_retrieving_key": "Indlæser krypteringsnøgle...", "error_title": "Indlæsningsfejl", @@ -948,7 +951,7 @@ "vessel_logbook": "Skib / Logbog", "signed_in_preparing": "Logget ind som {{username}}. Tilmelding forberedes...", "join_again": "Tilmeld dig igen", - "login_or_register_hint": "Log ind eller opret en konto for at få adgang til logbogen.", + "login_or_register_hint": "Log ind eller opret en konto for at blive medlem af logbogen.", "or_sign_up": "ELLER OPRETT EN NY KONTO", "register_crew_account": "Opret en ny crew-konto", "username_label": "Brugernavn", @@ -967,7 +970,7 @@ "total_distance": "Samlet strækning", "travel_days": "Rejsedage", "sail_distance": "Under sejl", - "motor_distance": "Maskinkørsel", + "motor_distance": "Maskintransport", "motor_hours_total": "Samlede maskintimer", "daily_motor_hours": "Maskin-timer pr. rejsedag", "avg_motor_hours": "Gennemsnitlige maskintimer pr. rejsedag", @@ -1014,11 +1017,11 @@ }, "welcome_public": { "title": "Velkommen om bord!", - "body": "Udforsk vores demo-logbog med tre rejsedage i Kieler Fjorden – helt uden at oprette en konto. Turen viser dig logbogsindlæg samt valg af skib og besætning til denne logbog. Du kan senere opdatere flåden og den faste besætning i din brugerprofil." + "body": "Udforsk vores demo-logbog med tre rejsedage i Kieler Fjorden – helt uden brugerkonto. Turen viser dig logbogsindlæg samt valg af skib og besætning til denne logbog. Du kan senere opdatere flåden og fast besætning i din brugerprofil." }, "nav_logs": { "title": "Logbogsnotater", - "body": "Her kan du administrere dine rejsedage – afgang, destination, vejr, brændstofstand og GPS-ruter." + "body": "Her kan du administrere dine rejsedage – afgang, destination, vejr, brændstofstand og GPS-spor." }, "entry_list": { "title": "Dine rejsedage", @@ -1026,7 +1029,7 @@ }, "entry_open": { "title": "Åbn rejsedag", - "body": "Sådan ser en udfyldt logbogsoptegnelse ud – med begivenheder, brændstofstand og mere." + "body": "Sådan ser en udfyldt logbogsoptegnelse ud – med begivenheder, brændstofmængder og mere." }, "entry_track": { "title": "GPS-rute", @@ -1034,7 +1037,7 @@ }, "nav_vessel": { "title": "Skib til logbogen", - "body": "Vælg det skib fra din flåde, der skal bruges til denne logbog. Du kan administrere dine skibe i brugerprofilen under »Flåde & besætning«." + "body": "Vælg det skib til denne logbog fra din flåde. Du kan administrere dine skibe i brugerprofilen under »Flåde & besætning«." }, "profile_vessel_pool": { "title": "Skibsflåde", @@ -1058,11 +1061,11 @@ }, "nav_profile": { "title": "Din brugerprofil", - "body": "Via Skipper-knappen øverst kan du gå til din personlige profil – uanset hvilket logbog du er i." + "body": "Via knappen »Skipper« øverst kan du gå til din personlige profil – uanset hvilket logbog du er i." }, "profile_preferences": { "title": "Konto & visning", - "body": "Her kan du administrere din kontoidentitet, dit tema og lys/mørk-tilstand. Du kan når som helst starte app-guiden igen. Passkeys og sikkerhedsindstillinger finder du længere nede i profilen." + "body": "Her kan du administrere din kontoidentitet, dit tema og lys/mørk-tilstand. Du kan når som helst starte app-rundvisningen igen. Passkeys og sikkerhedsindstillinger finder du længere nede i profilen." }, "finish": { "title": "Fint!", @@ -1072,7 +1075,7 @@ }, "seo": { "title": "Kapteins Daagbok – Gratis digitalt logbog til lystbåde (uden reklamer)", - "description": "Gratis, reklamefri digital bådlogbog med ende-til-ende-kryptering og Passkey-login. Dokumenter rejsedage, GPS-ruter, besætning og skibsdata sikkert – også offline som PWA.", + "description": "Gratis, reklamefri digital yachtlogbog med ende-til-ende-kryptering og Passkey-login. Dokumenter rejsedage, GPS-spor, besætning og skibsdata sikkert – også offline som PWA.", "keywords": "Yachtlogbog, skibsdagbog, skibslogbog, sejlads, Passkey, E2E-kryptering, GPS-spor, maritim logbog, gratis, uden reklamer, gratis, uden reklamer", "ogImageAlt": "Kapteins Daagbok Logo" } diff --git a/client/src/i18n/locales/de.json b/client/src/i18n/locales/de.json index 3151a32..a373d0a 100644 --- a/client/src/i18n/locales/de.json +++ b/client/src/i18n/locales/de.json @@ -542,6 +542,9 @@ "delete_confirm": "Bist du sicher, dass du dieses Logbuch unwiderruflich löschen möchtest? Alle lokalen Daten und Server-Kopien werden vernichtet.\n\nTipp: Erstelle vorher unter Einstellungen → Backup & Wiederherstellung eine Sicherungskopie (.daagbok), falls du die Daten später behalten möchtest.", "no_logbooks": "Keine Logbücher gefunden. Erstelle dein erstes Logbuch, um zu beginnen!", "loading": "Logbücher werden geladen...", + "travel_days_count_zero": "Keine Reisetage", + "travel_days_count_one": "1 Reisetag", + "travel_days_count_other": "{{count}} Reisetage", "status_synced": "Synchronisiert", "status_local": "Nur lokaler Cache", "delete_btn": "Logbuch löschen", diff --git a/client/src/i18n/locales/en.json b/client/src/i18n/locales/en.json index 544874b..5c6c4da 100644 --- a/client/src/i18n/locales/en.json +++ b/client/src/i18n/locales/en.json @@ -542,6 +542,9 @@ "delete_confirm": "Are you sure you want to permanently delete this logbook? All local data and server copies will be destroyed.\n\nTip: Create a backup first under Settings → Backup & restore (.daagbok) if you may need the data later.", "no_logbooks": "No logbooks found. Create your first logbook to begin!", "loading": "Loading logbooks...", + "travel_days_count_zero": "No travel days", + "travel_days_count_one": "1 travel day", + "travel_days_count_other": "{{count}} travel days", "status_synced": "Synced", "status_local": "Local Cache Only", "delete_btn": "Delete logbook", diff --git a/client/src/i18n/locales/es.json b/client/src/i18n/locales/es.json index 9f39f48..73537a6 100644 --- a/client/src/i18n/locales/es.json +++ b/client/src/i18n/locales/es.json @@ -542,6 +542,9 @@ "delete_confirm": "¿Estás seguro de que quieres eliminar este diario de forma definitiva? Se borrarán todos los datos locales y las copias del servidor.\n\nConsejo: si quieres conservar los datos más adelante, crea primero una copia de seguridad (.daagbok) en Ajustes → Copia de seguridad y restauración.", "no_logbooks": "No se han encontrado diarios. ¡Crea tu primer diario para empezar!", "loading": "Se están cargando los registros...", + "travel_days_count_zero": "Sin días de viaje", + "travel_days_count_one": "1 día de viaje", + "travel_days_count_other": "{{count}} días de viaje", "status_synced": "Doblada", "status_local": "Solo caché local", "delete_btn": "Borrar el registro", diff --git a/client/src/i18n/locales/fr.json b/client/src/i18n/locales/fr.json index d4a79b4..4ec5c4b 100644 --- a/client/src/i18n/locales/fr.json +++ b/client/src/i18n/locales/fr.json @@ -8,7 +8,7 @@ }, "footer": { "kofi_label": "Ko-fi", - "kofi_title": "Soutenez le projet, son développement et ses coûts d'exploitation sur Ko-fi" + "kofi_title": "Soutenez le projet, son développement et ses frais de fonctionnement sur Ko-fi" }, "languages": { "de": "Deutsch", @@ -50,7 +50,7 @@ }, "auth": { "welcome": "Bienvenue chez Kapteins Daagbok", - "tagline": "Ton journal de bord maritime sécurisé et crypté avec le protocole E2E.", + "tagline": "Ton journal de bord maritime sécurisé et crypté avec E2E.", "register": "S'inscrire avec Passkey", "login": "Se connecter avec Passkey", "login_as": "Se connecter en tant que {{name}}", @@ -88,7 +88,7 @@ "enter_pin_placeholder": "Saisis ton code PIN...", "decrypt_with_pin": "Décrypter", "use_recovery_instead": "Utiliser plutôt la clé de récupération", - "error_incorrect_pin": "Code PIN incorrect. Échec du décryptage.", + "error_incorrect_pin": "Code PIN incorrect. Échec du déchiffrement.", "error_invalid_host": "Passkey ne fonctionne pas via 127.0.0.1. Veuillez ouvrir l'application via localhost.", "use_localhost_link": "Passer à localhost", "error_passkey_cancelled": "Passkey - Connexion interrompue ou expirée. Veuillez réessayer.", @@ -96,7 +96,7 @@ "error_session_incomplete": "Inscription incomplète. Veuillez vous reconnecter avec Passkey.", "restore_checking": "La session est en cours de vérification…", "restore_title": "Restaurer la session", - "restore_subtitle": "Ton inscription est toujours active. Déverrouille ton journal de bord avec Passkey ou ton code PIN.", + "restore_subtitle": "Ton inscription est toujours active. Déverrouille ton journal de bord à l'aide de Passkey ou de ton code PIN.", "restore_unlocking": "Déverrouillage en cours…", "restore_with_passkey": "Déverrouiller avec Passkey ({{name}})", "restore_with_pin": "Déverrouiller avec le code PIN", @@ -106,7 +106,7 @@ "pwa": { "title": "Installer l'application", "generic_benefit": "Installez Kapteins Daagbok sur votre appareil pour bénéficier d'un accès plus rapide, d'une utilisation hors ligne et d'un stockage permanent des données.", - "ios_instructions": "Sur le iPad/iPhone : ajoute l'application à l'écran d'accueil afin que tes données de journal de bord restent protégées et que l'application se lance comme une application native.", + "ios_instructions": "Sur le iPad/iPhone : ajoute l'application à l'écran d'accueil pour que tes données de journal de bord restent protégées et que l'application se lance comme une application native.", "ios_step_share": "Appuyez sur l'icône de partage dans la barre Safari", "ios_step_add": "Sélectionner « Retour à l'écran d'accueil »", "install_now": "Installer maintenant", @@ -156,7 +156,7 @@ "saved": "Les données du navire ont été enregistrées avec succès !", "loading": "Chargement des données du navire...", "sails_list": "Gréement (voiles disponibles)", - "sails_help": "Indique ici les voiles dont dispose ton bateau (par exemple : grand-voile, génois, foc).", + "sails_help": "Indique ici les voiles dont dispose ton bateau (par exemple, grand-voile, génois, foc).", "add_sail": "Ajouter une voile", "sail_name_placeholder": "par exemple, la grand-voile", "no_sails": "Aucune voile n'est stockée.", @@ -187,7 +187,7 @@ "travel_day_number": "Jour de voyage {{number}}", "departure": "Port de départ (départ de)", "destination": "Port de destination (vers)", - "route": "Voyage depuis/vers", + "route": "Voyage au départ de/à destination de", "tanks": "Réservoirs", "customize_columns": "Ajuster les colonnes", "column_selector_title": "Colonnes à afficher", @@ -196,11 +196,11 @@ "greywater": "Eaux grises (litres)", "greywater_level": "niveau de remplissage", "tank_slider_of_max": "{{current}} / {{max}} L", - "tank_capacity_tooltip": "Si les capacités des réservoirs (en litres) sont indiquées dans les données du bateau, tu peux saisir ici les niveaux de remplissage à l'aide du curseur.", + "tank_capacity_tooltip": "Si les capacités des réservoirs (en litres) sont indiquées dans les données du navire, tu peux saisir ici les niveaux de remplissage à l'aide du curseur.", "morning": "Situation ce matin", "refilled": "Réapprovisionné", "evening": "Situation en fin de journée", - "consumption": "consommation quotidienne", + "consumption": "consommation journalière", "signatures": "Signatures / Validation", "sign_skipper": "Signature du skipper", "sign_crew": "Signature de l'équipe", @@ -225,7 +225,7 @@ "sign_classic_or_passkey": "En option : signature classique ou validation Passkey en haut", "sign_crew_passkey_hint": "Les membres de l'équipe disposant d'un accès en écriture peuvent partager via Passkey", "sign_offline_hint": "La validation Passkey nécessite une connexion Internet — la signature classique est possible hors ligne", - "sign_lock_notice": "Une fois le document signé, aucune modification ne peut être apportée à l'inscription dans le journal de bord (à l'exception des photos) sans que le skipper et l'équipage ne doivent à nouveau signer.", + "sign_lock_notice": "Une fois le document signé, aucune modification ne peut être apportée à l'inscription dans le journal de bord (à l'exception des photos) sans que le skipper et l'équipage ne doivent le signer à nouveau.", "sign_lock_active": "Cette entrée est signée. Toute modification apportée au journal de bord (à l'exception des photos) supprime automatiquement les signatures du skipper et de l'équipage.", "sign_lock_warning_title": "Confirmer la signature", "sign_lock_warning": "Une fois la signature apposée, aucune modification ne peut être apportée à l'entrée du journal de bord (à l'exception des photos) sans que le skipper et l'équipage ne doivent à nouveau signer.\n\nSouhaites-tu continuer ?", @@ -263,7 +263,7 @@ "live_sails_confirm": "S'inscrire", "live_sails_confirm_count": "S'inscrire ({{count}})", "live_sails": "Voile : {{sails}}", - "live_position": "Position", + "live_position": "Poste", "live_position_coords": "Position {{lat}}, {{lng}}", "live_position_manual_hint": "GPS indisponible. Saisissez manuellement la latitude et la longitude ou réessayez en appuyant sur le bouton GPS.", "live_position_gps_loading": "La position GPS est en cours de calcul…", @@ -300,7 +300,7 @@ "live_voice_error": "Impossible d'enregistrer le message vocal.", "live_voice_entry": "Note vocale : {{caption}}", "live_voice_entry_plain": "message vocal", - "live_voice_caption_label": "Inscription (facultative)", + "live_voice_caption_label": "Inscription (facultatif)", "live_voice_caption_placeholder": "par exemple, communications radio avec le capitaine du port", "live_voice_transcribe_action": "Transcrire", "live_voice_transcribing": "Transcris...", @@ -400,11 +400,11 @@ "event_remarks": "Remarques / Évènements", "gps_btn": "Obtenir les coordonnées GPS", "gps_permission_denied": "L'accès à la localisation a été refusé. Veuillez l'autoriser dans les paramètres de votre navigateur ou de votre appareil, puis réessayez.", - "gps_timeout": "Délai d'attente GPS. Veuillez réessayer, de préférence à l'extérieur, dans un endroit où la réception est bonne.", + "gps_timeout": "Délai d'attente GPS. Veuillez réessayer, de préférence à l'extérieur où la réception est bonne.", "gps_position_unavailable": "Aucun signal GPS disponible. Veuillez patienter ou saisir les coordonnées manuellement.", "gps_unavailable": "Le GPS n'est pas pris en charge par ce navigateur ou cet appareil.", "gps_failed": "Impossible de déterminer la position GPS.", - "gps_fallback_no_location": "Échec de la localisation GPS. Veuillez saisir un lieu dans la rubrique « Lieu / Port », indiquer le port de départ ou d'arrivée, ou saisir les coordonnées manuellement.", + "gps_fallback_no_location": "Échec du GPS. Veuillez saisir un lieu dans la rubrique « Lieu / Port », indiquer le port de départ ou d'arrivée, ou saisir les coordonnées manuellement.", "gps_fallback_success": "Coordonnées de « {{location}} » déterminées à partir du nom de la localité (et non par GPS).", "gps_fallback_failed": "La recherche par GPS et par nom de lieu a échoué. Veuillez saisir les coordonnées manuellement.", "gps_quality_excellent": "Réception GPS puissante (±{{accuracy}} m)", @@ -416,7 +416,7 @@ "gps_live_intro_body": "Pour enregistrer automatiquement ta position et utiliser le bouton GPS, l'application doit pouvoir accéder à ta localisation.\n\nAppuie sur « Autoriser l'accès à la localisation » ; dans la fenêtre suivante, confirme l'autorisation. Tu peux à tout moment saisir manuellement ta position dans la rubrique « Position ».", "gps_live_intro_allow": "Autoriser l'accès à la localisation", "gps_live_intro_later": "Plus tard", - "gps_enable_in_settings_hint": "L'accès à la localisation est bloqué. Tu peux autoriser l'accès ultérieurement dans les paramètres du navigateur ou de l'appareil (site web / application → Localisation).", + "gps_enable_in_settings_hint": "L'accès à la localisation est bloqué. Tu peux autoriser cet accès ultérieurement dans les paramètres du navigateur ou de l'appareil (site web / application → Localisation).", "weather_btn": "OpenWeatherMap Consulter la météo", "weather_offline": "OpenWeatherMap nécessite une connexion Internet. Tu es actuellement hors ligne.", "event_wind_pressure": "Pression atmosphérique (hPa)", @@ -482,7 +482,7 @@ "nmea_mode_change": "En cas de modification importante", "nmea_mode_both": "Les deux (fusionner)", "nmea_interval_label": "Intervalle (minutes)", - "nmea_import_track": "Importer un tracé GPS au format NMEA", + "nmea_import_track": "Importer une trace GPS au format NMEA", "nmea_preview": "Aperçu", "nmea_preview_hint": "{{count}} Entrées de journal suggérées", "nmea_select_all": "Tout sélectionner", @@ -542,6 +542,9 @@ "delete_confirm": "Es-tu sûr de vouloir supprimer définitivement ce journal ? Toutes les données locales et les copies sur le serveur seront effacées.\n\nConseil : si tu souhaites conserver ces données ultérieurement, pense à créer au préalable une copie de sauvegarde (.daagbok) dans Réglages → Sauvegarde et restauration.", "no_logbooks": "Aucun journal de bord trouvé. Crée ton premier journal de bord pour commencer !", "loading": "Chargement des journaux de bord...", + "travel_days_count_zero": "Pas de jours de voyage", + "travel_days_count_one": "1 jour de voyage", + "travel_days_count_other": "{{count}} Jours de voyage", "status_synced": "Doublé", "status_local": "Cache local uniquement", "delete_btn": "Effacer le journal de bord", @@ -553,7 +556,7 @@ "role_crew": "Accès à l'équipe", "role_crew_hint": "Journal de bord ouvert à tous — tu peux y contribuer en tant que membre d'équipage et y apposer ta signature", "role_read": "Lecture seule", - "role_read_hint": "Journal partagé — consultation uniquement, pas de modification", + "role_read_hint": "Journal partagé — lecture seule, pas de modification", "open_profile": "Ouvrir le profil de {{name}}", "open_logbook": "Ouvrir le journal de bord « {{title}} »", "edit_title": "Renommer le journal de bord", @@ -601,7 +604,7 @@ "add_passkey_failed": "Passkey n'a pas pu être ajouté.", "remove_passkey_btn": "Supprimer Passkey", "remove_passkey_last_title": "Dernier Passkey", - "remove_passkey_last_desc": "Le seul Passkey ne peut pas être supprimé sans perdre l'accès à ton compte. Pour supprimer complètement le compte, utilise la zone de suppression située en bas de cette page.", + "remove_passkey_last_desc": "Le seul Passkey ne peut pas être supprimé sans perdre l'accès à ton compte. Pour supprimer complètement le compte, utilise la zone de sécurité située en bas de cette page.", "remove_passkey_failed": "Passkey n'a pas pu être supprimé.", "remove_passkey_confirm_title": "Supprimer Passkey ?", "remove_passkey_confirm_desc": "Cet appareil ne pourra plus se connecter à ce Passkey par la suite.", @@ -626,7 +629,7 @@ "remove_pin_confirm_yes": "Supprimer le code PIN", "remove_pin_confirm_no": "Annuler", "security_title": "Liste de contrôle de sécurité", - "security_desc": "Aperçu des principaux mécanismes de sécurité de ton compte.", + "security_desc": "Aperçu des principaux mécanismes de protection de ton compte.", "security_passkeys_ok": "Au moins un Passkey enregistré", "security_passkeys_missing": "Aucun Passkey enregistré", "security_prf_ok": "Génération de clé PRF activée", @@ -640,9 +643,9 @@ "recovery_rotate_confirm_desc": "L'ancienne clé de 12 mots n'est plus valable à compter de maintenant. Assure-toi de conserver la nouvelle clé en lieu sûr avant de continuer.", "recovery_rotate_confirm_yes": "Créer une nouvelle clé", "recovery_rotate_confirm_no": "Annuler", - "recovery_rotate_new_warning": "IMPORTANT : note ces 12 mots et conserve-les hors ligne. L'ancienne clé de récupération n'est plus valable à compter de maintenant.", + "recovery_rotate_new_warning": "IMPORTANT : note ces 12 mots et conserve-les hors ligne. L'ancienne clé de récupération n'est plus valide à compter de maintenant.", "recovery_rotate_failed": "Impossible de créer la clé de récupération.", - "recovery_rotate_no_session": "La session de chiffrement a expiré — veuillez vous déconnecter puis vous reconnecter, puis réessayer.", + "recovery_rotate_no_session": "La session de cryptage a expiré — veuillez vous déconnecter puis vous reconnecter, puis réessayer.", "device_title": "Cet appareil", "device_desc": "Cache local, état de la synchronisation et connexion rapide sur ce navigateur.", "device_sync_pending": "{{count}} entrées de synchronisation en attente", @@ -678,7 +681,7 @@ "color_scheme_dark": "Sombre", "integrations_title": "Intégrations", "owm_key": "OpenWeatherMap Clé API", - "owm_help": "Facultatif : clé API OpenWeatherMap personnalisée. En l'absence de cette entrée, la clé côté serveur issue de la configuration de l'opérateur est utilisée.", + "owm_help": "Facultatif : votre propre clé API OpenWeatherMap. Si aucune valeur n'est indiquée, la clé côté serveur issue de la configuration de l'opérateur est utilisée.", "ai_title": "Fonctionnalités IA et protection des données", "ai_desc": "Autorise l'utilisation de l'intelligence artificielle (intégrations locales/cloud) pour tes journaux de bord.", "ai_help": "Cette fonctionnalité permet de résumer automatiquement les récits de voyage et de transcrire les notes vocales. Pour le traitement, les enregistrements vocaux et les entrées du journal de bord sont transmis de manière cryptée à OpenRouter. Les données n'y sont pas stockées de manière permanente.\n\nL'exploitation de ces ressources cloud engendrant des coûts, nous vous serions reconnaissants de bien vouloir nous soutenir volontairement via le lien de don Ko-fi situé en bas de page, afin que nous puissions continuer à offrir ces fonctionnalités gratuitement à tous.", @@ -693,9 +696,9 @@ "tour_restart": "Recommencer le circuit", "push_title": "Notifications push", "push_desc": "En tant que propriétaire du journal de bord, tu seras averti lorsque les membres d'équipage invités synchroniseront des modifications. Aucun contenu n'est transmis en clair.", - "push_enable": "M'avertir en cas de changement au sein de l'équipe", + "push_enable": "M'avertir en cas de changement dans l'équipe", "push_active": "Les notifications push sont activées sur cet appareil.", - "push_unsupported": "Les notifications push ne sont pas prises en charge par ce navigateur.", + "push_unsupported": "Les notifications push ne sont pas prises en charge dans ce navigateur.", "push_denied_hint": "Les notifications sont désactivées. Activez-les dans les paramètres de votre navigateur ou de votre appareil.", "push_ios_install_hint": "Sur le iPhone/iPad : ajoutez l'application à l'écran d'accueil (iOS 16.4 et versions ultérieures) pour recevoir des notifications push.", "push_error": "Les notifications push n'ont pas pu être activées.", @@ -732,7 +735,7 @@ }, "person_pool": { "title": "Équipage habituel et skipper", - "subtitle": "Crée ici ton vivier de personnel – skippers et équipage pour tous les carnets de bord. C'est dans ce vivier que tu sélectionneras l'équipage actif pour chaque carnet de bord et chaque jour de voyage.", + "subtitle": "Crée ici ton vivier de personnel – skippers et équipage pour tous les carnets de bord. C'est dans ce vivier que tu sélectionneras l'équipage en service pour chaque carnet de bord et chaque jour de voyage.", "loading": "Chargement de la liste des personnes…", "skippers_section": "Skipper attitré", "crew_section": "équipe de base", @@ -763,13 +766,13 @@ "day_skipper": "Skipper ce jour-là", "day_crew": "L'équipe ce jour-là", "no_skipper": "Aucun skipper n'a été choisi", - "no_crew": "Aucun équipage sélectionné" + "no_crew": "Aucune équipe sélectionnée" }, "crew": { - "title": "Profils des skippers et des équipiers", + "title": "Profils des skippers et des membres d'équipage", "skipper_section": "Profil du skipper", "skipper_read_only_hint": "Seul le propriétaire du journal de bord peut modifier le profil du skipper.", - "crew_section": "Liste de l'équipe", + "crew_section": "Liste de l'équipage", "add_crew": "Ajouter un membre de l'équipe", "edit_crew": "Modifier les informations d'un membre de l'équipe", "no_crew": "Aucun membre d'équipage n'a encore été ajouté.", @@ -807,7 +810,7 @@ "weather_success": "Les données météorologiques ont été récupérées avec succès !", "weather_error": "Échec de la récupération des données météorologiques. Vérifie la clé API et la connexion.", "weather_unauthorized": "Échec de la récupération des données météorologiques. La clé API n'est pas valide ou n'est pas autorisée.", - "weather_not_found": "Échec de la récupération des données météorologiques. La localité ou les coordonnées indiquées n'ont pas été trouvées.", + "weather_not_found": "Échec de la récupération des données météorologiques. Le lieu ou les coordonnées indiqués n'ont pas été trouvés.", "weather_bad_request": "Échec de la récupération des données météorologiques. Aucun lieu ni aucune position GPS n'ont été indiqués.", "weather_date_mismatch": "Les données météorologiques ne peuvent être consultées que pour la journée d'aujourd'hui ({{today}}). Cette entrée du journal de bord est datée du {{date}}.", "gps_error": "Veuillez indiquer un lieu ou déterminer les coordonnées GPS.", @@ -841,7 +844,7 @@ "backup_export_desc": "Télécharge toutes les données locales sous la forme d'un fichier .daagbok compressé. Conservez le fichier et la phrase de passe séparément et en lieu sûr.", "backup_restore_title": "Restaurer une sauvegarde", "backup_restore_desc": "Restaure une sauvegarde dans ton compte actuel, même après la création d'un nouveau compte.", - "backup_passphrase": "Phrase secrète de sauvegarde", + "backup_passphrase": "Phrase de passe de sauvegarde", "backup_passphrase_placeholder": "Au moins 8 caractères", "backup_passphrase_confirm": "Confirmer la phrase secrète", "backup_passphrase_short": "La phrase de passe de sauvegarde doit comporter au moins 8 caractères.", @@ -865,7 +868,7 @@ "backup_restore_cancelled": "Restauration interrompue.", "backup_invalid_json": "Ce fichier n'est pas un fichier JSON valide.", "backup_invalid_format": "Format de sauvegarde inconnu ou obsolète.", - "backup_not_owner": "Seul le propriétaire du journal de bord peut créer des sauvegardes.", + "backup_not_owner": "Seul le propriétaire du journal de bord peut effectuer des sauvegardes.", "backup_not_authenticated": "Veuillez vous connecter pour restaurer une sauvegarde.", "backup_id_conflict": "Un journal de bord portant cet identifiant existe déjà.", "backup_overwrite_confirm": "Le journal existant portant le même identifiant sera remplacé. Voulez-vous continuer ?", @@ -880,17 +883,17 @@ "title": "Remarques importantes", "intro": "Veuillez lire les remarques suivantes avant d'utiliser Kapteins Daagbok.", "e2e_title": "Chiffrement de bout en bout", - "e2e_body": "Les données de ton journal de bord sont chiffrées de bout en bout. Seul toi – ou les personnes disposant de ta clé – pouvez en lire le contenu. Seules des données chiffrées sont stockées sur le serveur.", + "e2e_body": "Les données de ton journal de bord sont chiffrées de bout en bout. Seul toi – ou les personnes disposant de ta clé – pouvez en consulter le contenu. Seules des données chiffrées sont stockées sur le serveur.", "pwa_title": "Application web progressive (PWA)", "pwa_body": "Kapteins Daagbok fonctionne comme une application web progressive dans ton navigateur et peut être installée sur ton appareil, un peu comme une application native, mais sans passer par l'App Store.", "storage_title": "Stockage local et synchronisation", - "storage_body": "Tes données sont temporairement enregistrées localement sur ton appareil (IndexedDB). Lorsque tu es connecté à Internet, les modifications sont synchronisées avec le serveur. Tu peux continuer à travailler même sans connexion ; la synchronisation s'effectuera plus tard.", + "storage_body": "Tes données sont temporairement stockées localement sur ton appareil (IndexedDB). Lorsque tu es connecté à Internet, les modifications sont synchronisées avec le serveur. Tu peux continuer à travailler même sans connexion ; la synchronisation s'effectuera plus tard.", "free_title": "Gratuit et sans publicité", "free_body": "Kapteins Daagbok est gratuit et ne contient aucune publicité.", "liability_title": "Clause de non-responsabilité", "liability_body": "L'utilisation se fait sous votre propre responsabilité. Nous déclinons toute responsabilité pour les dommages résultant de l'utilisation de l'application, y compris les entrées de journal de bord erronées ou incomplètes, la perte de données ou les dysfonctionnements techniques.", "warranty_title": "Aucune garantie", - "warranty_body": "Nous ne garantissons ni le bon fonctionnement, ni l'exactitude, ni la disponibilité du service. Son fonctionnement peut être interrompu, limité ou suspendu à tout moment.", + "warranty_body": "Nous ne garantissons ni le bon fonctionnement, ni l'exactitude, ni la disponibilité du service. Son fonctionnement peut être interrompu, restreint ou suspendu à tout moment.", "copyright": "© 2026 KnorrLabs, Markus F.J. Busche", "accept": "Accepter et continuer", "close": "Fermer", @@ -899,7 +902,7 @@ "feedback": { "button_title": "Envoyer un commentaire", "title": "Commentaires", - "intro": "Signale-nous des bugs, des idées ou donne-nous ton avis. Ton message sera transmis à l'équipe du projet via un canal de communication sécurisé.", + "intro": "Signale-nous les bugs, partage tes idées ou fais-nous part de tes commentaires. Ton message sera transmis à l'équipe du projet via un canal de communication sécurisé.", "category_label": "Catégorie", "category_general": "Généralités", "category_bug": "Signaler une erreur", @@ -1014,7 +1017,7 @@ }, "welcome_public": { "title": "Bienvenue à bord !", - "body": "Découvrez notre journal de bord de démonstration, qui retrace trois jours de voyage dans la baie de Kiel, sans avoir besoin de créer de compte. Ce parcours vous présente les entrées du journal de bord ainsi que le choix du bateau et de l'équipage pour ce journal. Vous pourrez gérer votre flotte et votre équipage habituel ultérieurement dans votre profil utilisateur." + "body": "Découvrez notre journal de bord de démonstration, qui retrace trois jours de voyage dans la baie de Kiel, sans avoir besoin de créer de compte. Ce circuit vous présente les entrées du journal de bord ainsi que le choix du bateau et de l'équipage pour ce journal. Vous pourrez gérer votre flotte et votre équipage habituel ultérieurement dans votre profil utilisateur." }, "nav_logs": { "title": "Entrées du journal de bord", @@ -1034,7 +1037,7 @@ }, "nav_vessel": { "title": "Navire à inscrire dans le journal de bord", - "body": "Choisis dans ta flotte le vaisseau pour ce journal de bord. Tu peux gérer tes vaisseaux dans ton profil utilisateur, sous « Flotte et équipage »." + "body": "Choisis dans ta flotte le vaisseau qui figurera dans ce journal de bord. Tu peux gérer tes vaisseaux dans ton profil utilisateur, sous « Flotte et équipage »." }, "profile_vessel_pool": { "title": "flotte de navires", @@ -1046,7 +1049,7 @@ }, "nav_logbook_crew": { "title": "Équipage par journal de bord", - "body": "Choisis parmi les membres de l'équipage ceux qui figureront dans ce journal de bord en tant que skipper et équipage. Les jours de voyage reprennent cette sélection par défaut." + "body": "Choisis parmi les personnes disponibles celles qui figureront dans ce journal de bord en tant que skipper et équipage. Les jours de voyage reprennent cette sélection par défaut." }, "nav_stats": { "title": "Tableau de bord statistique", @@ -1072,7 +1075,7 @@ }, "seo": { "title": "Kapteins Daagbok – Journal de bord numérique gratuit pour yacht (sans publicité)", - "description": "Journal de bord numérique gratuit et sans publicité pour les yachts, avec cryptage de bout en bout et connexion via Passkey. Consignez en toute sécurité vos dates de voyage, vos tracés GPS, les informations sur l'équipage et le navire – même hors ligne en tant que PWA.", + "description": "Journal de bord numérique gratuit et sans publicité pour les yachts, avec cryptage de bout en bout et connexion via Passkey. Consignez en toute sécurité vos jours de voyage, vos traces GPS, les informations sur l'équipage et le navire – même hors ligne en tant que PWA.", "keywords": "Journal de bord de yacht, journal de bord de navire, journal de bord, voile, Passkey, cryptage E2E, trace GPS, journal de bord maritime, gratuit, sans publicité, sans frais, sans pub", "ogImageAlt": "Logo Kapteins Daagbok" } diff --git a/client/src/i18n/locales/nb.json b/client/src/i18n/locales/nb.json index e774b1b..7b6bdd5 100644 --- a/client/src/i18n/locales/nb.json +++ b/client/src/i18n/locales/nb.json @@ -66,7 +66,7 @@ "copy_phrase": "Kopiere nøkkel", "enter_recovery": "Skriv inn gjenopprettingsnøkkelen", "recovery_fallback_warning": "Din Passkey er godkjent, men enheten din støtter ikke maskinvarebasert nøkkelgenerering. Skriv inn gjenopprettingsnøkkelen på 12 ord for å dekryptere loggboken din.", - "recovery_placeholder": "Skriv inn gjenopprettingsnøkkelen din, som består av 12 ord, atskilt med mellomrom...", + "recovery_placeholder": "Skriv inn gjenopprettingskoden din, som består av 12 ord, atskilt med mellomrom...", "back": "Tilbake", "decrypting": "Dekryptering...", "decrypt_logbook": "Dechiffrere loggboken", @@ -78,7 +78,7 @@ "processing": "Behandler...", "help": "Hjelp", "setup_pin_title": "Konfigurere lokal PIN-kode (valgfritt)", - "setup_pin_warning": "Siden enheten din ikke støtter direkte Passkey-nøkkelgenerering, må du ellers oppgi din 12-ords nøkkel hver gang du logger inn på denne enheten. Opprett en lokal PIN-kode for å unngå dette.", + "setup_pin_warning": "Siden enheten din ikke støtter direkte Passkey-nøkkelgenerering, må du ellers oppgi 12-ordsnøkkelen din hver gang du logger inn på denne enheten. Opprett en lokal PIN-kode for å unngå dette.", "pin_placeholder": "F.eks. 123456", "pin_label": "Lokal PIN-kode (4–8 siffer)", "save_pin": "Lagre PIN-kode og fortsett", @@ -92,7 +92,7 @@ "error_invalid_host": "Passkey fungerer ikke via 127.0.0.1. Vennligst åpne appen via localhost.", "use_localhost_link": "Bytt til localhost", "error_passkey_cancelled": "Passkey-påloggingen ble avbrutt eller har utløpt. Prøv på nytt.", - "error_invalid_rp_id": "Passkey-domenet stemmer ikke (RP-ID). Bruk kun http://localhost:5173 lokalt med RP_ID=localhost i .env.", + "error_invalid_rp_id": "Passkey-domenet passer ikke (RP-ID). Bruk kun http://localhost:5173 lokalt med RP_ID=localhost i .env.", "error_session_incomplete": "Påloggingen er ufullstendig. Vennligst logg inn på nytt med Passkey.", "restore_checking": "Økten blir sjekket…", "restore_title": "Gjenopprett økt", @@ -143,7 +143,7 @@ "length_m": "Lengde (m)", "draft_m": "Dypgang (m)", "air_draft_m": "Høyde (m)", - "invalid_metric": "Ugyldig tallverdi — vennligst skriv inn måleenheten som et desimaltall (f.eks. 12,5).", + "invalid_metric": "Ugyldig tallverdi — vennligst skriv inn lengden som et desimaltall (f.eks. 12,5).", "port": "Hjemmehavn", "owner": "Eier", "charter": "Charterfirma", @@ -164,7 +164,7 @@ "photo_change": "Bytt bilde", "photo_delete": "Slett bilde", "tanks_section": "Tanker (kapasitet)", - "tanks_help": "Valgfritt i liter — muliggjør glidebryter i journalen ved kjente tankstørrelser.", + "tanks_help": "Valgfritt i liter — muliggjør glidebryter i loggboken ved kjente tankstørrelser.", "freshwater_capacity_l": "Drikkevann (liter)", "fuel_capacity_l": "Drivstoff (liter)", "greywater_capacity_l": "Gråvann (liter)", @@ -189,7 +189,7 @@ "destination": "Ankomsthavn (til)", "route": "Reise fra/til", "tanks": "Tanker", - "customize_columns": "Juster kolonner", + "customize_columns": "Tilpass kolonner", "column_selector_title": "Kolonner som skal vises", "freshwater": "Ferskvann (liter)", "fuel": "Drivstoff (liter)", @@ -208,7 +208,7 @@ "sign_clear": "Slett", "sign_export_image": "[Signatur]", "sign_with_passkey": "Del med Passkey", - "sign_passkey_signing": "Passkey blir hentet…", + "sign_passkey_signing": "Passkey blir forespurt…", "sign_passkey_signed": "Godkjent av {{username}}", "sign_passkey_export": "Passkey: {{username}} ({{date}})", "sign_attribution_export": "{{username}} ({{date}})", @@ -223,7 +223,7 @@ "sign_badge_skipper_title_valid": "Skipper har godkjent", "sign_badge_skipper_title_invalid": "Skipper-signaturen er ugyldig — innholdet er endret", "sign_classic_or_passkey": "Valgfritt: klassisk signatur eller Passkey-godkjenning øverst", - "sign_crew_passkey_hint": "Medarbeidere med skriveadgang kan dele via Passkey", + "sign_crew_passkey_hint": "Medlemmer av teamet med skriveadgang kan dele via Passkey", "sign_offline_hint": "Passkey-godkjenning krever internett — klassisk signatur er mulig uten nett", "sign_lock_notice": "Etter at loggbokoppføringen er signert, kan den ikke endres (med unntak av bilder) uten at skipperen og mannskapet må signere på nytt.", "sign_lock_active": "Denne oppføringen er signert. Endringer i loggboken (unntatt bilder) fjerner automatisk skipperens og mannskapets signaturer.", @@ -251,7 +251,7 @@ "live_actions_label": "Hurtigkampanjer", "live_stream_label": "Hendelseslogg", "live_stream_title": "Tidsskrift", - "live_no_events": "Ingen oppføringer ennå — trykk på en aktivitet.", + "live_no_events": "Ingen oppføringer ennå — trykk på en handling.", "live_motor_start": "Motorstart", "live_motor_stop": "Motorstopp", "live_cast_off": "Legge fra land", @@ -276,9 +276,9 @@ "live_photo_retake_btn": "Ta opp på nytt", "live_photo_capture_failed": "Opptaket mislyktes. Prøv på nytt.", "live_photo_open_camera_btn": "Åpne kameraet", - "live_photo_native_hint": "Ta et bilde med enhetens kamera og lagre det deretter her.", - "live_photo_camera_starting": "Kameraet startes…", - "live_photo_camera_denied": "Kameratilgang nektet eller utilgjengelig.", + "live_photo_native_hint": "Ta et bilde med kameraet på enheten og lagre det deretter her.", + "live_photo_camera_starting": "Kameraet starter…", + "live_photo_camera_denied": "Kameraet har ikke tilgang eller er ikke tilgjengelig.", "live_photo_camera_unavailable": "Denne nettleseren støtter ikke kameraet.", "live_photo_no_camera": "Denne enheten har ikke kamera.", "live_photo_error": "Bildet kunne ikke lagres.", @@ -304,7 +304,7 @@ "live_voice_caption_placeholder": "f.eks. radiokommunikasjon med havnesjefen", "live_voice_transcribe_action": "Transkribere", "live_voice_transcribing": "Transkriber...", - "live_voice_transcribe_failed": "Talememoet er lagret, men transkripsjonen mislyktes.", + "live_voice_transcribe_failed": "Talememo lagret, men transkripsjonen mislyktes.", "live_undo_voice_hint": "Talemelding lagret", "live_comment_btn": "Kommentar", "live_comment_placeholder": "Skriv inn fri tekst…", @@ -353,11 +353,11 @@ "live_stw_entry": "STW {{speed}} kn", "live_sog_placeholder": "f.eks. 5,2", "live_stw_placeholder": "f.eks. 4,8", - "live_sog_hint": "Fart over grunn (kn) — GPS-verdien fylles inn automatisk hvis den er tilgjengelig.", + "live_sog_hint": "Fart over grunn (kn) — GPS-verdien fylles ut automatisk hvis den er tilgjengelig.", "delete_entry": "Slett dag", "delete_confirm": "Er du sikker på at du vil slette denne reisedagen uten mulighet for å angre?", "carry_over_tanks_title": "Skal data fra i går overføres?", - "carry_over_tanks_confirm": "Skal starthavn, ferskvann, drivstoff og gråvann ved avreise overføres fra den siste reisedagen?\n\nStarthavn: {{departure}}\nFerskvann: {{fw}} l\nDrivstoff: {{fuel}} l\nGråvann: {{greywater}} l", + "carry_over_tanks_confirm": "Skal starthavn, startnivåer for ferskvann, drivstoff og gråvann overføres fra den siste reisedagen?\n\nStarthavn: {{departure}}\nFerskvann: {{fw}} l\nDrivstoff: {{fuel}} l\nGråvann: {{greywater}} l", "carry_over_tanks_yes": "Bruk", "carry_over_tanks_no": "Starte fra 0", "event_title": "Kronologisk hendelseslogg", @@ -410,7 +410,7 @@ "gps_quality_excellent": "Sterk GPS-mottak (±{{accuracy}} m)", "gps_quality_good": "God GPS-mottak (±{{accuracy}} m)", "gps_quality_fair": "Middels GPS-mottak (±{{accuracy}} m) – gå utendørs for bedre mottak.", - "gps_quality_poor": "Svakt GPS-signal (±{{accuracy}} m) – sannsynligvis få satellitter. Prøv på nytt utendørs eller sjekk posisjonen.", + "gps_quality_poor": "Svakt GPS-signal (±{{accuracy}} m) – antakelig få satellitter. Prøv på nytt utendørs eller sjekk posisjonen.", "gps_quality_unknown": "GPS-posisjon hentet (nøyaktighet ikke oppgitt av enheten).", "gps_live_intro_title": "Plassering for Live-Log", "gps_live_intro_body": "For automatiske posisjonsoppføringer og GPS-knappen trenger appen tilgang til posisjonen din.\n\nTrykk på «Tillat posisjon» – bekreft tillatelsen i den neste dialogboksen. Du kan når som helst legge inn posisjonen manuelt under «Posisjon».", @@ -446,7 +446,7 @@ "ai_summary_offline": "AI-sammendraget krever en internettforbindelse. Du er for øyeblikket frakoblet.", "photos_title": "Bildevedlegg", "photo_caption_label": "Bildetekst / Etikett (valgfritt)", - "photo_caption_placeholder": "f.eks. sette seil nær havneinnseilingen", + "photo_caption_placeholder": "f.eks. sette seil nær havneinnløpet", "photo_btn": "Ta bilde / Last opp", "photo_camera_btn": "Ta et bilde", "photo_gallery_btn": "Velg fra galleriet", @@ -471,12 +471,12 @@ "track_map_speed_slow": "sakte", "track_map_speed_fast": "raskt", "nmea_import_title": "Importer NMEA-protokoll", - "nmea_import_intro": "Last inn en .nmea-fil fra loggeren om bord. Appen foreslår loggoppføringer – du bestemmer selv hva som skal importeres.", + "nmea_import_intro": "Last inn en .nmea-fil fra loggeren om bord. Appen foreslår loggoppføringer – du bestemmer selv hva som skal overføres.", "nmea_import_btn": "Importer NMEA", "nmea_file_label": "NMEA-fil", "nmea_stats": "{{lines}} setninger gjenkjent · Typer: {{types}}", - "nmea_warn_no_position": "Ingen posisjonssetter funnet — spor- og GPS-feltene kan stå tomme.", - "nmea_warn_duplicate_file": "Denne NMEA-filen er allerede importert. Hvis du importerer den samme filen på nytt, vil det føre til dupliserte loggoppføringer.", + "nmea_warn_no_position": "Ingen posisjonssetninger funnet — spor- og GPS-feltene kan stå tomme.", + "nmea_warn_duplicate_file": "Denne NMEA-filen er allerede importert. Hvis du importerer den samme filen på nytt, vil det føre til doble loggoppføringer.", "nmea_mode_label": "Opprette journaloppføringer", "nmea_mode_interval": "Etter tidsintervall", "nmea_mode_change": "Ved vesentlige endringer", @@ -541,7 +541,10 @@ "logged_in_as": "Logg inn som {{name}}", "delete_confirm": "Er du sikker på at du vil slette denne loggboken permanent? Alle lokale data og serverkopier vil bli slettet.\n\nTips: Lag først en sikkerhetskopi (.daagbok) under Innstillinger → Sikkerhetskopiering og gjenoppretting, hvis du ønsker å beholde dataene senere.", "no_logbooks": "Ingen loggbøker funnet. Opprett din første loggbok for å komme i gang!", - "loading": "Loggbøkene lastes inn...", + "loading": "Loggbøker lastes inn...", + "travel_days_count_zero": "Ingen reisedager", + "travel_days_count_one": "1. reisedag", + "travel_days_count_other": "{{count}} Reisedager", "status_synced": "Synkronisert", "status_local": "Kun lokal cache", "delete_btn": "Slett loggboken", @@ -551,14 +554,14 @@ "role_owner": "Egen loggbok", "role_owner_hint": "Du er eier og skipper av denne loggboken", "role_crew": "Tilgang for mannskapet", - "role_crew_hint": "Inviterte loggbok — du kan bidra som besetningsmedlem og skrive under", + "role_crew_hint": "Inviterte loggbok — du kan bidra som besetningsmedlem og signere", "role_read": "Bare lesing", "role_read_hint": "Delt loggbok — kun visning, ingen redigering", "open_profile": "Åpne profilen til {{name}}", "open_logbook": "Åpne loggboken «{{title}}»", "edit_title": "Endre navn på loggboken", "edit_placeholder": "Nytt navn på loggboken", - "edit_success": "Loggboken er nå omdøpt", + "edit_success": "Loggboken er omdøpt", "edit_btn": "Endre navn", "filter_label": "Filtrer loggbøker", "filter_placeholder": "Navn, år, dato, mannskap eller skip …", @@ -601,7 +604,7 @@ "add_passkey_failed": "Passkey kunne ikke legges til.", "remove_passkey_btn": "Fjern Passkey", "remove_passkey_last_title": "Siste Passkey", - "remove_passkey_last_desc": "Den eneste Passkey kan ikke fjernes uten at du mister tilgangen til kontoen din. For å slette kontoen fullstendig, bruk sikkerhetssonen nederst på denne siden.", + "remove_passkey_last_desc": "Den eneste Passkey kan ikke fjernes uten at du mister tilgangen til kontoen din. For å slette kontoen fullstendig, bruk skjemaet nederst på denne siden.", "remove_passkey_failed": "Passkey kunne ikke fjernes.", "remove_passkey_confirm_title": "Passkey fjerne?", "remove_passkey_confirm_desc": "Denne enheten kan ikke lenger logge seg på med denne Passkey etter dette.", @@ -646,12 +649,12 @@ "device_title": "Denne enheten", "device_desc": "Lokal cache, synkroniseringsstatus og hurtiginnlogging i denne nettleseren.", "device_sync_pending": "{{count}} utestående synkroniseringsoppføringer", - "device_sync_ok": "Alle lokale endringer er synkronisert", + "device_sync_ok": "Alle lokale endringer synkroniseres", "device_remembered": "Kontoen er lagret på denne enheten for hurtiginnlogging", "device_not_remembered": "Kontoen er ikke på listen over hurtiginnlogginger", "device_forget_btn": "Glemt kontoen på denne enheten", "device_forget_confirm_title": "Fjerne hurtiginnlogging?", - "device_forget_confirm_desc": "Kontoen fjernes fra listen over hurtiginnlogginger på denne enheten. Sesjonen din og de lokale loggene dine beholdes.", + "device_forget_confirm_desc": "Kontoen fjernes fra listen over hurtiginnlogginger på denne enheten. Din økt og lokale logger beholdes.", "device_forget_confirm_yes": "Fjern", "device_forget_confirm_no": "Avbryt", "passkey_label": "Navn på ny Passkey (valgfritt)", @@ -680,7 +683,7 @@ "owm_key": "OpenWeatherMap API-nøkkel", "owm_help": "Valgfritt: egen OpenWeatherMap-API-nøkkel. Hvis dette feltet ikke fylles ut, brukes nøkkelen på serversiden fra operatørkonfigurasjonen.", "ai_title": "AI-funksjoner og personvern", - "ai_desc": "Godkjenn bruk av kunstig intelligens (lokale/skybaserte integrasjoner) for loggbøkene dine.", + "ai_desc": "Godkjenn bruk av kunstig intelligens (lokale/skyintegrasjoner) for loggbøkene dine.", "ai_help": "Aktivering gjør det mulig å oppsummere reiserapporter automatisk og transkribere talemeldinger. For behandling overføres lydopptak og loggbokoppføringer i kryptert form til OpenRouter. Dataene lagres ikke permanent der.\n\nSiden driften av disse skyressursene medfører kostnader, setter vi pris på frivillig støtte via Ko-fi-donasjonslenken i bunnteksten, slik at vi kan tilby disse funksjonene gratis for alle på lang sikt.", "ai_enable_label": "Aktiver transkripsjon og daglige sammendrag", "ai_unauthorized_alert_title": "AI-funksjoner ikke godkjent", @@ -720,7 +723,7 @@ }, "logbook_vessel": { "title": "Fartøy for denne loggboken", - "subtitle": "Velg skipet for denne loggboken. Reisedagene bruker seil- og drivstoffdataene for det valgte skipet.", + "subtitle": "Velg skipet for denne loggboken. Reisedagene bruker seil- og drivstoffdataene til det valgte skipet.", "active_vessel": "Fartøy for denne loggboken", "no_vessels_in_pool": "Ingen skip i flåten – opprett først i brukerprofilen.", "no_vessel": "Ingen båt valgt", @@ -734,7 +737,7 @@ "title": "Fast mannskap og skipper", "subtitle": "Opprett din personellpool her – skippere og mannskap for alle loggbøker. Fra denne poolen velger du det aktive mannskapet for hver loggbok og hver reisedag.", "loading": "Brukerpoolen lastes inn…", - "skippers_section": "Faste skippere", + "skippers_section": "Faste skipper", "crew_section": "Fast mannskap", "add_skipper": "Legg til skipper", "add_crew": "Legg til et besetningsmedlem", @@ -755,11 +758,11 @@ "unnamed": "Uten navn", "save": "Lagre mannskap", "saved": "Mannskapet er lagret i loggboken.", - "selection_only_hint": "Du ser besetningen som eieren har fastsatt (delt loggbok)." + "selection_only_hint": "Du ser besetningen som eieren har angitt (delt loggbok)." }, "entry_crew": { "title": "Mannskapet på denne reisedagen", - "subtitle": "Kan avvike fra standarden i loggboken. De påfølgende reisedagene overtar dataene fra dagen før.", + "subtitle": "Kan avvike fra standarden i loggboken. De påfølgende reisedagene overtar opplysningene fra dagen før.", "day_skipper": "Skipper denne dagen", "day_crew": "Mannskapet denne dagen", "no_skipper": "Ingen skipper er valgt", @@ -823,7 +826,7 @@ "danger_zone_desc": "Når du sletter kontoen din, blir alle dine Passkey-er, loggbøker, skipdata, mannskapsprofiler, reiseoppføringer og E2E-nøkler slettet permanent. Denne handlingen kan ikke angres.", "delete_account_btn": "Slette kontoen permanent", "delete_account_confirm_title": "Slette kontoen?", - "delete_account_confirm_desc": "Er du helt sikker på at du vil slette kontoen din og alle tilhørende loggbøker og E2E-krypterte data permanent?", + "delete_account_confirm_desc": "Er du helt sikker på at du ønsker å slette kontoen din og alle tilhørende logger samt E2E-krypterte data permanent?", "delete_account_confirm_yes": "Ja, slett kontoen og alle opplysningene", "delete_account_confirm_no": "Avbryt", "delete_account_failed": "Kontoen kunne ikke slettes. Prøv på nytt.", @@ -882,9 +885,9 @@ "e2e_title": "End-til-ende-kryptering", "e2e_body": "Loggboksdataene dine krypteres fra ende til ende. Bare du – eller personer som har nøkkelen din – kan lese innholdet. Det lagres utelukkende krypterte data på serveren.", "pwa_title": "Progressiv nettapp (PWA)", - "pwa_body": "Kapteins Daagbok kjører som en progressiv nettapp i nettleseren din og kan installeres på enheten din – på samme måte som en innfødt app, men uten appbutikk.", + "pwa_body": "Kapteins Daagbok kjører som en progressiv nettapp i nettleseren din og kan installeres på enheten din – på samme måte som en innfødt app, men uten å gå via en app-butikk.", "storage_title": "Lokal lagring og synkronisering", - "storage_body": "Dataene dine lagres midlertidig lokalt på enheten din (IndexedDB). Når du har en aktiv internettforbindelse, synkroniseres endringene med serveren. Du kan fortsette å jobbe uten nettilgang; synkroniseringen skjer senere.", + "storage_body": "Dataene dine lagres midlertidig lokalt på enheten din (IndexedDB). Når du har en aktiv internettforbindelse, synkroniseres endringene med serveren. Du kan fortsette å jobbe uten nettforbindelse; synkroniseringen skjer senere.", "free_title": "Gratis og uten reklame", "free_body": "Kapteins Daagbok er gratis og inneholder ingen reklame.", "liability_title": "Ansvarsfraskrivelse", @@ -958,7 +961,7 @@ }, "stats": { "title": "Statistikk", - "subtitle": "Rangering, forbruk og drivtype på et øyeblikk", + "subtitle": "Rangering, drivstoffforbruk og drivtype på et øyeblikk", "scope_label": "Analyseområde", "scope_logbook": "Denne loggboken", "scope_account": "Alle loggbøker", @@ -983,7 +986,7 @@ "avg_distance": "Gjennomsnitt per reisedag", "avg_fuel": "Ø Drivstoff", "avg_water": "Ø Vann", - "fuel_per_nm": "Drivstoff per nautisk mil", + "fuel_per_nm": "Drivstoff per sjømil", "fuel_per_motor_hour": "Drivstoff per driftstime", "daily_fuel_per_motor_hour": "Drivstoffforbruk per maskintime per reisedag", "fuel_legend": "Drivstoff", @@ -1004,7 +1007,7 @@ "tour": { "skip": "Hopp over omvisningen", "back": "Tilbake", - "next": "Videre", + "next": "Les videre", "finish": "Ferdig", "progress": "Trinn {{current}} av {{total}}", "steps": { @@ -1054,7 +1057,7 @@ }, "nav_feedback": { "title": "Send tilbakemelding", - "body": "Gjennom dette skjemaet kan du sende feilmeldinger, forslag eller generell tilbakemelding direkte til prosjektteamet – også etter turen, når som helst via ikonet øverst til høyre." + "body": "Gjennom dette skjemaet kan du sende inn feilmeldinger, forslag eller generelle tilbakemeldinger direkte til prosjektteamet – også etter turen, når som helst via ikonet øverst til høyre." }, "nav_profile": { "title": "Brukerprofilen din", @@ -1072,7 +1075,7 @@ }, "seo": { "title": "Kapteins Daagbok – Gratis digitalt loggbok for yachter (uten reklame)", - "description": "Gratis, reklamefritt digitalt båtlogg med ende-til-ende-kryptering og Passkey-pålogging. Dokumenter reisedager, GPS-spor, mannskap og båtdata på en sikker måte – også offline som PWA.", + "description": "Gratis, reklamefritt digitalt båtloggbok med ende-til-ende-kryptering og Passkey-pålogging. Dokumenter reisedager, GPS-spor, mannskap og båtdata på en sikker måte – også offline som PWA.", "keywords": "Yachtlogg, skipslogg, bordlogg, seiling, Passkey, E2E-kryptering, GPS-spor, maritim logg, gratis, uten reklame, gratis, uten annonser", "ogImageAlt": "Kapteins Daagbok Logo" } diff --git a/client/src/i18n/locales/sv.json b/client/src/i18n/locales/sv.json index 51dbebd..e170f2e 100644 --- a/client/src/i18n/locales/sv.json +++ b/client/src/i18n/locales/sv.json @@ -31,7 +31,7 @@ "export_failed": "Exporten misslyckades." }, "common": { - "unsaved_changes_title": "Osparade ändringar", + "unsaved_changes_title": "Olagrade ändringar", "unsaved_changes_message": "Du har ändringar som inte har sparats. Vill du verkligen lämna sidan? Dina ändringar kommer att gå förlorade.", "unsaved_changes_stay": "Stanna kvar", "unsaved_changes_save_leave": "Spara och avsluta", @@ -43,7 +43,7 @@ "vessel": "Fartygsdata", "crew": "Besättning", "deviation": "Avledningstabell", - "logs": "Loggboksanteckningar", + "logs": "Loggposter", "stats": "Statistik", "settings": "Inställningar", "admin": "Admin" @@ -55,7 +55,7 @@ "login": "Logga in med Passkey", "login_as": "Logga in som {{name}}", "quick_login": "Snabbinloggning", - "forget_account": "Glömt ditt konto på den här enheten", + "forget_account": "Glömt inloggningsuppgifterna på den här enheten", "not_user": "Inte {{name}}?", "recovery_title": "Din återställningsnyckel", "recovery_warning": "VIKTIGT: Skriv ner dessa 12 ord. Om du tappar bort din Passkey och dessa ord går det inte att återställa dina data.", @@ -78,13 +78,13 @@ "processing": "Bearbetar...", "help": "Hjälp", "setup_pin_title": "Ställa in lokal PIN-kod (valfritt)", - "setup_pin_warning": "Eftersom din enhet inte stöder direkt Passkey-nyckelgenerering skulle du annars behöva ange din 12-ordsnyckel varje gång du loggar in på den här enheten. Ställ in en lokal PIN-kod för att undvika detta.", + "setup_pin_warning": "Eftersom din enhet inte stöder direkt Passkey-nyckelgenerering skulle du annars behöva ange din 12-ordskod vid varje inloggning på den här enheten. Ställ in en lokal PIN-kod för att undvika detta.", "pin_placeholder": "T.ex. 123456", "pin_label": "Lokal PIN-kod (4–8 siffror)", "save_pin": "Spara PIN-kod & Fortsätt", "skip_pin": "Hoppa över och använd återställning", "enter_pin_title": "Dekryptera med PIN-kod", - "enter_pin_warning": "Ange din lokala PIN-kod för att aktivera dekrypteringsnyckeln på den här enheten.", + "enter_pin_warning": "Ange din lokala PIN-kod för att låsa upp dekrypteringsnyckeln på den här enheten.", "enter_pin_placeholder": "Ange din PIN-kod...", "decrypt_with_pin": "Avkoda", "use_recovery_instead": "Använd istället återställningsnyckeln", @@ -221,14 +221,14 @@ "sign_badge_skipper": "skeppare", "sign_badge_skipper_invalid": "Ogiltigt", "sign_badge_skipper_title_valid": "Skipper har godkänt", - "sign_badge_skipper_title_invalid": "Skipper-signaturen är ogiltig — innehållet har ändrats", + "sign_badge_skipper_title_invalid": "Skippers signatur är ogiltig — innehållet har ändrats", "sign_classic_or_passkey": "Alternativ: klassisk signatur eller Passkey-godkännande högst upp", "sign_crew_passkey_hint": "Besättningsmedlemmar med skrivbehörighet kan dela via Passkey", - "sign_offline_hint": "Passkey-godkännande kräver internetuppkoppling — traditionell underskrift är möjlig offline", + "sign_offline_hint": "Passkey-godkännande kräver internetuppkoppling — traditionell signatur är möjlig offline", "sign_lock_notice": "Efter att loggboksanteckningen har undertecknats kan inga ändringar göras (förutom i bilderna) utan att skepparen och besättningen måste underteckna på nytt.", "sign_lock_active": "Denna anteckning är undertecknad. Ändringar i loggboken (förutom foton) raderar automatiskt skepparens och besättningens underskrifter.", "sign_lock_warning_title": "Bekräfta signaturen", - "sign_lock_warning": "Efter att loggboksanteckningen har undertecknats går det inte längre att göra ändringar (förutom i bilderna) utan att skepparen och besättningen måste underteckna den på nytt.\n\nVill du fortsätta?", + "sign_lock_warning": "Efter att loggboksanteckningen har undertecknats går det inte längre att göra ändringar (förutom i bilderna) utan att skepparen och besättningen måste underteckna på nytt.\n\nVill du fortsätta?", "sign_proceed": "Underteckna", "sign_cancel": "Avbryt", "sign_cleared_re_sign_title": "Underskrifter har tagits bort", @@ -249,7 +249,7 @@ "live_action_error": "Det gick inte att spara inlägget.", "live_open_editor": "Fullständig redigerare", "live_actions_label": "Snabba erbjudanden", - "live_stream_label": "Händelselogg", + "live_stream_label": "Händelseprotokoll", "live_stream_title": "Tidskrift", "live_no_events": "Inga inlägg ännu — klicka på en aktivitet.", "live_motor_start": "Motorstart", @@ -316,7 +316,7 @@ "live_weather_owm_btn": "OpenWeatherMap Hämta väderinformation", "live_weather_owm_loading": "Väder hämtas…", "live_weather_position_required": "För väder från OpenWeatherMap, ange först en position (knappen ”Position”). Positionen får inte vara äldre än 6 timmar.", - "live_weather_position_stale": "Den senaste positionen är äldre än 6 timmar. Logga in en ny position innan du hämtar väderinformation.", + "live_weather_position_stale": "Den senaste positionen är äldre än 6 timmar. Logga in en ny position innan du hämtar väderinformationen.", "live_wind_btn": "Vind", "live_temp_btn": "T °C", "live_pressure_btn": "Lufttryck", @@ -357,7 +357,7 @@ "delete_entry": "Ta bort dag", "delete_confirm": "Är du säker på att du vill radera den här resedagen utan möjlighet att ångra dig?", "carry_over_tanks_title": "Överföra data från föregående dag?", - "carry_over_tanks_confirm": "Ska utgångsvärdena för avgångshamn, färskvatten, bränsle och gråvatten från den sista resedagen användas?\n\nAvgångshamn: {{departure}}\nFärskvatten: {{fw}} l\nBränsle: {{fuel}} l\nGråvatten: {{greywater}} l", + "carry_over_tanks_confirm": "Ska starthamn, startnivåer för färskvatten, bränsle och gråvatten överföras från den sista resedagen?\n\nStarthamn: {{departure}}\nFärskvatten: {{fw}} L\nBränsle: {{fuel}} L\nGråvatten: {{greywater}} L", "carry_over_tanks_yes": "Bekräfta", "carry_over_tanks_no": "Börja från noll", "event_title": "Kronologisk händelselogg", @@ -399,7 +399,7 @@ "event_location_placeholder": "t.ex. Kiel", "event_remarks": "Anmärkningar / Händelser", "gps_btn": "Hämta GPS-koordinater", - "gps_permission_denied": "Åtkomst till platsinformationen nekades. Tillåt detta i webbläsarens eller enhetens inställningar och försök igen.", + "gps_permission_denied": "Åtkomst till platsen har nekats. Tillåt detta i webbläsarens eller enhetens inställningar och försök igen.", "gps_timeout": "GPS-tidsöverskridning. Försök igen – helst utomhus där mottagningen är god.", "gps_position_unavailable": "Ingen GPS-signal tillgänglig. Vänta eller ange koordinaterna manuellt.", "gps_unavailable": "GPS stöds inte av den här webbläsaren eller enheten.", @@ -411,12 +411,12 @@ "gps_quality_good": "Bra GPS-mottagning (±{{accuracy}} m)", "gps_quality_fair": "Måttlig GPS-mottagning (±{{accuracy}} m) – gå utomhus för bättre mottagning.", "gps_quality_poor": "Svag GPS-mottagning (±{{accuracy}} m) – troligen få satelliter. Försök igen utomhus eller kontrollera positionen.", - "gps_quality_unknown": "GPS-positionen har hämtats (enheten rapporterar ingen noggrannhet).", + "gps_quality_unknown": "GPS-positionen har hämtats (enheten rapporterar inte noggrannheten).", "gps_live_intro_title": "Plats för Live-Log", "gps_live_intro_body": "För automatiska positionsinmatningar och GPS-knappen behöver appen tillgång till din position.\n\nTryck på ”Tillåt position” – bekräfta godkännandet i nästa dialogruta. Du kan när som helst ange positionen manuellt under ”Position”.", "gps_live_intro_allow": "Tillåt platsåtkomst", "gps_live_intro_later": "Senare", - "gps_enable_in_settings_hint": "Åtkomst till platsuppgifter är blockerad. Du kan aktivera åtkomsten i webbläsarens eller enhetens inställningar (webbplats/app → plats).", + "gps_enable_in_settings_hint": "Åtkomst till din plats är blockerad. Du kan aktivera åtkomsten i webbläsarens eller enhetens inställningar (webbplats/app → plats).", "weather_btn": "OpenWeatherMap Hämta väderinformation", "weather_offline": "OpenWeatherMap kräver en internetanslutning. Du är för närvarande offline.", "event_wind_pressure": "Lufttryck (hPa)", @@ -441,7 +441,7 @@ "ai_summary_attempts_remaining": "Fortfarande {{remaining}} av {{max}} försök", "ai_summary_error": "Sammanfattningen med AI misslyckades. Försök igen senare.", "ai_summary_error_no_key": "Ingen OpenRouter-API-nyckel har konfigurerats på servern.", - "ai_summary_error_rate_limited": "Det maximala antalet genereringar för denna resedag har uppnåtts.", + "ai_summary_error_rate_limited": "Det maximala antalet genereringar för denna resdag har uppnåtts.", "ai_summary_error_forbidden": "Endast skepparen får skapa AI-sammanfattningar.", "ai_summary_offline": "AI-sammanfattningen kräver en internetanslutning. Du är för närvarande offline.", "photos_title": "Bilagor med bilder", @@ -452,7 +452,7 @@ "photo_gallery_btn": "Välj från galleriet", "photo_processing": "Bearbetas...", "no_photos": "Inga bilder har lagts till för denna resedag ännu.", - "photo_delete_confirm": "Är du säker på att du vill radera den här bilden utan möjlighet att återställa den?", + "photo_delete_confirm": "Är du säker på att du vill radera den här bilden permanent?", "confirm_yes": "Ja", "confirm_no": "Nej", "track_upload_title": "GPS-spår (fil)", @@ -542,6 +542,9 @@ "delete_confirm": "Är du säker på att du vill radera den här loggboken utan möjlighet till återställning? Alla lokala data och serverkopior kommer att raderas.\n\nTips: Skapa först en säkerhetskopia (.daagbok) under Inställningar → Säkerhetskopiering och återställning om du vill behålla uppgifterna senare.", "no_logbooks": "Inga loggböcker hittades. Skapa din första loggbok för att komma igång!", "loading": "Loggböckerna laddas...", + "travel_days_count_zero": "Inga resdagar", + "travel_days_count_one": "1 resedag", + "travel_days_count_other": "{{count}} Resdagar", "status_synced": "Synkroniserad", "status_local": "Endast lokal cache", "delete_btn": "Radera loggboken", @@ -611,7 +614,7 @@ "pin_status": "Status", "pin_active": "Aktiv på den här enheten", "pin_inactive": "Ej inrett", - "pin_confirm_label": "Bekräfta PIN-koden", + "pin_confirm_label": "Bekräfta PIN-kod", "pin_confirm_placeholder": "Ange PIN-koden igen", "pin_set_btn": "Ställa in PIN-kod", "pin_change_btn": "Ändra PIN-kod", @@ -647,7 +650,7 @@ "device_desc": "Lokal cache, synkroniseringsstatus och snabbinloggning i den här webbläsaren.", "device_sync_pending": "{{count}} utestående synkroniseringsposter", "device_sync_ok": "Alla lokala ändringar synkroniseras", - "device_remembered": "Ett konto för snabbinloggning har sparats på den här enheten", + "device_remembered": "Ett konto för snabb inloggning har sparats på den här enheten", "device_not_remembered": "Kontot finns inte med i listan för snabbinloggning", "device_forget_btn": "Glömt ditt konto på den här enheten", "device_forget_confirm_title": "Ta bort snabbinloggning?", @@ -668,7 +671,7 @@ "appearance_title": "App & presentation", "appearance_desc": "Designen och färgschemat gäller för hela appen på den här enheten.", "theme_label": "Appens designstil", - "theme_auto": "Automatiskt (OS-igenkänning)", + "theme_auto": "Automatiskt (operativsystemskänning)", "theme_ocean": "Ocean (glasmorfism)", "theme_material": "Material (Android)", "theme_cupertino": "Cupertino (iOS)", @@ -681,7 +684,7 @@ "owm_help": "Valfritt: egen OpenWeatherMap-API-nyckel. Om inget anges används den serverbaserade nyckeln från operatörskonfigurationen.", "ai_title": "AI-funktioner och dataskydd", "ai_desc": "Godkänn användningen av artificiell intelligens (lokala/molnbaserade integrationer) för dina loggböcker.", - "ai_help": "När funktionen är aktiverad kan reserapporter sammanfattas automatiskt och röstmeddelanden transkriberas. För bearbetning överförs röstinspelningar och loggboksanteckningar i krypterad form till OpenRouter. Uppgifterna sparas inte permanent där.\n\nEftersom driften av dessa molnresurser medför kostnader uppskattar vi frivilligt stöd via Ko-fi-donationslänken i sidfoten, så att vi kan erbjuda dessa funktioner gratis för alla på lång sikt.", + "ai_help": "När funktionen är aktiverad kan reserapporter sammanfattas automatiskt och röstanteckningar transkriberas. För bearbetning överförs röstinspelningar och loggboksanteckningar i krypterad form till OpenRouter. Uppgifterna sparas inte permanent där.\n\nEftersom driften av dessa molnresurser medför kostnader uppskattar vi frivilligt stöd via Ko-fi-donationslänken i sidfoten, så att vi kan erbjuda dessa funktioner gratis för alla på lång sikt.", "ai_enable_label": "Aktivera transkribering och dagliga sammanfattningar", "ai_unauthorized_alert_title": "AI-funktioner är inte tillåtna", "ai_unauthorized_alert_desc": "För att transkribera röstmemon eller sammanfatta reseskildringar måste du godkänna dataöverföringen till OpenRouter i din användarprofil under ”AI-funktioner & integritet”.", @@ -787,7 +790,7 @@ "save_member": "Spara medlem", "saved": "Skipperprofilen har sparats!", "loading": "Besättningsfiler laddas...", - "delete_confirm": "Är du säker på att du vill ta bort den här medlemmen ur gruppen?" + "delete_confirm": "Är du säker på att du vill ta bort den här besättningsmedlemmen?" }, "deviation": { "title": "Avvikelse-tabell (kompassavvikelse)", @@ -803,12 +806,12 @@ "title": "Inställningar för loggboken", "subtitle": "Dela, säkerhetskopiera och samarbeta kring denna loggbok.", "select_logbook_hint": "Välj en loggbok för att redigera dess inställningar.", - "no_key": "Ingen OpenWeatherMap-API-nyckel tillgänglig. Lägg in en egen nyckel i användarprofilen eller kontakta operatören.", + "no_key": "Ingen OpenWeatherMap-API-nyckel tillgänglig. Spara en egen nyckel i användarprofilen eller kontakta operatören.", "weather_success": "Väderdata har hämtats!", "weather_error": "Hämtningen av väderdata misslyckades. Kontrollera API-nyckeln och anslutningen.", - "weather_unauthorized": "Hämtningen av väderdata misslyckades. API-nyckeln är ogiltig eller inte auktoriserad.", + "weather_unauthorized": "Hämtningen av väderdata misslyckades. API-nyckeln är ogiltig eller saknar behörighet.", "weather_not_found": "Det gick inte att hämta väderdata. Den angivna orten eller koordinaterna hittades inte.", - "weather_bad_request": "Hämtningen av väderdata misslyckades. Ingen ort eller GPS-position har angetts.", + "weather_bad_request": "Hämtningen av väderdata misslyckades. Ingen ort och ingen GPS-position har angetts.", "weather_date_mismatch": "Väderdata kan endast hämtas för dagens datum ({{today}}). Denna loggboksanteckning är daterad den {{date}}.", "gps_error": "Ange en plats eller ta reda på GPS-koordinaterna.", "share_title": "Dela loggboken (skrivskyddad)", @@ -820,7 +823,7 @@ "link_qr_hint": "QR-kod att skanna med smarttelefonen", "link_qr_alt": "QR-kod för länken", "danger_zone_title": "Farlig zon", - "danger_zone_desc": "Om du raderar ditt konto kommer alla dina Passkey, loggböcker, fartygsdata, besättningsprofiler, reseinlägg och E2E-nycklar att raderas permanent. Denna åtgärd kan inte ångras.", + "danger_zone_desc": "Om du raderar ditt konto kommer alla dina Passkey, loggböcker, fartygsdata, besättningsprofiler, reseinlägg och E2E-nycklar att raderas oåterkalleligt. Denna åtgärd kan inte ångras.", "delete_account_btn": "Radera kontot permanent", "delete_account_confirm_title": "Vill du radera kontot?", "delete_account_confirm_desc": "Är du helt säker på att du vill radera ditt konto och alla tillhörande loggböcker samt E2E-krypterade data utan möjlighet till återställning?", @@ -836,7 +839,7 @@ "invite_push_prompt_later": "Senare", "invite_push_prompt_success": "Push-meddelanden är aktiverade på den här enheten.", "backup_title": "Säkerhetskopiering och återställning", - "backup_desc": "Fullständig krypterad säkerhetskopia av denna loggbok (inlägg, foton, röstmeddelanden, GPS-spår, besättning, fartyg). Skyddad med säkerhetskopieringslösenord – för återställning på detta eller ett nytt konto.", + "backup_desc": "Fullständig krypterad säkerhetskopia av denna loggbok (anteckningar, foton, röstmeddelanden, GPS-spår, besättning, fartyg). Skyddad med säkerhetskopieringslösenord – för återställning på detta eller ett nytt konto.", "backup_export_title": "Skapa en säkerhetskopia", "backup_export_desc": "Ladda ner alla lokala data som en komprimerad .daagbok-fil. Förvara filen och lösenordet separat och på ett säkert ställe.", "backup_restore_title": "Återställ säkerhetskopia", @@ -847,7 +850,7 @@ "backup_passphrase_short": "Säkerhetsfrasen måste bestå av minst 8 tecken.", "backup_passphrase_mismatch": "Lösenordssatserna stämmer inte överens.", "backup_wrong_passphrase": "Felaktig lösenfras eller skadad säkerhetskopia.", - "backup_export_btn": "Ladda ner säkerhetskopian", + "backup_export_btn": "Ladda ner säkerhetskopia", "backup_exporting": "Säkerhetskopiering pågår…", "backup_export_success": "Säkerhetskopia skapad ({{count}} resdagar).", "backup_file_label": "Säkerhetskopia (.daagbok)", @@ -872,7 +875,7 @@ "backup_new_id_confirm": "Ska säkerhetskopian importeras som en ny logg med ett nytt ID?", "backup_stat_entries": "{{count}} Resdagar", "backup_stat_photos": "{{count}} Foton", - "backup_stat_crew": "{{count}} Besättningsmedlemmar", + "backup_stat_crew": "{{count}} Besättningsposter", "backup_stat_tracks": "{{count}} GPS-spår", "backup_exported_at": "Exporterat: {{date}}" }, @@ -888,9 +891,9 @@ "free_title": "Gratis och utan reklam", "free_body": "Kapteins Daagbok är gratis och innehåller inga annonser.", "liability_title": "Ansvarsfriskrivning", - "liability_body": "Användningen sker på eget ansvar. Vi tar inget ansvar för skador som uppstår till följd av användningen av appen – inklusive felaktiga eller ofullständiga loggboksanteckningar, dataförlust eller tekniska störningar.", + "liability_body": "Användningen sker på eget ansvar. Vi tar inget ansvar för skador som uppstår till följd av användningen av appen – inklusive felaktiga eller ofullständiga loggboksposter, dataförlust eller tekniska störningar.", "warranty_title": "Ingen garanti", - "warranty_body": "Ingen garanti ges för tjänstens funktion, korrekthet eller tillgänglighet. Driften kan när som helst avbrytas, begränsas eller upphöra.", + "warranty_body": "Ingen garanti ges för tjänstens funktion, riktighet eller tillgänglighet. Driften kan när som helst avbrytas, begränsas eller upphöra.", "copyright": "© 2026 KnorrLabs, Markus F.J. Busche", "accept": "Godkänn och fortsätt", "close": "Stäng", @@ -917,7 +920,7 @@ "error_invalid_email": "Ange en giltig e-postadress.", "error_not_configured": "Feedback är inte tillgängligt på den här servern.", "error_rate_limited": "För många feedbackmeddelanden på kort tid. Vänta några minuter.", - "error_spam": "Det gick inte att skicka detta meddelande. Formulera det på ett annat sätt." + "error_spam": "Det gick inte att skicka meddelandet. Formulera det på ett annat sätt." }, "demo": { "logbook_title": "Demologgbok Östersjön", @@ -931,7 +934,7 @@ "error_missing_key": "Inbjudningslänken innehåller ingen dekrypteringsnyckel (#key=...). Använd den fullständiga länken från ägaren.", "error_expired": "Denna inbjudan har gått ut (giltig i 48 timmar).", "error_invalid_token": "Inbjudningstokenet är ogiltigt.", - "error_load_failed": "Det gick inte att hämta informationen om inbjudan.", + "error_load_failed": "Det gick inte att ladda inbjudningsuppgifterna.", "error_incomplete_session": "Inloggningen är ofullständig – logga in igen (användar-ID saknas).", "error_accept_failed": "Registreringen misslyckades.", "error_login_failed": "Passkey-Inloggningen misslyckades.", @@ -967,7 +970,7 @@ "total_distance": "Total sträcka", "travel_days": "Resedagar", "sail_distance": "Under segel", - "motor_distance": "Maskinrutt", + "motor_distance": "Maskinfärd", "motor_hours_total": "Totalt antal driftstimmar", "daily_motor_hours": "Maskinstimmar per resdag", "avg_motor_hours": "Genomsnittligt antal maskintimmar per resdag", @@ -977,10 +980,10 @@ "daily_etmal": "Dagsmål", "daily_consumption": "Dagsförbrukning", "route_overview": "Rutt", - "route_map_title": "Översikt över sträckorna", + "route_map_title": "Översikt över banorna", "propulsion_title": "Segel mot motor", "propulsion_hint": "Indelningen baseras på loggbokshändelserna per resedag, inte på GPS-segment.", - "avg_distance": "i genomsnitt per resdag", + "avg_distance": "i genomsnitt per resedag", "avg_fuel": "Ø Bränsle", "avg_water": "Ø Vatten", "fuel_per_nm": "Bränsle per sjömil", @@ -1014,15 +1017,15 @@ }, "welcome_public": { "title": "Välkommen ombord!", - "body": "Utforska vårt demologgbok med tre resdagar i Kielerförden – helt utan att behöva skapa ett konto. Turen visar dig loggboksposter samt valet av fartyg och besättning för denna loggbok. Du kan senare lägga till flottan och stambesättningen i din användarprofil." + "body": "Utforska vårt demologgbok med tre resdagar i Kielerförden – helt utan att behöva skapa ett konto. Turen visar dig loggboksposter samt valet av fartyg och besättning för denna loggbok. Du kan senare lägga till fartyg och fast besättning i din användarprofil." }, "nav_logs": { - "title": "Loggposter", + "title": "Loggboksanteckningar", "body": "Här hanterar du dina resedagar – avfärd, destination, väder, bränslenivåer och GPS-spår." }, "entry_list": { "title": "Dina resdagar", - "body": "Varje kort representerar en resedag. Tryck på en post för att se eller redigera detaljerna." + "body": "Varje kort representerar en resedag. Tryck på en post för att visa eller redigera detaljerna." }, "entry_open": { "title": "Öppna resedag", @@ -1038,7 +1041,7 @@ }, "profile_vessel_pool": { "title": "Fartygsflotta", - "body": "I användarprofilen lägger du in alla dina båtar – charterbåtar, egen båt osv. För varje loggbok väljer du sedan rätt båt." + "body": "I användarprofilen lägger du till alla dina båtar – charterbåtar, egen båt osv. För varje loggbok väljer du sedan rätt båt." }, "profile_crew_pool": { "title": "Fast besättning & skeppare", @@ -1046,11 +1049,11 @@ }, "nav_logbook_crew": { "title": "Besättning per loggbok", - "body": "Välj från listan vem som ska anges som skeppare och besättning i denna loggbok. Resedagarna övertar detta val som standard." + "body": "Välj från listan vilka som ska anges som skeppare och besättning i denna loggbok. Resedagarna övertar detta val som standard." }, "nav_stats": { "title": "Statistikpanel", - "body": "Här kan du se körsträckor, bränsleförbrukning, rutkartor och drivkraftsfördelning – automatiskt beräknat utifrån dina loggboksanteckningar." + "body": "Här kan du se körsträckor, bränsleförbrukning, rutkartor och drivmedelsfördelning – automatiskt beräknat utifrån dina loggboksanteckningar." }, "nav_feedback": { "title": "Skicka feedback", @@ -1062,7 +1065,7 @@ }, "profile_preferences": { "title": "Konto & visning", - "body": "Här hanterar du din kontoidentitet, ditt tema och ljus-/mörkläget. Du kan starta appguiden om när som helst. Passkeys och säkerhetsinställningar hittar du längre ner i profilen." + "body": "Här hanterar du din kontoidentitet, ditt tema och ljus-/mörkläget. Du kan starta appguiden om när som helst. Passkeys och säkerhetsinställningarna hittar du längre ner i profilen." }, "finish": { "title": "Okej!", diff --git a/client/src/services/logbook.ts b/client/src/services/logbook.ts index 7e65db2..8febb61 100644 --- a/client/src/services/logbook.ts +++ b/client/src/services/logbook.ts @@ -34,6 +34,8 @@ export interface DecryptedLogbook { isShared: boolean accessRole: LogbookAccessRole isDemo?: boolean + lastTravelDate?: string + entryCount?: number } // Helper to decrypt a logbook's title using the active logbook key or master key @@ -142,10 +144,24 @@ export async function fetchLogbooks(): Promise { // Retrieve all from Dexie cache const cachedLogbooks = await db.logbooks.toArray() - // Decrypt titles + // Decrypt titles and query last travel dates const decrypted: DecryptedLogbook[] = [] for (const lb of cachedLogbooks) { const title = await decryptLogbookTitle(lb.id, lb.encryptedTitle) + + // Find latest travel date from local entries cache + const entries = await db.entries.where({ logbookId: lb.id }).toArray() + let lastTravelDate: string | undefined = undefined + if (entries.length > 0) { + const dates = entries + .map((e) => e.listCache?.date) + .filter((d): d is string => typeof d === 'string' && d.length > 0) + if (dates.length > 0) { + dates.sort() + lastTravelDate = dates[dates.length - 1] + } + } + decrypted.push({ id: lb.id, title, @@ -155,7 +171,9 @@ export async function fetchLogbooks(): Promise { accessRole: lb.isShared === 1 ? parseCollaborationRole(lb.collaborationRole, `cached logbook ${lb.id}`) : 'OWNER', - isDemo: lb.isDemo === 1 + isDemo: lb.isDemo === 1, + lastTravelDate, + entryCount: entries.length }) }