mirror of
https://github.com/storytold/craft-launcher.git
synced 2026-10-13 23:08:16 +00:00
Add Polish (Polski) as an interface language. (#138)
* Add a Polish interface - pl.tsv: the full catalog (287 rows), written clean-room from the English labels; plurals use the same one|few|many rule as Russian. - Registered as the seventh language: "Polski" in the picker, locales pl, pl-PL and pl_PL.UTF-8, complete_menus = true so the completeness tests cover it. - tests/polish.rs: the Polish UI test, modeled on the French one. - README and AGENTS updated for the new language. * i18n: add Czech (cs) interface language Czech catalog with every key of the most complete catalog (287 rows), the cs language entry with locale detection (cs-CZ, cs_CZ.UTF-8, ?lang=cs), a Czech plural rule (1 / 2-4 / other) with a unit test, and the README language list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * i18n(pl): use Polish plural rule, so 21 is "21 aplikacji" plural_east_slavic treats 21, 31 and 101 as "one", which is right for Russian but not Polish, where only 1 itself takes the singular. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * i18n(cs): translate "Installed · latest {latest}" (added by #195) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * i18n(pl): translate "Installed · latest {latest}" (added by #195) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Losminek <301412321+Losminek@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
9 files changed
+535
-19
No files matched your search
@@ -76,8 +76,10 @@ colour tokens by name (`theme::Tokens`). Build new UI from `widgets.rs`; never h
|
||||
|
||||
Every user-facing string goes through `crates/ui-egui/src/i18n` (`tl!("…")` for literals, `fmt`
|
||||
for `{placeholders}`, `tn` for counts). English in the code is the lookup key; adding a string
|
||||
means adding its row to every catalog marked `complete_menus` (`ru.tsv`, `zh-CN.tsv`, `de.tsv`),
|
||||
which the i18n tests check. Product and app names (ArtCraft Launcher, Craft App Suite, PhotoCraft…) stay in English.
|
||||
means adding its row to every catalog marked `complete_menus` (`ru.tsv`, `zh-CN.tsv`, `de.tsv`,
|
||||
`fr.tsv`, `pt-BR.tsv`, `pl.tsv`), which the i18n tests check. Translate clean-room from the
|
||||
meaning of the English text, never through another catalog. Product and app names (ArtCraft
|
||||
Launcher, Craft App Suite, PhotoCraft…) stay in English.
|
||||
Chinese is drawn with the system's own CJK font (`crates/ui-egui/src/cjk_font.rs`, desktop only;
|
||||
English where there is none): never bundle a CJK font, they are 10 MB and more.
|
||||
|
||||
|
||||
@@ -85,15 +85,16 @@ The web version shows the same catalog in the browser, with the latest download
|
||||
## Interface languages
|
||||
|
||||
The interface is in English, Brazilian Portuguese (Português (Brasil)), Czech (Čeština), French
|
||||
(Français), German (Deutsch), Russian (Русский), Simplified Chinese (简体中文) or Spanish
|
||||
(Español). **Auto**, the default, follows the system or browser language; **Settings → Language**
|
||||
picks one and switches at once, and the choice is kept between runs. Czech locales (`cs-CZ`,
|
||||
`cs_CZ.UTF-8`…) select Czech, German ones (`de-DE`, `de-AT`, `de-CH`, `de_DE.UTF-8`…) German,
|
||||
French ones (`fr-FR`, `fr-CA`…) French, Spanish ones (`es-ES`, `es-MX`, `es-419`…) Spanish, and
|
||||
Portuguese ones (`pt-BR`, and `pt-PT` too, for now) Brazilian Portuguese. Simplified Chinese locales
|
||||
(`zh-CN`, `zh-SG`, `zh-Hans`, and POSIX forms such as `zh_CN.UTF-8`) select Chinese; Traditional
|
||||
Chinese ones don't. To try a language without changing the setting, start the desktop app with
|
||||
`ARTCRAFT_LAUNCHER_LOCALE=pt-BR`, or add `?lang=ru` to the web address.
|
||||
(Français), German (Deutsch), Polish (Polski), Russian (Русский), Simplified Chinese (简体中文) or
|
||||
Spanish (Español). **Auto**, the default, follows the system or browser language; **Settings →
|
||||
Language** picks one and switches at once, and the choice is kept between runs. Czech locales
|
||||
(`cs-CZ`, `cs_CZ.UTF-8`…) select Czech, German ones (`de-DE`, `de-AT`, `de-CH`, `de_DE.UTF-8`…)
|
||||
German, French ones (`fr-FR`, `fr-CA`…) French, Polish ones (`pl`, `pl-PL`, `pl_PL.UTF-8`) Polish,
|
||||
Spanish ones (`es-ES`, `es-MX`, `es-419`…) Spanish, and Portuguese ones (`pt-BR`, and `pt-PT` too,
|
||||
for now) Brazilian Portuguese. Simplified Chinese locales (`zh-CN`, `zh-SG`, `zh-Hans`, and POSIX
|
||||
forms such as `zh_CN.UTF-8`) select Chinese; Traditional Chinese ones don't. To try a language
|
||||
without changing the setting, start the desktop app with `ARTCRAFT_LAUNCHER_LOCALE=pt-BR`, or add
|
||||
`?lang=ru` to the web address.
|
||||
|
||||
Chinese is drawn with the system's own Chinese font (PingFang on macOS, Microsoft YaHei on
|
||||
Windows, Noto Sans CJK or WenQuanYi on Linux and FreeBSD). Where there is none, and in the web
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//! - `@id` context = keyed by command id (`tr_id`).
|
||||
//! - `@plural` context = plural forms: the English `one|other` key, and the language's forms
|
||||
//! separated by `|` (one form for a language whose nouns don't inflect for number, up to
|
||||
//! three: `one|few|many` for Russian).
|
||||
//! three: `one|few|many` for Russian, Ukrainian and Polish).
|
||||
//! - `@msg` context = a status/error message, or a template whose `{placeholders}` match any text
|
||||
//! (`message`, `msg`).
|
||||
//! - Any other context = disambiguation for `tr_ctx`.
|
||||
|
||||
@@ -7,7 +7,8 @@ use super::detect::system_lang;
|
||||
|
||||
/// One supported UI language.
|
||||
pub struct LangInfo {
|
||||
/// Canonical BCP 47 code (`en`, `ru`, `zh-CN`, `de`, `fr`, `cs`). Also the `interfaceLanguage` value.
|
||||
/// Canonical BCP 47 code (`en`, `ru`, `zh-CN`, `de`, `fr`, `pt-BR`, `es`, `cs`, `pl`). Also the
|
||||
/// `interfaceLanguage` value.
|
||||
pub code: &'static str,
|
||||
/// The language's name in itself, shown in the Preferences dropdown.
|
||||
pub name: &'static str,
|
||||
@@ -19,8 +20,8 @@ pub struct LangInfo {
|
||||
/// Catalog file contents (empty for the built-in English).
|
||||
pub source: &'static str,
|
||||
/// Plural form index for a count (English, German and Spanish: 0 = one, 1 = other; Russian:
|
||||
/// 0 = one, 1 = few, 2 = many; Czech: 0 = one, 1 = few, 2 = other; French: 0 = one for 0 and 1;
|
||||
/// Chinese: always 0).
|
||||
/// 0 = one, 1 = few, 2 = many; Czech: 0 = one, 1 = few, 2 = other; Polish: 0 = one only for 1,
|
||||
/// 1 = few, 2 = many; French: 0 = one for 0 and 1; Chinese: always 0).
|
||||
pub plural: fn(u64) -> usize,
|
||||
/// Number of plural forms the catalog's `@plural` rows carry (checked by tests).
|
||||
pub plural_forms: usize,
|
||||
@@ -65,8 +66,20 @@ pub(super) fn plural_czech(n: u64) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
/// Polish integer counts: only 1 itself is `one` (21 is "21 aplikacji"), 2–4 in the last digit
|
||||
/// (but not 12–14) `few`, everything else `many`.
|
||||
pub(super) fn plural_polish(n: u64) -> usize {
|
||||
if n == 1 {
|
||||
0
|
||||
} else if matches!(n % 10, 2..=4) && !matches!(n % 100, 12..=14) {
|
||||
1
|
||||
} else {
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
/// The registry. English first: it is the fallback and the source language.
|
||||
pub static LANGUAGES: [LangInfo; 8] = [
|
||||
pub static LANGUAGES: [LangInfo; 9] = [
|
||||
LangInfo {
|
||||
code: "en",
|
||||
name: "English",
|
||||
@@ -155,6 +168,17 @@ pub static LANGUAGES: [LangInfo; 8] = [
|
||||
complete_menus: true,
|
||||
catalog: OnceLock::new(),
|
||||
},
|
||||
LangInfo {
|
||||
code: "pl",
|
||||
name: "Polski",
|
||||
english_name: "Polish",
|
||||
cjk: false,
|
||||
source: include_str!("pl.tsv"),
|
||||
plural: plural_polish,
|
||||
plural_forms: 3,
|
||||
complete_menus: true,
|
||||
catalog: OnceLock::new(),
|
||||
},
|
||||
];
|
||||
|
||||
impl LangInfo {
|
||||
@@ -190,6 +214,7 @@ impl Lang {
|
||||
pub const PT_BR: Lang = Lang(&LANGUAGES[5]);
|
||||
pub const ES: Lang = Lang(&LANGUAGES[6]);
|
||||
pub const CS: Lang = Lang(&LANGUAGES[7]);
|
||||
pub const PL: Lang = Lang(&LANGUAGES[8]);
|
||||
|
||||
pub fn code(self) -> &'static str {
|
||||
self.0.code
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
//! 1. Add `xx.tsv` next to `ru.tsv` (copy its header; translate from the *meaning* of the
|
||||
//! English text, clean-room).
|
||||
//! 2. Add one row to [`LANGUAGES`] (code, native name, catalog, plural rule). For a complete
|
||||
//! catalog, cover every UI literal and plural key; the tests enforce that claim.
|
||||
//! catalog, cover every UI literal and plural key; the tests enforce that claim. A translation
|
||||
//! that isn't finished yet starts with `complete_menus: false`: it still shows in
|
||||
//! Preferences, strings without a row fall back to English, and the completeness tests
|
||||
//! skip it until every row is done.
|
||||
//!
|
||||
//! That is all: the Preferences dropdown, the system-locale match and the catalog tests
|
||||
//! (parse, placeholders, plural forms, coverage of every `tl!` literal) pick it up from the
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
# Polish (pl) catalog for ArtCraft Launcher.
|
||||
# Format: context<TAB>source<TAB>translation
|
||||
# Empty context = plain UI string (tl!, t).
|
||||
# @id = command-id keyed (tr_id).
|
||||
# @plural = plural forms: one|other (English) or one|few|many (Polish).
|
||||
# @msg = status/error message template (message, msg).
|
||||
# Other context = disambiguation for tr_ctx.
|
||||
#
|
||||
# Clean-room: written from the meaning of ArtCraft Launcher's English labels in neutral Polish,
|
||||
# using the terms Polish users of creative and system software know. The user is addressed
|
||||
# informally ("twoje", "cię"), as in Polish system interfaces.
|
||||
#
|
||||
# Coverage: the whole interface — every menu string and tl! literal (complete_menus = true).
|
||||
# Left in English on purpose: product name "ArtCraft Launcher" (and its "Launcher" tag), suite
|
||||
# name "Craft App Suite", app names (PhotoCraft, LightCraft, FilmCraft, DesignCraft, VectorCraft,
|
||||
# PdfCraft, EffectCraft, WordCraft, DeckCraft, GridCraft, CADCraft, SoundCraft), "GitHub",
|
||||
# "Discord".
|
||||
# Shortcut keys keep their key-cap names (Shift, Alt, Ctrl, Cmd, Esc).
|
||||
# Trailing "…" (U+2026) must be preserved. Placeholders {name}, {n}, {version}, {count}, {v},
|
||||
# {what}, {unit}, {real}, {e} must appear in translation.
|
||||
|
||||
Launcher Launcher
|
||||
Craft App Suite Craft App Suite
|
||||
Open Source Tools for Creatives, Makers, and Builders Narzędzia open source dla artystów, twórców i konstruktorów
|
||||
Settings Ustawienia
|
||||
Check for updates Sprawdź dostępność aktualizacji
|
||||
Grid Siatka
|
||||
Table Tabela
|
||||
Show apps as cards Wyświetlaj listę jako karty
|
||||
Show apps as a table Wyświetlaj listę jako tabelę
|
||||
All Wszystkie
|
||||
Updates Aktualizacje
|
||||
Not installed Niezainstalowane
|
||||
Search apps Wyszukaj aplikacje
|
||||
Sort Sortowanie
|
||||
Suite order Domyślna kolejność
|
||||
Name Nazwa
|
||||
Inspired by Wzorowane na
|
||||
Status Status
|
||||
Installed version Zainstalowana wersja
|
||||
Latest version Najnowsza wersja
|
||||
Newest release Najnowsze wydanie
|
||||
Discord Discord
|
||||
GitHub GitHub
|
||||
Website Strona
|
||||
Classic apps Klasyczne aplikacje
|
||||
New apps Nowe aplikacje
|
||||
Classic Klasyk
|
||||
NEW NOWE
|
||||
Install Instaluj
|
||||
Update to {v} Zaktualizuj do {v}
|
||||
Open Otwórz
|
||||
Download for {os} Pobierz dla {os}
|
||||
Download Pobierz
|
||||
Coming soon Wkrótce
|
||||
Checking… Sprawdzanie…
|
||||
Not available Niedostępna
|
||||
Offline Offline
|
||||
Downloading {done} of {total} Pobrano {done} z {total}
|
||||
Downloading… Pobieranie…
|
||||
Reconnecting… Wznawianie połączenia…
|
||||
Verifying… Weryfikowanie…
|
||||
Installing, then restarting… Instalowanie a następnie ponowne uruchomienie…
|
||||
Installing… Instalowanie…
|
||||
Removing… Usuwanie…
|
||||
Pause download Wstrzymaj pobieranie
|
||||
Cancel download Anuluj pobieranie
|
||||
Resume download Wznów pobieranie
|
||||
Discard download Usuń pobrane
|
||||
Release notes Informacje o wydaniu
|
||||
Show in Finder Pokaż w Finderze
|
||||
Show in Explorer Pokaż w Eksploratorze plików
|
||||
Show in Files Pokaż w menedżerze plików
|
||||
Reinstall Przeinstaluj
|
||||
Uninstall… Odinstaluj…
|
||||
All releases Wszystkie wydania
|
||||
ArtCraft Launcher {version} is available. Dostępna jest nowa wersja ArtCraft Launcher ({version}).
|
||||
Dismiss Zamknij
|
||||
Update and restart Zaktualizuj i zrestartuj
|
||||
A new version is available. Would you like to relaunch with the updated version? Nowa wersja jest dostępna. Czy chcesz uruchomić ponownie ze zaktualizowaną wersją
|
||||
Later Później
|
||||
What's new Co nowego
|
||||
No notes were published with this release. Dla tego wydania nie opublikowano żadnych notatek.
|
||||
Released {date} Wydano {date}
|
||||
Open on GitHub Otwórz na GitHubie
|
||||
Close Zamknij
|
||||
ArtCraft Launcher {version} ArtCraft Launcher {version}
|
||||
Only when I ask Tylko kiedy zapytam
|
||||
Automatically download and install updates Automatycznie pobieraj i instaluj aktualizacje
|
||||
Notify me when an installed app has an update Powiadom mnie o aktualizacjach dla zainstalowanych aplikacji
|
||||
Include pre-releases (betas and release candidates) Uwzględnij wersje przedpremierowe (beta i wersje kandydujące)
|
||||
Installing on Linux Instalowanie w systemie Linux
|
||||
Install new apps as Instaluj nowe aplikacje jako
|
||||
System package (recommended) Pakiet systemowy (zalecany)
|
||||
Updates always use the format an app was installed with. Aktualizacje zawsze używają formatu, w jakim pierwotnie zainstalowano aplikację.
|
||||
Running in the background Działanie w tle
|
||||
Keep running in the tray when the window is closed Po zamknięciu okna działaj w zasobniku systemowym
|
||||
Show the window on the current desktop Pokaż okno na bieżącym pulpicie
|
||||
Start ArtCraft Launcher when I log in Uruchom ArtCraft Launcher po zalogowaniu
|
||||
Community Społeczność
|
||||
Questions, ideas and news from the ArtCraft team Pytania, pomysły i nowości od zespołu ArtCraft
|
||||
Appearance Motyw
|
||||
Quit ArtCraft Launcher Wyjdź z ArtCraft Launcher
|
||||
Done Gotowe
|
||||
Uninstall {name}? Odinstalować {name}?
|
||||
The app will be moved to the Trash. Your documents and settings stay. Aplikacja zostanie przeniesiona do kosza. Twoje dokumenty i ustawienia pozostaną.
|
||||
Windows will remove it like any installed program. Your documents and settings stay. Windows usunie to jak normalny zainstalowany program. Twoje dokumenty i ustawienia pozostaną.
|
||||
Your system's package manager will remove it, and may ask for your password. Your documents and settings stay. Twój systemowy menedżer pakietów usunie aplikację, może też zapytać cię o hasło. Twoje dokumenty i ustawienia pozostaną.
|
||||
The app will be removed. Your documents and settings stay. Ta aplikacja zostanie usunięta. Twoje dokumenty i ustawienia pozostaną.
|
||||
Uninstall Odinstaluj
|
||||
Cancel Anuluj
|
||||
Checked {ago} Ostatnio sprawdzono {ago}
|
||||
just now przed chwilą
|
||||
yesterday wczoraj
|
||||
{month} {day}, {year} {day} {month} {year}
|
||||
|
||||
Automatically Automatycznie
|
||||
Every Craft app Wszystkie aplikacje Craft
|
||||
Apps on this computer Aplikacje na tym komputerze
|
||||
Installed apps with a newer version Zainstalowane aplikacje z nowszą wersją
|
||||
Apps you can install Aplikacje, które możesz zainstalować
|
||||
Checked {ago} · using {sources} Ostatnio sprawdzono {ago} · przy użyciu {sources}
|
||||
{a} and {b} {a} i {b}
|
||||
Join the Discord Dołącz na Discorda
|
||||
Learn more Więcej
|
||||
Minimize Minimalizuj
|
||||
Maximize Maksymalizuj
|
||||
Restore Przywróć
|
||||
New Nowe
|
||||
OK OK
|
||||
Open link Otwórz link
|
||||
Update Aktualizacja
|
||||
{name} icon Ikona {name}
|
||||
Loading ArtCraft Launcher… Ładowanie ArtCraft Launcher…
|
||||
Cancel update Anuluj aktualizację
|
||||
Stop waiting; the update can be started again later Przerwij oczekiwanie; aktualizację można uruchomić ponownie później
|
||||
Download again Pobierz ponownie
|
||||
Install cancelled Anulowano instalację
|
||||
Install cancelled. The download is kept for the next try. Anulowano instalację. Pobrany plik zostanie zachowany na następną próbę.
|
||||
Update cancelled Anulowano aktualizację
|
||||
Uninstall cancelled Anulowano odinstalowanie
|
||||
Retry install Ponów instalację
|
||||
Retry update to {version} Ponów aktualizację do {version}
|
||||
The download is still here. It's checked again, then installed. Pobrany plik wciąż tu jest. Zostanie sprawdzony ponownie, a następnie zainstalowany.
|
||||
Waiting for another app… Oczekiwanie na inną aplikację…
|
||||
Waiting for other installs… Oczekiwanie na inne instalacje…
|
||||
|
||||
# Package formats offered for download (PackageKind::label)
|
||||
Installer (.msi) Instalator (.msi)
|
||||
Portable (.zip) Wersja przenośna (.zip)
|
||||
Disk image (.dmg) Obraz dysku (.dmg)
|
||||
Debian package (.deb) Pakiet Debiana (.deb)
|
||||
RPM package (.rpm) Pakiet RPM (.rpm)
|
||||
Flatpak bundle Pakiet Flatpak
|
||||
Tarball (.tar.gz) Archiwum (.tar.gz)
|
||||
|
||||
# Contextual: each app's tagline, keyed by app id
|
||||
photocraft Image editing Edycja zdjęć
|
||||
vectorcraft Vector illustration Ilustracja wektorowa
|
||||
filmcraft Video editing, color and sound Montaż wideo, kolor i dźwięk
|
||||
lightcraft Photo library and raw development Biblioteka zdjęć i obróbka RAW
|
||||
pdfcraft Reading, organizing and protecting PDFs Czytanie, porządkowanie i zabezpieczanie plików PDF
|
||||
effectcraft Motion graphics and visual effects Grafika ruchoma i efekty wizualne
|
||||
designcraft Page layout and publishing Skład stron i publikowanie
|
||||
wordcraft Writing and document design Pisanie i projektowanie dokumentów
|
||||
deckcraft Presentations and slide shows Prezentacje i pokazy slajdów
|
||||
gridcraft Spreadsheets and data Arkusze kalkulacyjne i dane
|
||||
cadcraft Computer-aided design and drafting Projektowanie i kreślenie wspomagane komputerowo
|
||||
soundcraft Recording, editing and mixing audio Nagrywanie, edycja i miksowanie dźwięku
|
||||
|
||||
# Contextual: month abbreviations for date rendering
|
||||
month Jan sty
|
||||
month Feb lut
|
||||
month Mar mar
|
||||
month Apr kwi
|
||||
month May maj
|
||||
month Jun cze
|
||||
month Jul lip
|
||||
month Aug sie
|
||||
month Sep wrz
|
||||
month Oct paź
|
||||
month Nov lis
|
||||
month Dec gru
|
||||
Not checked yet Jeszcze nie sprawdzono
|
||||
GitHub's hourly limit was reached; full details return in {min} min Osiągnięto godzinowy limit GitHuba; pełne informacje wrócą za {min} min
|
||||
GitHub limit hit; back in {min} min Limit GitHuba osiągnięty; powrót za {min} min
|
||||
Installing for {platform} Instalowanie dla {platform}
|
||||
Downloads for {platform} Do pobrania dla {platform}
|
||||
No downloads for this system Brak pobrań dla tego systemu
|
||||
Join the ArtCraft community on Discord Dołącz do społeczności ArtCraft na Discordzie
|
||||
ArtCraft on {name} ArtCraft w serwisie {name}
|
||||
Couldn't open {name}: {e} Nie udało się otworzyć {name}: {e}
|
||||
Download cancelled Anulowano pobieranie
|
||||
Available to install Dostępna do instalacji
|
||||
Available Dostępna
|
||||
Installed · up to date Zainstalowana · aktualna
|
||||
Update available Dostępna aktualizacja
|
||||
Installed Zainstalowana
|
||||
installed zainstalowana
|
||||
Not available here Niedostępna w tym systemie
|
||||
Updating… Aktualizowanie…
|
||||
Update paused Aktualizacja wstrzymana
|
||||
Download paused Pobieranie wstrzymane
|
||||
{version} installed → {latest} released {version} zainstalowana → {latest} wydana
|
||||
Version {version} Wersja {version}
|
||||
{installed} installed · latest {latest} {installed} zainstalowana · najnowsza {latest}
|
||||
Installed · latest {latest} Zainstalowana · najnowsza {latest}
|
||||
Version {version} installed Wersja {version} zainstalowana
|
||||
Version {latest} Wersja {latest}
|
||||
No release published yet Nie opublikowano jeszcze wydania
|
||||
ArtCraft Launcher ArtCraft Launcher
|
||||
App Aplikacja
|
||||
Latest Najnowsza
|
||||
Released Wydano
|
||||
Auto Automatycznie
|
||||
Language Język
|
||||
Ascending Rosnąco
|
||||
Descending Malejąco
|
||||
Click to reverse the order Kliknij, aby odwrócić kolejność
|
||||
Click to sort by this column Kliknij, aby posortować według tej kolumny
|
||||
Like {name} Wzorowane na {name}
|
||||
{done} of {total} {done} z {total}
|
||||
Downloading Pobieranie
|
||||
Verifying checksum… Weryfikowanie sumy kontrolnej…
|
||||
Resume Wznów
|
||||
{done} of {total} downloaded Pobrano {done} z {total}
|
||||
{done} downloaded Pobrano {done}
|
||||
Checking for updates… Sprawdzanie aktualizacji…
|
||||
Downloads the new version, replaces this one and opens it again Pobiera nową wersję, zastępuje obecną i uruchamia ją ponownie.
|
||||
Couldn't check for updates: {f} Nie udało się sprawdzić aktualizacji: {f}
|
||||
Website (coming soon) Strona (wkrótce)
|
||||
GitHub repository Repozytorium na GitHubie
|
||||
ArtCraft ArtCraft
|
||||
Update 1 app Zaktualizuj 1 aplikację
|
||||
Update all ({count}) Zaktualizuj wszystkie ({count})
|
||||
⊞ Grid ⊞ Siatka
|
||||
☰ Table ☰ Tabela
|
||||
🔍 Search apps 🔍 Wyszukaj aplikacje
|
||||
{name} {version} {name} {version}
|
||||
Match system Zgodnie z systemem
|
||||
Dark Ciemny
|
||||
Light Jasny
|
||||
Full changelog Pełna lista zmian
|
||||
link link
|
||||
No apps match Brak pasujących aplikacji
|
||||
Open ArtCraft Launcher to update. Otwórz ArtCraft Launcher, aby zaktualizować aplikacje.
|
||||
{name} {v} is available Dostępna jest nowa wersja {name} {v}
|
||||
{count} updates are available Dostępne aktualizacje: {count}
|
||||
These notes weren't fetched (GitHub's request limit was reached). They're on the release page. Nie udało się pobrać tych notatek (osiągnięto limit zapytań GitHuba). Znajdziesz je na stronie wydania.
|
||||
When on, opening the launcher from the menu bar brings its window to the desktop you're on. When off, macOS switches you to the desktop the window was on. Gdy włączone, otwarcie launchera z paska menu przenosi jego okno na bieżący pulpit. Gdy wyłączone, macOS przełącza cię na pulpit, na którym było okno.
|
||||
Couldn't change the login item: {e} Nie udało się zmienić elementu logowania: {e}
|
||||
|
||||
# Contextual: table column headers
|
||||
column App Aplikacja
|
||||
column Installed Zainstalowana
|
||||
column Latest Najnowsza
|
||||
column Released Data wydania
|
||||
|
||||
# Contextual: the filter tab names a group (the status pill says "Installed")
|
||||
filter Installed Zainstalowane
|
||||
|
||||
# Plural forms for Polish (one|few|many)
|
||||
@plural {n} app|{n} apps {n} aplikacja|{n} aplikacje|{n} aplikacji
|
||||
@plural {n} min ago|{n} min ago {n} min temu|{n} min temu|{n} min temu
|
||||
@plural {n} h ago|{n} h ago {n} godz. temu|{n} godz. temu|{n} godz. temu
|
||||
@plural {n} day ago|{n} days ago {n} dzień temu|{n} dni temu|{n} dni temu
|
||||
|
||||
# Message templates (@msg): toasts from the backend. {placeholders} match any text.
|
||||
@msg Couldn't open {name}: {e} Nie udało się otworzyć {name}: {e}
|
||||
@msg Download cancelled Anulowano pobieranie
|
||||
@msg {name} updated to {version} Zaktualizowano {name} do wersji {version}
|
||||
@msg {name} installed: {version} Zainstalowano {name} w wersji {version}
|
||||
@msg {name} updated to {version} (this release publishes no checksum, so only its size was checked) Zaktualizowano {name} do wersji {version} (to wydanie nie zawiera sumy kontrolnej, więc sprawdzono tylko rozmiar)
|
||||
@msg {name} installed: {version} (this release publishes no checksum, so only its size was checked) Zainstalowano {name} w wersji {version} (to wydanie nie zawiera sumy kontrolnej, więc sprawdzono tylko rozmiar)
|
||||
@msg {name} was removed Usunięto {name}
|
||||
@msg {name} is running. Quit it, then try again. {name} jest uruchomiona. Zamknij ją i spróbuj ponownie.
|
||||
|
||||
# Command IDs for menu items (@id)
|
||||
# Format: @id<TAB>command_id<TAB>translation
|
||||
@id app.install Instaluj
|
||||
@id app.update Zaktualizuj do {v}
|
||||
@id app.open Otwórz
|
||||
@id app.download Pobierz dla {os}
|
||||
@id app.reveal Pokaż w Finderze
|
||||
@id app.reinstall Przeinstaluj
|
||||
@id app.uninstall Odinstaluj…
|
||||
@id app.notes Informacje o wydaniu
|
||||
@id app.website Strona
|
||||
@id app.github Repozytorium na GitHubie
|
||||
@id app.releases Wszystkie wydania
|
||||
@id launcher.update Zaktualizuj i zrestartuj
|
||||
@id launcher.download Pobierz
|
||||
@id launcher.notes Co nowego
|
||||
@id launcher.dismiss Zamknij
|
||||
@id settings.open Ustawienia
|
||||
@id settings.quit Wyjdź z ArtCraft Launcher
|
||||
@id view.grid Siatka
|
||||
@id view.table Tabela
|
||||
@id filter.all Wszystkie
|
||||
@id filter.installed Zainstalowane
|
||||
@id filter.updates Aktualizacje
|
||||
@id filter.notinstalled Niezainstalowane
|
||||
@id sort.suite Domyślna kolejność
|
||||
@id sort.name Nazwa
|
||||
@id sort.inspired Wzorowane na
|
||||
@id sort.status Status
|
||||
@id sort.installed Zainstalowana wersja
|
||||
@id sort.latest Najnowsza wersja
|
||||
@id sort.released Najnowsze wydanie
|
||||
@id help.discord Discord
|
||||
@id help.github GitHub
|
||||
@id help.website Strona
|
||||
@id update.check Sprawdź dostępność aktualizacji
|
||||
@id update.check_auto Automatycznie sprawdzaj dostępność aktualizacji
|
||||
@id update.notify Powiadom mnie o aktualizacjach dla zainstalowanych aplikacji
|
||||
@id update.prereleases Uwzględnij wersje przedpremierowe (beta i wersje kandydujące)
|
||||
@id linux.preferred_kind Instaluj nowe aplikacje jako
|
||||
@id tray.close_to_tray Po zamknięciu okna działaj w zasobniku systemowym
|
||||
@id tray.show_on_current_desktop Pokaż okno na bieżącym pulpicie
|
||||
@id tray.login_item Uruchom ArtCraft Launcher po zalogowaniu
|
||||
@id appearance.theme Wygląd
|
||||
|
||||
# Tray (menu bar) menu and tooltip
|
||||
Show ArtCraft Launcher Pokaż ArtCraft Launcher
|
||||
Check for Updates Sprawdź dostępność aktualizacji
|
||||
Visit getartcraft.com Odwiedź getartcraft.com
|
||||
ArtCraft on GitHub ArtCraft na GitHubie
|
||||
Join the ArtCraft Discord Dołącz do Discorda ArtCraft
|
||||
@plural ArtCraft Launcher · {n} update available|ArtCraft Launcher · {n} updates available ArtCraft Launcher · {n} dostępna aktualizacja|ArtCraft Launcher · {n} dostępne aktualizacje|ArtCraft Launcher · {n} dostępnych aktualizacji
|
||||
|
Can't render this file because it contains an unexpected character in line 11 and column 15.
|
@@ -4,7 +4,7 @@
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
|
||||
use super::catalog::{Catalog, unescape};
|
||||
use super::lang::{plural_czech, plural_east_slavic};
|
||||
use super::lang::{plural_czech, plural_east_slavic, plural_polish};
|
||||
use super::{LANGUAGES, Lang, LangInfo, lang_from_tag, message, tr, trn};
|
||||
|
||||
/// Each catalog's rows as (line number, context, source, translation), split exactly as the
|
||||
@@ -222,6 +222,25 @@ fn czech_plural_rule_works() {
|
||||
assert_eq!(trn(Lang::CS, 5, "{n} app", "{n} apps"), "5 aplikací");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn polish_plural_rule_works() {
|
||||
// Polish says "one" only for 1 itself: 21, 31 and 101 take "many", unlike Russian.
|
||||
assert_eq!(plural_polish(1), 0);
|
||||
for n in [2, 3, 4, 22, 23, 24, 102, 122] {
|
||||
assert_eq!(plural_polish(n), 1, "{n}");
|
||||
}
|
||||
for n in [0, 5, 11, 12, 13, 14, 15, 21, 25, 31, 100, 101, 111, 112] {
|
||||
assert_eq!(plural_polish(n), 2, "{n}");
|
||||
}
|
||||
assert_eq!(trn(Lang::PL, 1, "{n} app", "{n} apps"), "1 aplikacja");
|
||||
assert_eq!(trn(Lang::PL, 3, "{n} app", "{n} apps"), "3 aplikacje");
|
||||
assert_eq!(trn(Lang::PL, 22, "{n} app", "{n} apps"), "22 aplikacje");
|
||||
assert_eq!(trn(Lang::PL, 5, "{n} app", "{n} apps"), "5 aplikacji");
|
||||
assert_eq!(trn(Lang::PL, 21, "{n} app", "{n} apps"), "21 aplikacji");
|
||||
// A key the Polish catalog doesn't carry falls back to the English forms.
|
||||
assert_eq!(trn(Lang::PL, 3, "{n} unknown item", "{n} unknown items"), "3 unknown items");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn untranslated_plurals_fall_back_to_english_by_count() {
|
||||
// Russian's rule says "one" for 21, but English says "other".
|
||||
@@ -297,6 +316,14 @@ fn spanish_locales_and_plurals_work() {
|
||||
assert_eq!(message(Lang::ES, "PhotoCraft updated to 0.5.0"), "PhotoCraft actualizada a 0.5.0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn polish_locales_resolve() {
|
||||
for tag in ["pl", "pl-PL", "pl_PL.UTF-8", "PL_pl"] {
|
||||
assert_eq!(lang_from_tag(tag), Some(Lang::PL), "{tag}");
|
||||
}
|
||||
assert_eq!(super::detect::first_supported(["xx-XX", "pl-PL", "en-US"]), Some(Lang::PL));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simplified_chinese_locales_respect_the_script() {
|
||||
for tag in ["zh", "zh-CN", "zh_CN.UTF-8", "zh-SG", "zh-Hans", "zh-Hans-CN", "zh-Hans-HK", "ZH_cn"] {
|
||||
|
||||
@@ -88,7 +88,7 @@ pub struct Settings {
|
||||
pub sort_descending: bool,
|
||||
pub theme: ThemeChoice,
|
||||
/// Interface language: `auto` (follow the system) or a language code from the registry
|
||||
/// (`en`, `ru`, `zh-CN`, `de`).
|
||||
/// (`en`, `ru`, `zh-CN`, `de`, `fr`, `pt-BR`, `pl`).
|
||||
pub language: String,
|
||||
/// Closing the window keeps the launcher in the tray (menu bar) instead of quitting.
|
||||
pub close_to_tray: bool,
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
//! The Polish UI, in its own test binary: the UI language is process-wide, so it can't share one
|
||||
//! with the English UI tests. `ARTCRAFT_LAUNCHER_SNAPSHOTS=<dir>` also saves screenshots (run with
|
||||
//! `-- --test-threads=1`, see `ui.rs`).
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use artcraft_launcher_core::protocol::{Backend, Capabilities, Command, Event, JobPhase, LatestRelease, Origin, Source};
|
||||
use artcraft_launcher_core::release::{Asset, Release};
|
||||
use artcraft_launcher_core::status::InstallSource;
|
||||
use artcraft_launcher_core::{Arch, Installed, Os, Platform, SUITE, version};
|
||||
use artcraft_launcher_ui_egui::settings::ViewMode;
|
||||
use artcraft_launcher_ui_egui::{Host, LauncherUi, Settings};
|
||||
use egui_kittest::Harness;
|
||||
use egui_kittest::kittest::Queryable;
|
||||
|
||||
const NOW: i64 = 1_791_500_000;
|
||||
|
||||
struct Fake {
|
||||
events: Vec<Event>,
|
||||
clock: Rc<Cell<i64>>,
|
||||
}
|
||||
|
||||
impl Backend for Fake {
|
||||
fn send(&mut self, _command: Command) {}
|
||||
fn poll(&mut self) -> Vec<Event> {
|
||||
std::mem::take(&mut self.events)
|
||||
}
|
||||
fn capabilities(&self) -> Capabilities {
|
||||
Capabilities { manage_apps: true, reveal_label: "Show in Finder", self_update: true }
|
||||
}
|
||||
fn platform(&self) -> Option<Platform> {
|
||||
Some(Platform { os: Os::MacOs, arch: Arch::Arm64 })
|
||||
}
|
||||
fn now(&self) -> i64 {
|
||||
self.clock.get()
|
||||
}
|
||||
}
|
||||
|
||||
struct NoHost;
|
||||
impl Host for NoHost {}
|
||||
|
||||
fn release(id: &str, v: &str, at: i64) -> Release {
|
||||
let name = format!("{id}-{v}-macos-universal.dmg");
|
||||
Release {
|
||||
tag: format!("v{v}"),
|
||||
version: version::parse(v),
|
||||
name: format!("v{v}"),
|
||||
published_at: Some(at),
|
||||
html_url: format!("https://github.com/storytold/{id}/releases/tag/v{v}"),
|
||||
notes: String::new(),
|
||||
prerelease: false,
|
||||
assets: vec![Asset {
|
||||
name: name.clone(),
|
||||
size: 150 << 20,
|
||||
url: format!("https://github.com/storytold/{id}/releases/download/v{v}/{name}"),
|
||||
sha256: None,
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
fn events() -> Vec<Event> {
|
||||
let mut ev = Vec::new();
|
||||
for (i, app) in SUITE.iter().enumerate() {
|
||||
let latest = LatestRelease::Found(release(app.id, "0.5.0", NOW - 40 * 86_400 - i as i64 * 600));
|
||||
ev.push(Event::Latest { app: app.id.into(), latest, from: Origin::ArtCraftApi });
|
||||
let installed = matches!(app.id, "photocraft" | "lightcraft").then(|| Installed {
|
||||
version: version::parse(if app.id == "photocraft" { "0.4.1" } else { "0.5.0" }),
|
||||
source: InstallSource::MacApp,
|
||||
location: format!("/Applications/{}.app", app.name),
|
||||
package: None,
|
||||
});
|
||||
ev.push(Event::Detected { app: app.id.into(), installed });
|
||||
}
|
||||
ev.push(Event::Progress { app: "filmcraft".into(), phase: JobPhase::Verifying });
|
||||
ev.push(Event::CheckFinished { at: NOW - 180, source: Source::Feed, rate_limited_until: None });
|
||||
// A backend message, translated through its `@msg` template where it's shown.
|
||||
ev.push(Event::JobFinished { app: "lightcraft".into(), result: Ok("LightCraft updated to 0.5.0".into()) });
|
||||
ev
|
||||
}
|
||||
|
||||
fn harness(view: ViewMode) -> Harness<'static, Option<LauncherUi>> {
|
||||
artcraft_launcher_ui_egui::i18n::set_test_lang(artcraft_launcher_ui_egui::i18n::Lang::EN);
|
||||
let mut backend = Some(Fake { events: events(), clock: Rc::new(Cell::new(NOW)) });
|
||||
let settings =
|
||||
Settings { view, notify: false, language: "pl".into(), theme: artcraft_launcher_ui_egui::theme::ThemeChoice::Dark, ..Settings::default() };
|
||||
Harness::builder().with_size(egui::vec2(1180.0, 900.0)).with_theme(egui::Theme::Dark).build_ui_state(
|
||||
move |ui, state: &mut Option<LauncherUi>| {
|
||||
if state.is_none()
|
||||
&& let Some(b) = backend.take()
|
||||
{
|
||||
*state = Some(LauncherUi::new(ui.ctx(), Box::new(b), settings.clone()));
|
||||
}
|
||||
if let Some(l) = state.as_mut() {
|
||||
l.logic(&ui.ctx().clone(), &mut NoHost);
|
||||
l.ui(ui, &mut NoHost);
|
||||
}
|
||||
},
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
fn snapshot(h: &mut Harness<'_, Option<LauncherUi>>, name: &str) {
|
||||
let Some(dir) = std::env::var_os("ARTCRAFT_LAUNCHER_SNAPSHOTS") else { return };
|
||||
let img = h.render().unwrap();
|
||||
img.save(std::path::Path::new(&dir).join(format!("{name}.png"))).unwrap();
|
||||
}
|
||||
|
||||
// One test: the UI language is process-wide.
|
||||
#[test]
|
||||
fn polish_ui_translates_labels_dates_and_messages() {
|
||||
let mut h = harness(ViewMode::Grid);
|
||||
h.run_steps(8);
|
||||
snapshot(&mut h, "grid-pl-dark");
|
||||
// Product names stay in English.
|
||||
h.get_by_label("Launcher");
|
||||
h.get_by_label("Craft App Suite");
|
||||
h.get_by_label("Edycja zdjęć");
|
||||
h.get_by_label("Zaktualizuj do 0.5.0");
|
||||
h.get_by_label_contains("Weryfikowanie sumy kontrolnej…");
|
||||
h.get_by_label_contains("Ostatnio sprawdzono 3 min temu · przy użyciu ArtCraft API");
|
||||
h.get_by_label("Zaktualizowano LightCraft do wersji 0.5.0");
|
||||
|
||||
let mut table = harness(ViewMode::Table);
|
||||
table.run_steps(8);
|
||||
snapshot(&mut table, "table-pl-dark");
|
||||
table.get_by_label("Zainstalowana");
|
||||
assert!(table.query_all_by_label_contains("sie 2026").count() >= 1);
|
||||
}
|
||||
Reference in new issue
Block a user