v3.1.1 bug fixes (#1228)

* fix(shared-view): render each leg of multi-leg flights correctly

The read-only shared view showed the overall trip start/end airports and
the first leg's flight number on every leg of a multi-leg flight. The Day
Plan already expands legs (each carries __leg), but the renderer ignored it
and read flat top-level metadata; the Bookings tab had the same bug.

- Day Plan: use __leg for per-leg airline/flight number/route, plus dep-arr time
- Bookings tab: list each leg via getFlightLegs()
- unique React keys for multi-leg rows

Closes #1219

* feat(pdf): add legs to pdf export

* fix(demo): skip first-run admin seed in demo mode

When DEMO_MODE is on, the demo seeder creates its own admin (admin@trek.app,
username "admin") right after the generic seeds run. The first-run admin
bootstrap was grabbing username "admin" first, so the demo seeder hit the
UNIQUE(username) constraint and aborted before the demo user was ever created
- which surfaced as a 500 "Demo user not found" on demo-login. Skip the
generic admin bootstrap when demo mode owns the admin account.

* fix(docker): ship the encryption-key migration script in the image

The production image only copied server/dist, so the documented rotation
command `node --import tsx scripts/migrate-encryption.ts` failed inside the
container with a module-not-found error - the raw .ts was never present. The
script runs via tsx straight from source and only pulls node builtins plus
better-sqlite3 (both prod deps), so copying the single file into
/app/server/scripts is enough to make the rotation work again.

* fix(vacay): keep the mode toolbar above the mobile bottom nav

The floating Vacation/Company toolbar was pinned at bottom-3 with z-30, so on
mobile it landed in the same band as the fixed bottom nav (z-60) and got hidden
behind it - and could scroll out of reach entirely. Pin it above the nav with
the shared --bottom-nav-h variable (0px on desktop, so nothing changes there)
and reserve matching space below the calendar grid so it never gets swallowed.

* fix(dashboard): show the correct reservation date regardless of timezone

The upcoming-reservations widget built the date with new Date(reservation_time)
.toISOString(), which reinterprets the stored naive local time as UTC and can
roll the displayed day forward in non-UTC timezones (e.g. a 23:30 reservation
showing the next day). Read the date and time straight from the stored string
parts via splitReservationDateTime, and format the time with the shared
formatTime helper so it also honours the user's 12h/24h preference.

* fix(atlas): cursor-following tooltips and removing countries from search

Two related Atlas fixes:

- Country tooltips were bound with sticky:false, which anchors them at the
  feature's bounds centre. For countries with overseas territories (e.g.
  France) that centre sits far out in the ocean, so the tooltip popped up
  nowhere near the area being hovered. Make them sticky so they track the
  cursor.

- Selecting an already-visited country from the search bar always opened the
  "Mark / Bucket" dialog, with no way to remove it. Tiny countries like
  Vatican City or Singapore are hard to hit on the map, so search was the only
  way in. Mirror the map-click behaviour: a manually-marked country opens the
  Remove confirmation, a trip/place-backed one opens its detail.

* fix(oidc): keep dots in generated usernames

The OIDC username sanitizer stripped dots because they were missing from the
allowed character class, so a name claim like "first.last" became "firstlast".
Dots are valid usernames (the profile validator already allows
^[a-zA-Z0-9_.-]+$), so add the dot to the sanitizer.

* fix(collab): show poll option labels in the UI

The poll API formatted each option as { label, voters }, but the React poll
component renders opt.text - so every option button came out blank. Emit text
alongside label (kept for any other consumer) so options render again.

* feat(backup): make the upload size limit configurable

The restore upload was capped at a hard-coded 500 MB, so instances whose
backup archive (uploads/ included) grew past that got a 413 "File too large"
with no way to raise it. Add a BACKUP_UPLOAD_LIMIT_MB env var (default 500,
invalid values warn and fall back), documented in .env.example.

* feat(costs): create an expense from a booking, fix editing total-only items

Replace the inline price + budget-category fields in the Transport and
Reservation booking modals with a "Create expense" flow: the modal saves the
booking, then opens the full Costs editor prefilled (name + category mapped from
the booking type) and linked to the reservation. A booking with a linked expense
shows it inline with edit / remove.

Also fix the Costs editor so an expense with a recorded total but no payers
(transport-derived or pre-rework items) opens with its amount, lets you set the
currency, and saves - it previously showed 0 everywhere and could not be saved.
Legacy / localized categories now map to the fixed keys, and changing a booking's
type keeps its linked expense category in sync (unless it was manually set).

- shared: reservation_id on budget create, typeToCostCategory helper, i18n keys
- server: createBudgetItem stores reservation_id; keep total_price for payerless
  items; a booking update no longer wipes its linked expense and syncs the
  category on type change
- client: shared BookingCostsSection, exported ExpenseModal with prefill and an
  editable total, page-level save-then-open wiring

* test(reservations): align syncBudgetOnUpdate unit tests with no-wipe + type-sync

The service now leaves a linked expense alone when no budget entry is on the
payload (only an explicit total_price 0 deletes it) and syncs the category on a
booking type change. Update the unit tests accordingly - the old "price cleared"
case passed entry: undefined, which is now a no-op and left a mocked return
queued that leaked into the next test.

