Simplify translating of strings (#3479)

* Simplify translation fucntion

* Simplify translation fucntion
This commit is contained in:
Daniel Girtler 2025-05-19 22:33:02 +10:00 committed by GitHub
parent 790a7a2be9
commit 57bd2451e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 398 additions and 623 deletions

View File

@ -5,7 +5,6 @@ import os
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.hardware import SysInfo
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",

View File

@ -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 @@ class HyprlandProfile(XorgProfile):
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 @@ class HyprlandProfile(XorgProfile):
group,
header=header,
allow_skip=False,
frame=FrameProperties.min(str(_("Seat access"))),
frame=FrameProperties.min(tr("Seat access")),
alignment=Alignment.CENTER,
).run()

View File

@ -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 @@ class LabwcProfile(XorgProfile):
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 @@ class LabwcProfile(XorgProfile):
group,
header=header,
allow_skip=False,
frame=FrameProperties.min(str(_("Seat access"))),
frame=FrameProperties.min(tr("Seat access")),
alignment=Alignment.CENTER,
).run()

View File

@ -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 @@ class NiriProfile(XorgProfile):
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 @@ class NiriProfile(XorgProfile):
group,
header=header,
allow_skip=False,
frame=FrameProperties.min(str(_("Seat access"))),
frame=FrameProperties.min(tr("Seat access")),
alignment=Alignment.CENTER,
).run()

View File

@ -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 @@ class SwayProfile(XorgProfile):
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 @@ class SwayProfile(XorgProfile):
group,
header=header,
allow_skip=False,
frame=FrameProperties.min(str(_("Seat access"))),
frame=FrameProperties.min(tr("Seat access")),
alignment=Alignment.CENTER,
).run()

View File

@ -4,15 +4,11 @@ import sys
from enum import Enum, auto
from typing import TYPE_CHECKING
from archinstall.lib.translationhandler import tr
if TYPE_CHECKING:
from collections.abc import Callable
from archinstall.lib.translationhandler import DeferredTranslation
from ..lib.installer import Installer
_: Callable[[str], DeferredTranslation]
class ProfileType(Enum):
# top level default_profiles
@ -200,7 +196,7 @@ class Profile:
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"

View File

@ -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 @@ class XorgProfile(Profile):
@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}"

View File

@ -7,7 +7,7 @@ from argparse import ArgumentParser, Namespace
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.models.users import Password, User
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:
@ -429,7 +422,7 @@ class ArchConfigHandler:
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}")
@ -439,10 +432,10 @@ class ArchConfigHandler:
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,

View File

@ -2,8 +2,8 @@ import json
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 .output import debug, warn
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 @@ class ConfigurationOutput:
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 @@ class ConfigurationOutput:
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 save_config(config: ArchConfig) -> 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 save_config(config: ArchConfig) -> 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 save_config(config: ArchConfig) -> 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 save_config(config: ArchConfig) -> 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 save_config(config: ArchConfig) -> 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 save_config(config: ArchConfig) -> 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,
)

View File

@ -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 @@ class DiskLayoutConfigurationMenu(AbstractSubMenu[DiskLayoutConfiguration]):
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 @@ class DiskLayoutConfigurationMenu(AbstractSubMenu[DiskLayoutConfiguration]):
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 @@ class DiskLayoutConfigurationMenu(AbstractSubMenu[DiskLayoutConfiguration]):
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 @@ class DiskLayoutConfigurationMenu(AbstractSubMenu[DiskLayoutConfiguration]):
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

View File

