diff --git a/archinstall/applications/fonts.py b/archinstall/applications/fonts.py new file mode 100644 index 0000000000..3fa54c67d4 --- /dev/null +++ b/archinstall/applications/fonts.py @@ -0,0 +1,14 @@ +from typing import TYPE_CHECKING + +from archinstall.lib.models.application import FontsConfiguration +from archinstall.lib.output import debug + +if TYPE_CHECKING: + from archinstall.lib.installer import Installer + + +class FontsApp: + def install(self, install_session: Installer, fonts_config: FontsConfiguration) -> None: + packages = [f.value for f in fonts_config.fonts] + debug(f'Installing fonts: {packages}') + install_session.add_additional_packages(packages) diff --git a/archinstall/lib/applications/application_handler.py b/archinstall/lib/applications/application_handler.py index fb0ceced30..7fcf5dbacb 100644 --- a/archinstall/lib/applications/application_handler.py +++ b/archinstall/lib/applications/application_handler.py @@ -3,6 +3,7 @@ from archinstall.applications.audio import AudioApp from archinstall.applications.bluetooth import BluetoothApp from archinstall.applications.firewall import FirewallApp +from archinstall.applications.fonts import FontsApp from archinstall.applications.power_management import PowerManagementApp from archinstall.applications.print_service import PrintServiceApp from archinstall.lib.models import Audio @@ -42,3 +43,9 @@ def install_applications(self, install_session: Installer, app_config: Applicati install_session, app_config.firewall_config, ) + + if app_config.fonts_config: + FontsApp().install( + install_session, + app_config.fonts_config, + ) diff --git a/archinstall/lib/applications/application_menu.py b/archinstall/lib/applications/application_menu.py index 5ef50441f3..fdf35a56d8 100644 --- a/archinstall/lib/applications/application_menu.py +++ b/archinstall/lib/applications/application_menu.py @@ -10,6 +10,8 @@ BluetoothConfiguration, Firewall, FirewallConfiguration, + FontPackage, + FontsConfiguration, PowerManagement, PowerManagementConfiguration, PrintServiceConfiguration, @@ -77,6 +79,13 @@ def _define_menu_options(self) -> list[MenuItem]: preview_action=self._prev_firewall, key='firewall_config', ), + MenuItem( + text=tr('Additional fonts'), + action=select_fonts, + value=self._app_config.fonts_config, + preview_action=self._prev_fonts, + key='fonts_config', + ), ] def _prev_power_management(self, item: MenuItem) -> str | None: @@ -115,6 +124,13 @@ def _prev_firewall(self, item: MenuItem) -> str | None: return f'{tr("Firewall")}: {config.firewall.value}' return None + def _prev_fonts(self, item: MenuItem) -> str | None: + if item.value is not None: + config: FontsConfiguration = item.value + packages = ', '.join(f.value for f in config.fonts) + return f'{tr("Additional fonts")}: {packages}' + return None + async def select_power_management(preset: PowerManagementConfiguration | None = None) -> PowerManagementConfiguration | None: group = MenuItemGroup.from_enum(PowerManagement) @@ -217,3 +233,36 @@ async def select_firewall(preset: FirewallConfiguration | None = None) -> Firewa return FirewallConfiguration(firewall=result.get_value()) case ResultType.Reset: return None + + +async def select_fonts(preset: FontsConfiguration | None = None) -> FontsConfiguration | None: + descriptions = { + FontPackage.NOTO: tr('Unicode font coverage for most languages'), + FontPackage.EMOJI: tr('color emoji for browsers and apps'), + FontPackage.CJK: tr('Chinese, Japanese, Korean characters'), + } + items = [MenuItem(f'{f.value} ({descriptions[f]})', value=f) for f in FontPackage] + group = MenuItemGroup(items) + + if preset: + for f in preset.fonts: + group.set_selected_by_value(f) + + result = await Selection[FontPackage]( + group, + header=tr('Select font packages to install'), + allow_skip=True, + allow_reset=True, + multi=True, + ).show() + + match result.type_: + case ResultType.Skip: + return preset + case ResultType.Selection: + selected = result.get_values() + if selected: + return FontsConfiguration(fonts=selected) + return None + case ResultType.Reset: + return None diff --git a/archinstall/lib/models/application.py b/archinstall/lib/models/application.py index d32042ff2f..4365eb45c3 100644 --- a/archinstall/lib/models/application.py +++ b/archinstall/lib/models/application.py @@ -39,6 +39,16 @@ class FirewallConfigSerialization(TypedDict): firewall: str +class FontPackage(StrEnum): + NOTO = 'noto-fonts' + EMOJI = 'noto-fonts-emoji' + CJK = 'noto-fonts-cjk' + + +class FontsConfigSerialization(TypedDict): + fonts: list[str] + + class ZramAlgorithm(StrEnum): ZSTD = 'zstd' LZO_RLE = 'lzo-rle' @@ -53,6 +63,7 @@ class ApplicationSerialization(TypedDict): power_management_config: NotRequired[PowerManagementConfigSerialization] print_service_config: NotRequired[PrintServiceConfigSerialization] firewall_config: NotRequired[FirewallConfigSerialization] + fonts_config: NotRequired[FontsConfigSerialization] @dataclass @@ -127,6 +138,18 @@ def parse_arg(cls, arg: dict[str, Any]) -> Self: ) +@dataclass +class FontsConfiguration: + fonts: list[FontPackage] + + def json(self) -> FontsConfigSerialization: + return {'fonts': [f.value for f in self.fonts]} + + @classmethod + def parse_arg(cls, arg: FontsConfigSerialization) -> Self: + return cls(fonts=[FontPackage(f) for f in arg['fonts']]) + + @dataclass(frozen=True) class ZramConfiguration: enabled: bool @@ -149,6 +172,7 @@ class ApplicationConfiguration: power_management_config: PowerManagementConfiguration | None = None print_service_config: PrintServiceConfiguration | None = None firewall_config: FirewallConfiguration | None = None + fonts_config: FontsConfiguration | None = None @classmethod def parse_arg( @@ -177,6 +201,9 @@ def parse_arg( if args and (firewall_config := args.get('firewall_config')) is not None: app_config.firewall_config = FirewallConfiguration.parse_arg(firewall_config) + if args and (fonts_config := args.get('fonts_config')) is not None: + app_config.fonts_config = FontsConfiguration.parse_arg(fonts_config) + return app_config def json(self) -> ApplicationSerialization: @@ -197,4 +224,7 @@ def json(self) -> ApplicationSerialization: if self.firewall_config: config['firewall_config'] = self.firewall_config.json() + if self.fonts_config: + config['fonts_config'] = self.fonts_config.json() + return config diff --git a/archinstall/locales/base.pot b/archinstall/locales/base.pot index df0915c769..77bed7144e 100644 --- a/archinstall/locales/base.pot +++ b/archinstall/locales/base.pot @@ -1940,6 +1940,21 @@ msgstr "" msgid "Firewall" msgstr "" +msgid "Additional fonts" +msgstr "" + +msgid "Select font packages to install" +msgstr "" + +msgid "Unicode font coverage for most languages" +msgstr "" + +msgid "color emoji for browsers and apps" +msgstr "" + +msgid "Chinese, Japanese, Korean characters" +msgstr "" + msgid "Select audio configuration" msgstr "" diff --git a/archinstall/locales/uk/LC_MESSAGES/base.po b/archinstall/locales/uk/LC_MESSAGES/base.po index b88fd2901e..0897ad8da0 100644 --- a/archinstall/locales/uk/LC_MESSAGES/base.po +++ b/archinstall/locales/uk/LC_MESSAGES/base.po @@ -1881,6 +1881,21 @@ msgstr "Використовувати NetworkManager (з iwd)" msgid "Firewall" msgstr "Брандмауер" +msgid "Additional fonts" +msgstr "Додаткові шрифти" + +msgid "Select font packages to install" +msgstr "Оберіть пакети шрифтів для встановлення" + +msgid "Unicode font coverage for most languages" +msgstr "покриття шрифтами Unicode для більшості мов" + +msgid "color emoji for browsers and apps" +msgstr "кольорові емодзі для браузерів та програм" + +msgid "Chinese, Japanese, Korean characters" +msgstr "китайські, японські, корейські символи" + msgid "Select audio configuration" msgstr "Оберіть конфігурацію аудіо"