From ce5ca8c682de777a0652a08c6892ba24317a3d24 Mon Sep 17 00:00:00 2001 From: Softer Date: Fri, 24 Apr 2026 18:26:06 +0300 Subject: [PATCH] Show install summary when configuration is valid Previously the Install menu preview was empty when everything was valid, leaving the user with no "ready" signal. Now show "Ready to install" plus a two-column summary of the current configuration. - New _install_summary() composes an aligned key/value table with rows for disks+FS+LUKS, bootloader, kernel, profile, greeter, package count, network, locale and timezone. Column width adapts to the longest translated label so translations keep the alignment. - Rows whose underlying config is not set are skipped rather than rendered as empty. - base.pot / uk base.po: add new msgids for summary labels. --- archinstall/lib/global_menu.py | 69 +++++++++++++++++++++- archinstall/locales/base.pot | 15 +++++ archinstall/locales/uk/LC_MESSAGES/base.po | 15 +++++ 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index 3d94f31e..a3644091 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -498,6 +498,70 @@ class GlobalMenu(AbstractMenu[None]): return None + def _install_summary(self) -> str: + """ + Render a concise two-column summary of the current install configuration. + + The left column holds section labels, the right column holds values. + Column width adapts to the longest translated label so translations + do not break the alignment. Rows whose underlying config is not set + are skipped. + + Returns an empty string if nothing meaningful to show. + """ + rows: list[tuple[str, str]] = [] + + disk_config: DiskLayoutConfiguration | None = self._item_group.find_by_key('disk_config').value + if disk_config and disk_config.device_modifications: + disk_parts: list[str] = [] + for mod in disk_config.device_modifications: + path = str(mod.device_path) + root_part = mod.get_root_partition() + flags: list[str] = [] + if root_part and root_part.fs_type: + flags.append(root_part.fs_type.value) + if disk_config.disk_encryption: + flags.append(tr('LUKS')) + disk_parts.append(f'{path} ({" + ".join(flags)})' if flags else path) + rows.append((tr('Disks'), ', '.join(disk_parts))) + + bl_config: BootloaderConfiguration | None = self._item_group.find_by_key('bootloader_config').value + if bl_config and bl_config.bootloader != Bootloader.NO_BOOTLOADER: + rows.append((tr('Bootloader'), bl_config.bootloader.value)) + + kernels: list[str] | None = self._item_group.find_by_key('kernels').value + if kernels: + rows.append((tr('Kernel'), ', '.join(kernels))) + + profile_config: ProfileConfiguration | None = self._item_group.find_by_key('profile_config').value + if profile_config and profile_config.profile: + names = profile_config.profile.current_selection_names() + rows.append((tr('Profile'), ', '.join(names) if names else profile_config.profile.name)) + if profile_config.greeter: + rows.append((tr('Greeter'), profile_config.greeter.value)) + + packages: list[str] | None = self._item_group.find_by_key('packages').value + if packages: + rows.append((tr('Packages'), str(len(packages)))) + + net_config = self._item_group.find_by_key('network_config').value + if isinstance(net_config, NetworkConfiguration): + rows.append((tr('Network'), net_config.type.display_msg())) + + locale_config: LocaleConfiguration | None = self._item_group.find_by_key('locale_config').value + if locale_config: + rows.append((tr('Locale'), locale_config.sys_lang)) + + tz = self._item_group.find_by_key('timezone').value + if tz: + rows.append((tr('Timezone'), tz)) + + if not rows: + return '' + + label_width = max(len(label) for label, _ in rows) + 2 + return '\n'.join(f'{label:<{label_width}}{value}' for label, value in rows) + def _prev_install_invalid_config(self, item: MenuItem) -> str | None: if missing := self._missing_configs(): text = tr('Missing configurations:\n') @@ -508,7 +572,10 @@ class GlobalMenu(AbstractMenu[None]): if error := self._validate_bootloader(): return tr(f'Invalid configuration: {error}') - return None + summary = self._install_summary() + if summary: + return f'{tr("Ready to install")}\n\n{summary}' + return tr('Ready to install') def _prev_profile(self, item: MenuItem) -> str | None: profile_config: ProfileConfiguration | None = item.value diff --git a/archinstall/locales/base.pot b/archinstall/locales/base.pot index f707ec7a..54fea2a7 100644 --- a/archinstall/locales/base.pot +++ b/archinstall/locales/base.pot @@ -1245,6 +1245,21 @@ msgstr "" msgid "Invalid configuration: {error}" msgstr "" +msgid "Ready to install" +msgstr "" + +msgid "Disks" +msgstr "" + +msgid "Packages" +msgstr "" + +msgid "Network" +msgstr "" + +msgid "Locale" +msgstr "" + msgid "Type" msgstr "" diff --git a/archinstall/locales/uk/LC_MESSAGES/base.po b/archinstall/locales/uk/LC_MESSAGES/base.po index a178ac2d..583756ed 100644 --- a/archinstall/locales/uk/LC_MESSAGES/base.po +++ b/archinstall/locales/uk/LC_MESSAGES/base.po @@ -1219,6 +1219,21 @@ msgstr "Модель" msgid "Invalid configuration: {error}" msgstr "Неправильна конфігурація: {error}" +msgid "Ready to install" +msgstr "Готово до встановлення" + +msgid "Disks" +msgstr "Диски" + +msgid "Packages" +msgstr "Пакети" + +msgid "Network" +msgstr "Мережа" + +msgid "Locale" +msgstr "Локаль" + msgid "Type" msgstr "Тип"