aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-16 00:21:07 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-16 00:21:07 +0200
commit3b2d03a919e56d14f8097844b97b844ddf526cd6 (patch)
tree31b222fedf6d608809eb47c45c5f431d7001d87a /packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js
parent75065cc1ed5d9cd733871d478dc4f915663d795c (diff)
downloadmeshbay-3b2d03a919e56d14f8097844b97b844ddf526cd6.tar.gz
feat(hub): translate the web client into nine more languages
French, Spanish, Brazilian Portuguese, Simplified Chinese, Japanese, German, Italian, Dutch and Polish, all in the formal register. `hub`, `node` and `GEK` stay in English: they name the CLI, node.toml and the docs, and translating them would cut the interface off from everything an operator reads and types. Catalogues move out of i18n.js into locales/, one file per language, fetched with a dynamic import. A visitor downloads their language plus English as a fallback — about 36 KB rather than the ~180 KB that ten inlined catalogues would have cost everyone. i18n.js keeps only the loader, so the first render now waits for initLocale(). Three things the old code got wrong, none of them visible until there was a second language: - Resolution trimmed a tag to its base before matching, so a browser reporting pt-BR looked for a `pt` catalogue that does not exist and fell back to English. Matching is now exact first, then by base language. - Counted strings were single strings, so Polish could not express 1 plik / 2 pliki / 5 plików at all. t() selects through Intl.PluralRules; en.js gains the same treatment, which incidentally fixes "1 files". - Interpolation used String.replace, which reads `$&` in the replacement. A file named rap$&sody.mp3 rendered corrupted in its own delete dialog. Five strings were still hardcoded in app.js — the group name placeholder and the four visibility/join-policy descriptions — and are now keyed. test_locales.py holds the nine translations to the shape of en.js: same keys, a counted string stays counted everywhere, every plural entry covers each category Intl actually produces for that language, and the {placeholders} survive translation. Verified failing first, against a catalogue with a key removed, a placeholder dropped and the Polish `few` form deleted. The language menu also grew from one entry to ten, which overran a short viewport inside a dropdown that clipped instead of scrolling. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js419
1 files changed, 419 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js
new file mode 100644
index 0000000..d77a160
--- /dev/null
+++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js
@@ -0,0 +1,419 @@
+/**
+ * Polish — translated from locales/en.js.
+ *
+ * Register: formal — the polite impersonal ("Proszę wpisać…", "Można…"), which is
+ * how formal Polish software addresses the reader; direct "Pan / Pani" is used
+ * only where a sentence needs a subject.
+ * `hub`, `node` and `GEK` are left in English: they name the CLI
+ * (`meshbay-node`), node.toml and the docs, which are English throughout.
+ * Polish uses four plural categories, so counted strings carry all of
+ * one / few / many / other.
+ */
+
+export default {
+ // Nav
+ 'nav.toggle_menu': 'Pokaż menu',
+ 'nav.light_mode': 'Motyw jasny',
+ 'nav.dark_mode': 'Motyw ciemny',
+ 'nav.logout': 'Wyloguj',
+ 'nav.login': 'Zaloguj',
+
+ // Sidebar
+ 'sidebar.my_groups': 'Moje grupy',
+ 'sidebar.no_groups': 'Nie ma jeszcze żadnych grup',
+ 'sidebar.discover': 'Odkrywaj',
+ 'sidebar.public_groups': 'Grupy publiczne',
+
+ // Login
+ 'login.title': 'Logowanie',
+ 'login.username': 'Nazwa użytkownika',
+ 'login.password': 'Hasło',
+ 'login.submit': 'Zaloguj',
+ 'login.loading': 'Logowanie...',
+ 'login.no_account': 'Nie ma jeszcze konta?',
+ 'login.register_link': 'Załóż konto',
+
+ // Register
+ 'register.title': 'Zakładanie konta',
+ 'register.username': 'Nazwa użytkownika',
+ 'register.email': 'Adres e-mail',
+ 'register.password': 'Hasło-fraza (co najmniej 12 znaków)',
+ 'register.confirm': 'Potwierdź hasło',
+ 'register.submit': 'Załóż konto',
+ 'register.loading': 'Tworzenie konta...',
+ 'register.has_account': 'Konto już istnieje?',
+ 'register.login_link': 'Zaloguj',
+ 'register.success_title': 'Konto zostało założone',
+ 'register.success_msg': 'Można się już zalogować przy użyciu swoich danych.',
+ 'register.go_login': 'Przejdź do logowania',
+ 'register.err_mismatch': 'Hasła nie są zgodne',
+ 'register.err_min_len': {
+ one: 'Proszę użyć co najmniej {n} znaku',
+ few: 'Proszę użyć co najmniej {n} znaków',
+ many: 'Proszę użyć co najmniej {n} znaków',
+ other: 'Proszę użyć co najmniej {n} znaku',
+ },
+ 'register.err_too_weak': 'Zbyt łatwe do odgadnięcia. To hasło-fraza chroni klucze '
+ + 'tam, gdzie są przechowywane — kilka niepowiązanych ze sobą słów sprawdza się '
+ + 'bardzo dobrze.',
+ 'register.strength': 'Siła: około {bits} bitów. Chroni kopię kluczy przechowywaną na '
+ + 'nodes, do których się dołącza, więc warto ją dobrać starannie.',
+
+ // Home
+ 'home.welcome': 'Witamy w MeshBay',
+ 'home.no_groups': 'Nie należy Pan(i) jeszcze do żadnej grupy.',
+ 'home.browse_prefix': 'Warto przejrzeć ',
+ 'home.browse_link': 'grupy publiczne',
+ 'home.browse_suffix': ' albo poprosić administratora grupy o zaproszenie.',
+ 'home.my_groups': 'Moje grupy',
+
+ // Explore
+ 'explore.title': 'Grupy publiczne',
+ 'explore.search': 'Szukaj grup...',
+ 'explore.loading': 'Wczytywanie...',
+ 'explore.empty': 'Brak dostępnych grup publicznych.',
+ 'explore.create_group': 'Utwórz grupę',
+ 'explore.join': 'Dołącz',
+ 'explore.member': 'Należy',
+
+ // Group page
+ 'group.default_name': 'Grupa',
+ 'group.tab_files': 'Pliki',
+ 'group.tab_chat': 'Czat',
+ 'group.tab_members': 'Członkowie',
+ 'group.filter': 'Filtruj pliki...',
+ 'group.col_name': 'Nazwa',
+ 'group.col_size': 'Rozmiar',
+ 'group.col_type': 'Typ',
+ 'group.col_date': 'Data',
+ 'group.empty_filter': 'Żaden plik nie pasuje do filtra',
+ 'group.empty_dir': 'Ten folder jest pusty',
+ 'group.download': 'Pobierz',
+ 'group.play': 'Odtwórz',
+ 'group.offline_title': 'Obecnie żaden node nie jest dostępny dla tej grupy.',
+ 'group.offline_hint': 'Pliki pojawią się, gdy połączy się node hostujący tę grupę.',
+ 'group.upload': 'Wyślij',
+ 'group.mkdir': 'Nowy folder',
+ 'group.mkdir_prompt': 'Nazwa nowego folderu:',
+ 'group.view': 'Podgląd',
+ 'group.delete': 'Usuń',
+ 'group.delete_confirm': 'Usunąć {name}?',
+ 'group.delete_group': 'Usuń grupę',
+ 'group.delete_group_confirm': 'Trwale usunąć grupę „{name}” i odłączyć wszystkich '
+ + 'członków? Pliki znajdujące się na node zostaną zachowane.',
+ 'group.err_transport': 'Moduł transportu nie został wczytany',
+
+ // Status
+ 'status.idle': 'Bezczynny',
+ 'status.discovering': 'Szukanie nodes...',
+ 'status.connecting': 'Łączenie przez WebRTC...',
+ 'status.fetching': 'Pobieranie indeksu...',
+ 'status.files': {
+ one: '{n} plik',
+ few: '{n} pliki',
+ many: '{n} plików',
+ other: '{n} pliku',
+ },
+ 'status.offline': 'Żaden node nie jest dostępny',
+ 'status.error': 'Połączenie nie powiodło się',
+
+ // Chat
+ 'chat.empty': 'Nie ma jeszcze wiadomości. Warto zacząć rozmowę!',
+ 'chat.placeholder': 'Napisz wiadomość...',
+ 'chat.send': 'Wyślij',
+ 'chat.attach': 'Załącz plik',
+
+ // Video player
+ 'video.loading': 'Wczytywanie {name}...',
+ 'video.buffering': 'Buforowanie...',
+ 'video.close': 'Zamknij (Esc)',
+ 'preview.pdf_fallback': 'Ta przeglądarka nie wyświetli pliku PDF na stronie. Proszę '
+ + 'go pobrać — i tak został odszyfrowany tutaj.',
+ 'group.upload_indexing': 'indeksowanie…',
+ 'video.err_transport': 'Transport nie jest połączony',
+ 'video.err_mse': 'Kodek nieobsługiwany przy odtwarzaniu strumieniowym: {codec}',
+
+ // Settings
+ 'settings.title': 'Ustawienia',
+ 'settings.coming_soon': 'Wkrótce.',
+ 'settings.downloads': 'Pobieranie',
+ 'settings.dl_auto': 'Zapisuj automatycznie',
+ 'settings.dl_auto_hint': 'Pliki trafiają prosto do folderu wybranego poniżej, bez '
+ + 'żadnego okna. Pobranie dwudziestu plików umieści tam dwadzieścia plików.',
+ 'settings.dl_ask': 'Pytaj za każdym razem',
+ 'settings.dl_ask_hint': 'Okno „Zapisz jako” dla każdego pliku — po jednym na plik, '
+ + 'także przy pobieraniu zaznaczonych pozycji.',
+ 'settings.dl_folder': 'Folder: {name}',
+ 'settings.dl_no_folder': 'Nie wybrano folderu — pobrane pliki trafiają tam, gdzie '
+ + 'umieszcza je przeglądarka',
+ 'settings.dl_choose': 'Wybierz folder',
+ 'settings.dl_change': 'Zmień',
+ 'settings.dl_forget': 'Zapomnij',
+ 'settings.dl_path_note': 'Stronie internetowej nie da się podać ścieżki, więc nie ma '
+ + 'tu czego wpisywać: to przeglądarka udziela dostępu do wskazanego folderu, a '
+ + 'MeshBay zapisuje wyłącznie w jego wnętrzu. Raz na sesję może pojawić się prośba '
+ + 'o potwierdzenie.',
+ 'settings.dl_unsupported': 'Ta przeglądarka nie potrafi zapisywać w dowolnie '
+ + 'wybranym folderze (brak File System Access API), więc pobrane pliki trafiają do '
+ + 'jej własnego folderu pobierania. Chrome i Edge pozwalają wybrać folder.',
+ 'settings.profile': 'Profil',
+ 'settings.username': 'Nazwa użytkownika',
+ 'settings.node_pins': 'Tożsamości nodes',
+ 'settings.node_pins_hint': 'Klucz tożsamości każdego node jest zapamiętywany przy '
+ + 'pierwszym połączeniu. Jeśli się zmieni, połączenie zostanie odrzucone — czego '
+ + 'należy się spodziewać wyłącznie wtedy, gdy operator przeinstalował node. Przed '
+ + 'wyczyszczeniem warto to z nim potwierdzić.',
+ 'settings.node_pins_count': {
+ one: '{n} przypięta',
+ few: '{n} przypięte',
+ many: '{n} przypiętych',
+ other: '{n} przypiętej',
+ },
+ 'settings.node_pins_clear': 'Wyczyść przypięte tożsamości',
+ 'settings.danger': 'Usunięcie konta',
+ 'settings.delete_hint': 'Usuwa z huba konto, członkostwa w grupach i powiadomienia '
+ + 'oraz zwalnia nazwę użytkownika. Nie sięga tego, co znajduje się na nodes: '
+ + 'wysłane pliki pozostają tam, gdzie przechowuje je ich operator, a każdy node '
+ + 'zachowuje przypiętą tożsamość do czasu, aż jego operator ją odepnie. Dzienniki '
+ + 'połączeń są przechowywane przez rok, zgodnie z wymogami prawa.',
+ 'settings.delete_account': 'Usuń moje konto',
+ 'settings.delete_confirm': 'Proszę wpisać hasło-frazę, aby potwierdzić. Tej operacji '
+ + 'nie da się cofnąć.',
+ 'settings.delete_confirm_btn': 'Usuń bezpowrotnie',
+ 'settings.cancel': 'Anuluj',
+ 'settings.appearance': 'Wygląd',
+ 'settings.theme': 'Motyw',
+ 'settings.theme_light': 'Jasny',
+ 'settings.theme_dark': 'Ciemny',
+ 'settings.theme_system': 'Systemowy',
+ 'settings.language': 'Język',
+ 'settings.about': 'O programie',
+ 'settings.version': 'Wersja',
+ 'settings.protocol': 'Protokół',
+ 'settings.role': 'Rola',
+ 'settings.groups': 'Powiadomienia z grup',
+ 'settings.notifications': 'Powiadomienia',
+ 'settings.node_key': 'Powiąż node',
+ 'settings.node_key_desc': 'Osoby prowadzące własny node MeshBay mogą wkleić tutaj '
+ + 'jego klucz publiczny Ed25519, aby powiązać go ze swoim kontem. Klucz ten znajduje '
+ + 'się w panelu administracyjnym node.',
+ 'settings.node_key_placeholder': 'Wklej klucz publiczny Ed25519 node (base64)',
+ 'settings.node_key_submit': 'Powiąż node',
+ 'settings.node_key_success': 'Node został powiązany',
+ 'settings.node_key_current': 'Klucz powiązanego node',
+
+ // Sidebar
+ 'sidebar.create_group': 'Utwórz grupę',
+ 'sidebar.settings': 'Ustawienia',
+ 'sidebar.admin': 'Administracja',
+
+ // User menu
+ 'usermenu.language': 'Język',
+ 'usermenu.settings': 'Ustawienia',
+ 'usermenu.theme_light': 'Motyw jasny',
+ 'usermenu.theme_dark': 'Motyw ciemny',
+ 'usermenu.logout': 'Wyloguj',
+
+ // Admin panel
+ 'admin.title': 'Administracja',
+ 'admin.tab_stats': 'Statystyki',
+ 'admin.tab_users': 'Użytkownicy',
+ 'admin.tab_groups': 'Grupy',
+ 'admin.tab_nodes': 'Nodes',
+ 'admin.tab_logs': 'Dzienniki',
+ 'admin.col_observed_ip': 'Widziany z',
+ 'admin.col_hint': 'Zgłoszony adres',
+ 'admin.col_last_seen': 'Ostatnie zgłoszenie',
+ 'admin.node_online': 'dostępny',
+ 'admin.node_offline': 'niedostępny',
+ 'admin.no_nodes': 'Brak zarejestrowanych nodes',
+ 'admin.nodes_hint': '„Widziany z” to adres, z którego zgłoszenie rzeczywiście '
+ + 'dotarło, w żądaniu podpisanym kluczem node — i to na nim należy się opierać, '
+ + 'odpowiadając na zapytanie. Zgłoszony adres to ten, który node uważa za własny, '
+ + 'poznany od serwera STUN i przesłany do nas; przydaje się do nawiązania '
+ + 'połączenia i niczego nie dowodzi.',
+ 'admin.tab_blocklist': 'Lista blokad',
+
+ // Admin stats
+ 'admin.stat_users': 'Użytkownicy',
+ 'admin.stat_groups': 'Grupy',
+ 'admin.stat_nodes': 'Nodes',
+ 'admin.stat_online': 'Dostępne nodes',
+
+ // Admin users
+ 'admin.users_search': 'Szukaj użytkowników...',
+ 'admin.col_username': 'Nazwa użytkownika',
+ 'admin.col_role': 'Rola',
+ 'admin.col_status': 'Status',
+ 'admin.col_created': 'Utworzono',
+ 'admin.col_actions': 'Działania',
+ 'admin.col_email': 'E-mail',
+ 'admin.col_groups': 'Grupy',
+ 'admin.no_users': 'Nie znaleziono użytkowników',
+ 'admin.btn_suspend': 'Zawieś',
+ 'admin.btn_unsuspend': 'Przywróć',
+ 'admin.btn_details': 'Szczegóły',
+ 'admin.btn_delete': 'Usuń',
+ 'admin.delete_confirm': 'Usunąć konto „{user}”? Tej operacji nie da się cofnąć. '
+ + 'Wysłane przez tę osobę pliki pozostaną na hostujących je nodes, a każdy node '
+ + 'zachowa przypiętą tożsamość do czasu, aż jego operator ją odepnie. Zawieszenie '
+ + 'jest opcją odwracalną.',
+ 'admin.user_detail': 'Szczegóły użytkownika',
+ 'admin.btn_close': 'Zamknij',
+ 'admin.self_note': '(to Pan/Pani)',
+
+ // Admin groups
+ 'admin.col_name': 'Nazwa',
+ 'admin.col_visibility': 'Widoczność',
+ 'admin.col_members': 'Członkowie',
+ 'admin.no_groups': 'Nie znaleziono grup',
+
+ // Admin logs
+ 'admin.col_time': 'Czas',
+ 'admin.col_event': 'Zdarzenie',
+ 'admin.col_user': 'Użytkownik',
+ 'admin.col_ip': 'IP',
+ 'admin.col_detail': 'Szczegóły',
+ 'admin.filter_all': 'Wszystkie zdarzenia',
+ 'admin.no_logs': 'Nie znaleziono wpisów',
+ 'admin.btn_load_more': 'Wczytaj więcej',
+
+ // Admin blocklist
+ 'admin.col_hash': 'Skrót',
+ 'admin.col_reason': 'Powód',
+ 'admin.col_date': 'Data',
+ 'admin.col_added_by': 'Dodane przez',
+ 'admin.no_blocked': 'Brak zablokowanych skrótów',
+ 'admin.add_hash': 'Dodaj skrót do listy blokad',
+ 'admin.hash_placeholder': 'skrót blake3 (64 znaki szesnastkowe)',
+ 'admin.reason_placeholder': 'Powód',
+ 'admin.btn_block': 'Zablokuj',
+ 'admin.btn_unblock': 'Odblokuj',
+
+ // Notifications
+ // Create group
+ 'create_group.title': 'Tworzenie grupy',
+ 'create_group.name': 'Nazwa grupy',
+ 'create_group.name_placeholder': 'np. Zdjęcia rodzinne, Pliki projektu...',
+ 'create_group.visibility': 'Widoczność',
+ 'create_group.private': 'Prywatna',
+ 'create_group.private_desc': 'Tylko zaproszeni członkowie widzą pliki i mają do nich dostęp',
+ 'create_group.public': 'Publiczna',
+ 'create_group.public_desc': 'Każdy może odnaleźć i przeglądać tę grupę',
+ 'create_group.join_policy': 'Zasady dołączania',
+ 'create_group.invite': 'Tylko z zaproszeniem',
+ 'create_group.invite_desc': 'Członków musi zaprosić administrator',
+ 'create_group.open': 'Otwarta (każdy może dołączyć)',
+ 'create_group.open_desc': 'Każdy może dołączyć bez zatwierdzenia',
+ 'create_group.description': 'Opis',
+ 'create_group.description_hint': 'Czego dotyczy ta grupa? (opcjonalnie)',
+ 'create_group.submit': 'Utwórz',
+ 'create_group.hint': 'Grupa potrzebuje node, który będzie hostował pliki. Można '
+ + 'utworzyć grupę teraz, a node podłączyć później.',
+ 'create_group.creating': 'Tworzenie...',
+
+ // Members
+ 'members.col_role': 'Rola',
+ 'members.group_role': 'Rola w grupie',
+ 'members.admin': 'Administrator',
+ 'members.group_admin': 'Administrator grupy',
+ 'members.owner': 'Właściciel',
+ 'members.member': 'Członek',
+ 'members.invite_title': 'Zaproszenie członka',
+ 'members.username_placeholder': 'Nazwa użytkownika',
+ 'members.invite_btn': 'Zaproś',
+ 'members.invite_needs_pairing': 'Zaproszenia są podpisywane kluczem, który ten node '
+ + 'przypiął dla tej przeglądarki — proszę najpierw sparować ją poniżej, zanim '
+ + 'kogokolwiek Pan(i) zaprosi.',
+ 'members.invite_ask_operator': 'Zapraszać może wyłącznie operator node hostującego tę '
+ + 'grupę, z przeglądarki sparowanej z tym node.',
+ 'members.remove': 'Usuń',
+ 'members.remove_confirm': 'Usunąć użytkownika {user} z tej grupy? Jego konto, '
+ + 'pozostałe grupy i wysłane przez niego pliki pozostaną nienaruszone.',
+ 'members.remove_hint': 'Usunięcie kogoś odbiera mu członkostwo i sprawia, że node '
+ + 'przestaje wydawać mu klucz grupy. Nie usuwa to jego konta ani nie odbiera '
+ + 'klucza, który już posiada — jeśli to istotne, należy zmienić klucz na node '
+ + '(meshbay-node gek-init).',
+ 'members.pair_title': 'Sparowanie tej przeglądarki z Pana/Pani node',
+ 'members.pair_hint': 'Node przyjmuje działania operatora — zaproszenia, usuwanie '
+ + 'plików — wyłącznie z przeglądarki, z którą został sparowany. Proszę uruchomić na '
+ + 'node polecenie `meshbay-node operator pair` i wpisać tutaj kod. Kod nigdy nie '
+ + 'przechodzi przez hub.',
+ 'members.pair_btn': 'Sparuj',
+ 'members.pair_success': 'Ta przeglądarka jest już sparowana z node.',
+ 'members.invite_code_ready': 'Kod zaproszenia dla użytkownika {user} — proszę '
+ + 'przekazać go tak, jak zwykle się Państwo kontaktują. Działa jednorazowo i nigdy '
+ + 'nie przechodzi przez hub.',
+ 'members.invite_code_hint': 'Osoba zaproszona wpisze go, otwierając tę grupę po raz '
+ + 'pierwszy. Nie trzeba być wtedy dostępnym.',
+ 'transfers.title': 'Transfery',
+ 'transfers.clear': 'Wyczyść zakończone',
+ 'transfers.cancel': 'Anuluj',
+ 'transfers.open': 'Otwórz',
+ 'transfers.done': 'Zakończony',
+ 'transfers.cancelled': 'Anulowany',
+ 'transfers.failed': 'Nie powiódł się',
+ 'group.select': 'Zaznacz',
+ 'group.select_done': 'Gotowe',
+ 'group.actions': 'Działania ({n})',
+ 'group.download_n': 'Pobierz ({n})',
+ 'group.download_zip_n': 'Pobierz foldery jako zip ({n})',
+ 'group.delete_n': 'Usuń ({n})',
+ 'group.delete_n_confirm': {
+ one: 'Usunąć {n} element? {names}',
+ few: 'Usunąć {n} elementy? {names}',
+ many: 'Usunąć {n} elementów? {names}',
+ other: 'Usunąć {n} elementu? {names}',
+ },
+ 'group.download_zip': {
+ one: 'Pobierz jako zip ({n} plik)',
+ few: 'Pobierz jako zip ({n} pliki)',
+ many: 'Pobierz jako zip ({n} plików)',
+ other: 'Pobierz jako zip ({n} pliku)',
+ },
+ 'group.zip_empty': 'W tym folderze nie ma nic do pobrania.',
+ 'group.zip_no_stream': 'Ta przeglądarka nie potrafi zapisywać pobieranych danych '
+ + 'wprost na dysk, więc {name} ({size}) trzeba najpierw zbudować w pamięci. Przy '
+ + 'dużym archiwum może się to nie udać. Kontynuować?',
+ 'group.rmdir': 'Usuń folder',
+ 'group.rmdir_confirm': 'Usunąć folder „{name}”? Musi być pusty.',
+ 'group.rmdir_not_empty': 'Ten folder nie jest pusty. Proszę najpierw usunąć jego '
+ + 'zawartość — nic tutaj nie kasuje plików, których nie widać.',
+ 'group.desc_edit': 'Edytuj opis',
+ 'group.desc_add': 'Dodaj opis',
+ 'group.desc_save': 'Zapisz',
+ 'group.desc_cancel': 'Anuluj',
+ 'group.desc_placeholder': 'Do czego służy ta grupa — członkowie zobaczą to na swojej '
+ + 'stronie głównej.',
+ 'group.join_code_title': 'Ten node musi Pana/Panią rozpoznać',
+ 'group.join_code_hint': 'Proszę poprosić osobę zapraszającą o kod jednorazowy i '
+ + 'wpisać go tutaj. Od tej pory przeglądarka jest rozpoznawana i pytanie się nie '
+ + 'powtórzy.',
+ 'group.join_code_btn': 'Dołącz',
+
+ 'notif.purge': 'Wyczyść wszystko',
+ 'notif.title': 'Powiadomienia',
+ 'notif.empty': 'Brak powiadomień',
+ 'notif.mark_all_read': 'Oznacz wszystkie jako przeczytane',
+
+ // Sidebar
+ 'sidebar.search': 'Szukaj plików',
+
+ // Status
+
+ // Search
+ 'search.title': 'Wyszukiwanie plików',
+ 'search.placeholder': 'Szukaj we wszystkich grupach...',
+ 'search.no_results': 'Żaden plik nie pasuje do zapytania.',
+ 'search.synced': 'zsynchronizowano {ago}',
+ 'search.cache_note': 'Wyszukiwanie opiera się na stanie każdej grupy z chwili jej '
+ + 'ostatniego otwarcia. Otwarcie grupy odświeża tutaj jej pliki.',
+ 'search.col_group': 'Grupa',
+ 'search.result_count': {
+ one: 'Znaleziono {n} plik',
+ few: 'Znaleziono {n} pliki',
+ many: 'Znaleziono {n} plików',
+ other: 'Znaleziono {n} pliku',
+ },
+ 'search.hint': 'Przeszukuje nazwy plików we wszystkich zbuforowanych indeksach grup.',
+};