diff --git a/README.md b/README.md index 0b14ccc..cab0d9a 100644 --- a/README.md +++ b/README.md @@ -337,11 +337,20 @@ sudo pacman -S rhvoice-voice-evgeniy-eng # BigLinux repositories only: sudo pacman -S biglinux-kokoro-tts # Kokoro neural voices -sudo pacman -S piper-voices-pt-BR # Brazilian Portuguese Piper voices +sudo pacman -S piper-voices-pt-br # Brazilian Portuguese Piper voices (stable) +sudo pacman -S piper-voices-pt-BR # the same voices, as named in biglinux-testing ``` Piper voices can also be downloaded in the Voice Manager. +The Piper voice packages are spelled differently in BigLinux stable +(`piper-voices-pt-br`) and testing (`piper-voices-pt-BR`); both ship the same +files, so only one can be installed. When Piper is selected, the app looks +for both spellings and never offers the second one if either is installed. +Only when neither is in the repositories does it fall back to the AUR. It +builds the AUR package as you, never as root, with `pamac build` when pamac's +AUR support is on, or with `paru`/`yay`, and it says so before installing. + ### Uninstall ```bash @@ -406,7 +415,7 @@ All from the official Arch/Manjaro repositories. | `rhvoice-voice-evgeniy-eng` | official | RHVoice English voice | | `xclip` | official | X11 selection capture when `xsel` is missing | | `biglinux-kokoro-tts` | BigLinux | Kokoro neural voices (`koko`, model, base voices) | -| `piper-voices-pt-BR` | BigLinux | Brazilian Portuguese Piper voices, preinstalled | +| `piper-voices-pt-br` | BigLinux | Brazilian Portuguese Piper voices, preinstalled (`piper-voices-pt-BR` in testing) | | `piper-tts-bin` | BigLinux | Piper command-line fallback (the native engine needs only voices) | | `rhvoice-brazilian-portuguese-complementary-dict-biglinux` | BigLinux | Extra pronunciation dictionary for RHVoice | @@ -755,7 +764,7 @@ The engines and libraries it uses keep their own licenses, among them: | espeak-ng, RHVoice | GPL-3.0-or-later | | RHVoice voice Letícia F123 | CC-BY-SA-4.0 | | Kokoro model (`biglinux-kokoro-tts`) | Apache-2.0 | -| Piper voices (`piper-voices-pt-BR`) | MIT | +| Piper voices (`piper-voices-pt-br`) | MIT | | ONNX Runtime | MIT | | GTK 4, libadwaita, PyGObject, GStreamer | LGPL-2.1-or-later | | PySide6 / Qt 6 | LGPL-3.0 (or GPL-3.0) | diff --git a/locale/bg.po b/locale/bg.po index d91d48a..8a221c8 100644 --- a/locale/bg.po +++ b/locale/bg.po @@ -1295,3 +1295,10 @@ msgstr "Това ще върне всички настройки към първ #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Възстановяване" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Пакетите, отбелязани с AUR, не са във вашите хранилища: те идват от Arch User Repository, поддържат се от общността и се компилират на този компютър, което отнема повече време." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} не можа да бъде компилиран от AUR. Вижте подробностите." diff --git a/locale/ca.po b/locale/ca.po index 9b67946..9f1fddc 100644 --- a/locale/ca.po +++ b/locale/ca.po @@ -1677,3 +1677,12 @@ msgstr "Això retornarà tots els ajustaments als seus valors originals per defe #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Restaura" + +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Els paquets marcats amb AUR no són als vostres repositoris: provenen de l'Arch User Repository, els manté la comunitat i es compilen en aquest ordinador, cosa que triga més." + +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "No s'ha pogut compilar {packages} des de l'AUR. Vegeu els detalls." diff --git a/locale/cs.po b/locale/cs.po index b60a740..eb88de5 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -1295,3 +1295,10 @@ msgstr "Tímto se vrátí všechny úpravy na původní výchozí hodnoty." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Obnovit" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Balíčky označené AUR nejsou ve vašich repozitářích: pocházejí z Arch User Repository, udržuje je komunita a sestavují se na tomto počítači, což trvá déle." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} se nepodařilo sestavit z AUR. Podívejte se na podrobnosti." diff --git a/locale/da.po b/locale/da.po index 6615943..88f56fb 100644 --- a/locale/da.po +++ b/locale/da.po @@ -1295,3 +1295,10 @@ msgstr "Dette vil gendanne alle justeringer til deres oprindelige standardværdi #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Gendan" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Pakker markeret med AUR findes ikke i dine arkiver: de kommer fra Arch User Repository, vedligeholdes af fællesskabet og bygges på denne computer, hvilket tager længere tid." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} kunne ikke bygges fra AUR. Se detaljerne." diff --git a/locale/de.po b/locale/de.po index 98fde0c..2307b86 100644 --- a/locale/de.po +++ b/locale/de.po @@ -1303,3 +1303,10 @@ msgstr "Dies setzt alle Einstellungen auf die ursprünglichen Standardwerte zur #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Wiederherstellen" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Mit AUR markierte Pakete sind nicht in Ihren Paketquellen: Sie stammen aus dem Arch User Repository, werden von der Community gepflegt und auf diesem Computer gebaut, was länger dauert." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} konnte nicht aus dem AUR gebaut werden. Siehe Details." diff --git a/locale/el.po b/locale/el.po index 1e730e1..80cade2 100644 --- a/locale/el.po +++ b/locale/el.po @@ -1297,3 +1297,10 @@ msgstr "Αυτό θα επαναφέρει όλες τις ρυθμίσεις σ #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Επαναφορά" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Τα πακέτα με την ένδειξη AUR δεν βρίσκονται στα αποθετήριά σας: προέρχονται από το Arch User Repository, συντηρούνται από την κοινότητα και μεταγλωττίζονται σε αυτόν τον υπολογιστή, κάτι που διαρκεί περισσότερο." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "Δεν ήταν δυνατή η μεταγλώττιση του {packages} από το AUR. Δείτε τις λεπτομέρειες." diff --git a/locale/en.po b/locale/en.po index 3c8a815..408adf3 100644 --- a/locale/en.po +++ b/locale/en.po @@ -2114,3 +2114,12 @@ msgstr "This will return all adjustments to their original defaults." # File: tts-biglinux/usr/share/biglinux/tts-biglinux/window.py, line: 465 msgid "Restore" msgstr "Restore" + +# File: tts-biglinux/usr/share/biglinux/tts-biglinux/ui/main_view.py, line: 1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." + +# File: tts-biglinux/usr/share/biglinux/tts-biglinux/services/package_installer.py, line: 252 +# File: tts-biglinux/usr/share/biglinux/tts-biglinux/services/package_installer.py, line: 265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} could not be built from the AUR. See the details." diff --git a/locale/es.po b/locale/es.po index 1951981..1fda8fc 100644 --- a/locale/es.po +++ b/locale/es.po @@ -1303,3 +1303,10 @@ msgstr "Esto devolverá todos los ajustes a sus valores originales." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Restaurar" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Los paquetes marcados con AUR no están en sus repositorios: provienen del Arch User Repository, los mantiene la comunidad y se compilan en este equipo, lo que tarda más." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "No se pudo compilar {packages} desde el AUR. Consulte los detalles." diff --git a/locale/et.po b/locale/et.po index 7398469..26214cd 100644 --- a/locale/et.po +++ b/locale/et.po @@ -1295,3 +1295,10 @@ msgstr "See taastab kõik kohandused algsete vaikeseadeteni." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Taasta" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "AUR-iga märgitud pakette pole teie hoidlates: need pärinevad Arch User Repositoryst, neid haldab kogukond ja need ehitatakse selles arvutis, mis võtab kauem aega." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "Paketti {packages} ei õnnestunud AUR-ist ehitada. Vaadake üksikasju." diff --git a/locale/fi.po b/locale/fi.po index 11e324f..5454e77 100644 --- a/locale/fi.po +++ b/locale/fi.po @@ -1295,3 +1295,10 @@ msgstr "Tämä palauttaa kaikki säädöt alkuperäisiin oletusarvoihinsa." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Palauta" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "AUR-merkityt paketit eivät ole ohjelmistolähteissäsi: ne tulevat Arch User Repositorysta, yhteisö ylläpitää niitä ja ne käännetään tällä tietokoneella, mikä kestää kauemmin." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "Pakettia {packages} ei voitu kääntää AUR:sta. Katso lisätiedot." diff --git a/locale/fr.po b/locale/fr.po index 9a7e808..7d074fc 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -1303,3 +1303,10 @@ msgstr "Cela retournera tous les ajustements à leurs valeurs par défaut origin #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Restaurer" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Les paquets marqués AUR ne sont pas dans vos dépôts : ils proviennent de l'Arch User Repository, sont maintenus par la communauté et sont compilés sur cet ordinateur, ce qui prend plus de temps." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} n'a pas pu être compilé depuis l'AUR. Consultez les détails." diff --git a/locale/he.po b/locale/he.po index aeff71c..0b19bcd 100644 --- a/locale/he.po +++ b/locale/he.po @@ -1295,3 +1295,10 @@ msgstr "פעולה זו תחזיר את כל ההתאמות לברירות המ #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "שחזור" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "חבילות המסומנות ב-AUR אינן במאגרים שלך: הן מגיעות מ-Arch User Repository, מתוחזקות על ידי הקהילה ונבנות במחשב זה, מה שלוקח יותר זמן." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "לא ניתן היה לבנות את {packages} מ-AUR. ראו את הפרטים." diff --git a/locale/hr.po b/locale/hr.po index bc22759..351c46a 100644 --- a/locale/hr.po +++ b/locale/hr.po @@ -1297,3 +1297,10 @@ msgstr "Ovo će vratiti sve prilagodbe na izvorne zadane vrijednosti." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Vrati" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Paketi označeni s AUR nisu u vašim repozitorijima: dolaze iz Arch User Repositoryja, održava ih zajednica i grade se na ovom računalu, što traje dulje." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} nije moguće izgraditi iz AUR-a. Pogledajte pojedinosti." diff --git a/locale/hu.po b/locale/hu.po index 3072b56..ebf6671 100644 --- a/locale/hu.po +++ b/locale/hu.po @@ -1295,3 +1295,10 @@ msgstr "Ez visszaállítja az összes beállítást az eredeti alapértékekre." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Visszaállítás" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Az AUR jelölésű csomagok nincsenek a tárolóidban: az Arch User Repositoryból származnak, a közösség tartja karban őket, és ezen a számítógépen fordítódnak, ami tovább tart." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "A(z) {packages} nem fordítható le az AUR-ból. Lásd a részleteket." diff --git a/locale/is.po b/locale/is.po index 5007716..8eb1200 100644 --- a/locale/is.po +++ b/locale/is.po @@ -1295,3 +1295,10 @@ msgstr "Þetta mun færa allar stillingar til baka í upprunaleg sjálfgildi." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Endurstilla" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Pakkar merktir AUR eru ekki í hugbúnaðarsöfnunum þínum: þeir koma úr Arch User Repository, samfélagið viðheldur þeim og þeir eru byggðir á þessari tölvu, sem tekur lengri tíma." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "Ekki tókst að byggja {packages} úr AUR. Sjá nánar." diff --git a/locale/it.po b/locale/it.po index 07a404d..04f6f1d 100644 --- a/locale/it.po +++ b/locale/it.po @@ -1303,3 +1303,10 @@ msgstr "Tutte le regolazioni torneranno ai valori predefiniti originali." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Ripristina" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "I pacchetti contrassegnati con AUR non sono nei tuoi repository: provengono dall'Arch User Repository, sono mantenuti dalla comunità e vengono compilati su questo computer, il che richiede più tempo." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "Impossibile compilare {packages} dall'AUR. Vedi i dettagli." diff --git a/locale/ja.po b/locale/ja.po index c3db1d2..4b81427 100644 --- a/locale/ja.po +++ b/locale/ja.po @@ -1295,3 +1295,10 @@ msgstr "すべての設定を元のデフォルト値に戻します。" #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "復元" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "AUR と表示されたパッケージはリポジトリにありません。Arch User Repository から取得され、コミュニティが管理しており、このコンピューターでビルドされるため時間がかかります。" +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} を AUR からビルドできませんでした。詳細を確認してください。" diff --git a/locale/ko.po b/locale/ko.po index 7f6f30e..17e7538 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -1295,3 +1295,10 @@ msgstr "모든 조정이 원래 기본값으로 돌아갑니다." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "복원" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "AUR로 표시된 패키지는 저장소에 없습니다. Arch User Repository에서 제공되며, 커뮤니티가 관리하고 이 컴퓨터에서 빌드되므로 시간이 더 걸립니다." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "AUR에서 {packages}을(를) 빌드할 수 없습니다. 세부 정보를 확인하세요." diff --git a/locale/nl.po b/locale/nl.po index 481a26c..43077f4 100644 --- a/locale/nl.po +++ b/locale/nl.po @@ -1297,3 +1297,10 @@ msgstr "Dit zal alle aanpassingen terugzetten naar de oorspronkelijke standaardw #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Herstellen" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Pakketten gemarkeerd met AUR staan niet in je pakketbronnen: ze komen uit de Arch User Repository, worden door de gemeenschap onderhouden en op deze computer gebouwd, wat langer duurt." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} kon niet vanuit de AUR worden gebouwd. Zie de details." diff --git a/locale/no.po b/locale/no.po index 5952586..da7239c 100644 --- a/locale/no.po +++ b/locale/no.po @@ -1295,3 +1295,10 @@ msgstr "Dette vil tilbakestille alle justeringer til de opprinnelige standardver #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Gjenopprett" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Pakker merket AUR finnes ikke i pakkebrønnene dine: de kommer fra Arch User Repository, vedlikeholdes av fellesskapet og bygges på denne datamaskinen, noe som tar lengre tid." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} kunne ikke bygges fra AUR. Se detaljene." diff --git a/locale/pl.po b/locale/pl.po index bdccd09..ed35e9a 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -1295,3 +1295,10 @@ msgstr "Spowoduje to przywrócenie wszystkich ustawień do wartości domyślnych #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Przywróć" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Pakiety oznaczone jako AUR nie znajdują się w Twoich repozytoriach: pochodzą z Arch User Repository, są utrzymywane przez społeczność i budowane na tym komputerze, co trwa dłużej." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "Nie udało się zbudować {packages} z AUR. Zobacz szczegóły." diff --git a/locale/pt-BR.po b/locale/pt-BR.po index 6e74972..eb07e70 100644 --- a/locale/pt-BR.po +++ b/locale/pt-BR.po @@ -1669,3 +1669,12 @@ msgstr "Isso retornará todos os ajustes para os seus padrões originais." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Restaurar" + +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Os pacotes marcados com AUR não estão nos seus repositórios: vêm do Arch User Repository, são mantidos pela comunidade e são compilados neste computador, o que demora mais." + +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "Não foi possível compilar {packages} a partir do AUR. Veja os detalhes." diff --git a/locale/pt.po b/locale/pt.po index 7edec4c..371cc33 100644 --- a/locale/pt.po +++ b/locale/pt.po @@ -1295,3 +1295,10 @@ msgstr "Isto irá repor todos os ajustes para as predefinições originais." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Restaurar" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Os pacotes marcados com AUR não estão nos seus repositórios: vêm do Arch User Repository, são mantidos pela comunidade e são compilados neste computador, o que demora mais tempo." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "Não foi possível compilar {packages} a partir do AUR. Consulte os detalhes." diff --git a/locale/ro.po b/locale/ro.po index cbe85f3..4e0edf9 100644 --- a/locale/ro.po +++ b/locale/ro.po @@ -1295,3 +1295,10 @@ msgstr "Aceasta va readuce toate ajustările la valorile implicite originale." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Restabilește" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Pachetele marcate cu AUR nu se află în depozitele tale: provin din Arch User Repository, sunt întreținute de comunitate și sunt compilate pe acest calculator, ceea ce durează mai mult." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} nu a putut fi compilat din AUR. Vezi detaliile." diff --git a/locale/ru.po b/locale/ru.po index d7107ef..8fb9303 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -1303,3 +1303,10 @@ msgstr "Все настройки будут возвращены к значе #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Сбросить" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Пакеты с пометкой AUR отсутствуют в ваших репозиториях: они берутся из Arch User Repository, поддерживаются сообществом и собираются на этом компьютере, что занимает больше времени." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "Не удалось собрать {packages} из AUR. См. подробности." diff --git a/locale/sk.po b/locale/sk.po index dfd01cc..e586253 100644 --- a/locale/sk.po +++ b/locale/sk.po @@ -1295,3 +1295,10 @@ msgstr "Toto vráti všetky úpravy na pôvodné predvolené hodnoty." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Obnoviť" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Balíky označené AUR nie sú vo vašich repozitároch: pochádzajú z Arch User Repository, udržiava ich komunita a zostavujú sa na tomto počítači, čo trvá dlhšie." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} sa nepodarilo zostaviť z AUR. Pozrite si podrobnosti." diff --git a/locale/sv.po b/locale/sv.po index 3e288cb..f13115f 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -1295,3 +1295,10 @@ msgstr "Detta kommer att återställa alla justeringar till sina ursprungliga st #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Återställ" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Paket märkta med AUR finns inte i dina förråd: de kommer från Arch User Repository, underhålls av gemenskapen och byggs på den här datorn, vilket tar längre tid." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} kunde inte byggas från AUR. Se detaljerna." diff --git a/locale/tr.po b/locale/tr.po index 1c10aef..d3a2d41 100644 --- a/locale/tr.po +++ b/locale/tr.po @@ -1295,3 +1295,10 @@ msgstr "Bu, tüm ayarları orijinal varsayılan değerlerine döndürecektir." #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Geri yükle" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "AUR olarak işaretlenen paketler depolarınızda yok: Arch User Repository'den gelir, topluluk tarafından bakımı yapılır ve bu bilgisayarda derlenir; bu daha uzun sürer." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "{packages} AUR'dan derlenemedi. Ayrıntılara bakın." diff --git a/locale/tts-biglinux.pot b/locale/tts-biglinux.pot index cfeb348..da9ecdb 100644 --- a/locale/tts-biglinux.pot +++ b/locale/tts-biglinux.pot @@ -2112,3 +2112,14 @@ msgstr "" # File: tts-biglinux/usr/share/biglinux/tts-biglinux/window.py, line: 465 msgid "Restore" msgstr "" + +# +# File: tts-biglinux/usr/share/biglinux/tts-biglinux/ui/main_view.py, line: 1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "" + +# +# File: tts-biglinux/usr/share/biglinux/tts-biglinux/services/package_installer.py, line: 252 +# File: tts-biglinux/usr/share/biglinux/tts-biglinux/services/package_installer.py, line: 265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "" diff --git a/locale/uk.po b/locale/uk.po index f640082..105cb7d 100644 --- a/locale/uk.po +++ b/locale/uk.po @@ -1295,3 +1295,10 @@ msgstr "Це поверне всі налаштування до початко #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "Відновити" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "Пакунки з позначкою AUR відсутні у ваших репозиторіях: вони надходять з Arch User Repository, підтримуються спільнотою та збираються на цьому комп'ютері, що триває довше." +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "Не вдалося зібрати {packages} з AUR. Перегляньте подробиці." diff --git a/locale/zh.po b/locale/zh.po index d79d87c..1ca8c0c 100644 --- a/locale/zh.po +++ b/locale/zh.po @@ -1295,3 +1295,10 @@ msgstr "这将把所有调整恢复为原始默认值。" #: usr/share/biglinux/tts-biglinux/window.py:465 msgid "Restore" msgstr "恢复" +#: usr/share/biglinux/tts-biglinux/ui/main_view.py:1442 +msgid "Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer." +msgstr "标记为 AUR 的软件包不在您的软件源中:它们来自 Arch User Repository,由社区维护,并在此计算机上构建,耗时更长。" +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:252 +#: usr/share/biglinux/tts-biglinux/services/package_installer.py:265 +msgid "{packages} could not be built from the AUR. See the details." +msgstr "无法从 AUR 构建 {packages}。请查看详细信息。" diff --git a/pkgbuild/PKGBUILD b/pkgbuild/PKGBUILD index b4d1066..a174b21 100644 --- a/pkgbuild/PKGBUILD +++ b/pkgbuild/PKGBUILD @@ -7,7 +7,7 @@ pkgname=tts-biglinux # vercmp); the epoch makes 4.1.0 an upgrade over them. Never remove it. epoch=1 pkgver=4.1.0 -pkgrel=2 +pkgrel=3 arch=('x86_64') license=('GPL-3.0-or-later') url="https://github.com/biglinux/tts-biglinux" @@ -56,7 +56,7 @@ optdepends=( 'rhvoice-voice-evgeniy-eng: RHVoice English male voice' 'xclip: selection capture on X11 when xsel is not available' 'biglinux-kokoro-tts: Kokoro neural voices (BigLinux repository)' - 'piper-voices-pt-BR: Brazilian Portuguese Piper voices, preinstalled (BigLinux repository)' + 'piper-voices-pt-br: Brazilian Portuguese Piper voices, preinstalled (BigLinux repository; piper-voices-pt-BR in testing)' 'piper-tts-bin: Piper command-line fallback (BigLinux repository; the native engine needs only voices)' 'rhvoice-brazilian-portuguese-complementary-dict-biglinux: extra pronunciation dictionary for RHVoice (BigLinux repository)' ) diff --git a/tests/test_history_view.py b/tests/test_history_view.py index 6a0ac0f..88d2630 100644 --- a/tests/test_history_view.py +++ b/tests/test_history_view.py @@ -188,3 +188,43 @@ def test_history_is_always_in_the_main_menu(monkeypatch): for j in range(section.get_n_items()): labels.append(section.get_item_attribute_value(j, "label", None).get_string()) assert hv._("History") in labels + + +def _child_boxes(flowbox): + boxes, child = [], flowbox.get_first_child() + while child: + ok, rect = child.compute_bounds(flowbox) + boxes.append((round(rect.get_x()), round(rect.get_y()), round(rect.get_width()))) + child = child.get_next_sibling() + return boxes + + +def test_grid_puts_cards_side_by_side_in_equal_columns(page, tmp_path): + view, _settings, window = page + window.set_default_size(1000, 700) + for i in range(4): + _add("Um texto bem mais longo, para ocupar várias linhas no cartão. " * (i + 1), tmp=tmp_path) + _loaded(view) + view._view_toggle.set_active(True) + _pump(lambda: len(_child_boxes(view._grid)) == 4 and _child_boxes(view._grid)[1][0] > 0) + boxes = _child_boxes(view._grid) + assert view._grid.get_visible() and not view._list.get_visible() + assert boxes[0][1] == boxes[1][1] and boxes[1][0] > boxes[0][0] # same row, side by side + assert abs(boxes[0][2] - boxes[1][2]) <= 2 # whatever the text length + assert view._clamp.get_maximum_size() > 760 # the grid may use the window's width + view._view_toggle.set_active(False) + _pump(lambda: view._list.get_first_child() is not None) + assert view._list.get_visible() and not view._grid.get_visible() + assert view._clamp.get_maximum_size() == 760 + + +def test_grid_is_one_column_on_a_narrow_window(page, tmp_path): + view, _settings, window = page + window.set_default_size(400, 700) + for i in range(2): + _add(f"Leitura {i}.", tmp=tmp_path) + _loaded(view) + view._view_toggle.set_active(True) + _pump(lambda: len(_child_boxes(view._grid)) == 2 and _child_boxes(view._grid)[1][1] > 0) + first, second = _child_boxes(view._grid) + assert second[1] > first[1] and second[0] == first[0] # one under the other diff --git a/tests/test_package_installer.py b/tests/test_package_installer.py index 2ed85b6..2c4409a 100644 --- a/tests/test_package_installer.py +++ b/tests/test_package_installer.py @@ -68,3 +68,134 @@ def test_unsafe_package_names_are_refused(monkeypatch): monkeypatch.setattr(pi.subprocess, "run", lambda *a, **k: (_ for _ in ()).throw(AssertionError("must not run"))) assert not pi.query("x; rm -rf /").available assert not pi.install(["--overwrite=*"]).ok + + +# ── Two spellings, then the AUR ────────────────────────────────────── +# BigLinux stable has piper-voices-pt-br, testing piper-voices-pt-BR, the AUR +# piper-voices-pt-br. Both repository packages ship the same voice files. + +def _world(monkeypatch, repo=(), installed=(), aur=(), helper=True): + asked_aur = [] + monkeypatch.setattr(pi, "is_installed", lambda n: n in installed) + monkeypatch.setattr(pi, "query", lambda n: pi.PackageInfo(n, n in repo)) + + def fake_aur(names, timeout=10.0): + asked_aur.append(list(names)) + known = {a.lower(): a for a in aur} + return {n.lower(): known[n.lower()] for n in names if n.lower() in known} + + monkeypatch.setattr(pi, "aur_names", fake_aur) + monkeypatch.setattr(pi, "aur_helper", lambda: ["pamac", "build", "--no-confirm"] if helper else None) + return asked_aur + + +def _one(wanted="piper-voices-pt-BR"): + [r] = pi.resolve([wanted]) + return r.source, r.name + + +def test_both_spellings_are_tried(): + assert pi.name_variants("piper-voices-pt-BR") == ["piper-voices-pt-br", "piper-voices-pt-BR"] + assert pi.name_variants("piper-tts-bin") == ["piper-tts-bin"] + + +def test_stable_spelling_is_found(monkeypatch): + _world(monkeypatch, repo={"piper-voices-pt-br"}) + assert _one() == ("repo", "piper-voices-pt-br") + + +def test_testing_spelling_is_found(monkeypatch): + _world(monkeypatch, repo={"piper-voices-pt-BR"}) + assert _one() == ("repo", "piper-voices-pt-BR") + + +def test_lower_case_wins_when_both_exist(monkeypatch): + _world(monkeypatch, repo={"piper-voices-pt-BR", "piper-voices-pt-br"}) + assert _one() == ("repo", "piper-voices-pt-br") + + +def test_an_installed_spelling_is_never_installed_again(monkeypatch): + # Installing the other spelling would fail on the shared voice files. + _world(monkeypatch, repo={"piper-voices-pt-br", "piper-voices-pt-BR"}, installed={"piper-voices-pt-BR"}) + assert _one() == ("installed", "piper-voices-pt-BR") + + +def test_aur_only_as_a_last_resort(monkeypatch): + asked = _world(monkeypatch, repo={"piper-voices-pt-br"}, aur={"piper-voices-pt-br"}) + assert _one() == ("repo", "piper-voices-pt-br") + assert asked == [] # found in the repositories: the AUR is not even asked + _world(monkeypatch, aur={"piper-voices-pt-br"}) + assert _one() == ("aur", "piper-voices-pt-br") + + +def test_without_an_aur_helper_the_package_is_missing(monkeypatch): + asked = _world(monkeypatch, aur={"piper-voices-pt-br"}, helper=False) + assert _one() == ("", "") + assert asked == [] # no network query for nothing + + +def test_nowhere_is_missing(monkeypatch): + _world(monkeypatch) + assert _one() == ("", "") + + +def test_aur_names_are_case_insensitive(monkeypatch): + import io + import json + + seen = {} + + def fake_urlopen(url, timeout): + seen["url"] = url + return io.BytesIO(json.dumps({"results": [{"Name": "piper-voices-pt-br"}]}).encode()) + + monkeypatch.setattr(pi.urllib.request, "urlopen", fake_urlopen) + assert pi.aur_names(["piper-voices-pt-BR"]) == {"piper-voices-pt-br": "piper-voices-pt-br"} + assert seen["url"].startswith("https://aur.archlinux.org/rpc/v5/info?") + + def offline(url, timeout): + raise OSError("no network") + + monkeypatch.setattr(pi.urllib.request, "urlopen", offline) + assert pi.aur_names(["piper-voices-pt-BR"]) == {} + + +def test_aur_helper_choice(monkeypatch, tmp_path): + conf = tmp_path / "pamac.conf" + monkeypatch.setattr(pi, "PAMAC_CONF", conf) + tools = set() + monkeypatch.setattr(pi.shutil, "which", lambda t: f"/usr/bin/{t}" if t in tools else None) + assert pi.aur_helper() is None + tools.update({"pamac", "yay"}) + conf.write_text("#EnableAUR\n") + assert pi.aur_helper()[0] == "yay" # pamac without its AUR support + conf.write_text("EnableAUR\n") + assert pi.aur_helper()[:2] == ["pamac", "build"] + tools.discard("pamac") + tools.add("paru") + helper = pi.aur_helper() + assert helper[0] == "paru" and helper[-2:] == ["--sudo", "pkexec"] # no terminal for sudo + + +def test_install_aur_runs_as_the_person(monkeypatch): + seen = {} + + def fake_run(cmd, **kw): + seen["cmd"] = cmd + return subprocess.CompletedProcess(cmd, 0, "", "") + + monkeypatch.setattr(pi.subprocess, "run", fake_run) + monkeypatch.setattr(pi, "PACMAN_LOCK", pi.Path("/nonexistent/db.lck")) + monkeypatch.setattr(pi, "aur_helper", lambda: ["pamac", "build", "--no-confirm"]) + assert pi.install_aur(["piper-voices-pt-br", "-rf"]).ok + assert seen["cmd"] == ["pamac", "build", "--no-confirm", "piper-voices-pt-br"] # not pkexec, no option-like name + + +def test_install_aur_failure_is_explained(monkeypatch): + out = "==> ERROR: Failure while downloading https://huggingface.co/x.onnx\n Aborting...\n" + monkeypatch.setattr(pi.subprocess, "run", lambda cmd, **kw: subprocess.CompletedProcess(cmd, 1, out, "")) + monkeypatch.setattr(pi, "PACMAN_LOCK", pi.Path("/nonexistent/db.lck")) + monkeypatch.setattr(pi, "aur_helper", lambda: ["pamac", "build", "--no-confirm"]) + r = pi.install_aur(["piper-voices-pt-br"]) + assert not r.ok and "piper-voices-pt-br" in r.message + assert "Failure while downloading" in r.detail diff --git a/tests/test_voice_manager_rows.py b/tests/test_voice_manager_rows.py new file mode 100644 index 0000000..7e31078 --- /dev/null +++ b/tests/test_voice_manager_rows.py @@ -0,0 +1,20 @@ +"""Voice Manager rows: one per package, whatever the repository's spelling.""" +import pytest + +gi = pytest.importorskip("gi") +gi.require_version("Gtk", "4.0") +gi.require_version("Adw", "1") +try: + from ui.voice_manager_dialog import _one_per_spelling +except Exception as e: # pragma: no cover + pytest.skip(f"GTK unavailable headless: {e}", allow_module_level=True) + + +def test_voice_manager_shows_one_row_per_spelling(): + def row(name, installed="no"): + return {"pkg": name, "installed": installed} + + rows = [row("piper-voices-pt-BR"), row("piper-voices-pt-PT"), row("piper-voices-pt-br")] + assert [r["pkg"] for r in _one_per_spelling(rows)] == ["piper-voices-pt-PT", "piper-voices-pt-br"] + rows[0]["installed"] = "yes" # the installed spelling is the one shown + assert [r["pkg"] for r in _one_per_spelling(rows)] == ["piper-voices-pt-BR", "piper-voices-pt-PT"] diff --git a/usr/share/biglinux/tts-biglinux/services/package_installer.py b/usr/share/biglinux/tts-biglinux/services/package_installer.py index c89cadb..d4d6001 100644 --- a/usr/share/biglinux/tts-biglinux/services/package_installer.py +++ b/usr/share/biglinux/tts-biglinux/services/package_installer.py @@ -12,14 +12,22 @@ translated explanation, and the raw ``error:`` lines as technical detail. (The old code showed the last stderr line, which was often a harmless warning such as "espeak-ng-1.52.0-1 is up to date -- skipping".) +- A package may be spelled two ways: BigLinux stable has + ``piper-voices-pt-br``, testing ``piper-voices-pt-BR``. resolve() tries both + (an installed spelling first: both ship the same files), and the AUR only + as a last resort, through pamac (or paru/yay) as the person, never root. """ from __future__ import annotations +import json import logging import os import re +import shutil import subprocess +import urllib.parse +import urllib.request from dataclasses import dataclass, field from pathlib import Path @@ -28,6 +36,8 @@ logger = logging.getLogger(__name__) PACMAN_LOCK = Path("/var/lib/pacman/db.lck") +PAMAC_CONF = Path("/etc/pamac.conf") +AUR_RPC = "https://aur.archlinux.org/rpc/v5/info" _SAFE_PKG = re.compile(r"^[A-Za-z0-9@._+-]+$") _C_ENV = {**os.environ, "LC_ALL": "C", "LANG": "C"} @@ -74,6 +84,80 @@ def query(name: str) -> PackageInfo: ) +@dataclass +class Resolution: + """How a wanted package can be had.""" + wanted: str + name: str = "" # the spelling to install (or the one installed) + source: str = "" # "installed" | "repo" | "aur" | "" (nowhere) + + +def name_variants(name: str) -> list[str]: + """The spellings to look for, lower case first ("piper-voices-pt-BR" → + ["piper-voices-pt-br", "piper-voices-pt-BR"]): BigLinux stable and the + AUR use lower case.""" + return list(dict.fromkeys([name.lower(), name])) + + +def aur_helper() -> list[str] | None: + """argv prefix that builds and installs AUR packages, or None. + + pamac (BigLinux's own) when its AUR support is on; otherwise paru or + yay, which ask for the password through pkexec (no terminal here). + """ + if shutil.which("pamac") and _pamac_aur_enabled(): + return ["pamac", "build", "--no-confirm"] + if shutil.which("paru"): + return ["paru", "-S", "--aur", "--needed", "--noconfirm", "--skipreview", "--sudo", "pkexec"] + if shutil.which("yay"): + return ["yay", "-S", "--aur", "--needed", "--noconfirm", + "--answerdiff", "None", "--answerclean", "None", "--sudo", "pkexec"] + return None + + +def _pamac_aur_enabled() -> bool: + try: + lines = PAMAC_CONF.read_text(encoding="utf-8", errors="replace").splitlines() + except OSError: + return False + return any(line.split("#", 1)[0].strip() == "EnableAUR" for line in lines) + + +def aur_names(names: list[str], timeout: float = 10.0) -> dict[str, str]: + """Which of ``names`` exist in the AUR (case-insensitive): lower-case + name → the AUR's spelling. Empty when the AUR cannot be reached.""" + names = [n for n in names if _SAFE_PKG.match(n)] + if not names: + return {} + query = urllib.parse.urlencode([("arg[]", n) for n in names]) + try: + with urllib.request.urlopen(f"{AUR_RPC}?{query}", timeout=timeout) as resp: + data = json.load(resp) + except (OSError, ValueError) as e: + logger.debug("AUR query failed: %s", e) + return {} + return {r["Name"].lower(): r["Name"] for r in data.get("results", []) if r.get("Name")} + + +def resolve(packages: list[str], *, allow_aur: bool = True) -> list[Resolution]: + """Find each package under either spelling: installed, then in the + repositories, then (last resort) in the AUR if a helper can build it.""" + result: list[Resolution] = [] + for wanted in packages: + variants = name_variants(wanted) + found = next((Resolution(wanted, v, "installed") for v in variants if is_installed(v)), None) + if found is None: + found = next((Resolution(wanted, v, "repo") for v in variants if query(v).available), None) + result.append(found or Resolution(wanted)) + missing = [r for r in result if not r.source] + if missing and allow_aur and aur_helper(): + in_aur = aur_names([r.wanted for r in missing]) + for r in missing: + if r.wanted.lower() in in_aur: + r.name, r.source = in_aur[r.wanted.lower()], "aur" + return result + + def is_installed(name: str) -> bool: try: return subprocess.run( @@ -140,4 +224,50 @@ def install(packages: list[str], timeout: int = 1800) -> InstallResult: return result -__all__ = ["InstallResult", "PackageInfo", "explain_failure", "install", "is_installed", "query"] +def install_aur(packages: list[str], timeout: int = 3600) -> InstallResult: + """Build and install AUR packages as the person (blocking: worker thread). + + Never as root: AUR helpers refuse it, and a PKGBUILD must not run as + root. The helper asks for the password itself (polkit) to install. + """ + # No "--" (pamac does not take it): a name can never start with "-". + packages = [p for p in packages if _SAFE_PKG.match(p) and not p.startswith("-")] + if not packages: + return InstallResult(False, _("Nothing to install.")) + helper = aur_helper() + if helper is None: + return InstallResult(False, _("{packages} is not available in your repositories. Update the system (sudo pacman -Syu) and try again.").format( + packages=", ".join(packages)), missing=packages) + if PACMAN_LOCK.exists(): + return InstallResult( + False, + _("Another program is installing or updating packages. Wait for it to finish and try again."), + ) + try: + proc = subprocess.run( + [*helper, *packages], + capture_output=True, text=True, timeout=timeout, env=_C_ENV, stdin=subprocess.DEVNULL, + ) + except FileNotFoundError: + return InstallResult(False, _("{packages} could not be built from the AUR. See the details.").format( + packages=", ".join(packages)), helper[0]) + except subprocess.TimeoutExpired: + return InstallResult(False, _("The installation took too long and was stopped.")) + if proc.returncode == 0: + return InstallResult(True) + output = (proc.stdout or "") + "\n" + (proc.stderr or "") + lines = [ln.strip() for ln in output.splitlines() if ln.strip()] + errors = [ln for ln in lines if ln.lower().startswith(("error", "==> error"))] + detail = "\n".join(errors or lines[-8:]) + if "unable to lock database" in output.lower(): + message = _("Another program is installing or updating packages. Wait for it to finish and try again.") + else: + message = _("{packages} could not be built from the AUR. See the details.").format(packages=", ".join(packages)) + logger.warning("AUR install failed (%d): %s", proc.returncode, detail) + return InstallResult(False, message, detail) + + +__all__ = [ + "InstallResult", "PackageInfo", "Resolution", "aur_helper", "aur_names", "explain_failure", + "install", "install_aur", "is_installed", "name_variants", "query", "resolve", +] diff --git a/usr/share/biglinux/tts-biglinux/ui/history_view.py b/usr/share/biglinux/tts-biglinux/ui/history_view.py index 8f6bdc0..a58ae0e 100644 --- a/usr/share/biglinux/tts-biglinux/ui/history_view.py +++ b/usr/share/biglinux/tts-biglinux/ui/history_view.py @@ -88,6 +88,12 @@ def _show_in_file_manager(file_path: Path | None) -> None: # ── One entry ───────────────────────────────────────────────────────── +# Grid: card text width (characters) and how wide the page may get. +_GRID_TEXT_CHARS = 22 +_LIST_WIDTH = 760 +_GRID_WIDTH = 1280 + + class HistoryCard(Gtk.Box): """A history entry: text, details, player and actions.""" @@ -117,6 +123,12 @@ def __init__(self, entry: dict, view: HistoryView) -> None: self._text.set_ellipsize(Pango.EllipsizeMode.END) self._text.set_selectable(True) self._text.add_css_class("history-text-preview") + if view._grid_mode: + # A wrapping label asks for its whole text on one line: a fixed + # width lets several cards fit side by side, in equal columns. + self.add_css_class("grid") + self._text.set_width_chars(_GRID_TEXT_CHARS) + self._text.set_max_width_chars(_GRID_TEXT_CHARS) if not text: self._text.add_css_class("dim-label") text_box.append(self._text) @@ -406,9 +418,12 @@ def _build_ui(self) -> None: self._list.update_property([Gtk.AccessibleProperty.LABEL], [_("History entries")]) self._grid = Gtk.FlowBox() self._grid.set_selection_mode(Gtk.SelectionMode.NONE) - self._grid.set_homogeneous(True) + # Not homogeneous: each row is as tall as its own tallest card (one + # expanded text must not stretch every card of the page). + self._grid.set_homogeneous(False) + self._grid.set_valign(Gtk.Align.START) self._grid.set_min_children_per_line(1) - self._grid.set_max_children_per_line(3) + self._grid.set_max_children_per_line(4) self._grid.set_column_spacing(8) self._grid.set_row_spacing(8) self._grid.set_visible(False) @@ -424,7 +439,7 @@ def _build_ui(self) -> None: self._more_spinner.set_visible(False) content.append(self._more_spinner) self._clamp = Adw.Clamp() - self._clamp.set_maximum_size(760) + self._clamp.set_maximum_size(_LIST_WIDTH) self._clamp.set_child(content) self._scroll = Gtk.ScrolledWindow() self._scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) @@ -659,6 +674,7 @@ def _on_view_toggled(self, button: Gtk.ToggleButton) -> None: self._grid_mode = button.get_active() self._list.set_visible(not self._grid_mode) self._grid.set_visible(self._grid_mode) + self._clamp.set_maximum_size(_GRID_WIDTH if self._grid_mode else _LIST_WIDTH) button.set_tooltip_text(_("Show as list") if self._grid_mode else _("Show as grid")) button.set_icon_name("format-justify-fill-symbolic" if self._grid_mode else "view-grid-symbolic") self.reload() diff --git a/usr/share/biglinux/tts-biglinux/ui/main_view.py b/usr/share/biglinux/tts-biglinux/ui/main_view.py index f2d77d2..028c919 100644 --- a/usr/share/biglinux/tts-biglinux/ui/main_view.py +++ b/usr/share/biglinux/tts-biglinux/ui/main_view.py @@ -1398,39 +1398,48 @@ def _revert_to_rhvoice(self) -> None: if self._catalog: self._on_voices_discovered(self._catalog) - def _piper_package_plan(self) -> tuple[list[str], list[str]]: - """Piper packages to install and those not in the repositories (worker).""" + def _piper_package_plan(self) -> list: + """Where each Piper package can come from (worker). + + Each package under either spelling (BigLinux stable has + piper-voices-pt-br, testing piper-voices-pt-BR), the AUR last. + """ from services import package_installer lang = get_system_language() wanted = ["piper-tts-bin", self._PIPER_VOICE_PACKAGES.get(lang, "piper-voices-en-US")] if "piper-voices-pt-BR" not in wanted: wanted.append("piper-voices-pt-BR") # BigLinux default language - available, missing = [], [] - for name in wanted: - (available if package_installer.query(name).available else missing).append(name) - return available, missing + return package_installer.resolve(wanted) def _ask_install_piper(self) -> None: """Offer to install Piper — only the packages that really exist.""" run_in_thread(self._piper_package_plan, on_done=self._show_piper_install_dialog) - def _show_piper_install_dialog(self, plan: tuple[list[str], list[str]]) -> None: - available, missing = plan - voices = [p for p in available if p.startswith("piper-voices-")] - if not voices: + def _show_piper_install_dialog(self, plan: list) -> None: + voices = [r for r in plan if r.wanted.startswith("piper-voices-")] + if not any(r.source for r in voices): dialog = Adw.AlertDialog.new( _("Piper is not available"), _("No Piper voice package was found in your repositories ({packages}). Update the system (sudo pacman -Syu) and try again.").format( - packages=", ".join(p for p in missing if p.startswith("piper-voices-")) + packages=", ".join(r.wanted for r in voices) ), ) dialog.add_response("ok", _("OK")) dialog.connect("response", lambda *_a: self._revert_to_rhvoice()) dialog.present(self._root_window()) return + repo = [r.name for r in plan if r.source == "repo"] + aur = [r.name for r in plan if r.source == "aur"] + if not repo and not aur: # everything is installed already + from services.package_installer import InstallResult + + self._on_piper_installed(InstallResult(True)) + return body = _("Piper provides natural neural voices. These packages will be installed:") + "\n" - body += "\n".join(f"• {name}" for name in available) + body += "\n".join([f"• {name}" for name in repo] + [f"• {name} (AUR)" for name in aur]) + if aur: + body += "\n\n" + _("Packages marked AUR are not in your repositories: they come from the Arch User Repository, are maintained by the community and are built on this computer, which takes longer.") body += "\n\n" + _("This requires administrator permissions.") dialog = Adw.AlertDialog.new(_("Install Piper Neural TTS?"), body) dialog.add_response("cancel", _("Cancel")) @@ -1439,16 +1448,22 @@ def _show_piper_install_dialog(self, plan: tuple[list[str], list[str]]) -> None: dialog.set_default_response("install") dialog.set_close_response("cancel") + def _install(): + from services import package_installer + + result = package_installer.install(repo) if repo else package_installer.InstallResult(True) + if result.ok and aur: + result = package_installer.install_aur(aur) + return result + def _on_response(_d, response: str) -> None: if response != "install": self._revert_to_rhvoice() return - from services import package_installer - self._run_install_with_progress( title=_("Installing Piper TTS"), status_text=_("Downloading and installing packages…"), - worker=lambda: package_installer.install(available), + worker=_install, on_done=self._on_piper_installed, ) diff --git a/usr/share/biglinux/tts-biglinux/ui/voice_manager_dialog.py b/usr/share/biglinux/tts-biglinux/ui/voice_manager_dialog.py index e932a9d..6926df5 100644 --- a/usr/share/biglinux/tts-biglinux/ui/voice_manager_dialog.py +++ b/usr/share/biglinux/tts-biglinux/ui/voice_manager_dialog.py @@ -180,6 +180,7 @@ def _query_packages(search_term: str, prefix: str) -> list[dict[str, str]]: capture_output=True, text=True, timeout=10, + env={**os.environ, "LC_ALL": "C"}, # "[installed]" in every language ) if proc.returncode != 0: return packages @@ -200,7 +201,7 @@ def _query_packages(search_term: str, prefix: str) -> list[dict[str, str]]: continue pkg_name = m.group(1) version = m.group(2) - installed = "[instalado]" in header or "[installed]" in header + installed = "[installed]" in header if not pkg_name.startswith(prefix): continue @@ -275,6 +276,21 @@ def _annotate_sizes(data: dict[str, list[dict[str, str]]]) -> None: by_name[name]["size"] = sz +def _one_per_spelling(pkgs: list[dict[str, str]]) -> list[dict[str, str]]: + """One row per package whatever its spelling: BigLinux stable has + piper-voices-pt-br, testing piper-voices-pt-BR, and both ship the same + files (installing the second would fail). The installed one wins, then + the lower-case spelling (stable, AUR).""" + best: dict[str, dict[str, str]] = {} + for p in pkgs: + key = p["pkg"].lower() + cur = best.get(key) + rank = (p.get("installed") == "yes", p["pkg"] == key) + if cur is None or rank > (cur.get("installed") == "yes", cur["pkg"] == key): + best[key] = p + return [p for p in pkgs if best[p["pkg"].lower()] is p] + + def _query_all_voice_packages() -> dict[str, list[dict[str, str]]]: """Query pacman for all voice packages across all engines. @@ -301,7 +317,7 @@ def _query_all_voice_packages() -> dict[str, list[dict[str, str]]]: # ── Piper voices ── piper_pkgs = _query_packages("piper-voices-", "piper-voices-") # Filter out "piper-voices-common" - piper_pkgs = [p for p in piper_pkgs if p["pkg"] != "piper-voices-common"] + piper_pkgs = _one_per_spelling([p for p in piper_pkgs if p["pkg"] != "piper-voices-common"]) for pkg in piper_pkgs: locale = pkg["pkg"].removeprefix("piper-voices-") pkg["voice_name"] = locale