diff --git a/archinstall/__init__.py b/archinstall/__init__.py index d05a0d6fe9..9dd01f8299 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -5,7 +5,6 @@ import sys import time import traceback -from typing import TYPE_CHECKING from archinstall.lib.args import arch_config_handler from archinstall.lib.disk.utils import disk_layouts @@ -14,14 +13,9 @@ from .lib.output import FormattedOutput, debug, error, info, log, warn from .lib.pacman import Pacman from .lib.plugins import load_plugin, plugins -from .lib.translationhandler import DeferredTranslation, Language, translation_handler +from .lib.translationhandler import Language, tr, translation_handler from .tui.curses_menu import Tui -if TYPE_CHECKING: - from collections.abc import Callable - - _: Callable[[str], DeferredTranslation] - # @archinstall.plugin decorator hook to programmatically add # plugins in runtime. Useful in profiles_bck and other things. @@ -76,7 +70,7 @@ def main() -> int: return 0 if os.getuid() != 0: - print(_("Archinstall requires root privileges to run. See --help for more.")) + print(tr("Archinstall requires root privileges to run. See --help for more.")) return 1 _log_sys_info() @@ -125,7 +119,6 @@ def run_as_a_module() -> None: __all__ = [ - "DeferredTranslation", "FormattedOutput", "Language", "Pacman", diff --git a/archinstall/default_profiles/desktops/hyprland.py b/archinstall/default_profiles/desktops/hyprland.py index f19c04ff86..c6d6c24de7 100644 --- a/archinstall/default_profiles/desktops/hyprland.py +++ b/archinstall/default_profiles/desktops/hyprland.py @@ -1,20 +1,14 @@ -from typing import TYPE_CHECKING, override +from typing import override from archinstall.default_profiles.desktops import SeatAccess from archinstall.default_profiles.profile import GreeterType, ProfileType from archinstall.default_profiles.xorg import XorgProfile +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType from archinstall.tui.types import Alignment, FrameProperties -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class HyprlandProfile(XorgProfile): def __init__(self) -> None: @@ -54,8 +48,8 @@ def services(self) -> list[str]: def _ask_seat_access(self) -> None: # need to activate seat service and add to seat group - header = str(_("Hyprland needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)")) - header += "\n" + str(_("Choose an option to give Hyprland access to your hardware")) + "\n" + header = tr("Hyprland needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)") + header += "\n" + tr("Choose an option to give Hyprland access to your hardware") + "\n" items = [MenuItem(s.value, value=s) for s in SeatAccess] group = MenuItemGroup(items, sort_items=True) @@ -67,7 +61,7 @@ def _ask_seat_access(self) -> None: group, header=header, allow_skip=False, - frame=FrameProperties.min(str(_("Seat access"))), + frame=FrameProperties.min(tr("Seat access")), alignment=Alignment.CENTER, ).run() diff --git a/archinstall/default_profiles/desktops/labwc.py b/archinstall/default_profiles/desktops/labwc.py index 71816a722e..8856a2432f 100644 --- a/archinstall/default_profiles/desktops/labwc.py +++ b/archinstall/default_profiles/desktops/labwc.py @@ -1,20 +1,14 @@ -from typing import TYPE_CHECKING, override +from typing import override from archinstall.default_profiles.desktops import SeatAccess from archinstall.default_profiles.profile import GreeterType, ProfileType from archinstall.default_profiles.xorg import XorgProfile +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType from archinstall.tui.types import Alignment, FrameProperties -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class LabwcProfile(XorgProfile): def __init__(self) -> None: @@ -51,8 +45,8 @@ def services(self) -> list[str]: def _ask_seat_access(self) -> None: # need to activate seat service and add to seat group - header = str(_("labwc needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)")) - header += "\n" + str(_("Choose an option to give labwc access to your hardware")) + "\n" + header = tr("labwc needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)") + header += "\n" + tr("Choose an option to give labwc access to your hardware") + "\n" items = [MenuItem(s.value, value=s) for s in SeatAccess] group = MenuItemGroup(items, sort_items=True) @@ -64,7 +58,7 @@ def _ask_seat_access(self) -> None: group, header=header, allow_skip=False, - frame=FrameProperties.min(str(_("Seat access"))), + frame=FrameProperties.min(tr("Seat access")), alignment=Alignment.CENTER, ).run() diff --git a/archinstall/default_profiles/desktops/niri.py b/archinstall/default_profiles/desktops/niri.py index 2d0a4c12c2..f953c971c2 100644 --- a/archinstall/default_profiles/desktops/niri.py +++ b/archinstall/default_profiles/desktops/niri.py @@ -1,20 +1,14 @@ -from typing import TYPE_CHECKING, override +from typing import override from archinstall.default_profiles.desktops import SeatAccess from archinstall.default_profiles.profile import GreeterType, ProfileType from archinstall.default_profiles.xorg import XorgProfile +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType from archinstall.tui.types import Alignment, FrameProperties -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class NiriProfile(XorgProfile): def __init__(self) -> None: @@ -59,8 +53,8 @@ def services(self) -> list[str]: def _ask_seat_access(self) -> None: # need to activate seat service and add to seat group - header = str(_("niri needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)")) - header += "\n" + str(_("Choose an option to give niri access to your hardware")) + "\n" + header = tr("niri needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)") + header += "\n" + tr("Choose an option to give niri access to your hardware") + "\n" items = [MenuItem(s.value, value=s) for s in SeatAccess] group = MenuItemGroup(items, sort_items=True) @@ -72,7 +66,7 @@ def _ask_seat_access(self) -> None: group, header=header, allow_skip=False, - frame=FrameProperties.min(str(_("Seat access"))), + frame=FrameProperties.min(tr("Seat access")), alignment=Alignment.CENTER, ).run() diff --git a/archinstall/default_profiles/desktops/sway.py b/archinstall/default_profiles/desktops/sway.py index cd8c9c5252..53bc685042 100644 --- a/archinstall/default_profiles/desktops/sway.py +++ b/archinstall/default_profiles/desktops/sway.py @@ -1,20 +1,14 @@ -from typing import TYPE_CHECKING, override +from typing import override from archinstall.default_profiles.desktops import SeatAccess from archinstall.default_profiles.profile import GreeterType, ProfileType from archinstall.default_profiles.xorg import XorgProfile +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType from archinstall.tui.types import Alignment, FrameProperties -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class SwayProfile(XorgProfile): def __init__(self) -> None: @@ -61,8 +55,8 @@ def services(self) -> list[str]: def _ask_seat_access(self) -> None: # need to activate seat service and add to seat group - header = str(_("Sway needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)")) - header += "\n" + str(_("Choose an option to give Sway access to your hardware")) + "\n" + header = tr("Sway needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)") + header += "\n" + tr("Choose an option to give Sway access to your hardware") + "\n" items = [MenuItem(s.value, value=s) for s in SeatAccess] group = MenuItemGroup(items, sort_items=True) @@ -74,7 +68,7 @@ def _ask_seat_access(self) -> None: group, header=header, allow_skip=False, - frame=FrameProperties.min(str(_("Seat access"))), + frame=FrameProperties.min(tr("Seat access")), alignment=Alignment.CENTER, ).run() diff --git a/archinstall/default_profiles/profile.py b/archinstall/default_profiles/profile.py index 2200ca76e6..283f1480c7 100644 --- a/archinstall/default_profiles/profile.py +++ b/archinstall/default_profiles/profile.py @@ -4,15 +4,11 @@ from enum import Enum, auto from typing import TYPE_CHECKING -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation +from archinstall.lib.translationhandler import tr +if TYPE_CHECKING: from ..lib.installer import Installer - _: Callable[[str], DeferredTranslation] - class ProfileType(Enum): # top level default_profiles @@ -200,7 +196,7 @@ def packages_text(self, include_sub_packages: bool = False) -> str: if sub_profile.packages: packages.update(sub_profile.packages) - text = str(_("Installed packages")) + ":\n" + text = tr("Installed packages") + ":\n" for pkg in sorted(packages): text += f"\t- {pkg}\n" diff --git a/archinstall/default_profiles/xorg.py b/archinstall/default_profiles/xorg.py index c72936fd97..499a88402d 100644 --- a/archinstall/default_profiles/xorg.py +++ b/archinstall/default_profiles/xorg.py @@ -1,13 +1,7 @@ -from typing import TYPE_CHECKING, override +from typing import override from archinstall.default_profiles.profile import Profile, ProfileType - -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] +from archinstall.lib.translationhandler import tr class XorgProfile(Profile): @@ -26,7 +20,7 @@ def __init__( @override def preview_text(self) -> str: - text = str(_("Environment type: {}")).format(self.profile_type.value) + text = tr("Environment type: {}").format(self.profile_type.value) if packages := self.packages_text(): text += f"\n{packages}" diff --git a/archinstall/lib/args.py b/archinstall/lib/args.py index 027b0518b6..518b5a926f 100644 --- a/archinstall/lib/args.py +++ b/archinstall/lib/args.py @@ -7,7 +7,7 @@ from dataclasses import dataclass, field from importlib.metadata import version from pathlib import Path -from typing import TYPE_CHECKING, Any +from typing import Any from urllib.request import Request, urlopen from pydantic.dataclasses import dataclass as p_dataclass @@ -25,17 +25,10 @@ from archinstall.lib.output import debug, error, warn from archinstall.lib.plugins import load_plugin from archinstall.lib.storage import storage -from archinstall.lib.translationhandler import Language, translation_handler +from archinstall.lib.translationhandler import Language, tr, translation_handler from archinstall.lib.utils.util import get_password from archinstall.tui.curses_menu import Tui -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - @p_dataclass class Arguments: @@ -430,7 +423,7 @@ def _process_creds_data(self, creds_data: str) -> dict[str, Any] | None: return json.loads(creds_data) except ValueError as err: if "Invalid password" in str(err): - error(str(_("Incorrect credentials file decryption password"))) + error(tr("Incorrect credentials file decryption password")) exit(1) else: debug(f"Error decrypting credentials file: {err}") @@ -440,10 +433,10 @@ def _process_creds_data(self, creds_data: str) -> dict[str, Any] | None: with Tui(): while True: - header = str(_("Incorrect password")) if incorrect_password else None + header = tr("Incorrect password") if incorrect_password else None decryption_pwd = get_password( - text=str(_("Credentials file decryption password")), + text=tr("Credentials file decryption password"), header=header, allow_skip=False, skip_confirmation=True, diff --git a/archinstall/lib/configuration.py b/archinstall/lib/configuration.py index 6a1d88246a..d3da77fbde 100644 --- a/archinstall/lib/configuration.py +++ b/archinstall/lib/configuration.py @@ -2,8 +2,8 @@ import readline import stat from pathlib import Path -from typing import TYPE_CHECKING +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu, Tui from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -16,13 +16,6 @@ from .storage import storage from .utils.util import get_password, prompt_dir -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class ConfigurationOutput: def __init__(self, config: ArchConfig): @@ -61,8 +54,8 @@ def write_debug(self) -> None: debug(self.user_config_to_json()) def confirm_config(self) -> bool: - header = f"{_('The specified configuration will be applied')}. " - header += str(_("Would you like to continue?")) + "\n" + header = f"{tr('The specified configuration will be applied')}. " + header += tr("Would you like to continue?") + "\n" with Tui(): group = MenuItemGroup.yes_no() @@ -78,7 +71,7 @@ def confirm_config(self) -> bool: allow_skip=False, preview_size="auto", preview_style=PreviewStyle.BOTTOM, - preview_frame=FrameProperties.max(str(_("Configuration"))), + preview_frame=FrameProperties.max(tr("Configuration")), ).run() if result.item() != MenuItem.yes(): @@ -139,7 +132,7 @@ def preview(item: MenuItem) -> str | None: case "user_creds": if maybe_serial := config_output.user_credentials_to_json(): return f"{config_output.user_credentials_file}\n{maybe_serial}" - return str(_("No configuration")) + return tr("No configuration") case "all": output = [str(config_output.user_configuration_file)] config_output.user_credentials_to_json() @@ -151,17 +144,17 @@ def preview(item: MenuItem) -> str | None: items = [ MenuItem( - str(_("Save user configuration (including disk layout)")), + tr("Save user configuration (including disk layout)"), value="user_config", preview_action=preview, ), MenuItem( - str(_("Save user credentials")), + tr("Save user credentials"), value="user_creds", preview_action=preview, ), MenuItem( - str(_("Save all")), + tr("Save all"), value="all", preview_action=preview, ), @@ -171,7 +164,7 @@ def preview(item: MenuItem) -> str | None: result = SelectMenu[str]( group, allow_skip=True, - preview_frame=FrameProperties.max(str(_("Configuration"))), + preview_frame=FrameProperties.max(tr("Configuration")), preview_size="auto", preview_style=PreviewStyle.RIGHT, ).run() @@ -188,15 +181,15 @@ def preview(item: MenuItem) -> str | None: readline.parse_and_bind("tab: complete") dest_path = prompt_dir( - str(_("Directory")), - str(_("Enter a directory for the configuration(s) to be saved (tab completion enabled)")) + "\n", + tr("Directory"), + tr("Enter a directory for the configuration(s) to be saved (tab completion enabled)") + "\n", allow_skip=True, ) if not dest_path: return - header = str(_("Do you want to save the configuration file(s) to {}?")).format(dest_path) + header = tr("Do you want to save the configuration file(s) to {}?").format(dest_path) group = MenuItemGroup.yes_no() group.focus_item = MenuItem.yes() @@ -217,7 +210,7 @@ def preview(item: MenuItem) -> str | None: debug(f"Saving configuration files to {dest_path.absolute()}") - header = str(_("Do you want to encrypt the user_credentials.json file?")) + header = tr("Do you want to encrypt the user_credentials.json file?") group = MenuItemGroup.yes_no() group.focus_item = MenuItem.no() @@ -236,7 +229,7 @@ def preview(item: MenuItem) -> str | None: case ResultType.Selection: if result.item() == MenuItem.yes(): password = get_password( - text=str(_("Credentials file encryption password")), + text=tr("Credentials file encryption password"), allow_skip=True, ) diff --git a/archinstall/lib/disk/disk_menu.py b/archinstall/lib/disk/disk_menu.py index bfbc75623b..a1afa565d8 100644 --- a/archinstall/lib/disk/disk_menu.py +++ b/archinstall/lib/disk/disk_menu.py @@ -1,20 +1,14 @@ from dataclasses import dataclass -from typing import TYPE_CHECKING, override +from typing import override from archinstall.lib.models.device_model import DiskLayoutConfiguration, DiskLayoutType, LvmConfiguration +from archinstall.lib.translationhandler import tr from archinstall.tui.menu_item import MenuItem, MenuItemGroup from ..interactions.disk_conf import select_disk_config, select_lvm_config from ..menu.abstract_menu import AbstractSubMenu from ..output import FormattedOutput -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - @dataclass class DiskMenuConfig: @@ -44,7 +38,7 @@ def __init__(self, disk_layout_config: DiskLayoutConfiguration | None): def _define_menu_options(self) -> list[MenuItem]: return [ MenuItem( - text=str(_("Partitioning")), + text=tr("Partitioning"), action=self._select_disk_layout_config, value=self._disk_menu_config.disk_config, preview_action=self._prev_disk_layouts, @@ -104,14 +98,14 @@ def _prev_disk_layouts(self, item: MenuItem) -> str | None: disk_layout_conf = item.get_value() if disk_layout_conf.config_type == DiskLayoutType.Pre_mount: - msg = str(_("Configuration type: {}")).format(disk_layout_conf.config_type.display_msg()) + "\n" - msg += str(_("Mountpoint")) + ": " + str(disk_layout_conf.mountpoint) + msg = tr("Configuration type: {}").format(disk_layout_conf.config_type.display_msg()) + "\n" + msg += tr("Mountpoint") + ": " + str(disk_layout_conf.mountpoint) return msg device_mods = [d for d in disk_layout_conf.device_modifications if d.partitions] if device_mods: - output_partition = "{}: {}\n".format(str(_("Configuration")), disk_layout_conf.config_type.display_msg()) + output_partition = "{}: {}\n".format(tr("Configuration"), disk_layout_conf.config_type.display_msg()) output_btrfs = "" for mod in device_mods: @@ -119,7 +113,7 @@ def _prev_disk_layouts(self, item: MenuItem) -> str | None: partition_table = FormattedOutput.as_table(mod.partitions) output_partition += f"{mod.device_path}: {mod.device.device_info.model}\n" - output_partition += "{}: {}\n".format(str(_("Wipe")), mod.wipe) + output_partition += "{}: {}\n".format(tr("Wipe"), mod.wipe) output_partition += partition_table + "\n" # create btrfs table @@ -138,16 +132,16 @@ def _prev_lvm_config(self, item: MenuItem) -> str | None: lvm_config: LvmConfiguration = item.value - output = "{}: {}\n".format(str(_("Configuration")), lvm_config.config_type.display_msg()) + output = "{}: {}\n".format(tr("Configuration"), lvm_config.config_type.display_msg()) for vol_gp in lvm_config.vol_groups: pv_table = FormattedOutput.as_table(vol_gp.pvs) - output += "{}:\n{}".format(str(_("Physical volumes")), pv_table) + output += "{}:\n{}".format(tr("Physical volumes"), pv_table) output += f"\nVolume Group: {vol_gp.name}" lvm_volumes = FormattedOutput.as_table(vol_gp.volumes) - output += "\n\n{}:\n{}".format(str(_("Volumes")), lvm_volumes) + output += "\n\n{}:\n{}".format(tr("Volumes"), lvm_volumes) return output diff --git a/archinstall/lib/disk/encryption_menu.py b/archinstall/lib/disk/encryption_menu.py index eaa43c8cc2..590044b683 100644 --- a/archinstall/lib/disk/encryption_menu.py +++ b/archinstall/lib/disk/encryption_menu.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import TYPE_CHECKING, override +from typing import override from archinstall.lib.menu.menu_helper import MenuHelper from archinstall.lib.models.device_model import ( @@ -11,6 +11,7 @@ LvmVolume, PartitionModification, ) +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -23,13 +24,6 @@ from ..utils.util import get_password from .fido import Fido2 -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]): def __init__( @@ -56,14 +50,14 @@ def __init__( def _define_menu_options(self) -> list[MenuItem]: return [ MenuItem( - text=str(_("Encryption type")), + text=tr("Encryption type"), action=lambda x: select_encryption_type(self._disk_config, x), value=self._enc_config.encryption_type, preview_action=self._preview, key="encryption_type", ), MenuItem( - text=str(_("Encryption password")), + text=tr("Encryption password"), action=lambda x: select_encrypted_password(), value=self._enc_config.encryption_password, dependencies=[self._check_dep_enc_type], @@ -71,7 +65,7 @@ def _define_menu_options(self) -> list[MenuItem]: key="encryption_password", ), MenuItem( - text=str(_("Partitions")), + text=tr("Partitions"), action=lambda x: select_partitions_to_encrypt(self._disk_config.device_modifications, x), value=self._enc_config.partitions, dependencies=[self._check_dep_partitions], @@ -79,7 +73,7 @@ def _define_menu_options(self) -> list[MenuItem]: key="partitions", ), MenuItem( - text=str(_("LVM volumes")), + text=tr("LVM volumes"), action=self._select_lvm_vols, value=self._enc_config.lvm_volumes, dependencies=[self._check_dep_lvm_vols], @@ -87,7 +81,7 @@ def _define_menu_options(self) -> list[MenuItem]: key="lvm_volumes", ), MenuItem( - text=str(_("HSM")), + text=tr("HSM"), action=select_hsm, value=self._enc_config.hsm_device, dependencies=[self._check_dep_enc_type], @@ -177,7 +171,7 @@ def _prev_type(self) -> str | None: if enc_type: enc_text = EncryptionType.type_to_text(enc_type) - return f"{_('Encryption type')}: {enc_text}" + return f"{tr('Encryption type')}: {enc_text}" return None @@ -185,7 +179,7 @@ def _prev_password(self) -> str | None: enc_pwd = self._item_group.find_by_key("encryption_password").value if enc_pwd: - return f"{_('Encryption password')}: {enc_pwd.hidden()}" + return f"{tr('Encryption password')}: {enc_pwd.hidden()}" return None @@ -193,7 +187,7 @@ def _prev_partitions(self) -> str | None: partitions: list[PartitionModification] | None = self._item_group.find_by_key("partitions").value if partitions: - output = str(_("Partitions to be encrypted")) + "\n" + output = tr("Partitions to be encrypted") + "\n" output += FormattedOutput.as_table(partitions) return output.rstrip() @@ -203,7 +197,7 @@ def _prev_lvm_vols(self) -> str | None: volumes: list[PartitionModification] | None = self._item_group.find_by_key("lvm_volumes").value if volumes: - output = str(_("LVM volumes to be encrypted")) + "\n" + output = tr("LVM volumes to be encrypted") + "\n" output += FormattedOutput.as_table(volumes) return output.rstrip() @@ -217,7 +211,7 @@ def _prev_hsm(self) -> str | None: output = str(fido_device.path) output += f" ({fido_device.manufacturer}, {fido_device.product})" - return f"{_('HSM device')}: {output}" + return f"{tr('HSM device')}: {output}" def select_encryption_type(disk_config: DiskLayoutConfiguration, preset: EncryptionType) -> EncryptionType | None: @@ -238,7 +232,7 @@ def select_encryption_type(disk_config: DiskLayoutConfiguration, preset: Encrypt allow_skip=True, allow_reset=True, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Encryption type"))), + frame=FrameProperties.min(tr("Encryption type")), ).run() match result.type_: @@ -251,9 +245,9 @@ def select_encryption_type(disk_config: DiskLayoutConfiguration, preset: Encrypt def select_encrypted_password() -> Password | None: - header = str(_("Enter disk encryption password (leave blank for no encryption)")) + "\n" + header = tr("Enter disk encryption password (leave blank for no encryption)") + "\n" password = get_password( - text=str(_("Disk encryption password")), + text=tr("Disk encryption password"), header=header, allow_skip=True, ) @@ -262,7 +256,7 @@ def select_encrypted_password() -> Password | None: def select_hsm(preset: Fido2Device | None = None) -> Fido2Device | None: - header = str(_("Select a FIDO2 device to use for HSM")) + "\n" + header = tr("Select a FIDO2 device to use for HSM") + "\n" try: fido_devices = Fido2.get_fido2_devices() diff --git a/archinstall/lib/disk/filesystem.py b/archinstall/lib/disk/filesystem.py index c99b92a86f..50feb52364 100644 --- a/archinstall/lib/disk/filesystem.py +++ b/archinstall/lib/disk/filesystem.py @@ -2,8 +2,8 @@ import time from pathlib import Path -from typing import TYPE_CHECKING +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import Tui from ..interactions.general_conf import ask_abort @@ -25,13 +25,6 @@ from ..output import debug, info from .device_handler import device_handler -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class FilesystemHandler: def __init__( @@ -347,7 +340,7 @@ def _lvm_vol_handle_e2scrub(self, vol_gp: LvmVolumeGroup) -> None: def _final_warning(self, device_paths: str) -> bool: # Issue a final warning before we continue with something un-revertable. # We mention the drive one last time, and count from 5 to 0. - out = str(_(" ! Formatting {} in ")).format(device_paths) + out = tr(" ! Formatting {} in ").format(device_paths) Tui.print(out, row=0, endl="", clear_screen=True) try: diff --git a/archinstall/lib/disk/partitioning_menu.py b/archinstall/lib/disk/partitioning_menu.py index 7331796b57..9856d24cd7 100644 --- a/archinstall/lib/disk/partitioning_menu.py +++ b/archinstall/lib/disk/partitioning_menu.py @@ -2,7 +2,7 @@ import re from pathlib import Path -from typing import TYPE_CHECKING, override +from typing import override from archinstall.lib.models.device_model import ( BtrfsMountOption, @@ -17,6 +17,7 @@ Size, Unit, ) +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import EditMenu, SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -27,13 +28,6 @@ from ..utils.util import prompt_dir from .subvolume_menu import SubvolumeMenu -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class FreeSpace: def __init__(self, start: Size, end: Size) -> None: @@ -91,26 +85,26 @@ def __init__( self._using_gpt = device_mod.using_gpt(partition_table) self._actions = { - "suggest_partition_layout": str(_("Suggest partition layout")), - "remove_added_partitions": str(_("Remove all newly added partitions")), - "assign_mountpoint": str(_("Assign mountpoint")), - "mark_formatting": str(_("Mark/Unmark to be formatted (wipes data)")), - "mark_bootable": str(_("Mark/Unmark as bootable")), + "suggest_partition_layout": tr("Suggest partition layout"), + "remove_added_partitions": tr("Remove all newly added partitions"), + "assign_mountpoint": tr("Assign mountpoint"), + "mark_formatting": tr("Mark/Unmark to be formatted (wipes data)"), + "mark_bootable": tr("Mark/Unmark as bootable"), } if self._using_gpt: self._actions.update( { - "mark_esp": str(_("Mark/Unmark as ESP")), - "mark_xbootldr": str(_("Mark/Unmark as XBOOTLDR")), + "mark_esp": tr("Mark/Unmark as ESP"), + "mark_xbootldr": tr("Mark/Unmark as XBOOTLDR"), } ) self._actions.update( { - "set_filesystem": str(_("Change filesystem")), - "btrfs_mark_compressed": str(_("Mark/Unmark as compressed")), # btrfs only - "btrfs_mark_nodatacow": str(_("Mark/Unmark as nodatacow")), # btrfs only - "btrfs_set_subvolumes": str(_("Set subvolumes")), # btrfs only - "delete_partition": str(_("Delete partition")), + "set_filesystem": tr("Change filesystem"), + "btrfs_mark_compressed": tr("Mark/Unmark as compressed"), # btrfs only + "btrfs_mark_nodatacow": tr("Mark/Unmark as nodatacow"), # btrfs only + "btrfs_set_subvolumes": tr("Set subvolumes"), # btrfs only + "delete_partition": tr("Delete partition"), } ) @@ -125,8 +119,8 @@ def __init__( else: device_partitions = device_mod.partitions - prompt = str(_("Partition management: {}")).format(device.device_info.path) + "\n" - prompt += str(_("Total length: {}")).format(device.device_info.total_size.format_size(Unit.MiB)) + prompt = tr("Partition management: {}").format(device.device_info.path) + "\n" + prompt += tr("Total length: {}").format(device.device_info.total_size.format_size(Unit.MiB)) self._info = prompt + "\n" display_actions = list(self._actions.values()) @@ -138,7 +132,7 @@ def __init__( ) def wipe_str(self) -> str: - return "{}: {}".format(str(_("Wipe")), self._wipe) + return "{}: {}".format(tr("Wipe"), self._wipe) def as_segments(self, device_partitions: list[PartitionModification]) -> list[DiskSegment]: end = self._device.device_info.total_size @@ -216,9 +210,9 @@ def _run_actions_on_entry(self, entry: DiskSegment) -> None: def selected_action_display(self, selection: DiskSegment) -> str: if isinstance(selection.segment, PartitionModification): if selection.segment.status == ModificationStatus.Create: - return str(_("Partition - New")) + return tr("Partition - New") elif selection.segment.is_delete() and selection.segment.dev_path: - title = str(_("Partition")) + "\n\n" + title = tr("Partition") + "\n\n" title += "status: delete\n" title += f"device: {selection.segment.dev_path}\n" for part in self._device.partition_infos: @@ -402,7 +396,7 @@ def _prompt_formatting(self, partition: PartitionModification) -> None: # without asking the user which inner-filesystem they want to use. Since the flag 'encrypted' = True is already set, # it's safe to change the filesystem for this partition. if partition.fs_type == FilesystemType.Crypto_luks: - prompt = str(_("This partition is currently encrypted, to format it a filesystem has to be specified")) + "\n" + prompt = tr("This partition is currently encrypted, to format it a filesystem has to be specified") + "\n" fs_type = self._prompt_partition_fs_type(prompt) partition.fs_type = fs_type @@ -410,8 +404,8 @@ def _prompt_formatting(self, partition: PartitionModification) -> None: partition.mountpoint = None def _prompt_mountpoint(self) -> Path: - header = str(_("Partition mount-points are relative to inside the installation, the boot would be /boot as an example.")) + "\n" - prompt = str(_("Mountpoint")) + header = tr("Partition mount-points are relative to inside the installation, the boot would be /boot as an example.") + "\n" + prompt = tr("Mountpoint") mountpoint = prompt_dir(prompt, header, validate=False, allow_skip=False) assert mountpoint @@ -427,7 +421,7 @@ def _prompt_partition_fs_type(self, prompt: str | None = None) -> FilesystemType group, header=prompt, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Filesystem"))), + frame=FrameProperties.min(tr("Filesystem")), allow_skip=False, ).run() @@ -473,26 +467,26 @@ def _prompt_size(self, free_space: FreeSpace) -> Size: def validate(value: str) -> str | None: size = self._validate_value(sector_size, max_size, value) if not size: - return str(_("Invalid size")) + return tr("Invalid size") return None device_info = self._device.device_info sector_size = device_info.sector_size - text = str(_("Selected free space segment on device {}:")).format(device_info.path) + "\n\n" + text = tr("Selected free space segment on device {}:").format(device_info.path) + "\n\n" free_space_table = FormattedOutput.as_table([free_space]) prompt = text + free_space_table + "\n" max_sectors = free_space.length.format_size(Unit.sectors, sector_size) max_bytes = free_space.length.format_size(Unit.B) - prompt += str(_("Size: {} / {}")).format(max_sectors, max_bytes) + "\n\n" - prompt += str(_("All entered values can be suffixed with a unit: %, B, KB, KiB, MB, MiB...")) + "\n" - prompt += str(_("If no unit is provided, the value is interpreted as sectors")) + "\n" + prompt += tr("Size: {} / {}").format(max_sectors, max_bytes) + "\n\n" + prompt += tr("All entered values can be suffixed with a unit: %, B, KB, KiB, MB, MiB...") + "\n" + prompt += tr("If no unit is provided, the value is interpreted as sectors") + "\n" max_size = free_space.length - title = str(_("Size (default: {}): ")).format(max_size.format_highest()) + title = tr("Size (default: {}): ").format(max_size.format_highest()) result = EditMenu( title, @@ -547,7 +541,7 @@ def _create_new_partition(self, free_space: FreeSpace) -> PartitionModification: return partition def _reset_confirmation(self) -> bool: - prompt = str(_("This will remove all newly added partitions, continue?")) + "\n" + prompt = tr("This will remove all newly added partitions, continue?") + "\n" result = SelectMenu[bool]( MenuItemGroup.yes_no(), diff --git a/archinstall/lib/disk/subvolume_menu.py b/archinstall/lib/disk/subvolume_menu.py index e8b0ab17ce..cd1670089d 100644 --- a/archinstall/lib/disk/subvolume_menu.py +++ b/archinstall/lib/disk/subvolume_menu.py @@ -1,7 +1,8 @@ from pathlib import Path -from typing import TYPE_CHECKING, assert_never, override +from typing import assert_never, override from archinstall.lib.models.device_model import SubvolumeModification +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import EditMenu from archinstall.tui.result import ResultType from archinstall.tui.types import Alignment @@ -9,13 +10,6 @@ from ..menu.list_manager import ListManager from ..utils.util import prompt_dir -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class SubvolumeMenu(ListManager[SubvolumeModification]): def __init__( @@ -24,9 +18,9 @@ def __init__( prompt: str | None = None, ): self._actions = [ - str(_("Add subvolume")), - str(_("Edit subvolume")), - str(_("Delete subvolume")), + tr("Add subvolume"), + tr("Edit subvolume"), + tr("Delete subvolume"), ] super().__init__( @@ -42,7 +36,7 @@ def selected_action_display(self, selection: SubvolumeModification) -> str: def _add_subvolume(self, preset: SubvolumeModification | None = None) -> SubvolumeModification | None: result = EditMenu( - str(_("Subvolume name")), + tr("Subvolume name"), alignment=Alignment.CENTER, allow_skip=True, default_text=str(preset.name) if preset else None, @@ -58,10 +52,10 @@ def _add_subvolume(self, preset: SubvolumeModification | None = None) -> Subvolu case _: assert_never(result.type_) - header = f"{_('Subvolume name')}: {name}\n" + header = f"{tr('Subvolume name')}: {name}\n" path = prompt_dir( - str(_("Subvolume mountpoint")), + tr("Subvolume mountpoint"), header=header, allow_skip=True, validate=False, diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index c7764cf01b..b22e4b646f 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, override +from typing import override from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu from archinstall.lib.disk.encryption_menu import DiskEncryptionMenu @@ -35,16 +35,9 @@ from .models.users import Password, User from .output import FormattedOutput from .pacman.config import PacmanConfig -from .translationhandler import Language, translation_handler +from .translationhandler import Language, tr, translation_handler from .utils.util import get_password -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class GlobalMenu(AbstractMenu[None]): def __init__(self, arch_config: ArchConfig) -> None: @@ -62,46 +55,46 @@ def __init__(self, arch_config: ArchConfig) -> None: def _get_menu_options(self) -> list[MenuItem]: return [ MenuItem( - text=str(_("Archinstall language")), + text=tr("Archinstall language"), action=self._select_archinstall_language, display_action=lambda x: x.display_name if x else "", key="archinstall_language", ), MenuItem( - text=str(_("Locales")), + text=tr("Locales"), action=self._locale_selection, preview_action=self._prev_locale, key="locale_config", ), MenuItem( - text=str(_("Mirrors and repositories")), + text=tr("Mirrors and repositories"), action=self._mirror_configuration, preview_action=self._prev_mirror_config, key="mirror_config", ), MenuItem( - text=str(_("Disk configuration")), + text=tr("Disk configuration"), action=self._select_disk_config, preview_action=self._prev_disk_config, mandatory=True, key="disk_config", ), MenuItem( - text=str(_("Disk encryption")), + text=tr("Disk encryption"), action=self._disk_encryption, preview_action=self._prev_disk_encryption, dependencies=["disk_config"], key="disk_encryption", ), MenuItem( - text=str(_("Swap")), + text=tr("Swap"), value=True, action=ask_for_swap, preview_action=self._prev_swap, key="swap", ), MenuItem( - text=str(_("Bootloader")), + text=tr("Bootloader"), value=Bootloader.get_default(), action=self._select_bootloader, preview_action=self._prev_bootloader, @@ -109,7 +102,7 @@ def _get_menu_options(self) -> list[MenuItem]: key="bootloader", ), MenuItem( - text=str(_("Unified kernel images")), + text=tr("Unified kernel images"), value=False, enabled=SysInfo.has_uefi(), action=ask_for_uki, @@ -117,38 +110,38 @@ def _get_menu_options(self) -> list[MenuItem]: key="uki", ), MenuItem( - text=str(_("Hostname")), + text=tr("Hostname"), value="archlinux", action=ask_hostname, preview_action=self._prev_hostname, key="hostname", ), MenuItem( - text=str(_("Root password")), + text=tr("Root password"), action=self._set_root_password, preview_action=self._prev_root_pwd, key="root_enc_password", ), MenuItem( - text=str(_("User account")), + text=tr("User account"), action=self._create_user_account, preview_action=self._prev_users, key="users", ), MenuItem( - text=str(_("Profile")), + text=tr("Profile"), action=self._select_profile, preview_action=self._prev_profile, key="profile_config", ), MenuItem( - text=str(_("Audio")), + text=tr("Audio"), action=ask_for_audio_selection, preview_action=self._prev_audio, key="audio_config", ), MenuItem( - text=str(_("Kernels")), + text=tr("Kernels"), value=["linux"], action=select_kernel, preview_action=self._prev_kernel, @@ -156,35 +149,35 @@ def _get_menu_options(self) -> list[MenuItem]: key="kernels", ), MenuItem( - text=str(_("Network configuration")), + text=tr("Network configuration"), action=ask_to_configure_network, value={}, preview_action=self._prev_network_config, key="network_config", ), MenuItem( - text=str(_("Parallel Downloads")), + text=tr("Parallel Downloads"), action=add_number_of_parallel_downloads, value=0, preview_action=self._prev_parallel_dw, key="parallel_downloads", ), MenuItem( - text=str(_("Additional packages")), + text=tr("Additional packages"), action=self._select_additional_packages, value=[], preview_action=self._prev_additional_pkgs, key="packages", ), MenuItem( - text=str(_("Timezone")), + text=tr("Timezone"), action=ask_for_a_timezone, value="UTC", preview_action=self._prev_tz, key="timezone", ), MenuItem( - text=str(_("Automatic time sync (NTP)")), + text=tr("Automatic time sync (NTP)"), action=ask_ntp, value=True, preview_action=self._prev_ntp, @@ -194,17 +187,17 @@ def _get_menu_options(self) -> list[MenuItem]: text="", ), MenuItem( - text=str(_("Save configuration")), + text=tr("Save configuration"), action=lambda x: self._safe_config(), key=f"{CONFIG_KEY}_save", ), MenuItem( - text=str(_("Install")), + text=tr("Install"), preview_action=self._prev_install_invalid_config, key=f"{CONFIG_KEY}_install", ), MenuItem( - text=str(_("Abort")), + text=tr("Abort"), action=lambda x: exit(1), key=f"{CONFIG_KEY}_abort", ), @@ -239,7 +232,7 @@ def has_superuser() -> bool: if item.key in ["root_enc_password", "users"]: if not check("root_enc_password") and not has_superuser(): missing.add( - str(_("Either root-password or at least 1 user with sudo privileges must be specified")), + tr("Either root-password or at least 1 user with sudo privileges must be specified"), ) elif item.mandatory: if not check(item.key): @@ -307,7 +300,7 @@ def _prev_network_config(self, item: MenuItem) -> str | None: if network_config.type == NicType.MANUAL: output = FormattedOutput.as_table(network_config.nics) else: - output = f"{_('Network configuration')}:\n{network_config.type.display_msg()}" + output = f"{tr('Network configuration')}:\n{network_config.type.display_msg()}" return output return None @@ -320,13 +313,13 @@ def _prev_additional_pkgs(self, item: MenuItem) -> str | None: def _prev_tz(self, item: MenuItem) -> str | None: if item.value: - return f"{_('Timezone')}: {item.value}" + return f"{tr('Timezone')}: {item.value}" return None def _prev_ntp(self, item: MenuItem) -> str | None: if item.value is not None: - output = f"{_('NTP')}: " - output += str(_("Enabled")) if item.value else str(_("Disabled")) + output = f"{tr('NTP')}: " + output += tr("Enabled") if item.value else tr("Disabled") return output return None @@ -334,13 +327,13 @@ def _prev_disk_config(self, item: MenuItem) -> str | None: disk_layout_conf: DiskLayoutConfiguration | None = item.value if disk_layout_conf: - output = str(_("Configuration type: {}")).format(disk_layout_conf.config_type.display_msg()) + "\n" + output = tr("Configuration type: {}").format(disk_layout_conf.config_type.display_msg()) + "\n" if disk_layout_conf.config_type == DiskLayoutType.Pre_mount: - output += str(_("Mountpoint")) + ": " + str(disk_layout_conf.mountpoint) + output += tr("Mountpoint") + ": " + str(disk_layout_conf.mountpoint) if disk_layout_conf.lvm_config: - output += "{}: {}".format(str(_("LVM configuration type")), disk_layout_conf.lvm_config.config_type.display_msg()) + output += "{}: {}".format(tr("LVM configuration type"), disk_layout_conf.lvm_config.config_type.display_msg()) return output @@ -348,49 +341,49 @@ def _prev_disk_config(self, item: MenuItem) -> str | None: def _prev_swap(self, item: MenuItem) -> str | None: if item.value is not None: - output = f"{_('Swap on zram')}: " - output += str(_("Enabled")) if item.value else str(_("Disabled")) + output = f"{tr('Swap on zram')}: " + output += tr("Enabled") if item.value else tr("Disabled") return output return None def _prev_uki(self, item: MenuItem) -> str | None: if item.value is not None: - output = f"{_('Unified kernel images')}: " - output += str(_("Enabled")) if item.value else str(_("Disabled")) + output = f"{tr('Unified kernel images')}: " + output += tr("Enabled") if item.value else tr("Disabled") return output return None def _prev_hostname(self, item: MenuItem) -> str | None: if item.value is not None: - return f"{_('Hostname')}: {item.value}" + return f"{tr('Hostname')}: {item.value}" return None def _prev_root_pwd(self, item: MenuItem) -> str | None: if item.value is not None: password: Password = item.value - return f"{_('Root password')}: {password.hidden()}" + return f"{tr('Root password')}: {password.hidden()}" return None def _prev_audio(self, item: MenuItem) -> str | None: if item.value is not None: config: AudioConfiguration = item.value - return f"{_('Audio')}: {config.audio.value}" + return f"{tr('Audio')}: {config.audio.value}" return None def _prev_parallel_dw(self, item: MenuItem) -> str | None: if item.value is not None: - return f"{_('Parallel Downloads')}: {item.value}" + return f"{tr('Parallel Downloads')}: {item.value}" return None def _prev_kernel(self, item: MenuItem) -> str | None: if item.value: kernel = ", ".join(item.value) - return f"{_('Kernel')}: {kernel}" + return f"{tr('Kernel')}: {kernel}" return None def _prev_bootloader(self, item: MenuItem) -> str | None: if item.value is not None: - return f"{_('Bootloader')}: {item.value.value}" + return f"{tr('Bootloader')}: {item.value.value}" return None def _prev_disk_encryption(self, item: MenuItem) -> str | None: @@ -398,14 +391,14 @@ def _prev_disk_encryption(self, item: MenuItem) -> str | None: enc_config: DiskEncryption | None = item.value if disk_config and not DiskEncryption.validate_enc(disk_config): - return str(_("LVM disk encryption with more than 2 partitions is currently not supported")) + return tr("LVM disk encryption with more than 2 partitions is currently not supported") if enc_config: enc_type = EncryptionType.type_to_text(enc_config.encryption_type) - output = str(_("Encryption type")) + f": {enc_type}\n" + output = tr("Encryption type") + f": {enc_type}\n" if enc_config.encryption_password: - output += str(_("Password")) + f": {enc_config.encryption_password.hidden()}\n" + output += tr("Password") + f": {enc_config.encryption_password.hidden()}\n" if enc_config.partitions: output += f"Partitions: {len(enc_config.partitions)} selected\n" @@ -470,13 +463,13 @@ def _validate_bootloader(self) -> str | None: def _prev_install_invalid_config(self, item: MenuItem) -> str | None: if missing := self._missing_configs(): - text = str(_("Missing configurations:\n")) + text = tr("Missing configurations:\n") for m in missing: text += f"- {m}\n" return text[:-1] # remove last new line if error := self._validate_bootloader(): - return str(_(f"Invalid configuration: {error}")) + return tr(f"Invalid configuration: {error}") return None @@ -491,24 +484,24 @@ def _prev_profile(self, item: MenuItem) -> str | None: profile_config: ProfileConfiguration | None = item.value if profile_config and profile_config.profile: - output = str(_("Profiles")) + ": " + output = tr("Profiles") + ": " if profile_names := profile_config.profile.current_selection_names(): output += ", ".join(profile_names) + "\n" else: output += profile_config.profile.name + "\n" if profile_config.gfx_driver: - output += str(_("Graphics driver")) + ": " + profile_config.gfx_driver.value + "\n" + output += tr("Graphics driver") + ": " + profile_config.gfx_driver.value + "\n" if profile_config.greeter: - output += str(_("Greeter")) + ": " + profile_config.greeter.value + "\n" + output += tr("Greeter") + ": " + profile_config.greeter.value + "\n" return output return None def _set_root_password(self, preset: str | None = None) -> Password | None: - password = get_password(text=str(_("Root password")), allow_skip=True) + password = get_password(text=tr("Root password"), allow_skip=True) return password def _select_disk_config( @@ -583,25 +576,25 @@ def _prev_mirror_config(self, item: MenuItem) -> str | None: output = "" if mirror_config.mirror_regions: - title = str(_("Selected mirror regions")) + title = tr("Selected mirror regions") divider = "-" * len(title) regions = mirror_config.region_names output += f"{title}\n{divider}\n{regions}\n\n" if mirror_config.custom_servers: - title = str(_("Custom servers")) + title = tr("Custom servers") divider = "-" * len(title) servers = mirror_config.custom_server_urls output += f"{title}\n{divider}\n{servers}\n\n" if mirror_config.optional_repositories: - title = str(_("Optional repositories")) + title = tr("Optional repositories") divider = "-" * len(title) repos = ", ".join([r.value for r in mirror_config.optional_repositories]) output += f"{title}\n{divider}\n{repos}\n\n" if mirror_config.custom_repositories: - title = str(_("Custom repositories")) + title = tr("Custom repositories") table = FormattedOutput.as_table(mirror_config.custom_repositories) output += f"{title}:\n\n{table}" diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index 5e0f240b74..4eb6699bd3 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -2,19 +2,12 @@ from enum import Enum from functools import cached_property from pathlib import Path -from typing import TYPE_CHECKING from .exceptions import SysCallError from .general import SysCommand from .networking import enrich_iface_types, list_interfaces from .output import debug - -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] +from .translationhandler import tr class CpuVendor(Enum): @@ -81,7 +74,7 @@ def is_nvidia(self) -> bool: def packages_text(self) -> str: pkg_names = [p.value for p in self.gfx_packages()] - text = str(_("Installed packages")) + ":\n" + text = tr("Installed packages") + ":\n" for p in sorted(pkg_names): text += f"\t- {p}\n" diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index d7a51f095f..2b69131745 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -11,7 +11,7 @@ from pathlib import Path from subprocess import CalledProcessError from types import TracebackType -from typing import TYPE_CHECKING, Any +from typing import Any from archinstall.lib.disk.device_handler import device_handler from archinstall.lib.disk.fido import Fido2 @@ -29,6 +29,7 @@ Unit, ) from archinstall.lib.models.packages import Repository +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import Tui from .args import arch_config_handler @@ -48,11 +49,6 @@ from .plugins import plugins from .storage import storage -if TYPE_CHECKING: - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - # Any package that the Installer() is responsible for (optional and the default ones) __packages__ = ["base", "base-devel", "linux-firmware", "linux", "linux-lts", "linux-zen", "linux-hardened"] @@ -139,8 +135,8 @@ def __exit__(self, exc_type: type[BaseException] | None, exc_val, exc_tb: Traceb # We avoid printing /mnt/ because that might confuse people if they note it down # and then reboot, and a identical log file will be found in the ISO medium anyway. log_file = os.path.join(storage["LOG_PATH"], storage["LOG_FILE"]) - Tui.print(str(_("[!] A log file has been created here: {}").format(log_file))) - Tui.print(str(_("Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues"))) + Tui.print(str(tr("[!] A log file has been created here: {}").format(log_file))) + Tui.print(tr("Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues")) raise exc_val if not (missing_steps := self.post_install_check()): @@ -176,21 +172,21 @@ def _verify_service_stop(self) -> None: """ if not arch_config_handler.args.skip_ntp: - info(str(_("Waiting for time sync (timedatectl show) to complete."))) + info(tr("Waiting for time sync (timedatectl show) to complete.")) started_wait = time.time() notified = False while True: if not notified and time.time() - started_wait > 5: notified = True - warn(str(_("Time synchronization not completing, while you wait - check the docs for workarounds: https://archinstall.readthedocs.io/"))) + warn(tr("Time synchronization not completing, while you wait - check the docs for workarounds: https://archinstall.readthedocs.io/")) time_val = SysCommand("timedatectl show --property=NTPSynchronized --value").decode() if time_val and time_val.strip() == "yes": break time.sleep(1) else: - info(str(_("Skipping waiting for automatic time sync (this can cause issues if time is out of sync during installation)"))) + info(tr("Skipping waiting for automatic time sync (this can cause issues if time is out of sync during installation)")) info("Waiting for automatic mirror selection (reflector) to complete.") while self._service_state("reflector") not in ("dead", "failed", "exited"): @@ -200,7 +196,7 @@ def _verify_service_stop(self) -> None: # while self._service_state('pacman-init') not in ('dead', 'failed', 'exited'): # time.sleep(1) - info(str(_("Waiting for Arch Linux keyring sync (archlinux-keyring-wkd-sync) to complete."))) + info(tr("Waiting for Arch Linux keyring sync (archlinux-keyring-wkd-sync) to complete.")) # Wait for the timer to kick in while self._service_started("archlinux-keyring-wkd-sync.timer") is None: time.sleep(1) diff --git a/archinstall/lib/interactions/disk_conf.py b/archinstall/lib/interactions/disk_conf.py index eb7f7758d7..35cae1829d 100644 --- a/archinstall/lib/interactions/disk_conf.py +++ b/archinstall/lib/interactions/disk_conf.py @@ -1,5 +1,4 @@ from pathlib import Path -from typing import TYPE_CHECKING from archinstall.lib.args import arch_config_handler from archinstall.lib.disk.device_handler import device_handler @@ -28,6 +27,7 @@ _DeviceInfo, ) from archinstall.lib.output import debug +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -36,13 +36,6 @@ from ..output import FormattedOutput from ..utils.util import prompt_dir -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - def select_devices(preset: list[BDevice] | None = []) -> list[BDevice]: def _preview_device_selection(item: MenuItem) -> str | None: @@ -143,7 +136,7 @@ def select_disk_config(preset: DiskLayoutConfiguration | None = None) -> DiskLay group, allow_skip=True, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Disk configuration type"))), + frame=FrameProperties.min(tr("Disk configuration type")), allow_reset=True, ).run() @@ -159,7 +152,7 @@ def select_disk_config(preset: DiskLayoutConfiguration | None = None) -> DiskLay 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(_("Root mount directory")), output, allow_skip=True) + path = prompt_dir(tr("Root mount directory"), output, allow_skip=True) if path is None: return None @@ -213,7 +206,7 @@ def select_lvm_config( group, allow_reset=True, allow_skip=True, - frame=FrameProperties.min(str(_("LVM configuration type"))), + frame=FrameProperties.min(tr("LVM configuration type")), alignment=Alignment.CENTER, ).run() @@ -275,9 +268,9 @@ def select_main_filesystem_format() -> FilesystemType: def select_mount_options() -> list[str]: - prompt = str(_("Would you like to use compression or disable CoW?")) + "\n" - compression = str(_("Use compression")) - disable_cow = str(_("Disable Copy-on-Write")) + prompt = tr("Would you like to use compression or disable CoW?") + "\n" + compression = tr("Use compression") + disable_cow = tr("Disable Copy-on-Write") items = [ MenuItem(compression, value=BtrfsMountOption.compress.value), @@ -332,7 +325,7 @@ def suggest_single_disk_layout( min_size_to_allow_home_part = Size(64, Unit.GiB, sector_size) if filesystem_type == FilesystemType.Btrfs: - prompt = str(_("Would you like to use BTRFS subvolumes with a default structure?")) + "\n" + prompt = tr("Would you like to use BTRFS subvolumes with a default structure?") + "\n" group = MenuItemGroup.yes_no() group.set_focus_by_value(MenuItem.yes().value) result = SelectMenu[bool]( @@ -369,7 +362,7 @@ def suggest_single_disk_layout( elif separate_home: using_home_partition = True else: - prompt = str(_("Would you like to create a separate partition for /home?")) + "\n" + prompt = tr("Would you like to create a separate partition for /home?") + "\n" group = MenuItemGroup.yes_no() group.set_focus_by_value(MenuItem.yes().value) result = SelectMenu( @@ -474,11 +467,11 @@ def suggest_multi_disk_layout( root_device: BDevice | None = sorted_delta[0][0] if home_device is None or root_device is None: - text = str(_("The selected drives do not have the minimum capacity required for an automatic suggestion\n")) - text += str(_("Minimum capacity for /home partition: {}GiB\n").format(min_home_partition_size.format_size(Unit.GiB))) - text += str(_("Minimum capacity for Arch Linux partition: {}GiB").format(desired_root_partition_size.format_size(Unit.GiB))) + text = tr("The selected drives do not have the minimum capacity required for an automatic suggestion\n") + text += tr("Minimum capacity for /home partition: {}GiB\n").format(min_home_partition_size.format_size(Unit.GiB)) + text += tr("Minimum capacity for Arch Linux partition: {}GiB").format(desired_root_partition_size.format_size(Unit.GiB)) - items = [MenuItem(str(_("Continue")))] + items = [MenuItem(tr("Continue"))] group = MenuItemGroup(items) SelectMenu(group).run() @@ -568,7 +561,7 @@ def suggest_lvm_layout( filesystem_type = select_main_filesystem_format() if filesystem_type == FilesystemType.Btrfs: - prompt = str(_("Would you like to use BTRFS subvolumes with a default structure?")) + "\n" + prompt = tr("Would you like to use BTRFS subvolumes with a default structure?") + "\n" group = MenuItemGroup.yes_no() group.set_focus_by_value(MenuItem.yes().value) diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index 747b24fc46..e8b0f5fa7b 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -2,10 +2,11 @@ from enum import Enum from pathlib import Path -from typing import TYPE_CHECKING, assert_never +from typing import assert_never from archinstall.lib.models.packages import Repository from archinstall.lib.packages.packages import list_available_packages +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import EditMenu, SelectMenu, Tui from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -17,28 +18,18 @@ from ..output import warn from ..translationhandler import Language -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class PostInstallationAction(Enum): - EXIT = str(_("Exit archinstall")) - REBOOT = str(_("Reboot system")) - CHROOT = str(_("chroot into installation for post-installation configurations")) + EXIT = tr("Exit archinstall") + REBOOT = tr("Reboot system") + CHROOT = tr("chroot into installation for post-installation configurations") def ask_ntp(preset: bool = True) -> bool: - header = str(_("Would you like to use automatic time synchronization (NTP) with the default time servers?\n")) + "\n" + header = tr("Would you like to use automatic time synchronization (NTP) with the default time servers?\n") + "\n" header += ( - str( - _( - "Hardware time and other post-configuration steps might be required in order for NTP to work.\n" - "For more information, please check the Arch wiki", - ) + tr( + "Hardware time and other post-configuration steps might be required in order for NTP to work.\nFor more information, please check the Arch wiki", ) + "\n" ) @@ -67,7 +58,7 @@ def ask_ntp(preset: bool = True) -> bool: def ask_hostname(preset: str | None = None) -> str | None: result = EditMenu( - str(_("Hostname")), + tr("Hostname"), alignment=Alignment.CENTER, allow_skip=True, default_text=preset, @@ -98,7 +89,7 @@ def ask_for_a_timezone(preset: str | None = None) -> str | None: group, allow_reset=True, allow_skip=True, - frame=FrameProperties.min(str(_("Timezone"))), + frame=FrameProperties.min(tr("Timezone")), alignment=Alignment.CENTER, ).run() @@ -122,7 +113,7 @@ def ask_for_audio_selection(preset: AudioConfiguration | None = None) -> AudioCo group, allow_skip=True, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Audio"))), + frame=FrameProperties.min(tr("Audio")), ).run() match result.type_: @@ -166,7 +157,7 @@ def select_archinstall_language(languages: list[Language], preset: Language) -> allow_skip=True, allow_reset=False, alignment=Alignment.CENTER, - frame=FrameProperties.min(header=str(_("Select language"))), + frame=FrameProperties.min(header=tr("Select language")), ).run() match result.type_: @@ -185,17 +176,17 @@ def ask_additional_packages_to_install( repositories |= {Repository.Core, Repository.Extra} respos_text = ", ".join([r.value for r in repositories]) - output = str(_("Repositories: {}")).format(respos_text) + "\n" + output = tr("Repositories: {}").format(respos_text) + "\n" - output += str(_("Loading packages...")) + output += tr("Loading packages...") Tui.print(output, clear_screen=True) packages = list_available_packages(tuple(repositories)) package_groups = PackageGroup.from_available_packages(packages) # Additional packages (with some light weight error handling for invalid package names) - header = str(_("Only packages such as base, base-devel, linux, linux-firmware, efibootmgr and optional profile packages are installed.")) + "\n" - header += str(_("Select any packages from the below list that should be installed additionally")) + "\n" + header = tr("Only packages such as base, base-devel, linux, linux-firmware, efibootmgr and optional profile packages are installed.") + "\n" + header += tr("Select any packages from the below list that should be installed additionally") + "\n" # there are over 15k packages so this needs to be quick preset_packages: list[AvailablePackage | PackageGroup] = [] @@ -251,10 +242,10 @@ def ask_additional_packages_to_install( def add_number_of_parallel_downloads(preset: int | None = None) -> int | None: max_recommended = 5 - header = str(_("This option enables the number of parallel downloads that can occur during package downloads")) + "\n" - header += str(_("Enter the number of parallel downloads to be enabled.\n\nNote:\n")) - header += str(_(" - Maximum recommended value : {} ( Allows {} parallel downloads at a time )")).format(max_recommended, max_recommended) + "\n" - header += str(_(" - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )\n")) + header = tr("This option enables the number of parallel downloads that can occur during package downloads") + "\n" + header += tr("Enter the number of parallel downloads to be enabled.\n\nNote:\n") + header += tr(" - Maximum recommended value : {} ( Allows {} parallel downloads at a time )").format(max_recommended, max_recommended) + "\n" + header += tr(" - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )\n") def validator(s: str) -> str | None: try: @@ -264,10 +255,10 @@ def validator(s: str) -> str | None: except Exception: pass - return str(_("Invalid download number")) + return tr("Invalid download number") result = EditMenu( - str(_("Number downloads")), + tr("Number downloads"), header=header, allow_skip=True, allow_reset=True, @@ -300,8 +291,8 @@ def validator(s: str) -> str | None: def ask_post_installation() -> PostInstallationAction: - header = str(_("Installation completed")) + "\n\n" - header += str(_("What would you like to do next?")) + "\n" + header = tr("Installation completed") + "\n\n" + header += tr("What would you like to do next?") + "\n" items = [MenuItem(action.value, value=action) for action in PostInstallationAction] group = MenuItemGroup(items) @@ -321,7 +312,7 @@ def ask_post_installation() -> PostInstallationAction: def ask_abort() -> None: - prompt = str(_("Do you really want to abort?")) + "\n" + prompt = tr("Do you really want to abort?") + "\n" group = MenuItemGroup.yes_no() result = SelectMenu[bool]( diff --git a/archinstall/lib/interactions/manage_users_conf.py b/archinstall/lib/interactions/manage_users_conf.py index 99b7fed495..229255b00a 100644 --- a/archinstall/lib/interactions/manage_users_conf.py +++ b/archinstall/lib/interactions/manage_users_conf.py @@ -1,8 +1,9 @@ from __future__ import annotations import re -from typing import TYPE_CHECKING, override +from typing import override +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import EditMenu, SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -12,21 +13,14 @@ from ..models.users import User from ..utils.util import get_password -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class UserList(ListManager[User]): def __init__(self, prompt: str, lusers: list[User]): self._actions = [ - str(_("Add a user")), - str(_("Change password")), - str(_("Promote/Demote user")), - str(_("Delete User")), + tr("Add a user"), + tr("Change password"), + tr("Promote/Demote user"), + tr("Delete User"), ] super().__init__( @@ -50,8 +44,8 @@ def handle_action(self, action: str, entry: User | None, data: list[User]) -> li data = [d for d in data if d.username != new_user.username] data += [new_user] elif action == self._actions[1] and entry: # change password - header = f"{_('User')}: {entry.username}\n" - new_password = get_password(str(_("Password")), header=header) + header = f"{tr('User')}: {entry.username}\n" + new_password = get_password(tr("Password"), header=header) if new_password: user = next(filter(lambda x: x == entry, data)) @@ -67,11 +61,11 @@ def handle_action(self, action: str, entry: User | None, data: list[User]) -> li def _check_for_correct_username(self, username: str) -> str | None: if re.match(r"^[a-z_][a-z0-9_-]*\$?$", username) and len(username) <= 32: return None - return str(_("The username you entered is invalid")) + return tr("The username you entered is invalid") def _add_user(self) -> User | None: editResult = EditMenu( - str(_("Username")), + tr("Username"), allow_skip=True, validator=self._check_for_correct_username, ).input() @@ -84,15 +78,15 @@ def _add_user(self) -> User | None: case _: raise ValueError("Unhandled result type") - header = f"{_('Username')}: {username}\n" + header = f"{tr('Username')}: {username}\n" - password = get_password(str(_("Password")), header=header, allow_skip=True) + password = get_password(tr("Password"), header=header, allow_skip=True) if not password: return None - header += f"{_('Password')}: {password.hidden()}\n\n" - header += str(_('Should "{}" be a superuser (sudo)?\n')).format(username) + header += f"{tr('Password')}: {password.hidden()}\n\n" + header += str(tr('Should "{}" be a superuser (sudo)?\n')).format(username) group = MenuItemGroup.yes_no() group.focus_item = MenuItem.yes() diff --git a/archinstall/lib/interactions/network_menu.py b/archinstall/lib/interactions/network_menu.py index 38994580d8..9deb873eb6 100644 --- a/archinstall/lib/interactions/network_menu.py +++ b/archinstall/lib/interactions/network_menu.py @@ -1,8 +1,9 @@ from __future__ import annotations import ipaddress -from typing import TYPE_CHECKING, assert_never, override +from typing import assert_never, override +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import EditMenu, SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -12,20 +13,13 @@ from ..models.network_configuration import NetworkConfiguration, Nic, NicType from ..networking import list_interfaces -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class ManualNetworkConfig(ListManager[Nic]): def __init__(self, prompt: str, preset: list[Nic]): self._actions = [ - str(_("Add interface")), - str(_("Edit interface")), - str(_("Delete interface")), + tr("Add interface"), + tr("Edit interface"), + tr("Delete interface"), ] super().__init__( @@ -73,7 +67,7 @@ def _select_iface(self, data: list[Nic]) -> str | None: result = SelectMenu[str]( group, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Interfaces"))), + frame=FrameProperties.min(tr("Interfaces")), allow_skip=True, ).run() @@ -104,7 +98,7 @@ def validator(ip: str) -> str | None: ipaddress.ip_interface(ip) return None except ValueError: - return str(_("You need to enter a valid IP in IP-config mode")) + return tr("You need to enter a valid IP in IP-config mode") result = EditMenu( title, @@ -127,7 +121,7 @@ def _edit_iface(self, edit_nic: Nic) -> Nic: modes = ["DHCP (auto detect)", "IP (static)"] default_mode = "DHCP (auto detect)" - header = str(_('Select which mode to configure for "{}"').format(iface_name)) + "\n" + header = tr('Select which mode to configure for "{}"').format(iface_name) + "\n" items = [MenuItem(m, value=m) for m in modes] group = MenuItemGroup(items, sort_items=True) group.set_default_by_value(default_mode) @@ -137,7 +131,7 @@ def _edit_iface(self, edit_nic: Nic) -> Nic: header=header, allow_skip=False, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Modes"))), + frame=FrameProperties.min(tr("Modes")), ).run() match result.type_: @@ -151,20 +145,20 @@ def _edit_iface(self, edit_nic: Nic) -> Nic: assert_never(result.type_) if mode == "IP (static)": - header = str(_("Enter the IP and subnet for {} (example: 192.168.0.5/24): ").format(iface_name)) + "\n" - ip = self._get_ip_address(str(_("IP address")), header, False, False) + header = tr("Enter the IP and subnet for {} (example: 192.168.0.5/24): ").format(iface_name) + "\n" + ip = self._get_ip_address(tr("IP address"), header, False, False) - header = str(_("Enter your gateway (router) IP address (leave blank for none)")) + "\n" - gateway = self._get_ip_address(str(_("Gateway address")), header, True, False) + header = tr("Enter your gateway (router) IP address (leave blank for none)") + "\n" + gateway = self._get_ip_address(tr("Gateway address"), header, True, False) if edit_nic.dns: display_dns = " ".join(edit_nic.dns) else: display_dns = None - header = str(_("Enter your DNS servers with space separated (leave blank for none)")) + "\n" + header = tr("Enter your DNS servers with space separated (leave blank for none)") + "\n" dns_servers = self._get_ip_address( - str(_("DNS servers")), + tr("DNS servers"), header, True, True, @@ -195,7 +189,7 @@ def ask_to_configure_network(preset: NetworkConfiguration | None) -> NetworkConf result = SelectMenu[NetworkConfiguration]( group, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Network configuration"))), + frame=FrameProperties.min(tr("Network configuration")), allow_reset=True, allow_skip=True, ).run() @@ -215,7 +209,7 @@ def ask_to_configure_network(preset: NetworkConfiguration | None) -> NetworkConf return NetworkConfiguration(NicType.NM) case NicType.MANUAL: preset_nics = preset.nics if preset else [] - nics = ManualNetworkConfig(str(_("Configure interfaces")), preset_nics).run() + nics = ManualNetworkConfig(tr("Configure interfaces"), preset_nics).run() if nics: return NetworkConfiguration(NicType.MANUAL, nics) diff --git a/archinstall/lib/interactions/system_conf.py b/archinstall/lib/interactions/system_conf.py index 18b0d4c00d..d1c9b2cac6 100644 --- a/archinstall/lib/interactions/system_conf.py +++ b/archinstall/lib/interactions/system_conf.py @@ -1,7 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING - +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -10,13 +9,6 @@ from ..hardware import GfxDriver, SysInfo from ..models.bootloader import Bootloader -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - def select_kernel(preset: list[str] = []) -> list[str]: """ @@ -40,7 +32,7 @@ def select_kernel(preset: list[str] = []) -> list[str]: allow_skip=True, allow_reset=True, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Kernel"))), + frame=FrameProperties.min(tr("Kernel")), multi=True, ).run() @@ -58,7 +50,7 @@ def ask_for_bootloader(preset: Bootloader | None) -> Bootloader | None: if not SysInfo.has_uefi(): options = [Bootloader.Grub, Bootloader.Limine] default = Bootloader.Grub - header = str(_("UEFI is not detected and some options are disabled")) + header = tr("UEFI is not detected and some options are disabled") else: options = [b for b in Bootloader] default = Bootloader.Systemd @@ -73,7 +65,7 @@ def ask_for_bootloader(preset: Bootloader | None) -> Bootloader | None: group, header=header, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Bootloader"))), + frame=FrameProperties.min(tr("Bootloader")), allow_skip=True, ).run() @@ -87,7 +79,7 @@ def ask_for_bootloader(preset: Bootloader | None) -> Bootloader | None: def ask_for_uki(preset: bool = True) -> bool: - prompt = str(_("Would you like to use unified kernel images?")) + "\n" + prompt = tr("Would you like to use unified kernel images?") + "\n" group = MenuItemGroup.yes_no() group.set_focus_by_value(preset) @@ -130,11 +122,11 @@ def select_driver(options: list[GfxDriver] = [], preset: GfxDriver | None = None header = "" if SysInfo.has_amd_graphics(): - header += str(_("For the best compatibility with your AMD hardware, you may want to use either the all open-source or AMD / ATI options.")) + "\n" + header += tr("For the best compatibility with your AMD hardware, you may want to use either the all open-source or AMD / ATI options.") + "\n" if SysInfo.has_intel_graphics(): - header += str(_("For the best compatibility with your Intel hardware, you may want to use either the all open-source or Intel options.\n")) + header += tr("For the best compatibility with your Intel hardware, you may want to use either the all open-source or Intel options.\n") if SysInfo.has_nvidia_graphics(): - header += str(_("For the best compatibility with your Nvidia hardware, you may want to use the Nvidia proprietary driver.\n")) + header += tr("For the best compatibility with your Nvidia hardware, you may want to use the Nvidia proprietary driver.\n") result = SelectMenu[GfxDriver]( group, @@ -143,7 +135,7 @@ def select_driver(options: list[GfxDriver] = [], preset: GfxDriver | None = None allow_reset=True, preview_size="auto", preview_style=PreviewStyle.BOTTOM, - preview_frame=FrameProperties(str(_("Info")), h_frame_style=FrameStyle.MIN), + preview_frame=FrameProperties(tr("Info"), h_frame_style=FrameStyle.MIN), ).run() match result.type_: @@ -161,7 +153,7 @@ def ask_for_swap(preset: bool = True) -> bool: else: default_item = MenuItem.no() - prompt = str(_("Would you like to use swap on zram?")) + "\n" + prompt = tr("Would you like to use swap on zram?") + "\n" group = MenuItemGroup.yes_no() group.set_focus_by_value(default_item) diff --git a/archinstall/lib/locale/locale_menu.py b/archinstall/lib/locale/locale_menu.py index 867240b06d..291d4eaeb1 100644 --- a/archinstall/lib/locale/locale_menu.py +++ b/archinstall/lib/locale/locale_menu.py @@ -1,5 +1,6 @@ -from typing import TYPE_CHECKING, override +from typing import override +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -9,13 +10,6 @@ from ..models.locale import LocaleConfiguration from .utils import list_keyboard_languages, list_locales, set_kb_layout -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class LocaleMenu(AbstractSubMenu[LocaleConfiguration]): def __init__( @@ -35,21 +29,21 @@ def __init__( def _define_menu_options(self) -> list[MenuItem]: return [ MenuItem( - text=str(_("Keyboard layout")), + text=tr("Keyboard layout"), action=self._select_kb_layout, value=self._locale_conf.kb_layout, preview_action=self._prev_locale, key="kb_layout", ), MenuItem( - text=str(_("Locale language")), + text=tr("Locale language"), action=select_locale_lang, value=self._locale_conf.sys_lang, preview_action=self._prev_locale, key="sys_lang", ), MenuItem( - text=str(_("Locale encoding")), + text=tr("Locale encoding"), action=select_locale_enc, value=self._locale_conf.sys_enc, preview_action=self._prev_locale, @@ -88,7 +82,7 @@ def select_locale_lang(preset: str | None = None) -> str | None: result = SelectMenu[str]( group, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Locale language"))), + frame=FrameProperties.min(tr("Locale language")), allow_skip=True, ).run() @@ -112,7 +106,7 @@ def select_locale_enc(preset: str | None = None) -> str | None: result = SelectMenu[str]( group, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Locale encoding"))), + frame=FrameProperties.min(tr("Locale encoding")), allow_skip=True, ).run() @@ -144,7 +138,7 @@ def select_kb_layout(preset: str | None = None) -> str | None: result = SelectMenu[str]( group, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Keyboard layout"))), + frame=FrameProperties.min(tr("Keyboard layout")), allow_skip=True, ).run() diff --git a/archinstall/lib/menu/abstract_menu.py b/archinstall/lib/menu/abstract_menu.py index 2abbedf7cf..de7799eafb 100644 --- a/archinstall/lib/menu/abstract_menu.py +++ b/archinstall/lib/menu/abstract_menu.py @@ -1,8 +1,8 @@ from __future__ import annotations -from collections.abc import Callable -from typing import TYPE_CHECKING, Any, Self +from typing import Any, Self +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu, Tui from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -10,12 +10,6 @@ from ..output import error -if TYPE_CHECKING: - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - - CONFIG_KEY = "__config__" @@ -134,7 +128,7 @@ def __init__( auto_cursor: bool = True, allow_reset: bool = False, ): - back_text = f"{Chars.Right_arrow} " + str(_("Back")) + back_text = f"{Chars.Right_arrow} " + tr("Back") item_group.add_item(MenuItem(text=back_text)) super().__init__( diff --git a/archinstall/lib/menu/list_manager.py b/archinstall/lib/menu/list_manager.py index 3618167e76..637e7fa551 100644 --- a/archinstall/lib/menu/list_manager.py +++ b/archinstall/lib/menu/list_manager.py @@ -1,19 +1,13 @@ import copy -from typing import TYPE_CHECKING, cast +from typing import cast from archinstall.lib.menu.menu_helper import MenuHelper +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType from archinstall.tui.types import Alignment -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class ListManager[ValueT]: def __init__( @@ -43,8 +37,8 @@ def __init__( self._prompt = prompt self._separator = "" - self._confirm_action = str(_("Confirm and exit")) - self._cancel_action = str(_("Cancel")) + self._confirm_action = tr("Confirm and exit") + self._cancel_action = tr("Cancel") self._terminate_actions = [self._confirm_action, self._cancel_action] self._base_actions = base_actions diff --git a/archinstall/lib/mirrors.py b/archinstall/lib/mirrors.py index ff9c13d439..a2c166d31e 100644 --- a/archinstall/lib/mirrors.py +++ b/archinstall/lib/mirrors.py @@ -1,8 +1,9 @@ import time import urllib.parse from pathlib import Path -from typing import TYPE_CHECKING, override +from typing import override +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import EditMenu, SelectMenu, Tui from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -24,20 +25,13 @@ from .networking import fetch_data_from_url from .output import FormattedOutput, debug -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class CustomMirrorRepositoriesList(ListManager[CustomRepository]): def __init__(self, custom_repositories: list[CustomRepository]): self._actions = [ - str(_("Add a custom repository")), - str(_("Change custom repository")), - str(_("Delete custom repository")), + tr("Add a custom repository"), + tr("Change custom repository"), + tr("Delete custom repository"), ] super().__init__( @@ -75,7 +69,7 @@ def handle_action( def _add_custom_repository(self, preset: CustomRepository | None = None) -> CustomRepository | None: edit_result = EditMenu( - str(_("Repository name")), + tr("Repository name"), alignment=Alignment.CENTER, allow_skip=True, default_text=preset.name if preset else None, @@ -89,10 +83,10 @@ def _add_custom_repository(self, preset: CustomRepository | None = None) -> Cust case _: raise ValueError("Unhandled return type") - header = f"{_('Name')}: {name}" + header = f"{tr('Name')}: {name}" edit_result = EditMenu( - str(_("Url")), + tr("Url"), header=header, alignment=Alignment.CENTER, allow_skip=True, @@ -107,8 +101,8 @@ def _add_custom_repository(self, preset: CustomRepository | None = None) -> Cust case _: raise ValueError("Unhandled return type") - header += f"\n{_('Url')}: {url}\n" - prompt = f"{header}\n" + str(_("Select signature check")) + header += f"\n{tr('Url')}: {url}\n" + prompt = f"{header}\n" + tr("Select signature check") sign_chk_items = [MenuItem(s.value, value=s.value) for s in SignCheck] group = MenuItemGroup(sign_chk_items, sort_items=False) @@ -129,7 +123,7 @@ def _add_custom_repository(self, preset: CustomRepository | None = None) -> Cust case _: raise ValueError("Unhandled return type") - header += f"{_('Signature check')}: {sign_check.value}\n" + header += f"{tr('Signature check')}: {sign_check.value}\n" prompt = f"{header}\n" + "Select signature option" sign_opt_items = [MenuItem(s.value, value=s.value) for s in SignOption] @@ -157,9 +151,9 @@ def _add_custom_repository(self, preset: CustomRepository | None = None) -> Cust class CustomMirrorServersList(ListManager[CustomServer]): def __init__(self, custom_servers: list[CustomServer]): self._actions = [ - str(_("Add a custom server")), - str(_("Change custom server")), - str(_("Delete custom server")), + tr("Add a custom server"), + tr("Change custom server"), + tr("Delete custom server"), ] super().__init__( @@ -197,7 +191,7 @@ def handle_action( def _add_custom_server(self, preset: CustomServer | None = None) -> CustomServer | None: edit_result = EditMenu( - str(_("Server url")), + tr("Server url"), alignment=Alignment.CENTER, allow_skip=True, default_text=preset.url if preset else None, @@ -235,28 +229,28 @@ def __init__( def _define_menu_options(self) -> list[MenuItem]: return [ MenuItem( - text=str(_("Select regions")), + text=tr("Select regions"), action=select_mirror_regions, value=self._mirror_config.mirror_regions, preview_action=self._prev_regions, key="mirror_regions", ), MenuItem( - text=str(_("Add custom servers")), + text=tr("Add custom servers"), action=add_custom_mirror_servers, value=self._mirror_config.custom_servers, preview_action=self._prev_custom_servers, key="custom_servers", ), MenuItem( - text=str(_("Optional repositories")), + text=tr("Optional repositories"), action=select_optional_repositories, value=[], preview_action=self._prev_additional_repos, key="optional_repositories", ), MenuItem( - text=str(_("Add custom repository")), + text=tr("Add custom repository"), action=select_custom_mirror, value=self._mirror_config.custom_repositories, preview_action=self._prev_custom_mirror, @@ -282,7 +276,7 @@ def _prev_additional_repos(self, item: MenuItem) -> str | None: if item.value: repositories: list[Repository] = item.value repos = ", ".join([repo.value for repo in repositories]) - return f"{_('Additional repositories')}: {repos}" + return f"{tr('Additional repositories')}: {repos}" return None def _prev_custom_mirror(self, item: MenuItem) -> str | None: @@ -308,7 +302,7 @@ def run(self) -> MirrorConfiguration: def select_mirror_regions(preset: list[MirrorRegion]) -> list[MirrorRegion]: - Tui.print(str(_("Loading mirror regions...")), clear_screen=True) + Tui.print(tr("Loading mirror regions..."), clear_screen=True) mirror_list_handler.load_mirrors() available_regions = mirror_list_handler.get_mirror_regions() @@ -326,7 +320,7 @@ def select_mirror_regions(preset: list[MirrorRegion]) -> list[MirrorRegion]: result = SelectMenu[MirrorRegion]( group, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Mirror regions"))), + frame=FrameProperties.min(tr("Mirror regions")), allow_reset=True, allow_skip=True, multi=True, diff --git a/archinstall/lib/models/device_model.py b/archinstall/lib/models/device_model.py index 13f12b3ffa..a271f92b88 100644 --- a/archinstall/lib/models/device_model.py +++ b/archinstall/lib/models/device_model.py @@ -5,24 +5,18 @@ from dataclasses import dataclass, field from enum import Enum from pathlib import Path -from typing import TYPE_CHECKING, NotRequired, TypedDict, override +from typing import NotRequired, TypedDict, override import parted from parted import Disk, Geometry, Partition from pydantic import BaseModel, Field, ValidationInfo, field_serializer, field_validator +from archinstall.lib.translationhandler import tr + from ..hardware import SysInfo from ..models.users import Password from ..output import debug -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - - ENC_IDENTIFIER = "ainst" @@ -34,11 +28,11 @@ class DiskLayoutType(Enum): def display_msg(self) -> str: match self: case DiskLayoutType.Default: - return str(_("Use a best-effort default partition layout")) + return tr("Use a best-effort default partition layout") case DiskLayoutType.Manual: - return str(_("Manual Partitioning")) + return tr("Manual Partitioning") case DiskLayoutType.Pre_mount: - return str(_("Pre-mounted configuration")) + return tr("Pre-mounted configuration") class _DiskLayoutConfigurationSerialization(TypedDict): @@ -488,7 +482,7 @@ def table_data(self) -> dict[str, str]: part_info = { "Name": self.name, "Type": self.type.value, - "Filesystem": self.fs_type.value if self.fs_type else str(_("Unknown")), + "Filesystem": self.fs_type.value if self.fs_type else tr("Unknown"), "Path": str(self.path), "Start": self.start.format_size(Unit.sectors, self.sector_size, include_unit=False), "End": end.format_size(Unit.sectors, self.sector_size, include_unit=False), @@ -1044,7 +1038,7 @@ class LvmLayoutType(Enum): def display_msg(self) -> str: match self: case LvmLayoutType.Default: - return str(_("Default layout")) + return tr("Default layout") # case LvmLayoutType.Manual: # return str(_('Manual configuration')) @@ -1381,10 +1375,10 @@ class EncryptionType(Enum): @classmethod def _encryption_type_mapper(cls) -> dict[str, "EncryptionType"]: return { - str(_("No Encryption")): EncryptionType.NoEncryption, - str(_("LUKS")): EncryptionType.Luks, - str(_("LVM on LUKS")): EncryptionType.LvmOnLuks, - str(_("LUKS on LVM")): EncryptionType.LuksOnLvm, + tr("No Encryption"): EncryptionType.NoEncryption, + tr("LUKS"): EncryptionType.Luks, + tr("LVM on LUKS"): EncryptionType.LvmOnLuks, + tr("LUKS on LVM"): EncryptionType.LuksOnLvm, } @classmethod diff --git a/archinstall/lib/models/locale.py b/archinstall/lib/models/locale.py index 75cddd2d25..4d9d52cd61 100644 --- a/archinstall/lib/models/locale.py +++ b/archinstall/lib/models/locale.py @@ -1,14 +1,9 @@ from dataclasses import dataclass -from typing import TYPE_CHECKING, Any +from typing import Any -from ..locale.utils import get_kb_layout - -if TYPE_CHECKING: - from collections.abc import Callable +from archinstall.lib.translationhandler import tr - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] +from ..locale.utils import get_kb_layout @dataclass @@ -32,9 +27,9 @@ def json(self) -> dict[str, str]: } def preview(self) -> str: - output = "{}: {}\n".format(str(_("Keyboard layout")), self.kb_layout) - output += "{}: {}\n".format(str(_("Locale language")), self.sys_lang) - output += "{}: {}".format(str(_("Locale encoding")), self.sys_enc) + output = "{}: {}\n".format(tr("Keyboard layout"), self.kb_layout) + output += "{}: {}\n".format(tr("Locale language"), self.sys_lang) + output += "{}: {}".format(tr("Locale encoding"), self.sys_enc) return output @classmethod diff --git a/archinstall/lib/models/mirrors.py b/archinstall/lib/models/mirrors.py index 2af0515156..b82b45c168 100644 --- a/archinstall/lib/models/mirrors.py +++ b/archinstall/lib/models/mirrors.py @@ -5,7 +5,7 @@ import urllib.request from dataclasses import dataclass, field from enum import Enum -from typing import TYPE_CHECKING, Any, TypedDict, override +from typing import Any, TypedDict, override from pydantic import BaseModel, field_validator, model_validator @@ -13,13 +13,6 @@ from ..networking import DownloadTimer, ping from ..output import debug -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class MirrorStatusEntryV3(BaseModel): url: str diff --git a/archinstall/lib/models/network_configuration.py b/archinstall/lib/models/network_configuration.py index 5cd619a02e..c77247c312 100644 --- a/archinstall/lib/models/network_configuration.py +++ b/archinstall/lib/models/network_configuration.py @@ -4,15 +4,12 @@ from enum import Enum from typing import TYPE_CHECKING, NotRequired, TypedDict +from archinstall.lib.translationhandler import tr + from ..models.profile_model import ProfileConfiguration if TYPE_CHECKING: - from collections.abc import Callable - from archinstall.lib.installer import Installer - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] class NicType(Enum): @@ -23,11 +20,11 @@ class NicType(Enum): def display_msg(self) -> str: match self: case NicType.ISO: - return str(_("Copy ISO network configuration to installation")) + return tr("Copy ISO network configuration to installation") case NicType.NM: - return str(_("Use NetworkManager (necessary to configure internet graphically in GNOME and KDE Plasma)")) + return tr("Use NetworkManager (necessary to configure internet graphically in GNOME and KDE Plasma)") case NicType.MANUAL: - return str(_("Manual configuration")) + return tr("Manual configuration") class _NicSerialization(TypedDict): diff --git a/archinstall/lib/models/packages.py b/archinstall/lib/models/packages.py index cd2dcfe198..ec71ddef09 100644 --- a/archinstall/lib/models/packages.py +++ b/archinstall/lib/models/packages.py @@ -1,16 +1,11 @@ from dataclasses import dataclass, field from enum import Enum from functools import cached_property -from typing import TYPE_CHECKING, Any, override +from typing import Any, override from pydantic import BaseModel -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] +from archinstall.lib.translationhandler import tr class Repository(Enum): @@ -204,6 +199,6 @@ def from_available_packages( return pkg_groups def info(self) -> str: - output = str(_("Package group:")) + "\n - " + output = tr("Package group:") + "\n - " output += "\n - ".join(self.packages) return output diff --git a/archinstall/lib/models/users.py b/archinstall/lib/models/users.py index 64719a1eec..aab93f3e02 100644 --- a/archinstall/lib/models/users.py +++ b/archinstall/lib/models/users.py @@ -1,15 +1,10 @@ from dataclasses import dataclass, field from enum import Enum -from typing import TYPE_CHECKING, NotRequired, TypedDict, override +from typing import NotRequired, TypedDict, override -from ..crypt import crypt_yescrypt - -if TYPE_CHECKING: - from collections.abc import Callable +from archinstall.lib.translationhandler import tr - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] +from ..crypt import crypt_yescrypt class PasswordStrength(Enum): @@ -23,13 +18,13 @@ class PasswordStrength(Enum): def value(self) -> str: # pylint: disable=invalid-overridden-method match self: case PasswordStrength.VERY_WEAK: - return str(_("very weak")) + return tr("very weak") case PasswordStrength.WEAK: - return str(_("weak")) + return tr("weak") case PasswordStrength.MODERATE: - return str(_("moderate")) + return tr("moderate") case PasswordStrength.STRONG: - return str(_("strong")) + return tr("strong") def color(self) -> str: match self: diff --git a/archinstall/lib/pacman/__init__.py b/archinstall/lib/pacman/__init__.py index 4befba2814..ac62fe1a77 100644 --- a/archinstall/lib/pacman/__init__.py +++ b/archinstall/lib/pacman/__init__.py @@ -1,7 +1,8 @@ import time from collections.abc import Callable from pathlib import Path -from typing import TYPE_CHECKING + +from archinstall.lib.translationhandler import tr from ..exceptions import RequirementError from ..general import SysCommand @@ -9,11 +10,6 @@ from ..plugins import plugins from .config import PacmanConfig -if TYPE_CHECKING: - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class Pacman: def __init__(self, target: Path, silent: bool = False): @@ -31,14 +27,14 @@ def run(args: str, default_cmd: str = "pacman") -> SysCommand: pacman_db_lock = Path("/var/lib/pacman/db.lck") if pacman_db_lock.exists(): - warn(str(_("Pacman is already running, waiting maximum 10 minutes for it to terminate."))) + warn(tr("Pacman is already running, waiting maximum 10 minutes for it to terminate.")) started = time.time() while pacman_db_lock.exists(): time.sleep(0.25) if time.time() - started > (60 * 10): - error(str(_("Pre-existing pacman lock never exited. Please clean up any existing pacman sessions before using archinstall."))) + error(tr("Pre-existing pacman lock never exited. Please clean up any existing pacman sessions before using archinstall.")) exit(1) return SysCommand(f"{default_cmd} {args}") diff --git a/archinstall/lib/profile/profile_menu.py b/archinstall/lib/profile/profile_menu.py index 2c2c066ec5..9a2b699563 100644 --- a/archinstall/lib/profile/profile_menu.py +++ b/archinstall/lib/profile/profile_menu.py @@ -1,8 +1,9 @@ from __future__ import annotations -from typing import TYPE_CHECKING, override +from typing import override from archinstall.default_profiles.profile import GreeterType, Profile +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import SelectMenu from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -13,13 +14,6 @@ from ..menu.abstract_menu import AbstractSubMenu from ..models.profile_model import ProfileConfiguration -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class ProfileMenu(AbstractSubMenu[ProfileConfiguration]): def __init__( @@ -43,14 +37,14 @@ def __init__( def _define_menu_options(self) -> list[MenuItem]: return [ MenuItem( - text=str(_("Type")), + text=tr("Type"), action=self._select_profile, value=self._profile_config.profile, preview_action=self._preview_profile, key="profile", ), MenuItem( - text=str(_("Graphics driver")), + text=tr("Graphics driver"), action=self._select_gfx_driver, value=self._profile_config.gfx_driver if self._profile_config.profile and self._profile_config.profile.is_graphic_driver_supported() else None, preview_action=self._prev_gfx, @@ -59,7 +53,7 @@ def _define_menu_options(self) -> list[MenuItem]: key="gfx_driver", ), MenuItem( - text=str(_("Greeter")), + text=tr("Greeter"), action=lambda x: select_greeter(preset=x), value=self._profile_config.greeter if self._profile_config.profile and self._profile_config.profile.is_greeter_supported() else None, enabled=self._profile_config.profile.is_graphic_driver_supported() if self._profile_config.profile else False, @@ -107,8 +101,8 @@ def _select_gfx_driver(self, preset: GfxDriver | None = None) -> GfxDriver | Non if driver and "Sway" in profile.current_selection_names(): if driver.is_nvidia(): - header = str(_("The proprietary Nvidia driver is not supported by Sway.")) + "\n" - header += str(_("It is likely that you will run into issues, are you okay with that?")) + "\n" + header = tr("The proprietary Nvidia driver is not supported by Sway.") + "\n" + header += tr("It is likely that you will run into issues, are you okay with that?") + "\n" group = MenuItemGroup.yes_no() group.focus_item = MenuItem.no() @@ -137,7 +131,7 @@ def _prev_gfx(self, item: MenuItem) -> str | None: def _prev_greeter(self, item: MenuItem) -> str | None: if item.value: - return f"{_('Greeter')}: {item.value.value}" + return f"{tr('Greeter')}: {item.value.value}" return None def _preview_profile(self, item: MenuItem) -> str | None: @@ -146,7 +140,7 @@ def _preview_profile(self, item: MenuItem) -> str | None: if profile: if (sub_profiles := profile.current_selection) is not None: - text += str(_("Selected profiles: ")) + text += tr("Selected profiles: ") text += ", ".join([p.name for p in sub_profiles]) + "\n" if packages := profile.packages_text(include_sub_packages=True): @@ -178,7 +172,7 @@ def select_greeter( result = SelectMenu[GreeterType]( group, allow_skip=True, - frame=FrameProperties.min(str(_("Greeter"))), + frame=FrameProperties.min(tr("Greeter")), alignment=Alignment.CENTER, ).run() @@ -203,7 +197,7 @@ def select_profile( top_level_profiles = profile_handler.get_top_level_profiles() if header is None: - header = str(_("This is a list of pre-programmed default_profiles")) + "\n" + header = tr("This is a list of pre-programmed default_profiles") + "\n" items = [MenuItem(p.name, value=p) for p in top_level_profiles] group = MenuItemGroup(items, sort_items=True) @@ -215,7 +209,7 @@ def select_profile( allow_reset=allow_reset, allow_skip=True, alignment=Alignment.CENTER, - frame=FrameProperties.min(str(_("Main profile"))), + frame=FrameProperties.min(tr("Main profile")), ).run() match result.type_: diff --git a/archinstall/lib/profile/profiles_handler.py b/archinstall/lib/profile/profiles_handler.py index 514df8b09d..d466d6f8f4 100644 --- a/archinstall/lib/profile/profiles_handler.py +++ b/archinstall/lib/profile/profiles_handler.py @@ -10,6 +10,8 @@ from types import ModuleType from typing import TYPE_CHECKING, NotRequired, TypedDict +from archinstall.lib.translationhandler import tr + from ...default_profiles.profile import GreeterType, Profile from ..hardware import GfxDriver from ..models.profile_model import ProfileConfiguration @@ -17,14 +19,8 @@ from ..output import debug, error, info if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - from ..installer import Installer - _: Callable[[str], DeferredTranslation] - class ProfileSerialization(TypedDict): main: NotRequired[str] @@ -274,7 +270,7 @@ def _import_profile_from_url(self, url: str) -> None: self.remove_custom_profiles(profiles) self.add_custom_profiles(profiles) except ValueError: - err = str(_("Unable to fetch profile from specified url: {}")).format(url) + err = tr("Unable to fetch profile from specified url: {}").format(url) error(err) def _load_profile_class(self, module: ModuleType) -> list[Profile]: @@ -305,7 +301,7 @@ def _verify_unique_profile_names(self, profiles: list[Profile]) -> None: duplicates = [x for x in counter.items() if x[1] != 1] if len(duplicates) > 0: - err = str(_("Profiles must have unique name, but profile definitions with duplicate name found: {}")).format(duplicates[0][0]) + err = tr("Profiles must have unique name, but profile definitions with duplicate name found: {}").format(duplicates[0][0]) error(err) sys.exit(1) diff --git a/archinstall/lib/translationhandler.py b/archinstall/lib/translationhandler.py index 441b850fd2..f557b82389 100644 --- a/archinstall/lib/translationhandler.py +++ b/archinstall/lib/translationhandler.py @@ -161,7 +161,7 @@ def _provided_translations(self) -> list[str]: return translation_files -class DeferredTranslation: +class _DeferredTranslation: def __init__(self, message: str): self.message = message @@ -171,7 +171,7 @@ def __len__(self) -> int: @override def __str__(self) -> str: translate = _ - if translate is DeferredTranslation: + if translate is _DeferredTranslation: return self.message return translate(self.message) @@ -181,17 +181,19 @@ def __lt__(self, other) -> bool: def __gt__(self, other) -> bool: return self.message > other - def __add__(self, other) -> DeferredTranslation: + def __add__(self, other) -> _DeferredTranslation: if isinstance(other, str): - other = DeferredTranslation(other) + other = _DeferredTranslation(other) concat = self.message + other.message - return DeferredTranslation(concat) + return _DeferredTranslation(concat) - def format(self, *args) -> str: - return self.message.format(*args) +def tr(message: str) -> str: + return str(_DeferredTranslation(message)) + + +builtins._ = _DeferredTranslation # type: ignore[attr-defined] -builtins._ = DeferredTranslation # type: ignore[attr-defined] translation_handler = TranslationHandler() diff --git a/archinstall/lib/utils/util.py b/archinstall/lib/utils/util.py index 451bf0fe2a..3ef7f2c133 100644 --- a/archinstall/lib/utils/util.py +++ b/archinstall/lib/utils/util.py @@ -1,19 +1,12 @@ from pathlib import Path -from typing import TYPE_CHECKING +from archinstall.lib.translationhandler import tr from archinstall.tui.curses_menu import EditMenu from archinstall.tui.types import Alignment from ..models.users import Password from ..output import FormattedOutput -if TYPE_CHECKING: - from collections.abc import Callable - - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - def get_password( text: str, @@ -49,12 +42,12 @@ def get_password( return password if header is not None: - confirmation_header = f"{header}{_('Password')}: {password.hidden()}\n" + confirmation_header = f"{header}{tr('Password')}: {password.hidden()}\n" else: - confirmation_header = f"{_('Password')}: {password.hidden()}\n" + confirmation_header = f"{tr('Password')}: {password.hidden()}\n" result = EditMenu( - str(_("Confirm password")), + tr("Confirm password"), header=confirmation_header, alignment=Alignment.CENTER, allow_skip=False, @@ -64,7 +57,7 @@ def get_password( if password._plaintext == result.text(): return password - failure = str(_("The confirmation password did not match, please try again")) + failure = tr("The confirmation password did not match, please try again") def prompt_dir( @@ -80,7 +73,7 @@ def validate_path(path: str) -> str | None: if dest_path.exists() and dest_path.is_dir(): return None - return str(_("Not a valid directory")) + return tr("Not a valid directory") if validate: validate_func = validate_path diff --git a/archinstall/tui/curses_menu.py b/archinstall/tui/curses_menu.py index 2ad43c6f57..4ae3afe203 100644 --- a/archinstall/tui/curses_menu.py +++ b/archinstall/tui/curses_menu.py @@ -9,7 +9,9 @@ from curses.ascii import isprint from curses.textpad import Textbox from types import FrameType, TracebackType -from typing import TYPE_CHECKING, Literal, override +from typing import Literal, override + +from archinstall.lib.translationhandler import tr from ..lib.output import debug from .help import Help @@ -29,11 +31,6 @@ _FrameDim, ) -if TYPE_CHECKING: - from archinstall.lib.translationhandler import DeferredTranslation - - _: Callable[[str], DeferredTranslation] - class AbstractCurses[ValueT](metaclass=ABCMeta): def __init__(self) -> None: @@ -66,7 +63,7 @@ def _set_help_viewport(self) -> "Viewport": height, x_start, int((max_height / 2) - height / 2), - frame=FrameProperties.min(str(_("Archinstall help"))), + frame=FrameProperties.min(tr("Archinstall help")), ) def _confirm_interrupt(self, warning: str) -> bool: @@ -87,7 +84,7 @@ def _confirm_interrupt(self, warning: str) -> bool: return False def help_entry(self) -> ViewportEntry: - return ViewportEntry(str(_("Press Ctrl+h for help")), 0, 0, STYLE.NORMAL) + return ViewportEntry(tr("Press Ctrl+h for help"), 0, 0, STYLE.NORMAL) def _show_help(self) -> None: if not self._help_window: @@ -489,7 +486,7 @@ def __init__( self._hide_input = hide_input if self._interrupt_warning is None: - self._interrupt_warning = str(_("Are you sure you want to reset this setting?")) + "\n" + self._interrupt_warning = tr("Are you sure you want to reset this setting?") + "\n" title = f"* {title}" if not self._allow_skip else title self._frame = FrameProperties(title, FrameStyle.MAX) @@ -500,7 +497,7 @@ def __init__( self._info_vp: Viewport | None = None self._set_default_info = True - self._only_ascii_text = ViewportEntry(str(_("Only ASCII characters are supported")), 0, 0, STYLE.NORMAL) + self._only_ascii_text = ViewportEntry(tr("Only ASCII characters are supported"), 0, 0, STYLE.NORMAL) self._init_viewports() @@ -726,7 +723,7 @@ def __init__( self._header_entries = self.get_header_entries(header) if self._interrupt_warning is None: - self._interrupt_warning = str(_("Are you sure you want to reset this setting?")) + "\n" + self._interrupt_warning = tr("Are you sure you want to reset this setting?") + "\n" if self._orientation == Orientation.HORIZONTAL: self._horizontal_cols = columns diff --git a/archinstall/tui/help.py b/archinstall/tui/help.py index 955099dfe2..cffb2b9948 100644 --- a/archinstall/tui/help.py +++ b/archinstall/tui/help.py @@ -1,12 +1,7 @@ -from collections.abc import Callable from dataclasses import dataclass, field from enum import Enum -from typing import TYPE_CHECKING -from archinstall.lib.translationhandler import DeferredTranslation - -if TYPE_CHECKING: - _: Callable[[str], DeferredTranslation] +from archinstall.lib.translationhandler import tr class HelpTextGroupId(Enum): @@ -45,8 +40,8 @@ def general() -> HelpGroup: return HelpGroup( group_id=HelpTextGroupId.GENERAL, group_entries=[ - HelpText(str(_("Show help")), ["Ctrl+h"]), - HelpText(str(_("Exit help")), ["Esc"]), + HelpText(tr("Show help"), ["Ctrl+h"]), + HelpText(tr("Exit help"), ["Esc"]), ], ) @@ -55,13 +50,13 @@ def navigation() -> HelpGroup: return HelpGroup( group_id=HelpTextGroupId.NAVIGATION, group_entries=[ - HelpText(str(_("Preview scroll up")), ["PgUp"]), - HelpText(str(_("Preview scroll down")), ["PgDown"]), - HelpText(str(_("Move up")), ["k", "↑"]), - HelpText(str(_("Move down")), ["j", "↓"]), - HelpText(str(_("Move right")), ["l", "→"]), - HelpText(str(_("Move left")), ["h", "←"]), - HelpText(str(_("Jump to entry")), ["1..9"]), + HelpText(tr("Preview scroll up"), ["PgUp"]), + HelpText(tr("Preview scroll down"), ["PgDown"]), + HelpText(tr("Move up"), ["k", "↑"]), + HelpText(tr("Move down"), ["j", "↓"]), + HelpText(tr("Move right"), ["l", "→"]), + HelpText(tr("Move left"), ["h", "←"]), + HelpText(tr("Jump to entry"), ["1..9"]), ], ) @@ -70,12 +65,12 @@ def selection() -> HelpGroup: return HelpGroup( group_id=HelpTextGroupId.SELECTION, group_entries=[ - HelpText(str(_("Skip selection (if available)")), ["Esc"]), - HelpText(str(_("Reset selection (if available)")), ["Ctrl+c"]), - HelpText(str(_("Select on single select")), ["Enter"]), - HelpText(str(_("Select on multi select")), ["Space", "Tab"]), - HelpText(str(_("Reset")), ["Ctrl-C"]), - HelpText(str(_("Skip selection menu")), ["Esc"]), + HelpText(tr("Skip selection (if available)"), ["Esc"]), + HelpText(tr("Reset selection (if available)"), ["Ctrl+c"]), + HelpText(tr("Select on single select"), ["Enter"]), + HelpText(tr("Select on multi select"), ["Space", "Tab"]), + HelpText(tr("Reset"), ["Ctrl-C"]), + HelpText(tr("Skip selection menu"), ["Esc"]), ], ) @@ -84,8 +79,8 @@ def search() -> HelpGroup: return HelpGroup( group_id=HelpTextGroupId.SEARCH, group_entries=[ - HelpText(str(_("Start search mode")), ["/"]), - HelpText(str(_("Exit search mode")), ["Esc"]), + HelpText(tr("Start search mode"), ["/"]), + HelpText(tr("Exit search mode"), ["Esc"]), ], ) diff --git a/archinstall/tui/menu_item.py b/archinstall/tui/menu_item.py index 594861768f..77844c3d79 100644 --- a/archinstall/tui/menu_item.py +++ b/archinstall/tui/menu_item.py @@ -3,14 +3,11 @@ from collections.abc import Callable from dataclasses import dataclass, field from functools import cached_property -from typing import TYPE_CHECKING, Any, ClassVar +from typing import Any, ClassVar -from ..lib.utils.unicode import unicode_ljust - -if TYPE_CHECKING: - from archinstall.lib.translationhandler import DeferredTranslation +from archinstall.lib.translationhandler import tr - _: Callable[[str], DeferredTranslation] +from ..lib.utils.unicode import unicode_ljust @dataclass @@ -37,14 +34,14 @@ def get_value(self) -> Any: @classmethod def yes(cls) -> "MenuItem": if cls._yes is None: - cls._yes = cls(str(_("Yes")), value=True) + cls._yes = cls(tr("Yes"), value=True) return cls._yes @classmethod def no(cls) -> "MenuItem": if cls._no is None: - cls._no = cls(str(_("No")), value=True) + cls._no = cls(tr("No"), value=True) return cls._no @@ -207,7 +204,7 @@ def get_item_text(self, item: MenuItem) -> str: def _default_suffix(self, item: MenuItem) -> str: if self.default_item == item: - return str(_(" (default)")) + return tr(" (default)") return "" @cached_property