From 89cefb9a1c7d4c4968e7d8645149078e601c9d1c Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Fri, 12 May 2023 02:30:09 +1000 Subject: Cleanup imports and unused code (#1801) * Cleanup imports and unused code * Update build check * Keep deprecation exception * Simplify logging --------- Co-authored-by: Daniel Girtler --- archinstall/lib/interactions/general_conf.py | 243 +++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 archinstall/lib/interactions/general_conf.py (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py new file mode 100644 index 00000000..5fcfa633 --- /dev/null +++ b/archinstall/lib/interactions/general_conf.py @@ -0,0 +1,243 @@ +from __future__ import annotations + +import pathlib +from typing import List, Any, Optional, Dict, TYPE_CHECKING + +from ..locale import list_keyboard_languages, list_timezones +from ..menu import MenuSelectionType, Menu, TextInput +from ..mirrors import list_mirrors +from ..output import warn +from ..packages.packages import validate_package_list +from ..storage import storage +from ..translationhandler import Language + +if TYPE_CHECKING: + _: Any + + +def ask_ntp(preset: bool = True) -> bool: + prompt = str(_('Would you like to use automatic time synchronization (NTP) with the default time servers?\n')) + prompt += str(_('Hardware time and other post-configuration steps might be required in order for NTP to work.\nFor more information, please check the Arch wiki')) + if preset: + preset_val = Menu.yes() + else: + preset_val = Menu.no() + choice = Menu(prompt, Menu.yes_no(), skip=False, preset_values=preset_val, default_option=Menu.yes()).run() + + return False if choice.value == Menu.no() else True + + +def ask_hostname(preset: str = '') -> str: + while True: + hostname = TextInput( + str(_('Desired hostname for the installation: ')), + preset + ).run().strip() + + if hostname: + return hostname + + +def ask_for_a_timezone(preset: Optional[str] = None) -> Optional[str]: + timezones = list_timezones() + default = 'UTC' + + choice = Menu( + _('Select a timezone'), + list(timezones), + preset_values=preset, + default_option=default + ).run() + + match choice.type_: + case MenuSelectionType.Skip: return preset + case MenuSelectionType.Selection: return choice.single_value + + return None + + +def ask_for_audio_selection(desktop: bool = True, preset: Optional[str] = None) -> Optional[str]: + no_audio = str(_('No audio server')) + choices = ['pipewire', 'pulseaudio'] if desktop else ['pipewire', 'pulseaudio', no_audio] + default = 'pipewire' if desktop else no_audio + + choice = Menu(_('Choose an audio server'), choices, preset_values=preset, default_option=default).run() + + match choice.type_: + case MenuSelectionType.Skip: return preset + case MenuSelectionType.Selection: return choice.single_value + + return None + + +def select_language(preset: Optional[str] = None) -> Optional[str]: + """ + Asks the user to select a language + Usually this is combined with :ref:`archinstall.list_keyboard_languages`. + + :return: The language/dictionary key of the selected language + :rtype: str + """ + kb_lang = list_keyboard_languages() + # sort alphabetically and then by length + sorted_kb_lang = sorted(sorted(list(kb_lang)), key=len) + + choice = Menu( + _('Select keyboard layout'), + sorted_kb_lang, + preset_values=preset, + sort=False + ).run() + + match choice.type_: + case MenuSelectionType.Skip: return preset + case MenuSelectionType.Selection: return choice.single_value + + return None + + +def select_mirror_regions(preset_values: Dict[str, Any] = {}) -> Dict[str, Any]: + """ + Asks the user to select a mirror or region + Usually this is combined with :ref:`archinstall.list_mirrors`. + + :return: The dictionary information about a mirror/region. + :rtype: dict + """ + if preset_values is None: + preselected = None + else: + preselected = list(preset_values.keys()) + + mirrors = list_mirrors() + + choice = Menu( + _('Select one of the regions to download packages from'), + list(mirrors.keys()), + preset_values=preselected, + multi=True, + allow_reset=True + ).run() + + match choice.type_: + case MenuSelectionType.Reset: + return {} + case MenuSelectionType.Skip: + return preset_values + case MenuSelectionType.Selection: + return {selected: mirrors[selected] for selected in choice.multi_value} + + return {} + + +def select_archinstall_language(languages: List[Language], preset: Language) -> Language: + # these are the displayed language names which can either be + # the english name of a language or, if present, the + # name of the language in its own language + options = {lang.display_name: lang for lang in languages} + + title = 'NOTE: If a language can not displayed properly, a proper font must be set manually in the console.\n' + title += 'All available fonts can be found in "/usr/share/kbd/consolefonts"\n' + title += 'e.g. setfont LatGrkCyr-8x16 (to display latin/greek/cyrillic characters)\n' + + choice = Menu( + title, + list(options.keys()), + default_option=preset.display_name, + preview_size=0.5 + ).run() + + match choice.type_: + case MenuSelectionType.Skip: return preset + case MenuSelectionType.Selection: return options[choice.single_value] + + raise ValueError('Language selection not handled') + + +def ask_additional_packages_to_install(pre_set_packages: List[str] = []) -> List[str]: + # Additional packages (with some light weight error handling for invalid package names) + print(_('Only packages such as base, base-devel, linux, linux-firmware, efibootmgr and optional profile packages are installed.')) + print(_('If you desire a web browser, such as firefox or chromium, you may specify it in the following prompt.')) + + def read_packages(already_defined: list = []) -> list: + display = ' '.join(already_defined) + input_packages = TextInput(_('Write additional packages to install (space separated, leave blank to skip): '), display).run().strip() + return input_packages.split() if input_packages else [] + + pre_set_packages = pre_set_packages if pre_set_packages else [] + packages = read_packages(pre_set_packages) + + if not storage['arguments']['offline'] and not storage['arguments']['no_pkg_lookups']: + while True: + if len(packages): + # Verify packages that were given + print(_("Verifying that additional packages exist (this might take a few seconds)")) + valid, invalid = validate_package_list(packages) + + if invalid: + warn(f"Some packages could not be found in the repository: {invalid}") + packages = read_packages(valid) + continue + break + + return packages + + +def add_number_of_parrallel_downloads(input_number :Optional[int] = None) -> Optional[int]: + max_downloads = 5 + print(_(f"This option enables the number of parallel downloads that can occur during installation")) + print(_(f"Enter the number of parallel downloads to be enabled.\n (Enter a value between 1 to {max_downloads})\nNote:")) + print(_(f" - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )")) + print(_(f" - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )")) + print(_(f" - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )")) + + while True: + try: + input_number = int(TextInput(_("[Default value: 0] > ")).run().strip() or 0) + if input_number <= 0: + input_number = 0 + elif input_number > max_downloads: + input_number = max_downloads + break + except: + print(_(f"Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]")) + + pacman_conf_path = pathlib.Path("/etc/pacman.conf") + with pacman_conf_path.open() as f: + pacman_conf = f.read().split("\n") + + with pacman_conf_path.open("w") as fwrite: + for line in pacman_conf: + if "ParallelDownloads" in line: + fwrite.write(f"ParallelDownloads = {input_number+1}\n") if not input_number == 0 else fwrite.write("#ParallelDownloads = 0\n") + else: + fwrite.write(f"{line}\n") + + return input_number + + +def select_additional_repositories(preset: List[str]) -> List[str]: + """ + Allows the user to select additional repositories (multilib, and testing) if desired. + + :return: The string as a selected repository + :rtype: string + """ + + repositories = ["multilib", "testing"] + + choice = Menu( + _('Choose which optional additional repositories to enable'), + repositories, + sort=False, + multi=True, + preset_values=preset, + allow_reset=True + ).run() + + match choice.type_: + case MenuSelectionType.Skip: return preset + case MenuSelectionType.Reset: return [] + case MenuSelectionType.Selection: return choice.single_value + + return [] -- cgit v1.2.3-54-g00ecf From 8a292a163ea2e643a8ac5d4cfada8a27076de630 Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Mon, 15 May 2023 17:16:18 +1000 Subject: Add custom mirror support (#1816) Co-authored-by: Daniel Girtler --- archinstall/__init__.py | 8 +- archinstall/lib/global_menu.py | 34 ++- archinstall/lib/installer.py | 15 +- archinstall/lib/interactions/__init__.py | 2 +- archinstall/lib/interactions/general_conf.py | 37 +-- archinstall/lib/mirrors.py | 442 ++++++++++++++++++--------- archinstall/scripts/guided.py | 16 +- archinstall/scripts/swiss.py | 19 +- examples/interactive_installation.py | 14 +- 9 files changed, 358 insertions(+), 229 deletions(-) (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/__init__.py b/archinstall/__init__.py index 992bd9fa..e6fcb267 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -225,12 +225,8 @@ def load_config(): if profile_config := arguments.get('profile_config', None): arguments['profile_config'] = profile.ProfileConfiguration.parse_arg(profile_config) - if arguments.get('mirror-region', None) is not None: - if type(arguments.get('mirror-region', None)) is dict: - arguments['mirror-region'] = arguments.get('mirror-region', None) - else: - selected_region = arguments.get('mirror-region', None) - arguments['mirror-region'] = {selected_region: mirrors.list_mirrors()[selected_region]} + if mirror_config := arguments.get('mirror_config', None): + arguments['mirror_config'] = mirrors.MirrorConfiguration.parse_args(mirror_config) if arguments.get('servers', None) is not None: storage['_selected_servers'] = arguments.get('servers', None) diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index 13595132..fc58a653 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -5,6 +5,7 @@ from typing import Any, List, Optional, Union, Dict, TYPE_CHECKING from . import disk from .general import secret from .menu import Selector, AbstractMenu +from .mirrors import MirrorConfiguration, MirrorMenu from .models import NetworkConfiguration from .models.bootloader import Bootloader from .models.users import User @@ -26,7 +27,6 @@ from .interactions import select_kernel from .interactions import select_language from .interactions import select_locale_enc from .interactions import select_locale_lang -from .interactions import select_mirror_regions from .interactions import ask_ntp from .interactions.disk_conf import select_disk_config @@ -51,12 +51,13 @@ class GlobalMenu(AbstractMenu): _('Keyboard layout'), lambda preset: select_language(preset), default='us') - self._menu_options['mirror-region'] = \ + self._menu_options['mirror_config'] = \ Selector( - _('Mirror region'), - lambda preset: select_mirror_regions(preset), - display_func=lambda x: list(x.keys()) if x else '[]', - default={}) + _('Mirrors'), + lambda preset: self._mirror_configuration(preset), + display_func=lambda x: str(_('Defined')) if x else '', + preview_func=self._prev_mirror_config + ) self._menu_options['sys-language'] = \ Selector( _('Locale language'), @@ -354,3 +355,24 @@ class GlobalMenu(AbstractMenu): def _create_user_account(self, defined_users: List[User]) -> List[User]: users = ask_for_additional_users(defined_users=defined_users) return users + + def _mirror_configuration(self, preset: Optional[MirrorConfiguration] = None) -> Optional[MirrorConfiguration]: + data_store: Dict[str, Any] = {} + mirror_configuration = MirrorMenu(data_store, preset=preset).run() + return mirror_configuration + + def _prev_mirror_config(self) -> Optional[str]: + selector = self._menu_options['mirror_config'] + + if selector.has_selection(): + mirror_config: MirrorConfiguration = selector.current_selection # type: ignore + output = '' + if mirror_config.regions: + output += '{}: {}\n\n'.format(str(_('Mirror regions')), mirror_config.regions) + if mirror_config.custom_mirrors: + table = FormattedOutput.as_table(mirror_config.custom_mirrors) + output += '{}\n{}'.format(str(_('Custom mirrors')), table) + + return output.strip() + + return None diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 3c427ab2..30442774 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -6,7 +6,7 @@ import shutil import subprocess import time from pathlib import Path -from typing import Any, List, Optional, TYPE_CHECKING, Union, Dict, Callable, Iterable +from typing import Any, List, Optional, TYPE_CHECKING, Union, Dict, Callable from . import disk from .exceptions import DiskError, ServiceException, RequirementError, HardwareIncompatibilityError, SysCallError @@ -14,7 +14,7 @@ from .general import SysCommand from .hardware import SysInfo from .locale import verify_keyboard_layout, verify_x11_keyboard_layout from .luks import Luks2 -from .mirrors import use_mirrors +from .mirrors import use_mirrors, MirrorConfiguration, add_custom_mirrors from .models.bootloader import Bootloader from .models.network_configuration import NetworkConfiguration from .models.users import User @@ -383,14 +383,17 @@ class Installer: raise RequirementError("Pacstrap failed. See /var/log/archinstall/install.log or above message for error details.") - def set_mirrors(self, mirrors: Dict[str, Iterable[str]]): + def set_mirrors(self, mirror_config: MirrorConfiguration): for plugin in plugins.values(): if hasattr(plugin, 'on_mirrors'): - if result := plugin.on_mirrors(mirrors): - mirrors = result + if result := plugin.on_mirrors(mirror_config): + mirror_config = result destination = f'{self.target}/etc/pacman.d/mirrorlist' - use_mirrors(mirrors, destination=destination) + if mirror_config.mirror_regions: + use_mirrors(mirror_config.mirror_regions, destination) + if mirror_config.custom_mirrors: + add_custom_mirrors(mirror_config.custom_mirrors) def genfstab(self, flags :str = '-pU'): info(f"Updating {self.target}/etc/fstab") diff --git a/archinstall/lib/interactions/__init__.py b/archinstall/lib/interactions/__init__.py index b5691a10..158750cc 100644 --- a/archinstall/lib/interactions/__init__.py +++ b/archinstall/lib/interactions/__init__.py @@ -11,7 +11,7 @@ from .disk_conf import ( from .general_conf import ( ask_ntp, ask_hostname, ask_for_a_timezone, ask_for_audio_selection, select_language, - select_mirror_regions, select_archinstall_language, ask_additional_packages_to_install, + select_archinstall_language, ask_additional_packages_to_install, add_number_of_parrallel_downloads, select_additional_repositories ) diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index 5fcfa633..0338c61e 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -1,11 +1,10 @@ from __future__ import annotations import pathlib -from typing import List, Any, Optional, Dict, TYPE_CHECKING +from typing import List, Any, Optional, TYPE_CHECKING from ..locale import list_keyboard_languages, list_timezones from ..menu import MenuSelectionType, Menu, TextInput -from ..mirrors import list_mirrors from ..output import warn from ..packages.packages import validate_package_list from ..storage import storage @@ -96,40 +95,6 @@ def select_language(preset: Optional[str] = None) -> Optional[str]: return None -def select_mirror_regions(preset_values: Dict[str, Any] = {}) -> Dict[str, Any]: - """ - Asks the user to select a mirror or region - Usually this is combined with :ref:`archinstall.list_mirrors`. - - :return: The dictionary information about a mirror/region. - :rtype: dict - """ - if preset_values is None: - preselected = None - else: - preselected = list(preset_values.keys()) - - mirrors = list_mirrors() - - choice = Menu( - _('Select one of the regions to download packages from'), - list(mirrors.keys()), - preset_values=preselected, - multi=True, - allow_reset=True - ).run() - - match choice.type_: - case MenuSelectionType.Reset: - return {} - case MenuSelectionType.Skip: - return preset_values - case MenuSelectionType.Selection: - return {selected: mirrors[selected] for selected in choice.multi_value} - - return {} - - def select_archinstall_language(languages: List[Language], preset: Language) -> Language: # these are the displayed language names which can either be # the english name of a language or, if present, the diff --git a/archinstall/lib/mirrors.py b/archinstall/lib/mirrors.py index 62a0b081..521a8e5b 100644 --- a/archinstall/lib/mirrors.py +++ b/archinstall/lib/mirrors.py @@ -1,99 +1,279 @@ import pathlib -import urllib.error -import urllib.request -from typing import Union, Iterable, Dict, Any, List -from dataclasses import dataclass - -from .general import SysCommand -from .output import info, warn -from .exceptions import SysCallError +from dataclasses import dataclass, field +from enum import Enum +from typing import Dict, Any, List, Optional, TYPE_CHECKING + +from .menu import AbstractSubMenu, Selector, MenuSelectionType, Menu, ListManager, TextInput +from .networking import fetch_data_from_url +from .output import info, warn, FormattedOutput from .storage import storage +if TYPE_CHECKING: + _: Any -@dataclass -class CustomMirror: - url: str - signcheck: str - signoptions: str - name: str +class SignCheck(Enum): + Never = 'Never' + Optional = 'Optional' + Required = 'Required' -def sort_mirrorlist(raw_data :bytes, sort_order: List[str] = ['https', 'http']) -> bytes: - """ - This function can sort /etc/pacman.d/mirrorlist according to the - mirror's URL prefix. By default places HTTPS before HTTP but it also - preserves the country/rank-order. - This assumes /etc/pacman.d/mirrorlist looks like the following: +class SignOption(Enum): + TrustedOnly = 'TrustedOnly' + TrustAll = 'TrustAll' - ## Comment - Server = url - or +@dataclass +class CustomMirror: + name: str + url: str + sign_check: SignCheck + sign_option: SignOption + + def as_json(self) -> Dict[str, str]: + return { + 'Name': self.name, + 'Url': self.url, + 'Sign check': self.sign_check.value, + 'Sign options': self.sign_option.value + } + + def json(self) -> Dict[str, str]: + return { + 'name': self.name, + 'url': self.url, + 'sign_check': self.sign_check.value, + 'sign_option': self.sign_option.value + } + + @classmethod + def parse_args(cls, args: List[Dict[str, str]]) -> List['CustomMirror']: + configs = [] + for arg in args: + configs.append( + CustomMirror( + arg['name'], + arg['url'], + SignCheck(arg['sign_check']), + SignOption(arg['sign_option']) + ) + ) + + return configs - ## Comment - #Server = url - But the Comments need to start with double-hashmarks to be distringuished - from server url definitions (commented or uncommented). - """ - comments_and_whitespaces = b"" - sort_order += ['Unknown'] - categories: Dict[str, List] = {key: [] for key in sort_order} - - for line in raw_data.split(b"\n"): - if line[0:2] in (b'##', b''): - comments_and_whitespaces += line + b'\n' - elif line[:6].lower() == b'server' or line[:7].lower() == b'#server': - opening, url = line.split(b'=', 1) - opening, url = opening.strip(), url.strip() - if (category := url.split(b'://',1)[0].decode('UTF-8')) in categories: - categories[category].append(comments_and_whitespaces) - categories[category].append(opening + b' = ' + url + b'\n') - else: - categories["Unknown"].append(comments_and_whitespaces) - categories["Unknown"].append(opening + b' = ' + url + b'\n') - - comments_and_whitespaces = b"" - - new_raw_data = b'' - for category in sort_order + ["Unknown"]: - for line in categories[category]: - new_raw_data += line - - return new_raw_data - - -def filter_mirrors_by_region(regions :str, - destination :str = '/etc/pacman.d/mirrorlist', - sort_order :List[str] = ["https", "http"], - *args :str, - **kwargs :str -) -> Union[bool, bytes]: +@dataclass +class MirrorConfiguration: + mirror_regions: Dict[str, List[str]] = field(default_factory=dict) + custom_mirrors: List[CustomMirror] = field(default_factory=list) + + @property + def regions(self) -> str: + return ', '.join(self.mirror_regions.keys()) + + def json(self) -> Dict[str, Any]: + return { + 'mirror_regions': self.mirror_regions, + 'custom_mirrors': [c.json() for c in self.custom_mirrors] + } + + @classmethod + def parse_args(cls, args: Dict[str, Any]) -> 'MirrorConfiguration': + config = MirrorConfiguration() + + if 'mirror_regions' in args: + config.mirror_regions = args['mirror_regions'] + + if 'custom_mirrors' in args: + config.custom_mirrors = CustomMirror.parse_args(args['custom_mirrors']) + + return config + + +class CustomMirrorList(ListManager): + def __init__(self, prompt: str, custom_mirrors: List[CustomMirror]): + self._actions = [ + str(_('Add a custom mirror')), + str(_('Change custom mirror')), + str(_('Delete custom mirror')) + ] + super().__init__(prompt, custom_mirrors, [self._actions[0]], self._actions[1:]) + + def reformat(self, data: List[CustomMirror]) -> Dict[str, Any]: + table = FormattedOutput.as_table(data) + rows = table.split('\n') + + # these are the header rows of the table and do not map to any User obviously + # we're adding 2 spaces as prefix because the menu selector '> ' will be put before + # the selectable rows so the header has to be aligned + display_data: Dict[str, Optional[CustomMirror]] = {f' {rows[0]}': None, f' {rows[1]}': None} + + for row, user in zip(rows[2:], data): + row = row.replace('|', '\\|') + display_data[row] = user + + return display_data + + def selected_action_display(self, mirror: CustomMirror) -> str: + return mirror.name + + def handle_action( + self, + action: str, + entry: Optional[CustomMirror], + data: List[CustomMirror] + ) -> List[CustomMirror]: + if action == self._actions[0]: # add + new_mirror = self._add_custom_mirror() + if new_mirror is not None: + data = [d for d in data if d.name != new_mirror.name] + data += [new_mirror] + elif action == self._actions[1] and entry: # modify mirror + new_mirror = self._add_custom_mirror(entry) + if new_mirror is not None: + data = [d for d in data if d.name != entry.name] + data += [new_mirror] + elif action == self._actions[2] and entry: # delete + data = [d for d in data if d != entry] + + return data + + def _add_custom_mirror(self, mirror: Optional[CustomMirror] = None) -> Optional[CustomMirror]: + prompt = '\n\n' + str(_('Enter name (leave blank to skip): ')) + existing_name = mirror.name if mirror else '' + + while True: + name = TextInput(prompt, existing_name).run() + if not name: + return mirror + break + + prompt = '\n' + str(_('Enter url (leave blank to skip): ')) + existing_url = mirror.url if mirror else '' + + while True: + url = TextInput(prompt, existing_url).run() + if not url: + return mirror + break + + sign_check_choice = Menu( + str(_('Select signature check option')), + [s.value for s in SignCheck], + skip=False, + clear_screen=False, + preset_values=mirror.sign_check.value if mirror else None + ).run() + + sign_option_choice = Menu( + str(_('Select signature option')), + [s.value for s in SignOption], + skip=False, + clear_screen=False, + preset_values=mirror.sign_option.value if mirror else None + ).run() + + return CustomMirror( + name, + url, + SignCheck(sign_check_choice.single_value), + SignOption(sign_option_choice.single_value) + ) + + +class MirrorMenu(AbstractSubMenu): + def __init__( + self, + data_store: Dict[str, Any], + preset: Optional[MirrorConfiguration] = None + ): + if preset: + self._preset = preset + else: + self._preset = MirrorConfiguration() + + super().__init__(data_store=data_store) + + def setup_selection_menu_options(self): + self._menu_options['mirror_regions'] = \ + Selector( + _('Mirror region'), + lambda preset: select_mirror_regions(preset), + display_func=lambda x: ', '.join(x.keys()) if x else '', + default=self._preset.mirror_regions, + enabled=True) + self._menu_options['custom_mirrors'] = \ + Selector( + _('Custom mirrors'), + lambda preset: select_custom_mirror(preset=preset), + display_func=lambda x: str(_('Defined')) if x else '', + preview_func=self._prev_custom_mirror, + default=self._preset.custom_mirrors, + enabled=True + ) + + def _prev_custom_mirror(self) -> Optional[str]: + selector = self._menu_options['custom_mirrors'] + + if selector.has_selection(): + custom_mirrors: List[CustomMirror] = selector.current_selection # type: ignore + output = FormattedOutput.as_table(custom_mirrors) + return output.strip() + + return None + + def run(self, allow_reset: bool = True) -> Optional[MirrorConfiguration]: + super().run(allow_reset=allow_reset) + + if self._data_store.get('mirror_regions', None) or self._data_store.get('custom_mirrors', None): + return MirrorConfiguration( + mirror_regions=self._data_store['mirror_regions'], + custom_mirrors=self._data_store['custom_mirrors'], + ) + + return None + + +def select_mirror_regions(preset_values: Dict[str, List[str]] = {}) -> Dict[str, List[str]]: """ - This function will change the active mirrors on the live medium by - filtering which regions are active based on `regions`. + Asks the user to select a mirror or region + Usually this is combined with :ref:`archinstall.list_mirrors`. - :param regions: A series of country codes separated by `,`. For instance `SE,US` for sweden and United States. - :type regions: str + :return: The dictionary information about a mirror/region. + :rtype: dict """ - region_list = [f'country={region}' for region in regions.split(',')] - response = urllib.request.urlopen(urllib.request.Request(f"https://archlinux.org/mirrorlist/?{'&'.join(region_list)}&protocol=https&protocol=http&ip_version=4&ip_version=6&use_mirror_status=on'", headers={'User-Agent': 'ArchInstall'})) - new_list = response.read().replace(b"#Server", b"Server") + if preset_values is None: + preselected = None + else: + preselected = list(preset_values.keys()) - if sort_order: - new_list = sort_mirrorlist(new_list, sort_order=sort_order) + mirrors = list_mirrors() - if destination: - with open(destination, "wb") as mirrorlist: - mirrorlist.write(new_list) + choice = Menu( + _('Select one of the regions to download packages from'), + list(mirrors.keys()), + preset_values=preselected, + multi=True, + allow_reset=True + ).run() - return True - else: - return new_list.decode('UTF-8') + match choice.type_: + case MenuSelectionType.Reset: + return {} + case MenuSelectionType.Skip: + return preset_values + case MenuSelectionType.Selection: + return {selected: mirrors[selected] for selected in choice.multi_value} + + return {} -def add_custom_mirrors(mirrors: List[CustomMirror]) -> bool: +def select_custom_mirror(prompt: str = '', preset: List[CustomMirror] = []): + custom_mirrors = CustomMirrorList(prompt, preset).run() + return custom_mirrors + + +def add_custom_mirrors(mirrors: List[CustomMirror]): """ This will append custom mirror definitions in pacman.conf @@ -102,99 +282,57 @@ def add_custom_mirrors(mirrors: List[CustomMirror]) -> bool: """ with open('/etc/pacman.conf', 'a') as pacman: for mirror in mirrors: - pacman.write(f"[{mirror.name}]\n") - pacman.write(f"SigLevel = {mirror.signcheck} {mirror.signoptions}\n") + pacman.write(f"\n\n[{mirror.name}]\n") + pacman.write(f"SigLevel = {mirror.sign_check.value} {mirror.sign_option.value}\n") pacman.write(f"Server = {mirror.url}\n") - return True - - -def insert_mirrors(mirrors :Dict[str, Any], *args :str, **kwargs :str) -> bool: - """ - This function will insert a given mirror-list at the top of `/etc/pacman.d/mirrorlist`. - It will not flush any other mirrors, just insert new ones. - - :param mirrors: A dictionary of `{'url' : 'country', 'url2' : 'country'}` - :type mirrors: dict - """ - original_mirrorlist = '' - with open('/etc/pacman.d/mirrorlist', 'r') as original: - original_mirrorlist = original.read() - - with open('/etc/pacman.d/mirrorlist', 'w') as new_mirrorlist: - for mirror, country in mirrors.items(): - new_mirrorlist.write(f'## {country}\n') - new_mirrorlist.write(f'Server = {mirror}\n') - new_mirrorlist.write('\n') - new_mirrorlist.write(original_mirrorlist) - - return True - def use_mirrors( - regions: Dict[str, Iterable[str]], + regions: Dict[str, List[str]], destination: str = '/etc/pacman.d/mirrorlist' ): - info(f'A new package mirror-list has been created: {destination}') - with open(destination, 'w') as mirrorlist: + with open(destination, 'w') as fp: for region, mirrors in regions.items(): for mirror in mirrors: - mirrorlist.write(f'## {region}\n') - mirrorlist.write(f'Server = {mirror}\n') + fp.write(f'## {region}\n') + fp.write(f'Server = {mirror}\n') + + info(f'A new package mirror-list has been created: {destination}') + +def _parse_mirror_list(mirrorlist: str) -> Dict[str, List[str]]: + file_content = mirrorlist.split('\n') + file_content = list(filter(lambda x: x, file_content)) # filter out empty lines + first_srv_idx = [idx for idx, line in enumerate(file_content) if 'server' in line.lower()][0] + mirrors = file_content[first_srv_idx - 1:] -def re_rank_mirrors( - top: int = 10, - src: str = '/etc/pacman.d/mirrorlist', - dst: str = '/etc/pacman.d/mirrorlist', -) -> bool: - try: - cmd = SysCommand(f"/usr/bin/rankmirrors -n {top} {src}") - except SysCallError: - return False - with open(dst, 'w') as f: - f.write(str(cmd)) - return True + mirror_list: Dict[str, List[str]] = {} + for idx in range(0, len(mirrors), 2): + region = mirrors[idx].removeprefix('## ') + url = mirrors[idx + 1].removeprefix('#').removeprefix('Server = ') + mirror_list.setdefault(region, []).append(url) -def list_mirrors(sort_order :List[str] = ["https", "http"]) -> Dict[str, Any]: - regions: Dict[str, Dict[str, Any]] = {} + return mirror_list + + +def list_mirrors() -> Dict[str, List[str]]: + regions: Dict[str, List[str]] = {} if storage['arguments']['offline']: - with pathlib.Path('/etc/pacman.d/mirrorlist').open('rb') as fh: - mirrorlist = fh.read() + with pathlib.Path('/etc/pacman.d/mirrorlist').open('r') as fp: + mirrorlist = fp.read() else: url = "https://archlinux.org/mirrorlist/?protocol=https&protocol=http&ip_version=4&ip_version=6&use_mirror_status=on" - try: - response = urllib.request.urlopen(url) - except urllib.error.URLError as err: + mirrorlist = fetch_data_from_url(url) + except ValueError as err: warn(f'Could not fetch an active mirror-list: {err}') return regions - mirrorlist = response.read() - - if sort_order: - mirrorlist = sort_mirrorlist(mirrorlist, sort_order=sort_order) - - region = 'Unknown region' - for line in mirrorlist.split(b'\n'): - if len(line.strip()) == 0: - continue - - clean_line = line.decode('UTF-8').strip('\n').strip('\r') - - if clean_line[:3] == '## ': - region = clean_line[3:] - elif clean_line[:10] == '#Server = ': - regions.setdefault(region, {}) - - url = clean_line.lstrip('#Server = ') - regions[region][url] = True - elif clean_line.startswith('Server = '): - regions.setdefault(region, {}) - - url = clean_line.lstrip('Server = ') - regions[region][url] = True + regions = _parse_mirror_list(mirrorlist) + sorted_regions = {} + for region, urls in regions.items(): + sorted_regions[region] = sorted(urls, reverse=True) - return regions + return sorted_regions diff --git a/archinstall/scripts/guided.py b/archinstall/scripts/guided.py index 1e19c9a3..1aecc1cd 100644 --- a/archinstall/scripts/guided.py +++ b/archinstall/scripts/guided.py @@ -11,7 +11,7 @@ from archinstall.default_profiles.applications.pipewire import PipewireProfile from archinstall.lib.configuration import ConfigurationOutput from archinstall.lib.installer import Installer from archinstall.lib.menu import Menu -from archinstall.lib.mirrors import use_mirrors +from archinstall.lib.mirrors import use_mirrors, add_custom_mirrors from archinstall.lib.models.bootloader import Bootloader from archinstall.lib.models.network_configuration import NetworkConfigurationHandler from archinstall.lib.networking import check_mirror_reachable @@ -45,7 +45,7 @@ def ask_user_questions(): global_menu.enable('keyboard-layout') # Set which region to download packages from during the installation - global_menu.enable('mirror-region') + global_menu.enable('mirror_config') global_menu.enable('sys-language') @@ -137,8 +137,11 @@ def perform_installation(mountpoint: Path): installation.generate_key_files() # Set mirrors used by pacstrap (outside of installation) - if archinstall.arguments.get('mirror-region', None): - use_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors for the live medium + if mirror_config := archinstall.arguments.get('mirror_config', None): + if mirror_config.mirror_regions: + use_mirrors(mirror_config.mirror_regions) + if mirror_config.custom_mirrors: + add_custom_mirrors(mirror_config.custom_mirrors) installation.minimal_installation( testing=enable_testing, @@ -147,9 +150,8 @@ def perform_installation(mountpoint: Path): locales=[locale] ) - if archinstall.arguments.get('mirror-region') is not None: - if archinstall.arguments.get("mirrors", None) is not None: - installation.set_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors in the installation medium + if mirror_config := archinstall.arguments.get('mirror_config', None): + installation.set_mirrors(mirror_config) # Set the mirrors in the installation medium if archinstall.arguments.get('swap'): installation.setup_swap('zram') diff --git a/archinstall/scripts/swiss.py b/archinstall/scripts/swiss.py index a49f568d..1998f073 100644 --- a/archinstall/scripts/swiss.py +++ b/archinstall/scripts/swiss.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict import archinstall from archinstall import SysInfo, info, debug -from archinstall.lib.mirrors import use_mirrors +from archinstall.lib import mirrors from archinstall.lib import models from archinstall.lib import disk from archinstall.lib.networking import check_mirror_reachable @@ -92,7 +92,7 @@ class SwissMainMenu(GlobalMenu): match self._execution_mode: case ExecutionMode.Full | ExecutionMode.Lineal: options_list = [ - 'keyboard-layout', 'mirror-region', 'disk_config', + 'keyboard-layout', 'mirror_config', 'disk_config', 'disk_encryption', 'swap', 'bootloader', 'hostname', '!root-password', '!users', 'profile_config', 'audio', 'kernels', 'packages', 'additional-repositories', 'nic', 'timezone', 'ntp' @@ -107,7 +107,7 @@ class SwissMainMenu(GlobalMenu): mandatory_list = ['disk_config'] case ExecutionMode.Only_OS: options_list = [ - 'keyboard-layout', 'mirror-region','bootloader', 'hostname', + 'keyboard-layout', 'mirror_config','bootloader', 'hostname', '!root-password', '!users', 'profile_config', 'audio', 'kernels', 'packages', 'additional-repositories', 'nic', 'timezone', 'ntp' ] @@ -196,8 +196,11 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode): installation.generate_key_files() # Set mirrors used by pacstrap (outside of installation) - if archinstall.arguments.get('mirror-region', None): - use_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors for the live medium + if mirror_config := archinstall.arguments.get('mirror_config', None): + if mirror_config.mirror_regions: + mirrors.use_mirrors(mirror_config.mirror_regions) + if mirror_config.custom_mirrors: + mirrors.add_custom_mirrors(mirror_config.custom_mirrors) installation.minimal_installation( testing=enable_testing, @@ -206,10 +209,8 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode): locales=[locale] ) - if archinstall.arguments.get('mirror-region') is not None: - if archinstall.arguments.get("mirrors", None) is not None: - installation.set_mirrors( - archinstall.arguments['mirror-region']) # Set the mirrors in the installation medium + if mirror_config := archinstall.arguments.get('mirror_config', None): + installation.set_mirrors(mirror_config) # Set the mirrors in the installation medium if archinstall.arguments.get('swap'): installation.setup_swap('zram') diff --git a/examples/interactive_installation.py b/examples/interactive_installation.py index 487db4dd..7c4ffed7 100644 --- a/examples/interactive_installation.py +++ b/examples/interactive_installation.py @@ -24,7 +24,7 @@ def ask_user_questions(): global_menu.enable('keyboard-layout') # Set which region to download packages from during the installation - global_menu.enable('mirror-region') + global_menu.enable('mirror_config') global_menu.enable('sys-language') @@ -116,8 +116,11 @@ def perform_installation(mountpoint: Path): installation.generate_key_files() # Set mirrors used by pacstrap (outside of installation) - if archinstall.arguments.get('mirror-region', None): - mirrors.use_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors for the live medium + if mirror_config := archinstall.arguments.get('mirror_config', None): + if mirror_config.mirror_regions: + mirrors.use_mirrors(mirror_config.mirror_regions) + if mirror_config.custom_mirrors: + mirrors.add_custom_mirrors(mirror_config.custom_mirrors) installation.minimal_installation( testing=enable_testing, @@ -126,9 +129,8 @@ def perform_installation(mountpoint: Path): locales=[locale] ) - if archinstall.arguments.get('mirror-region') is not None: - if archinstall.arguments.get("mirrors", None) is not None: - installation.set_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors in the installation medium + if mirror_config := archinstall.arguments.get('mirror_config', None): + installation.set_mirrors(mirror_config) # Set the mirrors in the installation medium if archinstall.arguments.get('swap'): installation.setup_swap('zram') -- cgit v1.2.3-54-g00ecf From 06eadb31d4f0bca0c8cb95b6a9eb62ddd2d7cff2 Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Mon, 5 Jun 2023 18:02:49 +1000 Subject: Move locales and cleanup menu (#1814) * Cleanup imports and unused code * Cleanup imports and unused code * Update build check * Keep deprecation exception * Simplify logging * Move locale into new sub-menu --------- Co-authored-by: Daniel Girtler --- archinstall/__init__.py | 3 +- archinstall/default_profiles/profile.py | 19 +--- archinstall/lib/global_menu.py | 95 +++++++++++----- archinstall/lib/hardware.py | 2 +- archinstall/lib/installer.py | 38 +++---- archinstall/lib/interactions/__init__.py | 3 +- archinstall/lib/interactions/general_conf.py | 12 +-- archinstall/lib/interactions/locale_conf.py | 43 -------- archinstall/lib/interactions/system_conf.py | 6 +- archinstall/lib/locale/__init__.py | 6 ++ archinstall/lib/locale/locale.py | 68 ++++++++++++ archinstall/lib/locale/locale_menu.py | 155 +++++++++++++++++++++++++++ archinstall/lib/menu/abstract_menu.py | 38 +------ archinstall/lib/utils/util.py | 23 +++- archinstall/scripts/guided.py | 17 ++- archinstall/scripts/swiss.py | 16 +-- examples/interactive_installation.py | 17 ++- 17 files changed, 374 insertions(+), 187 deletions(-) delete mode 100644 archinstall/lib/interactions/locale_conf.py create mode 100644 archinstall/lib/locale/__init__.py create mode 100644 archinstall/lib/locale/locale.py create mode 100644 archinstall/lib/locale/locale_menu.py (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/__init__.py b/archinstall/__init__.py index e6fcb267..ce58e255 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -213,8 +213,7 @@ def load_config(): """ from .lib.models import NetworkConfiguration - arguments.setdefault('sys-language', 'en_US') - arguments.setdefault('sys-encoding', 'utf-8') + arguments['locale_config'] = locale.LocaleConfiguration.parse_arg(arguments) if (archinstall_lang := arguments.get('archinstall-language', None)) is not None: arguments['archinstall-language'] = TranslationHandler().get_language_by_name(archinstall_lang) diff --git a/archinstall/default_profiles/profile.py b/archinstall/default_profiles/profile.py index b1ad1f50..ce07c286 100644 --- a/archinstall/default_profiles/profile.py +++ b/archinstall/default_profiles/profile.py @@ -3,7 +3,7 @@ from __future__ import annotations from enum import Enum, auto from typing import List, Optional, Any, Dict, TYPE_CHECKING, TypeVar -from archinstall.lib.output import FormattedOutput +from archinstall.lib.utils.util import format_cols if TYPE_CHECKING: from archinstall.lib.installer import Installer @@ -185,17 +185,6 @@ class Profile: return None def packages_text(self) -> str: - text = str(_('Installed packages')) + ':\n' - - nr_packages = len(self.packages) - if nr_packages <= 5: - col = 1 - elif nr_packages <= 10: - col = 2 - elif nr_packages <= 15: - col = 3 - else: - col = 4 - - text += FormattedOutput.as_columns(self.packages, col) - return text + header = str(_('Installed packages')) + output = format_cols(self.packages, header) + return output diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index fc58a653..91ebc6a0 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -4,6 +4,7 @@ from typing import Any, List, Optional, Union, Dict, TYPE_CHECKING from . import disk from .general import secret +from .locale.locale_menu import LocaleConfiguration, LocaleMenu from .menu import Selector, AbstractMenu from .mirrors import MirrorConfiguration, MirrorMenu from .models import NetworkConfiguration @@ -24,9 +25,7 @@ from .interactions import ask_to_configure_network from .interactions import get_password, ask_for_a_timezone from .interactions import select_additional_repositories from .interactions import select_kernel -from .interactions import select_language -from .interactions import select_locale_enc -from .interactions import select_locale_lang +from .utils.util import format_cols from .interactions import ask_ntp from .interactions.disk_conf import select_disk_config @@ -36,6 +35,7 @@ if TYPE_CHECKING: class GlobalMenu(AbstractMenu): def __init__(self, data_store: Dict[str, Any]): + self._defined_text = str(_('Defined')) super().__init__(data_store=data_store, auto_cursor=True, preview_size=0.3) def setup_selection_menu_options(self): @@ -46,28 +46,19 @@ class GlobalMenu(AbstractMenu): lambda x: self._select_archinstall_language(x), display_func=lambda x: x.display_name, default=self.translation_handler.get_language_by_abbr('en')) - self._menu_options['keyboard-layout'] = \ + self._menu_options['locale_config'] = \ Selector( - _('Keyboard layout'), - lambda preset: select_language(preset), - default='us') + _('Locales'), + lambda preset: self._locale_selection(preset), + preview_func=self._prev_locale, + display_func=lambda x: self._defined_text if x else '') self._menu_options['mirror_config'] = \ Selector( _('Mirrors'), lambda preset: self._mirror_configuration(preset), - display_func=lambda x: str(_('Defined')) if x else '', + display_func=lambda x: self._defined_text if x else '', preview_func=self._prev_mirror_config ) - self._menu_options['sys-language'] = \ - Selector( - _('Locale language'), - lambda preset: select_locale_lang(preset), - default='en_US') - self._menu_options['sys-encoding'] = \ - Selector( - _('Locale encoding'), - lambda preset: select_locale_enc(preset), - default='UTF-8') self._menu_options['disk_config'] = \ Selector( _('Disk configuration'), @@ -103,32 +94,32 @@ class GlobalMenu(AbstractMenu): Selector( _('Root password'), lambda preset:self._set_root_password(), - display_func=lambda x: secret(x) if x else 'None') + display_func=lambda x: secret(x) if x else '') self._menu_options['!users'] = \ Selector( _('User account'), lambda x: self._create_user_account(x), default=[], - display_func=lambda x: f'{len(x)} {_("User(s)")}' if len(x) > 0 else None, + display_func=lambda x: f'{len(x)} {_("User(s)")}' if len(x) > 0 else '', preview_func=self._prev_users) self._menu_options['profile_config'] = \ Selector( _('Profile'), lambda preset: self._select_profile(preset), - display_func=lambda x: x.profile.name if x else 'None', + display_func=lambda x: x.profile.name if x else '', preview_func=self._prev_profile ) self._menu_options['audio'] = \ Selector( _('Audio'), lambda preset: self._select_audio(preset), - display_func=lambda x: x if x else 'None', + display_func=lambda x: x if x else '', default=None ) self._menu_options['parallel downloads'] = \ Selector( _('Parallel Downloads'), - add_number_of_parrallel_downloads, + lambda preset: add_number_of_parrallel_downloads(preset), display_func=lambda x: x if x else '0', default=0 ) @@ -141,19 +132,20 @@ class GlobalMenu(AbstractMenu): self._menu_options['packages'] = \ Selector( _('Additional packages'), - # lambda x: ask_additional_packages_to_install(storage['arguments'].get('packages', None)), - ask_additional_packages_to_install, + lambda preset: ask_additional_packages_to_install(preset), + display_func=lambda x: self._defined_text if x else '', + preview_func=self._prev_additional_pkgs, default=[]) self._menu_options['additional-repositories'] = \ Selector( _('Optional repositories'), - select_additional_repositories, + lambda preset: select_additional_repositories(preset), display_func=lambda x: ', '.join(x) if x else None, default=[]) self._menu_options['nic'] = \ Selector( _('Network configuration'), - ask_to_configure_network, + lambda preset: ask_to_configure_network(preset), display_func=lambda x: self._display_network_conf(x), preview_func=self._prev_network_config, default={}) @@ -177,12 +169,37 @@ class GlobalMenu(AbstractMenu): self._menu_options['install'] = \ Selector( self._install_text(), - exec_func=lambda n,v: True if len(self._missing_configs()) == 0 else False, + exec_func=lambda n, v: True if len(self._missing_configs()) == 0 else False, preview_func=self._prev_install_missing_config, no_store=True) self._menu_options['abort'] = Selector(_('Abort'), exec_func=lambda n,v:exit(1)) + def _missing_configs(self) -> List[str]: + def check(s): + return self._menu_options.get(s).has_selection() + + def has_superuser() -> bool: + sel = self._menu_options['!users'] + if sel.current_selection: + return any([u.sudo for u in sel.current_selection]) + return False + + mandatory_fields = dict(filter(lambda x: x[1].is_mandatory(), self._menu_options.items())) + missing = set() + + for key, selector in mandatory_fields.items(): + if key in ['!root-password', '!users']: + if not check('!root-password') and not has_superuser(): + missing.add( + str(_('Either root-password or at least 1 user with sudo privileges must be specified')) + ) + elif key == 'disk_config': + if not check('disk_config'): + missing.add(self._menu_options['disk_config'].description) + + return list(missing) + def _update_install_text(self, name: str, value: str): text = self._install_text() self._menu_options['install'].update_description(text) @@ -216,6 +233,21 @@ class GlobalMenu(AbstractMenu): disk_encryption = disk.DiskEncryptionMenu(mods, data_store, preset=preset).run() return disk_encryption + def _locale_selection(self, preset: LocaleConfiguration) -> LocaleConfiguration: + data_store: Dict[str, Any] = {} + locale_config = LocaleMenu(data_store, preset).run() + return locale_config + + def _prev_locale(self) -> Optional[str]: + selector = self._menu_options['locale_config'] + if selector.has_selection(): + config: LocaleConfiguration = selector.current_selection # type: ignore + output = '{}: {}\n'.format(str(_('Keyboard layout')), config.kb_layout) + output += '{}: {}\n'.format(str(_('Locale language')), config.sys_lang) + output += '{}: {}'.format(str(_('Locale encoding')), config.sys_enc) + return output + return None + def _prev_network_config(self) -> Optional[str]: selector = self._menu_options['nic'] if selector.has_selection(): @@ -224,6 +256,13 @@ class GlobalMenu(AbstractMenu): return FormattedOutput.as_table(ifaces) return None + def _prev_additional_pkgs(self): + selector = self._menu_options['packages'] + if selector.has_selection(): + packages: List[str] = selector.current_selection + return format_cols(packages, None) + return None + def _prev_disk_layouts(self) -> Optional[str]: selector = self._menu_options['disk_config'] disk_layout_conf: Optional[disk.DiskLayoutConfiguration] = selector.current_selection diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index 220d3d37..2b65e07c 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -3,9 +3,9 @@ from functools import cached_property from pathlib import Path from typing import Optional, Dict, List +from .exceptions import SysCallError from .general import SysCommand from .networking import list_interfaces, enrich_iface_types -from .exceptions import SysCallError from .output import debug AVAILABLE_GFX_DRIVERS = { diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 30442774..6eac85fc 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -12,6 +12,7 @@ from . import disk from .exceptions import DiskError, ServiceException, RequirementError, HardwareIncompatibilityError, SysCallError from .general import SysCommand from .hardware import SysInfo +from .locale import LocaleConfiguration from .locale import verify_keyboard_layout, verify_x11_keyboard_layout from .luks import Luks2 from .mirrors import use_mirrors, MirrorConfiguration, add_custom_mirrors @@ -457,37 +458,36 @@ class Installer: with open(f'{self.target}/etc/hostname', 'w') as fh: fh.write(hostname + '\n') - def set_locale(self, locale :str, encoding :str = 'UTF-8', *args :str, **kwargs :str) -> bool: - if not len(locale): - return True - + def set_locale(self, locale_config: LocaleConfiguration): modifier = '' + lang = locale_config.sys_lang + encoding = locale_config.sys_enc # This is a temporary patch to fix #1200 - if '.' in locale: - locale, potential_encoding = locale.split('.', 1) + if '.' in locale_config.sys_lang: + lang, potential_encoding = locale_config.sys_lang.split('.', 1) # Override encoding if encoding is set to the default parameter # and the "found" encoding differs. - if encoding == 'UTF-8' and encoding != potential_encoding: + if locale_config.sys_enc == 'UTF-8' and locale_config.sys_enc != potential_encoding: encoding = potential_encoding # Make sure we extract the modifier, that way we can put it in if needed. - if '@' in locale: - locale, modifier = locale.split('@', 1) + if '@' in locale_config.sys_lang: + lang, modifier = locale_config.sys_lang.split('@', 1) modifier = f"@{modifier}" # - End patch with open(f'{self.target}/etc/locale.gen', 'a') as fh: - fh.write(f'{locale}.{encoding}{modifier} {encoding}\n') + fh.write(f'{lang}.{encoding}{modifier} {encoding}\n') + with open(f'{self.target}/etc/locale.conf', 'w') as fh: - fh.write(f'LANG={locale}.{encoding}{modifier}\n') + fh.write(f'LANG={lang}.{encoding}{modifier}\n') try: SysCommand(f'/usr/bin/arch-chroot {self.target} locale-gen') - return True - except SysCallError: - return False + except SysCallError as e: + error(f'Failed to run locale-gen on target: {e}') def set_timezone(self, zone :str, *args :str, **kwargs :str) -> bool: if not zone: @@ -620,7 +620,7 @@ class Installer: return True - def mkinitcpio(self, *flags :str) -> bool: + def mkinitcpio(self, flags: List[str], locale_config: LocaleConfiguration) -> bool: for plugin in plugins.values(): if hasattr(plugin, 'on_mkinitcpio'): # Allow plugins to override the usage of mkinitcpio altogether. @@ -630,7 +630,7 @@ class Installer: # mkinitcpio will error out if there's no vconsole. if (vconsole := Path(f"{self.target}/etc/vconsole.conf")).exists() is False: with vconsole.open('w') as fh: - fh.write(f"KEYMAP={storage['arguments']['keyboard-layout']}\n") + fh.write(f"KEYMAP={locale_config.kb_layout}\n") with open(f'{self.target}/etc/mkinitcpio.conf', 'w') as mkinit: mkinit.write(f"MODULES=({' '.join(self.modules)})\n") @@ -658,7 +658,7 @@ class Installer: testing: bool = False, multilib: bool = False, hostname: str = 'archinstall', - locales: List[str] = ['en_US.UTF-8 UTF-8'] + locale_config: LocaleConfiguration = LocaleConfiguration.default() ): for mod in self._disk_config.device_modifications: for part in mod.partitions: @@ -734,12 +734,12 @@ class Installer: # sys_command(f'/usr/bin/arch-chroot {self.target} ln -s /usr/share/zoneinfo/{localtime} /etc/localtime') # sys_command('/usr/bin/arch-chroot /mnt hwclock --hctosys --localtime') self.set_hostname(hostname) - self.set_locale(*locales[0].split()) + self.set_locale(locale_config) # TODO: Use python functions for this SysCommand(f'/usr/bin/arch-chroot {self.target} chmod 700 /root') - self.mkinitcpio('-P') + self.mkinitcpio(['-P'], locale_config) self.helper_flags['base'] = True diff --git a/archinstall/lib/interactions/__init__.py b/archinstall/lib/interactions/__init__.py index 158750cc..466cfa0b 100644 --- a/archinstall/lib/interactions/__init__.py +++ b/archinstall/lib/interactions/__init__.py @@ -1,4 +1,3 @@ -from .locale_conf import select_locale_lang, select_locale_enc from .manage_users_conf import UserList, ask_for_additional_users from .network_conf import ManualNetworkConfig, ask_to_configure_network from .utils import get_password @@ -10,7 +9,7 @@ from .disk_conf import ( ) from .general_conf import ( - ask_ntp, ask_hostname, ask_for_a_timezone, ask_for_audio_selection, select_language, + ask_ntp, ask_hostname, ask_for_a_timezone, ask_for_audio_selection, select_archinstall_language, ask_additional_packages_to_install, add_number_of_parrallel_downloads, select_additional_repositories ) diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index 0338c61e..3b78847b 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -3,7 +3,7 @@ from __future__ import annotations import pathlib from typing import List, Any, Optional, TYPE_CHECKING -from ..locale import list_keyboard_languages, list_timezones +from ..locale import list_timezones, list_keyboard_languages from ..menu import MenuSelectionType, Menu, TextInput from ..output import warn from ..packages.packages import validate_package_list @@ -119,18 +119,18 @@ def select_archinstall_language(languages: List[Language], preset: Language) -> raise ValueError('Language selection not handled') -def ask_additional_packages_to_install(pre_set_packages: List[str] = []) -> List[str]: +def ask_additional_packages_to_install(preset: List[str] = []) -> List[str]: # Additional packages (with some light weight error handling for invalid package names) print(_('Only packages such as base, base-devel, linux, linux-firmware, efibootmgr and optional profile packages are installed.')) print(_('If you desire a web browser, such as firefox or chromium, you may specify it in the following prompt.')) - def read_packages(already_defined: list = []) -> list: - display = ' '.join(already_defined) + def read_packages(p: List = []) -> list: + display = ' '.join(p) input_packages = TextInput(_('Write additional packages to install (space separated, leave blank to skip): '), display).run().strip() return input_packages.split() if input_packages else [] - pre_set_packages = pre_set_packages if pre_set_packages else [] - packages = read_packages(pre_set_packages) + preset = preset if preset else [] + packages = read_packages(preset) if not storage['arguments']['offline'] and not storage['arguments']['no_pkg_lookups']: while True: diff --git a/archinstall/lib/interactions/locale_conf.py b/archinstall/lib/interactions/locale_conf.py deleted file mode 100644 index de115202..00000000 --- a/archinstall/lib/interactions/locale_conf.py +++ /dev/null @@ -1,43 +0,0 @@ -from typing import Any, TYPE_CHECKING, Optional - -from ..locale import list_locales -from ..menu import Menu, MenuSelectionType - -if TYPE_CHECKING: - _: Any - - -def select_locale_lang(preset: Optional[str] = None) -> Optional[str]: - locales = list_locales() - locale_lang = set([locale.split()[0] for locale in locales]) - - choice = Menu( - _('Choose which locale language to use'), - list(locale_lang), - sort=True, - preset_values=preset - ).run() - - match choice.type_: - case MenuSelectionType.Selection: return choice.single_value - case MenuSelectionType.Skip: return preset - - return None - - -def select_locale_enc(preset: Optional[str] = None) -> Optional[str]: - locales = list_locales() - locale_enc = set([locale.split()[1] for locale in locales]) - - choice = Menu( - _('Choose which locale encoding to use'), - list(locale_enc), - sort=True, - preset_values=preset - ).run() - - match choice.type_: - case MenuSelectionType.Selection: return choice.single_value - case MenuSelectionType.Skip: return preset - - return None diff --git a/archinstall/lib/interactions/system_conf.py b/archinstall/lib/interactions/system_conf.py index bbcb5b23..ea7e5989 100644 --- a/archinstall/lib/interactions/system_conf.py +++ b/archinstall/lib/interactions/system_conf.py @@ -29,14 +29,14 @@ def select_kernel(preset: List[str] = []) -> List[str]: sort=True, multi=True, preset_values=preset, - allow_reset=True, allow_reset_warning_msg=warning ).run() match choice.type_: case MenuSelectionType.Skip: return preset - case MenuSelectionType.Reset: return [] - case MenuSelectionType.Selection: return choice.value # type: ignore + case MenuSelectionType.Selection: return choice.single_value + + return [] def ask_for_bootloader(preset: Bootloader) -> Bootloader: diff --git a/archinstall/lib/locale/__init__.py b/archinstall/lib/locale/__init__.py new file mode 100644 index 00000000..6c32d6f3 --- /dev/null +++ b/archinstall/lib/locale/__init__.py @@ -0,0 +1,6 @@ +from .locale_menu import LocaleConfiguration +from .locale import ( + list_keyboard_languages, list_locales, list_x11_keyboard_languages, + verify_keyboard_layout, verify_x11_keyboard_layout, set_kb_layout, + list_timezones +) diff --git a/archinstall/lib/locale/locale.py b/archinstall/lib/locale/locale.py new file mode 100644 index 00000000..c3294e83 --- /dev/null +++ b/archinstall/lib/locale/locale.py @@ -0,0 +1,68 @@ +from typing import Iterator, List + +from ..exceptions import ServiceException, SysCallError +from ..general import SysCommand +from ..output import error + + +def list_keyboard_languages() -> Iterator[str]: + for line in SysCommand("localectl --no-pager list-keymaps", environment_vars={'SYSTEMD_COLORS': '0'}): + yield line.decode('UTF-8').strip() + + +def list_locales() -> List[str]: + with open('/etc/locale.gen', 'r') as fp: + locales = [] + # before the list of locales begins there's an empty line with a '#' in front + # so we'll collect the localels from bottom up and halt when we're donw + entries = fp.readlines() + entries.reverse() + + for entry in entries: + text = entry.replace('#', '').strip() + if text == '': + break + locales.append(text) + + locales.reverse() + return locales + + +def list_x11_keyboard_languages() -> Iterator[str]: + for line in SysCommand("localectl --no-pager list-x11-keymap-layouts", environment_vars={'SYSTEMD_COLORS': '0'}): + yield line.decode('UTF-8').strip() + + +def verify_keyboard_layout(layout :str) -> bool: + for language in list_keyboard_languages(): + if layout.lower() == language.lower(): + return True + return False + + +def verify_x11_keyboard_layout(layout :str) -> bool: + for language in list_x11_keyboard_languages(): + if layout.lower() == language.lower(): + return True + return False + + +def set_kb_layout(locale :str) -> bool: + if len(locale.strip()): + if not verify_keyboard_layout(locale): + error(f"Invalid keyboard locale specified: {locale}") + return False + + try: + SysCommand(f'localectl set-keymap {locale}') + except SysCallError as err: + raise ServiceException(f"Unable to set locale '{locale}' for console: {err}") + + return True + + return False + + +def list_timezones() -> Iterator[str]: + for line in SysCommand("timedatectl --no-pager list-timezones", environment_vars={'SYSTEMD_COLORS': '0'}): + yield line.decode('UTF-8').strip() diff --git a/archinstall/lib/locale/locale_menu.py b/archinstall/lib/locale/locale_menu.py new file mode 100644 index 00000000..29dd775d --- /dev/null +++ b/archinstall/lib/locale/locale_menu.py @@ -0,0 +1,155 @@ +from dataclasses import dataclass +from typing import Dict, Any, TYPE_CHECKING, Optional + +from .locale import set_kb_layout, list_keyboard_languages, list_locales +from ..menu import Selector, AbstractSubMenu, MenuSelectionType, Menu + +if TYPE_CHECKING: + _: Any + + +@dataclass +class LocaleConfiguration: + kb_layout: str + sys_lang: str + sys_enc: str + + @staticmethod + def default() -> 'LocaleConfiguration': + return LocaleConfiguration('us', 'en_US', 'UTF-8') + + def json(self) -> Dict[str, str]: + return { + 'kb_layout': self.kb_layout, + 'sys_lang': self.sys_lang, + 'sys_enc': self.sys_enc + } + + @classmethod + def _load_config(cls, config: 'LocaleConfiguration', args: Dict[str, Any]) -> 'LocaleConfiguration': + if 'sys_lang' in args: + config.sys_lang = args['sys_lang'] + if 'sys_enc' in args: + config.sys_enc = args['sys_enc'] + if 'kb_layout' in args: + config.kb_layout = args['kb_layout'] + + return config + + @classmethod + def parse_arg(cls, args: Dict[str, Any]) -> 'LocaleConfiguration': + default = cls.default() + + if 'locale_config' in args: + default = cls._load_config(default, args['locale_config']) + else: + default = cls._load_config(default, args) + + return default + + +class LocaleMenu(AbstractSubMenu): + def __init__( + self, + data_store: Dict[str, Any], + locele_conf: LocaleConfiguration + ): + self._preset = locele_conf + super().__init__(data_store=data_store) + + def setup_selection_menu_options(self): + self._menu_options['keyboard-layout'] = \ + Selector( + _('Keyboard layout'), + lambda preset: self._select_kb_layout(preset), + default='us', + enabled=True) + self._menu_options['sys-language'] = \ + Selector( + _('Locale language'), + lambda preset: select_locale_lang(preset), + default='en_US', + enabled=True) + self._menu_options['sys-encoding'] = \ + Selector( + _('Locale encoding'), + lambda preset: select_locale_enc(preset), + default='UTF-8', + enabled=True) + + def run(self, allow_reset: bool = True) -> LocaleConfiguration: + super().run(allow_reset=allow_reset) + + return LocaleConfiguration( + self._data_store['keyboard-layout'], + self._data_store['sys-language'], + self._data_store['sys-encoding'] + ) + + def _select_kb_layout(self, preset: Optional[str]) -> Optional[str]: + kb_lang = select_kb_layout(preset) + if kb_lang: + set_kb_layout(kb_lang) + return kb_lang + + +def select_locale_lang(preset: Optional[str] = None) -> Optional[str]: + locales = list_locales() + locale_lang = set([locale.split()[0] for locale in locales]) + + choice = Menu( + _('Choose which locale language to use'), + list(locale_lang), + sort=True, + preset_values=preset + ).run() + + match choice.type_: + case MenuSelectionType.Selection: return choice.single_value + case MenuSelectionType.Skip: return preset + + return None + + +def select_locale_enc(preset: Optional[str] = None) -> Optional[str]: + locales = list_locales() + locale_enc = set([locale.split()[1] for locale in locales]) + + choice = Menu( + _('Choose which locale encoding to use'), + list(locale_enc), + sort=True, + preset_values=preset + ).run() + + match choice.type_: + case MenuSelectionType.Selection: return choice.single_value + case MenuSelectionType.Skip: return preset + + return None + + +def select_kb_layout(preset: Optional[str] = None) -> Optional[str]: + """ + Asks the user to select a language + Usually this is combined with :ref:`archinstall.list_keyboard_languages`. + + :return: The language/dictionary key of the selected language + :rtype: str + """ + kb_lang = list_keyboard_languages() + # sort alphabetically and then by length + sorted_kb_lang = sorted(sorted(list(kb_lang)), key=len) + + choice = Menu( + _('Select keyboard layout'), + sorted_kb_lang, + preset_values=preset, + sort=False + ).run() + + match choice.type_: + case MenuSelectionType.Skip: return preset + case MenuSelectionType.Selection: return choice.single_value + + return None diff --git a/archinstall/lib/menu/abstract_menu.py b/archinstall/lib/menu/abstract_menu.py index 2bd56374..eee99747 100644 --- a/archinstall/lib/menu/abstract_menu.py +++ b/archinstall/lib/menu/abstract_menu.py @@ -3,7 +3,6 @@ from __future__ import annotations from typing import Callable, Any, List, Iterator, Tuple, Optional, Dict, TYPE_CHECKING from .menu import Menu, MenuSelectionType -from ..locale import set_keyboard_language from ..output import error from ..translationhandler import TranslationHandler, Language @@ -130,7 +129,7 @@ class Selector: if current: padding += 5 description = str(self._description).ljust(padding, ' ') - current = str(_('set: {}').format(current)) + current = current else: description = self._description current = '' @@ -243,31 +242,6 @@ class AbstractMenu: elif selector is not None and selector.has_selection(): self._data_store[selector_name] = selector.current_selection - def _missing_configs(self) -> List[str]: - def check(s): - return self._menu_options.get(s).has_selection() - - def has_superuser() -> bool: - sel = self._menu_options['!users'] - if sel.current_selection: - return any([u.sudo for u in sel.current_selection]) - return False - - mandatory_fields = dict(filter(lambda x: x[1].is_mandatory(), self._menu_options.items())) - missing = set() - - for key, selector in mandatory_fields.items(): - if key in ['!root-password', '!users']: - if not check('!root-password') and not has_superuser(): - missing.add( - str(_('Either root-password or at least 1 user with sudo privileges must be specified')) - ) - elif key == 'disk_config': - if not check('disk_config'): - missing.add(self._menu_options['disk_config'].description) - - return list(missing) - def setup_selection_menu_options(self): """ Define the menu options. Menu options can be defined here in a subclass or done per program calling self.set_option() @@ -328,9 +302,6 @@ class AbstractMenu: cursor_pos = None while True: - # Before continuing, set the preferred keyboard layout/language in the current terminal. - # This will just help the user with the next following questions. - self._set_kb_language() enabled_menus = self._menus_to_enable() padding = self._get_menu_text_padding(list(enabled_menus.values())) @@ -425,13 +396,6 @@ class AbstractMenu: return True - def _set_kb_language(self): - """ general for ArchInstall""" - # Before continuing, set the preferred keyboard layout/language in the current terminal. - # This will just help the user with the next following questions. - if self._data_store.get('keyboard-layout', None) and len(self._data_store['keyboard-layout']): - set_keyboard_language(self._data_store['keyboard-layout']) - def _verify_selection_enabled(self, selection_name: str) -> bool: """ general """ if selection := self._menu_options.get(selection_name, None): diff --git a/archinstall/lib/utils/util.py b/archinstall/lib/utils/util.py index 34716f4a..8df75ab1 100644 --- a/archinstall/lib/utils/util.py +++ b/archinstall/lib/utils/util.py @@ -1,6 +1,7 @@ from pathlib import Path -from typing import Any, TYPE_CHECKING, Optional +from typing import Any, TYPE_CHECKING, Optional, List +from ..output import FormattedOutput from ..output import info if TYPE_CHECKING: @@ -28,3 +29,23 @@ def is_subpath(first: Path, second: Path): return True except ValueError: return False + + +def format_cols(items: List[str], header: Optional[str]) -> str: + if header: + text = f'{header}:\n' + else: + text = '' + + nr_items = len(items) + if nr_items <= 5: + col = 1 + elif nr_items <= 10: + col = 2 + elif nr_items <= 15: + col = 3 + else: + col = 4 + + text += FormattedOutput.as_columns(items, col) + return text diff --git a/archinstall/scripts/guided.py b/archinstall/scripts/guided.py index 1aecc1cd..7f9b9fd6 100644 --- a/archinstall/scripts/guided.py +++ b/archinstall/scripts/guided.py @@ -5,6 +5,7 @@ from typing import Any, TYPE_CHECKING import archinstall from archinstall import info, debug from archinstall import SysInfo +from archinstall.lib import locale from archinstall.lib import disk from archinstall.lib.global_menu import GlobalMenu from archinstall.default_profiles.applications.pipewire import PipewireProfile @@ -42,14 +43,10 @@ def ask_user_questions(): global_menu.enable('archinstall-language') - global_menu.enable('keyboard-layout') - # Set which region to download packages from during the installation global_menu.enable('mirror_config') - global_menu.enable('sys-language') - - global_menu.enable('sys-encoding') + global_menu.enable('locale_config') global_menu.enable('disk_config', mandatory=True) @@ -76,7 +73,7 @@ def ask_user_questions(): global_menu.enable('audio') # Ask for preferred kernel: - global_menu.enable('kernels') + global_menu.enable('kernels', mandatory=True) global_menu.enable('packages') @@ -114,9 +111,7 @@ def perform_installation(mountpoint: Path): # Retrieve list of additional repositories and set boolean values appropriately enable_testing = 'testing' in archinstall.arguments.get('additional-repositories', []) enable_multilib = 'multilib' in archinstall.arguments.get('additional-repositories', []) - - locale = f"{archinstall.arguments.get('sys-language', 'en_US')} {archinstall.arguments.get('sys-encoding', 'UTF-8').upper()}" - + locale_config: locale.LocaleConfiguration = archinstall.arguments['locale_config'] disk_encryption: disk.DiskEncryption = archinstall.arguments.get('disk_encryption', None) with Installer( @@ -147,7 +142,7 @@ def perform_installation(mountpoint: Path): testing=enable_testing, multilib=enable_multilib, hostname=archinstall.arguments.get('hostname', 'archlinux'), - locales=[locale] + locale_config=locale_config ) if mirror_config := archinstall.arguments.get('mirror_config', None): @@ -210,7 +205,7 @@ def perform_installation(mountpoint: Path): # This step must be after profile installs to allow profiles_bck to install language pre-requisits. # After which, this step will set the language both for console and x11 if x11 was installed for instance. - installation.set_keyboard_language(archinstall.arguments['keyboard-layout']) + installation.set_keyboard_language(locale_config.kb_layout) if profile_config := archinstall.arguments.get('profile_config', None): profile_config.profile.post_install(installation) diff --git a/archinstall/scripts/swiss.py b/archinstall/scripts/swiss.py index 1998f073..375458a1 100644 --- a/archinstall/scripts/swiss.py +++ b/archinstall/scripts/swiss.py @@ -8,6 +8,7 @@ from archinstall import SysInfo, info, debug from archinstall.lib import mirrors from archinstall.lib import models from archinstall.lib import disk +from archinstall.lib import locale from archinstall.lib.networking import check_mirror_reachable from archinstall.lib.profile.profiles_handler import profile_handler from archinstall.lib import menu @@ -92,14 +93,14 @@ class SwissMainMenu(GlobalMenu): match self._execution_mode: case ExecutionMode.Full | ExecutionMode.Lineal: options_list = [ - 'keyboard-layout', 'mirror_config', 'disk_config', + 'mirror_config', 'disk_config', 'disk_encryption', 'swap', 'bootloader', 'hostname', '!root-password', '!users', 'profile_config', 'audio', 'kernels', 'packages', 'additional-repositories', 'nic', 'timezone', 'ntp' ] if archinstall.arguments.get('advanced', False): - options_list.extend(['sys-language', 'sys-encoding']) + options_list.extend(['locale_config']) mandatory_list = ['disk_config', 'bootloader', 'hostname'] case ExecutionMode.Only_HD: @@ -107,7 +108,7 @@ class SwissMainMenu(GlobalMenu): mandatory_list = ['disk_config'] case ExecutionMode.Only_OS: options_list = [ - 'keyboard-layout', 'mirror_config','bootloader', 'hostname', + 'mirror_config','bootloader', 'hostname', '!root-password', '!users', 'profile_config', 'audio', 'kernels', 'packages', 'additional-repositories', 'nic', 'timezone', 'ntp' ] @@ -115,7 +116,7 @@ class SwissMainMenu(GlobalMenu): mandatory_list = ['hostname'] if archinstall.arguments.get('advanced', False): - options_list += ['sys-language','sys-encoding'] + options_list += ['locale_config'] case ExecutionMode.Minimal: pass case _: @@ -176,8 +177,7 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode): enable_testing = 'testing' in archinstall.arguments.get('additional-repositories', []) enable_multilib = 'multilib' in archinstall.arguments.get('additional-repositories', []) - - locale = f"{archinstall.arguments.get('sys-language', 'en_US')} {archinstall.arguments.get('sys-encoding', 'UTF-8').upper()}" + locale_config: locale.LocaleConfiguration = archinstall.arguments['locale_config'] with Installer( mountpoint, @@ -206,7 +206,7 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode): testing=enable_testing, multilib=enable_multilib, hostname=archinstall.arguments.get('hostname', 'archlinux'), - locales=[locale] + locale_config=locale_config ) if mirror_config := archinstall.arguments.get('mirror_config', None): @@ -263,7 +263,7 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode): # This step must be after profile installs to allow profiles_bck to install language pre-requisits. # After which, this step will set the language both for console and x11 if x11 was installed for instance. - installation.set_keyboard_language(archinstall.arguments['keyboard-layout']) + installation.set_keyboard_language(locale_config.kb_layout) if profile_config := archinstall.arguments.get('profile_config', None): profile_config.profile.post_install(installation) diff --git a/examples/interactive_installation.py b/examples/interactive_installation.py index 7c4ffed7..ce1a80ec 100644 --- a/examples/interactive_installation.py +++ b/examples/interactive_installation.py @@ -10,6 +10,7 @@ from archinstall.default_profiles.applications.pipewire import PipewireProfile from archinstall import disk from archinstall import menu from archinstall import models +from archinstall import locale from archinstall import info, debug if TYPE_CHECKING: @@ -21,14 +22,10 @@ def ask_user_questions(): global_menu.enable('archinstall-language') - global_menu.enable('keyboard-layout') - # Set which region to download packages from during the installation global_menu.enable('mirror_config') - global_menu.enable('sys-language') - - global_menu.enable('sys-encoding') + global_menu.enable('locale_config') global_menu.enable('disk_config', mandatory=True) @@ -55,7 +52,7 @@ def ask_user_questions(): global_menu.enable('audio') # Ask for preferred kernel: - global_menu.enable('kernels') + global_menu.enable('kernels', mandatory=True) global_menu.enable('packages') @@ -93,9 +90,7 @@ def perform_installation(mountpoint: Path): # Retrieve list of additional repositories and set boolean values appropriately enable_testing = 'testing' in archinstall.arguments.get('additional-repositories', []) enable_multilib = 'multilib' in archinstall.arguments.get('additional-repositories', []) - - locale = f"{archinstall.arguments.get('sys-language', 'en_US')} {archinstall.arguments.get('sys-encoding', 'UTF-8').upper()}" - + locale_config: locale.LocaleConfiguration = archinstall.arguments['locale_config'] disk_encryption: disk.DiskEncryption = archinstall.arguments.get('disk_encryption', None) with Installer( @@ -126,7 +121,7 @@ def perform_installation(mountpoint: Path): testing=enable_testing, multilib=enable_multilib, hostname=archinstall.arguments.get('hostname', 'archlinux'), - locales=[locale] + locale_config=locale_config ) if mirror_config := archinstall.arguments.get('mirror_config', None): @@ -189,7 +184,7 @@ def perform_installation(mountpoint: Path): # This step must be after profile installs to allow profiles_bck to install language pre-requisits. # After which, this step will set the language both for console and x11 if x11 was installed for instance. - installation.set_keyboard_language(archinstall.arguments['keyboard-layout']) + installation.set_keyboard_language(locale_config.kb_layout) if profile_config := archinstall.arguments.get('profile_config', None): profile_config.profile.post_install(installation) -- cgit v1.2.3-54-g00ecf From 91ee3575d369becdf1f0b93a259929b6662170c7 Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Mon, 5 Jun 2023 18:47:14 +1000 Subject: Fix 1749 (#1840) Co-authored-by: Daniel Girtler Co-authored-by: Anton Hvornum --- archinstall/lib/interactions/general_conf.py | 10 ++-- archinstall/locales/ar/LC_MESSAGES/base.po | 23 ++++---- archinstall/locales/base.pot | 15 ++++-- archinstall/locales/cs/LC_MESSAGES/base.mo | Bin 26115 -> 25981 bytes archinstall/locales/cs/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/de/LC_MESSAGES/base.po | 73 ++++++++++++++++++++++++-- archinstall/locales/el/LC_MESSAGES/base.mo | Bin 35562 -> 35428 bytes archinstall/locales/el/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/en/LC_MESSAGES/base.po | 11 ++-- archinstall/locales/es/LC_MESSAGES/base.po | 11 ++-- archinstall/locales/fr/LC_MESSAGES/base.mo | Bin 27562 -> 27428 bytes archinstall/locales/fr/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/id/LC_MESSAGES/base.mo | Bin 26392 -> 26258 bytes archinstall/locales/id/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/it/LC_MESSAGES/base.mo | Bin 26675 -> 26541 bytes archinstall/locales/it/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/ka/LC_MESSAGES/base.mo | Bin 44957 -> 44823 bytes archinstall/locales/ka/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/ko/LC_MESSAGES/base.mo | Bin 27355 -> 27221 bytes archinstall/locales/ko/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/nl/LC_MESSAGES/base.po | 11 ++-- archinstall/locales/pl/LC_MESSAGES/base.mo | Bin 25444 -> 25126 bytes archinstall/locales/pl/LC_MESSAGES/base.po | 21 +++++--- archinstall/locales/pt/LC_MESSAGES/base.po | 11 ++-- archinstall/locales/pt_BR/LC_MESSAGES/base.mo | Bin 27157 -> 27023 bytes archinstall/locales/pt_BR/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/ru/LC_MESSAGES/base.mo | Bin 36023 -> 35889 bytes archinstall/locales/ru/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/sv/LC_MESSAGES/base.po | 11 ++-- archinstall/locales/ta/LC_MESSAGES/base.mo | Bin 47610 -> 47476 bytes archinstall/locales/ta/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/tr/LC_MESSAGES/base.po | 11 ++-- archinstall/locales/uk/LC_MESSAGES/base.mo | Bin 36158 -> 36024 bytes archinstall/locales/uk/LC_MESSAGES/base.po | 20 ++++--- archinstall/locales/ur/LC_MESSAGES/base.po | 11 ++-- archinstall/locales/zh-CN/LC_MESSAGES/base.mo | Bin 24126 -> 23992 bytes archinstall/locales/zh-CN/LC_MESSAGES/base.po | 20 ++++--- 37 files changed, 326 insertions(+), 133 deletions(-) (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index 3b78847b..ad9ee386 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -151,10 +151,10 @@ def ask_additional_packages_to_install(preset: List[str] = []) -> List[str]: def add_number_of_parrallel_downloads(input_number :Optional[int] = None) -> Optional[int]: max_downloads = 5 print(_(f"This option enables the number of parallel downloads that can occur during installation")) - print(_(f"Enter the number of parallel downloads to be enabled.\n (Enter a value between 1 to {max_downloads})\nNote:")) - print(_(f" - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )")) - print(_(f" - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )")) - print(_(f" - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )")) + print(str(_("Enter the number of parallel downloads to be enabled.\n (Enter a value between 1 to {})\nNote:")).format(max_downloads)) + print(str(_(" - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )")).format(max_downloads, max_downloads, max_downloads + 1)) + print(_(" - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )")) + print(_(" - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )")) while True: try: @@ -165,7 +165,7 @@ def add_number_of_parrallel_downloads(input_number :Optional[int] = None) -> Opt input_number = max_downloads break except: - print(_(f"Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]")) + print(str(_("Invalid input! Try again with a valid input [1 to {}, or 0 to disable]")).format(max_downloads)) pacman_conf_path = pathlib.Path("/etc/pacman.conf") with pacman_conf_path.open() as f: diff --git a/archinstall/locales/ar/LC_MESSAGES/base.po b/archinstall/locales/ar/LC_MESSAGES/base.po index 6c37bdff..0944913a 100644 --- a/archinstall/locales/ar/LC_MESSAGES/base.po +++ b/archinstall/locales/ar/LC_MESSAGES/base.po @@ -751,14 +751,13 @@ msgstr "" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" msgstr "" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" @@ -1056,12 +1055,6 @@ msgstr "" msgid "Defined" msgstr "" -msgid "Mirrors" -msgstr "" - -msgid "Mirror regions" -msgstr "" - msgid "Save user configuration (including disk layout)" msgstr "" @@ -1078,3 +1071,15 @@ msgstr "" msgid "Saving {} configuration files to {}" msgstr "" + +msgid "Mirrors" +msgstr "" + +msgid "Mirror regions" +msgstr "" + +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr "" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "" diff --git a/archinstall/locales/base.pot b/archinstall/locales/base.pot index 2ca84604..cc01f5fc 100644 --- a/archinstall/locales/base.pot +++ b/archinstall/locales/base.pot @@ -793,16 +793,15 @@ msgid "" "installation" msgstr "" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" msgid "" -" - Maximum value : {max_downloads} ( Allows {max_downloads} parallel " -"downloads, allows {max_downloads+1} downloads at a time )" +" - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads " +"at a time )" msgstr "" msgid "" @@ -1146,3 +1145,11 @@ msgstr "" msgid "Mirror regions" msgstr "" + +msgid "" +" - Maximum value : {} ( Allows {} parallel downloads, allows " +"{max_downloads+1} downloads at a time )" +msgstr "" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "" diff --git a/archinstall/locales/cs/LC_MESSAGES/base.mo b/archinstall/locales/cs/LC_MESSAGES/base.mo index a256081c..b8808152 100644 Binary files a/archinstall/locales/cs/LC_MESSAGES/base.mo and b/archinstall/locales/cs/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/cs/LC_MESSAGES/base.po b/archinstall/locales/cs/LC_MESSAGES/base.po index cf6bd3a1..20f3c257 100644 --- a/archinstall/locales/cs/LC_MESSAGES/base.po +++ b/archinstall/locales/cs/LC_MESSAGES/base.po @@ -786,18 +786,17 @@ msgstr "Nakonfigurováno {} rozhraní" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "Tato možnost povolí specifikovaný počet paralelních stahování, která mohou nastat při instalaci" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "Zadejte povolený počet paralelních stahování.\n" -" (Zadejte hodnotu mezi 1 a {max_downloads})\n" +" (Zadejte hodnotu mezi 1 a {})\n" "Poznámka:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Maximální hodnota : {max_downloads} (Povolí {max_downloads} paralelních stahování, povolí {max_downloads+1} stahování naráz )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - Maximální hodnota : {} (Povolí {} paralelních stahování, povolí {} stahování naráz )" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - Minimální hodnota : 1 (Povolí 1 paralelní stahování, povolí 2 stahování naráz)" @@ -805,9 +804,9 @@ msgstr " - Minimální hodnota : 1 (Povolí 1 paralelní stahování, povolí msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - Zakázáno/Výchozí : 0 (Zakáže paralelní stahování, povolí pouze 1 stahování naráz)" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "Neplatný vstup! Zkuste to, prosím, znovu s platným vstupem [1 až {max_downloads}, nebo 0 pro vypnutí]" +msgstr "Neplatný vstup! Zkuste to, prosím, znovu s platným vstupem [1 až {}, nebo 0 pro vypnutí]" msgid "Parallel Downloads" msgstr "Paralelní stahování" @@ -1163,3 +1162,10 @@ msgstr "Oblast zrcadla" #, fuzzy msgid "Mirror regions" msgstr "Oblast zrcadla" + +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - Maximální hodnota : {} (Povolí {} paralelních stahování, povolí {} stahování naráz )" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "Neplatný vstup! Zkuste to, prosím, znovu s platným vstupem [1 až {}, nebo 0 pro vypnutí]" diff --git a/archinstall/locales/de/LC_MESSAGES/base.po b/archinstall/locales/de/LC_MESSAGES/base.po index b20d6e90..6dfb0801 100644 --- a/archinstall/locales/de/LC_MESSAGES/base.po +++ b/archinstall/locales/de/LC_MESSAGES/base.po @@ -793,18 +793,17 @@ msgstr "{} Schnittstellen konfiguriert" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "Diese Option setzt die Nummer an parallelen Downloads, die während der Installtion durchgeführt werden" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "Geben Sie die Nummer an parallelen Downloads an.\n" " (Wert zwischen 1 und {max_downloads})\n" "Achtung:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Maximalwert :{max_downloads} (Erlaubt {max_downloads} parallele Downloads, erlaubt {max_downloads+1} Downloads gleichzeitig)" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - Maximalwert :{} (Erlaubt {} parallele Downloads, erlaubt {} Downloads gleichzeitig)" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr "- Minimalwert : 1 (Erlaubt einen parallelen Download, erlaubt zwei Downloads gleichzeitig)" @@ -1188,6 +1187,72 @@ msgstr "" msgid "Saving {} configuration files to {}" msgstr "Konfiguration speichern" +#, fuzzy +msgid "Add a custom mirror" +msgstr "Benutzerkonto hinzufügen" + +msgid "Change custom mirror" +msgstr "" + +msgid "Delete custom mirror" +msgstr "" + +#, fuzzy +msgid "Enter name (leave blank to skip): " +msgstr "Geben sie einen weiteren Benutzernamen an der angelegt werden soll (leer lassen um zu Überspringen): " + +#, fuzzy +msgid "Enter url (leave blank to skip): " +msgstr "Geben sie einen weiteren Benutzernamen an der angelegt werden soll (leer lassen um zu Überspringen): " + +#, fuzzy +msgid "Select signature check option" +msgstr "Laufwerke-layout auswählen" + +#, fuzzy +msgid "Select signature option" +msgstr "Laufwerke-layout auswählen" + +msgid "Custom mirrors" +msgstr "" + +msgid "Defined" +msgstr "" + +#, fuzzy +msgid "Save user configuration (including disk layout)" +msgstr "Benutzerkonfiguration speichern" + +#, fuzzy +msgid "" +"Enter a directory for the configuration(s) to be saved (tab completion enabled)\n" +"Save directory: " +msgstr "Geben sie eine Ordner an wo die Konfigurationen gespeichert werden sollen: " + +msgid "" +"Do you want to save {} configuration file(s) in the following location?\n" +"\n" +"{}" +msgstr "" + +#, fuzzy +msgid "Saving {} configuration files to {}" +msgstr "Konfiguration speichern" + +#, fuzzy +msgid "Mirrors" +msgstr "Mirror-region" + +#, fuzzy +msgid "Mirror regions" +msgstr "Mirror-region" + +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr "" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "" + #~ msgid "Add :" #~ msgstr "Hinzufügen :" diff --git a/archinstall/locales/el/LC_MESSAGES/base.mo b/archinstall/locales/el/LC_MESSAGES/base.mo index 103eaf0c..9a8c99af 100644 Binary files a/archinstall/locales/el/LC_MESSAGES/base.mo and b/archinstall/locales/el/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/el/LC_MESSAGES/base.po b/archinstall/locales/el/LC_MESSAGES/base.po index 4a33dd5e..4b4db260 100644 --- a/archinstall/locales/el/LC_MESSAGES/base.po +++ b/archinstall/locales/el/LC_MESSAGES/base.po @@ -793,18 +793,17 @@ msgstr "Διαμορφωμένες {} διεπαφές" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "Αυτή η επιλογή θέτει τον αριθμό των παράλληλων λήψεων που μπορούν να συμβούν κατά την εγκατάσταση" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "Εισάγετε τον αριθμό των παράλληλων λήψεων προς ενεργοποίηση.\n" -" (Εισάγετε μία τιμή από 1 μέχρι {max_downloads})\n" +" (Εισάγετε μία τιμή από 1 μέχρι {})\n" "Σημείωση:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Μέγιστη τιμή : {max_downloads} ( Επιτρέπει {max_downloads} παράλληλες λήψεις, επιτρέπει {max_downloads+1} λήψεις σε μία στιγμή )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - Μέγιστη τιμή : {} ( Επιτρέπει {} παράλληλες λήψεις, επιτρέπει {} λήψεις σε μία στιγμή )" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - Ελάχιστη τιμή : 1 ( Επιτρέπει 1 παράλληλη λήψη, επιτρέπει 2 λήψεις σε μία στιγμή )" @@ -812,9 +811,9 @@ msgstr " - Ελάχιστη τιμή : 1 ( Επιτρέπει 1 παράλλη msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - Απενεργοποίηση/Προκαθορισμένο : 0 ( Απενεργοποιεί τις παράλληλες λήψεις, επιτρέπει μόνο 1 λήψη σε μία στιγμή )" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "Μη έγκυρη είσοδος! Προσπαθήστε ξανά με μία έγκυρη είσοδο [1 μέχρι {max_downloads}, ή 0 για απενεργοποίηση]" +msgstr "Μη έγκυρη είσοδος! Προσπαθήστε ξανά με μία έγκυρη είσοδο [1 μέχρι {}, ή 0 για απενεργοποίηση]" msgid "Parallel Downloads" msgstr "Παράλληλες Λήψεις" @@ -1170,3 +1169,10 @@ msgstr "Περιοχή mirror" #, fuzzy msgid "Mirror regions" msgstr "Περιοχή mirror" + +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - Μέγιστη τιμή : {} ( Επιτρέπει {} παράλληλες λήψεις, επιτρέπει {} λήψεις σε μία στιγμή )" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "Μη έγκυρη είσοδος! Προσπαθήστε ξανά με μία έγκυρη είσοδο [1 μέχρι {}, ή 0 για απενεργοποίηση]" diff --git a/archinstall/locales/en/LC_MESSAGES/base.po b/archinstall/locales/en/LC_MESSAGES/base.po index f08c5ffc..5a38a4db 100644 --- a/archinstall/locales/en/LC_MESSAGES/base.po +++ b/archinstall/locales/en/LC_MESSAGES/base.po @@ -747,14 +747,13 @@ msgstr "" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" msgstr "" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" @@ -1067,3 +1066,9 @@ msgstr "" msgid "Mirror regions" msgstr "" + +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr "" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "" diff --git a/archinstall/locales/es/LC_MESSAGES/base.po b/archinstall/locales/es/LC_MESSAGES/base.po index 6ba5f7b6..22ab693c 100644 --- a/archinstall/locales/es/LC_MESSAGES/base.po +++ b/archinstall/locales/es/LC_MESSAGES/base.po @@ -794,14 +794,13 @@ msgstr "" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" msgstr "" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" @@ -1170,6 +1169,12 @@ msgstr "Región del servidor" msgid "Mirror regions" msgstr "Región del servidor" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr "" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "" + #~ msgid "Add :" #~ msgstr "Añadir :" diff --git a/archinstall/locales/fr/LC_MESSAGES/base.mo b/archinstall/locales/fr/LC_MESSAGES/base.mo index 22e004e0..81e6ce00 100644 Binary files a/archinstall/locales/fr/LC_MESSAGES/base.mo and b/archinstall/locales/fr/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/fr/LC_MESSAGES/base.po b/archinstall/locales/fr/LC_MESSAGES/base.po index 15aea6ac..ec5fc68e 100644 --- a/archinstall/locales/fr/LC_MESSAGES/base.po +++ b/archinstall/locales/fr/LC_MESSAGES/base.po @@ -793,18 +793,17 @@ msgstr "Interfaces {} configurées" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "Cette option active le nombre de téléchargements parallèles qui peuvent se produire pendant l'installation" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "Saisir le nombre de téléchargements parallèles à activer.\n" -" (Entrer une valeur comprise entre 1 et {max_downloads})\n" +" (Entrer une valeur comprise entre 1 et {})\n" "Note :" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Valeur maximale : {max_downloads} (Autorise {max_downloads} téléchargements parallèles, autorise {max_downloads+1} téléchargements à la fois)" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - Valeur maximale : {} (Autorise {} téléchargements parallèles, autorise {} téléchargements à la fois)" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - Valeur minimale : 1 (Autorise 1 téléchargement parallèle, autorise 2 téléchargements à la fois)" @@ -812,9 +811,9 @@ msgstr " - Valeur minimale : 1 (Autorise 1 téléchargement parallèle, autorise msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - Désactiver/Défaut : 0 (Désactive le téléchargement parallèle, n'autorise qu'un seul téléchargement à la fois)" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "Entrée invalide ! Réessayer avec une entrée valide [1 pour {max_downloads}, ou 0 pour désactiver]" +msgstr "Entrée invalide ! Réessayer avec une entrée valide [1 pour {}, ou 0 pour désactiver]" msgid "Parallel Downloads" msgstr "Téléchargements parallèles" @@ -1171,6 +1170,13 @@ msgstr "Région miroir" msgid "Mirror regions" msgstr "Région miroir" +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - Valeur maximale : {} (Autorise {} téléchargements parallèles, autorise {} téléchargements à la fois)" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "Entrée invalide ! Réessayer avec une entrée valide [1 pour {}, ou 0 pour désactiver]" + #, python-brace-format #~ msgid "Edit {origkey} :" #~ msgstr "Modifier {origkey} :" diff --git a/archinstall/locales/id/LC_MESSAGES/base.mo b/archinstall/locales/id/LC_MESSAGES/base.mo index b81fe108..db3649bd 100644 Binary files a/archinstall/locales/id/LC_MESSAGES/base.mo and b/archinstall/locales/id/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/id/LC_MESSAGES/base.po b/archinstall/locales/id/LC_MESSAGES/base.po index 01986796..f2ede55f 100644 --- a/archinstall/locales/id/LC_MESSAGES/base.po +++ b/archinstall/locales/id/LC_MESSAGES/base.po @@ -793,18 +793,17 @@ msgstr "Interface {} dikonfigurasi" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "Opsi ini memungkinkan jumlah unduhan paralel yang dapat terjadi selama instalasi" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "Masukkan jumlah unduhan paralel yang akan diaktifkan.\n" -" (Masukkan nilai antara 1 hingga {max_downloads})\n" +" (Masukkan nilai antara 1 hingga {})\n" "Catatan:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Nilai maksimum : {max_downloads} ( Memungkinkan {max_downloads} unduhan paralel, memungkinkan {max_downloads+1} unduhan sekaligus)" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - Nilai maksimum : {} ( Memungkinkan {} unduhan paralel, memungkinkan {} unduhan sekaligus)" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - Nilai minimum : 1 (Mengizinkan 1 unduhan paralel, memungkinkan 2 unduhan sekaligus)" @@ -812,9 +811,9 @@ msgstr " - Nilai minimum : 1 (Mengizinkan 1 unduhan paralel, memungkinkan 2 un msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - Nonaktifkan/Default: 0 (Menonaktifkan pengunduhan paralel, hanya mengizinkan 1 unduhan pada satu waktu)" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "Input tidak valid! Coba lagi dengan input yang valid [1 untuk {max_downloads}, atau 0 untuk menonaktifkan]" +msgstr "Input tidak valid! Coba lagi dengan input yang valid [1 untuk {}, atau 0 untuk menonaktifkan]" msgid "Parallel Downloads" msgstr "Unduhan Paralel" @@ -1169,3 +1168,10 @@ msgstr "Wilayah mirror" #, fuzzy msgid "Mirror regions" msgstr "Wilayah mirror" + +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - Nilai maksimum : {} ( Memungkinkan {} unduhan paralel, memungkinkan {} unduhan sekaligus)" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "Input tidak valid! Coba lagi dengan input yang valid [1 untuk {}, atau 0 untuk menonaktifkan]" diff --git a/archinstall/locales/it/LC_MESSAGES/base.mo b/archinstall/locales/it/LC_MESSAGES/base.mo index f199746c..e63c377e 100644 Binary files a/archinstall/locales/it/LC_MESSAGES/base.mo and b/archinstall/locales/it/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/it/LC_MESSAGES/base.po b/archinstall/locales/it/LC_MESSAGES/base.po index c856a286..703f0000 100644 --- a/archinstall/locales/it/LC_MESSAGES/base.po +++ b/archinstall/locales/it/LC_MESSAGES/base.po @@ -793,18 +793,17 @@ msgstr "Configurate {} interfacce" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "Questa opzione consente di impostare il numero di download paralleli che possono avvenire durante l'installazione" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "Inserisci il numero di download paralleli da abilitare.\n" -" (Inserisci un valore compreso tra 1 e {max_downloads})\n" +" (Inserisci un valore compreso tra 1 e {})\n" "Nota:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Valore massimo : {max_downloads} ( Consente {max_downloads} download parallelo, consente {max_downloads+1} download alla volta )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - Valore massimo : {} ( Consente {} download parallelo, consente {} download alla volta )" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - Valore minimo : 1 ( Consente 1 download parallelo, consente 2 download alla volta )" @@ -812,9 +811,9 @@ msgstr " - Valore minimo : 1 ( Consente 1 download parallelo, consente 2 downl msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - Disabilita/Predefinito : 0 ( Disabilita il download parallelo, consente solo 1 download alla volta )" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "Input non valido! Riprova con un input valido [da 1 a {max_downloads}, o 0 per disabilitare]." +msgstr "Input non valido! Riprova con un input valido [da 1 a {}, o 0 per disabilitare]." msgid "Parallel Downloads" msgstr "Download paralleli" @@ -1169,3 +1168,10 @@ msgstr "Regione dei mirror" #, fuzzy msgid "Mirror regions" msgstr "Regione dei mirror" + +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - Valore massimo : {} ( Consente {} download parallelo, consente {} download alla volta )" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "Input non valido! Riprova con un input valido [da 1 a {}, o 0 per disabilitare]." diff --git a/archinstall/locales/ka/LC_MESSAGES/base.mo b/archinstall/locales/ka/LC_MESSAGES/base.mo index b95a6e0e..31e14aa2 100644 Binary files a/archinstall/locales/ka/LC_MESSAGES/base.mo and b/archinstall/locales/ka/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/ka/LC_MESSAGES/base.po b/archinstall/locales/ka/LC_MESSAGES/base.po index 029e4256..6e4823eb 100644 --- a/archinstall/locales/ka/LC_MESSAGES/base.po +++ b/archinstall/locales/ka/LC_MESSAGES/base.po @@ -794,18 +794,17 @@ msgstr "მორგებულია {} ინტერფეისი" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "ეს პარამეტრი დაყენებისას მითითებული რაოდენობის პარალელურ გადმოწერას დაუშვებს" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "შეიყვანეთ დასაშვები პარალელური გადმოწერების რაოდენობა.\n" -" (შეიყვანეთ მნიშვნელობა 1-დან {max_downloads}-მდე)\n" +" (შეიყვანეთ მნიშვნელობა 1-დან {}-მდე)\n" "დაიმახსოვრეთ:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - მინიმალური მნიშვნელობა : {max_downloads} ( დაუშვებს {max_downloads} პარალელურ გადმოწერას, დაუშვებს {max_downloads+1} ერთდროულ გადმოწერას )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - მინიმალური მნიშვნელობა : {} ( დაუშვებს {} პარალელურ გადმოწერას, დაუშვებს {} ერთდროულ გადმოწერას )" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - მინიმალური მნიშვნელობა : 1 ( დაუშვებს 1 პარალელურ გადმოწერას, დაუშვებს 2 ერთდროულ გადმოწერას )" @@ -813,9 +812,9 @@ msgstr " - მინიმალური მნიშვნელობა : msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - გამორთვა/ნაგულისხმები : 0 ( პარალელური გადმოწერების გათიშვა. დროის ერთ მომენტში მხოლოდ ერთი გადმოწერა მოხდება )" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "შეყვანილი რიცხვი არასწორია! თავიდან სცადეთ [1-დან {max_downloads}-მდე, ან 0, გასათიშად]" +msgstr "შეყვანილი რიცხვი არასწორია! თავიდან სცადეთ [1-დან {}-მდე, ან 0, გასათიშად]" msgid "Parallel Downloads" msgstr "პარალელური გადმოწერები" @@ -1168,3 +1167,10 @@ msgstr "სარკის რეგიონი" #, fuzzy msgid "Mirror regions" msgstr "სარკის რეგიონი" + +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - მინიმალური მნიშვნელობა : {} ( დაუშვებს {} პარალელურ გადმოწერას, დაუშვებს {} ერთდროულ გადმოწერას )" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "შეყვანილი რიცხვი არასწორია! თავიდან სცადეთ [1-დან {}-მდე, ან 0, გასათიშად]" diff --git a/archinstall/locales/ko/LC_MESSAGES/base.mo b/archinstall/locales/ko/LC_MESSAGES/base.mo index 4c89f1f8..ddec6151 100644 Binary files a/archinstall/locales/ko/LC_MESSAGES/base.mo and b/archinstall/locales/ko/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/ko/LC_MESSAGES/base.po b/archinstall/locales/ko/LC_MESSAGES/base.po index 7d30a785..de46b698 100644 --- a/archinstall/locales/ko/LC_MESSAGES/base.po +++ b/archinstall/locales/ko/LC_MESSAGES/base.po @@ -794,18 +794,17 @@ msgstr "구성된 {} 인터페이스" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "이 옵션은 설치 중에 발생할 수 있는 병렬 다운로드 수를 활성화합니다" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "활성화할 병렬 다운로드 수를 입력하세요.\n" -" (1 부터 {max_downloads} 까지의 숫자중 하나를 입력하세요)\n" +" (1 부터 {} 까지의 숫자중 하나를 입력하세요)\n" "메모:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - 최댓값 : {max_downloads} ( {max_downloads} 개의 병렬 다운로드 허용, 한 번에 {max_downloads+1} 개의 다운로드 허용 )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - 최댓값 : {} ( {} 개의 병렬 다운로드 허용, 한 번에 {} 개의 다운로드 허용 )" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - 최솟값 : 1 ( 1 개의 병렬 다운로드 허용, 한 번에 2 개의 다운로드 허용 )" @@ -813,9 +812,9 @@ msgstr " - 최솟값 : 1 ( 1 개의 병렬 다운로드 허용, 한 번에 2 msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - 비활성화/기본 : - ( 병렬 다운로드 비활성화, 한 번에 1 개의 다운로드만 허용 )" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "잘못된 값입니다! 유효한 값으로 다시 시도해주세요 [1 부터 {max_downloads} 까지, 비활성화 하려면 0]" +msgstr "잘못된 값입니다! 유효한 값으로 다시 시도해주세요 [1 부터 {} 까지, 비활성화 하려면 0]" msgid "Parallel Downloads" msgstr "병렬 다운로드" @@ -1170,3 +1169,10 @@ msgstr "미러 위치" #, fuzzy msgid "Mirror regions" msgstr "미러 위치" + +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - 최댓값 : {} ( {} 개의 병렬 다운로드 허용, 한 번에 {} 개의 다운로드 허용 )" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "잘못된 값입니다! 유효한 값으로 다시 시도해주세요 [1 부터 {} 까지, 비활성화 하려면 0]" diff --git a/archinstall/locales/nl/LC_MESSAGES/base.po b/archinstall/locales/nl/LC_MESSAGES/base.po index e22a6d0f..6dfeed53 100644 --- a/archinstall/locales/nl/LC_MESSAGES/base.po +++ b/archinstall/locales/nl/LC_MESSAGES/base.po @@ -823,14 +823,13 @@ msgstr "" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" msgstr "" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" @@ -1195,6 +1194,12 @@ msgstr "Spiegelserverregio" msgid "Mirror regions" msgstr "Spiegelserverregio" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr "" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "" + #~ msgid "Add :" #~ msgstr "Toevoegen:" diff --git a/archinstall/locales/pl/LC_MESSAGES/base.mo b/archinstall/locales/pl/LC_MESSAGES/base.mo index 7ca4f9b0..0904a1a1 100644 Binary files a/archinstall/locales/pl/LC_MESSAGES/base.mo and b/archinstall/locales/pl/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/pl/LC_MESSAGES/base.po b/archinstall/locales/pl/LC_MESSAGES/base.po index 8c3ce4f5..fa53c7f0 100644 --- a/archinstall/locales/pl/LC_MESSAGES/base.po +++ b/archinstall/locales/pl/LC_MESSAGES/base.po @@ -794,18 +794,19 @@ msgstr "Skonfigurowano {} interfejsów" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "Ta opcja pozwala określić maksymalną liczbę pobieranych plików podczas instalacji" -#, fuzzy, python-brace-format +#, fuzzy msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "Wprowadź maksymalną liczbę plików pobieranych jednocześnie.\n" -" (Liczba z zakresu od 1 do {max_downloads})\n" +" (Liczba z zakresu od 1 do {})\n" "Zauważ:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Maksymalna wartość : {max_downloads} ( Zwiększa liczbę zadań o {max_downloads}, co pozwala na pobieranie {max_downloads+1} plików jednocześnie )" +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - Maksymalna wartość : {} ( Zwiększa liczbę zadań o {}, co pozwala na pobieranie {} plików jednocześnie )" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - Minimalna wartość : 1 ( Zwiększa liczbę zadań o 1, co pozwala na pobieranie 2 plików jednocześnie )" @@ -815,7 +816,7 @@ msgstr " - Wyłącz/domyślnie : 0 ( Wyłącza pobieranie równoległe, więc ty #, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "Nieprawidłowa wartość! Spróbuj wprowadzić wartość od 1 do {max_downloads}, lub 0 aby wyłączyć." +msgstr "Nieprawidłowa wartość! Spróbuj wprowadzić wartość od 1 do {}, lub 0 aby wyłączyć." msgid "Parallel Downloads" msgstr "Pobieranie równoległe" @@ -1181,6 +1182,14 @@ msgstr "Region lustra" msgid "Mirror regions" msgstr "Region lustra" +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - Maksymalna wartość : {} ( Zwiększa liczbę zadań o {}, co pozwala na pobieranie {} plików jednocześnie )" + +#, fuzzy +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "Nieprawidłowa wartość! Spróbuj wprowadzić wartość od 1 do {}, lub 0 aby wyłączyć." + #~ msgid "Add :" #~ msgstr "Dodaj :" diff --git a/archinstall/locales/pt/LC_MESSAGES/base.po b/archinstall/locales/pt/LC_MESSAGES/base.po index 35c3ca73..7f0d5eba 100644 --- a/archinstall/locales/pt/LC_MESSAGES/base.po +++ b/archinstall/locales/pt/LC_MESSAGES/base.po @@ -843,14 +843,13 @@ msgstr "" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" msgstr "" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" @@ -1217,6 +1216,12 @@ msgstr "Região do mirror" msgid "Mirror regions" msgstr "Região do mirror" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr "" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "" + #~ msgid "Add :" #~ msgstr "Adicionar :" diff --git a/archinstall/locales/pt_BR/LC_MESSAGES/base.mo b/archinstall/locales/pt_BR/LC_MESSAGES/base.mo index 4dd57dba..51580dbb 100644 Binary files a/archinstall/locales/pt_BR/LC_MESSAGES/base.mo and b/archinstall/locales/pt_BR/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/pt_BR/LC_MESSAGES/base.po b/archinstall/locales/pt_BR/LC_MESSAGES/base.po index 93b33002..c36250f5 100644 --- a/archinstall/locales/pt_BR/LC_MESSAGES/base.po +++ b/archinstall/locales/pt_BR/LC_MESSAGES/base.po @@ -797,18 +797,17 @@ msgstr "{} interfaces configuradas" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "Esta opção habilita o número de downloads paralelos que podem ocorrer durante a instalação" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "Insira o número de downloads paralelos para serem habilitados.\n" -" (Insira um valor entre 1 e {max_downloads})\n" +" (Insira um valor entre 1 e {})\n" "Observação:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Valor máximo : {max_downloads} ( Permite {max_donwloads} downloads paralelos, permite {max_donwloads+1} downloads por vez )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - Valor máximo : {} ( Permite {} downloads paralelos, permite {} downloads por vez )" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - Valor minimo : 1 ( Permite 1 download paralelo, permite 2 downloads por vez )" @@ -816,9 +815,9 @@ msgstr " - Valor minimo : 1 ( Permite 1 download paralelo, permite 2 downloads msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - Desativar/Padrão : 0 ( Desativa os downloads paralelos, permite apenas 1 download por vez )" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "Entrada inválida! Tente novamente com uma entrada válida [1 para {max_downloads}, ou 0 para desativar]" +msgstr "Entrada inválida! Tente novamente com uma entrada válida [1 para {}, ou 0 para desativar]" msgid "Parallel Downloads" msgstr "Downloads Paralelos" @@ -1171,3 +1170,10 @@ msgstr "Região do mirror" #, fuzzy msgid "Mirror regions" msgstr "Região do mirror" + +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - Valor máximo : {} ( Permite {} downloads paralelos, permite {} downloads por vez )" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "Entrada inválida! Tente novamente com uma entrada válida [1 para {}, ou 0 para desativar]" diff --git a/archinstall/locales/ru/LC_MESSAGES/base.mo b/archinstall/locales/ru/LC_MESSAGES/base.mo index 1da3a370..4480d852 100644 Binary files a/archinstall/locales/ru/LC_MESSAGES/base.mo and b/archinstall/locales/ru/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/ru/LC_MESSAGES/base.po b/archinstall/locales/ru/LC_MESSAGES/base.po index a0263aa3..90d78f2e 100644 --- a/archinstall/locales/ru/LC_MESSAGES/base.po +++ b/archinstall/locales/ru/LC_MESSAGES/base.po @@ -794,18 +794,17 @@ msgstr "Настроено интерфейсов: {}" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "Этот параметр определяет количество параллельных загрузок, которые могут происходить во время установки" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "Введите количество параллельных загрузок, которые будут включены.\n" -" (Введите значение от 1 до {max_downloads})\n" +" (Введите значение от 1 до {})\n" "Примечание:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Максимальное значение: {max_downloads} ( Позволяет {max_downloads} параллельных загрузок, позволяет {max_downloads+1} загрузок одновременно )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - Максимальное значение: {} ( Позволяет {} параллельных загрузок, позволяет {} загрузок одновременно )" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - Минимальное значение: 1 ( Позволяет 1 параллельную загрузку, позволяет 2 загрузки одновременно )" @@ -813,9 +812,9 @@ msgstr " - Минимальное значение: 1 ( Позволяет 1 п msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - Отключить/по умолчанию: 0 ( Отключает параллельную загрузку, позволяет только 1 загрузку за один раз )" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "Неверный ввод! Повторите попытку с правильным вводом [1 - {max_downloads}, или 0 - отключить]" +msgstr "Неверный ввод! Повторите попытку с правильным вводом [1 - {}, или 0 - отключить]" msgid "Parallel Downloads" msgstr "Параллельные загрузки" @@ -1171,6 +1170,13 @@ msgstr "Регион зеркала" msgid "Mirror regions" msgstr "Регион зеркала" +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - Максимальное значение: {} ( Позволяет {} параллельных загрузок, позволяет {} загрузок одновременно )" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "Неверный ввод! Повторите попытку с правильным вводом [1 - {}, или 0 - отключить]" + #, python-brace-format #~ msgid "Edit {origkey} :" #~ msgstr "Редактировать {origkey}:" diff --git a/archinstall/locales/sv/LC_MESSAGES/base.po b/archinstall/locales/sv/LC_MESSAGES/base.po index ea81ad80..ebb7a275 100644 --- a/archinstall/locales/sv/LC_MESSAGES/base.po +++ b/archinstall/locales/sv/LC_MESSAGES/base.po @@ -804,14 +804,13 @@ msgstr "" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" msgstr "" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" @@ -1178,3 +1177,9 @@ msgstr "Region för paketsynk" #, fuzzy msgid "Mirror regions" msgstr "Region för paketsynk" + +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr "" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "" diff --git a/archinstall/locales/ta/LC_MESSAGES/base.mo b/archinstall/locales/ta/LC_MESSAGES/base.mo index 3f175509..fc2b70e6 100644 Binary files a/archinstall/locales/ta/LC_MESSAGES/base.mo and b/archinstall/locales/ta/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/ta/LC_MESSAGES/base.po b/archinstall/locales/ta/LC_MESSAGES/base.po index 44aebb19..14ed4d98 100644 --- a/archinstall/locales/ta/LC_MESSAGES/base.po +++ b/archinstall/locales/ta/LC_MESSAGES/base.po @@ -793,18 +793,17 @@ msgstr "கட்டமைக்கப்பட்ட {} இடைமுகங msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "இந்த விருப்பம் நிறுவலின் போது நிகழக்கூடிய இணையான பதிவிறக்கங்களின் எண்ணிக்கையை செயல்படுத்துகிறது" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "இயக்கப்பட வேண்டிய இணையான பதிவிறக்கங்களின் எண்ணிக்கையை உள்ளிடவும்.\n" -" (1 முதல் {max_downloads} வரையிலான மதிப்பை உள்ளிடவும்)\n" +" (1 முதல் {} வரையிலான மதிப்பை உள்ளிடவும்)\n" "குறிப்பு:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - அதிகபட்ச மதிப்பு : {max_downloads} ( {max_downloads} இணையான பதிவிறக்கங்களை அனுமதிக்கிறது, ஒரே நேரத்தில் {max_downloads+1} பதிவிறக்கங்களை அனுமதிக்கிறது )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - அதிகபட்ச மதிப்பு : {} ( {} இணையான பதிவிறக்கங்களை அனுமதிக்கிறது, ஒரே நேரத்தில் {} பதிவிறக்கங்களை அனுமதிக்கிறது )" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - குறைந்தபட்ச மதிப்பு : 1 (1 இணை பதிவிறக்கத்தை அனுமதிக்கிறது, ஒரு நேரத்தில் 2 பதிவிறக்கங்களை அனுமதிக்கிறது )" @@ -812,9 +811,9 @@ msgstr " - குறைந்தபட்ச மதிப்பு : 1 (1 இ msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - முடக்கு/இயல்புநிலை: 0 (இணை பதிவிறக்கத்தை முடக்குகிறது, ஒரு நேரத்தில் 1 பதிவிறக்கத்தை மட்டுமே அனுமதிக்கிறது )" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "தவறான உள்ளீடு! சரியான உள்ளீட்டில் [1 முதல் {max_downloads} வரை அல்லது முடக்க 0 வரை] மீண்டும் முயற்சிக்கவும்" +msgstr "தவறான உள்ளீடு! சரியான உள்ளீட்டில் [1 முதல் {} வரை அல்லது முடக்க 0 வரை] மீண்டும் முயற்சிக்கவும்" msgid "Parallel Downloads" msgstr "இணையான பதிவிறக்கங்கள்" @@ -1169,3 +1168,10 @@ msgstr "மிரர் பிராந்தியம்" #, fuzzy msgid "Mirror regions" msgstr "மிரர் பிராந்தியம்" + +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - அதிகபட்ச மதிப்பு : {} ( {} இணையான பதிவிறக்கங்களை அனுமதிக்கிறது, ஒரே நேரத்தில் {} பதிவிறக்கங்களை அனுமதிக்கிறது )" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "தவறான உள்ளீடு! சரியான உள்ளீட்டில் [1 முதல் {} வரை அல்லது முடக்க 0 வரை] மீண்டும் முயற்சிக்கவும்" diff --git a/archinstall/locales/tr/LC_MESSAGES/base.po b/archinstall/locales/tr/LC_MESSAGES/base.po index 40efea03..20fa4f23 100644 --- a/archinstall/locales/tr/LC_MESSAGES/base.po +++ b/archinstall/locales/tr/LC_MESSAGES/base.po @@ -804,14 +804,13 @@ msgstr "" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" msgstr "" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" @@ -1177,3 +1176,9 @@ msgstr "İndirme sunucusu bölgesi" #, fuzzy msgid "Mirror regions" msgstr "İndirme sunucusu bölgesi" + +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr "" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "" diff --git a/archinstall/locales/uk/LC_MESSAGES/base.mo b/archinstall/locales/uk/LC_MESSAGES/base.mo index ae98dcfb..e7cb8b0b 100644 Binary files a/archinstall/locales/uk/LC_MESSAGES/base.mo and b/archinstall/locales/uk/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/uk/LC_MESSAGES/base.po b/archinstall/locales/uk/LC_MESSAGES/base.po index f2c7737c..a700c126 100644 --- a/archinstall/locales/uk/LC_MESSAGES/base.po +++ b/archinstall/locales/uk/LC_MESSAGES/base.po @@ -793,18 +793,17 @@ msgstr "Налаштовані інтерфейси {}" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "Цей параметр вмикає кількість паралельних завантажень, які можуть відбуватися під час встановлення" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "Введіть кількість паралельних завантажень, які потрібно ввімкнути.\n" -" (Введіть значення від 1 до {max_downloads})\n" +" (Введіть значення від 1 до {})\n" "Примітка:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Максимальне значення : {max_downloads} ( Дозволяє {max_downloads} паралельних завантажень, дозволяє {max_downloads+1} завантажень за раз )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - Максимальне значення : {} ( Дозволяє {} паралельних завантажень, дозволяє {} завантажень за раз )" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - Мінімальне значення : 1 ( дозволяє 1 паралельне завантаження, дозволяє 2 завантаження одночасно )" @@ -812,9 +811,9 @@ msgstr " - Мінімальне значення : 1 ( дозволяє 1 па msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - Вимкнути/Типово : 0 ( Вимикає паралельне завантаження, дозволяє лише 1 завантаження за раз )" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "Некоректне введення! Повторіть спробу з валідним введенням [від 1 до {max_downloads} або 0 для вимкнення]" +msgstr "Некоректне введення! Повторіть спробу з валідним введенням [від 1 до {} або 0 для вимкнення]" msgid "Parallel Downloads" msgstr "Паралельні Завантаження" @@ -1167,3 +1166,10 @@ msgstr "Регіон дзеркала" #, fuzzy msgid "Mirror regions" msgstr "Регіон дзеркала" + +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - Максимальне значення : {} ( Дозволяє {} паралельних завантажень, дозволяє {} завантажень за раз )" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "Некоректне введення! Повторіть спробу з валідним введенням [від 1 до {} або 0 для вимкнення]" diff --git a/archinstall/locales/ur/LC_MESSAGES/base.po b/archinstall/locales/ur/LC_MESSAGES/base.po index 6660f3b4..ac648108 100644 --- a/archinstall/locales/ur/LC_MESSAGES/base.po +++ b/archinstall/locales/ur/LC_MESSAGES/base.po @@ -825,14 +825,13 @@ msgstr "" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" msgstr "" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" @@ -1198,6 +1197,12 @@ msgstr "متبادل علاقہ" msgid "Mirror regions" msgstr "متبادل علاقہ" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr "" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "" + #~ msgid "Add :" #~ msgstr "شامل:" diff --git a/archinstall/locales/zh-CN/LC_MESSAGES/base.mo b/archinstall/locales/zh-CN/LC_MESSAGES/base.mo index 693308ab..4502c562 100644 Binary files a/archinstall/locales/zh-CN/LC_MESSAGES/base.mo and b/archinstall/locales/zh-CN/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/zh-CN/LC_MESSAGES/base.po b/archinstall/locales/zh-CN/LC_MESSAGES/base.po index afa1716b..04a703ed 100644 --- a/archinstall/locales/zh-CN/LC_MESSAGES/base.po +++ b/archinstall/locales/zh-CN/LC_MESSAGES/base.po @@ -792,18 +792,17 @@ msgstr "已配置的 {} 接口" msgid "This option enables the number of parallel downloads that can occur during installation" msgstr "此选项启用安装期间可能发生的并行下载次数" -#, python-brace-format msgid "" "Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {max_downloads})\n" +" (Enter a value between 1 to {})\n" "Note:" msgstr "" "输入要启用的并行下载数。\n" -" (输入一个介于 1 到 {max_downloads} 之间的值)\n" +" (输入一个介于 1 到 {} 之间的值)\n" "提示:" -msgid " - Maximum value : {max_downloads} ( Allows {max_downloads} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - 最大值:{max_downloads}(允许 {max_downloads} 次并行下载,一次允许 {max_downloads+1} 次下载)" +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +msgstr " - 最大值:{}(允许 {} 次并行下载,一次允许 {} 次下载)" msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" msgstr " - 最小值:1(允许 1 次并行下载,一次允许 2 次下载)" @@ -811,9 +810,9 @@ msgstr " - 最小值:1(允许 1 次并行下载,一次允许 2 次下载 msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" msgstr " - 禁用/默认:0(禁用并行下载,一次只允许 1 个下载)" -#, python-brace-format +#, fuzzy, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "输入无效! 使用有效输入重试 [1 到 {max_downloads},或 0 到禁用]" +msgstr "输入无效! 使用有效输入重试 [1 到 {},或 0 到禁用]" msgid "Parallel Downloads" msgstr "并行下载" @@ -1168,3 +1167,10 @@ msgstr "镜像区域" #, fuzzy msgid "Mirror regions" msgstr "镜像区域" + +#, fuzzy +msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +msgstr " - 最大值:{}(允许 {} 次并行下载,一次允许 {} 次下载)" + +msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +msgstr "输入无效! 使用有效输入重试 [1 到 {},或 0 到禁用]" -- cgit v1.2.3-54-g00ecf From 439bb5428bb6a6f512f695a83ee6b3b8f6537598 Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Tue, 25 Jul 2023 19:17:09 +1000 Subject: Fix 1934 - audio server regression (#1946) * Audio configuration * Update * Update schema --------- Co-authored-by: Daniel Girtler --- archinstall/__init__.py | 3 ++ archinstall/lib/global_menu.py | 27 ++++++++------ archinstall/lib/interactions/general_conf.py | 30 +++++++++++---- archinstall/lib/models/__init__.py | 1 + archinstall/lib/models/audio_configuration.py | 54 +++++++++++++++++++++++++++ archinstall/scripts/guided.py | 19 +++------- archinstall/scripts/swiss.py | 19 ++++------ docs/installing/guided.rst | 2 +- examples/config-sample.json | 22 ++++------- examples/custom-command-sample.json | 1 - examples/interactive_installation.py | 22 +++-------- schema.json | 19 ++++++---- 12 files changed, 137 insertions(+), 82 deletions(-) create mode 100644 archinstall/lib/models/audio_configuration.py (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/__init__.py b/archinstall/__init__.py index c4b64912..cfaecd16 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -237,6 +237,9 @@ def load_config(): if arguments.get('bootloader', None) is not None: arguments['bootloader'] = models.Bootloader.from_arg(arguments['bootloader']) + if arguments.get('audio_config', None) is not None: + arguments['audio_config'] = models.AudioConfiguration.parse_arg(arguments['audio_config']) + if arguments.get('disk_encryption', None) is not None and disk_config is not None: password = arguments.get('encryption_password', '') arguments['disk_encryption'] = disk.DiskEncryption.parse_arg( diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index 5503d9ce..fb62b7b5 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Any, List, Optional, Union, Dict, TYPE_CHECKING +from typing import Any, List, Optional, Dict, TYPE_CHECKING from . import disk from .general import secret @@ -9,6 +9,7 @@ from .menu import Selector, AbstractMenu from .mirrors import MirrorConfiguration, MirrorMenu from .models import NetworkConfiguration, NicType from .models.bootloader import Bootloader +from .models.audio_configuration import Audio, AudioConfiguration from .models.users import User from .output import FormattedOutput from .profile.profile_menu import ProfileConfiguration @@ -109,12 +110,11 @@ class GlobalMenu(AbstractMenu): display_func=lambda x: x.profile.name if x else '', preview_func=self._prev_profile ) - self._menu_options['audio'] = \ + self._menu_options['audio_config'] = \ Selector( _('Audio'), lambda preset: self._select_audio(preset), - display_func=lambda x: x if x else '', - default=None + display_func=lambda x: self._display_audio(x) ) self._menu_options['parallel downloads'] = \ Selector( @@ -421,13 +421,18 @@ class GlobalMenu(AbstractMenu): profile_config = ProfileMenu(store, preset=current_profile).run() return profile_config - def _select_audio(self, current: Union[str, None]) -> Optional[str]: - profile_config: Optional[ProfileConfiguration] = self._menu_options['profile_config'].current_selection - if profile_config and profile_config.profile: - is_desktop = profile_config.profile.is_desktop_profile() if profile_config else False - selection = ask_for_audio_selection(is_desktop, current) - return selection - return None + def _select_audio( + self, + current: Optional[AudioConfiguration] = None + ) -> Optional[AudioConfiguration]: + selection = ask_for_audio_selection(current) + return selection + + def _display_audio(self, current: Optional[AudioConfiguration]) -> str: + if not current: + return Audio.no_audio_text() + else: + return current.audio.name def _create_user_account(self, defined_users: List[User]) -> List[User]: users = ask_for_additional_users(defined_users=defined_users) diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index ad9ee386..1c570a69 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -5,6 +5,7 @@ from typing import List, Any, Optional, TYPE_CHECKING from ..locale import list_timezones, list_keyboard_languages from ..menu import MenuSelectionType, Menu, TextInput +from ..models.audio_configuration import Audio, AudioConfiguration from ..output import warn from ..packages.packages import validate_package_list from ..storage import storage @@ -55,16 +56,31 @@ def ask_for_a_timezone(preset: Optional[str] = None) -> Optional[str]: return None -def ask_for_audio_selection(desktop: bool = True, preset: Optional[str] = None) -> Optional[str]: - no_audio = str(_('No audio server')) - choices = ['pipewire', 'pulseaudio'] if desktop else ['pipewire', 'pulseaudio', no_audio] - default = 'pipewire' if desktop else no_audio +def ask_for_audio_selection( + current: Optional[AudioConfiguration] = None +) -> Optional[AudioConfiguration]: + choices = [ + Audio.Pipewire.name, + Audio.Pulseaudio.name, + Audio.no_audio_text() + ] - choice = Menu(_('Choose an audio server'), choices, preset_values=preset, default_option=default).run() + preset = current.audio.name if current else None + + choice = Menu( + _('Choose an audio server'), + choices, + preset_values=preset + ).run() match choice.type_: - case MenuSelectionType.Skip: return preset - case MenuSelectionType.Selection: return choice.single_value + case MenuSelectionType.Skip: return current + case MenuSelectionType.Selection: + value = choice.single_value + if value == Audio.no_audio_text(): + return None + else: + return AudioConfiguration(Audio[value]) return None diff --git a/archinstall/lib/models/__init__.py b/archinstall/lib/models/__init__.py index 7415f63f..a1c90e48 100644 --- a/archinstall/lib/models/__init__.py +++ b/archinstall/lib/models/__init__.py @@ -6,3 +6,4 @@ from .network_configuration import ( from .bootloader import Bootloader from .gen import VersionDef, PackageSearchResult, PackageSearch, LocalPackage from .users import PasswordStrength, User +from .audio_configuration import Audio, AudioConfiguration diff --git a/archinstall/lib/models/audio_configuration.py b/archinstall/lib/models/audio_configuration.py new file mode 100644 index 00000000..3a4029db --- /dev/null +++ b/archinstall/lib/models/audio_configuration.py @@ -0,0 +1,54 @@ +from dataclasses import dataclass +from enum import Enum +from typing import Any, TYPE_CHECKING, Dict + +from ..hardware import SysInfo +from ..output import info +from ...default_profiles.applications.pipewire import PipewireProfile + +if TYPE_CHECKING: + _: Any + + +@dataclass +class Audio(Enum): + Pipewire = 'pipewire' + Pulseaudio = 'pulseaudio' + + @staticmethod + def no_audio_text() -> str: + return str(_('No audio server')) + + +@dataclass +class AudioConfiguration: + audio: Audio + + def __dump__(self) -> Dict[str, Any]: + return { + 'audio': self.audio.value + } + + @staticmethod + def parse_arg(arg: Dict[str, Any]) -> 'AudioConfiguration': + return AudioConfiguration( + Audio(arg['audio']) + ) + + def install_audio_config( + self, + installation: Any + ): + info(f'Installing audio server: {self.audio.name}') + + match self.audio: + case Audio.Pipewire: + PipewireProfile().install(installation) + case Audio.Pulseaudio: + installation.add_additional_packages("pulseaudio") + + if SysInfo.requires_sof_fw(): + installation.add_additional_packages('sof-firmware') + + if SysInfo.requires_alsa_fw(): + installation.add_additional_packages('alsa-firmware') diff --git a/archinstall/scripts/guided.py b/archinstall/scripts/guided.py index c8df590d..605d2b0e 100644 --- a/archinstall/scripts/guided.py +++ b/archinstall/scripts/guided.py @@ -8,11 +8,11 @@ from archinstall import SysInfo from archinstall.lib import locale from archinstall.lib import disk from archinstall.lib.global_menu import GlobalMenu -from archinstall.default_profiles.applications.pipewire import PipewireProfile from archinstall.lib.configuration import ConfigurationOutput from archinstall.lib.installer import Installer from archinstall.lib.menu import Menu from archinstall.lib.mirrors import use_mirrors, add_custom_mirrors +from archinstall.lib.models import AudioConfiguration from archinstall.lib.models.bootloader import Bootloader from archinstall.lib.models.network_configuration import NetworkConfiguration from archinstall.lib.networking import check_mirror_reachable @@ -70,7 +70,7 @@ def ask_user_questions(): global_menu.enable('profile_config') # Ask about audio server selection if one is not already set - global_menu.enable('audio') + global_menu.enable('audio_config') # Ask for preferred kernel: global_menu.enable('kernels', mandatory=True) @@ -172,18 +172,9 @@ def perform_installation(mountpoint: Path): if users := archinstall.arguments.get('!users', None): installation.create_users(users) - if audio := archinstall.arguments.get('audio', None): - info(f'Installing audio server: {audio}') - if audio == 'pipewire': - PipewireProfile().install(installation) - elif audio == 'pulseaudio': - installation.add_additional_packages("pulseaudio") - - if SysInfo.requires_sof_fw(): - installation.add_additional_packages('sof-firmware') - - if SysInfo.requires_alsa_fw(): - installation.add_additional_packages('alsa-firmware') + audio_config: Optional[AudioConfiguration] = archinstall.arguments.get('audio_config', None) + if audio_config: + audio_config.install_audio_config(installation) else: info("No audio server will be installed") diff --git a/archinstall/scripts/swiss.py b/archinstall/scripts/swiss.py index a2ab0549..cd532f6d 100644 --- a/archinstall/scripts/swiss.py +++ b/archinstall/scripts/swiss.py @@ -1,7 +1,7 @@ import os from enum import Enum from pathlib import Path -from typing import TYPE_CHECKING, Any, Dict +from typing import TYPE_CHECKING, Any, Dict, Optional import archinstall from archinstall import SysInfo, info, debug @@ -9,13 +9,13 @@ from archinstall.lib import mirrors from archinstall.lib import models from archinstall.lib import disk from archinstall.lib import locale +from archinstall.lib.models import AudioConfiguration from archinstall.lib.networking import check_mirror_reachable from archinstall.lib.profile.profiles_handler import profile_handler from archinstall.lib import menu from archinstall.lib.global_menu import GlobalMenu from archinstall.lib.installer import Installer from archinstall.lib.configuration import ConfigurationOutput -from archinstall.default_profiles.applications.pipewire import PipewireProfile if TYPE_CHECKING: _: Any @@ -95,7 +95,7 @@ class SwissMainMenu(GlobalMenu): options_list = [ 'mirror_config', 'disk_config', 'disk_encryption', 'swap', 'bootloader', 'hostname', '!root-password', - '!users', 'profile_config', 'audio', 'kernels', 'packages', 'additional-repositories', 'network_config', + '!users', 'profile_config', 'audio_config', 'kernels', 'packages', 'additional-repositories', 'network_config', 'timezone', 'ntp' ] @@ -109,7 +109,7 @@ class SwissMainMenu(GlobalMenu): case ExecutionMode.Only_OS: options_list = [ 'mirror_config','bootloader', 'hostname', - '!root-password', '!users', 'profile_config', 'audio', 'kernels', + '!root-password', '!users', 'profile_config', 'audio_config', 'kernels', 'packages', 'additional-repositories', 'network_config', 'timezone', 'ntp' ] @@ -236,14 +236,11 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode): if users := archinstall.arguments.get('!users', None): installation.create_users(users) - if audio := archinstall.arguments.get('audio', None): - info(f'Installing audio server: {audio}') - if audio == 'pipewire': - PipewireProfile().install(installation) - elif audio == 'pulseaudio': - installation.add_additional_packages("pulseaudio") + audio_config: Optional[AudioConfiguration] = archinstall.arguments.get('audio_config', None) + if audio_config: + audio_config.install_audio_config(installation) else: - info("No audio server will be installed.") + info("No audio server will be installed") if profile_config := archinstall.arguments.get('profile_config', None): profile_handler.install_profile_config(installation, profile_config) diff --git a/docs/installing/guided.rst b/docs/installing/guided.rst index 0a075282..c5e7f1ed 100644 --- a/docs/installing/guided.rst +++ b/docs/installing/guided.rst @@ -53,7 +53,7 @@ There are three different configuration files, all of which are optional. .. code-block:: json { - "audio": "pipewire", + "audio_config": {"audio": "pipewire"}, "bootloader": "systemd-bootctl", "custom-commands": [ "cd /home/devel; git clone https://aur.archlinux.org/paru.git", diff --git a/examples/config-sample.json b/examples/config-sample.json index 38415b2c..ed1cc38e 100644 --- a/examples/config-sample.json +++ b/examples/config-sample.json @@ -2,7 +2,7 @@ "config_version": "2.5.2", "additional-repositories": [], "archinstall-language": "English", - "audio": "pipewire", + "audio_config": {"audio": "pipewire"}, "bootloader": "Systemd-boot", "debug": false, "disk_config": { @@ -99,19 +99,13 @@ "http://archlinux.mirror.digitalpacific.com.au/$repo/os/$arch": true, } }, - "network_config": { - "nics": [ - { - "dhcp": false, - "dns": [ - "3.3.3.3" - ], - "gateway": "2.2.2.2", - "iface": "enp0s31f6", - "ip": "1.1.1.1" - } - ], - "type": "manual" + "nic": { + "dhcp": true, + "dns": null, + "gateway": null, + "iface": null, + "ip": null, + "type": "nm" }, "no_pkg_lookups": false, "ntp": true, diff --git a/examples/custom-command-sample.json b/examples/custom-command-sample.json index b2250e2c..34d63d74 100644 --- a/examples/custom-command-sample.json +++ b/examples/custom-command-sample.json @@ -1,6 +1,5 @@ { "dry_run": true, - "audio": "none", "bootloader": "systemd-bootctl", "debug": false, "harddrives": [ diff --git a/examples/interactive_installation.py b/examples/interactive_installation.py index 8e82ca7e..e075df9b 100644 --- a/examples/interactive_installation.py +++ b/examples/interactive_installation.py @@ -1,12 +1,11 @@ from pathlib import Path -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Optional import archinstall from archinstall import Installer from archinstall import profile from archinstall import SysInfo from archinstall import mirrors -from archinstall.default_profiles.applications.pipewire import PipewireProfile from archinstall import disk from archinstall import menu from archinstall import models @@ -49,7 +48,7 @@ def ask_user_questions(): global_menu.enable('profile_config') # Ask about audio server selection if one is not already set - global_menu.enable('audio') + global_menu.enable('audio_config') # Ask for preferred kernel: global_menu.enable('kernels', mandatory=True) @@ -151,20 +150,11 @@ def perform_installation(mountpoint: Path): if users := archinstall.arguments.get('!users', None): installation.create_users(users) - if audio := archinstall.arguments.get('audio', None): - info(f'Installing audio server: {audio}') - if audio == 'pipewire': - PipewireProfile().install(installation) - elif audio == 'pulseaudio': - installation.add_additional_packages("pulseaudio") - - if SysInfo.requires_sof_fw(): - installation.add_additional_packages('sof-firmware') - - if SysInfo.requires_alsa_fw(): - installation.add_additional_packages('alsa-firmware') + audio_config: Optional[models.AudioConfiguration] = archinstall.arguments.get('audio_config', None) + if audio_config: + audio_config.install_audio_config(installation) else: - info("No audio server will be installed.") + info("No audio server will be installed") if profile_config := archinstall.arguments.get('profile_config', None): profile.profile_handler.install_profile_config(installation, profile_config) diff --git a/schema.json b/schema.json index b74588a1..5616ed41 100644 --- a/schema.json +++ b/schema.json @@ -12,14 +12,19 @@ "testing" ] }, - "audio": { + "audio_config": { "description": "Audio server to be installed", - "type": "string", - "enum": [ - "pipewire", - "pulseaudio", - "none" - ] + "type": "object", + "properties": { + "audio": { + "description": "Audio server to be installed", + "type": "string", + "enum": [ + "pipewire", + "pulseaudio" + ] + } + }, }, "bootloader": { "description": "Bootloader to be installed", -- cgit v1.2.3-54-g00ecf From 9cbb2b75940e3aad1a0236662c45437d70eac1af Mon Sep 17 00:00:00 2001 From: Mário Victor Ribeiro Silva Date: Mon, 31 Jul 2023 04:38:42 -0300 Subject: Parallel downloads (#1952) * refactor: remove max_downloads limit * Update parallel downloads * Update parallel downloads --- archinstall/lib/interactions/general_conf.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index 1c570a69..14fcc3f8 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -165,23 +165,20 @@ def ask_additional_packages_to_install(preset: List[str] = []) -> List[str]: def add_number_of_parrallel_downloads(input_number :Optional[int] = None) -> Optional[int]: - max_downloads = 5 - print(_(f"This option enables the number of parallel downloads that can occur during installation")) - print(str(_("Enter the number of parallel downloads to be enabled.\n (Enter a value between 1 to {})\nNote:")).format(max_downloads)) - print(str(_(" - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )")).format(max_downloads, max_downloads, max_downloads + 1)) - print(_(" - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )")) - print(_(" - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )")) + max_recommended = 5 + print(_(f"This option enables the number of parallel downloads that can occur during package downloads")) + print(_("Enter the number of parallel downloads to be enabled.\n\nNote:\n")) + print(str(_(" - Maximum recommended value : {} ( Allows {} parallel downloads at a time )")).format(max_recommended, max_recommended)) + print(_(" - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )\n")) while True: try: input_number = int(TextInput(_("[Default value: 0] > ")).run().strip() or 0) if input_number <= 0: input_number = 0 - elif input_number > max_downloads: - input_number = max_downloads break except: - print(str(_("Invalid input! Try again with a valid input [1 to {}, or 0 to disable]")).format(max_downloads)) + print(str(_("Invalid input! Try again with a valid input [or 0 to disable]")).format(max_recommended)) pacman_conf_path = pathlib.Path("/etc/pacman.conf") with pacman_conf_path.open() as f: @@ -190,7 +187,7 @@ def add_number_of_parrallel_downloads(input_number :Optional[int] = None) -> Opt with pacman_conf_path.open("w") as fwrite: for line in pacman_conf: if "ParallelDownloads" in line: - fwrite.write(f"ParallelDownloads = {input_number+1}\n") if not input_number == 0 else fwrite.write("#ParallelDownloads = 0\n") + fwrite.write(f"ParallelDownloads = {input_number}\n") if not input_number == 0 else fwrite.write("#ParallelDownloads = 0\n") else: fwrite.write(f"{line}\n") -- cgit v1.2.3-54-g00ecf From 12b7017240a040fd4fbebf7c5794a1ca5560f0ea Mon Sep 17 00:00:00 2001 From: Alexander Seiler Date: Mon, 18 Sep 2023 14:04:36 +0200 Subject: Fix many typos (#1692) Signed-off-by: Alexander Seiler --- archinstall/__init__.py | 2 +- archinstall/default_profiles/profile.py | 6 +++--- archinstall/lib/disk/device_model.py | 2 +- archinstall/lib/disk/fido.py | 2 +- archinstall/lib/general.py | 2 +- archinstall/lib/global_menu.py | 4 ++-- archinstall/lib/installer.py | 10 +++++----- archinstall/lib/interactions/__init__.py | 2 +- archinstall/lib/interactions/general_conf.py | 2 +- archinstall/lib/menu/list_manager.py | 2 +- archinstall/lib/menu/menu.py | 2 +- archinstall/lib/output.py | 2 +- archinstall/lib/translationhandler.py | 2 +- archinstall/scripts/guided.py | 4 ++-- archinstall/scripts/swiss.py | 6 +++--- examples/interactive_installation.py | 4 ++-- 16 files changed, 27 insertions(+), 27 deletions(-) (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/__init__.py b/archinstall/__init__.py index 39588904..7645ae39 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -43,7 +43,7 @@ __version__ = "2.6.0" storage['__version__'] = __version__ -# add the custome _ as a builtin, it can now be used anywhere in the +# add the custom _ as a builtin, it can now be used anywhere in the # project to mark strings as translatable with _('translate me') DeferredTranslation.install() diff --git a/archinstall/default_profiles/profile.py b/archinstall/default_profiles/profile.py index 982bd5a3..49a9c19d 100644 --- a/archinstall/default_profiles/profile.py +++ b/archinstall/default_profiles/profile.py @@ -81,7 +81,7 @@ class Profile: def packages(self) -> List[str]: """ Returns a list of packages that should be installed when - this profile is among the choosen ones + this profile is among the chosen ones """ return self._packages @@ -128,7 +128,7 @@ class Profile: """ Set the custom settings for the profile. This is also called when the settings are parsed from the config - and can be overriden to perform further actions based on the profile + and can be overridden to perform further actions based on the profile """ self.custom_settings = settings @@ -179,7 +179,7 @@ class Profile: def preview_text(self) -> Optional[str]: """ Used for preview text in profiles_bck. If a description is set for a - profile it will automatically display that one in the preivew. + profile it will automatically display that one in the preview. If no preview or a different text should be displayed just """ if self.description: diff --git a/archinstall/lib/disk/device_model.py b/archinstall/lib/disk/device_model.py index 6eeb0d91..69038b01 100644 --- a/archinstall/lib/disk/device_model.py +++ b/archinstall/lib/disk/device_model.py @@ -202,7 +202,7 @@ class Size: # not sure why we would ever wanna convert to percentages if target_unit == Unit.Percent and total_size is None: - raise ValueError('Missing paramter total size to be able to convert to percentage') + raise ValueError('Missing parameter total size to be able to convert to percentage') if self.unit == target_unit: return self diff --git a/archinstall/lib/disk/fido.py b/archinstall/lib/disk/fido.py index 96a74991..9eeba56a 100644 --- a/archinstall/lib/disk/fido.py +++ b/archinstall/lib/disk/fido.py @@ -34,7 +34,7 @@ class Fido2: /dev/hidraw1 Yubico YubiKey OTP+FIDO+CCID """ - # to prevent continous reloading which will slow + # to prevent continuous reloading which will slow # down moving the cursor in the menu if not cls._loaded or reload: try: diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index 611378ee..e22e7eed 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -30,7 +30,7 @@ if TYPE_CHECKING: def generate_password(length :int = 64) -> str: - haystack = string.printable # digits, ascii_letters, punctiation (!"#$[] etc) and whitespace + haystack = string.printable # digits, ascii_letters, punctuation (!"#$[] etc) and whitespace return ''.join(secrets.choice(haystack) for i in range(length)) diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index fb62b7b5..b38dac0b 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -15,7 +15,7 @@ from .output import FormattedOutput from .profile.profile_menu import ProfileConfiguration from .storage import storage from .configuration import save_config -from .interactions import add_number_of_parrallel_downloads +from .interactions import add_number_of_parallel_downloads from .interactions import ask_additional_packages_to_install from .interactions import ask_for_additional_users from .interactions import ask_for_audio_selection @@ -119,7 +119,7 @@ class GlobalMenu(AbstractMenu): self._menu_options['parallel downloads'] = \ Selector( _('Parallel Downloads'), - lambda preset: add_number_of_parrallel_downloads(preset), + lambda preset: add_number_of_parallel_downloads(preset), display_func=lambda x: x if x else '0', default=0 ) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 09e91ab8..34c9441f 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -194,7 +194,7 @@ class Installer: for part_mod in sorted_part_mods: if luks_handler := luks_handlers.get(part_mod): # mount encrypted partition - self._mount_luks_partiton(part_mod, luks_handler) + self._mount_luks_partition(part_mod, luks_handler) else: # partition is not encrypted self._mount_partition(part_mod) @@ -219,7 +219,7 @@ class Installer: if part_mod.fs_type == disk.FilesystemType.Btrfs and part_mod.dev_path: self._mount_btrfs_subvol(part_mod.dev_path, part_mod.btrfs_subvols) - def _mount_luks_partiton(self, part_mod: disk.PartitionModification, luks_handler: Luks2): + def _mount_luks_partition(self, part_mod: disk.PartitionModification, luks_handler: Luks2): # it would be none if it's btrfs as the subvolumes will have the mountpoints defined if part_mod.mountpoint and luks_handler.mapper_dev: target = self.target / part_mod.relative_mountpoint @@ -315,7 +315,7 @@ class Installer: raise RequirementError(f'Could not generate fstab, strapping in packages most likely failed (disk out of space?)\n Error: {err}') if not gen_fstab: - raise RequirementError(f'Genrating fstab returned empty value') + raise RequirementError(f'Generating fstab returned empty value') with open(fstab_path, 'a') as fp: fp.write(gen_fstab) @@ -434,7 +434,7 @@ class Installer: return False - def activate_time_syncronization(self) -> None: + def activate_time_synchronization(self) -> None: info('Activating systemd-timesyncd for time synchronization using Arch Linux and ntp.org NTP servers') self.enable_service('systemd-timesyncd') @@ -1008,7 +1008,7 @@ When = PostTransaction Exec = /bin/sh -c \\"/usr/bin/limine bios-install /dev/disk/by-uuid/{root_uuid} && /usr/bin/cp /usr/share/limine/limine-bios.sys /boot/\\" """) - # Limine does not ship with a default configuation file. We are going to + # Limine does not ship with a default configuration file. We are going to # create a basic one that is similar to the one GRUB generates. try: config = f""" diff --git a/archinstall/lib/interactions/__init__.py b/archinstall/lib/interactions/__init__.py index 53be8e7a..50c0012d 100644 --- a/archinstall/lib/interactions/__init__.py +++ b/archinstall/lib/interactions/__init__.py @@ -11,7 +11,7 @@ from .disk_conf import ( from .general_conf import ( ask_ntp, ask_hostname, ask_for_a_timezone, ask_for_audio_selection, select_archinstall_language, ask_additional_packages_to_install, - add_number_of_parrallel_downloads, select_additional_repositories + add_number_of_parallel_downloads, select_additional_repositories ) from .system_conf import ( diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index 14fcc3f8..8dd6e94f 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -164,7 +164,7 @@ def ask_additional_packages_to_install(preset: List[str] = []) -> List[str]: return packages -def add_number_of_parrallel_downloads(input_number :Optional[int] = None) -> Optional[int]: +def add_number_of_parallel_downloads(input_number :Optional[int] = None) -> Optional[int]: max_recommended = 5 print(_(f"This option enables the number of parallel downloads that can occur during package downloads")) print(_("Enter the number of parallel downloads to be enabled.\n\nNote:\n")) diff --git a/archinstall/lib/menu/list_manager.py b/archinstall/lib/menu/list_manager.py index be31fdf0..54fb6a1b 100644 --- a/archinstall/lib/menu/list_manager.py +++ b/archinstall/lib/menu/list_manager.py @@ -80,7 +80,7 @@ class ListManager: self._data = self.handle_action(choice.value, None, self._data) elif choice.value in self._terminate_actions: break - else: # an entry of the existing selection was choosen + else: # an entry of the existing selection was chosen selected_entry = data_formatted[choice.value] # type: ignore self._run_actions_on_entry(selected_entry) diff --git a/archinstall/lib/menu/menu.py b/archinstall/lib/menu/menu.py index 358ba5e4..3bd31b88 100644 --- a/archinstall/lib/menu/menu.py +++ b/archinstall/lib/menu/menu.py @@ -123,7 +123,7 @@ class Menu(TerminalMenu): :param allow_reset: This will explicitly handle a ctrl+c instead and return that specific state :type allow_reset: bool - param allow_reset_warning_msg: If raise_error_on_interrupt is True the warnign is set, a user confirmation is displayed + param allow_reset_warning_msg: If raise_error_on_interrupt is True the warning is set, a user confirmation is displayed type allow_reset_warning_msg: str :param extra_bottom_space: Add an extra empty line at the end of the menu diff --git a/archinstall/lib/output.py b/archinstall/lib/output.py index 63d9c1fb..62a1ba27 100644 --- a/archinstall/lib/output.py +++ b/archinstall/lib/output.py @@ -22,7 +22,7 @@ class FormattedOutput: ) -> Dict[str, Any]: """ the original values returned a dataclass as dict thru the call to some specific methods - this version allows thru the parameter class_formatter to call a dynamicly selected formatting method. + this version allows thru the parameter class_formatter to call a dynamically selected formatting method. Can transmit a filter list to the class_formatter, """ if class_formatter: diff --git a/archinstall/lib/translationhandler.py b/archinstall/lib/translationhandler.py index a2e44065..33230562 100644 --- a/archinstall/lib/translationhandler.py +++ b/archinstall/lib/translationhandler.py @@ -138,7 +138,7 @@ class TranslationHandler: def get_language_by_abbr(self, abbr: str) -> Language: """ - Get a language object by its abbrevation, e.g. en + Get a language object by its abbreviation, e.g. en """ try: return next(filter(lambda x: x.abbr == abbr, self._translated_languages)) diff --git a/archinstall/scripts/guided.py b/archinstall/scripts/guided.py index 51549fa8..d7cf16cd 100644 --- a/archinstall/scripts/guided.py +++ b/archinstall/scripts/guided.py @@ -185,7 +185,7 @@ def perform_installation(mountpoint: Path): installation.set_timezone(timezone) if archinstall.arguments.get('ntp', False): - installation.activate_time_syncronization() + installation.activate_time_synchronization() if archinstall.accessibility_tools_in_use(): installation.enable_espeakup() @@ -193,7 +193,7 @@ def perform_installation(mountpoint: Path): if (root_pw := archinstall.arguments.get('!root-password', None)) and len(root_pw): installation.user_set_pw('root', root_pw) - # This step must be after profile installs to allow profiles_bck to install language pre-requisits. + # This step must be after profile installs to allow profiles_bck to install language pre-requisites. # After which, this step will set the language both for console and x11 if x11 was installed for instance. installation.set_keyboard_language(locale_config.kb_layout) diff --git a/archinstall/scripts/swiss.py b/archinstall/scripts/swiss.py index 80fa0a48..c04ccca4 100644 --- a/archinstall/scripts/swiss.py +++ b/archinstall/scripts/swiss.py @@ -54,7 +54,7 @@ class SetupMenu(GlobalMenu): super().setup_selection_menu_options() self._menu_options['mode'] = menu.Selector( - 'Excution mode', + 'Execution mode', lambda x : select_mode(), display_func=lambda x: x.value if x else '', default=ExecutionMode.Full) @@ -249,7 +249,7 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode): installation.set_timezone(timezone) if archinstall.arguments.get('ntp', False): - installation.activate_time_syncronization() + installation.activate_time_synchronization() if archinstall.accessibility_tools_in_use(): installation.enable_espeakup() @@ -257,7 +257,7 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode): if (root_pw := archinstall.arguments.get('!root-password', None)) and len(root_pw): installation.user_set_pw('root', root_pw) - # This step must be after profile installs to allow profiles_bck to install language pre-requisits. + # This step must be after profile installs to allow profiles_bck to install language pre-requisites. # After which, this step will set the language both for console and x11 if x11 was installed for instance. installation.set_keyboard_language(locale_config.kb_layout) diff --git a/examples/interactive_installation.py b/examples/interactive_installation.py index 9eac029c..f8cc75fc 100644 --- a/examples/interactive_installation.py +++ b/examples/interactive_installation.py @@ -163,7 +163,7 @@ def perform_installation(mountpoint: Path): installation.set_timezone(timezone) if archinstall.arguments.get('ntp', False): - installation.activate_time_syncronization() + installation.activate_time_synchronization() if archinstall.accessibility_tools_in_use(): installation.enable_espeakup() @@ -171,7 +171,7 @@ def perform_installation(mountpoint: Path): if (root_pw := archinstall.arguments.get('!root-password', None)) and len(root_pw): installation.user_set_pw('root', root_pw) - # This step must be after profile installs to allow profiles_bck to install language pre-requisits. + # This step must be after profile installs to allow profiles_bck to install language pre-requisites. # After which, this step will set the language both for console and x11 if x11 was installed for instance. installation.set_keyboard_language(locale_config.kb_layout) -- cgit v1.2.3-54-g00ecf From d6e3a4651f2ff944a00e8acfb316db8be2fbcf3e Mon Sep 17 00:00:00 2001 From: Sxmourai <49468969+Sxmourai@users.noreply.github.com> Date: Fri, 22 Sep 2023 11:46:59 +0200 Subject: Renamed hyperland to hyprland, fixed seatd via post_installation and added waybar-hyprland (#1824) * Renamed hyperland to hyprland, fixed seatd via post_installation and installed waybar * Removed the launching of seatd on the installation process * Starting to add nvidia support, and automatic configuring of hyprland * Starting to add auto configuration of hyprland... But this will need maintenance * Added hyprpaper auto config Gonna make waybar auto config next * Waybar auto config is starting... I can't test rn I'm on vacation and my connection is quite bad (68 days for arch iso) * Added wlogout support (and swaylock) * Fixed file managers printing * Starting to add a shell config... Definitely don't push this * Reverted custom-shell config (create a separate PR) * Removed systemd-logind, as that was just for testing the selector * Added polkit as an option for the seat. As it's a dependency of the hyprland package * Flake8 fix * The name change wasn't propegated to the menu * Added newline at the end of general_conf.py to not alter it * Removed newline at the end of general_conf.py to not alter it * Renamed the Hyprland class --------- Co-authored-by: Anton Hvornum Co-authored-by: Anton Hvornum --- archinstall/default_profiles/desktops/hyperland.py | 27 ---------- archinstall/default_profiles/desktops/hyprland.py | 62 ++++++++++++++++++++++ archinstall/lib/interactions/general_conf.py | 2 +- 3 files changed, 63 insertions(+), 28 deletions(-) delete mode 100644 archinstall/default_profiles/desktops/hyperland.py create mode 100644 archinstall/default_profiles/desktops/hyprland.py (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/default_profiles/desktops/hyperland.py b/archinstall/default_profiles/desktops/hyperland.py deleted file mode 100644 index 58ee8cca..00000000 --- a/archinstall/default_profiles/desktops/hyperland.py +++ /dev/null @@ -1,27 +0,0 @@ -from typing import List, Optional, Any, TYPE_CHECKING - -from archinstall.default_profiles.profile import ProfileType, GreeterType -from archinstall.default_profiles.xorg import XorgProfile - -if TYPE_CHECKING: - _: Any - - -class HyperlandProfile(XorgProfile): - def __init__(self): - super().__init__('Hyperland', ProfileType.DesktopEnv, description='') - - @property - def packages(self) -> List[str]: - return [ - "hyprland", - "dunst", - "xdg-desktop-portal-hyprland", - "kitty", - "qt5-wayland", - "qt6-wayland" - ] - - @property - def default_greeter_type(self) -> Optional[GreeterType]: - return GreeterType.Sddm diff --git a/archinstall/default_profiles/desktops/hyprland.py b/archinstall/default_profiles/desktops/hyprland.py new file mode 100644 index 00000000..f464c828 --- /dev/null +++ b/archinstall/default_profiles/desktops/hyprland.py @@ -0,0 +1,62 @@ +from enum import Enum +from typing import List, Optional, TYPE_CHECKING, Any + +from archinstall.default_profiles.profile import ProfileType, GreeterType +from archinstall.default_profiles.xorg import XorgProfile +from archinstall.lib.menu import Menu + +if TYPE_CHECKING: + from archinstall.lib.installer import Installer + _: Any + + +class SeatAccess(Enum): + seatd = 'seatd' + polkit = 'polkit' + + +class HyprlandProfile(XorgProfile): + def __init__(self): + super().__init__('Hyprland', ProfileType.DesktopEnv, description='') + + self.custom_settings = {'seat_access': None} + + @property + def packages(self) -> List[str]: + return [ + "hyprland", + "dunst", + "xdg-desktop-portal-hyprland", + "qt5-wayland", + "qt6-wayland" + ] + + @property + def default_greeter_type(self) -> Optional[GreeterType]: + return GreeterType.Sddm + + @property + def services(self) -> List[str]: + if pref := self.custom_settings.get('seat_access', None): + return [pref] + return [] + + def _ask_seat_access(self): + # need to activate seat service and add to seat group + title = str(_('Hyprland needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)')) + title += str(_('\n\nChoose an option to give Hyprland access to your hardware')) + + options = [e.value for e in SeatAccess] + default = None + + if seat := self.custom_settings.get('seat_access', None): + default = seat + + choice = Menu(title, options, skip=False, preset_values=default).run() + self.custom_settings['seat_access'] = choice.single_value + + def do_on_select(self): + self._ask_seat_access() + + def install(self, install_session: 'Installer'): + super().install(install_session) diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index 8dd6e94f..56598e25 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -218,4 +218,4 @@ def select_additional_repositories(preset: List[str]) -> List[str]: case MenuSelectionType.Reset: return [] case MenuSelectionType.Selection: return choice.single_value - return [] + return [] \ No newline at end of file -- cgit v1.2.3-54-g00ecf From dc69acd4b43931f9fd3a267d78834d1a38fbb10f Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Mon, 9 Oct 2023 06:40:59 -0400 Subject: Fix keyboard layout and timezone menus (#2153) --- archinstall/lib/interactions/general_conf.py | 4 ++-- archinstall/lib/locale/locale_menu.py | 2 +- archinstall/lib/locale/utils.py | 23 ++++++++++------------- 3 files changed, 13 insertions(+), 16 deletions(-) (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index 56598e25..a23426d0 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -44,7 +44,7 @@ def ask_for_a_timezone(preset: Optional[str] = None) -> Optional[str]: choice = Menu( _('Select a timezone'), - list(timezones), + timezones, preset_values=preset, default_option=default ).run() @@ -95,7 +95,7 @@ def select_language(preset: Optional[str] = None) -> Optional[str]: """ kb_lang = list_keyboard_languages() # sort alphabetically and then by length - sorted_kb_lang = sorted(sorted(list(kb_lang)), key=len) + sorted_kb_lang = sorted(kb_lang, key=lambda x: (len(x), x)) choice = Menu( _('Select keyboard layout'), diff --git a/archinstall/lib/locale/locale_menu.py b/archinstall/lib/locale/locale_menu.py index 729b3b6e..75cc1332 100644 --- a/archinstall/lib/locale/locale_menu.py +++ b/archinstall/lib/locale/locale_menu.py @@ -139,7 +139,7 @@ def select_kb_layout(preset: Optional[str] = None) -> Optional[str]: """ kb_lang = list_keyboard_languages() # sort alphabetically and then by length - sorted_kb_lang = sorted(sorted(list(kb_lang)), key=len) + sorted_kb_lang = sorted(kb_lang, key=lambda x: (len(x), x)) choice = Menu( _('Select keyboard layout'), diff --git a/archinstall/lib/locale/utils.py b/archinstall/lib/locale/utils.py index 330ca0ce..d7641d50 100644 --- a/archinstall/lib/locale/utils.py +++ b/archinstall/lib/locale/utils.py @@ -1,16 +1,15 @@ -from typing import Iterator, List +from typing import List from ..exceptions import ServiceException, SysCallError from ..general import SysCommand from ..output import error -def list_keyboard_languages() -> Iterator[str]: - for line in SysCommand( +def list_keyboard_languages() -> List[str]: + return SysCommand( "localectl --no-pager list-keymaps", environment_vars={'SYSTEMD_COLORS': '0'} - ).decode(): - yield line + ).decode().splitlines() def list_locales() -> List[str]: @@ -24,12 +23,11 @@ def list_locales() -> List[str]: return locales -def list_x11_keyboard_languages() -> Iterator[str]: - for line in SysCommand( +def list_x11_keyboard_languages() -> List[str]: + return SysCommand( "localectl --no-pager list-x11-keymap-layouts", environment_vars={'SYSTEMD_COLORS': '0'} - ).decode(): - yield line + ).decode().splitlines() def verify_keyboard_layout(layout :str) -> bool: @@ -62,9 +60,8 @@ def set_kb_layout(locale :str) -> bool: return False -def list_timezones() -> Iterator[str]: - for line in SysCommand( +def list_timezones() -> List[str]: + return SysCommand( "timedatectl --no-pager list-timezones", environment_vars={'SYSTEMD_COLORS': '0'} - ).decode(): - yield line + ).decode().splitlines() -- cgit v1.2.3-54-g00ecf From 5e59acf937c3bb9cfe6a3b7a0a264b9df00239ee Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 10 Oct 2023 04:00:22 -0400 Subject: Add handling of signal interrupt and EOF at input prompts (#2154) --- archinstall/lib/configuration.py | 2 +- archinstall/lib/interactions/disk_conf.py | 5 ++++- archinstall/lib/interactions/general_conf.py | 15 ++++++++------- archinstall/lib/interactions/manage_users_conf.py | 6 +++++- archinstall/lib/interactions/utils.py | 7 ++++++- archinstall/lib/menu/text_input.py | 11 ++++++++++- 6 files changed, 34 insertions(+), 12 deletions(-) (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/lib/configuration.py b/archinstall/lib/configuration.py index aeeddbb8..95e237d7 100644 --- a/archinstall/lib/configuration.py +++ b/archinstall/lib/configuration.py @@ -177,5 +177,5 @@ def save_config(config: Dict): case "all": config_output.save(dest_path) - except KeyboardInterrupt: + except (KeyboardInterrupt, EOFError): return diff --git a/archinstall/lib/interactions/disk_conf.py b/archinstall/lib/interactions/disk_conf.py index 84a3196c..c18119ec 100644 --- a/archinstall/lib/interactions/disk_conf.py +++ b/archinstall/lib/interactions/disk_conf.py @@ -134,7 +134,10 @@ def select_disk_config( output = "You will use whatever drive-setup is mounted at the specified directory\n" output += "WARNING: Archinstall won't check the suitability of this setup\n" - path = prompt_dir(str(_('Enter the root directory of the mounted devices: ')), output) + try: + path = prompt_dir(str(_('Enter the root directory of the mounted devices: ')), output) + except (KeyboardInterrupt, EOFError): + return preset mods = disk.device_handler.detect_pre_mounted_mods(path) return disk.DiskLayoutConfiguration( diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index a23426d0..b12a6fb8 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -28,14 +28,15 @@ def ask_ntp(preset: bool = True) -> bool: def ask_hostname(preset: str = '') -> str: - while True: - hostname = TextInput( - str(_('Desired hostname for the installation: ')), - preset - ).run().strip() + hostname = TextInput( + str(_('Desired hostname for the installation: ')), + preset + ).run().strip() + + if not hostname: + return preset - if hostname: - return hostname + return hostname def ask_for_a_timezone(preset: Optional[str] = None) -> Optional[str]: diff --git a/archinstall/lib/interactions/manage_users_conf.py b/archinstall/lib/interactions/manage_users_conf.py index 879578da..ca912283 100644 --- a/archinstall/lib/interactions/manage_users_conf.py +++ b/archinstall/lib/interactions/manage_users_conf.py @@ -75,7 +75,11 @@ class UserList(ListManager): prompt = '\n\n' + str(_('Enter username (leave blank to skip): ')) while True: - username = input(prompt).strip(' ') + try: + username = input(prompt).strip(' ') + except (KeyboardInterrupt, EOFError): + return None + if not username: return None if not self._check_for_correct_username(username): diff --git a/archinstall/lib/interactions/utils.py b/archinstall/lib/interactions/utils.py index f6b5b2d3..fdbb4625 100644 --- a/archinstall/lib/interactions/utils.py +++ b/archinstall/lib/interactions/utils.py @@ -17,7 +17,12 @@ def get_password(prompt: str = '') -> Optional[str]: if not prompt: prompt = _("Enter a password: ") - while password := getpass.getpass(prompt): + while True: + try: + password = getpass.getpass(prompt) + except (KeyboardInterrupt, EOFError): + break + if len(password.strip()) <= 0: break diff --git a/archinstall/lib/menu/text_input.py b/archinstall/lib/menu/text_input.py index 05ca0f22..971df5fd 100644 --- a/archinstall/lib/menu/text_input.py +++ b/archinstall/lib/menu/text_input.py @@ -1,4 +1,5 @@ import readline +import sys class TextInput: @@ -12,6 +13,14 @@ class TextInput: def run(self) -> str: readline.set_pre_input_hook(self._hook) - result = input(self._prompt) + try: + result = input(self._prompt) + except (KeyboardInterrupt, EOFError): + # To make sure any output that may follow + # will be on the line after the prompt + sys.stdout.write('\n') + sys.stdout.flush() + + result = '' readline.set_pre_input_hook() return result -- cgit v1.2.3-54-g00ecf From 6ee6d1eda05d3f69f6aaabac55a741e693449994 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Mon, 20 Nov 2023 06:55:45 -0500 Subject: Remove `select_language()` duplicate of `select_kb_layout()` (#2151) * Remove `select_language()` duplicate of `select_kb_layout()` * Added a deprecation warning on select_language() * Moved select_language() back into it's original location, just to keep the PR diff minimal * Removed import for now, to please flake8 --------- Co-authored-by: Anton Hvornum --- archinstall/lib/interactions/general_conf.py | 29 ++++++++-------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'archinstall/lib/interactions/general_conf.py') diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index b12a6fb8..a879552e 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -3,7 +3,7 @@ from __future__ import annotations import pathlib from typing import List, Any, Optional, TYPE_CHECKING -from ..locale import list_timezones, list_keyboard_languages +from ..locale import list_timezones from ..menu import MenuSelectionType, Menu, TextInput from ..models.audio_configuration import Audio, AudioConfiguration from ..output import warn @@ -87,29 +87,16 @@ def ask_for_audio_selection( def select_language(preset: Optional[str] = None) -> Optional[str]: - """ - Asks the user to select a language - Usually this is combined with :ref:`archinstall.list_keyboard_languages`. - - :return: The language/dictionary key of the selected language - :rtype: str - """ - kb_lang = list_keyboard_languages() - # sort alphabetically and then by length - sorted_kb_lang = sorted(kb_lang, key=lambda x: (len(x), x)) + from ..locale.locale_menu import select_kb_layout - choice = Menu( - _('Select keyboard layout'), - sorted_kb_lang, - preset_values=preset, - sort=False - ).run() + # We'll raise an exception in an upcoming version. + # from ..exceptions import Deprecated + # raise Deprecated("select_language() has been deprecated, use select_kb_layout() instead.") - match choice.type_: - case MenuSelectionType.Skip: return preset - case MenuSelectionType.Selection: return choice.single_value + # No need to translate this i feel, as it's a short lived message. + warn("select_language() is deprecated, use select_kb_layout() instead. select_language() will be removed in a future version") - return None + return select_kb_layout(preset) def select_archinstall_language(languages: List[Language], preset: Language) -> Language: -- cgit v1.2.3-54-g00ecf