@ -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 @@ from archinstall.lib.models.device_model import (
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 ..output import FormattedOutput
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 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
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 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
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 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
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 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
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 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
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 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
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 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
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 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
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 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
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()

View File

@ -2,8 +2,8 @@ from __future__ import annotations
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 ..models.device_model import (
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 @@ class FilesystemHandler:
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:

View File

@ -2,7 +2,7 @@ from __future__ import annotations
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 @@ from archinstall.lib.models.device_model import (
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 ..output import FormattedOutput
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 @@ class PartitioningList(ListManager[DiskSegment]):
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 @@ class PartitioningList(ListManager[DiskSegment]):
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 @@ class PartitioningList(ListManager[DiskSegment]):
)
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 @@ class PartitioningList(ListManager[DiskSegment]):
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 @@ class PartitioningList(ListManager[DiskSegment]):
# 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 @@ class PartitioningList(ListManager[DiskSegment]):
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 @@ class PartitioningList(ListManager[DiskSegment]):
group,
header=prompt,
alignment=Alignment.CENTER,
frame=FrameProperties.min(str(_("Filesystem"))),
frame=FrameProperties.min(tr("Filesystem")),
allow_skip=False,
).run()
@ -473,26 +467,26 @@ class PartitioningList(ListManager[DiskSegment]):
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 @@ class PartitioningList(ListManager[DiskSegment]):
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(),

View File

@ -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 archinstall.tui.types import Alignment
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 @@ class SubvolumeMenu(ListManager[SubvolumeModification]):
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 @@ class SubvolumeMenu(ListManager[SubvolumeModification]):
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 @@ class SubvolumeMenu(ListManager[SubvolumeModification]):
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,

View File

@ -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.profile_model import ProfileConfiguration
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 @@ class GlobalMenu(AbstractMenu[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 @@ class GlobalMenu(AbstractMenu[None]):
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 @@ class GlobalMenu(AbstractMenu[None]):
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 @@ class GlobalMenu(AbstractMenu[None]):
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 @@ class GlobalMenu(AbstractMenu[None]):
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 @@ class GlobalMenu(AbstractMenu[None]):
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 @@ class GlobalMenu(AbstractMenu[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 @@ class GlobalMenu(AbstractMenu[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 @@ class GlobalMenu(AbstractMenu[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 @@ class GlobalMenu(AbstractMenu[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 @@ class GlobalMenu(AbstractMenu[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 @@ class GlobalMenu(AbstractMenu[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 @@ class GlobalMenu(AbstractMenu[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 @@ class GlobalMenu(AbstractMenu[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}"

View File

@ -2,19 +2,12 @@ import os
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 @@ class GfxDriver(Enum):
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"

View File

@ -11,7 +11,7 @@ from collections.abc import Callable
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 @@ from archinstall.lib.models.device_model import (
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 .pacman.config import PacmanConfig
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 @@ class Installer:
# We avoid printing /mnt/<log path> 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 @@ class Installer:
"""
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 @@ class Installer:
# 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)

View File

@ -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 @@ from archinstall.lib.models.device_model import (
_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 archinstall.tui.types import Alignment, FrameProperties, Orientation, Previ
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)

View File

@ -2,10 +2,11 @@ from __future__ import annotations
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 ..models.packages import AvailablePackage, PackageGroup
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 add_number_of_parallel_downloads(preset: int | None = None) -> int | 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 add_number_of_parallel_downloads(preset: int | None = None) -> int | 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](

View File

@ -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 ..menu.list_manager import ListManager
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 @@ class UserList(ListManager[User]):
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 @@ class UserList(ListManager[User]):
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 @@ class UserList(ListManager[User]):
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()

View File

@ -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 ..menu.list_manager import ListManager
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 @@ class ManualNetworkConfig(ListManager[Nic]):
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 @@ class ManualNetworkConfig(ListManager[Nic]):
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 @@ class ManualNetworkConfig(ListManager[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 @@ class ManualNetworkConfig(ListManager[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 @@ class ManualNetworkConfig(ListManager[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)

View File

@ -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 archinstall.tui.types import Alignment, FrameProperties, FrameStyle, Orient
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)

View File

@ -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 ..menu.abstract_menu import AbstractSubMenu
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 @@ class LocaleMenu(AbstractSubMenu[LocaleConfiguration]):
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()

View File

@ -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 archinstall.tui.types import Chars, FrameProperties, FrameStyle, PreviewSty
from ..output import error
if TYPE_CHECKING:
from archinstall.lib.translationhandler import DeferredTranslation
_: Callable[[str], DeferredTranslation]
CONFIG_KEY = "__config__"
@ -134,7 +128,7 @@ class AbstractSubMenu[ValueT](AbstractMenu[ValueT]):
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__(

View File

@ -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 @@ class ListManager[ValueT]:
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

View File

@ -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 .models.packages import Repository
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 @@ class CustomMirrorRepositoriesList(ListManager[CustomRepository]):
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 @@ class CustomMirrorRepositoriesList(ListManager[CustomRepository]):
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 @@ class CustomMirrorRepositoriesList(ListManager[CustomRepository]):
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 @@ class CustomMirrorRepositoriesList(ListManager[CustomRepository]):
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 @@ class CustomMirrorRepositoriesList(ListManager[CustomRepository]):
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 @@ class CustomMirrorServersList(ListManager[CustomServer]):
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 @@ class MirrorMenu(AbstractSubMenu[MirrorConfiguration]):
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 @@ class MirrorMenu(AbstractSubMenu[MirrorConfiguration]):
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 @@ class MirrorMenu(AbstractSubMenu[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,

View File

@ -5,24 +5,18 @@ import uuid
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 @@ class _PartitionInfo:
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

View File

@ -1,15 +1,10 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any
from typing import Any
from archinstall.lib.translationhandler import tr
from ..locale.utils import get_kb_layout
if TYPE_CHECKING:
from collections.abc import Callable
from archinstall.lib.translationhandler import DeferredTranslation
_: Callable[[str], DeferredTranslation]
@dataclass
class LocaleConfiguration:
@ -32,9 +27,9 @@ class LocaleConfiguration:
}
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

View File

@ -5,7 +5,7 @@ import urllib.parse
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 ..models.packages import Repository
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

View File

@ -4,15 +4,12 @@ from dataclasses import dataclass, field
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):

View File

@ -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 @@ class PackageGroup:
return pkg_groups
def info(self) -> str:
output = str(_("Package group:")) + "\n - "
output = tr("Package group:") + "\n - "
output += "\n - ".join(self.packages)
return output

View File

@ -1,16 +1,11 @@
from dataclasses import dataclass, field
from enum import Enum
from typing import TYPE_CHECKING, NotRequired, TypedDict, override
from typing import NotRequired, TypedDict, override
from archinstall.lib.translationhandler import tr
from ..crypt import crypt_yescrypt
if TYPE_CHECKING:
from collections.abc import Callable
from archinstall.lib.translationhandler import DeferredTranslation
_: Callable[[str], DeferredTranslation]
class PasswordStrength(Enum):
VERY_WEAK = "very weak"
@ -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:

View File

@ -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 ..output import error, info, warn
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 @@ class Pacman:
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}")

View File

@ -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 ..interactions.system_conf import select_driver
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 @@ class ProfileMenu(AbstractSubMenu[ProfileConfiguration]):
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 @@ class ProfileMenu(AbstractSubMenu[ProfileConfiguration]):
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 @@ class ProfileMenu(AbstractSubMenu[ProfileConfiguration]):
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 @@ class ProfileMenu(AbstractSubMenu[ProfileConfiguration]):
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 @@ class ProfileMenu(AbstractSubMenu[ProfileConfiguration]):
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_:

View File

@ -10,6 +10,8 @@ from tempfile import NamedTemporaryFile
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 ..networking import fetch_data_from_url, list_interfaces
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 @@ class ProfileHandler:
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 @@ class ProfileHandler:
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)

View File

@ -161,7 +161,7 @@ class TranslationHandler:
return translation_files
class DeferredTranslation:
class _DeferredTranslation:
def __init__(self, message: str):
self.message = message
@ -171,7 +171,7 @@ class DeferredTranslation:
@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 @@ class DeferredTranslation:
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)
def format(self, *args) -> str:
return self.message.format(*args)
return _DeferredTranslation(concat)
builtins._ = DeferredTranslation # type: ignore[attr-defined]
def tr(message: str) -> str:
return str(_DeferredTranslation(message))
builtins._ = _DeferredTranslation # type: ignore[attr-defined]
translation_handler = TranslationHandler()

View File

@ -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 prompt_dir(
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

View File

@ -9,7 +9,9 @@ from collections.abc import Callable
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 @@ from .types import (
_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 @@ class AbstractCurses[ValueT](metaclass=ABCMeta):
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 @@ class AbstractCurses[ValueT](metaclass=ABCMeta):
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 @@ class EditMenu(AbstractCurses[str]):
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 @@ class EditMenu(AbstractCurses[str]):
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 @@ class SelectMenu[ValueT](AbstractCurses[ValueT]):
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

View File

@ -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 @@ class Help:
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 @@ class Help:
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 @@ class Help:
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 @@ class Help:
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"]),
],
)

View File

@ -3,15 +3,12 @@ from __future__ import annotations
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 archinstall.lib.translationhandler import tr
from ..lib.utils.unicode import unicode_ljust
if TYPE_CHECKING:
from archinstall.lib.translationhandler import DeferredTranslation
_: Callable[[str], DeferredTranslation]
@dataclass
class MenuItem:
@ -37,14 +34,14 @@ class MenuItem:
@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 @@ class MenuItemGroup:
def _default_suffix(self, item: MenuItem) -> str:
if self.default_item == item:
return str(_(" (default)"))
return tr(" (default)")
return ""
@cached_property