* fix(planner): keep a reservation on its day when edited (#1237)

Editing a booking forced its day_id to the globally selected day, which is null
when editing from the Book tab - so the booking lost its day and vanished from
the Plan. Preserve the reservation own day_id on edit instead.

* fix(planner): derive a booking day from its date when none is set (#1237)

The client always sends day_id on a reservation update, so the server only
derived it from reservation_time when the field was absent. A non-transport
booking saved without a selected day (Book tab) therefore got day_id null and
vanished from the Plan, even though its date matched a day. Derive the day from
reservation_time whenever day_id is null, mirroring create.

* fix(planner): let a booking's day follow its date when edited (#1237)

Preserving the old day_id on edit left a re-dated booking on its previous start
day while end_day_id followed the new date, so it spanned both. Stop sending
day_id from the edit modal entirely - the server derives both ends from the
booking's date (and keeps the current day when there is no date), so a re-dated
booking moves cleanly to the matching day.

* fix(atlas): keep the continent breakdown in sync on mark/unmark (#1225)

The optimistic mark/unmark updates bumped the country total but never the
per-continent counts, so the continent column froze until a full reload. Move
the country to continent map into @trek/shared (single source for server and
client) and adjust the matching continent count at every optimistic site: the
country confirm flow plus the choose / region mark and region unmark handlers.

* feat(admin): let admins set a default currency for new users

Adds a currency picker to Admin > User Defaults. Stored as the default_currency
user-default, so users who have not picked their own currency inherit it in
Costs.

* fix(atlas): give every sub-national region a distinct code (#1217)

geoBoundaries fills shapeISO with the bare country code for some countries (every
Spanish region got "ESP", every Chinese "CHN", also Chile/Oman), so marking one
region lit up the whole country. build-atlas-geo.mjs now keeps shapeISO only when
it is a real "XX-..." subdivision code and otherwise synthesizes a unique
per-country id from the region name. Regenerated admin1.geojson.gz: Spain/China/
Chile/Oman now carry distinct region codes (countries with real codes, e.g.
Germany, are unchanged).

* fix(dashboard): never crash on a malformed reservation date

A reservation with an invalid date blanked the whole My Trips page: the old
Upcoming widget did new Date(value).toISOString(), which throws "Invalid time
value" (fixed in #1222 by reading the string parts). Also guard splitDate so a
bad date renders a dash instead of "Invalid Date" or throwing.

* fix(airtrail): gate airtrail update behind a user setting, on airtrail update: rebuild payload from fresh data to prevent any data loss

* fix(airtrail): add back missing tests

* fix(costs): rework the cost panel UX wise and apply prettier on the shared package

* chore(prettier) prettier this file

* fix(airtrail): don't use cabin class as seat on import

When an AirTrail flight has a cabin class but no seat number, the mapper
fell back to the class for metadata.seat, so reservations showed e.g.
"economy" as the seat. Use only the seat number; leave the seat blank
otherwise. The class is still surfaced separately in the import picker.

Closes #1246

* fix(airtrail): import scheduled flight times instead of actual

AirTrail exposes both scheduled (departureScheduled/arrivalScheduled) and
actual (departure/arrival) times. TREK read the actual times, so a delayed or
early flight imported the wrong time for planning.

Read the scheduled times on import and on poll-sync (both go through
mapFlightToReservation); when a flight has no scheduled time, leave the clock
blank (date preserved) rather than fabricating 00:00 or falling back to actual.
The change-detection hash now tracks the scheduled values, so existing linked
reservations re-sync once on the next poll. The opt-in writeback mirrors the
read, pushing TREK edits to the scheduled fields so they round-trip.

* fix(planner): hydrate per-assignment times when editing a place from the pool

Times live per day-assignment, not on the pool place, so reopening a
place from the Places panel / inspector showed empty Start/End fields
(#1247). The editor now resolves a place's lone assignment when no day
is in context and hydrates the fields from it; ambiguous (0 or 2+ days)
edits hide the fields instead of showing non-persisting inputs.

* fix(mcp): make write tools return client-valid, hydrated entities

Audit of all write tools under server/src/mcp/tools (issue #1244 anchor).

S1 (broken):
- create_budget_item / create_budget_item_with_members now default the
  split to all trip members when member_ids omitted, so the entry passes
  the client save-gate instead of being member-less (#1244).
- create_transport / update_transport backfill lat/lng/timezone for
  code-only flight endpoints (NOT NULL columns) and return a clean error
  for unresolvable endpoints instead of crashing.

S2 (under-hydration): set_budget_item_members, create_journey,
create_journey_entry, create_packing_bag, bulk_import_packing and
update_vacay_plan now return the hydrated shape the matching read/REST
route returns; bulk_import widened to accept bag/weight_grams/checked.

S3 (parity): check_in_end added to accommodation tools; atlas
mark_region_visited echoes the client shape; update_journey_entry/
update_journey_preferences, set_bag_members, set_packing_category_assignees,
apply_packing_template return hydrated payloads; set_vacay_color echoes
the color.

Auth: save_packing_template now requires admin, matching the REST gate.

Also refactors server/src/config.ts (JWT-secret handling).

Adds getBudgetItem hydrated getter, exports EndpointInput, and MCP
regression tests (incl. new tools-transports and tools-journey suites).

* fix(mcp): fix ICS/maps/accommodation bugs, add settlement & template tools

Bugs:
- export_trip_ics: include flights that store times per-endpoint
  (local_date/local_time) instead of a top-level reservation_time
- resolve_maps_url: follow redirects for cid=/share links and fall back
  to parsing the page body, all SSRF-guarded
- link_hotel_accommodation: normalize accommodation_id (TEXT column) to an
  integer in the reservation read paths so it no longer returns "14.0"

Gaps:
- packing: save_packing_template returns the new template id; add
  list_packing_templates (read) and delete_packing_template (admin)
- budget: update_budget_item accepts payers/member_ids; clarify create/
  update/members descriptions to ask which members share the expense and
  who paid
- budget: add settlement tools — get_settlement_summary, list_settlements,
  create/update/delete_settlement (budget_edit, mirrors REST + WS events)

* chore: bump nodemailer

* chore: bump multer

---------

Co-authored-by: Maurice <mauriceboe@icloud.com>
This commit is contained in:
jubnl
2026-06-18 20:13:30 +02:00
committed by GitHub
parent f6af1d67a2
commit d152f9d02b
659 changed files with 10954 additions and 12275 deletions
+43 -80
View File
@@ -2,8 +2,7 @@ import type { TranslationStrings } from '../types';
const admin: TranslationStrings = {
'admin.smtp.title': 'E-maile i powiadomienia',
'admin.smtp.hint':
'Konfiguracja SMTP dla powiadomień e-mail. Opcjonalnie: URL Webhooka dla Discorda, Slacka, itp.',
'admin.smtp.hint': 'Konfiguracja SMTP dla powiadomień e-mail. Opcjonalnie: URL Webhooka dla Discorda, Slacka, itp.',
'admin.smtp.testButton': 'Wyślij testowego e-maila',
'admin.smtp.testSuccess': 'Testowy e-mail został wysłany pomyślnie',
'admin.smtp.testFailed': 'Nie udało się wysłać testowego e-maila',
@@ -29,8 +28,7 @@ const admin: TranslationStrings = {
'admin.editUser': 'Edytuj użytkownika',
'admin.newPassword': 'Nowe hasło',
'admin.newPasswordHint': 'Pozostaw puste, aby zachować obecne hasło',
'admin.deleteUser':
'Usunąć użytkownika "{name}"? Wszystkie jego podróże zostaną trwale usunięte.',
'admin.deleteUser': 'Usunąć użytkownika "{name}"? Wszystkie jego podróże zostaną trwale usunięte.',
'admin.deleteUserTitle': 'Usuń użytkownika',
'admin.newPasswordPlaceholder': 'Podaj nowe hasło...',
'admin.toast.loadError': 'Nie udało się załadować danych administratora',
@@ -63,19 +61,16 @@ const admin: TranslationStrings = {
'admin.invite.deleteError': 'Nie udało się usunąć linku zaproszenia',
'admin.tabs.settings': 'Ustawienia',
'admin.allowRegistration': 'Zezwól na rejestrację',
'admin.allowRegistrationHint':
'Nowi użytkownicy mogą się rejestrować samodzielnie',
'admin.allowRegistrationHint': 'Nowi użytkownicy mogą się rejestrować samodzielnie',
'admin.authMethods': 'Authentication Methods',
'admin.passwordLogin': 'Password Login',
'admin.passwordLoginHint': 'Allow users to sign in with email and password',
'admin.passwordRegistration': 'Password Registration',
'admin.passwordRegistrationHint':
'Allow new users to register with email and password',
'admin.passwordRegistrationHint': 'Allow new users to register with email and password',
'admin.oidcLogin': 'SSO Login',
'admin.oidcLoginHint': 'Allow users to sign in with SSO',
'admin.oidcRegistration': 'SSO Auto-Provisioning',
'admin.oidcRegistrationHint':
'Automatically create accounts for new SSO users',
'admin.oidcRegistrationHint': 'Automatically create accounts for new SSO users',
'admin.envOverrideHint':
'Password login settings are controlled by the OIDC_ONLY environment variable and cannot be changed here.',
'admin.lockoutWarning': 'At least one login method must remain enabled',
@@ -86,14 +81,12 @@ const admin: TranslationStrings = {
'admin.apiKeysHint':
'Opcjonalne. Umożliwiają pobieranie większej ilości danych o miejscach, takich jak zdjęcia i pogoda.',
'admin.mapsKey': 'Klucz Google Maps API',
'admin.mapsKeyHint':
'Wymagany do wyszukiwania miejsc. Uzyskaj go na console.cloud.google.com',
'admin.mapsKeyHint': 'Wymagany do wyszukiwania miejsc. Uzyskaj go na console.cloud.google.com',
'admin.mapsKeyHintLong':
'Bez klucza API, OpenStreetMap jest wykorzystywany do wyszukiwania miejsc. Z kluczem API Google, zdjęcia, oceny i godziny otwarcia również mogą być pobierane. Uzyskaj go na console.cloud.google.com.',
'admin.recommended': 'Polecane',
'admin.weatherKey': 'Klucz OpenWeatherMap API',
'admin.weatherKeyHint':
'Do danych pogodowych. Uzyskaj go bezpłatnie na openweathermap.org',
'admin.weatherKeyHint': 'Do danych pogodowych. Uzyskaj go bezpłatnie na openweathermap.org',
'admin.validateKey': 'Testuj',
'admin.keyValid': 'Połączono',
'admin.keyInvalid': 'Niepoprawny',
@@ -103,15 +96,13 @@ const admin: TranslationStrings = {
'Zezwól na logowanie za pomocą zewnętrznych dostawców, takich jak Google, Apple, Authentik lub Keycloak.',
'admin.oidcDisplayName': 'Wyświetlana nazwa',
'admin.oidcIssuer': 'URL wystawcy',
'admin.oidcIssuerHint':
'Adres URL wystawcy OpenID Connect dostawcy, np. https://accounts.google.com',
'admin.oidcIssuerHint': 'Adres URL wystawcy OpenID Connect dostawcy, np. https://accounts.google.com',
'admin.oidcSaved': 'Konfiguracja OIDC została zapisana',
'admin.oidcOnlyMode': 'Wyłącz uwierzytelnianie hasłem',
'admin.oidcOnlyModeHint':
'Po włączeniu dozwolone jest tylko logowanie jednokrotne. Logowanie i rejestracja za pomocą hasła są zablokowane.',
'admin.fileTypes': 'Dozwolone typy plików',
'admin.fileTypesHint':
'Ustaw, które typy plików mogą być przesyłane przez użytkowników.',
'admin.fileTypesHint': 'Ustaw, które typy plików mogą być przesyłane przez użytkowników.',
'admin.fileTypesFormat':
'Rozszerzenia oddzielone przecinkami (np. jpg,png,pdf,doc). Użyj * aby zezwolić na wszystkie typy.',
'admin.fileTypesSaved': 'Ustawienia typów plików zostały zapisane',
@@ -125,8 +116,7 @@ const admin: TranslationStrings = {
'admin.placesDetails.subtitle':
'Pobiera szczegółowe informacje o miejscu (godziny, ocena, strona) z Google Places API. Wyłącz, aby zaoszczędzić limit API.',
'admin.bagTracking.title': 'Kontrola bagażu',
'admin.bagTracking.subtitle':
'Włącz wagę i przypisywanie do toreb dla przedmiotów do pakowania',
'admin.bagTracking.subtitle': 'Włącz wagę i przypisywanie do toreb dla przedmiotów do pakowania',
'admin.collab.chat.title': 'Czat',
'admin.collab.chat.subtitle': 'Wiadomości w czasie rzeczywistym',
'admin.collab.notes.title': 'Notatki',
@@ -145,11 +135,9 @@ const admin: TranslationStrings = {
'admin.defaultSettings.resetToBuiltIn': 'przywróć',
'admin.tabs.templates': 'Szablony pakowania',
'admin.packingTemplates.title': 'Szablony pakowania',
'admin.packingTemplates.subtitle':
'Twórz szablony list pakowania do wielokrotnego użycia dla swoich podróży',
'admin.packingTemplates.subtitle': 'Twórz szablony list pakowania do wielokrotnego użycia dla swoich podróży',
'admin.packingTemplates.create': 'Nowy szablon',
'admin.packingTemplates.namePlaceholder':
'Nazwa szablonu (np. Wakacje na plaży)',
'admin.packingTemplates.namePlaceholder': 'Nazwa szablonu (np. Wakacje na plaży)',
'admin.packingTemplates.empty': 'Nie utworzono jeszcze żadnych szablonów',
'admin.packingTemplates.items': 'przedmiotów',
'admin.packingTemplates.categories': 'kategorie',
@@ -165,34 +153,24 @@ const admin: TranslationStrings = {
'admin.packingTemplates.saveError': 'Nie udało się zapisać szablonu',
'admin.tabs.addons': 'Dodatki',
'admin.addons.title': 'Dodatki',
'admin.addons.subtitle':
'Włączaj lub wyłączaj funkcje, aby dostosować swoje doświadczenie w TREK.',
'admin.addons.subtitle': 'Włączaj lub wyłączaj funkcje, aby dostosować swoje doświadczenie w TREK.',
'admin.addons.catalog.packing.name': 'Listy',
'admin.addons.catalog.packing.description':
'Listy pakowania i zadania do wykonania dla Twoich podróży',
'admin.addons.catalog.packing.description': 'Listy pakowania i zadania do wykonania dla Twoich podróży',
'admin.addons.catalog.budget.name': 'Budżet',
'admin.addons.catalog.budget.description':
'Śledź wydatki i planuj budżet podróży',
'admin.addons.catalog.budget.description': 'Śledź wydatki i planuj budżet podróży',
'admin.addons.catalog.documents.name': 'Dokumenty',
'admin.addons.catalog.documents.description':
'Przechowuj i zarządzaj dokumentami podróżnymi',
'admin.addons.catalog.documents.description': 'Przechowuj i zarządzaj dokumentami podróżnymi',
'admin.addons.catalog.vacay.name': 'Urlopy',
'admin.addons.catalog.vacay.description':
'Osobisty planer urlopu z widokiem kalendarza',
'admin.addons.catalog.vacay.description': 'Osobisty planer urlopu z widokiem kalendarza',
'admin.addons.catalog.atlas.name': 'Atlas',
'admin.addons.catalog.atlas.description':
'Mapa świata z odwiedzonymi krajami i statystykami podróży',
'admin.addons.catalog.atlas.description': 'Mapa świata z odwiedzonymi krajami i statystykami podróży',
'admin.addons.catalog.collab.name': 'Współpraca',
'admin.addons.catalog.collab.description':
'Notatki w czasie rzeczywistym, ankiety i czat do planowania podróży',
'admin.addons.catalog.collab.description': 'Notatki w czasie rzeczywistym, ankiety i czat do planowania podróży',
'admin.addons.catalog.memories.name': 'Zdjęcia (Immich)',
'admin.addons.catalog.memories.description':
'Udostępniaj zdjęcia z podróży za pośrednictwem swojej instancji Immich',
'admin.addons.catalog.memories.description': 'Udostępniaj zdjęcia z podróży za pośrednictwem swojej instancji Immich',
'admin.addons.catalog.mcp.name': 'MCP',
'admin.addons.catalog.mcp.description':
'Model Context Protocol dla integracji asystenta AI',
'admin.addons.subtitleBefore':
'Włączaj lub wyłączaj funkcje, aby dostosować swoje doświadczenie w ',
'admin.addons.catalog.mcp.description': 'Model Context Protocol dla integracji asystenta AI',
'admin.addons.subtitleBefore': 'Włączaj lub wyłączaj funkcje, aby dostosować swoje doświadczenie w ',
'admin.addons.subtitleAfter': '.',
'admin.addons.enabled': 'Włączone',
'admin.addons.disabled': 'Wyłączone',
@@ -201,8 +179,7 @@ const admin: TranslationStrings = {
'admin.addons.type.integration': 'Integracja',
'admin.addons.tripHint': 'Dostępne jako zakładka w każdej podróży',
'admin.addons.globalHint': 'Dostępne jako osobna sekcja w menu głównym',
'admin.addons.integrationHint':
'Usługi backendowe i integracje API bez dedykowanej strony',
'admin.addons.integrationHint': 'Usługi backendowe i integracje API bez dedykowanej strony',
'admin.addons.toast.updated': 'Dodatek został zaktualizowany',
'admin.addons.toast.error': 'Nie udało się zaktualizować dodatku',
'admin.addons.noAddons': 'Brak dostępnych dodatków',
@@ -213,16 +190,14 @@ const admin: TranslationStrings = {
'admin.weather.forecast': '16-dniowa prognoza',
'admin.weather.forecastDesc': 'Wcześniej 5 dni (OpenWeatherMap)',
'admin.weather.climate': 'Historyczne dane klimatyczne',
'admin.weather.climateDesc':
'Średnie z ostatnich 85 lat dla dni poza 16-dniową prognozą',
'admin.weather.climateDesc': 'Średnie z ostatnich 85 lat dla dni poza 16-dniową prognozą',
'admin.weather.requests': '10,000 zapytań / dzień',
'admin.weather.requestsDesc': 'Bezpłatnie, bez klucza API',
'admin.weather.locationHint':
'Pogoda jest określana na podstawie pierwszego miejsca z przypisanymi współrzędnymi w danym dniu. Jeśli do dnia nie przypisano żadnego miejsca, jako punkt odniesienia używane jest dowolne miejsce z listy.',
'admin.tabs.mcpTokens': 'Dostęp MCP',
'admin.mcpTokens.title': 'Dostęp MCP',
'admin.mcpTokens.subtitle':
'Zarządzaj sesjami OAuth i tokenami API dla wszystkich użytkowników',
'admin.mcpTokens.subtitle': 'Zarządzaj sesjami OAuth i tokenami API dla wszystkich użytkowników',
'admin.mcpTokens.sectionTitle': 'Tokeny API',
'admin.mcpTokens.owner': 'Właściciel',
'admin.mcpTokens.tokenName': 'Nazwa tokenu',
@@ -243,8 +218,7 @@ const admin: TranslationStrings = {
'admin.oauthSessions.created': 'Utworzono',
'admin.oauthSessions.empty': 'Brak aktywnych sesji OAuth',
'admin.oauthSessions.revokeTitle': 'Unieważnij sesję',
'admin.oauthSessions.revokeMessage':
'Ta sesja OAuth zostanie natychmiast unieważniona. Klient straci dostęp do MCP.',
'admin.oauthSessions.revokeMessage': 'Ta sesja OAuth zostanie natychmiast unieważniona. Klient straci dostęp do MCP.',
'admin.oauthSessions.revokeSuccess': 'Sesja unieważniona',
'admin.oauthSessions.revokeError': 'Nie udało się unieważnić sesji',
'admin.oauthSessions.loadError': 'Nie udało się załadować sesji OAuth',
@@ -273,8 +247,7 @@ const admin: TranslationStrings = {
'admin.github.by': 'przez',
'admin.github.support': 'Pomóż mi rozwijać TREK',
'admin.update.available': 'Dostępna aktualizacja',
'admin.update.text':
'Dostępna jest wersja TREK {version}. Używasz {current}.',
'admin.update.text': 'Dostępna jest wersja TREK {version}. Używasz {current}.',
'admin.update.button': 'Zobacz na GitHubie',
'admin.update.install': 'Zainstaluj aktualizację',
'admin.update.confirmTitle': 'Zainstalować aktualizację?',
@@ -282,14 +255,12 @@ const admin: TranslationStrings = {
'TREK zostanie zaktualizowany z {current} do {version}. Serwer zostanie automatycznie zrestartowany po zakończeniu.',
'admin.update.dataInfo':
'Wszystkie twoje dane (podróże, użytkownicy, klucze API, przesłane pliki, urlopy, Atlas, budżety) zostaną zachowane.',
'admin.update.warning':
'Aplikacja będzie niedostępna przez krótki czas podczas restartu.',
'admin.update.warning': 'Aplikacja będzie niedostępna przez krótki czas podczas restartu.',
'admin.update.confirm': 'Zaktualizuj',
'admin.update.installing': 'Aktualizowanie...',
'admin.update.success': 'Aktualizacja zakończona! Serwer restartuje się...',
'admin.update.failed': 'Aktualizacja nie powiodła się',
'admin.update.backupHint':
'Zalecamy utworzenie kopii zapasowej przed aktualizacją.',
'admin.update.backupHint': 'Zalecamy utworzenie kopii zapasowej przed aktualizacją.',
'admin.update.backupLink': 'Zrób kopię zapasową',
'admin.update.howTo': 'Jak zaktualizować',
'admin.update.dockerText':
@@ -314,10 +285,8 @@ const admin: TranslationStrings = {
'admin.notifications.adminWebhookPanel.hint':
'Ten webhook służy wyłącznie do powiadomień admina (np. alertów o nowych wersjach). Jest niezależny od webhooków użytkowników i wysyła automatycznie, gdy URL jest skonfigurowany.',
'admin.notifications.adminWebhookPanel.saved': 'URL webhooka admina zapisany',
'admin.notifications.adminWebhookPanel.testSuccess':
'Testowy webhook wysłany pomyślnie',
'admin.notifications.adminWebhookPanel.testFailed':
'Wysyłanie testowego webhooka nie powiodło się',
'admin.notifications.adminWebhookPanel.testSuccess': 'Testowy webhook wysłany pomyślnie',
'admin.notifications.adminWebhookPanel.testFailed': 'Wysyłanie testowego webhooka nie powiodło się',
'admin.notifications.adminWebhookPanel.alwaysOnHint':
'Webhook admina wysyła automatycznie, gdy URL jest skonfigurowany',
'admin.notifications.ntfy': 'Ntfy',
@@ -325,8 +294,7 @@ const admin: TranslationStrings = {
'Pozwala użytkownikom skonfigurować własne tematy ntfy dla powiadomień push. Ustaw domyślny serwer poniżej, aby wstępnie wypełnić ustawienia użytkownika.',
'admin.notifications.testNtfy': 'Wyślij testowe Ntfy',
'admin.notifications.testNtfySuccess': 'Testowe Ntfy wysłane pomyślnie',
'admin.notifications.testNtfyFailed':
'Wysyłanie testowego Ntfy nie powiodło się',
'admin.notifications.testNtfyFailed': 'Wysyłanie testowego Ntfy nie powiodło się',
'admin.notifications.adminNtfyPanel.title': 'Admin Ntfy',
'admin.notifications.adminNtfyPanel.hint':
'Ten temat Ntfy jest używany wyłącznie do powiadomień admina (np. alertów o wersjach). Jest niezależny od tematów użytkowników i zawsze wysyła po skonfigurowaniu.',
@@ -337,25 +305,19 @@ const admin: TranslationStrings = {
'admin.notifications.adminNtfyPanel.topicLabel': 'Temat admina',
'admin.notifications.adminNtfyPanel.topicPlaceholder': 'trek-admin-alerts',
'admin.notifications.adminNtfyPanel.tokenLabel': 'Token dostępu (opcjonalne)',
'admin.notifications.adminNtfyPanel.tokenCleared':
'Token dostępu admina wyczyszczony',
'admin.notifications.adminNtfyPanel.tokenCleared': 'Token dostępu admina wyczyszczony',
'admin.notifications.adminNtfyPanel.saved': 'Ustawienia admin Ntfy zapisane',
'admin.notifications.adminNtfyPanel.test': 'Wyślij testowe Ntfy',
'admin.notifications.adminNtfyPanel.testSuccess':
'Testowe Ntfy wysłane pomyślnie',
'admin.notifications.adminNtfyPanel.testFailed':
'Wysyłanie testowego Ntfy nie powiodło się',
'admin.notifications.adminNtfyPanel.alwaysOnHint':
'Admin Ntfy zawsze wysyła po skonfigurowaniu tematu',
'admin.notifications.adminNtfyPanel.testSuccess': 'Testowe Ntfy wysłane pomyślnie',
'admin.notifications.adminNtfyPanel.testFailed': 'Wysyłanie testowego Ntfy nie powiodło się',
'admin.notifications.adminNtfyPanel.alwaysOnHint': 'Admin Ntfy zawsze wysyła po skonfigurowaniu tematu',
'admin.notifications.adminNotificationsHint':
'Skonfiguruj, które kanały dostarczają powiadomienia admina (np. alerty o wersjach). Webhook wysyła automatycznie, gdy ustawiony jest URL webhooka admina.',
'admin.notifications.tripReminders.title': 'Przypomnienia o podróżach',
'admin.notifications.tripReminders.hint':
'Wysyła powiadomienie z przypomnieniem przed rozpoczęciem podróży (wymaga ustawienia dni przypomnienia dla podróży).',
'admin.notifications.tripReminders.enabled':
'Przypomnienia o podróżach włączone',
'admin.notifications.tripReminders.disabled':
'Przypomnienia o podróżach wyłączone',
'admin.notifications.tripReminders.enabled': 'Przypomnienia o podróżach włączone',
'admin.notifications.tripReminders.disabled': 'Przypomnienia o podróżach wyłączone',
'admin.webhook.hint':
'Pozwól użytkownikom konfigurować własne adresy URL webhooka dla powiadomień (Discord, Slack itp.).',
'admin.tabs.permissions': 'Uprawnienia',
@@ -363,8 +325,7 @@ const admin: TranslationStrings = {
'admin.addons.catalog.journey.description':
'Śledzenie podróży i dziennik z zameldowaniami, zdjęciami i codziennymi historiami',
'admin.passkey.title': 'Logowanie kluczem dostępu',
'admin.passkey.cardHint':
'Pozwól użytkownikom logować się kluczami dostępu (WebAuthn). Domyślnie wyłączone.',
'admin.passkey.cardHint': 'Pozwól użytkownikom logować się kluczami dostępu (WebAuthn). Domyślnie wyłączone.',
'admin.passkey.login': 'Włącz logowanie kluczem dostępu',
'admin.passkey.loginHint':
'Pokaż opcję „Zaloguj się kluczem dostępu” i pozwól użytkownikom rejestrować klucze dostępu w swoich ustawieniach.',
@@ -382,11 +343,13 @@ const admin: TranslationStrings = {
'admin.passkey.resetConfirm': 'Usunąć wszystkie klucze dostępu dla {name}?',
'admin.passkey.resetDone': 'Usunięto {count} kluczy dostępu',
'admin.defaultSettings.mapProvider': 'Silnik map',
'admin.defaultSettings.mapProviderHint': 'Domyślna mapa dla wszystkich na tej instancji. Każdy użytkownik może ją zmienić we własnych ustawieniach.',
'admin.defaultSettings.mapProviderHint':
'Domyślna mapa dla wszystkich na tej instancji. Każdy użytkownik może ją zmienić we własnych ustawieniach.',
'admin.defaultSettings.providerLeaflet': 'Standardowa (bezpłatna)',
'admin.defaultSettings.providerMapbox': 'Mapbox (3D)',
'admin.defaultSettings.mapboxToken': 'Współdzielony token Mapbox',
'admin.defaultSettings.mapboxTokenHint': 'Używany dla każdego użytkownika, który nie wprowadził własnego tokena — dzięki temu cała instancja korzysta z Mapbox bez udostępniania klucza każdemu z osobna. Przechowywany w postaci zaszyfrowanej.',
'admin.defaultSettings.mapboxTokenHint':
'Używany dla każdego użytkownika, który nie wprowadził własnego tokena — dzięki temu cała instancja korzysta z Mapbox bez udostępniania klucza każdemu z osobna. Przechowywany w postaci zaszyfrowanej.',
'admin.defaultSettings.mapboxStyle': 'Styl mapy',
'admin.defaultSettings.mapboxStylePlaceholder': 'Wybierz styl…',
'admin.defaultSettings.mapbox3d': 'Budynki i teren 3D',
+1 -2
View File
@@ -29,8 +29,7 @@ const atlas: TranslationStrings = {
'atlas.visitedCountries': 'Odwiedzone kraje',
'atlas.cities': 'Miasta',
'atlas.noData': 'Brak danych o podróżach',
'atlas.noDataHint':
'Utwórz podróż i dodaj miejsca, aby zobaczyć swoją mapę świata',
'atlas.noDataHint': 'Utwórz podróż i dodaj miejsca, aby zobaczyć swoją mapę świata',
'atlas.lastTrip': 'Ostatnia podróż',
'atlas.nextTrip': 'Następna podróż',
'atlas.daysLeft': 'dni do wyjazdu',
+7 -14
View File
@@ -20,29 +20,24 @@ const backup: TranslationStrings = {
'backup.toast.loadError': 'Nie udało się załadować kopii zapasowych',
'backup.toast.created': 'Kopia zapasowa została utworzona pomyślnie',
'backup.toast.createError': 'Nie udało się utworzyć kopii zapasowej',
'backup.toast.restored':
'Kopia zapasowa została przywrócona. Strona zostanie przeładowana...',
'backup.toast.restored': 'Kopia zapasowa została przywrócona. Strona zostanie przeładowana...',
'backup.toast.restoreError': 'Nie udało się przywrócić kopii zapasowej',
'backup.toast.uploadError': 'Nie udało się przesłać kopii zapasowej',
'backup.toast.deleted': 'Kopia zapasowa została usunięta',
'backup.toast.deleteError': 'Nie udało się usunąć kopii zapasowej',
'backup.toast.downloadError': 'Nie udało się pobrać kopii zapasowej',
'backup.toast.settingsSaved':
'Ustawienia automatycznej kopii zapasowej zostały zapisane',
'backup.toast.settingsSaved': 'Ustawienia automatycznej kopii zapasowej zostały zapisane',
'backup.toast.settingsError': 'Nie udało się zapisać ustawień',
'backup.auto.title': 'Automatyczna kopia zapasowa',
'backup.auto.subtitle':
'Tworzenie automatycznej kopii zapasowej według harmonogramu',
'backup.auto.subtitle': 'Tworzenie automatycznej kopii zapasowej według harmonogramu',
'backup.auto.enable': 'Włącz automatyczną kopię zapasową',
'backup.auto.enableHint':
'Kopie zapasowe będą tworzone automatycznie zgodnie z wybranym harmonogramem',
'backup.auto.enableHint': 'Kopie zapasowe będą tworzone automatycznie zgodnie z wybranym harmonogramem',
'backup.auto.interval': 'Częstotliwość',
'backup.auto.hour': 'Uruchom o godzinie',
'backup.auto.hourHint': 'Czas lokalny serwera ({format} format)',
'backup.auto.dayOfWeek': 'Dzień tygodnia',
'backup.auto.dayOfMonth': 'Dzień miesiąca',
'backup.auto.dayOfMonthHint':
'Ograniczone do 128 dla kompatybilności ze wszystkimi miesiącami',
'backup.auto.dayOfMonthHint': 'Ograniczone do 128 dla kompatybilności ze wszystkimi miesiącami',
'backup.auto.scheduleSummary': 'Harmonogram',
'backup.auto.summaryDaily': 'Każdego dnia o {hour}:00',
'backup.auto.summaryWeekly': 'Co {day} o {hour}:00',
@@ -51,8 +46,7 @@ const backup: TranslationStrings = {
'backup.auto.envLockedHint':
'Automatyczne kopie zapasowe są konfigurowane za pomocą zmiennych środowiskowych Dockera. Aby zmienić te ustawienia, zaktualizuj plik docker-compose.yml i uruchom ponownie kontener.',
'backup.auto.copyEnv': 'Kopiuj zmienne środowiskowe Dockera',
'backup.auto.envCopied':
'Zmienne środowiskowe Dockera zostały skopiowane do schowka',
'backup.auto.envCopied': 'Zmienne środowiskowe Dockera zostały skopiowane do schowka',
'backup.auto.keepLabel': 'Usuń stare kopie zapasowe po',
'backup.dow.sunday': 'Nd',
'backup.dow.monday': 'Pon',
@@ -74,8 +68,7 @@ const backup: TranslationStrings = {
'backup.restoreConfirmTitle': 'Przywrócić kopię zapasową?',
'backup.restoreWarning':
'Wszystkie obecne dane (podróże, miejsca, użytkownicy, przesłane pliki) zostaną trwale zastąpione danymi z kopii zapasowej. Tej operacji nie można cofnąć.',
'backup.restoreTip':
'Wskazówka: Przed przywróceniem utwórz kopię zapasową bieżącej instancji.',
'backup.restoreTip': 'Wskazówka: Przed przywróceniem utwórz kopię zapasową bieżącej instancji.',
'backup.restoreConfirm': 'Tak, przywróć',
};
export default backup;
+80 -74
View File
@@ -24,8 +24,7 @@ const budget: TranslationStrings = {
'budget.byCategory': 'Według kategorii',
'budget.editTooltip': 'Kliknij, aby edytować',
'budget.linkedToReservation': 'Powiązano z rezerwacją — edytuj nazwę tam',
'budget.confirm.deleteCategory':
'Czy na pewno chcesz usunąć kategorię "{name}" z {count} wpisami?',
'budget.confirm.deleteCategory': 'Czy na pewno chcesz usunąć kategorię "{name}" z {count} wpisami?',
'budget.deleteCategory': 'Usuń kategorię',
'budget.perPerson': 'Za osobę',
'budget.paid': 'Zapłacone',
@@ -38,78 +37,85 @@ const budget: TranslationStrings = {
'budget.exportCsv': 'Eksportuj CSV',
'budget.table.date': 'Data',
'budget.categoriesLabel': 'kategorie',
"costs.you": "Ty",
"costs.youShort": "T",
"costs.youLower": "ty",
"costs.youOwe": "Jesteś winien",
"costs.youOweSub": "Powinieneś zapłacić innym",
"costs.youreOwed": "Należy ci się",
"costs.youreOwedSub": "Inni powinni zapłacić tobie",
"costs.totalSpend": "Łączne wydatki na podróż",
"costs.totalSpendSub": "Wszystkich podróżnych",
"costs.to": "Do",
"costs.from": "Od",
"costs.allSettled": "Wszystko rozliczone",
"costs.nothingOwed": "Nikt nie jest ci nic winien",
"costs.yourShare": "Twój udział",
"costs.youPaid": "Zapłaciłeś",
"costs.expenses": "Wydatki",
"costs.entries": "Wpisów: {count}",
"costs.searchPlaceholder": "Szukaj wydatków…",
"costs.filter.all": "Wszystkie",
"costs.filter.mine": "Opłacone przeze mnie",
"costs.filter.owed": "Należy mi się",
"costs.addExpense": "Dodaj wydatek",
"costs.editExpense": "Edytuj wydatek",
"costs.noMatch": "Brak wydatków pasujących do wyszukiwania.",
"costs.emptyText": "Brak wydatków. Dodaj pierwszy.",
"costs.spent": "wydano {amount}",
"costs.noDate": "Brak daty",
"costs.noOnePaid": "Nikt jeszcze nie zapłacił",
"costs.youLent": "pożyczyłeś {amount}",
"costs.youBorrowed": "pożyczyłeś od innych {amount}",
"costs.settleUp": "Rozlicz",
"costs.history": "Historia",
"costs.everyoneSquare": "Wszyscy rozliczeni",
"costs.nothingOutstanding": "Brak nierozliczonych płatności.",
"costs.pay": "zapłać",
"costs.pays": "płaci",
"costs.settle": "Rozlicz",
"costs.balances": "Salda",
"costs.byCategory": "Według kategorii",
"costs.noCategories": "Brak wydatków.",
"costs.settleHistory": "Historia rozliczeń",
"costs.noSettlements": "Brak rozliczonych płatności.",
"costs.paymentsSettled": "Rozliczonych płatności: {count}",
"costs.paid": "zapłacono",
"costs.undo": "Cofnij",
"costs.whatFor": "Na co to było?",
"costs.namePlaceholder": "np. kolacja, pamiątki, paliwo…",
"costs.totalAmount": "Łączna kwota",
"costs.currency": "Waluta",
"costs.day": "Dzień",
"costs.rateLabel": "1 {from} w {to}",
"costs.category": "Kategoria",
"costs.whoPaid": "Kto zapłacił?",
"costs.splitBetween": "Podziel równo między",
"costs.pickSomeone": "Wybierz co najmniej jedną osobę do podziału.",
"costs.splitSummary": "Podział na {count} · {amount} na osobę",
"costs.cat.accommodation": "Nocleg",
"costs.cat.food": "Jedzenie i napoje",
"costs.cat.groceries": "Zakupy spożywcze",
"costs.cat.transport": "Transport",
"costs.cat.flights": "Loty",
"costs.cat.activities": "Atrakcje",
"costs.cat.sightseeing": "Zwiedzanie",
"costs.cat.shopping": "Zakupy",
"costs.cat.fees": "Opłaty i bilety",
"costs.cat.health": "Zdrowie",
"costs.cat.tips": "Napiwki",
"costs.cat.other": "Inne",
"costs.daysCount": "Dni: {count}",
"costs.travelers": "Podróżnych: {count}",
"costs.liveRate": "kurs na żywo",
"costs.settleAll": "Rozlicz wszystko",
'costs.you': 'Ty',
'costs.youShort': 'T',
'costs.youLower': 'ty',
'costs.youOwe': 'Jesteś winien',
'costs.youOweSub': 'Powinieneś zapłacić innym',
'costs.youreOwed': 'Należy ci się',
'costs.youreOwedSub': 'Inni powinni zapłacić tobie',
'costs.totalSpend': 'Łączne wydatki na podróż',
'costs.totalSpendSub': 'Wszystkich podróżnych',
'costs.to': 'Do',
'costs.from': 'Od',
'costs.allSettled': 'Wszystko rozliczone',
'costs.nothingOwed': 'Nikt nie jest ci nic winien',
'costs.yourShare': 'Twój udział',
'costs.youPaid': 'Zapłaciłeś',
'costs.expenses': 'Wydatki',
'costs.entries': 'Wpisów: {count}',
'costs.searchPlaceholder': 'Szukaj wydatków…',
'costs.filter.all': 'Wszystkie',
'costs.filter.mine': 'Opłacone przeze mnie',
'costs.filter.owed': 'Należy mi się',
'costs.addExpense': 'Dodaj wydatek',
'costs.editExpense': 'Edytuj wydatek',
'costs.noMatch': 'Brak wydatków pasujących do wyszukiwania.',
'costs.emptyText': 'Brak wydatków. Dodaj pierwszy.',
'costs.spent': 'wydano {amount}',
'costs.noDate': 'Brak daty',
'costs.noOnePaid': 'Nikt jeszcze nie zapłacił',
'costs.youLent': 'pożyczyłeś {amount}',
'costs.youBorrowed': 'pożyczyłeś od innych {amount}',
'costs.settleUp': 'Rozlicz',
'costs.history': 'Historia',
'costs.everyoneSquare': 'Wszyscy rozliczeni',
'costs.nothingOutstanding': 'Brak nierozliczonych płatności.',
'costs.pay': 'zapłać',
'costs.pays': 'płaci',
'costs.settle': 'Rozlicz',
'costs.balances': 'Salda',
'costs.byCategory': 'Według kategorii',
'costs.noCategories': 'Brak wydatków.',
'costs.settleHistory': 'Historia rozliczeń',
'costs.noSettlements': 'Brak rozliczonych płatności.',
'costs.paymentsSettled': 'Rozliczonych płatności: {count}',
'costs.paid': 'zapłacono',
'costs.undo': 'Cofnij',
'costs.whatFor': 'Na co to było?',
'costs.namePlaceholder': 'np. kolacja, pamiątki, paliwo…',
'costs.totalAmount': 'Łączna kwota',
'costs.currency': 'Waluta',
'costs.day': 'Dzień',
'costs.rateLabel': '1 {from} w {to}',
'costs.category': 'Kategoria',
'costs.whoPaid': 'Kto zapłacił?',
'costs.splitBetween': 'Podziel równo między',
'costs.pickSomeone': 'Wybierz co najmniej jedną osobę do podziału.',
'costs.splitSummary': 'Podział na {count} · {amount} na osobę',
'costs.cat.accommodation': 'Nocleg',
'costs.cat.food': 'Jedzenie i napoje',
'costs.cat.groceries': 'Zakupy spożywcze',
'costs.cat.transport': 'Transport',
'costs.cat.flights': 'Loty',
'costs.cat.activities': 'Atrakcje',
'costs.cat.sightseeing': 'Zwiedzanie',
'costs.cat.shopping': 'Zakupy',
'costs.cat.fees': 'Opłaty i bilety',
'costs.cat.health': 'Zdrowie',
'costs.cat.tips': 'Napiwki',
'costs.cat.other': 'Inne',
'costs.daysCount': 'Dni: {count}',
'costs.travelers': 'Podróżnych: {count}',
'costs.liveRate': 'kurs na żywo',
'costs.settleAll': 'Rozlicz wszystko',
'costs.payment': 'Płatność',
'costs.editPayment': 'Edytuj płatność',
'costs.addPayment': 'Dodaj płatność',
'costs.unfinished': 'Niezakończone',
'costs.unfinishedHint': 'Tylko w sumie — jeszcze nierozliczone',
'costs.tapToInclude': 'Dotknij, aby dodać',
'costs.amount': 'Kwota',
};
export default budget;
+1 -2
View File
@@ -13,8 +13,7 @@ const categories: TranslationStrings = {
'categories.defaultName': 'Kategoria',
'categories.update': 'Aktualizuj',
'categories.create': 'Utwórz',
'categories.confirm.delete':
'Usunąć kategorię? Miejsca w tej kategorii nie zostaną usunięte.',
'categories.confirm.delete': 'Usunąć kategorię? Miejsca w tej kategorii nie zostaną usunięte.',
'categories.toast.loadError': 'Nie udało się załadować kategorii',
'categories.toast.nameRequired': 'Proszę podać nazwę',
'categories.toast.updated': 'Kategoria została zaktualizowana',
+2 -4
View File
@@ -13,10 +13,8 @@ const collab: TranslationStrings = {
'collab.chat.send': 'Wyślij',
'collab.chat.placeholder': 'Napisz wiadomość...',
'collab.chat.empty': 'Rozpocznij konwersację',
'collab.chat.emptyHint':
'Wiadomości są widoczne dla wszystkich uczestników podróży',
'collab.chat.emptyDesc':
'Dziel się pomysłami, planami i aktualizacjami z uczestnikami podróży',
'collab.chat.emptyHint': 'Wiadomości są widoczne dla wszystkich uczestników podróży',
'collab.chat.emptyDesc': 'Dziel się pomysłami, planami i aktualizacjami z uczestnikami podróży',
'collab.chat.today': 'Dzisiaj',
'collab.chat.yesterday': 'Wczoraj',
'collab.chat.deletedMessage': 'usunięto wiadomość',
+3 -6
View File
@@ -20,8 +20,7 @@ const dashboard: TranslationStrings = {
'dashboard.timezoneCustomTzPlaceholder': 'np. Europe/Warsaw',
'dashboard.timezoneCustomAdd': 'Dodaj',
'dashboard.timezoneCustomErrorEmpty': 'Podaj identyfikator strefy czasowej',
'dashboard.timezoneCustomErrorInvalid':
'Nieprawidłowa strefa czasowa. Użyj formatu takiego jak Europe/Warsaw',
'dashboard.timezoneCustomErrorInvalid': 'Nieprawidłowa strefa czasowa. Użyj formatu takiego jak Europe/Warsaw',
'dashboard.timezoneCustomErrorDuplicate': 'Już dodana',
'dashboard.emptyTitle': 'Brak podróży',
'dashboard.emptyText': 'Utwórz swoją pierwszą podróż i zacznij planować!',
@@ -50,8 +49,7 @@ const dashboard: TranslationStrings = {
'dashboard.toast.archiveError': 'Nie udało się zarchiwizować podróży',
'dashboard.toast.restored': 'Podróż została przywrócona',
'dashboard.toast.restoreError': 'Nie udało się przywrócić podróży',
'dashboard.confirm.delete':
'Usunąć podróż "{title}"? Wszystkie miejsca i plany zostaną trwale usunięte.',
'dashboard.confirm.delete': 'Usunąć podróż "{title}"? Wszystkie miejsca i plany zostaną trwale usunięte.',
'dashboard.editTrip': 'Edytuj podróż',
'dashboard.createTrip': 'Utwórz nową podróż',
'dashboard.tripTitle': 'Nazwa podróży',
@@ -61,8 +59,7 @@ const dashboard: TranslationStrings = {
'dashboard.startDate': 'Data rozpoczęcia',
'dashboard.endDate': 'Data zakończenia',
'dashboard.dayCount': 'Liczba dni',
'dashboard.dayCountHint':
'Ile dni zaplanować, gdy nie ustawiono dat podróży.',
'dashboard.dayCountHint': 'Ile dni zaplanować, gdy nie ustawiono dat podróży.',
'dashboard.noDateHint':
'Nie ustawiono daty — zostanie utworzonych 7 domyślnych dni. Możesz to zmienić w dowolnym momencie.',
'dashboard.coverImage': 'Okładka',
+1 -2
View File
@@ -7,8 +7,7 @@ const day: TranslationStrings = {
'day.sunrise': 'Wschód słońca',
'day.sunset': 'Zachód słońca',
'day.hourlyForecast': 'Prognoza godzinowa',
'day.climateHint':
'Historyczne średnie — rzeczywista prognoza dostępna na następne 16 dni od tej daty.',
'day.climateHint': 'Historyczne średnie — rzeczywista prognoza dostępna na następne 16 dni od tej daty.',
'day.noWeather': 'Brak danych pogodowych. Dodaj miejsce ze współrzędnymi.',
'day.overview': 'Przegląd dnia',
'day.accommodation': 'Zakwaterowanie',
+5 -10
View File
@@ -3,16 +3,14 @@ import type { TranslationStrings } from '../types';
const dayplan: TranslationStrings = {
'dayplan.icsTooltip': 'Eksportuj kalendarz (ICS)',
'dayplan.emptyDay': 'Brak miejsc zaplanowanych na ten dzień',
'dayplan.cannotReorderTransport':
'Nie można zmieniać kolejności dla rezerwacji z określoną godziną',
'dayplan.cannotReorderTransport': 'Nie można zmieniać kolejności dla rezerwacji z określoną godziną',
'dayplan.confirmRemoveTimeTitle': 'Usunąć godzinę?',
'dayplan.confirmRemoveTimeBody':
'To miejsce ma określoną godzinę ({time}). Przeniesienie go usunie godzinę i umożliwi swobodne sortowanie.',
'dayplan.confirmRemoveTimeAction': 'Usuń godzinę i przenieś',
'dayplan.confirmDeleteNoteTitle': 'Usunąć notatkę?',
'dayplan.confirmDeleteNoteBody': 'Ta notatka zostanie trwale usunięta.',
'dayplan.cannotDropOnTimed':
'Nie można umieszczać elementów pomiędzy wpisami z określoną godziną',
'dayplan.cannotDropOnTimed': 'Nie można umieszczać elementów pomiędzy wpisami z określoną godziną',
'dayplan.cannotBreakChronology':
'Spowodowałoby to naruszenie chronologicznej kolejności elementów i rezerwacji z określoną godziną',
'dayplan.addNote': 'Dodaj notatkę',
@@ -29,13 +27,10 @@ const dayplan: TranslationStrings = {
'dayplan.optimize': 'Optymalizuj',
'dayplan.optimized': 'Trasa została zoptymalizowana',
'dayplan.routeError': 'Nie udało się obliczyć trasy',
'dayplan.toast.needTwoPlaces':
'Potrzeba co najmniej dwóch miejsc, aby zoptymalizować trasę',
'dayplan.toast.needTwoPlaces': 'Potrzeba co najmniej dwóch miejsc, aby zoptymalizować trasę',
'dayplan.toast.routeOptimized': 'Trasa została zoptymalizowana',
'dayplan.toast.routeOptimizedFromHotel':
'Trasa została zoptymalizowana względem Twojego zakwaterowania',
'dayplan.toast.noGeoPlaces':
'Nie znaleziono miejsc ze współrzędnymi do obliczenia trasy',
'dayplan.toast.routeOptimizedFromHotel': 'Trasa została zoptymalizowana względem Twojego zakwaterowania',
'dayplan.toast.noGeoPlaces': 'Nie znaleziono miejsc ze współrzędnymi do obliczenia trasy',
'dayplan.confirmed': 'Potwierdzono',
'dayplan.pendingRes': 'Oczekujące',
'dayplan.pdf': 'PDF',
+2 -4
View File
@@ -2,8 +2,7 @@ import type { NotificationLocale } from '../externalNotifications/types';
const pl: NotificationLocale = {
email: {
footer:
'Otrzymałeś/aś tę wiadomość, ponieważ masz włączone powiadomienia w TREK.',
footer: 'Otrzymałeś/aś tę wiadomość, ponieważ masz włączone powiadomienia w TREK.',
manage: 'Zarządzaj preferencjami w ustawieniach',
madeWith: 'Made with',
openTrek: 'Otwórz TREK',
@@ -56,8 +55,7 @@ const pl: NotificationLocale = {
body: 'Otrzymaliśmy prośbę o zresetowanie hasła do Twojego konta TREK. Kliknij przycisk poniżej, aby ustawić nowe hasło.',
ctaIntro: 'Zresetuj hasło',
expiry: 'Link wygaśnie za 60 minut.',
ignore:
'Jeśli to nie Ty, zignoruj tę wiadomość — Twoje hasło pozostanie bez zmian.',
ignore: 'Jeśli to nie Ty, zignoruj tę wiadomość — Twoje hasło pozostanie bez zmian.',
},
};
+2 -4
View File
@@ -13,8 +13,7 @@ const files: TranslationStrings = {
'files.uploadError': 'Przesyłanie nie powiodło się',
'files.dropzone': 'Przeciągnij pliki tutaj',
'files.dropzoneHint': 'lub kliknij, aby przeglądać',
'files.allowedTypes':
'Obrazki, PDF, DOC, DOCX, XLS, XLSX, TXT, CSV · Maks 50 MB',
'files.allowedTypes': 'Obrazki, PDF, DOC, DOCX, XLS, XLSX, TXT, CSV · Maks 50 MB',
'files.uploading': 'Przesyłanie...',
'files.filterAll': 'Wszystkie',
'files.filterPdf': 'PDF',
@@ -52,8 +51,7 @@ const files: TranslationStrings = {
'files.toast.assigned': 'Plik został przypisany',
'files.toast.assignError': 'Nie udało się przypisać',
'files.toast.restoreError': 'Nie udało się przywrócić',
'files.confirm.permanentDelete':
'Czy na pewno chcesz trwale usunąć ten plik? Tej operacji nie można cofnąć.',
'files.confirm.permanentDelete': 'Czy na pewno chcesz trwale usunąć ten plik? Tej operacji nie można cofnąć.',
'files.confirm.emptyTrash':
'Czy na pewno chcesz trwale usunąć wszystkie pliki z kosza? Tej operacji nie można cofnąć.',
'files.noteLabel': 'Notatka',
+13 -26
View File
@@ -14,14 +14,12 @@ const journey: TranslationStrings = {
'journey.createError': 'Nie udało się utworzyć dziennika podróży',
'journey.deleteError': 'Nie udało się usunąć dziennika podróży',
'journey.deleteConfirmTitle': 'Usuń',
'journey.deleteConfirmMessage':
'Usunąć „{title}"? Tej operacji nie można cofnąć.',
'journey.deleteConfirmMessage': 'Usunąć „{title}"? Tej operacji nie można cofnąć.',
'journey.deleteConfirmGeneric': 'Czy na pewno chcesz to usunąć?',
'journey.notFound': 'Nie znaleziono dziennika podróży',
'journey.photos': 'Zdjęcia',
'journey.timelineEmpty': 'Brak przystanków',
'journey.timelineEmptyHint':
'Dodaj zameldowanie lub napisz wpis w dzienniku, aby rozpocząć',
'journey.timelineEmptyHint': 'Dodaj zameldowanie lub napisz wpis w dzienniku, aby rozpocząć',
'journey.status.draft': 'Szkic',
'journey.status.active': 'Aktywny',
'journey.status.completed': 'Zakończony',
@@ -47,30 +45,25 @@ const journey: TranslationStrings = {
'journey.editor.titlePlaceholder': 'Nadaj temu momentowi nazwę...',
'journey.editor.bodyPlaceholder': 'Opowiedz historię tego dnia...',
'journey.editor.placePlaceholder': 'Lokalizacja (opcjonalnie)',
'journey.editor.tagsPlaceholder':
'Tagi: ukryty skarb, najlepszy posiłek, warto wrócić...',
'journey.editor.tagsPlaceholder': 'Tagi: ukryty skarb, najlepszy posiłek, warto wrócić...',
'journey.visibility.private': 'Prywatny',
'journey.visibility.shared': 'Udostępniony',
'journey.visibility.public': 'Publiczny',
'journey.emptyState.title': 'Twoja historia zaczyna się tutaj',
'journey.emptyState.subtitle':
'Zamelduj się w miejscu lub napisz swój pierwszy wpis w dzienniku',
'journey.frontpage.subtitle':
'Zamień swoje podróże w historie, których nigdy nie zapomnisz',
'journey.emptyState.subtitle': 'Zamelduj się w miejscu lub napisz swój pierwszy wpis w dzienniku',
'journey.frontpage.subtitle': 'Zamień swoje podróże w historie, których nigdy nie zapomnisz',
'journey.frontpage.createJourney': 'Utwórz dziennik podróży',
'journey.frontpage.activeJourney': 'Aktywny dziennik podróży',
'journey.frontpage.allJourneys': 'Wszystkie dzienniki podróży',
'journey.frontpage.journeys': 'dzienniki podróży',
'journey.frontpage.createNew': 'Utwórz nowy dziennik podróży',
'journey.frontpage.createNewSub':
'Wybierz podróże, pisz historie, dziel się przygodami',
'journey.frontpage.createNewSub': 'Wybierz podróże, pisz historie, dziel się przygodami',
'journey.frontpage.live': 'Na żywo',
'journey.frontpage.synced': 'Zsynchronizowany',
'journey.frontpage.continueWriting': 'Kontynuuj pisanie',
'journey.frontpage.updated': 'Zaktualizowano {time}',
'journey.frontpage.suggestionLabel': 'Podróż właśnie się zakończyła',
'journey.frontpage.suggestionText':
'Zamień <strong>{title}</strong> w dziennik podróży',
'journey.frontpage.suggestionText': 'Zamień <strong>{title}</strong> w dziennik podróży',
'journey.frontpage.dismiss': 'Odrzuć',
'journey.frontpage.journeyName': 'Nazwa dziennika podróży',
'journey.frontpage.namePlaceholder': 'np. Azja Południowo-Wschodnia 2026',
@@ -85,11 +78,9 @@ const journey: TranslationStrings = {
'journey.detail.newEntry': 'Nowy wpis',
'journey.detail.editEntry': 'Edytuj wpis',
'journey.detail.noEntries': 'Brak wpisów',
'journey.detail.noEntriesHint':
'Dodaj podróż, aby rozpocząć ze szkieletowymi wpisami',
'journey.detail.noEntriesHint': 'Dodaj podróż, aby rozpocząć ze szkieletowymi wpisami',
'journey.detail.noPhotos': 'Brak zdjęć',
'journey.detail.noPhotosHint':
'Prześlij zdjęcia do wpisów lub przeglądaj bibliotekę Immich/Synology',
'journey.detail.noPhotosHint': 'Prześlij zdjęcia do wpisów lub przeglądaj bibliotekę Immich/Synology',
'journey.detail.journeyStats': 'Statystyki podróży',
'journey.detail.syncedTrips': 'Zsynchronizowane podróże',
'journey.detail.noTripsLinked': 'Brak powiązanych podróży',
@@ -115,8 +106,7 @@ const journey: TranslationStrings = {
'journey.editor.uploadPhotos': 'Prześlij zdjęcia',
'journey.editor.uploading': 'Przesyłanie...',
'journey.editor.uploadingProgress': 'Przesyłanie {done}/{total}…',
'journey.editor.uploadPartialFailed':
'{failed} z {total} zdjęć nie powiodło się — zapisz ponownie, aby spróbować',
'journey.editor.uploadPartialFailed': '{failed} z {total} zdjęć nie powiodło się — zapisz ponownie, aby spróbować',
'journey.editor.fromGallery': 'Z galerii',
'journey.editor.allPhotosAdded': 'Wszystkie zdjęcia już dodane',
'journey.editor.writeStory': 'Napisz swoją historię...',
@@ -195,12 +185,10 @@ const journey: TranslationStrings = {
'journey.settings.reopenJourney': 'Przywróć podróż',
'journey.settings.archived': 'Podróż zarchiwizowana',
'journey.settings.reopened': 'Podróż wznowiona',
'journey.settings.endDescription':
'Ukrywa odznakę Na żywo. Możesz wznowić w dowolnym momencie.',
'journey.settings.endDescription': 'Ukrywa odznakę Na żywo. Możesz wznowić w dowolnym momencie.',
'journey.settings.delete': 'Usuń',
'journey.settings.deleteJourney': 'Usuń dziennik podróży',
'journey.settings.deleteMessage':
'Usunąć „{title}"? Wszystkie wpisy i zdjęcia zostaną utracone.',
'journey.settings.deleteMessage': 'Usunąć „{title}"? Wszystkie wpisy i zdjęcia zostaną utracone.',
'journey.settings.saved': 'Ustawienia zapisane',
'journey.settings.saveFailed': 'Zapisywanie nie powiodło się',
'journey.settings.coverUpdated': 'Okładka zaktualizowana',
@@ -211,8 +199,7 @@ const journey: TranslationStrings = {
'journey.photosUploadFailed': 'Nie udało się przesłać niektórych zdjęć',
'journey.photosAdded': '{count} zdjęć dodanych',
'journey.public.notFound': 'Nie znaleziono',
'journey.public.notFoundMessage':
'Ten dziennik podróży nie istnieje lub link wygasł.',
'journey.public.notFoundMessage': 'Ten dziennik podróży nie istnieje lub link wygasł.',
'journey.public.readOnly': 'Tylko do odczytu · Publiczny dziennik podróży',
'journey.public.tagline': 'Travel Resource & Exploration Kit',
'journey.public.sharedVia': 'Udostępnione przez',
+13 -26
View File
@@ -10,8 +10,7 @@ const login: TranslationStrings = {
'login.features.realtime': 'Synchronizacja w czasie rzeczywistym',
'login.features.realtimeDesc': 'Planuj wspólnie przez WebSocket',
'login.features.budget': 'Śledzenie budżetu',
'login.features.budgetDesc':
'Kategorie, wykresy i koszty w przeliczeniu na osobę',
'login.features.budgetDesc': 'Kategorie, wykresy i koszty w przeliczeniu na osobę',
'login.features.collab': 'Współpraca',
'login.features.collabDesc': 'Wielu użytkowników i wspólne podróże',
'login.features.packing': 'Listy pakowania',
@@ -21,17 +20,14 @@ const login: TranslationStrings = {
'login.features.files': 'Dokumenty',
'login.features.filesDesc': 'Przesyłaj i zarządzaj dokumentami',
'login.features.routes': 'Inteligentne trasy',
'login.features.routesDesc':
'Automatyczna optymalizacja i eksport do Google Maps',
'login.selfHosted':
'Własny hosting · Otwarty kod źródłowy · Twoje dane pozostają Twoje',
'login.features.routesDesc': 'Automatyczna optymalizacja i eksport do Google Maps',
'login.selfHosted': 'Własny hosting · Otwarty kod źródłowy · Twoje dane pozostają Twoje',
'login.title': 'Zaloguj się',
'login.subtitle': 'Witaj ponownie',
'login.signingIn': 'Logowanie...',
'login.signIn': 'Zaloguj się',
'login.createAdmin': 'Utwórz konto administratora',
'login.createAdminHint':
'Skonfiguruj pierwsze konto administratora dla TREK.',
'login.createAdminHint': 'Skonfiguruj pierwsze konto administratora dla TREK.',
'login.createAccount': 'Utwórz konto',
'login.createAccountHint': 'Zarejestruj nowe konto.',
'login.creating': 'Tworzenie...',
@@ -40,24 +36,20 @@ const login: TranslationStrings = {
'login.register': 'Zarejestruj się',
'login.emailPlaceholder': 'twoj@email.pl',
'login.username': 'Nazwa użytkownika',
'login.oidc.registrationDisabled':
'Rejestracja jest wyłączona. Skontaktuj się z administratorem.',
'login.oidc.registrationDisabled': 'Rejestracja jest wyłączona. Skontaktuj się z administratorem.',
'login.oidc.noEmail': 'Nie otrzymano e-maila od dostawcy.',
'login.oidc.tokenFailed': 'Nie udało się uwierzytelnić.',
'login.oidc.invalidState': 'Nieprawidłowa sesja. Spróbuj ponownie.',
'login.demoFailed': 'Nie udało się zalogować do wersji demonstracyjnej',
'login.oidcSignIn': 'Zaloguj się z {name}',
'login.oidcOnly':
'Uwierzytelnianie hasłem jest wyłączone. Zaloguj się za pomocą swojego dostawcy SSO.',
'login.oidcLoggedOut':
'Zostałeś wylogowany. Zaloguj się ponownie za pomocą swojego dostawcy SSO.',
'login.oidcOnly': 'Uwierzytelnianie hasłem jest wyłączone. Zaloguj się za pomocą swojego dostawcy SSO.',
'login.oidcLoggedOut': 'Zostałeś wylogowany. Zaloguj się ponownie za pomocą swojego dostawcy SSO.',
'login.demoHint': 'Wypróbuj demo — nie wymaga rejestracji',
'login.mfaTitle': 'Uwierzytelnianie dwuskładnikowe',
'login.mfaSubtitle': 'Wprowadź 6-cyfrowy kod z aplikacji uwierzytelniającej.',
'login.mfaCodeLabel': 'Kod weryfikacyjny',
'login.mfaCodeRequired': 'Wprowadź kod z aplikacji uwierzytelniającej.',
'login.mfaHint':
'Otwórz Google Authenticator, Authy lub inną aplikację TOTP.',
'login.mfaHint': 'Otwórz Google Authenticator, Authy lub inną aplikację TOTP.',
'login.mfaBack': '← Powrót do logowania',
'login.mfaVerify': 'Weryfikuj',
'login.invalidInviteLink': 'Nieprawidłowy lub wygasły link zaproszenia',
@@ -71,8 +63,7 @@ const login: TranslationStrings = {
'Wpisz adres e-mail użyty przy rejestracji. Jeśli konto istnieje, wyślemy link do resetu.',
'login.forgotPasswordSubmit': 'Wyślij link',
'login.forgotPasswordSentTitle': 'Sprawdź swoją pocztę',
'login.forgotPasswordSentBody':
'Jeśli istnieje konto dla tego adresu, link jest już w drodze. Wygaśnie za 60 minut.',
'login.forgotPasswordSentBody': 'Jeśli istnieje konto dla tego adresu, link jest już w drodze. Wygaśnie za 60 minut.',
'login.forgotPasswordSmtpHintOff':
'Uwaga: administrator nie skonfigurował SMTP, więc link resetujący zostanie zapisany w konsoli serwera zamiast wysłania e-mailem.',
'login.backToLogin': 'Wróć do logowania',
@@ -81,22 +72,18 @@ const login: TranslationStrings = {
'login.passwordsDontMatch': 'Hasła nie są zgodne',
'login.mfaCode': 'Kod 2FA',
'login.resetPasswordTitle': 'Ustaw nowe hasło',
'login.resetPasswordBody':
'Wybierz silne hasło, którego tu jeszcze nie używałeś. Minimum 8 znaków.',
'login.resetPasswordMfaBody':
'Wpisz kod 2FA lub kod zapasowy, aby zakończyć reset.',
'login.resetPasswordBody': 'Wybierz silne hasło, którego tu jeszcze nie używałeś. Minimum 8 znaków.',
'login.resetPasswordMfaBody': 'Wpisz kod 2FA lub kod zapasowy, aby zakończyć reset.',
'login.resetPasswordSubmit': 'Zresetuj hasło',
'login.resetPasswordVerify': 'Zweryfikuj i zresetuj',
'login.resetPasswordSuccessTitle': 'Hasło zaktualizowane',
'login.resetPasswordSuccessBody': 'Możesz się teraz zalogować nowym hasłem.',
'login.resetPasswordInvalidLink': 'Nieprawidłowy link',
'login.resetPasswordInvalidLinkBody':
'Brakuje linku lub jest uszkodzony. Poproś o nowy, aby kontynuować.',
'login.resetPasswordInvalidLinkBody': 'Brakuje linku lub jest uszkodzony. Poproś o nowy, aby kontynuować.',
'login.resetPasswordFailed': 'Reset nie powiódł się. Link mógł wygasnąć.',
'login.setNewPassword': 'Ustaw nowe hasło',
'login.setNewPasswordHint': 'Musisz zmienić hasło.',
'login.passkey.signIn': 'Zaloguj się kluczem dostępu',
'login.passkey.failed':
'Logowanie kluczem dostępu nie powiodło się. Spróbuj ponownie.',
'login.passkey.failed': 'Logowanie kluczem dostępu nie powiodło się. Spróbuj ponownie.',
};
export default login;
+5 -10
View File
@@ -9,8 +9,7 @@ const memories: TranslationStrings = {
'Połącz jednego z tych dostawców zdjęć: {provider_names} w Ustawieniach, aby móc dodawać zdjęcia do tej podróży.',
'memories.noDates': 'Dodaj daty do swojej podróży, aby załadować zdjęcia.',
'memories.noPhotos': 'Nie znaleziono zdjęć',
'memories.noPhotosHint':
'Nie znaleziono zdjęć w Immich dla tego zakresu dat podróży.',
'memories.noPhotosHint': 'Nie znaleziono zdjęć w Immich dla tego zakresu dat podróży.',
'memories.photosFound': 'zdjęć',
'memories.fromOthers': 'od innych',
'memories.sharePhotos': 'Udostępnij zdjęcia',
@@ -24,10 +23,8 @@ const memories: TranslationStrings = {
'memories.providerPassword': 'Hasło',
'memories.providerOTP': 'Kod MFA (jeśli włączony)',
'memories.skipSSLVerification': 'Pomiń weryfikację certyfikatu SSL',
'memories.immichAutoUpload':
'Przy przesyłaniu kopiuj zdjęcia journey także do Immich',
'memories.providerUrlHintSynology':
'Uwzględnij ścieżkę aplikacji Photos w URL, np. https://nas:5001/photo',
'memories.immichAutoUpload': 'Przy przesyłaniu kopiuj zdjęcia journey także do Immich',
'memories.providerUrlHintSynology': 'Uwzględnij ścieżkę aplikacji Photos w URL, np. https://nas:5001/photo',
'memories.testConnection': 'Test',
'memories.testShort': 'Test',
'memories.connected': 'Połączono',
@@ -72,10 +69,8 @@ const memories: TranslationStrings = {
'memories.error.addPhotos': 'Nie udało się dodać zdjęć',
'memories.error.removePhoto': 'Nie udało się usunąć zdjęcia',
'memories.error.toggleSharing': 'Nie udało się zaktualizować udostępniania',
'memories.saveRouteNotConfigured':
'Trasa zapisu nie jest skonfigurowana dla tego dostawcy',
'memories.testRouteNotConfigured':
'Trasa testowa nie jest skonfigurowana dla tego dostawcy',
'memories.saveRouteNotConfigured': 'Trasa zapisu nie jest skonfigurowana dla tego dostawcy',
'memories.testRouteNotConfigured': 'Trasa testowa nie jest skonfigurowana dla tego dostawcy',
'memories.fillRequiredFields': 'Proszę wypełnić wszystkie wymagane pola',
};
export default memories;
+3 -6
View File
@@ -14,11 +14,9 @@ const notif: TranslationStrings = {
'notif.todo_due.title': 'Zadanie z terminem',
'notif.todo_due.text': '{todo} w {trip} — termin {due}',
'notif.vacay_invite.title': 'Zaproszenie Vacay Fusion',
'notif.vacay_invite.text':
'{actor} zaprosił Cię do połączenia planów urlopowych',
'notif.vacay_invite.text': '{actor} zaprosił Cię do połączenia planów urlopowych',
'notif.photos_shared.title': 'Zdjęcia udostępnione',
'notif.photos_shared.text':
'{actor} udostępnił {count} zdjęcie/zdjęcia w {trip}',
'notif.photos_shared.text': '{actor} udostępnił {count} zdjęcie/zdjęcia w {trip}',
'notif.collab_message.title': 'Nowa wiadomość',
'notif.collab_message.text': '{actor} wysłał wiadomość w {trip}',
'notif.packing_tagged.title': 'Zadanie pakowania',
@@ -37,7 +35,6 @@ const notif: TranslationStrings = {
'notif.generic.title': 'Powiadomienie',
'notif.generic.text': 'Masz nowe powiadomienie',
'notif.dev.unknown_event.title': '[DEV] Nieznane zdarzenie',
'notif.dev.unknown_event.text':
'Typ zdarzenia "{event}" nie jest zarejestrowany w EVENT_NOTIFICATION_CONFIG',
'notif.dev.unknown_event.text': 'Typ zdarzenia "{event}" nie jest zarejestrowany w EVENT_NOTIFICATION_CONFIG',
};
export default notif;
+31 -62
View File
@@ -15,83 +15,57 @@ const oauth: TranslationStrings = {
'oauth.scope.group.weather': 'Pogoda',
'oauth.scope.group.journey': 'Dziennik podróży',
'oauth.scope.trips:read.label': 'Przeglądaj podróże i itineraria',
'oauth.scope.trips:read.description':
'Odczytuj podróże, dni, notatki i członków',
'oauth.scope.trips:read.description': 'Odczytuj podróże, dni, notatki i członków',
'oauth.scope.trips:write.label': 'Edytuj podróże i itineraria',
'oauth.scope.trips:write.description':
'Twórz i aktualizuj podróże, dni, notatki oraz zarządzaj członkami',
'oauth.scope.trips:write.description': 'Twórz i aktualizuj podróże, dni, notatki oraz zarządzaj członkami',
'oauth.scope.trips:delete.label': 'Usuń podróże',
'oauth.scope.trips:delete.description':
'Trwale usuń całe podróże — ta akcja jest nieodwracalna',
'oauth.scope.trips:delete.description': 'Trwale usuń całe podróże — ta akcja jest nieodwracalna',
'oauth.scope.trips:share.label': 'Zarządzaj linkami udostępniania',
'oauth.scope.trips:share.description':
'Twórz, aktualizuj i unieważniaj publiczne linki udostępniania',
'oauth.scope.trips:share.description': 'Twórz, aktualizuj i unieważniaj publiczne linki udostępniania',
'oauth.scope.places:read.label': 'Przeglądaj miejsca i dane mapy',
'oauth.scope.places:read.description':
'Odczytuj miejsca, przypisania dni, tagi i kategorie',
'oauth.scope.places:read.description': 'Odczytuj miejsca, przypisania dni, tagi i kategorie',
'oauth.scope.places:write.label': 'Zarządzaj miejscami',
'oauth.scope.places:write.description':
'Twórz, aktualizuj i usuń miejsca, przypisania i tagi',
'oauth.scope.places:write.description': 'Twórz, aktualizuj i usuń miejsca, przypisania i tagi',
'oauth.scope.atlas:read.label': 'Przeglądaj Atlas',
'oauth.scope.atlas:read.description':
'Odczytuj odwiedzone kraje, regiony i listę marzeń',
'oauth.scope.atlas:read.description': 'Odczytuj odwiedzone kraje, regiony i listę marzeń',
'oauth.scope.atlas:write.label': 'Zarządzaj Atlasem',
'oauth.scope.atlas:write.description':
'Oznaczaj kraje i regiony jako odwiedzone, zarządzaj listą marzeń',
'oauth.scope.atlas:write.description': 'Oznaczaj kraje i regiony jako odwiedzone, zarządzaj listą marzeń',
'oauth.scope.packing:read.label': 'Przeglądaj listy pakowania',
'oauth.scope.packing:read.description':
'Odczytuj przedmioty, torby i przypisania kategorii',
'oauth.scope.packing:read.description': 'Odczytuj przedmioty, torby i przypisania kategorii',
'oauth.scope.packing:write.label': 'Zarządzaj listami pakowania',
'oauth.scope.packing:write.description':
'Dodawaj, aktualizuj, usuwaj, zaznaczaj i porządkuj przedmioty i torby',
'oauth.scope.packing:write.description': 'Dodawaj, aktualizuj, usuwaj, zaznaczaj i porządkuj przedmioty i torby',
'oauth.scope.todos:read.label': 'Przeglądaj listy zadań',
'oauth.scope.todos:read.description':
'Odczytuj zadania podróży i przypisania kategorii',
'oauth.scope.todos:read.description': 'Odczytuj zadania podróży i przypisania kategorii',
'oauth.scope.todos:write.label': 'Zarządzaj listami zadań',
'oauth.scope.todos:write.description':
'Twórz, aktualizuj, zaznaczaj, usuwaj i porządkuj zadania',
'oauth.scope.todos:write.description': 'Twórz, aktualizuj, zaznaczaj, usuwaj i porządkuj zadania',
'oauth.scope.budget:read.label': 'Przeglądaj budżet',
'oauth.scope.budget:read.description':
'Odczytuj pozycje budżetu i zestawienie wydatków',
'oauth.scope.budget:read.description': 'Odczytuj pozycje budżetu i zestawienie wydatków',
'oauth.scope.budget:write.label': 'Zarządzaj budżetem',
'oauth.scope.budget:write.description':
'Twórz, aktualizuj i usuń pozycje budżetu',
'oauth.scope.budget:write.description': 'Twórz, aktualizuj i usuń pozycje budżetu',
'oauth.scope.reservations:read.label': 'Przeglądaj rezerwacje',
'oauth.scope.reservations:read.description':
'Odczytuj rezerwacje i szczegóły zakwaterowania',
'oauth.scope.reservations:read.description': 'Odczytuj rezerwacje i szczegóły zakwaterowania',
'oauth.scope.reservations:write.label': 'Zarządzaj rezerwacjami',
'oauth.scope.reservations:write.description':
'Twórz, aktualizuj, usuwaj i porządkuj rezerwacje',
'oauth.scope.reservations:write.description': 'Twórz, aktualizuj, usuwaj i porządkuj rezerwacje',
'oauth.scope.collab:read.label': 'Przeglądaj współpracę',
'oauth.scope.collab:read.description':
'Odczytuj notatki, ankiety i wiadomości',
'oauth.scope.collab:read.description': 'Odczytuj notatki, ankiety i wiadomości',
'oauth.scope.collab:write.label': 'Zarządzaj współpracą',
'oauth.scope.collab:write.description':
'Twórz, aktualizuj i usuń notatki, ankiety i wiadomości',
'oauth.scope.collab:write.description': 'Twórz, aktualizuj i usuń notatki, ankiety i wiadomości',
'oauth.scope.notifications:read.label': 'Przeglądaj powiadomienia',
'oauth.scope.notifications:read.description':
'Odczytuj powiadomienia i liczby nieprzeczytanych',
'oauth.scope.notifications:read.description': 'Odczytuj powiadomienia i liczby nieprzeczytanych',
'oauth.scope.notifications:write.label': 'Zarządzaj powiadomieniami',
'oauth.scope.notifications:write.description':
'Oznaczaj powiadomienia jako przeczytane i odpowiadaj na nie',
'oauth.scope.notifications:write.description': 'Oznaczaj powiadomienia jako przeczytane i odpowiadaj na nie',
'oauth.scope.vacay:read.label': 'Przeglądaj plany urlopowe',
'oauth.scope.vacay:read.description':
'Odczytuj dane planowania urlopu, wpisy i statystyki',
'oauth.scope.vacay:read.description': 'Odczytuj dane planowania urlopu, wpisy i statystyki',
'oauth.scope.vacay:write.label': 'Zarządzaj planami urlopowymi',
'oauth.scope.vacay:write.description':
'Twórz i zarządzaj wpisami urlopowymi, świętami i planami zespołu',
'oauth.scope.vacay:write.description': 'Twórz i zarządzaj wpisami urlopowymi, świętami i planami zespołu',
'oauth.scope.geo:read.label': 'Mapy i geokodowanie',
'oauth.scope.geo:read.description':
'Wyszukuj miejsca, rozwiązuj adresy URL map i odwrotnie geokoduj współrzędne',
'oauth.scope.geo:read.description': 'Wyszukuj miejsca, rozwiązuj adresy URL map i odwrotnie geokoduj współrzędne',
'oauth.scope.weather:read.label': 'Prognozy pogody',
'oauth.scope.weather:read.description':
'Pobieraj prognozy pogody dla miejsc i dat podróży',
'oauth.scope.weather:read.description': 'Pobieraj prognozy pogody dla miejsc i dat podróży',
'oauth.scope.journey:read.label': 'Przeglądaj dzienniki podróży',
'oauth.scope.journey:read.description':
'Odczytuj dzienniki podróży, wpisy i listę współautorów',
'oauth.scope.journey:read.description': 'Odczytuj dzienniki podróży, wpisy i listę współautorów',
'oauth.scope.journey:write.label': 'Zarządzaj dziennikami podróży',
'oauth.scope.journey:write.description':
'Twórz, aktualizuj i usuwaj dzienniki podróży oraz ich wpisy',
'oauth.scope.journey:write.description': 'Twórz, aktualizuj i usuwaj dzienniki podróży oraz ich wpisy',
'oauth.scope.journey:share.label': 'Zarządzaj linkami dzienników podróży',
'oauth.scope.journey:share.description':
'Twórz, aktualizuj i unieważniaj publiczne linki udostępniania dzienników podróży',
@@ -99,14 +73,11 @@ const oauth: TranslationStrings = {
'oauth.authorize.loading': 'Loading…', // en-fallback
'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback
'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback
'oauth.authorize.loginDescription':
'{client} wants access to your TREK account. Please sign in first.', // en-fallback
'oauth.authorize.loginDescription': '{client} wants access to your TREK account. Please sign in first.', // en-fallback
'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback
'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback
'oauth.authorize.requestDescription':
'This application is requesting access to your TREK account.', // en-fallback
'oauth.authorize.trustNote':
'Only grant access to applications you trust. Your data stays on your server.', // en-fallback
'oauth.authorize.requestDescription': 'This application is requesting access to your TREK account.', // en-fallback
'oauth.authorize.trustNote': 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback
'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback
'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback
'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback
@@ -115,9 +86,7 @@ const oauth: TranslationStrings = {
'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback
'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback
'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback
'oauth.authorize.alwaysTool.listTrips':
'List your trips so the AI can discover trip IDs', // en-fallback
'oauth.authorize.alwaysTool.getTripSummary':
'Read a trip overview needed to use any other tool', // en-fallback
'oauth.authorize.alwaysTool.listTrips': 'List your trips so the AI can discover trip IDs', // en-fallback
'oauth.authorize.alwaysTool.getTripSummary': 'Read a trip overview needed to use any other tool', // en-fallback
};
export default oauth;
+2 -4
View File
@@ -51,10 +51,8 @@ const packing: TranslationStrings = {
'packing.bagName': 'Nazwa torby...',
'packing.addBag': 'Dodaj torbę',
'packing.changeCategory': 'Zmień kategorię',
'packing.confirm.clearChecked':
'Czy na pewno chcesz usunąć {count} spakowanych przedmiotów?',
'packing.confirm.deleteCat':
'Czy na pewno chcesz usunąć kategorię "{name}" z {count} przedmiotami?',
'packing.confirm.clearChecked': 'Czy na pewno chcesz usunąć {count} spakowanych przedmiotów?',
'packing.confirm.deleteCat': 'Czy na pewno chcesz usunąć kategorię "{name}" z {count} przedmiotami?',
'packing.defaultCategory': 'Inne',
'packing.toast.saveError': 'Nie udało się zapisać',
'packing.toast.deleteError': 'Nie udało się usunąć',
+7 -14
View File
@@ -6,13 +6,10 @@ const places: TranslationStrings = {
'places.sidebarDrop': 'Upuść, aby zaimportować',
'places.importFileHint':
'Importuj pliki .gpx, .kml lub .kmz z narzędzi takich jak Google My Maps, Google Earth lub tracker GPS.',
'places.importFileDropHere':
'Kliknij, aby wybrać plik lub przeciągnij i upuść tutaj',
'places.importFileDropHere': 'Kliknij, aby wybrać plik lub przeciągnij i upuść tutaj',
'places.importFileDropActive': 'Upuść plik, aby go wybrać',
'places.importFileUnsupported':
'Nieobsługiwany typ pliku. Użyj .gpx, .kml lub .kmz.',
'places.importFileTooLarge':
'Plik jest za duży. Maksymalny rozmiar przesyłania to {maxMb} MB.',
'places.importFileUnsupported': 'Nieobsługiwany typ pliku. Użyj .gpx, .kml lub .kmz.',
'places.importFileTooLarge': 'Plik jest za duży. Maksymalny rozmiar przesyłania to {maxMb} MB.',
'places.importFileError': 'Import nie powiódł się',
'places.importAllSkipped': 'Wszystkie miejsca były już w podróży.',
'places.gpxImported': '{count} miejsc zaimportowanych z GPX',
@@ -29,8 +26,7 @@ const places: TranslationStrings = {
'places.deleteSelected': 'Usuń wybrane',
'places.kmlKmzImported': 'Zaimportowano {count} miejsc z KMZ/KML',
'places.urlResolved': 'Miejsce zaimportowane z URL',
'places.kmlKmzSummaryValues':
'Placemarks: {total} • Zaimportowano: {created} • Pominięto: {skipped}',
'places.kmlKmzSummaryValues': 'Placemarks: {total} • Zaimportowano: {created} • Pominięto: {skipped}',
'places.importGoogleList': 'Lista Google',
'places.assignToDay': 'Do którego dnia dodać?',
'places.all': 'Wszystkie',
@@ -59,15 +55,13 @@ const places: TranslationStrings = {
'places.formTime': 'Godzina',
'places.startTime': 'Początek',
'places.endTime': 'Koniec',
'places.endTimeBeforeStart':
'Godzina zakończenia jest przed godziną rozpoczęcia',
'places.endTimeBeforeStart': 'Godzina zakończenia jest przed godziną rozpoczęcia',
'places.timeCollision': 'Nakładanie się godzin z:',
'places.formWebsite': 'Strona internetowa',
'places.formNotes': 'Notatki',
'places.formNotesPlaceholder': 'Osobiste notatki...',
'places.formReservation': 'Rezerwacja',
'places.reservationNotesPlaceholder':
'Notatki z rezerwacji, numer potwierdzenia...',
'places.reservationNotesPlaceholder': 'Notatki z rezerwacji, numer potwierdzenia...',
'places.mapsSearchPlaceholder': 'Szukaj miejsc...',
'places.mapsSearchError': 'Nie udało się wyszukać miejsca.',
'places.loadingDetails': 'Ładowanie szczegółów miejsca…',
@@ -85,8 +79,7 @@ const places: TranslationStrings = {
'places.googleListHint': 'Wklej link do listy Google Maps.',
'places.googleListImported': 'Zaimportowano {count} miejsc',
'places.googleListError': 'Nie udało się zaimportować listy',
'places.naverListHint':
'Wklej link do udostępnionej listy Naver Maps, aby zaimportować wszystkie miejsca.',
'places.naverListHint': 'Wklej link do udostępnionej listy Naver Maps, aby zaimportować wszystkie miejsca.',
'places.naverListImported': 'Zaimportowano {count} miejsc z "{list}"',
'places.naverListError': 'Nie udało się zaimportować listy Naver Maps',
'places.viewDetails': 'Zobacz szczegóły',
+3 -6
View File
@@ -7,8 +7,7 @@ const planner: TranslationStrings = {
'planner.documents': 'Dokumenty',
'planner.dayPlan': 'Plan',
'planner.reservations': 'Rezerwacje',
'planner.minTwoPlaces':
'Wymagane są przynajmniej dwa miejsca ze współrzędnymi',
'planner.minTwoPlaces': 'Wymagane są przynajmniej dwa miejsca ze współrzędnymi',
'planner.noGeoPlaces': 'Brak miejsc ze współrzędnymi',
'planner.routeCalculated': 'Trasa została obliczona',
'planner.routeCalcFailed': 'Nie udało się obliczyć trasy',
@@ -34,8 +33,7 @@ const planner: TranslationStrings = {
'planner.resConfirmed': 'Rezerwacja potwierdzona · ',
'planner.notePlaceholder': 'Notatka…',
'planner.noteTimePlaceholder': 'Godzina (opcjonalnie)',
'planner.noteExamplePlaceholder':
'np. S3 o 14:30 z dworca centralnego, prom z molo 7, przerwa na lunch…',
'planner.noteExamplePlaceholder': 'np. S3 o 14:30 z dworca centralnego, prom z molo 7, przerwa na lunch…',
'planner.totalCost': 'Całkowity koszt',
'planner.searchPlaces': 'Szukaj miejsc…',
'planner.allCategories': 'Wszystkie kategorie',
@@ -49,8 +47,7 @@ const planner: TranslationStrings = {
'planner.route': 'Trasa',
'planner.optimize': 'Optymalizuj',
'planner.openGoogleMaps': 'Otwórz w Google Maps',
'planner.selectDayHint':
'Wybierz dzień z listy po lewej, aby zobaczyć jego plan',
'planner.selectDayHint': 'Wybierz dzień z listy po lewej, aby zobaczyć jego plan',
'planner.noPlacesForDay': 'Brak miejsc dla tego dnia',
'planner.addPlacesLink': 'Dodaj miejsca →',
'planner.minTotal': 'min. łącznie',
+1 -2
View File
@@ -5,8 +5,7 @@ const register: TranslationStrings = {
'register.passwordTooShort': 'Hasło musi mieć co najmniej 6 znaków',
'register.failed': 'Rejestracja nie powiodła się',
'register.getStarted': 'Rozpocznij',
'register.subtitle':
'Utwórz konto i zacznij planować swoje wymarzone podróże.',
'register.subtitle': 'Utwórz konto i zacznij planować swoje wymarzone podróże.',
'register.feature1': 'Nieograniczone plany podróży',
'register.feature2': 'Interaktywna mapa',
'register.feature3': 'Zarządzaj miejscami i kategoriami',
+12 -11
View File
@@ -52,8 +52,7 @@ const reservations: TranslationStrings = {
'reservations.type.train': 'Pociąg',
'reservations.type.car': 'Samochód',
'reservations.needsReview': 'Sprawdź',
'reservations.needsReviewHint':
'Nie udało się automatycznie dopasować lotniska — potwierdź lokalizację.',
'reservations.needsReviewHint': 'Nie udało się automatycznie dopasować lotniska — potwierdź lokalizację.',
'reservations.searchLocation': 'Szukaj stacji, portu, adresu...',
'reservations.type.cruise': 'Rejs',
'reservations.type.event': 'Wydarzenie',
@@ -64,11 +63,9 @@ const reservations: TranslationStrings = {
'reservations.type.bicycle': 'Rower',
'reservations.type.taxi': 'Taksówka',
'reservations.type.transport_other': 'Inne',
'reservations.confirm.delete':
'Czy na pewno chcesz usunąć rezerwację "{name}"?',
'reservations.confirm.delete': 'Czy na pewno chcesz usunąć rezerwację "{name}"?',
'reservations.confirm.deleteTitle': 'Usunąć rezerwację?',
'reservations.confirm.deleteBody':
'Rezerwacja "{name}" zostanie trwale usunięta.',
'reservations.confirm.deleteBody': 'Rezerwacja "{name}" zostanie trwale usunięta.',
'reservations.toast.updated': 'Rezerwacja została zaktualizowana',
'reservations.toast.removed': 'Rezerwacja została usunięta',
'reservations.toast.fileUploaded': 'Plik został przesłany',
@@ -100,8 +97,7 @@ const reservations: TranslationStrings = {
'reservations.budgetCategory': 'Kategoria budżetu',
'reservations.budgetCategoryPlaceholder': 'np. Transport, Zakwaterowanie',
'reservations.budgetCategoryAuto': 'Auto (na podstawie typu rezerwacji)',
'reservations.budgetHint':
'Wpis budżetowy zostanie automatycznie utworzony podczas zapisywania.',
'reservations.budgetHint': 'Wpis budżetowy zostanie automatycznie utworzony podczas zapisywania.',
'reservations.departureDate': 'Wylot',
'reservations.arrivalDate': 'Przylot',
'reservations.departureTime': 'Godz. wylotu',
@@ -122,8 +118,7 @@ const reservations: TranslationStrings = {
'reservations.span.start': 'Start',
'reservations.span.end': 'Koniec',
'reservations.span.ongoing': 'W trakcie',
'reservations.validation.endBeforeStart':
'Data/godzina zakończenia musi być późniejsza niż data/godzina rozpoczęcia',
'reservations.validation.endBeforeStart': 'Data/godzina zakończenia musi być późniejsza niż data/godzina rozpoczęcia',
'reservations.addBooking': 'Dodaj rezerwację',
'reservations.import.title': 'Importuj potwierdzenia rezerwacji',
'reservations.import.cta': 'Importuj z pliku',
@@ -138,7 +133,8 @@ const reservations: TranslationStrings = {
'reservations.import.back': 'Wstecz',
'reservations.import.success': 'Zaimportowano {count} rezerwację/rezerwacje',
'reservations.import.partialFailure': '{created} zaimportowano, {failed} nieudane',
'reservations.import.error': 'Przetwarzanie nieudane. Upewnij się, że plik jest prawidłowym potwierdzeniem rezerwacji.',
'reservations.import.error':
'Przetwarzanie nieudane. Upewnij się, że plik jest prawidłowym potwierdzeniem rezerwacji.',
'reservations.import.unavailable': 'Import rezerwacji nie jest dostępny na tym serwerze.',
'reservations.import.unsupportedFormat': 'Nieobsługiwany format pliku. Użyj EML, PDF, PKPass, HTML lub TXT.',
'reservations.import.fileTooLarge': 'Plik „{name}" przekracza limit 10 MB.',
@@ -159,5 +155,10 @@ const reservations: TranslationStrings = {
'reservations.airtrail.otherFlights': 'Inne loty',
'reservations.airtrail.empty': 'Nie znaleziono lotów na Twoim koncie AirTrail.',
'reservations.airtrail.importCta': 'Importuj {count}',
'reservations.costsLabel': 'Costs',
'reservations.createExpense': 'Create expense',
'reservations.createExpenseHint': 'Saves the booking, then opens the Costs editor.',
'reservations.linkedExpense': 'Linked expense',
'reservations.removeExpense': 'Remove expense',
};
export default reservations;
+36 -55
View File
@@ -14,12 +14,10 @@ const settings: TranslationStrings = {
'settings.mapTemplate': 'Szablon mapy',
'settings.mapTemplatePlaceholder.select': 'Wybierz szablon...',
'settings.mapDefaultHint': 'Pozostaw puste dla OpenStreetMap (domyślnie)',
'settings.mapTemplatePlaceholder':
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
'settings.mapTemplatePlaceholder': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
'settings.mapHint': 'Szablon URL dla kafelków mapy',
'settings.mapProvider': 'Dostawca mapy',
'settings.mapProviderHint':
'Dotyczy map Trip Planner i Journey. Atlas zawsze używa Leaflet.',
'settings.mapProviderHint': 'Dotyczy map Trip Planner i Journey. Atlas zawsze używa Leaflet.',
'settings.mapLeafletSubtitle': 'Klasyczne 2D, dowolne kafelki rastrowe',
'settings.mapMapboxSubtitle': 'Kafelki wektorowe, budynki 3D i teren',
'settings.mapExperimental': 'Eksperymentalne',
@@ -30,13 +28,11 @@ const settings: TranslationStrings = {
'settings.mapStylePlaceholder': 'Wybierz styl Mapbox',
'settings.mapStyleHint': 'Preset lub własny URL mapbox://styles/USER/ID',
'settings.map3dBuildings': 'Budynki 3D i teren',
'settings.map3dHint':
'Nachylenie + prawdziwe wytłaczanie budynków 3D — działa w każdym stylu, także satelitarnym.',
'settings.map3dHint': 'Nachylenie + prawdziwe wytłaczanie budynków 3D — działa w każdym stylu, także satelitarnym.',
'settings.mapHighQuality': 'Tryb wysokiej jakości',
'settings.mapHighQualityHint':
'Antialiasing + projekcja globusa dla ostrzejszych krawędzi i realistycznego widoku świata.',
'settings.mapHighQualityWarning':
'Może wpływać na wydajność na słabszych urządzeniach.',
'settings.mapHighQualityWarning': 'Może wpływać na wydajność na słabszych urządzeniach.',
'settings.mapTipLabel': 'Wskazówka:',
'settings.mapTip':
'Kliknij prawym przyciskiem i przeciągnij, aby obrócić/pochylić mapę. Środkowy przycisk dodaje miejsce (prawy jest zarezerwowany dla obrotu).',
@@ -45,11 +41,9 @@ const settings: TranslationStrings = {
'settings.saveMap': 'Zapisz mapę',
'settings.apiKeys': 'Klucze API',
'settings.mapsKey': 'Klucz Google Maps API',
'settings.mapsKeyHint':
'Do wyszukiwania miejsc. Wymaga Places API (New). Uzyskaj dostęp na console.cloud.google.com',
'settings.mapsKeyHint': 'Do wyszukiwania miejsc. Wymaga Places API (New). Uzyskaj dostęp na console.cloud.google.com',
'settings.weatherKey': 'Klucz OpenWeatherMap API',
'settings.weatherKeyHint':
'Do danych pogodowych. Bezpłatnie na openweathermap.org/api',
'settings.weatherKeyHint': 'Do danych pogodowych. Bezpłatnie na openweathermap.org/api',
'settings.keyPlaceholder': 'Podaj klucz...',
'settings.configured': 'Skonfigurowano',
'settings.saveKeys': 'Zapisz klucze',
@@ -89,8 +83,7 @@ const settings: TranslationStrings = {
'settings.mcp.copied': 'Skopiowano!',
'settings.mcp.apiTokens': 'Tokeny API',
'settings.mcp.createToken': 'Utwórz nowy token',
'settings.mcp.noTokens':
'Brak tokenów. Utwórz go, aby połączyć klientów MCP.',
'settings.mcp.noTokens': 'Brak tokenów. Utwórz go, aby połączyć klientów MCP.',
'settings.mcp.tokenCreatedAt': 'Utworzono',
'settings.mcp.tokenUsedAt': 'Użyto',
'settings.mcp.deleteTokenTitle': 'Usuń token',
@@ -98,8 +91,7 @@ const settings: TranslationStrings = {
'Ten token przestanie działać natychmiastowo. Każdy klient MCP używający go straci dostęp.',
'settings.mcp.modal.createTitle': 'Utwórz token API',
'settings.mcp.modal.tokenName': 'Nazwa tokenu',
'settings.mcp.modal.tokenNamePlaceholder':
'np. Claude Desktop, Laptop służbowy',
'settings.mcp.modal.tokenNamePlaceholder': 'np. Claude Desktop, Laptop służbowy',
'settings.mcp.modal.creating': 'Tworzenie...',
'settings.mcp.modal.create': 'Utwórz token',
'settings.mcp.modal.createdTitle': 'Token został utworzony',
@@ -135,16 +127,13 @@ const settings: TranslationStrings = {
'settings.oauth.sessionExpires': 'Wygasa',
'settings.oauth.revoke': 'Unieważnij',
'settings.oauth.revokeSession': 'Unieważnij sesję',
'settings.oauth.revokeSessionMessage':
'Spowoduje to natychmiastowe unieważnienie dostępu dla tej sesji OAuth.',
'settings.oauth.revokeSessionMessage': 'Spowoduje to natychmiastowe unieważnienie dostępu dla tej sesji OAuth.',
'settings.oauth.modal.createTitle': 'Zarejestruj klienta OAuth',
'settings.oauth.modal.presets': 'Szybkie ustawienia',
'settings.oauth.modal.clientName': 'Nazwa aplikacji',
'settings.oauth.modal.clientNamePlaceholder':
'np. Claude Web, Moja aplikacja MCP',
'settings.oauth.modal.clientNamePlaceholder': 'np. Claude Web, Moja aplikacja MCP',
'settings.oauth.modal.redirectUris': 'URI przekierowania',
'settings.oauth.modal.redirectUrisPlaceholder':
'https://your-app.com/callback\nhttps://your-app.com/auth',
'settings.oauth.modal.redirectUrisPlaceholder': 'https://your-app.com/callback\nhttps://your-app.com/auth',
'settings.oauth.modal.redirectUrisHint':
'Jeden URI na linię. Wymagane HTTPS (localhost zwolniony). Wymagana dokładna zgodność.',
'settings.oauth.modal.scopes': 'Dozwolone uprawnienia',
@@ -157,15 +146,13 @@ const settings: TranslationStrings = {
'settings.oauth.modal.createdTitle': 'Klient zarejestrowany',
'settings.oauth.modal.createdWarning':
'Sekret klienta jest wyświetlany tylko raz. Skopiuj go teraz — nie można go odzyskać.',
'settings.oauth.toast.createError':
'Nie udało się zarejestrować klienta OAuth',
'settings.oauth.toast.createError': 'Nie udało się zarejestrować klienta OAuth',
'settings.oauth.toast.deleted': 'Klient OAuth usunięty',
'settings.oauth.toast.deleteError': 'Nie udało się usunąć klienta OAuth',
'settings.oauth.toast.revoked': 'Sesja unieważniona',
'settings.oauth.toast.revokeError': 'Nie udało się unieważnić sesji',
'settings.oauth.toast.rotateError': 'Nie udało się odnowić sekretu klienta',
'settings.oauth.modal.machineClient':
'Klient maszynowy (bez logowania przez przeglądarkę)',
'settings.oauth.modal.machineClient': 'Klient maszynowy (bez logowania przez przeglądarkę)',
'settings.oauth.modal.machineClientHint':
'Używa grantu client_credentials — nie są potrzebne URI przekierowania. Token jest wystawiany bezpośrednio przez client_id + client_secret i działa w Twoim imieniu w ramach wybranych zakresów.',
'settings.oauth.modal.machineClientUsage':
@@ -186,8 +173,7 @@ const settings: TranslationStrings = {
'settings.about.supporters.tierEmpty': 'Bądź pierwszy',
'settings.about.supporter.tier.noReturnTicket': 'No Return Ticket',
'settings.about.supporter.tier.lostLuggageVip': 'Lost Luggage VIP',
'settings.about.supporter.tier.businessClassDreamer':
'Business Class Dreamer',
'settings.about.supporter.tier.businessClassDreamer': 'Business Class Dreamer',
'settings.about.supporter.tier.budgetTraveller': 'Budget Traveller',
'settings.about.supporter.tier.hostelBunkmate': 'Hostel Bunkmate',
'settings.about.description':
@@ -208,8 +194,7 @@ const settings: TranslationStrings = {
'settings.passwordRequired': 'Proszę podać aktualne i nowe hasło',
'settings.passwordTooShort': 'Hasło musi mieć co najmniej 8 znaków',
'settings.passwordMismatch': 'Hasła nie są identyczne',
'settings.passwordWeak':
'Hasło musi zawierać wielką literę, małą literę i cyfrę',
'settings.passwordWeak': 'Hasło musi zawierać wielką literę, małą literę i cyfrę',
'settings.passwordChanged': 'Hasło zostało zmienione pomyślnie',
'settings.deleteAccount': 'Usuń konto',
'settings.deleteAccountTitle': 'Usunąć twoje konto?',
@@ -238,8 +223,7 @@ const settings: TranslationStrings = {
'settings.mfa.backupTitle': 'Kody zapasowe',
'settings.mfa.backupDescription':
'Użyj tych jednorazowych kodów zapasowych, jeżeli stracisz dostęp do swojej aplikacji uwierzytelniającej.',
'settings.mfa.backupWarning':
'Zapisz te kody. Każdy z nich może być wykorzystany tylko raz.',
'settings.mfa.backupWarning': 'Zapisz te kody. Każdy z nich może być wykorzystany tylko raz.',
'settings.mfa.backupCopy': 'Kopiuj kody',
'settings.mfa.backupDownload': 'Pobierz TXT',
'settings.mfa.backupPrint': 'Drukuj / PDF',
@@ -247,20 +231,16 @@ const settings: TranslationStrings = {
'settings.mfa.enabled': '2FA jest włączone dla Twojego konta.',
'settings.mfa.disabled': '2FA jest wyłączone.',
'settings.mfa.setup': 'Skonfiguruj aplikację uwierzytelniającą',
'settings.mfa.scanQr':
'Zeskanuj ten kod QR za pomocą aplikacji lub wprowadź klucz ręcznie.',
'settings.mfa.scanQr': 'Zeskanuj ten kod QR za pomocą aplikacji lub wprowadź klucz ręcznie.',
'settings.mfa.secretLabel': 'Tajny klucz (wprowadź ręcznie)',
'settings.mfa.codePlaceholder': '6-cyfrowy kod',
'settings.mfa.enable': 'Włącz 2FA',
'settings.mfa.cancelSetup': 'Anuluj',
'settings.mfa.disableTitle': 'Wyłącz 2FA',
'settings.mfa.disableHint':
'Podaj hasło do konta i aktualny kod z aplikacji uwierzytelniającej.',
'settings.mfa.disableHint': 'Podaj hasło do konta i aktualny kod z aplikacji uwierzytelniającej.',
'settings.mfa.disable': 'Wyłącz 2FA',
'settings.mfa.toastEnabled':
'Uwierzytelnianie dwuskładnikowe zostało włączone',
'settings.mfa.toastDisabled':
'Uwierzytelnianie dwuskładnikowe zostało wyłączone',
'settings.mfa.toastEnabled': 'Uwierzytelnianie dwuskładnikowe zostało włączone',
'settings.mfa.toastDisabled': 'Uwierzytelnianie dwuskładnikowe zostało wyłączone',
'settings.mfa.demoBlocked': 'Niedostępne w trybie demonstracyjnym',
'settings.bookingLabels': 'Etykiety tras rezerwacji',
'settings.bookingLabelsHint':
@@ -270,13 +250,11 @@ const settings: TranslationStrings = {
'Brak skonfigurowanych kanałów powiadomień. Poproś administratora o skonfigurowanie powiadomień e-mail lub webhook.',
'settings.webhookUrl.label': 'URL webhooka',
'settings.webhookUrl.placeholder': 'https://discord.com/api/webhooks/...',
'settings.webhookUrl.hint':
'Wprowadź adres URL webhooka Discord, Slack lub własnego, aby otrzymywać powiadomienia.',
'settings.webhookUrl.hint': 'Wprowadź adres URL webhooka Discord, Slack lub własnego, aby otrzymywać powiadomienia.',
'settings.webhookUrl.saved': 'URL webhooka zapisany',
'settings.webhookUrl.test': 'Testuj',
'settings.webhookUrl.testSuccess': 'Testowy webhook wysłany pomyślnie',
'settings.webhookUrl.testFailed':
'Wysyłanie testowego webhooka nie powiodło się',
'settings.webhookUrl.testFailed': 'Wysyłanie testowego webhooka nie powiodło się',
'settings.ntfyUrl.topicLabel': 'Temat Ntfy',
'settings.ntfyUrl.topicPlaceholder': 'my-trek-alerts',
'settings.ntfyUrl.serverLabel': 'URL serwera Ntfy (opcjonalne)',
@@ -287,8 +265,7 @@ const settings: TranslationStrings = {
'settings.ntfyUrl.tokenHint': 'Wymagane dla tematów chronionych hasłem.',
'settings.ntfyUrl.saved': 'Ustawienia Ntfy zapisane',
'settings.ntfyUrl.test': 'Testuj',
'settings.ntfyUrl.testSuccess':
'Testowe powiadomienie Ntfy wysłane pomyślnie',
'settings.ntfyUrl.testSuccess': 'Testowe powiadomienie Ntfy wysłane pomyślnie',
'settings.ntfyUrl.testFailed': 'Testowe powiadomienie Ntfy nie powiodło się',
'settings.ntfyUrl.tokenCleared': 'Token dostępu wyczyszczony',
'settings.notificationPreferences.inapp': 'In-App',
@@ -296,11 +273,10 @@ const settings: TranslationStrings = {
'settings.notificationPreferences.email': 'Email',
'settings.notificationPreferences.ntfy': 'Ntfy',
'settings.notificationsActive': 'Aktywny kanał',
'settings.notificationsManagedByAdmin':
'Zdarzenia konfigurowane przez administratora.',
'settings.notificationsManagedByAdmin': 'Zdarzenia konfigurowane przez administratora.',
'settings.mustChangePassword': 'Musisz zmienić hasło przed kontynuowaniem.',
"settings.currency": "Currency",
"settings.currencyHint": "All amounts in Costs are converted to and shown in this currency.",
'settings.currency': 'Currency',
'settings.currencyHint': 'All amounts in Costs are converted to and shown in this currency.',
'settings.passkey.title': 'Klucze dostępu',
'settings.passkey.description':
'Loguj się szybciej i z odpornością na phishing za pomocą klucza dostępu — odcisku palca, twarzy, kodu PIN lub klucza sprzętowego. Twoje hasło pozostaje jako zapasowa opcja.',
@@ -317,8 +293,7 @@ const settings: TranslationStrings = {
'settings.passkey.addError': 'Nie udało się dodać klucza dostępu',
'settings.passkey.cancelled': 'Konfiguracja klucza dostępu anulowana',
'settings.passkey.deleted': 'Klucz dostępu został usunięty',
'settings.passkey.deleteConfirm':
'Usunąć ten klucz dostępu? Potwierdź swoim hasłem.',
'settings.passkey.deleteConfirm': 'Usunąć ten klucz dostępu? Potwierdź swoim hasłem.',
'settings.passkey.rename': 'Zmień nazwę',
'settings.passkey.defaultName': 'Klucz dostępu',
'settings.passkey.synced': 'Zsynchronizowany',
@@ -326,15 +301,21 @@ const settings: TranslationStrings = {
'settings.passkey.lastUsed': 'Ostatnio użyty',
'settings.passkey.neverUsed': 'Nigdy nieużywany',
'settings.mapPoiPill': 'Odkrywaj miejsca na mapie',
'settings.mapPoiPillHint': 'Pokaż na mapie wyprawy pasek z kategoriami, aby znaleźć pobliskie restauracje, hotele i więcej z OpenStreetMap.',
'settings.mapPoiPillHint':
'Pokaż na mapie wyprawy pasek z kategoriami, aby znaleźć pobliskie restauracje, hotele i więcej z OpenStreetMap.',
'settings.airtrail.title': 'AirTrail',
'settings.airtrail.hint': 'Połącz swój własny AirTrail, aby importować i synchronizować loty. Utwórz klucz API w AirTrail w sekcji Ustawienia → Bezpieczeństwo.',
'settings.airtrail.hint':
'Połącz swój własny AirTrail, aby importować i synchronizować loty. Utwórz klucz API w AirTrail w sekcji Ustawienia → Bezpieczeństwo.',
'settings.airtrail.url': 'Adres URL instancji',
'settings.airtrail.apiKey': 'Klucz API',
'settings.airtrail.apiKeyPlaceholder': 'Klucz API typu Bearer',
'settings.airtrail.apiKeyHint': 'Wygenerowany w AirTrail w sekcji Ustawienia → Bezpieczeństwo. Przechowywany w postaci zaszyfrowanej.',
'settings.airtrail.apiKeyHint':
'Wygenerowany w AirTrail w sekcji Ustawienia → Bezpieczeństwo. Przechowywany w postaci zaszyfrowanej.',
'settings.airtrail.allowInsecureTls': 'Zezwalaj na certyfikaty samopodpisane',
'settings.airtrail.allowInsecureTlsHint': 'Włącz tylko dla zaufanej instancji we własnej sieci.',
'settings.airtrail.writeBack': 'Zapisuj zmiany z powrotem w AirTrail',
'settings.airtrail.writeBackHint':
'Domyślnie wyłączone: AirTrail jest źródłem prawdy, a TREK tylko z niego odczytuje. Włącz, aby wysyłać zmiany wprowadzone w TREK z powrotem do AirTrail.',
'settings.airtrail.connected': 'Połączono',
'settings.airtrail.notConnected': 'Nie połączono',
'settings.airtrail.toast.saved': 'Zapisano połączenie z AirTrail',
+10 -20
View File
@@ -5,8 +5,7 @@ const system_notice: TranslationStrings = {
'system_notice.welcome_v1.body':
'Twój kompleksowy planer podróży. Twórz trasy, dziel się wycieczkami ze znajomymi i bądź zorganizowany — online i offline.',
'system_notice.welcome_v1.cta_label': 'Zaplanuj podróż',
'system_notice.welcome_v1.hero_alt':
'Malownicze miejsce z interfejsem planowania TREK',
'system_notice.welcome_v1.hero_alt': 'Malownicze miejsce z interfejsem planowania TREK',
'system_notice.welcome_v1.highlight_plan': 'Trasy dzień po dniu',
'system_notice.welcome_v1.highlight_share': 'Współpraca z partnerami podróży',
'system_notice.welcome_v1.highlight_offline': 'Działa offline na telefonie',
@@ -26,34 +25,25 @@ const system_notice: TranslationStrings = {
'system_notice.v3_journey.cta_label': 'Otwórz Journey',
'system_notice.v3_journey.highlight_timeline': 'Dzienna oś czasu i galeria',
'system_notice.v3_journey.highlight_photos': 'Import z Immich lub Synology',
'system_notice.v3_journey.highlight_share':
'Udostępnij publicznie — bez logowania',
'system_notice.v3_journey.highlight_export':
'Eksportuj jako książkę fotograficzną PDF',
'system_notice.v3_journey.highlight_share': 'Udostępnij publicznie — bez logowania',
'system_notice.v3_journey.highlight_export': 'Eksportuj jako książkę fotograficzną PDF',
'system_notice.v3_features.title': 'Więcej nowości w 3.0',
'system_notice.v3_features.body':
'Kilka innych rzeczy wartych uwagi w tym wydaniu.',
'system_notice.v3_features.highlight_dashboard':
'Przeprojektowany pulpit mobile-first',
'system_notice.v3_features.body': 'Kilka innych rzeczy wartych uwagi w tym wydaniu.',
'system_notice.v3_features.highlight_dashboard': 'Przeprojektowany pulpit mobile-first',
'system_notice.v3_features.highlight_offline': 'Pełny tryb offline jako PWA',
'system_notice.v3_features.highlight_search':
'Autouzupełnianie wyszukiwania miejsc',
'system_notice.v3_features.highlight_import':
'Import miejsc z plików KMZ/KML',
'system_notice.v3_features.highlight_search': 'Autouzupełnianie wyszukiwania miejsc',
'system_notice.v3_features.highlight_import': 'Import miejsc z plików KMZ/KML',
'system_notice.v3_mcp.title': 'MCP: aktualizacja OAuth 2.1',
'system_notice.v3_mcp.body':
'Integracja MCP została całkowicie przeprojektowana. OAuth 2.1 jest teraz zalecaną metodą uwierzytelniania. Statyczne tokeny (trek_…) są przestarzałe i zostaną usunięte w przyszłej wersji.',
'system_notice.v3_mcp.highlight_oauth': 'OAuth 2.1 zalecany (mcp-remote)',
'system_notice.v3_mcp.highlight_scopes': '24 szczegółowe zakresy uprawnień',
'system_notice.v3_mcp.highlight_deprecated':
'Statyczne tokeny trek_ przestarzałe',
'system_notice.v3_mcp.highlight_tools':
'Rozszerzony zestaw narzędzi i promptów',
'system_notice.v3_mcp.highlight_deprecated': 'Statyczne tokeny trek_ przestarzałe',
'system_notice.v3_mcp.highlight_tools': 'Rozszerzony zestaw narzędzi i promptów',
'system_notice.v3_thankyou.title': 'Osobiste słowo ode mnie',
'system_notice.v3_thankyou.body':
'Zanim pójdziesz dalej — chcę się na chwilę zatrzymać.\n\nTREK zaczął się jako poboczny projekt, który zbudowałem na własne podróże. Nigdy nie wyobrażałem sobie, że wyrośnie na coś, czemu 4000 z was ufa przy planowaniu swoich przygód. Każda gwiazdka, każdy issue, każda prośba o funkcję — czytam je wszystkie i to one trzymają mnie na nogach podczas późnych nocy między pracą na pełny etat a uczelnią.\n\nChcę, żebyście wiedzieli: TREK zawsze będzie open source, zawsze self-hosted, zawsze wasz. Bez śledzenia, bez subskrypcji, bez haczyków. Po prostu narzędzie zbudowane przez kogoś, kto kocha podróżowanie tak samo jak wy.\n\nSzczególne podziękowania dla [jubnl](https://github.com/jubnl) — stałeś się niesamowitym współpracownikiem. Tak wiele z tego, co czyni wersję 3.0 wspaniałą, nosi twój ślad. Dziękuję, że uwierzyłeś w ten projekt, gdy był jeszcze surowy.\n\nI każdemu z was, kto zgłosił błąd, przetłumaczył tekst, podzielił się TREK z przyjacielem lub po prostu użył go do zaplanowania podróży — **dziękuję**. To wy jesteście powodem, dla którego to istnieje.\n\nZa wiele kolejnych wspólnych przygód.\n\n— Maurice\n\n---\n\n[Dołącz do społeczności na Discordzie](https://discord.gg/7Q6M6jDwzf)\n\nJeśli TREK sprawia, że Twoje podróże są lepsze, [mała kawa](https://ko-fi.com/mauriceboe) zawsze pomaga utrzymać światła włączone.',
'system_notice.v3014_whitespace_collision.title':
'Wymagane działanie: konflikt konta użytkownika',
'system_notice.v3014_whitespace_collision.title': 'Wymagane działanie: konflikt konta użytkownika',
'system_notice.v3014_whitespace_collision.body':
'Aktualizacja 3.0.14 wykryła jeden lub więcej konfliktów nazwy użytkownika lub adresu e-mail spowodowanych spacjami na początku lub końcu przechowywanych wartości. Dotknięte konta zostały automatycznie przemianowane. Sprawdź logi serwera pod kątem wierszy zaczynających się od **[migration] WHITESPACE COLLISION**, aby zidentyfikować konta wymagające przeglądu.',
};
+1 -1
View File
@@ -9,7 +9,7 @@ const trip: TranslationStrings = {
'trip.tabs.packingShort': 'Pakowanie',
'trip.tabs.lists': 'Listy',
'trip.tabs.listsShort': 'Listy',
'trip.tabs.budget': "Costs",
'trip.tabs.budget': 'Costs',
'trip.tabs.files': 'Pliki',
'trip.loading': 'Ładowanie podróży...',
'trip.mobilePlan': 'Plan',
+12 -24
View File
@@ -8,8 +8,7 @@ const vacay: TranslationStrings = {
'vacay.addPrevYear': 'Dodaj poprzedni rok',
'vacay.removeYear': 'Usuń rok',
'vacay.removeYearConfirm': 'Usunąć {year}?',
'vacay.removeYearHint':
'Wszystkie wpisy dotyczące urlopów oraz dni wolnych w tym roku zostaną trwale usunięte.',
'vacay.removeYearHint': 'Wszystkie wpisy dotyczące urlopów oraz dni wolnych w tym roku zostaną trwale usunięte.',
'vacay.remove': 'Usuń',
'vacay.persons': 'Osoby',
'vacay.noPersons': 'Nie dodano osób',
@@ -17,8 +16,7 @@ const vacay: TranslationStrings = {
'vacay.editPerson': 'Edytuj osobę',
'vacay.removePerson': 'Usuń osobę',
'vacay.removePersonConfirm': 'Usunąć {name}?',
'vacay.removePersonHint':
'Wszystkie wpisy dotyczące urlopów dla tej osoby zostaną trwale usunięte.',
'vacay.removePersonHint': 'Wszystkie wpisy dotyczące urlopów dla tej osoby zostaną trwale usunięte.',
'vacay.personName': 'Imię',
'vacay.personNamePlaceholder': 'Podaj imię',
'vacay.color': 'Kolor',
@@ -53,16 +51,12 @@ const vacay: TranslationStrings = {
'vacay.calendarColor': 'Kolor',
'vacay.noCalendars': 'Nie dodano jeszcze kalendarzy świąt',
'vacay.companyHolidays': 'Urlopy firmowe',
'vacay.companyHolidaysHint':
'Pozwala oznaczać dni wolne od pracy w kalendarzu',
'vacay.companyHolidaysNoDeduct':
'Urlopy firmowe nie są odejmowane od puli dni urlopowych.',
'vacay.companyHolidaysHint': 'Pozwala oznaczać dni wolne od pracy w kalendarzu',
'vacay.companyHolidaysNoDeduct': 'Urlopy firmowe nie są odejmowane od puli dni urlopowych.',
'vacay.weekStart': 'Tydzień zaczyna się w',
'vacay.weekStartHint':
'Wybierz czy tydzień zaczyna się w poniedziałek czy niedzielę',
'vacay.weekStartHint': 'Wybierz czy tydzień zaczyna się w poniedziałek czy niedzielę',
'vacay.carryOver': 'Przeniesienie na kolejny rok',
'vacay.carryOverHint':
'Automatycznie przenosi pozostałe dni urlopowe na kolejny rok',
'vacay.carryOverHint': 'Automatycznie przenosi pozostałe dni urlopowe na kolejny rok',
'vacay.sharing': 'Udostępnianie',
'vacay.sharingHint': 'Udostępnij swój plan urlopów innym użytkownikom TREK',
'vacay.owner': 'Właściciel',
@@ -70,8 +64,7 @@ const vacay: TranslationStrings = {
'vacay.shareSuccess': 'Plan został udostępniony pomyślnie',
'vacay.shareError': 'Nie udało się udostępnić planu',
'vacay.dissolve': 'Rozłącz kalendarze',
'vacay.dissolveHint':
'Rozłącz kalendarze ponownie. Twoje wpisy zostaną zachowane.',
'vacay.dissolveHint': 'Rozłącz kalendarze ponownie. Twoje wpisy zostaną zachowane.',
'vacay.dissolveAction': 'Rozłącz',
'vacay.dissolved': 'Kalendarz został rozłączony',
'vacay.fusedWith': 'Połączono z',
@@ -79,8 +72,7 @@ const vacay: TranslationStrings = {
'vacay.noData': 'Brak danych',
'vacay.changeColor': 'Zmień kolor',
'vacay.inviteUser': 'Zaproś użytkownika',
'vacay.inviteHint':
'Zaproś innego użytkownika TREK do wspólnego kalendarza urlopów.',
'vacay.inviteHint': 'Zaproś innego użytkownika TREK do wspólnego kalendarza urlopów.',
'vacay.selectUser': 'Wybierz użytkownika',
'vacay.sendInvite': 'Wyślij zaproszenie',
'vacay.inviteSent': 'Zaproszenie zostało wysłane',
@@ -92,14 +84,10 @@ const vacay: TranslationStrings = {
'vacay.acceptFusion': 'Akceptuj i połącz',
'vacay.inviteTitle': 'Zaproszenie do połączenia',
'vacay.inviteWantsToFuse': 'chce udostępnić kalendarz urlopów.',
'vacay.fuseInfo1':
'Obie strony będą widzieć wszystkie wpisy urlopowe w jednym wspólnym kalendarzu.',
'vacay.fuseInfo2':
'Obie strony mogą tworzyć i edytować wpisy dla drugiej strony.',
'vacay.fuseInfo3':
'Obie strony mogą usuwać wpisy i zmieniać pulę dni urlopowych.',
'vacay.fuseInfo4':
'Ustawienia, takie jak święta państwowe i urlopy firmowe, są współdzielone.',
'vacay.fuseInfo1': 'Obie strony będą widzieć wszystkie wpisy urlopowe w jednym wspólnym kalendarzu.',
'vacay.fuseInfo2': 'Obie strony mogą tworzyć i edytować wpisy dla drugiej strony.',
'vacay.fuseInfo3': 'Obie strony mogą usuwać wpisy i zmieniać pulę dni urlopowych.',
'vacay.fuseInfo4': 'Ustawienia, takie jak święta państwowe i urlopy firmowe, są współdzielone.',
'vacay.fuseInfo5':
'Połączenie może zostać rozwiązane w dowolnym momencie przez każdą ze stron. Twoje wpisy zostaną zachowane.',
};