Handy/src/i18n/locales/pl/translation.json
Viren Mohindra ef24cfefda
feat: add models settings page with filtering and management (#478)
* feat: add models settings page with filtering and management

- add dedicated models settings page in sidebar
- reuse ModelCard component from onboarding for consistent UI
- add filter buttons for all/multi-language/translation models
- add model deletion with native confirmation dialog (tauri-plugin-dialog)
- consolidate model event listeners into useModels hook (Zustand store)
- remove duplicate event listeners from ModelSelector, LanguageSelector, TranslateToEnglish
- gate AccessibilityPermissions to macOS only
- add is_recommended field to model registry for featured models
- remove unused get_recommended_first_model command
- add translations for all 9 supported languages

* feat: add language filter to models settings page

adds a searchable language dropdown filter to the models page that lets users filter models by language support. when a non-english language is selected, models that don't support multiple languages (like parakeet) are hidden.

- add searchable language dropdown (right-aligned in filter row)
- filter models using supports_language_selection capability
- add allLanguages translation key to all 10 locales

* feat: add translation consistency checker script

- add scripts/check-translations.cjs to validate all language files
- script dynamically discovers languages from directory structure
- checks that all languages have same keys as english reference
- detects missing and extra keys in each language
- add check:translations npm script
- integrate into github actions lint workflow
- validates translations on every pull request

* fix: update imports and add missing translations after rebase

- replace useModels hook with useModelStore in components
- add permission error keys to all languages
- add model settings keys to cs and tr (new languages from main)

* fix: translate english placeholders in cs and tr locale files

* refactor: simplify model dropdown and migrate store to immer

- model dropdown now only shows downloaded models (no download/delete)
- convert store to immer with record types for immutability
- remove unused translation keys (welcome, downloadPrompt, etc.)
- add missing moonshine-base model fields
- sync translations after rebase

* fix: add download cancellation support and ui improvements

- add full download cancellation with Arc<AtomicBool> flags in rust backend
- add progress event throttling (100ms) to prevent ui freeze
- add cancel button to model card in settings page
- add model-deleted event listener to refresh dropdown after deletion
- remove pink background from recommended models in settings (keep badge only)
- add cancel/cancelDownload translation keys to all 14 languages

* fix: remove duplicate language/translate settings from general and advanced

settings are now only in ModelSettingsCard, not duplicated in their old locations

* fix: prevent model dropdown from being clipped by window edge

* add languages explicitly, clean up some ui

* fix: clear bottom progress bar when download is cancelled

The ModelSelector component maintains its own local state for download
progress. When a download was cancelled, the Rust backend would update
its state but never emitted an event to notify the frontend. This caused
the bottom progress bar to remain stuck showing "Downloading X%".

Added model-download-cancelled event emission in Rust and corresponding
listener in ModelSelector to clear progress state on cancellation.

* fix: align model card content to top to prevent floating elements

Changed ModelCard flex alignment from items-center to items-start so
the accuracy/speed bars stay at the top when the card expands (e.g.,
during download with progress bar visible).

* fix: prevent model deletion from interrupting active extractions

Added extracting_models HashSet to track models currently being
extracted. The update_download_status() function now skips cleanup
of .extracting directories for models that are actively extracting,
preventing a race condition where deleting one model would interrupt
another model's extraction process.

* refactor: migrate ModelCard buttons to Button component

Added two new Button variants for common patterns:
- primary-soft: soft/tinted primary buttons (used for download)
- danger-ghost: subtle destructive actions (used for delete/cancel)

Migrated all hardcoded buttons in ModelCard to use the shared Button
component for consistency and maintainability.

* feat: separate downloaded and available models into sections

Split the models list into "Your Models" and "Available to Download"
sections for clearer visual distinction between downloaded and
downloadable models.

Also adds missing translation keys to all locales:
- modelSelector.capabilities.singleLanguage
- modelSelector.capabilities.languageOnly
- settings.models.yourModels
- settings.models.availableModels

* fix: add missing translations after rebase onto main

add post-processing hotkey translations to all 15 locales and
backfill 29 missing keys for korean locale added in main.

* fix: add label to model delete button for clearer destructive state

* check translations as typescript

* format

* better text for dropdown

* wip ui tweaks

* rounded + ui tweaks

* fix download not 0% immediately, ui tweaks

* tweak name

* block for model downloading in onboarding

* small fixes

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
2026-02-08 12:18:22 +08:00

500 lines
19 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"tray": {
"settings": "Ustawienia...",
"checkUpdates": "Sprawdź aktualizacje...",
"copyLastTranscript": "Kopiuj ostatnią transkrypcję",
"quit": "Zamknij",
"cancel": "Anuluj"
},
"sidebar": {
"general": "Ogólne",
"models": "Modele",
"advanced": "Zaawansowane",
"postProcessing": "Postproces",
"history": "Historia",
"debug": "Debugowanie",
"about": "O programie"
},
"onboarding": {
"subtitle": "Aby rozpocząć, wybierz model transkrypcji",
"recommended": "Polecane",
"download": "Pobierz",
"downloading": "Pobieranie...",
"downloadFailed": "Pobieranie nie powiodło się. Spróbuj ponownie.",
"modelCard": {
"accuracy": "dokładność",
"speed": "szybkość"
},
"models": {
"small": {
"name": "Whisper Small",
"description": "Szybki i dość dokładny."
},
"medium": {
"name": "Whisper Medium",
"description": "Dobra dokładność, średnia szybkość"
},
"turbo": {
"name": "Whisper Turbo",
"description": "Zrównoważona dokładność i szybkość."
},
"large": {
"name": "Whisper Large",
"description": "Dobra dokładność, ale wolny."
},
"parakeet-tdt-0.6b-v2": {
"name": "Parakeet V2",
"description": "Tylko angielski. Najlepszy model dla osób mówiących po angielsku."
},
"parakeet-tdt-0.6b-v3": {
"name": "Parakeet V3",
"description": "Szybki i dokładny"
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
}
},
"errors": {
"loadModels": "Nie udało się wczytać dostępnych modeli",
"downloadModel": "Nie udało się pobrać modelu: {{error}}"
},
"permissions": {
"title": "Wymagane uprawnienia",
"description": "Handy potrzebuje kilku uprawnień, aby działać poprawnie.",
"microphone": {
"title": "Dostęp do mikrofonu",
"description": "Wymagany do słyszenia Twojego głosu w celu transkrypcji."
},
"accessibility": {
"title": "Dostęp do dostępności",
"description": "Wymagany do wpisywania transkrybowanego tekstu w Twoich aplikacjach."
},
"grant": "Przyznaj uprawnienie",
"granted": "Przyznano",
"waiting": "Oczekiwanie...",
"allGranted": "Wszystko gotowe!",
"errors": {
"checkFailed": "Nie udało się sprawdzić uprawnień. Spróbuj ponownie.",
"requestFailed": "Nie udało się poprosić o uprawnienie. Spróbuj ponownie."
}
}
},
"modelSelector": {
"active": "Aktywny",
"switching": "Przełączanie...",
"noModelsAvailable": "Brak dostępnych modeli",
"extracting": "Rozpakowywanie {{modelName}}...",
"extractingMultiple": "Rozpakowywanie {{count}} modeli...",
"extractingGeneric": "Rozpakowywanie...",
"downloading": "Pobieranie {{percentage}}%",
"downloadingMultiple": "Pobieranie {{count}} modeli...",
"modelReady": "Model gotowy",
"loading": "Wczytywanie {{modelName}}...",
"loadingGeneric": "Wczytywanie...",
"modelError": "Błąd modelu",
"modelUnloaded": "Model wyładowany",
"noModelDownloadRequired": "Brak modelu wymagane pobranie",
"deleteModel": "Usuń {{modelName}}",
"downloadSpeed": "{{speed}} MB/s",
"capabilities": {
"languageSelection": "Obsługuje wiele języków wejściowych",
"multiLanguage": "Wielojęzyczny",
"translation": "Może tłumaczyć na angielski",
"translate": "Tłumacz na angielski",
"singleLanguage": "Obsługuje tylko ten język",
"languageOnly": "Tylko {{language}}"
},
"cancel": "Anuluj",
"cancelDownload": "Anuluj pobieranie"
},
"settings": {
"modelSettings": {
"title": "Ustawienia {{model}}",
"noSettingsNeeded": "Ten model działa automatycznie bez konieczności konfiguracji."
},
"models": {
"title": "Modele transkrypcji",
"description": "Wybierz model transkrypcji lub pobierz dodatkowe modele. Różne modele oferują różne poziomy dokładności i szybkości.",
"downloaded": "Pobrane",
"available": "Dostępne do pobrania",
"deleteConfirm": "Czy na pewno chcesz usunąć {{modelName}}? Będziesz musiał pobrać go ponownie, aby go użyć.",
"deleteActiveConfirm": "{{modelName}} jest Twoim aktywnym modelem. Usunięcie go zatrzyma transkrypcje, dopóki nie wybierzesz nowego modelu. Czy na pewno chcesz kontynuować?",
"deleteTitle": "Usuń model",
"filters": {
"all": "Wszystkie",
"multiLanguage": "Wielojęzyczne",
"translation": "Tłumaczenie",
"allLanguages": "Wszystkie języki"
},
"noModelsMatch": "Żadne modele nie pasują do tego filtra.",
"yourModels": "Pobrane modele",
"availableModels": "Dostępne do pobrania"
},
"general": {
"title": "Ogólne",
"shortcut": {
"title": "Skróty Handy",
"description": "Skonfiguruj skróty klawiaturowe do uruchamiania nagrywania mowy",
"loading": "Wczytywanie skrótów...",
"none": "Brak skonfigurowanych skrótów",
"notFound": "Nie znaleziono skrótu",
"pressKeys": "Naciśnij klawisze...",
"bindings": {
"transcribe": {
"name": "Skrót transkrypcji",
"description": "Skrót klawiaturowy do nagrywania i transkrypcji głosu."
},
"cancel": {
"name": "Skrót anulowania",
"description": "Skrót klawiaturowy do anulowania bieżącego nagrywania."
},
"transcribe_with_post_process": {
"name": "Skrót postprocessingu",
"description": "Opcjonalnie: Dedykowany skrót klawiszowy, który zawsze stosuje postprocessing AI do transkrypcji."
}
},
"errors": {
"restore": "Nie udało się przywrócić oryginalnego skrótu",
"set": "Nie udało się ustawić skrótu: {{error}}",
"reset": "Nie udało się zresetować skrótu do wartości domyślnej"
}
},
"language": {
"title": "Język",
"description": "Wybierz język rozpoznawania mowy. Opcja Auto automatycznie określi język, a wybór konkretnego języka może poprawić dokładność.",
"descriptionUnsupported": "Model Parakeet automatycznie wykrywa język. Nie jest potrzebny ręczny wybór.",
"searchPlaceholder": "Szukaj języka...",
"noResults": "Nie znaleziono języków",
"auto": "Auto"
},
"pushToTalk": {
"label": "Push To Talk",
"description": "Przytrzymaj, aby nagrywać, puść, aby zatrzymać"
}
},
"sound": {
"title": "Dźwięk",
"microphone": {
"title": "Mikrofon",
"description": "Wybierz preferowane urządzenie mikrofonowe",
"placeholder": "Wybierz mikrofon...",
"loading": "Wczytywanie..."
},
"audioFeedback": {
"label": "Informacja dźwiękowa",
"description": "Odtwarzaj dźwięk przy rozpoczęciu i zakończeniu nagrywania"
},
"outputDevice": {
"title": "Urządzenie wyjściowe",
"description": "Wybierz preferowane urządzenie audio do odtwarzania dźwięków",
"placeholder": "Wybierz urządzenie wyjściowe...",
"loading": "Wczytywanie..."
},
"volume": {
"title": "Głośność",
"description": "Dostosuj głośność dźwięków informacyjnych"
}
},
"advanced": {
"title": "Zaawansowane",
"groups": {
"app": "Aplikacja",
"output": "Wyjście",
"transcription": "Transkrypcja",
"history": "Historia",
"experimental": "Eksperymentalne"
},
"experimentalToggle": {
"label": "Funkcje Eksperymentalne",
"description": "Włącz funkcje eksperymentalne, które są jeszcze w fazie rozwoju."
},
"startHidden": {
"label": "Uruchom ukryty",
"description": "Uruchom w zasobniku systemowym bez otwierania okna."
},
"autostart": {
"label": "Uruchamiaj przy starcie",
"description": "Automatycznie uruchamiaj Handy po zalogowaniu."
},
"overlay": {
"title": "Pozycja nakładki",
"description": "Wyświetlaj wizualną nakładkę podczas nagrywania i transkrypcji. Na Linuxie zalecane 'Brak'.",
"options": {
"none": "Brak",
"bottom": "Dół",
"top": "Góra"
}
},
"pasteMethod": {
"title": "Metoda wklejania",
"description": "Wybierz sposób wstawiania tekstu. Direct: symuluje wpisywanie. None: pomija wklejanie, tylko aktualizuje historię/clipboard.",
"options": {
"clipboard": "Schowek ({{modifier}}+V)",
"clipboardCtrlShiftV": "Schowek (Ctrl+Shift+V)",
"clipboardShiftInsert": "Schowek (Shift+Insert)",
"direct": "Bezpośrednio",
"none": "Brak"
}
},
"clipboardHandling": {
"title": "Obsługa schowka",
"description": "Nie modyfikuj schowka zachowuje jego zawartość. Kopiuj do schowka pozostawia wynik transkrypcji w schowku.",
"options": {
"dontModify": "Nie modyfikuj schowka",
"copyToClipboard": "Kopiuj do schowka"
}
},
"translateToEnglish": {
"label": "Tłumacz na angielski",
"description": "Automatycznie tłumacz mowę z innych języków na angielski podczas transkrypcji.",
"descriptionUnsupported": "Tłumaczenie nie jest obsługiwane przez model {{model}}."
},
"modelUnload": {
"title": "Wyładowanie modelu",
"description": "Automatycznie zwalnia pamięć GPU/CPU po określonym czasie nieużywania",
"options": {
"never": "Nigdy",
"immediately": "Natychmiast",
"min2": "Po 2 minutach",
"min5": "Po 5 minutach",
"min10": "Po 10 minutach",
"min15": "Po 15 minutach",
"hour1": "Po 1 godzinie",
"sec5": "Po 5 sekundach (Debug)"
}
},
"customWords": {
"title": "Własne słowa",
"description": "Dodaj słowa, które często są źle rozpoznawane lub zapisywane podczas transkrypcji. System automatycznie poprawi podobnie brzmiące słowa, aby pasowały do Twojej listy.",
"placeholder": "Dodaj słowo",
"add": "Dodaj",
"remove": "Usuń {{word}}"
}
},
"postProcessing": {
"title": "Postprocess",
"hotkey": {
"title": "Skrót klawiszowy"
},
"api": {
"title": "API (zgodne z OpenAI)",
"provider": {
"title": "Dostawca",
"description": "Wybierz dostawcę zgodnego z OpenAI."
},
"appleIntelligence": {
"title": "Apple Intelligence",
"description": "Działa całkowicie na urządzeniu. Nie wymaga klucza API ani dostępu do sieci.",
"requirements": "Wymaga komputera Mac z Apple Silicon i systemem macOS Tahoe (26.0) lub nowszym. Apple Intelligence musi być włączone w Ustawieniach systemowych.",
"unavailable": "Apple Intelligence nie jest dostępne na tym urządzeniu. Wymaga komputera Mac z Apple Silicon i systemem macOS Tahoe (26.0) lub nowszym z włączonym Apple Intelligence w Ustawieniach systemowych."
},
"baseUrl": {
"title": "Adres bazowy",
"description": "Bazowy adres API dla wybranego dostawcy. Tylko dostawca niestandardowy może być edytowany.",
"placeholder": "https://api.openai.com/v1"
},
"apiKey": {
"title": "Klucz API",
"description": "Klucz API dla wybranego dostawcy.",
"placeholder": "sk-..."
},
"model": {
"title": "Model",
"descriptionApple": "Podaj opcjonalny limit tokenów lub pozostaw domyślne ustawienie urządzenia.",
"descriptionCustom": "Podaj identyfikator modelu wymagany przez Twój niestandardowy endpoint.",
"descriptionDefault": "Wybierz model udostępniony przez wybranego dostawcę.",
"placeholderApple": "Apple Intelligence",
"placeholderWithOptions": "Wyszukaj lub wybierz model",
"placeholderNoOptions": "Wpisz nazwę modelu",
"refreshModels": "Odśwież modele"
}
},
"prompts": {
"title": "Prompt",
"selectedPrompt": {
"title": "Wybrany prompt",
"description": "Wybierz szablon do ulepszania transkrypcji lub utwórz nowy. Użyj ${output} w treści, aby odwołać się do przechwyconej transkrypcji."
},
"noPrompts": "Brak dostępnych promptów",
"selectPrompt": "Wybierz prompt",
"createNew": "Utwórz nowy prompt",
"promptLabel": "Etykieta promptu",
"promptLabelPlaceholder": "Wpisz nazwę promptu",
"promptInstructions": "Instrukcje promptu",
"promptInstructionsPlaceholder": "Wpisz instrukcje do wykonania po transkrypcji. Przykład: Popraw gramatykę i jasność dla następującego tekstu: ${output}",
"promptTip": "Wskazówka: użyj <code>${output}</code>, aby wstawić transkrybowany tekst do promptu.",
"updatePrompt": "Zaktualizuj prompt",
"deletePrompt": "Usuń prompt",
"createPrompt": "Utwórz prompt",
"cancel": "Anuluj",
"selectToEdit": "Wybierz prompt powyżej, aby zobaczyć i edytować jego szczegóły.",
"createFirst": "Kliknij 'Utwórz nowy prompt' powyżej, aby utworzyć pierwszy prompt postprocessingu."
}
},
"history": {
"title": "Historia",
"openFolder": "Otwórz folder nagrań",
"loading": "Wczytywanie historii...",
"empty": "Brak transkrypcji. Rozpocznij nagrywanie, aby zbudować historię!",
"copyToClipboard": "Kopiuj transkrypcję do schowka",
"save": "Zapisz transkrypcję",
"unsave": "Usuń z zapisanych",
"delete": "Usuń wpis",
"deleteError": "Nie udało się usunąć wpisu. Spróbuj ponownie."
},
"debug": {
"title": "Debugowanie",
"logDirectory": {
"title": "Katalog logów",
"description": "Miejsce przechowywania plików logów"
},
"logLevel": {
"title": "Poziom logów",
"description": "Ustaw poziom szczegółowości logowania"
},
"updateChecks": {
"label": "Sprawdzaj aktualizacje",
"description": "Automatycznie sprawdzaj nowe wersje Handy"
},
"soundTheme": {
"label": "Motyw dźwiękowy",
"description": "Wybierz motyw dźwiękowy dla informacji o rozpoczęciu i zakończeniu nagrywania"
},
"wordCorrectionThreshold": {
"title": "Próg korekty słów",
"description": "Czułość dla własnych korekt słów"
},
"historyLimit": {
"title": "Limit historii",
"description": "Maksymalna liczba wpisów w historii",
"entries": "wpisy"
},
"recordingRetention": {
"title": "Automatyczne usuwanie nagrań",
"description": "Automatycznie usuwaj stare nagrania, aby zaoszczędzić miejsce",
"never": "Nigdy",
"preserveLimit": "Zachowaj ostatnie {{count}}",
"days3": "Po 3 dniach",
"weeks2": "Po 2 tygodniach",
"months3": "Po 3 miesiącach",
"placeholder": "Wybierz okres retencji..."
},
"alwaysOnMicrophone": {
"label": "Mikrofon zawsze aktywny",
"description": "Utrzymuj mikrofon aktywny dla szybszej reakcji"
},
"clamshellMicrophone": {
"title": "Mikrofon przy zamkniętej pokrywie",
"description": "Mikrofon używany, gdy pokrywa laptopa jest zamknięta"
},
"postProcessingToggle": {
"label": "Postprocess",
"description": "Włącz AI do ulepszania tekstu po transkrypcji"
},
"muteWhileRecording": {
"label": "Wycisz podczas nagrywania",
"description": "Wycisz dźwięk systemu podczas nagrywania"
},
"appendTrailingSpace": {
"label": "Dodaj spację na końcu",
"description": "Dodaj spację po wklejonej transkrypcji"
},
"keyboardImplementation": {
"title": "Keyboard Implementation",
"description": "Choose the keyboard shortcut backend.",
"bindingsReset": "Keyboard shortcuts were incompatible and reset to defaults"
},
"paths": {
"appData": "Dane aplikacji:",
"models": "Modele:",
"settings": "Ustawienia:"
},
"pasteDelay": {
"title": "Opóźnienie wklejania",
"description": "Opóźnienie przed wysłaniem klawisza wklejania (w milisekundach). Zwiększ, jeśli wklejany jest nieprawidłowy tekst."
}
},
"about": {
"title": "O programie",
"version": {
"title": "Wersja",
"description": "Aktualna wersja Handy"
},
"appDataDirectory": {
"title": "Katalog danych aplikacji",
"description": "Miejsce, gdzie Handy przechowuje swoje dane"
},
"sourceCode": {
"title": "Kod źródłowy",
"description": "Zobacz kod źródłowy i współtwórz",
"button": "Zobacz na GitHub"
},
"supportDevelopment": {
"title": "Wspieraj rozwój",
"description": "Pomóż nam dalej rozwijać Handy",
"button": "Wesprzyj"
},
"acknowledgments": {
"title": "Podziękowania",
"whisper": {
"title": "Whisper.cpp",
"description": "Wydajne wykonywanie modelu rozpoznawania mowy Whisper od OpenAI",
"details": "Handy używa Whisper.cpp do szybkiego, lokalnego przetwarzania mowy na tekst. Dzięki niesamowitej pracy Georgi Gerganova i współtwórców."
}
}
}
},
"footer": {
"downloadingModel": "Pobieranie {{model}}...",
"checkingUpdates": "Sprawdzanie aktualizacji...",
"updateAvailable": "Dostępna aktualizacja: {{version}}",
"updateAvailableShort": "Dostępna aktualizacja",
"upToDate": "Aktualne",
"downloadUpdate": "Pobierz aktualizację",
"restart": "Uruchom ponownie",
"updateCheckingDisabled": "Sprawdzanie aktualizacji wyłączone",
"downloading": "Pobieranie... {{progress}}%",
"installing": "Instalowanie...",
"preparing": "Przygotowywanie...",
"checkForUpdates": "Sprawdź aktualizacje"
},
"common": {
"loading": "Wczytywanie...",
"save": "Zapisz",
"cancel": "Anuluj",
"reset": "Resetuj",
"add": "Dodaj",
"remove": "Usuń",
"delete": "Usuń",
"edit": "Edytuj",
"create": "Utwórz",
"update": "Aktualizuj",
"close": "Zamknij",
"open": "Otwórz",
"default": "Domyślne",
"enabled": "Włączone",
"disabled": "Wyłączone",
"on": "Włącz",
"off": "Wyłącz",
"yes": "Tak",
"no": "Nie",
"noOptionsFound": "Nie znaleziono opcji"
},
"accessibility": {
"permissionsRequired": "Wymagane uprawnienia dostępności",
"permissionsDescription": "Handy potrzebuje uprawnień dostępności, aby wpisywać transkrybowany tekst.",
"openSettings": "Otwórz ustawienia systemowe",
"dismiss": "Zamknij"
},
"errors": {
"loadDirectory": "Błąd wczytywania katalogu: {{error}}"
},
"appLanguage": {
"title": "Język aplikacji",
"description": "Zmień język interfejsu Handy"
},
"overlay": {
"transcribing": "Transkrypcja..."
}
}