* Extract binding descriptions into base.pot and translate raw widget bindings (#4584)
xgettext only knew the tr keyword, so binding descriptions - translated
at runtime via tr(b.description) in _translate_bindings() - never made
it into base.pot. The strings added manually in #4363 were wiped by the
regeneration in #4557.
Teach the generator two more keywords: Binding:3 picks up our own
binding definitions, and tr_noop marks strings that only exist inside
the textual package, listed in the new tui/binding_descriptions.py.
The list walks the full MRO of the textual classes used in components.py,
since _translate_bindings() operates on the merged bindings map (e.g.
Scroll Up comes from ScrollView and carries live translations in 18
locales today).
Raw Input and Button widgets never went through _translate_bindings(),
so their help-panel descriptions stayed English regardless of .po
content - subclass them (_Input/_Button) following the _OptionList
pattern to make those translations real.
test_tooling/check_binding_descriptions.py verifies the list against
the installed textual after upgrades (manual, not wired into CI).
* Document key binding descriptions in the locales README
str.title() title-cased every label word, which is wrong outside
English: it turned the Ukrainian "Ім'я хоста" into "Ім'Я Хоста" and
broke acronyms ("NTP" -> "Ntp"). The source strings and their
translations are already written with the correct casing.
Capitalize only the first letter of each label instead.
* add vn lang, trans lang, translating ~28%
* done 80/735 (10% not ~28% sorry) and 735/735 done (counted fuzzy or google translate helper). See https://gist.github.com/BlackCatOfficialytb/e85bad1758d9e29c349f2d75b91363f1 for program to help me translate
* doing plenty of things
* up to 40% by removing fuzzy tag in correct translate words/paragraph
* fix the extension
* more words/paragraphs are unfuzzied
* trans up to 57%
* translate up to 61%
* Fix ValueError exception when no disks are detected in the disk menu
in lib/disk/disk_menu.py, the menu items are created using info from a list called "devices" (device_handler.devices). when no block devices are detected, the list is empty, creating zero MenuItems, and causing the following ValueError:
ValueError: Menu must have at least one item
this change checks if the length of the list is shorter than 1 (empty list) before constructing the menu. if the list is empty, the user will be notified that no disks were detected. otherwise, the menu is created and behaves as normal
* Fixed ruff formatting issue
* Fixed ruff formatting issue
---------
Co-authored-by: Anton Hvornum <torxed@archlinux.org>
Plymouth is purely cosmetic and a frequent source of boot breakage,
most notably a black screen with the NVIDIA driver and a hidden LUKS
password prompt. Show a yellow confirmation warning listing these risks
when enabling it; when Plymouth is already enabled the user is only
changing the theme, so the warning is skipped. Regenerate base.pot for
the new strings.
select_plymouth_theme() compared enum item values against a raw string,
so the previously selected theme was never highlighted when reopening
the menu. Use set_focus_by_value() like other single-select menus.
Regenerate base.pot to pick up the three Plymouth strings introduced
in #4555.
* Skip custom mirror config when keyring sync fails
Check the exit state of archlinux-keyring-wkd-sync.service after
waiting for it to finish. If it failed, skip set_mirrors() and
continue installation with default mirrors instead of crashing
with "GPGME error: No data" during pacman -Syy.
* Reinit keyring automatically when pacman sync fails with GPGME error
Instead of skipping mirror configuration when wkd-sync fails, catch
the GPGME error at the point where it actually occurs - during
pacman -Syy. If the sync fails with a keyring-related error, reinit
the keyring with pacman-key --init/--populate and retry the sync.
* Simplify pacman sync() and guard gpg-agent kill on running state
Collapse the duplicated self.ask() blocks in sync() into a single call
via a msg variable, and drop the redundant default_cmd='pacman' (it is
already the default). In _reinit_keyring(), check that gpg-agent is
actually running (pgrep -x) before killing it, instead of catching the
killall error and assuming it was not running.
* Add users to seat group when seatd is selected
When a desktop profile uses seatd for seat access, the user must be
in the seat group for the compositor to access input devices. Without
this, sway/hyprland/niri/labwc fail to start after installation.
* Move seat access provisioning into DesktopProfile.provision()
The four Wayland profiles (Hyprland, Sway, niri, labwc) each duplicated a
provision() override calling provision_seat_access(). Move that into the
base DesktopProfile.provision() loop, which already iterates the selected
profiles, and read CustomSetting.SeatAccess from each. The None check now
lives at the call site (walrus), so provision_seat_access() takes a plain
str. This removes the per-profile overrides and their TYPE_CHECKING imports.
* Use top-level imports in seat access utils
The Installer and User imports were under a TYPE_CHECKING guard, but
they cause no circular import (bspwm.py already imports both at top
level). Move them to module scope per review feedback.