index : archinstall32 | |
Archlinux32 installer | gitolite user |
summaryrefslogtreecommitdiff |
author | Andreas Baumann <mail@andreasbaumann.cc> | 2024-05-10 15:56:28 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2024-05-10 15:56:28 +0200 |
commit | 683da22298abbd90f51d4dd38a7ec4b0dfb04555 (patch) | |
tree | ec2ac04967f9277df038edc362201937b331abe5 /archinstall/lib/locale | |
parent | af7ab9833c9f9944874f0162ae0975175ddc628d (diff) | |
parent | 3381cd55673e5105697d354cf4a1be9a7bcef062 (diff) |
-rw-r--r-- | archinstall/lib/locale/__init__.py | 10 | ||||
-rw-r--r-- | archinstall/lib/locale/locale_menu.py | 158 | ||||
-rw-r--r-- | archinstall/lib/locale/utils.py | 67 |
diff --git a/archinstall/lib/locale/__init__.py b/archinstall/lib/locale/__init__.py new file mode 100644 index 00000000..90f1aecc --- /dev/null +++ b/archinstall/lib/locale/__init__.py @@ -0,0 +1,10 @@ +from .locale_menu import LocaleConfiguration +from .utils import ( + list_keyboard_languages, + list_locales, + list_x11_keyboard_languages, + verify_keyboard_layout, + verify_x11_keyboard_layout, + list_timezones, + set_kb_layout +) diff --git a/archinstall/lib/locale/locale_menu.py b/archinstall/lib/locale/locale_menu.py new file mode 100644 index 00000000..db119f20 --- /dev/null +++ b/archinstall/lib/locale/locale_menu.py @@ -0,0 +1,158 @@ +from dataclasses import dataclass +from typing import Dict, Any, TYPE_CHECKING, Optional + +from .utils import list_keyboard_languages, list_locales, set_kb_layout +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], + locale_conf: LocaleConfiguration + ): + self._preset = locale_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=self._preset.kb_layout, + enabled=True) + self._menu_options['sys-language'] = \ + Selector( + _('Locale language'), + lambda preset: select_locale_lang(preset), + default=self._preset.sys_lang, + enabled=True) + self._menu_options['sys-encoding'] = \ + Selector( + _('Locale encoding'), + lambda preset: select_locale_enc(preset), + default=self._preset.sys_enc, + enabled=True) + + def run(self, allow_reset: bool = True) -> LocaleConfiguration: + super().run(allow_reset=allow_reset) + + if not self._data_store: + return LocaleConfiguration.default() + + 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(kb_lang, key=lambda x: (len(x), x)) + + 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/locale/utils.py b/archinstall/lib/locale/utils.py new file mode 100644 index 00000000..d7641d50 --- /dev/null +++ b/archinstall/lib/locale/utils.py @@ -0,0 +1,67 @@ +from typing import List + +from ..exceptions import ServiceException, SysCallError +from ..general import SysCommand +from ..output import error + + +def list_keyboard_languages() -> List[str]: + return SysCommand( + "localectl --no-pager list-keymaps", + environment_vars={'SYSTEMD_COLORS': '0'} + ).decode().splitlines() + + +def list_locales() -> List[str]: + locales = [] + + with open('/usr/share/i18n/SUPPORTED') as file: + for line in file: + if line != 'C.UTF-8 UTF-8\n': + locales.append(line.rstrip()) + + return locales + + +def list_x11_keyboard_languages() -> List[str]: + return SysCommand( + "localectl --no-pager list-x11-keymap-layouts", + environment_vars={'SYSTEMD_COLORS': '0'} + ).decode().splitlines() + + +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() -> List[str]: + return SysCommand( + "timedatectl --no-pager list-timezones", + environment_vars={'SYSTEMD_COLORS': '0'} + ).decode().splitlines() |