diff --git a/.github/workflows/iso-build.yaml b/.github/workflows/iso-build.yaml index dfaed9b8..83d58fd6 100644 --- a/.github/workflows/iso-build.yaml +++ b/.github/workflows/iso-build.yaml @@ -32,7 +32,7 @@ jobs: - run: cat /etc/os-release - run: pacman-key --init - run: pacman --noconfirm -Sy archlinux-keyring - - run: ./build_iso.sh + - run: ./test_tooling/mkarchiso/build_iso.sh - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: Arch Live ISO diff --git a/.github/workflows/translation-check.yaml b/.github/workflows/translation-check.yaml new file mode 100644 index 00000000..15be16cf --- /dev/null +++ b/.github/workflows/translation-check.yaml @@ -0,0 +1,22 @@ +name: Translation validation +on: + push: + paths: + - 'archinstall/**/*.py' + - 'archinstall/locales/**' + - '.github/workflows/translation-check.yaml' + pull_request: + paths: + - 'archinstall/**/*.py' + - 'archinstall/locales/**' + - '.github/workflows/translation-check.yaml' +jobs: + translations: + name: Validate translations + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - name: Install gettext + run: sudo apt-get update && sudo apt-get install -y gettext + - name: Run translation checks + run: bash archinstall/locales/locales_generator.sh check diff --git a/.github/workflows/uki-build.yaml b/.github/workflows/uki-build.yaml new file mode 100644 index 00000000..df41bc55 --- /dev/null +++ b/.github/workflows/uki-build.yaml @@ -0,0 +1,40 @@ +# This workflow will build an Arch Linux UKI file with the commit on it + +name: Build Arch UKI with ArchInstall Commit + +on: + push: + branches: + - master + - main # In case we adopt this convention in the future + pull_request: + paths-ignore: + - 'docs/**' + - '**.editorconfig' + - '**.gitignore' + - '**.md' + - 'LICENSE' + - 'PKGBUILD' + release: + types: + - created + +jobs: + build: + runs-on: ubuntu-latest + container: + image: archlinux/archlinux:latest + options: --privileged + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - run: pwd + - run: find . + - run: cat /etc/os-release + - run: pacman-key --init + - run: pacman --noconfirm -Sy archlinux-keyring + - run: pacman --noconfirm -Sy mkosi + - run: (cd test_tooling/mkosi/ && mkosi build -B) + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: Arch Live UKI + path: test_tooling/mkosi/mkosi.output/*.efi diff --git a/.gitignore b/.gitignore index 376bdbd5..54c865e0 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,7 @@ requirements.txt /cmd_output.txt node_modules/ uv.lock +test_tooling/mkosi/mkosi.output/*image* +test_tooling/mkosi/mkosi.cache/** +test_tooling/mkosi/mkosi.tools/** +test_tooling/mkosi/mkosi.tools.manifest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c573ae04..6ba223de 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ default_stages: ['pre-commit'] repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.12 + rev: v0.15.14 hooks: # fix unused imports and sort them - id: ruff @@ -41,6 +41,7 @@ repos: additional_dependencies: - pydantic - pytest + - hypothesis - cryptography - textual - repo: local diff --git a/archinstall/applications/audio.py b/archinstall/applications/audio.py index b749fe67..e5d79718 100644 --- a/archinstall/applications/audio.py +++ b/archinstall/applications/audio.py @@ -1,9 +1,9 @@ from typing import TYPE_CHECKING from archinstall.lib.hardware import SysInfo +from archinstall.lib.log import debug from archinstall.lib.models.application import Audio, AudioConfiguration from archinstall.lib.models.users import User -from archinstall.lib.output import debug if TYPE_CHECKING: from archinstall.lib.installer import Installer diff --git a/archinstall/applications/bluetooth.py b/archinstall/applications/bluetooth.py index a0ffbc75..6bd4999e 100644 --- a/archinstall/applications/bluetooth.py +++ b/archinstall/applications/bluetooth.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING -from archinstall.lib.output import debug +from archinstall.lib.log import debug if TYPE_CHECKING: from archinstall.lib.installer import Installer diff --git a/archinstall/applications/firewall.py b/archinstall/applications/firewall.py index e450dbc6..dadaa05b 100644 --- a/archinstall/applications/firewall.py +++ b/archinstall/applications/firewall.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING +from archinstall.lib.log import debug from archinstall.lib.models.application import Firewall, FirewallConfiguration -from archinstall.lib.output import debug if TYPE_CHECKING: from archinstall.lib.installer import Installer diff --git a/archinstall/applications/fonts.py b/archinstall/applications/fonts.py index 3fa54c67..73eb326e 100644 --- a/archinstall/applications/fonts.py +++ b/archinstall/applications/fonts.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING +from archinstall.lib.log import debug from archinstall.lib.models.application import FontsConfiguration -from archinstall.lib.output import debug if TYPE_CHECKING: from archinstall.lib.installer import Installer diff --git a/archinstall/applications/power_management.py b/archinstall/applications/power_management.py index b9f32b05..744411f3 100644 --- a/archinstall/applications/power_management.py +++ b/archinstall/applications/power_management.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING +from archinstall.lib.log import debug from archinstall.lib.models.application import PowerManagement, PowerManagementConfiguration -from archinstall.lib.output import debug if TYPE_CHECKING: from archinstall.lib.installer import Installer diff --git a/archinstall/applications/print_service.py b/archinstall/applications/print_service.py index 3e4913f0..fbe28f89 100644 --- a/archinstall/applications/print_service.py +++ b/archinstall/applications/print_service.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING -from archinstall.lib.output import debug +from archinstall.lib.log import debug if TYPE_CHECKING: from archinstall.lib.installer import Installer diff --git a/archinstall/default_profiles/desktop.py b/archinstall/default_profiles/desktop.py index daf70831..b70f9f11 100644 --- a/archinstall/default_profiles/desktop.py +++ b/archinstall/default_profiles/desktop.py @@ -1,8 +1,8 @@ from typing import TYPE_CHECKING, Self, override from archinstall.default_profiles.profile import DisplayServerType, GreeterType, Profile, ProfileType, SelectResult +from archinstall.lib.log import info from archinstall.lib.menu.helpers import Selection -from archinstall.lib.output import info from archinstall.lib.profile.profiles_handler import profile_handler from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType diff --git a/archinstall/default_profiles/desktops/niri.py b/archinstall/default_profiles/desktops/niri.py index 4d955fbf..d8db75f5 100644 --- a/archinstall/default_profiles/desktops/niri.py +++ b/archinstall/default_profiles/desktops/niri.py @@ -7,7 +7,7 @@ from archinstall.default_profiles.profile import CustomSetting, DisplayServerTyp class NiriProfile(Profile): def __init__(self) -> None: super().__init__( - 'Niri', + 'niri', ProfileType.WindowMgr, support_gfx_driver=True, display_server=DisplayServerType.Wayland, diff --git a/archinstall/default_profiles/desktops/niri_dms.py b/archinstall/default_profiles/desktops/niri_dms.py new file mode 100644 index 00000000..11f32e34 --- /dev/null +++ b/archinstall/default_profiles/desktops/niri_dms.py @@ -0,0 +1,66 @@ +import shutil +from pathlib import Path +from typing import TYPE_CHECKING, override + +from archinstall.default_profiles.profile import DisplayServerType, GreeterType, Profile, ProfileType + +if TYPE_CHECKING: + from archinstall.lib.installer import Installer + from archinstall.lib.models.users import User + + +_TERMINAL = 'alacritty' +_ASSETS_DIR = Path(__file__).parent / 'niri_dms_assets' + + +class NiriDmsProfile(Profile): + def __init__(self) -> None: + super().__init__( + 'niri - DankMaterialShell', + ProfileType.WindowMgr, + support_gfx_driver=True, + display_server=DisplayServerType.Wayland, + ) + + @property + @override + def packages(self) -> list[str]: + return [ + 'niri', + 'dms-shell-niri', + 'polkit', + 'xdg-desktop-portal-gnome', + 'xorg-xwayland', + 'matugen', + 'cava', + 'kimageformats', + 'cups-pk-helper', + 'tuned-ppd', + _TERMINAL, + ] + + @property + @override + def default_greeter_type(self) -> GreeterType: + return GreeterType.GreetdDms + + @override + def provision(self, install_session: Installer, users: list[User]) -> None: + binds = (_ASSETS_DIR / 'dms/binds.kdl').read_text().replace('{{TERMINAL_COMMAND}}', _TERMINAL) + + for user in users: + home = install_session.target / 'home' / user.username + niri_dir = home / '.config/niri' + dms_dir = niri_dir / 'dms' + dms_dir.mkdir(parents=True, exist_ok=True) + + shutil.copy(_ASSETS_DIR / 'niri.kdl', niri_dir / 'config.kdl') + for name in ('colors.kdl', 'layout.kdl', 'alttab.kdl', 'outputs.kdl', 'cursor.kdl'): + shutil.copy(_ASSETS_DIR / 'dms' / name, dms_dir / name) + (dms_dir / 'binds.kdl').write_text(binds) + + niri_unit_dropin = home / '.config/systemd/user/niri.service.d' + niri_unit_dropin.mkdir(parents=True, exist_ok=True) + (niri_unit_dropin / 'dms.conf').write_text('[Unit]\nWants=dms.service\n') + + install_session.arch_chroot(f'chown -R {user.username}:{user.username} /home/{user.username}/.config') diff --git a/archinstall/default_profiles/desktops/niri_dms_assets/dms/alttab.kdl b/archinstall/default_profiles/desktops/niri_dms_assets/dms/alttab.kdl new file mode 100644 index 00000000..5f9bdcd0 --- /dev/null +++ b/archinstall/default_profiles/desktops/niri_dms_assets/dms/alttab.kdl @@ -0,0 +1,10 @@ +// ! DO NOT EDIT ! +// ! AUTO-GENERATED BY DMS ! +// ! CHANGES WILL BE OVERWRITTEN ! +// ! PLACE YOUR CUSTOM CONFIGURATION ELSEWHERE ! + +recent-windows { + highlight { + corner-radius 12 + } +} diff --git a/archinstall/default_profiles/desktops/niri_dms_assets/dms/binds.kdl b/archinstall/default_profiles/desktops/niri_dms_assets/dms/binds.kdl new file mode 100644 index 00000000..27cb860e --- /dev/null +++ b/archinstall/default_profiles/desktops/niri_dms_assets/dms/binds.kdl @@ -0,0 +1,221 @@ +binds { + // === System & Overview === + Mod+D repeat=false { toggle-overview; } + Mod+Tab repeat=false { toggle-overview; } + Mod+Shift+Slash { show-hotkey-overlay; } + + // === Application Launchers === + Mod+T hotkey-overlay-title="Open Terminal" { spawn "{{TERMINAL_COMMAND}}"; } + Mod+Space hotkey-overlay-title="Application Launcher" { + spawn "dms" "ipc" "call" "spotlight" "toggle"; + } + Mod+V hotkey-overlay-title="Clipboard Manager" { + spawn "dms" "ipc" "call" "clipboard" "toggle"; + } + Mod+M hotkey-overlay-title="Task Manager" { + spawn "dms" "ipc" "call" "processlist" "focusOrToggle"; + } + + Super+X hotkey-overlay-title="Power Menu: Toggle" { spawn "dms" "ipc" "call" "powermenu" "toggle"; } + Mod+Comma hotkey-overlay-title="Settings" { + spawn "dms" "ipc" "call" "settings" "focusOrToggle"; + } + Mod+Y hotkey-overlay-title="Browse Wallpapers" { + spawn "dms" "ipc" "call" "dankdash" "wallpaper"; + } + Mod+N hotkey-overlay-title="Notification Center" { spawn "dms" "ipc" "call" "notifications" "toggle"; } + Mod+Shift+N hotkey-overlay-title="Notepad" { spawn "dms" "ipc" "call" "notepad" "toggle"; } + + // === Security === + Mod+Alt+L hotkey-overlay-title="Lock Screen" { + spawn "dms" "ipc" "call" "lock" "lock"; + } + Mod+Shift+E { quit; } + Ctrl+Alt+Delete hotkey-overlay-title="Task Manager" { + spawn "dms" "ipc" "call" "processlist" "focusOrToggle"; + } + + // === Audio Controls === + XF86AudioRaiseVolume allow-when-locked=true { + spawn "dms" "ipc" "call" "audio" "increment" "3"; + } + XF86AudioLowerVolume allow-when-locked=true { + spawn "dms" "ipc" "call" "audio" "decrement" "3"; + } + XF86AudioMute allow-when-locked=true { + spawn "dms" "ipc" "call" "audio" "mute"; + } + XF86AudioMicMute allow-when-locked=true { + spawn "dms" "ipc" "call" "audio" "micmute"; + } + XF86AudioPause allow-when-locked=true { + spawn "dms" "ipc" "call" "mpris" "playPause"; + } + XF86AudioPlay allow-when-locked=true { + spawn "dms" "ipc" "call" "mpris" "playPause"; + } + XF86AudioPrev allow-when-locked=true { + spawn "dms" "ipc" "call" "mpris" "previous"; + } + XF86AudioNext allow-when-locked=true { + spawn "dms" "ipc" "call" "mpris" "next"; + } + Ctrl+XF86AudioRaiseVolume allow-when-locked=true { + spawn "dms" "ipc" "call" "mpris" "increment" "3"; + } + Ctrl+XF86AudioLowerVolume allow-when-locked=true { + spawn "dms" "ipc" "call" "mpris" "decrement" "3"; + } + + // === Brightness Controls === + XF86MonBrightnessUp allow-when-locked=true { + spawn "dms" "ipc" "call" "brightness" "increment" "5" ""; + } + XF86MonBrightnessDown allow-when-locked=true { + spawn "dms" "ipc" "call" "brightness" "decrement" "5" ""; + } + + // === Window Management === + Mod+Q repeat=false { close-window; } + Mod+F { maximize-column; } + Mod+Shift+F { fullscreen-window; } + Mod+Shift+T { toggle-window-floating; } + Mod+Shift+V { switch-focus-between-floating-and-tiling; } + Mod+W { toggle-column-tabbed-display; } + Mod+Shift+W hotkey-overlay-title="Create window rule" { spawn "dms" "ipc" "call" "window-rules" "toggle"; } + + // === Focus Navigation === + Mod+Left { focus-column-left; } + Mod+Down { focus-window-down; } + Mod+Up { focus-window-up; } + Mod+Right { focus-column-right; } + Mod+H { focus-column-left; } + Mod+J { focus-window-down; } + Mod+K { focus-window-up; } + Mod+L { focus-column-right; } + + // === Window Movement === + Mod+Shift+Left { move-column-left; } + Mod+Shift+Down { move-window-down; } + Mod+Shift+Up { move-window-up; } + Mod+Shift+Right { move-column-right; } + Mod+Shift+H { move-column-left; } + Mod+Shift+J { move-window-down; } + Mod+Shift+K { move-window-up; } + Mod+Shift+L { move-column-right; } + + // === Column Navigation === + Mod+Home { focus-column-first; } + Mod+End { focus-column-last; } + Mod+Ctrl+Home { move-column-to-first; } + Mod+Ctrl+End { move-column-to-last; } + + // === Monitor Navigation === + Mod+Ctrl+Left { focus-monitor-left; } + //Mod+Ctrl+Down { focus-monitor-down; } + //Mod+Ctrl+Up { focus-monitor-up; } + Mod+Ctrl+Right { focus-monitor-right; } + Mod+Ctrl+H { focus-monitor-left; } + Mod+Ctrl+J { focus-monitor-down; } + Mod+Ctrl+K { focus-monitor-up; } + Mod+Ctrl+L { focus-monitor-right; } + + // === Move to Monitor === + Mod+Shift+Ctrl+Left { move-column-to-monitor-left; } + Mod+Shift+Ctrl+Down { move-column-to-monitor-down; } + Mod+Shift+Ctrl+Up { move-column-to-monitor-up; } + Mod+Shift+Ctrl+Right { move-column-to-monitor-right; } + Mod+Shift+Ctrl+H { move-column-to-monitor-left; } + Mod+Shift+Ctrl+J { move-column-to-monitor-down; } + Mod+Shift+Ctrl+K { move-column-to-monitor-up; } + Mod+Shift+Ctrl+L { move-column-to-monitor-right; } + + // === Workspace Navigation === + Mod+Page_Down { focus-workspace-down; } + Mod+Page_Up { focus-workspace-up; } + Mod+U { focus-workspace-down; } + Mod+I { focus-workspace-up; } + Mod+Ctrl+Down { move-column-to-workspace-down; } + Mod+Ctrl+Up { move-column-to-workspace-up; } + Mod+Ctrl+U { move-column-to-workspace-down; } + Mod+Ctrl+I { move-column-to-workspace-up; } + + // === Workspace Management === + Ctrl+Shift+R hotkey-overlay-title="Rename Workspace" { + spawn "dms" "ipc" "call" "workspace-rename" "open"; + } + + // === Move Workspaces === + Mod+Shift+Page_Down { move-workspace-down; } + Mod+Shift+Page_Up { move-workspace-up; } + Mod+Shift+U { move-workspace-down; } + Mod+Shift+I { move-workspace-up; } + + // === Mouse Wheel Navigation === + Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; } + Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; } + Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; } + Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; } + + Mod+WheelScrollRight { focus-column-right; } + Mod+WheelScrollLeft { focus-column-left; } + Mod+Ctrl+WheelScrollRight { move-column-right; } + Mod+Ctrl+WheelScrollLeft { move-column-left; } + + Mod+Shift+WheelScrollDown { focus-column-right; } + Mod+Shift+WheelScrollUp { focus-column-left; } + Mod+Ctrl+Shift+WheelScrollDown { move-column-right; } + Mod+Ctrl+Shift+WheelScrollUp { move-column-left; } + + // === Numbered Workspaces === + Mod+1 { focus-workspace 1; } + Mod+2 { focus-workspace 2; } + Mod+3 { focus-workspace 3; } + Mod+4 { focus-workspace 4; } + Mod+5 { focus-workspace 5; } + Mod+6 { focus-workspace 6; } + Mod+7 { focus-workspace 7; } + Mod+8 { focus-workspace 8; } + Mod+9 { focus-workspace 9; } + + // === Move to Numbered Workspaces === + Mod+Shift+1 { move-column-to-workspace 1; } + Mod+Shift+2 { move-column-to-workspace 2; } + Mod+Shift+3 { move-column-to-workspace 3; } + Mod+Shift+4 { move-column-to-workspace 4; } + Mod+Shift+5 { move-column-to-workspace 5; } + Mod+Shift+6 { move-column-to-workspace 6; } + Mod+Shift+7 { move-column-to-workspace 7; } + Mod+Shift+8 { move-column-to-workspace 8; } + Mod+Shift+9 { move-column-to-workspace 9; } + + // === Column Management === + Mod+BracketLeft { consume-or-expel-window-left; } + Mod+BracketRight { consume-or-expel-window-right; } + Mod+Period { expel-window-from-column; } + + // === Sizing & Layout === + Mod+R { switch-preset-column-width; } + Mod+Shift+R { switch-preset-window-height; } + Mod+Ctrl+R { reset-window-height; } + Mod+Ctrl+F { expand-column-to-available-width; } + Mod+C { center-column; } + Mod+Ctrl+C { center-visible-columns; } + + // === Manual Sizing === + Mod+Minus { set-column-width "-10%"; } + Mod+Equal { set-column-width "+10%"; } + Mod+Shift+Minus { set-window-height "-10%"; } + Mod+Shift+Equal { set-window-height "+10%"; } + + // === Screenshots === + XF86Launch1 { screenshot; } + Ctrl+XF86Launch1 { screenshot-screen; } + Alt+XF86Launch1 { screenshot-window; } + Print { screenshot; } + Ctrl+Print { screenshot-screen; } + Alt+Print { screenshot-window; } + // === System Controls === + Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; } + Mod+Shift+P { power-off-monitors; } +} diff --git a/archinstall/default_profiles/desktops/niri_dms_assets/dms/colors.kdl b/archinstall/default_profiles/desktops/niri_dms_assets/dms/colors.kdl new file mode 100644 index 00000000..145a1798 --- /dev/null +++ b/archinstall/default_profiles/desktops/niri_dms_assets/dms/colors.kdl @@ -0,0 +1,39 @@ +// ! Auto-generated file. Do not edit directly. +// Remove `include "dms/colors.kdl"` from your config to override. + +layout { + background-color "transparent" + + focus-ring { + active-color "#d0bcff" + inactive-color "#948f99" + urgent-color "#f2b8b5" + } + + border { + active-color "#d0bcff" + inactive-color "#948f99" + urgent-color "#f2b8b5" + } + + shadow { + color "#00000070" + } + + tab-indicator { + active-color "#d0bcff" + inactive-color "#948f99" + urgent-color "#f2b8b5" + } + + insert-hint { + color "#d0bcff80" + } +} + +recent-windows { + highlight { + active-color "#4f378b" + urgent-color "#f2b8b5" + } +} diff --git a/archinstall/default_profiles/desktops/niri_dms_assets/dms/cursor.kdl b/archinstall/default_profiles/desktops/niri_dms_assets/dms/cursor.kdl new file mode 100644 index 00000000..db3d385a --- /dev/null +++ b/archinstall/default_profiles/desktops/niri_dms_assets/dms/cursor.kdl @@ -0,0 +1,6 @@ +// Place cursor configuration here. +// Example: +// cursor { +// xcursor-theme "Adwaita" +// xcursor-size 24 +// } diff --git a/archinstall/default_profiles/desktops/niri_dms_assets/dms/layout.kdl b/archinstall/default_profiles/desktops/niri_dms_assets/dms/layout.kdl new file mode 100644 index 00000000..1951500b --- /dev/null +++ b/archinstall/default_profiles/desktops/niri_dms_assets/dms/layout.kdl @@ -0,0 +1,22 @@ +// ! DO NOT EDIT ! +// ! AUTO-GENERATED BY DMS ! +// ! CHANGES WILL BE OVERWRITTEN ! +// ! PLACE YOUR CUSTOM CONFIGURATION ELSEWHERE ! + +layout { + gaps 4 + + border { + width 2 + } + + focus-ring { + width 2 + } +} +window-rule { + geometry-corner-radius 12 + clip-to-geometry true + tiled-state true + draw-border-with-background false +} diff --git a/archinstall/default_profiles/desktops/niri_dms_assets/dms/outputs.kdl b/archinstall/default_profiles/desktops/niri_dms_assets/dms/outputs.kdl new file mode 100644 index 00000000..3fe37358 --- /dev/null +++ b/archinstall/default_profiles/desktops/niri_dms_assets/dms/outputs.kdl @@ -0,0 +1,7 @@ +// Place per-output configuration here. +// Example: +// output "DP-1" { +// mode "2560x1440@165" +// position x=0 y=0 +// scale 1 +// } diff --git a/archinstall/default_profiles/desktops/niri_dms_assets/niri.kdl b/archinstall/default_profiles/desktops/niri_dms_assets/niri.kdl new file mode 100644 index 00000000..0a759e46 --- /dev/null +++ b/archinstall/default_profiles/desktops/niri_dms_assets/niri.kdl @@ -0,0 +1,279 @@ +// This config is in the KDL format: https://kdl.dev +// "/-" comments out the following node. +// Check the wiki for a full description of the configuration: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Introduction +config-notification { + disable-failed +} + +gestures { + hot-corners { + off + } +} + +// Input device configuration. +// Find the full list of options on the wiki: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Input +input { + keyboard { + xkb { + // You can set rules, model, layout, variant and options. + // For more information, see xkeyboard-config(7). + + // For example: + // layout "us,ru" + // options "grp:win_space_toggle,compose:ralt,ctrl:nocaps" + + // If this section is empty, niri will fetch xkb settings + // from org.freedesktop.locale1. You can control these using + // localectl set-x11-keymap. + } + + // Enable numlock on startup, omitting this setting disables it. + numlock + } + + // Next sections include libinput settings. + // Omitting settings disables them, or leaves them at their default values. + // All commented-out settings here are examples, not defaults. + touchpad { + // off + tap + // dwt + // dwtp + // drag false + // drag-lock + natural-scroll + // accel-speed 0.2 + // accel-profile "flat" + // scroll-method "two-finger" + // disabled-on-external-mouse + } + + mouse { + // off + // natural-scroll + // accel-speed 0.2 + // accel-profile "flat" + // scroll-method "no-scroll" + } + + trackpoint { + // off + // natural-scroll + // accel-speed 0.2 + // accel-profile "flat" + // scroll-method "on-button-down" + // scroll-button 273 + // scroll-button-lock + // middle-emulation + } + + // Uncomment this to make the mouse warp to the center of newly focused windows. + // warp-mouse-to-focus + + // Focus windows and outputs automatically when moving the mouse into them. + // Setting max-scroll-amount="0%" makes it work only on windows already fully on screen. + // focus-follows-mouse max-scroll-amount="0%" +} +// You can configure outputs by their name, which you can find +// by running `niri msg outputs` while inside a niri instance. +// The built-in laptop monitor is usually called "eDP-1". +// Find more information on the wiki: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Outputs +// Remember to uncomment the node by removing "/-"! +/-output "eDP-2" { + mode "2560x1600@239.998993" + position x=2560 y=0 + variable-refresh-rate +} +// Settings that influence how windows are positioned and sized. +// Find more information on the wiki: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Layout +layout { + // Set gaps around windows in logical pixels. + background-color "transparent" + // When to center a column when changing focus, options are: + // - "never", default behavior, focusing an off-screen column will keep at the left + // or right edge of the screen. + // - "always", the focused column will always be centered. + // - "on-overflow", focusing a column will center it if it doesn't fit + // together with the previously focused column. + center-focused-column "never" + // You can customize the widths that "switch-preset-column-width" (Mod+R) toggles between. + preset-column-widths { + // Proportion sets the width as a fraction of the output width, taking gaps into account. + // For example, you can perfectly fit four windows sized "proportion 0.25" on an output. + // The default preset widths are 1/3, 1/2 and 2/3 of the output. + proportion 0.33333 + proportion 0.5 + proportion 0.66667 + // Fixed sets the width in logical pixels exactly. + // fixed 1920 + } + // You can also customize the heights that "switch-preset-window-height" (Mod+Shift+R) toggles between. + // preset-window-heights { } + // You can change the default width of the new windows. + default-column-width { proportion 0.5; } + // If you leave the brackets empty, the windows themselves will decide their initial width. + // default-column-width {} + // By default focus ring and border are rendered as a solid background rectangle + // behind windows. That is, they will show up through semitransparent windows. + // This is because windows using client-side decorations can have an arbitrary shape. + // + // If you don't like that, you should uncomment `prefer-no-csd` below. + // Niri will draw focus ring and border *around* windows that agree to omit their + // client-side decorations. + // + // Alternatively, you can override it with a window rule called + // `draw-border-with-background`. + border { + off + width 4 + active-color "#707070" // Neutral gray + inactive-color "#d0d0d0" // Light gray + urgent-color "#cc4444" // Softer red + } + shadow { + softness 30 + spread 5 + offset x=0 y=5 + color "#0007" + } + struts { + } +} +layer-rule { + match namespace="^quickshell$" + place-within-backdrop true +} +overview { + workspace-shadow { + off + } +} +// Add lines like this to spawn processes at startup. +// Note that running niri as a session supports xdg-desktop-autostart, +// which may be more convenient to use. +// See the binds section below for more spawn examples. +// This line starts waybar, a commonly used bar for Wayland compositors. +environment { + XDG_CURRENT_DESKTOP "niri" +} +hotkey-overlay { + skip-at-startup +} +prefer-no-csd +screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png" +animations { + workspace-switch { + spring damping-ratio=0.80 stiffness=523 epsilon=0.0001 + } + window-open { + duration-ms 150 + curve "ease-out-expo" + } + window-close { + duration-ms 150 + curve "ease-out-quad" + } + horizontal-view-movement { + spring damping-ratio=0.85 stiffness=423 epsilon=0.0001 + } + window-movement { + spring damping-ratio=0.75 stiffness=323 epsilon=0.0001 + } + window-resize { + spring damping-ratio=0.85 stiffness=423 epsilon=0.0001 + } + config-notification-open-close { + spring damping-ratio=0.65 stiffness=923 epsilon=0.001 + } + screenshot-ui-open { + duration-ms 200 + curve "ease-out-quad" + } + overview-open-close { + spring damping-ratio=0.85 stiffness=800 epsilon=0.0001 + } +} +// Window rules let you adjust behavior for individual windows. +// Find more information on the wiki: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules +// Work around WezTerm's initial configure bug +// by setting an empty default-column-width. +window-rule { + // This regular expression is intentionally made as specific as possible, + // since this is the default config, and we want no false positives. + // You can get away with just app-id="wezterm" if you want. + match app-id=r#"^org\.wezfurlong\.wezterm$"# + default-column-width {} +} +window-rule { + match app-id=r#"^org\.gnome\."# + draw-border-with-background false + geometry-corner-radius 12 + clip-to-geometry true +} +window-rule { + match app-id=r#"^gnome-control-center$"# + match app-id=r#"^pavucontrol$"# + match app-id=r#"^nm-connection-editor$"# + default-column-width { proportion 0.5; } + open-floating false +} +window-rule { + match app-id=r#"^org\.gnome\.Calculator$"# + match app-id=r#"^gnome-calculator$"# + match app-id=r#"^galculator$"# + match app-id=r#"^blueman-manager$"# + match app-id=r#"^org\.gnome\.Nautilus$"# + match app-id=r#"^xdg-desktop-portal$"# + open-floating true +} +window-rule { + match app-id=r#"^steam$"# title=r#"^notificationtoasts_\d+_desktop$"# + default-floating-position x=10 y=10 relative-to="bottom-right" + open-focused false +} +window-rule { + match app-id=r#"^org\.wezfurlong\.wezterm$"# + match app-id="Alacritty" + match app-id="zen" + match app-id="com.mitchellh.ghostty" + match app-id="kitty" + draw-border-with-background false +} +window-rule { + match app-id=r#"firefox$"# title="^Picture-in-Picture$" + match app-id="zoom" + open-floating true +} +// Open dms windows as floating by default +window-rule { + match app-id=r#"org.quickshell$"# + match app-id=r#"com.danklinux.dms$"# + open-floating true +} +debug { + honor-xdg-activation-with-invalid-serial +} + +// Override to disable super+tab +recent-windows { + binds { + Alt+Tab { next-window scope="output"; } + Alt+Shift+Tab { previous-window scope="output"; } + Alt+grave { next-window filter="app-id"; } + Alt+Shift+grave { previous-window filter="app-id"; } + } +} + +// Include dms files +include "dms/colors.kdl" +include "dms/layout.kdl" +include "dms/alttab.kdl" +include "dms/binds.kdl" +include "dms/outputs.kdl" +include "dms/cursor.kdl" diff --git a/archinstall/default_profiles/profile.py b/archinstall/default_profiles/profile.py index cc56186f..6c328a46 100644 --- a/archinstall/default_profiles/profile.py +++ b/archinstall/default_profiles/profile.py @@ -37,6 +37,7 @@ class GreeterType(Enum): Ly = 'ly' CosmicSession = 'cosmic-greeter' PlasmaLoginManager = 'plasma-login-manager' + GreetdDms = 'dms-greeter' class SelectResult(Enum): diff --git a/archinstall/default_profiles/server.py b/archinstall/default_profiles/server.py index bdd3d079..0e2506e0 100644 --- a/archinstall/default_profiles/server.py +++ b/archinstall/default_profiles/server.py @@ -1,8 +1,8 @@ from typing import TYPE_CHECKING, Self, override from archinstall.default_profiles.profile import Profile, ProfileType, SelectResult +from archinstall.lib.log import info from archinstall.lib.menu.helpers import Selection -from archinstall.lib.output import info from archinstall.lib.profile.profiles_handler import profile_handler from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType diff --git a/archinstall/lib/args.py b/archinstall/lib/args.py index efe9baa2..e3729504 100644 --- a/archinstall/lib/args.py +++ b/archinstall/lib/args.py @@ -6,7 +6,7 @@ import urllib.error import urllib.parse from argparse import ArgumentParser, Namespace from dataclasses import dataclass, field -from enum import StrEnum +from enum import Enum, StrEnum from pathlib import Path from typing import Any, Self from urllib.request import Request, urlopen @@ -14,6 +14,7 @@ from urllib.request import Request, urlopen from pydantic.dataclasses import dataclass as p_dataclass from archinstall.lib.crypt import decrypt +from archinstall.lib.log import debug, error, logger, warn from archinstall.lib.menu.util import get_password from archinstall.lib.models.application import ApplicationConfiguration, ZramConfiguration from archinstall.lib.models.authentication import AuthenticationConfiguration @@ -28,13 +29,16 @@ from archinstall.lib.models.packages import Repository from archinstall.lib.models.pacman import PacmanConfiguration from archinstall.lib.models.profile import ProfileConfiguration from archinstall.lib.models.users import Password, User, UserSerialization -from archinstall.lib.output import debug, error, logger, warn from archinstall.lib.plugins import load_plugin from archinstall.lib.translationhandler import Language, tr, translation_handler from archinstall.lib.version import get_version from archinstall.tui.components import tui +class SubCommand(Enum): + SHARE_LOG = 'share-log' + + @p_dataclass class Arguments: config: Path | None = None @@ -58,6 +62,8 @@ class Arguments: advanced: bool = False verbose: bool = False + command: SubCommand | None = None + class ArchConfigType(StrEnum): VERSION = 'version' @@ -365,13 +371,13 @@ class ArchConfig: class ArchConfigHandler: def __init__(self) -> None: self._parser: ArgumentParser = self._define_arguments() - args: Arguments = self._parse_args() - self._args = args + self._add_sub_parsers() + self._args: Arguments = self._parse_args() config = self._parse_config() try: - self._config = ArchConfig.from_config(config, args) + self._config = ArchConfig.from_config(config, self._args) self._config.version = get_version() except ValueError as err: warn(str(err)) @@ -397,8 +403,13 @@ class ArchConfigHandler: def print_help(self) -> None: self._parser.print_help() + def _add_sub_parsers(self) -> None: + subparsers = self._parser.add_subparsers(dest='command', help='Available subcommands') + _ = subparsers.add_parser(SubCommand.SHARE_LOG.value, help='Upload log file to public server') + def _define_arguments(self) -> ArgumentParser: parser = ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument( '-v', '--version', diff --git a/archinstall/lib/authentication/authentication_handler.py b/archinstall/lib/authentication/authentication_handler.py index 3a3b8cd4..bae192fd 100644 --- a/archinstall/lib/authentication/authentication_handler.py +++ b/archinstall/lib/authentication/authentication_handler.py @@ -3,9 +3,9 @@ from pathlib import Path from typing import TYPE_CHECKING from archinstall.lib.command import SysCommandWorker +from archinstall.lib.log import debug, info from archinstall.lib.models.authentication import AuthenticationConfiguration, U2FLoginConfiguration, U2FLoginMethod from archinstall.lib.models.users import User -from archinstall.lib.output import debug, info from archinstall.lib.translationhandler import tr if TYPE_CHECKING: diff --git a/archinstall/lib/authentication/authentication_menu.py b/archinstall/lib/authentication/authentication_menu.py index 5453099f..497b925b 100644 --- a/archinstall/lib/authentication/authentication_menu.py +++ b/archinstall/lib/authentication/authentication_menu.py @@ -6,9 +6,9 @@ from archinstall.lib.menu.helpers import Confirmation, Selection from archinstall.lib.menu.util import get_password from archinstall.lib.models.authentication import AuthenticationConfiguration, U2FLoginConfiguration, U2FLoginMethod from archinstall.lib.models.users import Password, User -from archinstall.lib.output import FormattedOutput from archinstall.lib.translationhandler import tr from archinstall.lib.user.user_menu import select_users +from archinstall.lib.utils.format import as_table from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -65,7 +65,7 @@ class AuthenticationMenu(AbstractSubMenu[AuthenticationConfiguration]): users: list[User] | None = item.value if users: - return FormattedOutput.as_table(users) + return as_table(users) return None def _prev_root_pwd(self, item: MenuItem) -> str | None: diff --git a/archinstall/lib/boot.py b/archinstall/lib/boot.py index b1e8c888..e8fa4c88 100644 --- a/archinstall/lib/boot.py +++ b/archinstall/lib/boot.py @@ -6,7 +6,7 @@ from typing import ClassVar, Self from archinstall.lib.command import SysCommand, SysCommandWorker from archinstall.lib.exceptions import SysCallError -from archinstall.lib.output import error +from archinstall.lib.log import error class Boot: diff --git a/archinstall/lib/command.py b/archinstall/lib/command.py index b99854d2..b0d45754 100644 --- a/archinstall/lib/command.py +++ b/archinstall/lib/command.py @@ -11,7 +11,7 @@ from types import TracebackType from typing import Any, Self, override from archinstall.lib.exceptions import RequirementError, SysCallError -from archinstall.lib.output import debug, error, logger +from archinstall.lib.log import debug, error, logger from archinstall.lib.utils.encoding import clear_vt100_escape_codes diff --git a/archinstall/lib/configuration.py b/archinstall/lib/configuration.py index 0b689ba3..4b77d946 100644 --- a/archinstall/lib/configuration.py +++ b/archinstall/lib/configuration.py @@ -8,11 +8,12 @@ from pydantic import TypeAdapter from archinstall.lib.args import ArchConfig, ArchConfigType from archinstall.lib.crypt import encrypt +from archinstall.lib.log import debug, logger, warn from archinstall.lib.menu.helpers import Confirmation, Selection from archinstall.lib.menu.util import get_password, prompt_dir from archinstall.lib.models.network import NetworkConfiguration -from archinstall.lib.output import as_key_value_pair, debug, logger, warn from archinstall.lib.translationhandler import tr +from archinstall.lib.utils.format import as_key_value_pair from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType diff --git a/archinstall/lib/crypt.py b/archinstall/lib/crypt.py index 99fa62d6..b7ad4edf 100644 --- a/archinstall/lib/crypt.py +++ b/archinstall/lib/crypt.py @@ -6,7 +6,7 @@ from pathlib import Path from cryptography.fernet import Fernet, InvalidToken from cryptography.hazmat.primitives.kdf.argon2 import Argon2id -from archinstall.lib.output import debug +from archinstall.lib.log import debug libcrypt = ctypes.CDLL('libcrypt.so') diff --git a/archinstall/lib/disk/device_handler.py b/archinstall/lib/disk/device_handler.py index 2e51d3d2..360cbfd1 100644 --- a/archinstall/lib/disk/device_handler.py +++ b/archinstall/lib/disk/device_handler.py @@ -15,6 +15,7 @@ from archinstall.lib.disk.utils import ( umount, ) from archinstall.lib.exceptions import DiskError, SysCallError, UnknownFilesystemFormat +from archinstall.lib.log import debug, error, info, log from archinstall.lib.models.device import ( DEFAULT_ITER_TIME, BDevice, @@ -35,7 +36,6 @@ from archinstall.lib.models.device import ( _PartitionInfo, ) from archinstall.lib.models.users import Password -from archinstall.lib.output import debug, error, info, log from archinstall.lib.pathnames import ARCHISO_MOUNTPOINT diff --git a/archinstall/lib/disk/disk_menu.py b/archinstall/lib/disk/disk_menu.py index 26aa145d..f8e8e2e3 100644 --- a/archinstall/lib/disk/disk_menu.py +++ b/archinstall/lib/disk/disk_menu.py @@ -5,6 +5,7 @@ from typing import override from archinstall.lib.disk.device_handler import device_handler from archinstall.lib.disk.encryption_menu import DiskEncryptionMenu from archinstall.lib.disk.partitioning_menu import manual_partitioning +from archinstall.lib.log import debug from archinstall.lib.menu.abstract_menu import AbstractSubMenu from archinstall.lib.menu.helpers import Confirmation, Notify, Selection, Table from archinstall.lib.menu.util import prompt_dir @@ -35,8 +36,8 @@ from archinstall.lib.models.device import ( Unit, _DeviceInfo, ) -from archinstall.lib.output import FormattedOutput, debug from archinstall.lib.translationhandler import tr +from archinstall.lib.utils.format import as_table from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -221,7 +222,7 @@ class DiskLayoutConfigurationMenu(AbstractSubMenu[DiskMenuConfig]): for mod in device_mods: # create partition table - partition_table = FormattedOutput.as_table(mod.partitions) + partition_table = as_table(mod.partitions) output_partition += f'{mod.device_path}: {mod.device.device_info.model}\n' output_partition += '{}: {}\n'.format(tr('Wipe'), mod.wipe) @@ -230,7 +231,7 @@ class DiskLayoutConfigurationMenu(AbstractSubMenu[DiskMenuConfig]): # create btrfs table btrfs_partitions = [p for p in mod.partitions if p.btrfs_subvols] for partition in btrfs_partitions: - output_btrfs += FormattedOutput.as_table(partition.btrfs_subvols) + '\n' + output_btrfs += as_table(partition.btrfs_subvols) + '\n' output = output_partition + output_btrfs return output.rstrip() @@ -246,12 +247,12 @@ class DiskLayoutConfigurationMenu(AbstractSubMenu[DiskMenuConfig]): 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) + pv_table = as_table(vol_gp.pvs) output += '{}:\n{}'.format(tr('Physical volumes'), pv_table) output += f'\nVolume Group: {vol_gp.name}' - lvm_volumes = FormattedOutput.as_table(vol_gp.volumes) + lvm_volumes = as_table(vol_gp.volumes) output += '\n\n{}:\n{}'.format(tr('Volumes'), lvm_volumes) return output @@ -302,7 +303,7 @@ async def select_devices(preset: list[BDevice] | None = []) -> list[BDevice] | N dev = device_handler.get_device(device.path) if dev and dev.partition_infos: - return FormattedOutput.as_table(dev.partition_infos) + return as_table(dev.partition_infos) return None if preset is None: diff --git a/archinstall/lib/disk/encryption_menu.py b/archinstall/lib/disk/encryption_menu.py index f5d4f095..53aa73fe 100644 --- a/archinstall/lib/disk/encryption_menu.py +++ b/archinstall/lib/disk/encryption_menu.py @@ -17,8 +17,8 @@ from archinstall.lib.models.device import ( PartitionModification, ) from archinstall.lib.models.users import Password -from archinstall.lib.output import FormattedOutput from archinstall.lib.translationhandler import tr +from archinstall.lib.utils.format import as_table from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -199,7 +199,7 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]): def _prev_partitions(self, item: MenuItem) -> str | None: if item.value: output = tr('Partitions to be encrypted') + '\n' - output += FormattedOutput.as_table(item.value) + output += as_table(item.value) return output.rstrip() return None @@ -207,7 +207,7 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]): def _prev_lvm_vols(self, item: MenuItem) -> str | None: if item.value: output = tr('LVM volumes to be encrypted') + '\n' - output += FormattedOutput.as_table(item.value) + output += as_table(item.value) return output.rstrip() return None diff --git a/archinstall/lib/disk/fido.py b/archinstall/lib/disk/fido.py index 0538417f..6392b55c 100644 --- a/archinstall/lib/disk/fido.py +++ b/archinstall/lib/disk/fido.py @@ -4,9 +4,9 @@ from typing import ClassVar from archinstall.lib.command import SysCommand, SysCommandWorker from archinstall.lib.exceptions import SysCallError +from archinstall.lib.log import error, info from archinstall.lib.models.device import Fido2Device from archinstall.lib.models.users import Password -from archinstall.lib.output import error, info from archinstall.lib.utils.encoding import clear_vt100_escape_codes_from_str diff --git a/archinstall/lib/disk/filesystem.py b/archinstall/lib/disk/filesystem.py index 1afa8c6e..2c51b09d 100644 --- a/archinstall/lib/disk/filesystem.py +++ b/archinstall/lib/disk/filesystem.py @@ -13,6 +13,7 @@ from archinstall.lib.disk.lvm import ( lvm_vol_reduce, ) from archinstall.lib.disk.utils import udev_sync +from archinstall.lib.log import debug, info from archinstall.lib.models.device import ( DiskEncryption, DiskLayoutConfiguration, @@ -27,7 +28,6 @@ from archinstall.lib.models.device import ( Size, Unit, ) -from archinstall.lib.output import debug, info class FilesystemHandler: diff --git a/archinstall/lib/disk/luks.py b/archinstall/lib/disk/luks.py index 275222f8..5d62abc8 100644 --- a/archinstall/lib/disk/luks.py +++ b/archinstall/lib/disk/luks.py @@ -7,9 +7,9 @@ from types import TracebackType from archinstall.lib.command import SysCommand, SysCommandWorker, run from archinstall.lib.disk.utils import get_lsblk_info, umount from archinstall.lib.exceptions import DiskError, SysCallError +from archinstall.lib.log import debug, info from archinstall.lib.models.device import DEFAULT_ITER_TIME from archinstall.lib.models.users import Password -from archinstall.lib.output import debug, info from archinstall.lib.utils.util import generate_password diff --git a/archinstall/lib/disk/lvm.py b/archinstall/lib/disk/lvm.py index 34ae9a26..c2c5b6a6 100644 --- a/archinstall/lib/disk/lvm.py +++ b/archinstall/lib/disk/lvm.py @@ -7,6 +7,7 @@ from typing import Literal, overload from archinstall.lib.command import SysCommand, SysCommandWorker from archinstall.lib.disk.utils import udev_sync from archinstall.lib.exceptions import SysCallError +from archinstall.lib.log import debug from archinstall.lib.models.device import ( LvmGroupInfo, LvmPVInfo, @@ -17,7 +18,6 @@ from archinstall.lib.models.device import ( Size, Unit, ) -from archinstall.lib.output import debug def _lvm_info( diff --git a/archinstall/lib/disk/partitioning_menu.py b/archinstall/lib/disk/partitioning_menu.py index a524cf99..b8ddd231 100644 --- a/archinstall/lib/disk/partitioning_menu.py +++ b/archinstall/lib/disk/partitioning_menu.py @@ -19,8 +19,8 @@ from archinstall.lib.models.device import ( Size, Unit, ) -from archinstall.lib.output import FormattedOutput from archinstall.lib.translationhandler import tr +from archinstall.lib.utils.format import as_table from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -479,7 +479,7 @@ class PartitioningList(ListManager[DiskSegment]): sector_size = device_info.sector_size text = tr('Selected free space segment on device {}:').format(device_info.path) + '\n\n' - free_space_table = FormattedOutput.as_table([free_space]) + free_space_table = as_table([free_space]) prompt = text + free_space_table + '\n' max_sectors = free_space.length.format_size(Unit.sectors, sector_size) diff --git a/archinstall/lib/disk/utils.py b/archinstall/lib/disk/utils.py index 808ff451..900445e1 100644 --- a/archinstall/lib/disk/utils.py +++ b/archinstall/lib/disk/utils.py @@ -4,8 +4,8 @@ from pydantic import BaseModel from archinstall.lib.command import SysCommand from archinstall.lib.exceptions import DiskError, SysCallError +from archinstall.lib.log import debug, info, warn from archinstall.lib.models.device import LsblkInfo -from archinstall.lib.output import debug, info, warn class LsblkOutput(BaseModel): diff --git a/archinstall/lib/general/general_menu.py b/archinstall/lib/general/general_menu.py index be5498d8..dcf7d8aa 100644 --- a/archinstall/lib/general/general_menu.py +++ b/archinstall/lib/general/general_menu.py @@ -1,8 +1,8 @@ from enum import Enum from archinstall.lib.locale.utils import list_timezones +from archinstall.lib.log import warn from archinstall.lib.menu.helpers import Confirmation, Input, Selection -from archinstall.lib.output import warn from archinstall.lib.translationhandler import Language, tr from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index 9e544ffd..ff3deb8f 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -27,11 +27,11 @@ from archinstall.lib.models.packages import Repository from archinstall.lib.models.pacman import PacmanConfiguration from archinstall.lib.models.profile import ProfileConfiguration from archinstall.lib.network.network_menu import select_network -from archinstall.lib.output import FormattedOutput from archinstall.lib.packages.packages import list_available_packages, select_additional_packages from archinstall.lib.pacman.config import PacmanConfig from archinstall.lib.pacman.pacman_menu import PacmanMenu from archinstall.lib.translationhandler import Language, tr, translation_handler +from archinstall.lib.utils.format import as_table from archinstall.tui.components import tui from archinstall.tui.menu_item import MenuItem, MenuItemGroup, MsgLevelType, PreviewResult @@ -299,7 +299,7 @@ class GlobalMenu(AbstractMenu[None]): if item.value: network_config: NetworkConfiguration = item.value if network_config.type == NicType.MANUAL: - output = FormattedOutput.as_table(network_config.nics) + output = as_table(network_config.nics) else: output = f'{tr("Network configuration")}:\n{network_config.type.display_msg()}' @@ -321,7 +321,7 @@ class GlobalMenu(AbstractMenu[None]): output += f'{tr("Root password")}: {auth_config.root_enc_password.hidden()}\n' if auth_config.users: - output += FormattedOutput.as_table(auth_config.users) + '\n' + output += as_table(auth_config.users) + '\n' if auth_config.u2f_config: u2f_config = auth_config.u2f_config @@ -631,7 +631,7 @@ class GlobalMenu(AbstractMenu[None]): if mirror_config.custom_repositories: title = tr('Custom repositories') - table = FormattedOutput.as_table(mirror_config.custom_repositories) + table = as_table(mirror_config.custom_repositories) output += f'{title}:\n\n{table}' return output.strip() diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index 2cfdb706..f1587a3c 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -6,8 +6,8 @@ from typing import Self from archinstall.lib.command import SysCommand from archinstall.lib.exceptions import SysCallError +from archinstall.lib.log import debug from archinstall.lib.networking import enrich_iface_types, list_interfaces -from archinstall.lib.output import debug from archinstall.lib.translationhandler import tr diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 801eaee2..bf7d91ba 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -29,6 +29,7 @@ from archinstall.lib.exceptions import DiskError, HardwareIncompatibilityError, from archinstall.lib.hardware import SysInfo from archinstall.lib.linux_path import LPath from archinstall.lib.locale.utils import verify_keyboard_layout, verify_x11_keyboard_layout +from archinstall.lib.log import debug, error, info, log, logger, warn from archinstall.lib.mirror.mirror_handler import MirrorListHandler from archinstall.lib.models.application import ZramAlgorithm from archinstall.lib.models.bootloader import Bootloader, BootloaderConfiguration @@ -52,7 +53,6 @@ from archinstall.lib.models.package_types import DEFAULT_KERNEL, Kernel from archinstall.lib.models.packages import Repository from archinstall.lib.models.pacman import PacmanConfiguration from archinstall.lib.models.users import User -from archinstall.lib.output import debug, error, info, log, logger, warn from archinstall.lib.packages.packages import installed_package from archinstall.lib.pacman.config import PacmanConfig from archinstall.lib.pacman.pacman import Pacman @@ -375,7 +375,12 @@ class Installer: # it would be none if it's btrfs as the subvolumes will have the mountpoints defined if part_mod.mountpoint: target = self.target / part_mod.relative_mountpoint - mount(part_mod.dev_path, target, options=part_mod.mount_options) + options = part_mod.mount_options + + if part_mod.is_efi(): + options = list(dict.fromkeys(options + ['fmask=0077', 'dmask=0077'])) + + mount(part_mod.dev_path, target, options=options) elif part_mod.fs_type == FilesystemType.BTRFS: # Only mount BTRFS subvolumes that have mountpoints specified subvols_with_mountpoints = [sv for sv in part_mod.btrfs_subvols if sv.mountpoint is not None] diff --git a/archinstall/lib/locale/utils.py b/archinstall/lib/locale/utils.py index 497e1fcb..31946028 100644 --- a/archinstall/lib/locale/utils.py +++ b/archinstall/lib/locale/utils.py @@ -3,7 +3,7 @@ from pathlib import Path from archinstall.lib.command import SysCommand from archinstall.lib.exceptions import ServiceException, SysCallError -from archinstall.lib.output import error +from archinstall.lib.log import error from archinstall.lib.utils.util import running_from_iso diff --git a/archinstall/lib/log.py b/archinstall/lib/log.py new file mode 100644 index 00000000..bd060e99 --- /dev/null +++ b/archinstall/lib/log.py @@ -0,0 +1,259 @@ +import logging +import os +import sys +import urllib.error +import urllib.request +from enum import Enum +from pathlib import Path + +from archinstall.lib.utils.util import timestamp + + +class Logger: + def __init__(self, path: Path | None = None) -> None: + if path is None: + path = Path('/var/log/archinstall') + + self._path: Path = path + + @property + def path(self) -> Path: + return self._path / 'install.log' + + @path.setter + def path(self, value: Path) -> None: + self._path = value + + @property + def directory(self) -> Path: + return self._path + + def _check_permissions(self) -> None: + log_file = self.path + + try: + self._path.mkdir(exist_ok=True, parents=True) + log_file.touch(exist_ok=True) + + with log_file.open('a') as f: + f.write('') + except PermissionError: + # Fallback to creating the log file in the current folder + logger._path = Path('./').absolute() + + warn(f'Not enough permission to place log file at {log_file}, creating it in {logger.path} instead') + + def log(self, level: int, content: str) -> None: + self._check_permissions() + + with self.path.open('a') as f: + ts = timestamp() + level_name = logging.getLevelName(level) + f.write(f'[{ts}] - {level_name} - {content}\n') + + def get_content(self, max_bytes: int | None = None) -> bytes: + content = self.path.read_bytes() + + if max_bytes is not None: + size = self.path.stat().st_size + + if size > max_bytes: + content = content[-max_bytes:] + + return content + + +logger = Logger() + + +def _supports_color() -> bool: + """ + Found first reference here: + https://stackoverflow.com/questions/7445658/how-to-detect-if-the-console-does-support-ansi-escape-codes-in-python + And re-used this: + https://github.com/django/django/blob/master/django/core/management/color.py#L12 + + Return True if the running system's terminal supports color, + and False otherwise. + """ + supported_platform = sys.platform != 'win32' or 'ANSICON' in os.environ + + # isatty is not always implemented, #6223. + is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() + return supported_platform and is_a_tty + + +class Font(Enum): + bold = '1' + italic = '3' + underscore = '4' + blink = '5' + reverse = '7' + conceal = '8' + + +def _stylize_output( + text: str, + fg: str, + bg: str | None, + reset: bool, + font: list[Font] = [], +) -> str: + """ + Heavily influenced by: + https://github.com/django/django/blob/ae8338daf34fd746771e0678081999b656177bae/django/utils/termcolors.py#L13 + Color options here: + https://askubuntu.com/questions/528928/how-to-do-underline-bold-italic-strikethrough-color-background-and-size-i + + Adds styling to a text given a set of color arguments. + """ + colors = { + 'black': '0', + 'red': '1', + 'green': '2', + 'yellow': '3', + 'blue': '4', + 'magenta': '5', + 'cyan': '6', + 'white': '7', + 'teal': '8;5;109', # Extended 256-bit colors (not always supported) + 'orange': '8;5;208', # https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#256-colors + 'darkorange': '8;5;202', + 'gray': '8;5;246', + 'grey': '8;5;246', + 'darkgray': '8;5;240', + 'lightgray': '8;5;256', + } + + foreground = {key: f'3{colors[key]}' for key in colors} + background = {key: f'4{colors[key]}' for key in colors} + code_list = [] + + if text == '' and reset: + return '\x1b[0m' + + code_list.append(foreground[str(fg)]) + + if bg: + code_list.append(background[str(bg)]) + + for o in font: + code_list.append(o.value) + + ansi = ';'.join(code_list) + + return f'\033[{ansi}m{text}\033[0m' + + +def journal_log(message: str, level: int = logging.DEBUG) -> None: + try: + import systemd.journal # type: ignore[import-not-found] + except ModuleNotFoundError: + return + + log_adapter = logging.getLogger('archinstall') + log_fmt = logging.Formatter('[%(levelname)s]: %(message)s') + log_ch = systemd.journal.JournalHandler() + log_ch.setFormatter(log_fmt) + log_adapter.addHandler(log_ch) + log_adapter.setLevel(logging.DEBUG) + + log_adapter.log(level, message) + + +def info( + *msgs: str, + level: int = logging.INFO, + fg: str = 'white', + bg: str | None = None, + reset: bool = False, + font: list[Font] = [], +) -> None: + log(*msgs, level=level, fg=fg, bg=bg, reset=reset, font=font) + + +def debug( + *msgs: str, + level: int = logging.DEBUG, + fg: str = 'white', + bg: str | None = None, + reset: bool = False, + font: list[Font] = [], +) -> None: + log(*msgs, level=level, fg=fg, bg=bg, reset=reset, font=font) + + +def error( + *msgs: str, + level: int = logging.ERROR, + fg: str = 'red', + bg: str | None = None, + reset: bool = False, + font: list[Font] = [], +) -> None: + log(*msgs, level=level, fg=fg, bg=bg, reset=reset, font=font) + + +def warn( + *msgs: str, + level: int = logging.WARNING, + fg: str = 'yellow', + bg: str | None = None, + reset: bool = False, + font: list[Font] = [], +) -> None: + log(*msgs, level=level, fg=fg, bg=bg, reset=reset, font=font) + + +def log( + *msgs: str, + level: int = logging.INFO, + fg: str = 'white', + bg: str | None = None, + reset: bool = False, + font: list[Font] = [], +) -> None: + text = ' '.join(str(x) for x in msgs) + + logger.log(level, text) + + # Attempt to colorize the output if supported + # Insert default colors and override with **kwargs + if _supports_color(): + text = _stylize_output(text, fg, bg, reset, font) + + journal_log(text, level=level) + + if level != logging.DEBUG: + print(text) + + +def share_install_log( + paste_url: str, + max_bytes: int | None = None, +) -> str | None: + log_path = logger.path + + if not log_path.exists(): + info(f'Log file not found: {log_path}') + return None + + content = logger.get_content(max_bytes=max_bytes) + + if len(content) == 0: + info(f'Log file is empty: {log_path}') + return None + + try: + req = urllib.request.Request(paste_url, data=content) + with urllib.request.urlopen(req) as response: + url = response.read().decode().strip() + except urllib.error.URLError as e: + info(f'Upload failed: {e}') + return None + + if not url.startswith('http'): + info(f'Unexpected response from {paste_url}: {url[:200]!r}') + return None + + return url diff --git a/archinstall/lib/menu/abstract_menu.py b/archinstall/lib/menu/abstract_menu.py index 590cabf1..c37f5657 100644 --- a/archinstall/lib/menu/abstract_menu.py +++ b/archinstall/lib/menu/abstract_menu.py @@ -2,8 +2,8 @@ from enum import Enum from types import TracebackType from typing import Any, Self, override +from archinstall.lib.log import error from archinstall.lib.menu.helpers import Selection -from archinstall.lib.output import error from archinstall.lib.translationhandler import tr from archinstall.tui.components import InstanceRunnable from archinstall.tui.menu_item import MenuItem, MenuItemGroup diff --git a/archinstall/lib/menu/menu_helper.py b/archinstall/lib/menu/menu_helper.py index 6ca3b953..0d9a4032 100644 --- a/archinstall/lib/menu/menu_helper.py +++ b/archinstall/lib/menu/menu_helper.py @@ -1,4 +1,4 @@ -from archinstall.lib.output import FormattedOutput +from archinstall.lib.utils.format import as_table from archinstall.tui.menu_item import MenuItem, MenuItemGroup @@ -32,7 +32,7 @@ class MenuHelper[ValueT]: display_data: dict[str, ValueT | str | None] = {} if data: - table = FormattedOutput.as_table(data) + table = as_table(data) rows = table.split('\n') # these are the header rows of the table diff --git a/archinstall/lib/mirror/mirror_handler.py b/archinstall/lib/mirror/mirror_handler.py index ef0ba1a9..8117605d 100644 --- a/archinstall/lib/mirror/mirror_handler.py +++ b/archinstall/lib/mirror/mirror_handler.py @@ -2,10 +2,10 @@ import time import urllib.parse from pathlib import Path +from archinstall.lib.log import debug, info from archinstall.lib.models import MirrorRegion from archinstall.lib.models.mirrors import MirrorStatusEntryV3, MirrorStatusListV3 from archinstall.lib.networking import fetch_data_from_url -from archinstall.lib.output import debug, info from archinstall.lib.pathnames import MIRRORLIST diff --git a/archinstall/lib/mirror/mirror_menu.py b/archinstall/lib/mirror/mirror_menu.py index 5158bffd..6c5de14a 100644 --- a/archinstall/lib/mirror/mirror_menu.py +++ b/archinstall/lib/mirror/mirror_menu.py @@ -13,8 +13,8 @@ from archinstall.lib.models.mirrors import ( SignOption, ) from archinstall.lib.models.packages import Repository -from archinstall.lib.output import FormattedOutput from archinstall.lib.translationhandler import tr +from archinstall.lib.utils.format import as_table from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType @@ -65,7 +65,7 @@ class CustomMirrorRepositoriesList(ListManager[CustomRepository]): async def _add_custom_repository(self, preset: CustomRepository | None = None) -> CustomRepository | None: edit_result = await Input( - header=tr('Enter a respository name'), + header=tr('Enter a repository name'), allow_skip=True, default_value=preset.name if preset else None, ).show() @@ -281,7 +281,7 @@ class MirrorMenu(AbstractSubMenu[MirrorConfiguration]): return None custom_mirrors: list[CustomRepository] = item.value - output = FormattedOutput.as_table(custom_mirrors) + output = as_table(custom_mirrors) return output.strip() def _prev_custom_servers(self, item: MenuItem) -> str | None: diff --git a/archinstall/lib/models/bootloader.py b/archinstall/lib/models/bootloader.py index 0dbd4268..bd6bce7e 100644 --- a/archinstall/lib/models/bootloader.py +++ b/archinstall/lib/models/bootloader.py @@ -3,8 +3,8 @@ from dataclasses import dataclass from enum import Enum from typing import Any, Self, override +from archinstall.lib.log import warn from archinstall.lib.models.config import SubConfig -from archinstall.lib.output import warn from archinstall.lib.translationhandler import tr diff --git a/archinstall/lib/models/device.py b/archinstall/lib/models/device.py index a21f3c6f..a50f7d8e 100644 --- a/archinstall/lib/models/device.py +++ b/archinstall/lib/models/device.py @@ -12,9 +12,9 @@ from parted import Disk, Geometry, Partition from pydantic import BaseModel, Field, ValidationInfo, field_serializer, field_validator from archinstall.lib.hardware import SysInfo +from archinstall.lib.log import debug from archinstall.lib.models.config import SubConfig from archinstall.lib.models.users import Password -from archinstall.lib.output import debug from archinstall.lib.translationhandler import tr ENC_IDENTIFIER = 'ainst' diff --git a/archinstall/lib/models/mirrors.py b/archinstall/lib/models/mirrors.py index 3ded2a9a..1d678328 100644 --- a/archinstall/lib/models/mirrors.py +++ b/archinstall/lib/models/mirrors.py @@ -9,10 +9,10 @@ from typing import TYPE_CHECKING, Any, Self, TypedDict, override from pydantic import BaseModel, ValidationInfo, field_validator, model_validator +from archinstall.lib.log import debug from archinstall.lib.models.config import SubConfig from archinstall.lib.models.packages import Repository from archinstall.lib.networking import DownloadTimer, ping -from archinstall.lib.output import debug from archinstall.lib.translationhandler import tr if TYPE_CHECKING: diff --git a/archinstall/lib/models/network.py b/archinstall/lib/models/network.py index 9e61cb56..bcbd288a 100644 --- a/archinstall/lib/models/network.py +++ b/archinstall/lib/models/network.py @@ -3,8 +3,8 @@ from dataclasses import dataclass, field from enum import Enum from typing import NotRequired, Self, TypedDict, override +from archinstall.lib.log import debug from archinstall.lib.models.config import SubConfig -from archinstall.lib.output import debug from archinstall.lib.translationhandler import tr @@ -12,6 +12,7 @@ class NicType(Enum): ISO = 'iso' NM = 'nm' NM_IWD = 'nm_iwd' + IWD = 'iwd' MANUAL = 'manual' def display_msg(self) -> str: @@ -22,6 +23,8 @@ class NicType(Enum): return tr('Use Network Manager (default backend)') case NicType.NM_IWD: return tr('Use Network Manager (iwd backend)') + case NicType.IWD: + return tr('Use standalone iwd') case NicType.MANUAL: return tr('Manual configuration') @@ -131,6 +134,10 @@ class NetworkConfiguration(SubConfig): return cls(NicType.ISO) case NicType.NM: return cls(NicType.NM) + case NicType.NM_IWD: + return cls(NicType.NM_IWD) + case NicType.IWD: + return cls(NicType.IWD) case NicType.MANUAL: nics_arg = config.get('nics', []) if nics_arg: diff --git a/archinstall/lib/network/network_handler.py b/archinstall/lib/network/network_handler.py index 13548584..09d2750c 100644 --- a/archinstall/lib/network/network_handler.py +++ b/archinstall/lib/network/network_handler.py @@ -1,3 +1,5 @@ +import textwrap + from archinstall.lib.installer import Installer from archinstall.lib.models.network import NetworkConfiguration, NicType from archinstall.lib.models.profile import ProfileConfiguration @@ -32,6 +34,13 @@ def install_network_config( _configure_nm_iwd(installation) installation.disable_service('iwd.service') + case NicType.IWD: + installation.add_additional_packages(['iwd']) + _configure_iwd_standalone(installation) + installation.enable_service('iwd.service') + installation.enable_service('systemd-networkd.service') + installation.enable_service('systemd-resolved.service') + case NicType.MANUAL: for nic in network_config.nics: installation.configure_nic(nic) @@ -45,3 +54,36 @@ def _configure_nm_iwd(installation: Installer) -> None: iwd_backend_conf = nm_conf_dir / 'wifi_backend.conf' _ = iwd_backend_conf.write_text('[device]\nwifi.backend=iwd\n') + + +def _configure_iwd_standalone(installation: Installer) -> None: + # iwd manages wireless only; systemd-networkd handles wired DHCP. + iwd_conf_dir = installation.target / 'etc/iwd' + iwd_conf_dir.mkdir(parents=True, exist_ok=True) + + main_conf = iwd_conf_dir / 'main.conf' + main_conf_content = textwrap.dedent("""\ + [General] + EnableNetworkConfiguration=true + + [Network] + NameResolvingService=systemd + """) + _ = main_conf.write_text(main_conf_content) + + networkd_dir = installation.target / 'etc/systemd/network' + networkd_dir.mkdir(parents=True, exist_ok=True) + wired_conf = networkd_dir / '20-wired.network' + wired_conf_content = textwrap.dedent("""\ + [Match] + Type=ether + Kind=!* + + [Network] + DHCP=yes + """) + _ = wired_conf.write_text(wired_conf_content) + + resolv = installation.target / 'etc/resolv.conf' + resolv.unlink(missing_ok=True) + resolv.symlink_to('/run/systemd/resolve/stub-resolv.conf') diff --git a/archinstall/lib/network/network_menu.py b/archinstall/lib/network/network_menu.py index 120af19e..88c26dba 100644 --- a/archinstall/lib/network/network_menu.py +++ b/archinstall/lib/network/network_menu.py @@ -202,6 +202,8 @@ async def select_network(preset: NetworkConfiguration | None) -> NetworkConfigur return NetworkConfiguration(NicType.NM) case NicType.NM_IWD: return NetworkConfiguration(NicType.NM_IWD) + case NicType.IWD: + return NetworkConfiguration(NicType.IWD) case NicType.MANUAL: preset_nics = preset.nics if preset else [] nics = await ManualNetworkConfig(tr('Configure interfaces'), preset_nics).show() diff --git a/archinstall/lib/network/wifi_handler.py b/archinstall/lib/network/wifi_handler.py index 4c858601..b5590343 100644 --- a/archinstall/lib/network/wifi_handler.py +++ b/archinstall/lib/network/wifi_handler.py @@ -5,9 +5,9 @@ from typing import assert_never, override from archinstall.lib.command import SysCommand from archinstall.lib.exceptions import SysCallError +from archinstall.lib.log import debug from archinstall.lib.models.network import WifiConfiguredNetwork, WifiNetwork from archinstall.lib.network.wpa_supplicant import WpaSupplicantConfig -from archinstall.lib.output import debug from archinstall.lib.translationhandler import tr from archinstall.tui.components import ConfirmationScreen, InputScreen, InstanceRunnable, LoadingScreen, NotifyScreen, TableSelectionScreen, tui from archinstall.tui.menu_item import MenuItem, MenuItemGroup diff --git a/archinstall/lib/network/wpa_supplicant.py b/archinstall/lib/network/wpa_supplicant.py index 935e9b4d..17ed3227 100644 --- a/archinstall/lib/network/wpa_supplicant.py +++ b/archinstall/lib/network/wpa_supplicant.py @@ -1,8 +1,8 @@ from dataclasses import dataclass, field from pathlib import Path +from archinstall.lib.log import debug from archinstall.lib.models.network import WifiNetwork -from archinstall.lib.output import debug @dataclass diff --git a/archinstall/lib/networking.py b/archinstall/lib/networking.py index e950a697..97701e89 100644 --- a/archinstall/lib/networking.py +++ b/archinstall/lib/networking.py @@ -13,7 +13,7 @@ from urllib.parse import urlencode from urllib.request import urlopen from archinstall.lib.exceptions import DownloadTimeout, SysCallError -from archinstall.lib.output import debug, error, info +from archinstall.lib.log import debug, error, info from archinstall.lib.pacman.pacman import Pacman diff --git a/archinstall/lib/output.py b/archinstall/lib/output.py deleted file mode 100644 index 86a47ed1..00000000 --- a/archinstall/lib/output.py +++ /dev/null @@ -1,415 +0,0 @@ -import logging -import os -import sys -import urllib.error -import urllib.request -from collections.abc import Callable -from dataclasses import asdict, is_dataclass -from datetime import UTC, datetime -from enum import Enum -from pathlib import Path -from typing import TYPE_CHECKING, Any - -from archinstall.lib.utils.encoding import unicode_ljust, unicode_rjust -from archinstall.tui.rich import BaseRichTable - -if TYPE_CHECKING: - from _typeshed import DataclassInstance - - -class FormattedOutput: - @staticmethod - def _get_values( - o: DataclassInstance, - class_formatter: str | Callable | None = None, # type: ignore[type-arg] # pyright: ignore[reportMissingTypeArgument] - filter_list: list[str] = [], - ) -> dict[str, Any]: - """ - the original values returned a dataclass as dict thru the call to some specific methods - this version allows thru the parameter class_formatter to call a dynamically selected formatting method. - Can transmit a filter list to the class_formatter, - """ - if class_formatter: - # if invoked per reference it has to be a standard function or a classmethod. - # A method of an instance does not make sense - if callable(class_formatter): - return class_formatter(o, filter_list) - # if is invoked by name we restrict it to a method of the class. No need to mess more - elif hasattr(o, class_formatter) and callable(getattr(o, class_formatter)): - func = getattr(o, class_formatter) - return func(filter_list) - - raise ValueError('Unsupported formatting call') - elif hasattr(o, 'table_data'): - return o.table_data() - elif hasattr(o, 'json'): - return o.json() - elif is_dataclass(o): - return asdict(o) - else: - return o.__dict__ # type: ignore[unreachable] - - @classmethod - def as_table( - cls, - obj: list[Any], - class_formatter: str | Callable | None = None, # type: ignore[type-arg] - filter_list: list[str] = [], - capitalize: bool = False, - ) -> str: - """variant of as_table (subtly different code) which has two additional parameters - filter which is a list of fields which will be shown - class_formatter a special method to format the outgoing data - - A general comment, the format selected for the output (a string where every data record is separated by newline) - is for compatibility with a print statement - As_table_filter can be a drop in replacement for as_table - """ - raw_data = [cls._get_values(o, class_formatter, filter_list) for o in obj] - - # determine the maximum column size - column_width: dict[str, int] = {} - for o in raw_data: - for k, v in o.items(): - if not filter_list or k in filter_list: - column_width.setdefault(k, 0) - column_width[k] = max([column_width[k], len(str(v)), len(k)]) - - if not filter_list: - filter_list = list(column_width.keys()) - - # create the header lines - output = '' - key_list = [] - for key in filter_list: - width = column_width[key] - key = key.replace('!', '').replace('_', ' ') - - if capitalize: - key = key.capitalize() - - key_list.append(unicode_ljust(key, width)) - - output += ' | '.join(key_list) + '\n' - output += '-' * len(output) + '\n' - - # create the data lines - for record in raw_data: - obj_data = [] - for key in filter_list: - width = column_width.get(key, len(key)) - value = record.get(key, '') - - if '!' in key: - value = '*' * len(value) - - if isinstance(value, (int, float)) or (isinstance(value, str) and value.isnumeric()): - obj_data.append(unicode_rjust(str(value), width)) - else: - obj_data.append(unicode_ljust(str(value), width)) - - output += ' | '.join(obj_data) + '\n' - - return output - - @staticmethod - def as_columns(entries: list[str], cols: int) -> str: - """ - Will format a list into a given number of columns - """ - chunks = [] - output = '' - - for i in range(0, len(entries), cols): - chunks.append(entries[i : i + cols]) - - for row in chunks: - out_fmt = '{: <30} ' * len(row) - output += out_fmt.format(*row) + '\n' - - return output - - -def as_key_value_pair( - entries: dict[str, str | list[str] | bool], - ignore_empty: bool = True, -) -> str: - """ - Formats key-values as a Rich Table: - key1 : value1 - key2 : value2 - ... - """ - table = BaseRichTable() - table.add_column('key', style='bold', no_wrap=True) - table.add_column('value', style='white', max_width=70) - - for label, value in entries.items(): - if ignore_empty and not value: - continue - - if isinstance(value, bool): - value = 'Yes' if value else 'No' - - if isinstance(value, list): - value = '\n '.join(str(val) for val in value) - - table.add_row(label.title(), f': {value}') - - return table.stringify() - - -class Journald: - @staticmethod - def log(message: str, level: int = logging.DEBUG) -> None: - try: - import systemd.journal # type: ignore[import-not-found] - except ModuleNotFoundError: - return - - log_adapter = logging.getLogger('archinstall') - log_fmt = logging.Formatter('[%(levelname)s]: %(message)s') - log_ch = systemd.journal.JournalHandler() - log_ch.setFormatter(log_fmt) - log_adapter.addHandler(log_ch) - log_adapter.setLevel(logging.DEBUG) - - log_adapter.log(level, message) - - -class Logger: - def __init__(self, path: Path = Path('/var/log/archinstall')) -> None: - self._path = path - - @property - def path(self) -> Path: - return self._path / 'install.log' - - @property - def directory(self) -> Path: - return self._path - - def _check_permissions(self) -> None: - log_file = self.path - - try: - self._path.mkdir(exist_ok=True, parents=True) - log_file.touch(exist_ok=True) - - with log_file.open('a') as f: - f.write('') - except PermissionError: - # Fallback to creating the log file in the current folder - logger._path = Path('./').absolute() - - warn(f'Not enough permission to place log file at {log_file}, creating it in {logger.path} instead') - - def log(self, level: int, content: str) -> None: - self._check_permissions() - - with self.path.open('a') as f: - ts = _timestamp() - level_name = logging.getLevelName(level) - f.write(f'[{ts}] - {level_name} - {content}\n') - - -logger = Logger() - - -def _supports_color() -> bool: - """ - Found first reference here: - https://stackoverflow.com/questions/7445658/how-to-detect-if-the-console-does-support-ansi-escape-codes-in-python - And re-used this: - https://github.com/django/django/blob/master/django/core/management/color.py#L12 - - Return True if the running system's terminal supports color, - and False otherwise. - """ - supported_platform = sys.platform != 'win32' or 'ANSICON' in os.environ - - # isatty is not always implemented, #6223. - is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() - return supported_platform and is_a_tty - - -class Font(Enum): - bold = '1' - italic = '3' - underscore = '4' - blink = '5' - reverse = '7' - conceal = '8' - - -def _stylize_output( - text: str, - fg: str, - bg: str | None, - reset: bool, - font: list[Font] = [], -) -> str: - """ - Heavily influenced by: - https://github.com/django/django/blob/ae8338daf34fd746771e0678081999b656177bae/django/utils/termcolors.py#L13 - Color options here: - https://askubuntu.com/questions/528928/how-to-do-underline-bold-italic-strikethrough-color-background-and-size-i - - Adds styling to a text given a set of color arguments. - """ - colors = { - 'black': '0', - 'red': '1', - 'green': '2', - 'yellow': '3', - 'blue': '4', - 'magenta': '5', - 'cyan': '6', - 'white': '7', - 'teal': '8;5;109', # Extended 256-bit colors (not always supported) - 'orange': '8;5;208', # https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#256-colors - 'darkorange': '8;5;202', - 'gray': '8;5;246', - 'grey': '8;5;246', - 'darkgray': '8;5;240', - 'lightgray': '8;5;256', - } - - foreground = {key: f'3{colors[key]}' for key in colors} - background = {key: f'4{colors[key]}' for key in colors} - code_list = [] - - if text == '' and reset: - return '\x1b[0m' - - code_list.append(foreground[str(fg)]) - - if bg: - code_list.append(background[str(bg)]) - - for o in font: - code_list.append(o.value) - - ansi = ';'.join(code_list) - - return f'\033[{ansi}m{text}\033[0m' - - -def info( - *msgs: str, - level: int = logging.INFO, - fg: str = 'white', - bg: str | None = None, - reset: bool = False, - font: list[Font] = [], -) -> None: - log(*msgs, level=level, fg=fg, bg=bg, reset=reset, font=font) - - -def _timestamp() -> str: - now = datetime.now(tz=UTC) - return now.strftime('%Y-%m-%d %H:%M:%S') - - -def debug( - *msgs: str, - level: int = logging.DEBUG, - fg: str = 'white', - bg: str | None = None, - reset: bool = False, - font: list[Font] = [], -) -> None: - log(*msgs, level=level, fg=fg, bg=bg, reset=reset, font=font) - - -def error( - *msgs: str, - level: int = logging.ERROR, - fg: str = 'red', - bg: str | None = None, - reset: bool = False, - font: list[Font] = [], -) -> None: - log(*msgs, level=level, fg=fg, bg=bg, reset=reset, font=font) - - -def warn( - *msgs: str, - level: int = logging.WARNING, - fg: str = 'yellow', - bg: str | None = None, - reset: bool = False, - font: list[Font] = [], -) -> None: - log(*msgs, level=level, fg=fg, bg=bg, reset=reset, font=font) - - -def log( - *msgs: str, - level: int = logging.INFO, - fg: str = 'white', - bg: str | None = None, - reset: bool = False, - font: list[Font] = [], -) -> None: - text = ' '.join(str(x) for x in msgs) - - logger.log(level, text) - - # Attempt to colorize the output if supported - # Insert default colors and override with **kwargs - if _supports_color(): - text = _stylize_output(text, fg, bg, reset, font) - - Journald.log(text, level=level) - - if level != logging.DEBUG: - print(text) - - -def share_install_log( - paste_url: str = 'https://paste.rs', - max_size: int = 10 * 1024 * 1024, - confirm: Callable[[str], bool] = lambda _: True, -) -> int: - log_path = logger.path - - if not log_path.exists(): - info(f'Log file not found: {log_path}') - return 1 - - size = log_path.stat().st_size - if size == 0: - info(f'Log file is empty: {log_path}') - return 1 - - if size > max_size: - info(f'Log file exceeds {max_size} bytes, uploading last {max_size} bytes') - content = log_path.read_bytes()[-max_size:] - else: - content = log_path.read_bytes() - - header = f'About to upload {log_path} ({len(content)} bytes) to {paste_url}\n\n' - header += 'The log may contain hostname, mirror URLs, package list and partition layout.\n' - header += 'The uploaded paste is public.\n\n' - header += 'Continue?' - - if not confirm(header): - info('Cancelled.') - return 1 - - try: - req = urllib.request.Request(paste_url, data=content) - with urllib.request.urlopen(req) as response: - url = response.read().decode().strip() - except urllib.error.URLError as e: - info(f'Upload failed: {e}') - return 1 - - if not url.startswith('http'): - info(f'Unexpected response from {paste_url}: {url[:200]!r}') - return 1 - - # raw print so the URL is pipe-friendly (no ANSI colors, no log prefix) - print(url) - return 0 diff --git a/archinstall/lib/packages/packages.py b/archinstall/lib/packages/packages.py index a7422986..5b276f76 100644 --- a/archinstall/lib/packages/packages.py +++ b/archinstall/lib/packages/packages.py @@ -1,9 +1,9 @@ from functools import lru_cache from archinstall.lib.exceptions import SysCallError +from archinstall.lib.log import debug from archinstall.lib.menu.helpers import Loading, Notify, Selection from archinstall.lib.models.packages import AvailablePackage, LocalPackage, PackageGroup, Repository -from archinstall.lib.output import debug from archinstall.lib.pacman.pacman import Pacman from archinstall.lib.translationhandler import tr from archinstall.tui.menu_item import MenuItem, MenuItemGroup diff --git a/archinstall/lib/packages/util.py b/archinstall/lib/packages/util.py index 335d312e..134592bb 100644 --- a/archinstall/lib/packages/util.py +++ b/archinstall/lib/packages/util.py @@ -1,6 +1,6 @@ from functools import lru_cache -from archinstall.lib.output import debug +from archinstall.lib.log import debug from archinstall.lib.packages.packages import check_package_upgrade diff --git a/archinstall/lib/pacman/pacman.py b/archinstall/lib/pacman/pacman.py index 83f8b40d..c78f6145 100644 --- a/archinstall/lib/pacman/pacman.py +++ b/archinstall/lib/pacman/pacman.py @@ -5,7 +5,7 @@ from pathlib import Path from archinstall.lib.command import SysCommand from archinstall.lib.exceptions import RequirementError -from archinstall.lib.output import error, info, warn +from archinstall.lib.log import error, info, warn from archinstall.lib.pathnames import PACMAN_CONF from archinstall.lib.plugins import plugins from archinstall.lib.translationhandler import tr diff --git a/archinstall/lib/plugins.py b/archinstall/lib/plugins.py index 919fcf23..ac8383b1 100644 --- a/archinstall/lib/plugins.py +++ b/archinstall/lib/plugins.py @@ -7,7 +7,7 @@ import urllib.request from importlib import metadata from pathlib import Path -from archinstall.lib.output import error, info, warn +from archinstall.lib.log import error, info, warn from archinstall.lib.version import get_version plugins = {} diff --git a/archinstall/lib/profile/profiles_handler.py b/archinstall/lib/profile/profiles_handler.py index c75f95c0..1e770de5 100644 --- a/archinstall/lib/profile/profiles_handler.py +++ b/archinstall/lib/profile/profiles_handler.py @@ -9,9 +9,9 @@ from typing import TYPE_CHECKING, NotRequired, TypedDict from archinstall.default_profiles.profile import CustomSetting, GreeterType, Profile from archinstall.lib.hardware import GfxDriver, GfxPackage +from archinstall.lib.log import debug, error, info from archinstall.lib.models.profile import ProfileConfiguration from archinstall.lib.networking import fetch_data_from_url -from archinstall.lib.output import debug, error, info from archinstall.lib.translationhandler import tr if TYPE_CHECKING: @@ -175,6 +175,9 @@ class ProfileHandler: case GreeterType.PlasmaLoginManager: packages = ['plasma-login-manager'] service = ['plasmalogin'] + case GreeterType.GreetdDms: + packages = ['greetd'] + service = ['greetd'] if packages: install_session.add_additional_packages(packages) @@ -194,6 +197,26 @@ class ProfileHandler: with open(path, 'w') as file: file.write(filedata) + if greeter == GreeterType.GreetdDms: + greetd_config = install_session.target / 'etc/greetd/config.toml' + greetd_config.parent.mkdir(parents=True, exist_ok=True) + greetd_config.write_text( + '[terminal]\n' + 'vt = 1\n' + '\n' + '[default_session]\n' + 'user = "greeter"\n' + 'command = "/usr/share/quickshell/dms/Modules/Greetd/assets/dms-greeter --command niri -p /usr/share/quickshell/dms"\n', + ) + + tmpfiles = install_session.target / 'etc/tmpfiles.d/dms-greeter.conf' + tmpfiles.parent.mkdir(parents=True, exist_ok=True) + tmpfiles.write_text( + '# Path Mode User Group Age Argument\n' + 'd /var/cache/dms-greeter 0750 greeter greeter -\n' + 'd /var/lib/greeter 0755 greeter greeter -\n', + ) + def install_gfx_driver(self, install_session: Installer, driver: GfxDriver) -> None: debug(f'Installing GFX driver: {driver.value}') diff --git a/archinstall/lib/translationhandler.py b/archinstall/lib/translationhandler.py index 093ca6de..c2736f35 100644 --- a/archinstall/lib/translationhandler.py +++ b/archinstall/lib/translationhandler.py @@ -9,7 +9,7 @@ from typing import override from archinstall.lib.command import SysCommand from archinstall.lib.exceptions import SysCallError -from archinstall.lib.output import debug +from archinstall.lib.log import debug from archinstall.lib.utils.util import running_from_iso diff --git a/archinstall/lib/utils/format.py b/archinstall/lib/utils/format.py new file mode 100644 index 00000000..2ac8c377 --- /dev/null +++ b/archinstall/lib/utils/format.py @@ -0,0 +1,148 @@ +from collections.abc import Callable +from dataclasses import asdict, is_dataclass +from typing import TYPE_CHECKING, Any + +from archinstall.lib.utils.encoding import unicode_ljust, unicode_rjust +from archinstall.tui.rich import BaseRichTable + +if TYPE_CHECKING: + from _typeshed import DataclassInstance + + +def as_key_value_pair( + entries: dict[str, str | list[str] | bool], + ignore_empty: bool = True, +) -> str: + """ + Formats key-values as a Rich Table: + key1 : value1 + key2 : value2 + ... + """ + table = BaseRichTable() + table.add_column('key', style='bold', no_wrap=True) + table.add_column('value', style='white', max_width=70) + + for label, value in entries.items(): + if ignore_empty and not value: + continue + + if isinstance(value, bool): + value = 'Yes' if value else 'No' + + if isinstance(value, list): + value = '\n '.join(str(val) for val in value) + + table.add_row(label.title(), f': {value}') + + return table.stringify() + + +def as_columns(entries: list[str], cols: int) -> str: + """ + Will format a list into a given number of columns + """ + chunks: list[list[str]] = [] + output = '' + + for i in range(0, len(entries), cols): + chunks.append(entries[i : i + cols]) + + for row in chunks: + out_fmt = '{: <30} ' * len(row) + output += out_fmt.format(*row) + '\n' + + return output + + +def _get_values( + o: DataclassInstance, + class_formatter: str | Callable | None = None, # type: ignore[type-arg] # pyright: ignore[reportMissingTypeArgument] + filter_list: list[str] = [], +) -> dict[str, Any]: + """ + the original values returned a dataclass as dict thru the call to some specific methods + this version allows thru the parameter class_formatter to call a dynamically selected formatting method. + Can transmit a filter list to the class_formatter, + """ + if class_formatter: + # if invoked per reference it has to be a standard function or a classmethod. + # A method of an instance does not make sense + if callable(class_formatter): + return class_formatter(o, filter_list) + # if is invoked by name we restrict it to a method of the class. No need to mess more + elif hasattr(o, class_formatter) and callable(getattr(o, class_formatter)): + func = getattr(o, class_formatter) + return func(filter_list) + + raise ValueError('Unsupported formatting call') + elif hasattr(o, 'table_data'): + return o.table_data() + elif hasattr(o, 'json'): + return o.json() + elif is_dataclass(o): + return asdict(o) + else: + return o.__dict__ # type: ignore[unreachable] + + +def as_table( + obj: list[Any], + class_formatter: str | Callable | None = None, # type: ignore[type-arg] + filter_list: list[str] = [], + capitalize: bool = False, +) -> str: + """variant of as_table (subtly different code) which has two additional parameters + filter which is a list of fields which will be shown + class_formatter a special method to format the outgoing data + + A general comment, the format selected for the output (a string where every data record is separated by newline) + is for compatibility with a print statement + As_table_filter can be a drop in replacement for as_table + """ + raw_data = [_get_values(o, class_formatter, filter_list) for o in obj] + + # determine the maximum column size + column_width: dict[str, int] = {} + for o in raw_data: + for k, v in o.items(): + if not filter_list or k in filter_list: + column_width.setdefault(k, 0) + column_width[k] = max([column_width[k], len(str(v)), len(k)]) + + if not filter_list: + filter_list = list(column_width.keys()) + + # create the header lines + output = '' + key_list = [] + for key in filter_list: + width = column_width[key] + key = key.replace('!', '').replace('_', ' ') + + if capitalize: + key = key.capitalize() + + key_list.append(unicode_ljust(key, width)) + + output += ' | '.join(key_list) + '\n' + output += '-' * len(output) + '\n' + + # create the data lines + for record in raw_data: + obj_data = [] + for key in filter_list: + width = column_width.get(key, len(key)) + value = record.get(key, '') + + if '!' in key: + value = '*' * len(value) + + if isinstance(value, (int, float)) or (isinstance(value, str) and value.isnumeric()): + obj_data.append(unicode_rjust(str(value), width)) + else: + obj_data.append(unicode_ljust(str(value), width)) + + output += ' | '.join(obj_data) + '\n' + + return output diff --git a/archinstall/lib/utils/util.py b/archinstall/lib/utils/util.py index 574cc8d5..f94ca18c 100644 --- a/archinstall/lib/utils/util.py +++ b/archinstall/lib/utils/util.py @@ -1,8 +1,14 @@ import secrets import string +from datetime import UTC, datetime -from archinstall.lib.output import FormattedOutput from archinstall.lib.pathnames import ARCHISO_MOUNTPOINT +from archinstall.lib.utils.format import as_columns + + +def timestamp() -> str: + now = datetime.now(tz=UTC) + return now.strftime('%Y-%m-%d %H:%M:%S') def running_from_iso() -> bool: @@ -36,7 +42,7 @@ def format_cols(items: list[str], header: str | None = None) -> str: else: col = 4 - text += FormattedOutput.as_columns(items, col) + text += as_columns(items, col) # remove whitespaces on each row text = '\n'.join(t.strip() for t in text.split('\n')) return text diff --git a/archinstall/locales/base.pot b/archinstall/locales/base.pot index 0b08df29..4db4554c 100644 --- a/archinstall/locales/base.pot +++ b/archinstall/locales/base.pot @@ -1245,7 +1245,7 @@ msgid "Product" msgstr "" #, python-brace-format -msgid "Invalid configuration: {error}" +msgid "Invalid configuration: {}" msgstr "" msgid "Ready to install" @@ -2304,3 +2304,162 @@ msgstr "" #, python-brace-format msgid "Choose an option how to give {} access to your hardware" msgstr "" + +#, python-brace-format +msgid "About to upload \"{}\" to the publicly accessible {}" +msgstr "" + +msgid "Do you want to continue?" +msgstr "" + +#, python-brace-format +msgid "Log uploaded successfully. URL: {}" +msgstr "" + +msgid "Failed to upload log." +msgstr "" + +msgid "ArchInstall Language" +msgstr "" + +msgid "Version" +msgstr "" + +msgid "Installation Script" +msgstr "" + +msgid "Application" +msgstr "" + +msgid "Services" +msgstr "" + +msgid "Custom commands" +msgstr "" + +msgid "Users" +msgstr "" + +msgid "Root encrypted password" +msgstr "" + +msgid "Zram enabled" +msgstr "" + +#, python-brace-format +msgid "Zram algorithm {}" +msgstr "" + +msgid "Bluetooth enabled" +msgstr "" + +#, python-brace-format +msgid "Audio server \"{}\"" +msgstr "" + +#, python-brace-format +msgid "Power management \"{}\"" +msgstr "" + +msgid "Print service enabled" +msgstr "" + +#, python-brace-format +msgid "Firewall \"{}\"" +msgstr "" + +#, python-brace-format +msgid "Extra fonts \"{}\"" +msgstr "" + +msgid "Root password set" +msgstr "" + +#, python-brace-format +msgid "Configured {} user(s)" +msgstr "" + +msgid "U2F set up" +msgstr "" + +#, python-brace-format +msgid "Bootloader \"{}\"" +msgstr "" + +msgid "UKI enabled" +msgstr "" + +msgid "Default" +msgstr "" + +msgid "Manual" +msgstr "" + +msgid "Pre-mount" +msgstr "" + +#, python-brace-format +msgid "{} layout" +msgstr "" + +#, python-brace-format +msgid "Devices {}" +msgstr "" + +msgid "LVM set up" +msgstr "" + +#, python-brace-format +msgid "{} encryption" +msgstr "" + +#, python-brace-format +msgid "Btrfs snapshot \"{}\"" +msgstr "" + +#, python-brace-format +msgid "Keyboard layout \"{}\"" +msgstr "" + +#, python-brace-format +msgid "Locale language \"{}\"" +msgstr "" + +#, python-brace-format +msgid "Locale encoding \"{}\"" +msgstr "" + +#, python-brace-format +msgid "Console font \"{}\"" +msgstr "" + +#, python-brace-format +msgid "Mirror regions \"{}\"" +msgstr "" + +#, python-brace-format +msgid "Optional repositories \"{}\"" +msgstr "" + +msgid "Custom servers set up" +msgstr "" + +msgid "Custom repositories set up" +msgstr "" + +msgid "Use standalone iwd" +msgstr "" + +msgid "Color enabled" +msgstr "" + +#, python-brace-format +msgid "{} grphics driver" +msgstr "" + +#, python-brace-format +msgid "{} greeter" +msgstr "" + +msgid "Enter a repository name" +msgstr "" diff --git a/archinstall/locales/fi/LC_MESSAGES/base.po b/archinstall/locales/fi/LC_MESSAGES/base.po index 31cf6af2..9534151e 100644 --- a/archinstall/locales/fi/LC_MESSAGES/base.po +++ b/archinstall/locales/fi/LC_MESSAGES/base.po @@ -2190,7 +2190,7 @@ msgstr "Valittu työpöydän profiili vaati tavallisen käyttäjän kirjautumise #, python-brace-format msgid "Environment type: {} {}" -msgstr "Ympäristötyyppi: {}" +msgstr "Ympäristötyyppi: {} {}" msgid "Input cannot be empty" msgstr "Syöttö ei voi olla tyhjä" @@ -2245,4 +2245,4 @@ msgstr "Määritetään U2F laitetta käyttäjälle: {}" #, python-brace-format msgid "Default: {}ms, Recommended range: 1000-60000" -msgstr "Oletusarvo: 10000ms, suositeltu 1000-60000ms" +msgstr "Oletusarvo: {}ms, suositeltu 1000-60000ms" diff --git a/archinstall/locales/hi/LC_MESSAGES/base.po b/archinstall/locales/hi/LC_MESSAGES/base.po index 9d64d477..3cfe309f 100644 --- a/archinstall/locales/hi/LC_MESSAGES/base.po +++ b/archinstall/locales/hi/LC_MESSAGES/base.po @@ -1502,9 +1502,6 @@ msgstr "सक्षम" msgid "Disabled" msgstr "अक्षम" -msgid "Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues" -msgstr "कृपया इस समस्या (और फ़ाइल) को https://github.com/archlinux/archinstall/issues पर सबमिट करें।" - msgid "Mirror name" msgstr "मिरर का नाम" diff --git a/archinstall/locales/it/LC_MESSAGES/base.mo b/archinstall/locales/it/LC_MESSAGES/base.mo index 79d934d4..a4166e67 100644 Binary files a/archinstall/locales/it/LC_MESSAGES/base.mo and b/archinstall/locales/it/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/it/LC_MESSAGES/base.po b/archinstall/locales/it/LC_MESSAGES/base.po index 55585263..f46e8a73 100644 --- a/archinstall/locales/it/LC_MESSAGES/base.po +++ b/archinstall/locales/it/LC_MESSAGES/base.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2026-04-12 10:26+0200\n" +"PO-Revision-Date: 2026-05-16 12:52+0200\n" "Last-Translator: Van Matten\n" "Language-Team: Alessio Cuccovillo , Van Matten\n" "Language: it\n" @@ -56,7 +56,7 @@ msgid "Only packages such as base, base-devel, linux, linux-firmware, efibootmgr msgstr "Vengono installati solo pacchetti come base, base-devel, linux, linux-firmware, efibootmgr e pacchetti di profilo opzionali." msgid "Note: base-devel is no longer installed by default. Add it here if you need build tools." -msgstr "Nota: base-devel non è più installato di default. Aggiungilo qui se ti servono i build tools." +msgstr "Nota: base-devel non è più installato come predefinito. Aggiungilo qui se ti servono i build tools." msgid "If you desire a web browser, such as firefox or chromium, you may specify it in the following prompt." msgstr "Se desideri un browser web, come Firefox o Chromium, puoi specificarlo nel seguente prompt." @@ -118,7 +118,7 @@ msgid "" msgstr "" "{}\n" "\n" -"Seleziona per indice quali partizioni eliminare" +"Seleziona per indice le partizioni da eliminare" msgid "" "{}\n" @@ -127,13 +127,13 @@ msgid "" msgstr "" "{}\n" "\n" -"Seleziona per indice quale partizione montare dove" +"Seleziona per indice la partizione dove montare" msgid " * Partition mount-points are relative to inside the installation, the boot would be /boot as an example." -msgstr " * I punti di mount della partizione sono relativi all'interno dell'installazione, per esempio l'avvio sarebbe /boot." +msgstr " * I punti di montaggio della partizione sono relativi all'interno dell'installazione, per esempio l'avvio sarebbe /boot." msgid "Select where to mount partition (leave blank to remove mountpoint): " -msgstr "Seleziona dove montare la partizione (lascia vuoto per rimuovere il punto di mount): " +msgstr "Seleziona dove montare la partizione (lascia vuoto per rimuovere il punto di montaggio): " msgid "" "{}\n" @@ -142,7 +142,7 @@ msgid "" msgstr "" "{}\n" "\n" -"Seleziona quale partizione mascherare per la formattazione" +"Seleziona la partizione da mascherare per la formattazione" msgid "" "{}\n" @@ -151,7 +151,7 @@ msgid "" msgstr "" "{}\n" "\n" -"Seleziona quale partizione contrassegnare come crittografata" +"Seleziona la partizione da contrassegnare come crittografata" msgid "" "{}\n" @@ -160,7 +160,7 @@ msgid "" msgstr "" "{}\n" "\n" -"Seleziona quale partizione contrassegnare come avviabile" +"Seleziona la partizione da contrassegnare come avviabile" msgid "" "{}\n" @@ -169,7 +169,7 @@ msgid "" msgstr "" "{}\n" "\n" -"Seleziona su quale partizione impostare un filesystem" +"Seleziona la partizione su cui impostare un filesystem" msgid "Enter a desired filesystem type for the partition: " msgstr "Inserisci un tipo di filesystem desiderato per la partizione: " @@ -187,7 +187,7 @@ msgid "Select what you wish to do with the selected block devices" msgstr "Seleziona cosa desideri fare con i dispositivi a blocchi selezionati" msgid "This is a list of pre-programmed profiles, they might make it easier to install things like desktop environments" -msgstr "Questo è un elenco di profili pre-programmati, che potrebbero semplificare l'installazione di elementi come gli ambienti desktop" +msgstr "Questo è un elenco di profili preprogrammati, che potrebbero semplificare l'installazione di elementi come gli ambienti desktop" msgid "Select keyboard layout" msgstr "Seleziona il layout della tastiera" @@ -196,7 +196,7 @@ msgid "Select one of the regions to download packages from" msgstr "Seleziona una delle regioni da cui scaricare i pacchetti" msgid "Select one or more hard drives to use and configure" -msgstr "Seleziona uno o più dischi rigidi da utilizzare e configurare" +msgstr "Seleziona uno o più unità da utilizzare e configurare" msgid "For the best compatibility with your AMD hardware, you may want to use either the all open-source or AMD / ATI options." msgstr "Per la migliore compatibilità con il tuo hardware AMD, potresti voler utilizzare tutte le opzioni open source o AMD / ATI." @@ -220,13 +220,13 @@ msgid "All open-source (default)" msgstr "Tutti gli open source (predefinito)" msgid "Choose which kernels to use or leave blank for default \"{}\"" -msgstr "Scegli quali kernel usare o lascia vuoto per il predefinito \"{}\"" +msgstr "Scegli i kernel da usare o lascia vuoto per il predefinito \"{}\"" msgid "Choose which locale language to use" -msgstr "Scegli quale lingua locale utilizzare" +msgstr "Scegli la lingua da usare" msgid "Choose which locale encoding to use" -msgstr "Scegli quale codifica locale utilizzare" +msgstr "Scegli la codifica da usare" msgid "Select one of the values shown below: " msgstr "Seleziona uno dei valori mostrati di seguito: " @@ -235,7 +235,7 @@ msgid "Select one or more of the options below: " msgstr "Seleziona una o più delle seguenti opzioni " msgid "Adding partition...." -msgstr "Aggiungendo la partizione...." +msgstr "Aggiunta della partizione in corso..." msgid "You need to enter a valid fs-type in order to continue. See `man parted` for valid fs-type's." msgstr "Devi inserire un tipo di filesystem valido per continuare. Vedi `man parted` per tipi di filesystem validi." @@ -253,13 +253,16 @@ msgid "Mirror region" msgstr "Regione dei mirror" msgid "Locale language" -msgstr "Lingua locale" +msgstr "Lingua" msgid "Locale encoding" -msgstr "Codifica locale" +msgstr "Codifica" + +msgid "Console font" +msgstr "Font della console" msgid "Drive(s)" -msgstr "Dischi" +msgstr "Unità" msgid "Disk layout" msgstr "Layout del disco" @@ -301,7 +304,7 @@ msgid "Automatic time sync (NTP)" msgstr "Sincronizzazione automatica dell'ora (NTP)" msgid "Install ({} config(s) missing)" -msgstr "Installa ({} configurazioni mancanti)" +msgstr "Installa ({} configurazione/i mancante/i)" msgid "" "You decided to skip harddrive selection\n" @@ -309,7 +312,7 @@ msgid "" "WARNING: Archinstall won't check the suitability of this setup\n" "Do you wish to continue?" msgstr "" -"Hai deciso di saltare la selezione del disco rigido\n" +"Hai deciso di saltare la selezione dell'unità\n" "e utilizzerà qualsiasi configurazione dell'unità montata su {} (sperimentale)\n" "ATTENZIONE: Archinstall non verificherà l'idoneità di questa configurazione\n" "Vuoi continuare?" @@ -327,7 +330,7 @@ msgid "Clear/Delete all partitions" msgstr "Cancella/Elimina tutte le partizioni" msgid "Assign mount-point for a partition" -msgstr "Assegna punto di mount per una partizione" +msgstr "Assegna punto di montaggio per una partizione" msgid "Mark/Unmark a partition to be formatted (wipes data)" msgstr "Seleziona/Deseleziona una partizione da formattare (cancella i dati)" @@ -376,7 +379,7 @@ msgid "Enter a encryption password for {}" msgstr "Inserisci una password di crittografia per {}" msgid "Enter disk encryption password (leave blank for no encryption): " -msgstr "Inserisci la password di crittografia del disco (lasciare vuoto per nessuna crittografia): " +msgstr "Inserisci la password di crittografia del disco (lascia vuoto per nessuna crittografia): " msgid "Create a required super-user with sudo privileges: " msgstr "Crea un superuser richiesto con privilegi sudo: " @@ -454,7 +457,7 @@ msgid "Pre-existing pacman lock never exited. Please clean up any existing pacma msgstr "Il lock di pacman preesistente non è mai terminato. Rimuovi ogni sessione pacman esistente prima di usare archinstall." msgid "Choose which optional additional repositories to enable" -msgstr "Scegli quali repository aggiuntivi facoltativi abilitare" +msgstr "Scegli i repository aggiuntivi facoltativi da abilitare" msgid "Add a user" msgstr "Aggiungi un utente" @@ -476,7 +479,7 @@ msgstr "" "Definisci un nuovo utente\n" msgid "User Name : " -msgstr "Nome utente : " +msgstr "Nome utente: " msgid "Should {} be a superuser (sudoer)?" msgstr "{} dovrebbe essere un superuser (sudoer)?" @@ -497,7 +500,7 @@ msgid "" msgstr "" "{}\n" "\n" -"Seleziona su quale partizione impostare i sottovolumi" +"Seleziona la partizione su cui impostare i sottovolumi" msgid "Manage btrfs subvolumes for current partition" msgstr "Gestisci i sottovolumi btrfs per la partizione corrente" @@ -518,7 +521,7 @@ msgid "Save all" msgstr "Salva tutto" msgid "Choose which configuration to save" -msgstr "Scegli quale configurazione salvare" +msgstr "Scegli la configurazione da salvare" msgid "Enter a directory for the configuration(s) to be saved: " msgstr "Inserisci una cartella in cui salvare le configurazioni: " @@ -570,7 +573,7 @@ msgid "Subvolume name " msgstr "Nome del sottovolume " msgid "Subvolume mountpoint" -msgstr "Punto di mount del sottovolume" +msgstr "Punto di montaggio del sottovolume" msgid "Subvolume options" msgstr "Opzioni del sottovolume" @@ -579,10 +582,10 @@ msgid "Save" msgstr "Salva" msgid "Subvolume name :" -msgstr "Nome del sottovolume :" +msgstr "Nome del sottovolume:" msgid "Select a mount point :" -msgstr "Seleziona un punto di mount:" +msgstr "Seleziona un punto di montaggio:" msgid "Select the desired subvolume options " msgstr "Seleziona le opzioni del sottovolume desiderate " @@ -607,10 +610,10 @@ msgid "The selected drives do not have the minimum capacity required for an auto msgstr "Le unità selezionate non hanno la capacità minima richiesta per un suggerimento automatico\n" msgid "Minimum capacity for /home partition: {}GB\n" -msgstr "Capacità minima per la partizione /home: {}GB\n" +msgstr "Capacità minima per la partizione /home: {} GB\n" msgid "Minimum capacity for Arch Linux partition: {}GB" -msgstr "Capacità minima per la partizione Arch Linux: {}GB" +msgstr "Capacità minima per la partizione Arch Linux: {} GB" msgid "Continue" msgstr "Continua" @@ -661,13 +664,13 @@ msgid "Select your desired desktop environment" msgstr "Seleziona l'ambiente desktop desiderato" msgid "A very basic installation that allows you to customize Arch Linux as you see fit." -msgstr "Un'installazione molto semplice che ti consente di personalizzare Arch Linux come meglio credi." +msgstr "Un'installazione molto semplificata che ti consente di personalizzare Arch Linux come meglio credi." msgid "Provides a selection of various server packages to install and enable, e.g. httpd, nginx, mariadb" msgstr "Fornisce una selezione di vari pacchetti server da installare e abilitare, per esempio httpd, nginx, mariadb" msgid "Choose which servers to install, if none then a minimal installation will be done" -msgstr "Scegli quali server installare, se nessuno verrà eseguita un'installazione minima" +msgstr "Scegli i server da installare, se non ne sarà selezionato nessuno, verrà eseguita un'installazione minima" msgid "Installs a minimal system as well as xorg and graphics drivers." msgstr "Installa un sistema minimo oltre a xorg e driver grafici." @@ -682,13 +685,13 @@ msgid "Are you sure you want to reset this setting?" msgstr "Sei sicuro di voler ripristinare questa impostazione?" msgid "Select one or more hard drives to use and configure\n" -msgstr "Seleziona uno o più dischi rigidi da utilizzare e configurare\n" +msgstr "Seleziona uno o più unità da utilizzare e configurare\n" msgid "Any modifications to the existing setting will reset the disk layout!" msgstr "Qualsiasi modifica all'impostazione esistente ripristinerà il layout del disco!" msgid "If you reset the harddrive selection this will also reset the current disk layout. Are you sure?" -msgstr "Se si ripristina la selezione del disco rigido, verrà ripristinato anche il layout del disco corrente. Sei sicuro?" +msgstr "Se ripristini la selezione dell'unità, verrà ripristinato anche il layout del disco corrente. Sei sicuro?" msgid "Save and exit" msgstr "Salva ed esci" @@ -741,7 +744,7 @@ msgid "Select one of the disks or skip and use /mnt as default" msgstr "Seleziona uno dei dischi o salta e usa /mnt come predefinito" msgid "Select which partitions to mark for formatting:" -msgstr "Seleziona quali partizioni contrassegnare per la formattazione:" +msgstr "Seleziona le partizioni da contrassegnare per la formattazione:" msgid "Use HSM to unlock encrypted drive" msgstr "Utilizza HSM per sbloccare l'unità crittografata" @@ -798,14 +801,14 @@ msgid "Configured {} interfaces" msgstr "Interfacce {} configurate" msgid "This option enables the number of parallel downloads that can occur during installation" -msgstr "Questa opzione consente di impostare il numero di download paralleli che possono avvenire durante l'installazione" +msgstr "Questa opzione consente di impostare il numero di download in parallelo che possono avvenire durante l'installazione" msgid "" "Enter the number of parallel downloads to be enabled.\n" " (Enter a value between 1 to {})\n" "Note:" msgstr "" -"Inserisci il numero di download paralleli da abilitare.\n" +"Inserisci il numero di download in parallelo da abilitare.\n" " (Inserisci un valore compreso tra 1 e {})\n" "Nota:" @@ -816,20 +819,33 @@ msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads a msgstr " - Valore minimo : 1 ( Consente 1 download parallelo, consente 2 download alla volta )" msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" -msgstr " - Disabilita/Predefinito : 0 ( Disabilita il download parallelo, consente solo 1 download alla volta )" +msgstr " - Disabilita/Predefinito : 0 ( Disabilita il download in parallelo, consente solo 1 download alla volta )" #, python-brace-format msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" msgstr "Input non valido! Riprova con un input valido [da 1 a {max_downloads}, o 0 per disabilitare]." msgid "Parallel Downloads" -msgstr "Download paralleli" +msgstr "Download in parallelo" + +msgid "Pacman" +msgstr "Pacman" + +msgid "Color" +msgstr "Colore" + +#, python-brace-format +msgid "Enter the number of parallel downloads (1-{})" +msgstr "Inserisci il numero di download in parallelo (1-{})" + +msgid "Enable colored output for pacman" +msgstr "Attiva l'output colorato di pacman" msgid "ESC to skip" msgstr "ESC per saltare" msgid "CTRL+C to reset" -msgstr "CTRL+C per resettare" +msgstr "CTRL+C per ripristinare" msgid "TAB to select" msgstr "TAB per selezionare" @@ -861,27 +877,27 @@ msgid "Select one or more devices to use and configure" msgstr "Seleziona uno o più dispositivi da utilizzare e configurare" msgid "If you reset the device selection this will also reset the current disk layout. Are you sure?" -msgstr "Se si ripristina la selezione del disco rigido, verrà ripristinato anche il layout del disco corrente. Sei sicuro?" +msgstr "Se ripristini la selezione del dispositivo, verrà ripristinato anche il layout del disco corrente. Sei sicuro?" msgid "Existing Partitions" msgstr "Partizioni esistenti" msgid "Select a partitioning option" -msgstr "Selezione opzione di partizionamento" +msgstr "Seleziona un'opzione di partizionamento" msgid "Enter the root directory of the mounted devices: " msgstr "Inserisci la cartella principale dei dispositivi montati: " #, python-brace-format msgid "Minimum capacity for /home partition: {}GiB\n" -msgstr "Capacità minima per la partizione /home: {}GiB\n" +msgstr "Capacità minima per la partizione /home: {} GiB\n" #, python-brace-format msgid "Minimum capacity for Arch Linux partition: {}GiB" -msgstr "Capacità minima per la partizione Arch Linux: {}GiB" +msgstr "Capacità minima per la partizione Arch Linux: {} GiB" msgid "This is a list of pre-programmed profiles_bck, they might make it easier to install things like desktop environments" -msgstr "Questo è un elenco di profili pre-programmati, che potrebbero semplificare l'installazione di elementi come gli ambienti desktop" +msgstr "Questo è un elenco di profiles_bck preprogrammati, che potrebbero semplificare l'installazione di elementi come gli ambienti desktop" msgid "Current profile selection" msgstr "Selezione profilo corrente" @@ -890,7 +906,7 @@ msgid "Remove all newly added partitions" msgstr "Elimina tutte le partizioni appena aggiunte" msgid "Assign mountpoint" -msgstr "Assegna punto di mount" +msgstr "Assegna punto di montaggio" msgid "Mark/Unmark to be formatted (wipes data)" msgstr "Seleziona/Deseleziona come da formattare (cancella i dati)" @@ -917,13 +933,13 @@ msgid "This partition is currently encrypted, to format it a filesystem has to b msgstr "Questa partizione è attualmente crittografata, per formattarla è necessario specificare un filesystem" msgid "Partition mount-points are relative to inside the installation, the boot would be /boot as an example." -msgstr "I punti di mount della partizione sono relativi all'interno dell'installazione, l'avvio sarebbe per esempio /boot." +msgstr "I punti di montaggio della partizione sono relativi all'interno dell'installazione, l'avvio sarebbe per esempio /boot." msgid "If mountpoint /boot is set, then the partition will also be marked as bootable." -msgstr "Se il punto di mount /boot è impostato, anche la partizione sarà contrassegnata come avviabile." +msgstr "Se il punto di montaggio /boot è impostato, anche la partizione sarà contrassegnata come avviabile." msgid "Mountpoint: " -msgstr "Punto di mount: " +msgstr "Punto di montaggio: " msgid "Current free sectors on device {}:" msgstr "Settori attualmente liberi sul dispositivo {}:" @@ -985,7 +1001,7 @@ msgid "Partitions to be encrypted" msgstr "Partizioni da crittografare" msgid "Select disk encryption option" -msgstr "Selezione opzione per crittografia disco" +msgstr "Seleziona un'opzione per la crittografia del disco" msgid "Select a FIDO2 device to use for HSM" msgstr "Seleziona un dispositivo FIDO2 da utilizzare per HSM" @@ -1028,7 +1044,7 @@ msgid "Back" msgstr "Indietro" msgid "Please chose which greeter to install for the chosen profiles: {}" -msgstr "Scegli quale greeter installare per i profili scelti: {}" +msgstr "Scegli il greeter da installare per i profili scelti: {}" #, python-brace-format msgid "Environment type: {}" @@ -1075,7 +1091,7 @@ msgstr "" "Seleziona un driver grafico o lascia vuoto per installare tutti i driver open source" msgid "Sway needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" -msgstr "Sway ha bisogno dell’accesso al tuo posto (insieme di dispositivi hardware, ad esempio tastiera, mouse, ecc.)" +msgstr "Sway richiede l’accesso al tuo posto (insieme di dispositivi hardware, ad esempio tastiera, mouse, ecc.)" msgid "" "\n" @@ -1093,13 +1109,13 @@ msgid "Greeter" msgstr "Greeter" msgid "Please chose which greeter to install" -msgstr "Scegli quale greeter installare" +msgstr "Scegli il greeter da installare" msgid "This is a list of pre-programmed default_profiles" msgstr "Questo è un elenco di default_profiles preprogrammati" msgid "Disk configuration" -msgstr "Configurazione disco" +msgstr "Configurazione del disco" msgid "Profiles" msgstr "Profili" @@ -1144,7 +1160,7 @@ msgid "" "Enter a directory for the configuration(s) to be saved (tab completion enabled)\n" "Save directory: " msgstr "" -"Inserisci una cartella in cui salvare le configurazioni (completamento col tasto tab abilitato)\n" +"Inserisci una cartella in cui salvare le configurazioni (completamento col tasto tab attivo)\n" "Cartella di salvataggio: " msgid "" @@ -1166,7 +1182,7 @@ msgid "Mirror regions" msgstr "Regione dei mirror" msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - Valore massimo : {} ( Consente {} download paralleli, consente {max_downloads+1} downloads alla volta )" +msgstr " - Valore massimo : {} ( Consente {} download in parallelo, consente {max_downloads+1} download alla volta )" msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" msgstr "Input non valido! Riprova con un input valido [da 1 a {}, o 0 per disabilitare]." @@ -1208,33 +1224,48 @@ msgstr "Prodotto" msgid "Invalid configuration: {error}" msgstr "Configurazione non valida: {error}" +msgid "Ready to install" +msgstr "Pronto per l'installazione" + +msgid "Disks" +msgstr "Dischi" + +msgid "Packages" +msgstr "Pacchetti" + +msgid "Network" +msgstr "Rete" + +msgid "Locale" +msgstr "Localizzazione" + msgid "Type" msgstr "Tipo" msgid "This option enables the number of parallel downloads that can occur during package downloads" -msgstr "Questa opzione consente di impostare il numero di download paralleli che possono avvenire durante l'installazione" +msgstr "Questa opzione consente di impostare il numero di download in parallelo che possono avvenire durante l'installazione" msgid "" "Enter the number of parallel downloads to be enabled.\n" "\n" "Note:\n" msgstr "" -"Inserisci il numero di download paralleli da abilitare.\n" +"Inserisci il numero di download in parallelo da abilitare.\n" "\n" "Nota:\n" #, python-brace-format msgid " - Maximum recommended value : {} ( Allows {} parallel downloads at a time )" -msgstr " - Valore massimo raccomandato : {} ( Consente {} download paralleli)" +msgstr " - Valore massimo raccomandato : {} ( Consente {} download in parallelo)" msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )\n" -msgstr " - Disabilita/Predefinito : 0 ( Disabilita il download parallelo, consente solo 1 download alla volta )\n" +msgstr " - Disabilita/Predefinito : 0 ( Disabilita il download in parallelo, consente solo 1 download alla volta )\n" msgid "Invalid input! Try again with a valid input [or 0 to disable]" msgstr "Input non valido! Riprova con un input valido [0 per disabilitare]." msgid "Hyprland needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" -msgstr "Hyprland ha bisogno dell’accesso al tuo posto (insieme di dispositivi hardware, ad esempio tastiera, mouse, ecc.)" +msgstr "Hyprland richiede l’accesso al tuo posto (insieme di dispositivi hardware, ad esempio tastiera, mouse, ecc.)" msgid "" "\n" @@ -1270,7 +1301,7 @@ msgid "Selected profiles: " msgstr "Profili selezionati: " msgid "Time synchronization not completing, while you wait - check the docs for workarounds: https://archinstall.readthedocs.io/" -msgstr "La sincronizzazione dell’orario non si sta completando, in attesa, leggi la documentazione alla ricerca di una soluzione: https://archinstall.readthedocs.io/" +msgstr "La sincronizzazione dell’orario non si sta completando, mentre aspetti leggi la documentazione alla ricerca di una soluzione: https://archinstall.readthedocs.io/" msgid "Mark/Unmark as nodatacow" msgstr "Seleziona/Deseleziona come nodatacow" @@ -1322,7 +1353,7 @@ msgid "LVM volumes to be encrypted" msgstr "Volumi LVM da crittografare" msgid "Select which LVM volumes to encrypt" -msgstr "Seleziona volumi LVM da crittografare" +msgstr "Seleziona i volumi LVM da crittografare" msgid "Default layout" msgstr "Layout predefinito" @@ -1361,7 +1392,7 @@ msgid "Seat access" msgstr "Accesso al posto" msgid "Mountpoint" -msgstr "Punto di mount" +msgstr "Punto di montaggio" msgid "HSM" msgstr "HSM" @@ -1479,7 +1510,7 @@ msgid "Directory" msgstr "Cartella" msgid "Enter a directory for the configuration(s) to be saved (tab completion enabled)" -msgstr "Inserisci una cartella in cui salvare le configurazioni (completamento col tasto tab abilitato)" +msgstr "Inserisci una cartella in cui salvare le configurazioni (completamento col tasto tab attivo)" #, python-brace-format msgid "Do you want to save the configuration file(s) to {}?" @@ -1513,7 +1544,7 @@ msgid "Choose an option to give Hyprland access to your hardware" msgstr "Scegli un’opzione per concedere a Hyprland l'accesso al tuo hardware" msgid "Additional repositories" -msgstr "Repository aggiuntive" +msgstr "Repository aggiuntivi" msgid "NTP" msgstr "NTP" @@ -1543,7 +1574,7 @@ msgid "HSM device" msgstr "Dispositivo HSM" msgid "Some packages could not be found in the repository" -msgstr "Alcuni pacchetti non sono stati trovati nella repository" +msgstr "Alcuni pacchetti non sono stati trovati nel repository" msgid "User" msgstr "Utente" @@ -1564,16 +1595,16 @@ msgid "Select any packages from the below list that should be installed addition msgstr "Seleziona dalla lista sotto i pacchetti aggiuntivi da installare" msgid "Add a custom repository" -msgstr "Aggiungi una repository personalizzata" +msgstr "Aggiungi un repository personalizzato" msgid "Change custom repository" -msgstr "Cambia repository personalizzata" +msgstr "Cambia repository personalizzato" msgid "Delete custom repository" -msgstr "Elimina repository personalizzata" +msgstr "Elimina repository personalizzato" msgid "Repository name" -msgstr "Nome repository" +msgstr "Nome del repository" msgid "Add a custom server" msgstr "Aggiungi un server personalizzato" @@ -1594,7 +1625,7 @@ msgid "Add custom servers" msgstr "Aggiungi server personalizzati" msgid "Add custom repository" -msgstr "Aggiungi repository personalizzate" +msgstr "Aggiungi repository personalizzato" msgid "Loading mirror regions..." msgstr "Caricamento regioni dei mirror in corso..." @@ -1609,7 +1640,7 @@ msgid "Custom servers" msgstr "Server personalizzati" msgid "Custom repositories" -msgstr "Repository personalizzate" +msgstr "Repository personalizzati" msgid "Only ASCII characters are supported" msgstr "Sono supportati solo caratteri ASCII" @@ -1756,7 +1787,7 @@ msgid "Toggle option" msgstr "Opzioni di attivazione" msgid "Scroll Up" -msgstr "Scorri Su" +msgstr "Scorri su" msgid "Scroll Down" msgstr "Scorri giù" @@ -1783,13 +1814,13 @@ msgid "Copy selected text" msgstr "Copia il testo selezionato" msgid "labwc needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" -msgstr "labwc ha bisogno dell’accesso al tuo posto (insieme di dispositivi hardware, ad esempio tastiera, mouse, ecc.)" +msgstr "labwc richiede l’accesso al tuo posto (insieme di dispositivi hardware, ad esempio tastiera, mouse, ecc.)" msgid "Choose an option to give labwc access to your hardware" msgstr "Scegli un’opzione per concedere a labwc l’accesso al tuo hardware" msgid "niri needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" -msgstr "niri ha bisogno dell’accesso al tuo posto (insieme di dispositivi hardware, ad esempio tastiera, mouse, ecc.)" +msgstr "niri richiede l’accesso al tuo posto (insieme di dispositivi hardware, ad esempio tastiera, mouse, ecc.)" msgid "Choose an option to give niri access to your hardware" msgstr "Scegli un’opzione per concedere a niri l’accesso al tuo hardware" @@ -1832,7 +1863,7 @@ msgid "Do you want to encrypt the user_credentials.json file?" msgstr "Vuoi criptare il file di user_credentials.json?" msgid "Credentials file encryption password" -msgstr "Password di crittazione del file delle credenziali" +msgstr "Password di crittografia del file delle credenziali" #, python-brace-format msgid "Repositories: {}" @@ -1917,7 +1948,7 @@ msgid "No network connection found" msgstr "Nessuna connessione di rete trovata" msgid "Would you like to connect to a Wifi?" -msgstr "Desideri connetterti ad una Wi-FI?" +msgstr "Desideri connetterti ad una Wi-Fi?" msgid "No wifi interface found" msgstr "Nessuna interfaccia Wi-Fi trovata" @@ -2000,11 +2031,26 @@ msgstr "Usa NetworkManager (backend iwd)" msgid "Firewall" msgstr "Firewall" +msgid "Additional fonts" +msgstr "Font aggiuntivi" + +msgid "Select font packages to install" +msgstr "Seleziona i pacchetti di font da installare" + +msgid "Unicode font coverage for most languages" +msgstr "Copertura Unicode del font per la maggior parte delle lingue" + +msgid "color emoji for browsers and apps" +msgstr "emoji a colori per browser e app" + +msgid "Chinese, Japanese, Korean characters" +msgstr "Caratteri cinesi, giapponesi, coreani" + msgid "Select audio configuration" msgstr "Seleziona la configurazione audio" msgid "Enter credentials file decryption password" -msgstr "Inserici la password di decrittazione del file delle credenziali" +msgstr "Inserisci la password di decrittazione del file delle credenziali" msgid "Enter root password" msgstr "Inserisci la password di root" @@ -2025,7 +2071,7 @@ msgid "Select disks for the installation" msgstr "Seleziona il disco per l'installazione" msgid "Enter a mountpoint" -msgstr "Inserisci un punto di mount" +msgstr "Inserisci un punto di montaggio" #, python-brace-format msgid "Enter a size (default: {}): " @@ -2035,7 +2081,7 @@ msgid "Enter subvolume name" msgstr "Inserisci il nome del sottovolume" msgid "Enter subvolume mountpoint" -msgstr "Inserisci il punto di mount del sottovolume" +msgstr "Inserisci il punto di montaggio del sottovolume" msgid "Select a disk configuration" msgstr "Seleziona una configurazione del disco" @@ -2047,7 +2093,7 @@ msgid "You will use whatever drive-setup is mounted at the specified directory" msgstr "Userai qualunque configurazione del disco che sia montata nella cartella specificata" msgid "WARNING: Archinstall won't check the suitability of this setup" -msgstr "ATTENZIONE: Archinstall non verificherà la compatibilità di di questa configurazione" +msgstr "ATTENZIONE: Archinstall non verificherà la compatibilità di questa configurazione" msgid "Select main filesystem" msgstr "Seleziona il filesystem principale" @@ -2066,22 +2112,22 @@ msgid "Value must be between 1 and {}" msgstr "Il valore deve essere tra 1 e {}" msgid "Select which kernel(s) to install" -msgstr "Scegli quali kernel installare" +msgstr "Seleziona i kernel da installare" msgid "Enter a respository name" msgstr "Inserisci il nome di un repository" msgid "Enter the repository url" -msgstr "Inserisci l'URL della repository" +msgstr "Inserisci l'URL del repository" msgid "Enter server url" msgstr "Inserisci l'URL del server" msgid "Select mirror regions to be enabled" -msgstr "Seleziona quali regioni dei mirror abilitare" +msgstr "Seleziona le regioni dei mirror da abilitare" msgid "Select optional repositories to be enabled" -msgstr "Seleziona quali repository aggiuntive opzionali abilitare" +msgstr "Seleziona i repository opzionali da abilitare" msgid "Select an interface" msgstr "Seleziona un'interfaccia" @@ -2089,11 +2135,17 @@ msgstr "Seleziona un'interfaccia" msgid "Choose network configuration" msgstr "Scegli la configurazione di rete" +msgid "Recommended: Network Manager for desktop, Manual for server" +msgstr "Raccomandato: Network Manager per computer, Manuale per server" + +msgid "Warning: no network configuration selected. Network will need to be set up manually on the installed system." +msgstr "Attenzione: nessuna configurazione di rete selezionata. La rete dovrà essere impostata manualmente sul sistema installato." + msgid "No packages found" msgstr "Nessun pacchetto trovato" msgid "Select which greeter to install" -msgstr "Seleziona quale greeter installare" +msgstr "Seleziona il greeter da installare" msgid "Select a profile type" msgstr "Seleziona un tipo di profilo" @@ -2126,6 +2178,9 @@ msgstr "Il profilo desktop selezionato richiede un utente regolare per accedere msgid "Environment type: {} {}" msgstr "Tipo di ambiente: {} {}" +msgid "Input cannot be empty" +msgstr "Il campo non può essere vuoto" + msgid "Recommended" msgstr "Raccomandato" @@ -2156,5 +2211,194 @@ msgstr "Descrizione" msgid "Select a flavor of KDE Plasma to install" msgstr "Seleziona la configurazione di KDE Plasma da installare" -msgid "Input cannot be empty" -msgstr "Il campo non può essere vuoto" +msgid "Arial/Times/Courier replacement, Cyrillic support for Steam/games" +msgstr "Sostituto di Arial/Times/Courier, supporta il cirillico per Steam/giochi" + +msgid "wide Unicode coverage, good fallback font" +msgstr "ampia copertura Unicode, ottimo font di riserva" + +#, python-brace-format +msgid "Setting up U2F login: {u2f_config.u2f_login_method.value}" +msgstr "Impostazione accesso U2F: {u2f_config.u2f_login_method.value}" + +#, python-brace-format +msgid "Default: {DEFAULT_ITER_TIME}ms, Recommended range: 1000-60000" +msgstr "Predefinito: {DEFAULT_ITER_TIME} ms, Intervallo consigliato: 1000-60000" + +#, python-brace-format +msgid "Setting up U2F login: {}" +msgstr "Impostazione accesso U2F: {}" + +#, python-brace-format +msgid "Default: {}ms, Recommended range: 1000-60000" +msgstr "Predefinito: {} ms, Intervallo consigliato: 1000-60000" + +#, python-brace-format +msgid "{} needs access to your seat" +msgstr "{} richiede l’accesso al tuo posto" + +msgid "collection of hardware devices i.e. keyboard, mouse" +msgstr "insieme di dispositivi hardware, ad esempio tastiera e mouse" + +#, python-brace-format +msgid "Choose an option how to give {} access to your hardware" +msgstr "Scegli un’opzione per concedere a {} l’accesso al tuo hardware" + +#, python-brace-format +msgid "About to upload \"{}\" to the publicly accessible {}" +msgstr "\"{}\" sta per essere caricato per essere pubblicamente accessibile {}" + +msgid "Do you want to continue?" +msgstr "Vuoi continuare?" + +#, python-brace-format +msgid "Log uploaded successfully. URL: {}" +msgstr "Log caricato con successo. URL: {}" + +msgid "Failed to upload log." +msgstr "Impossibile caricare il log." + +msgid "ArchInstall Language" +msgstr "Lingua di ArchInstall" + +msgid "Version" +msgstr "Versione" + +msgid "Installation Script" +msgstr "Script di installazione" + +msgid "Application" +msgstr "Applicazione" + +msgid "Services" +msgstr "Servizi" + +msgid "Custom commands" +msgstr "Comandi personalizzati" + +msgid "Users" +msgstr "Utenti" + +msgid "Root encrypted password" +msgstr "Password di root crittografata" + +msgid "Zram enabled" +msgstr "Zram attiva" + +#, python-brace-format +msgid "Zram algorithm {}" +msgstr "Algoritmo Zram {}" + +msgid "Bluetooth enabled" +msgstr "Bluetooth attivo" + +#, python-brace-format +msgid "Audio server \"{}\"" +msgstr "Server audio \"{}\"" + +#, python-brace-format +msgid "Power management \"{}\"" +msgstr "Gestione energetica \"{}\"" + +msgid "Print service enabled" +msgstr "Servizio di stampa attivo" + +#, python-brace-format +msgid "Firewall \"{}\"" +msgstr "Firewall \"{}\"" + +#, python-brace-format +msgid "Extra fonts \"{}\"" +msgstr "Font aggiuntivi \"{}\"" + +msgid "Root password set" +msgstr "Imposta la password di root" + +#, python-brace-format +msgid "Configured {} user(s)" +msgstr "{} utente/i configurato/i" + +msgid "U2F set up" +msgstr "Imposta U2F" + +#, python-brace-format +msgid "Bootloader \"{}\"" +msgstr "Bootloader \"{}\"" + +msgid "UKI enabled" +msgstr "UKI attiva" + +msgid "Default" +msgstr "Predefinito" + +msgid "Manual" +msgstr "Manuale" + +msgid "Pre-mount" +msgstr "Premontaggio" + +#, python-brace-format +msgid "{} layout" +msgstr "Layout {}" + +#, python-brace-format +msgid "Devices {}" +msgstr "Dispositivi {}" + +msgid "LVM set up" +msgstr "Imposta LVM" + +#, python-brace-format +msgid "{} encryption" +msgstr "Crittografia {}" + +#, python-brace-format +msgid "Btrfs snapshot \"{}\"" +msgstr "Snapshot Btrfs \"{}\"" + +#, python-brace-format +msgid "Keyboard layout \"{}\"" +msgstr "Layout della tastiera \"{}\"" + +#, python-brace-format +msgid "Locale language \"{}\"" +msgstr "Lingua \"{}\"" + +#, python-brace-format +msgid "Locale encoding \"{}\"" +msgstr "Codifica \"{}\"" + +#, python-brace-format +msgid "Console font \"{}\"" +msgstr "Font della console \"{}\"" + +#, python-brace-format +msgid "Mirror regions \"{}\"" +msgstr "Regioni dei mirror \"{}\"" + +#, python-brace-format +msgid "Optional repositories \"{}\"" +msgstr "Repository opzionali \"{}\"" + +msgid "Custom servers set up" +msgstr "Imposta server personalizzati" + +msgid "Custom repositories set up" +msgstr "Imposta repository personalizzati" + +msgid "Use standalone iwd" +msgstr "Usa iwd standalone" + +msgid "Color enabled" +msgstr "Colore attivo" + +#, python-brace-format +msgid "{} grphics driver" +msgstr "Driver grafici {}" + +#, python-brace-format +msgid "{} greeter" +msgstr "Greeter {}" + +msgid "Enter a repository name" +msgstr "Inserisci il nome di un repository" diff --git a/archinstall/locales/ja/LC_MESSAGES/base.mo b/archinstall/locales/ja/LC_MESSAGES/base.mo index 96b625c6..0331225b 100644 Binary files a/archinstall/locales/ja/LC_MESSAGES/base.mo and b/archinstall/locales/ja/LC_MESSAGES/base.mo differ diff --git a/archinstall/locales/ja/LC_MESSAGES/base.po b/archinstall/locales/ja/LC_MESSAGES/base.po index 1e0f52e1..162f5dba 100644 --- a/archinstall/locales/ja/LC_MESSAGES/base.po +++ b/archinstall/locales/ja/LC_MESSAGES/base.po @@ -11,2174 +11,6 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.8\n" -msgid "[!] A log file has been created here: {} {}" -msgstr "[!] ここにログファイルが作成されました: {} {}" - -msgid " Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues" -msgstr " この問題(およびファイル)を https://github.com/archlinux/archinstall/issues に送信してください" - -msgid "Do you really want to abort?" -msgstr "本当に中止しますか?" - -msgid "And one more time for verification: " -msgstr "確認のためにもう1度: " - -msgid "Would you like to use swap on zram?" -msgstr "zram でスワップを使用しますか?" - -msgid "Desired hostname for the installation: " -msgstr "インストール時のホスト名: " - -msgid "Username for required superuser with sudo privileges: " -msgstr "sudo 権限を持つスーパーユーザーのユーザー名: " - -msgid "Any additional users to install (leave blank for no users): " -msgstr "インストールする追加のユーザー(ユーザーがない場合は無記入): " - -msgid "Should this user be a superuser (sudoer)?" -msgstr "このユーザーはスーパーユーザーに昇格しますか(sudoer)?" - -msgid "Select a timezone" -msgstr "タイムゾーンを選択" - -msgid "Would you like to use GRUB as a bootloader instead of systemd-boot?" -msgstr "systemd-boot の代わりに GRUB をブートローダーとして使用しますか?" - -msgid "Choose a bootloader" -msgstr "ブートローダーを選択" - -msgid "Choose an audio server" -msgstr "オーディオサーバーを選択" - -msgid "Only packages such as base, base-devel, linux, linux-firmware, efibootmgr and optional profile packages are installed." -msgstr "base, base-devel, linux, linux-firmware, efibootmgr などのパッケージとオプションのプロファイルパッケージのみがインストールされます。" - -msgid "Note: base-devel is no longer installed by default. Add it here if you need build tools." -msgstr "注意: base-devel はデフォルトではインストールされなくなりました。ビルドツールが必要な場合は、ここで追加してください。" - -msgid "If you desire a web browser, such as firefox or chromium, you may specify it in the following prompt." -msgstr "firefox や chromium などのウェブブラウザーをインストールする場合は、次のプロンプトで指定できます。" - -msgid "Write additional packages to install (space separated, leave blank to skip): " -msgstr "追加でインストールするパッケージを書く(スペースで区切る。無記入でスキップ): " - -msgid "Copy ISO network configuration to installation" -msgstr "ISO のネットワーク設定をインストール環境にコピー" - -msgid "Use NetworkManager (necessary for configuring internet graphically in GNOME and KDE)" -msgstr "ネットワークマネージャーを使用(GNOME と KDE でインターネットをグラフィカルに設定するのに必要)" - -msgid "Select one network interface to configure" -msgstr "設定するネットワークインターフェイスを 1 つ選択" - -msgid "Select which mode to configure for \"{}\" or skip to use default mode \"{}\"" -msgstr "どのモードを \"{}\" に設定するかを選択。スキップでデフォルトモード \"{}\" を使用" - -#, python-brace-format -msgid "Enter the IP and subnet for {} (example: 192.168.0.5/24): " -msgstr "{} の IP とサブネットを入力(例: 192.168.0.5/24): " - -msgid "Enter your gateway (router) IP address or leave blank for none: " -msgstr "ゲートウェイ(ルーター)の IP アドレスを入力。無い場合は無記入: " - -msgid "Enter your DNS servers (space separated, blank for none): " -msgstr "DNS サーバーを入力(スペースで区切る。無い場合は無記入): " - -msgid "Select which filesystem your main partition should use" -msgstr "メインパーティションで使用するファイルシステムを選択" - -msgid "Current partition layout" -msgstr "現在のパーティションレイアウト" - -msgid "" -"Select what to do with\n" -"{}" -msgstr "" -"何をするか選択\n" -"{}" - -msgid "Enter a desired filesystem type for the partition" -msgstr "パーティションのファイルシステムを入力" - -msgid "Enter the start location (in parted units: s, GB, %, etc. ; default: {}): " -msgstr "開始場所を入力(単位: s, GB, % など。デフォルト: {}): " - -msgid "Enter the end location (in parted units: s, GB, %, etc. ; ex: {}): " -msgstr "終了場所を入力(単位: s, GB, % など。例: {}): " - -msgid "{} contains queued partitions, this will remove those, are you sure?" -msgstr "{} にはキューに入っているパーティションが含まれます。それらが削除されますがよろしいですか?" - -msgid "" -"{}\n" -"\n" -"Select by index which partitions to delete" -msgstr "" -"{}\n" -"\n" -"削除するパーティションをインデックスで選択" - -msgid "" -"{}\n" -"\n" -"Select by index which partition to mount where" -msgstr "" -"{}\n" -"\n" -"どのパーティションをどこにマウントするかをインデックスで選択" - -msgid " * Partition mount-points are relative to inside the installation, the boot would be /boot as an example." -msgstr "* パーティションのマウントポイントはインストールにおける相対的なものであり、例として boot は /boot になります。" - -msgid "Select where to mount partition (leave blank to remove mountpoint): " -msgstr "パーティションをマウントする場所を選択(無記入でマウントポイントを削除): " - -msgid "" -"{}\n" -"\n" -"Select which partition to mask for formatting" -msgstr "" -"{}\n" -"\n" -"フォーマット対象としてマークするパーティションを選択" - -msgid "" -"{}\n" -"\n" -"Select which partition to mark as encrypted" -msgstr "" -"{}\n" -"\n" -"暗号化対象としてマークするパーティションを選択" - -msgid "" -"{}\n" -"\n" -"Select which partition to mark as bootable" -msgstr "" -"{}\n" -"\n" -"ブータブルとしてマークするパーティションを選択" - -msgid "" -"{}\n" -"\n" -"Select which partition to set a filesystem on" -msgstr "" -"{}\n" -"\n" -"ファイルシステムを設定するパーティションを選択" - -msgid "Enter a desired filesystem type for the partition: " -msgstr "パーティションのファイルシステムを入力: " - -msgid "Archinstall language" -msgstr "Archinstall の言語" - -msgid "Wipe all selected drives and use a best-effort default partition layout" -msgstr "選択したすべてのドライブを消去し、ベストエフォートのデフォルトパーティションレイアウトを使用する" - -msgid "Select what to do with each individual drive (followed by partition usage)" -msgstr "個々のドライブをどうするかを選択(次にパーティションの使用方法が続く)" - -msgid "Select what you wish to do with the selected block devices" -msgstr "選択したブロックデバイスで何をするかを選択" - -msgid "This is a list of pre-programmed profiles, they might make it easier to install things like desktop environments" -msgstr "これは事前にプログラムされたプロファイルのリストです。デスクトップ環境などのインストールが簡単になる可能性があります" - -msgid "Select keyboard layout" -msgstr "キーボードレイアウトを選択" - -msgid "Select one of the regions to download packages from" -msgstr "パッケージをダウンロードする地域を 1 つ選択" - -msgid "Select one or more hard drives to use and configure" -msgstr "使用・設定する 1 つ以上のハードドライブを選択" - -msgid "For the best compatibility with your AMD hardware, you may want to use either the all open-source or AMD / ATI options." -msgstr "AMD ハードウェアとの互換性を最大限に高めるには、すべてのオープンソースまたは AMD/ATI オプションのいずれかを使用することをお勧めします。" - -msgid "For the best compatibility with your Intel hardware, you may want to use either the all open-source or Intel options.\n" -msgstr "Intel ハードウェアとの互換性を最大限に高めるには、すべてのオープンソースまたは Intel オプションのいずれかを使用することをお勧めします。\n" - -msgid "For the best compatibility with your Nvidia hardware, you may want to use the Nvidia proprietary driver.\n" -msgstr "Nvidia ハードウェアとの互換性を最大限に高めるには、Nvidia 独自のドライバーを使用することをお勧めします。\n" - -msgid "" -"\n" -"\n" -"Select a graphics driver or leave blank to install all open-source drivers" -msgstr "" -"\n" -"\n" -"グラフィックドライバーを選択するか、無記入ですべてのオープンソースドライバーをインストール" - -msgid "All open-source (default)" -msgstr "すべてのオープンソース(デフォルト)" - -msgid "Choose which kernels to use or leave blank for default \"{}\"" -msgstr "使用するカーネルを選択。無記入でデフォルトの \"{}\"" - -msgid "Choose which locale language to use" -msgstr "使用するロケール言語を選択" - -msgid "Choose which locale encoding to use" -msgstr "使用するロケールエンコーディングを選択" - -msgid "Select one of the values shown below: " -msgstr "以下の値のいずれかを選択: " - -msgid "Select one or more of the options below: " -msgstr "以下のオプションを 1 つ以上選択: " - -msgid "Adding partition...." -msgstr "パーティションを追加...." - -msgid "You need to enter a valid fs-type in order to continue. See `man parted` for valid fs-type's." -msgstr "続行するには、有効な fs-type を入力する必要があります。有効な fs-type については、 `man parted` を参照してください。" - -msgid "Error: Listing profiles on URL \"{}\" resulted in:" -msgstr "エラー: URL \"{}\" のプロファイルをリストすると、次の結果が発生:" - -msgid "Error: Could not decode \"{}\" result as JSON:" -msgstr "エラー: \"{}\" の結果を JSON としてデコードできませんでした:" - -msgid "Keyboard layout" -msgstr "キーボードレイアウト" - -msgid "Mirror region" -msgstr "ミラーの地域" - -msgid "Locale language" -msgstr "ロケール言語" - -msgid "Locale encoding" -msgstr "ロケールエンコーディング" - -msgid "Console font" -msgstr "コンソールフォント" - -msgid "Drive(s)" -msgstr "ドライブ" - -msgid "Disk layout" -msgstr "ディスクレイアウト" - -msgid "Encryption password" -msgstr "暗号化パスワード" - -msgid "Swap" -msgstr "スワップ" - -msgid "Bootloader" -msgstr "ブートローダー" - -msgid "Root password" -msgstr "root パスワード" - -msgid "Superuser account" -msgstr "スーパーユーザーアカウント" - -msgid "User account" -msgstr "ユーザーアカウント" - -msgid "Profile" -msgstr "プロファイル" - -msgid "Audio" -msgstr "オーディオ" - -msgid "Kernels" -msgstr "カーネル" - -msgid "Additional packages" -msgstr "追加パッケージ" - -msgid "Network configuration" -msgstr "ネットワーク設定" - -msgid "Automatic time sync (NTP)" -msgstr "時刻の自動同期(NTP)" - -msgid "Install ({} config(s) missing)" -msgstr "インストール({} 個の設定がありません)" - -msgid "" -"You decided to skip harddrive selection\n" -"and will use whatever drive-setup is mounted at {} (experimental)\n" -"WARNING: Archinstall won't check the suitability of this setup\n" -"Do you wish to continue?" -msgstr "" -"ハードドライブの選択をスキップし、\n" -"{} にマウントしているドライブのセットアップを使用します(実験的)\n" -"警告: Archinstall はこのセットアップの適合性をチェックしません\n" -"続行しますか?" - -msgid "Re-using partition instance: {}" -msgstr "パーティションインスタンスの再利用: {}" - -msgid "Create a new partition" -msgstr "新しいパーティションを作成" - -msgid "Delete a partition" -msgstr "パーティションを削除" - -msgid "Clear/Delete all partitions" -msgstr "すべてのパーティションをクリア/削除" - -msgid "Assign mount-point for a partition" -msgstr "パーティションにマウントポイントを割り当てる" - -msgid "Mark/Unmark a partition to be formatted (wipes data)" -msgstr "フォーマットするパーティションとしてマーク/マーク解除(データを消去)" - -msgid "Mark/Unmark a partition as encrypted" -msgstr "暗号化するパーティションとしてマーク/マーク解除" - -msgid "Mark/Unmark a partition as bootable (automatic for /boot)" -msgstr "ブータブルパーティションとしてマーク/マーク解除(/boot の場合は自動)" - -msgid "Set desired filesystem for a partition" -msgstr "パーティションのファイルシステムを設定" - -msgid "Abort" -msgstr "中止" - -msgid "Hostname" -msgstr "ホスト名" - -msgid "Not configured, unavailable unless setup manually" -msgstr "未設定。手動で設定しない限り使用できません" - -msgid "Timezone" -msgstr "タイムゾーン" - -msgid "Set/Modify the below options" -msgstr "以下のオプションを設定/変更" - -msgid "Install" -msgstr "インストール" - -msgid "" -"Use ESC to skip\n" -"\n" -msgstr "" -"Esc でスキップ\n" -"\n" - -msgid "Suggest partition layout" -msgstr "パーティションレイアウトを提案" - -msgid "Enter a password: " -msgstr "パスワードを入力: " - -msgid "Enter a encryption password for {}" -msgstr "{} の暗号化パスワードを入力" - -msgid "Enter disk encryption password (leave blank for no encryption): " -msgstr "ディスクの暗号化パスワードを入力(暗号化しない場合は無記入): " - -msgid "Create a required super-user with sudo privileges: " -msgstr "sudo 権限を持つスーパーユーザーを作成: " - -msgid "Enter root password (leave blank to disable root): " -msgstr "root パスワードを入力(root を無効にする場合は無記入): " - -msgid "Password for user \"{}\": " -msgstr "ユーザー \"{}\" のパスワード: " - -msgid "Verifying that additional packages exist (this might take a few seconds)" -msgstr "追加のパッケージが存在することを確認(これには数秒かかる場合があります)" - -msgid "Would you like to use automatic time synchronization (NTP) with the default time servers?\n" -msgstr "デフォルトのタイムサーバーで時刻の自動同期(NTP)を使用しますか?\n" - -msgid "" -"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" -msgstr "" -"NTP が機能するには、ハードウェアクロックおよびその他の設定後のステップが必要になる場合があります。\n" -"詳細については Arch wiki を確認してください" - -msgid "Enter a username to create an additional user (leave blank to skip): " -msgstr "ユーザー名を入力して追加ユーザーを作成(無記入でスキップ): " - -msgid "Use ESC to skip\n" -msgstr "Esc でスキップ\n" - -msgid "" -"\n" -" Choose an object from the list, and select one of the available actions for it to execute" -msgstr "" -"\n" -"リストからオブジェクトを選択し、そのオブジェクトで実行できるアクションの 1 つを選択" - -msgid "Cancel" -msgstr "キャンセル" - -msgid "Confirm and exit" -msgstr "確認して終了" - -msgid "Add" -msgstr "追加" - -msgid "Copy" -msgstr "コピー" - -msgid "Edit" -msgstr "編集" - -msgid "Delete" -msgstr "削除" - -msgid "Select an action for '{}'" -msgstr "'{}' へのアクションを選択" - -msgid "Copy to new key:" -msgstr "新しいキーにコピー:" - -msgid "Unknown nic type: {}. Possible values are {}" -msgstr "不明な NIC タイプ: {}。可能な値は {}" - -msgid "" -"\n" -"This is your chosen configuration:" -msgstr "" -"\n" -"これが選択した設定です:" - -msgid "Pacman is already running, waiting maximum 10 minutes for it to terminate." -msgstr "Pacman はすでに実行されており、終了するまで最大 10 分間待機します。" - -msgid "Pre-existing pacman lock never exited. Please clean up any existing pacman sessions before using archinstall." -msgstr "既存の pacman のロックが終了しませんでした。archinstall を使用する前に、既存の pacman セッションをすべてクリーンアップしてください。" - -msgid "Choose which optional additional repositories to enable" -msgstr "オプションで有効にする追加リポジトリを選択" - -msgid "Add a user" -msgstr "ユーザーを追加" - -msgid "Change password" -msgstr "パスワードを変更" - -msgid "Promote/Demote user" -msgstr "ユーザーを昇格/降格" - -msgid "Delete User" -msgstr "ユーザーを削除" - -msgid "" -"\n" -"Define a new user\n" -msgstr "" -"\n" -"新しいユーザーを定義\n" - -msgid "User Name : " -msgstr "ユーザー名: " - -msgid "Should {} be a superuser (sudoer)?" -msgstr "{} はスーパーユーザーに昇格しますか(sudoer)?" - -msgid "Define users with sudo privilege: " -msgstr "sudo 権限を持つユーザーを定義: " - -msgid "No network configuration" -msgstr "ネットワーク設定なし" - -msgid "Set desired subvolumes on a btrfs partition" -msgstr "Btrfs パーティションに必要なサブボリュームを設定" - -msgid "" -"{}\n" -"\n" -"Select which partition to set subvolumes on" -msgstr "" -"{}\n" -"\n" -"サブボリュームを設定するパーティションを選択" - -msgid "Manage btrfs subvolumes for current partition" -msgstr "現在のパーティションの Btrfs サブボリュームを管理" - -msgid "No configuration" -msgstr "設定なし" - -msgid "Save user configuration" -msgstr "ユーザー設定を保存" - -msgid "Save user credentials" -msgstr "ユーザーの認証情報を保存" - -msgid "Save disk layout" -msgstr "ディスクレイアウトを保存" - -msgid "Save all" -msgstr "すべて保存" - -msgid "Choose which configuration to save" -msgstr "保存する設定を選択" - -msgid "Enter a directory for the configuration(s) to be saved: " -msgstr "設定を保存するディレクトリを入力: " - -msgid "Not a valid directory: {}" -msgstr "有効なディレクトリではありません: {}" - -msgid "The password you are using seems to be weak," -msgstr "使用しているパスワードは弱いようです、" - -msgid "are you sure you want to use it?" -msgstr "本当に使用してもよろしいですか?" - -msgid "Optional repositories" -msgstr "オプションリポジトリ" - -msgid "Save configuration" -msgstr "設定を保存" - -msgid "Missing configurations:\n" -msgstr "設定が存在しません:\n" - -msgid "Either root-password or at least 1 superuser must be specified" -msgstr "root パスワードか、1人以上のスーパーユーザーを指定してください" - -msgid "Manage superuser accounts: " -msgstr "スーパーユーザーアカウントを管理: " - -msgid "Manage ordinary user accounts: " -msgstr "一般ユーザーのアカウントを管理: " - -msgid " Subvolume :{:16}" -msgstr " サブボリューム :{:16}" - -msgid " mounted at {:16}" -msgstr " マウント場所 {:16}" - -msgid " with option {}" -msgstr " 次のオプションで {}" - -msgid "" -"\n" -" Fill the desired values for a new subvolume \n" -msgstr "" -"\n" -" 新しいサブボリュームに必要な値を入力 \n" - -msgid "Subvolume name " -msgstr "サブボリューム名 " - -msgid "Subvolume mountpoint" -msgstr "サブボリュームのマウントポイント" - -msgid "Subvolume options" -msgstr "サブボリュームのオプション" - -msgid "Save" -msgstr "保存" - -msgid "Subvolume name :" -msgstr "サブボリューム名:" - -msgid "Select a mount point :" -msgstr "マウントポイントを選択:" - -msgid "Select the desired subvolume options " -msgstr "サブボリュームのオプションを選択" - -msgid "Define users with sudo privilege, by username: " -msgstr "sudo 権限を持つユーザーを、ユーザー名で定義: " - -#, python-brace-format -msgid "[!] A log file has been created here: {}" -msgstr "[!] ここにログファイルが作成されました: {}" - -msgid "Would you like to use BTRFS subvolumes with a default structure?" -msgstr "デフォルトの設定で Btrfs サブボリュームを使用しますか?" - -msgid "Would you like to use BTRFS compression?" -msgstr "Btrfs の圧縮を使用しますか?" - -msgid "Would you like to create a separate partition for /home?" -msgstr "/home 用に別のパーティションを作成しますか?" - -msgid "The selected drives do not have the minimum capacity required for an automatic suggestion\n" -msgstr "選択したドライブには、自動提案に必要な最小容量がありません\n" - -msgid "Minimum capacity for /home partition: {}GB\n" -msgstr "/home パーティションの最小容量: {}GB\n" - -msgid "Minimum capacity for Arch Linux partition: {}GB" -msgstr "Arch Linux パーティションの最小容量: {}GB" - -msgid "Continue" -msgstr "続行" - -msgid "yes" -msgstr "yes" - -msgid "no" -msgstr "no" - -msgid "set: {}" -msgstr "セット: {}" - -msgid "Manual configuration setting must be a list" -msgstr "手動設定はリストである必要があります" - -msgid "No iface specified for manual configuration" -msgstr "手動設定に iface が指定されていません" - -msgid "Manual nic configuration with no auto DHCP requires an IP address" -msgstr "自動 DHCP を使用しない手動 NIC 設定には、IP アドレスが必要です" - -msgid "Add interface" -msgstr "インターフェイスを追加" - -msgid "Edit interface" -msgstr "インターフェイスを編集" - -msgid "Delete interface" -msgstr "インターフェイスを削除" - -msgid "Select interface to add" -msgstr "追加するインターフェースを選択" - -msgid "Manual configuration" -msgstr "手動設定" - -msgid "Mark/Unmark a partition as compressed (btrfs only)" -msgstr "圧縮するパーティションとしてマーク/マーク解除(Btrfs のみ)" - -msgid "The password you are using seems to be weak, are you sure you want to use it?" -msgstr "使用しているパスワードは弱いようですが、本当に使用してもよろしいですか?" - -msgid "Provides a selection of desktop environments and tiling window managers, e.g. gnome, kde, sway" -msgstr "デスクトップ環境とタイルウィンドウマネージャーの選択を提供します。e.g. gnome, kde, sway" - -msgid "Select your desired desktop environment" -msgstr "デスクトップ環境を選択" - -msgid "A very basic installation that allows you to customize Arch Linux as you see fit." -msgstr "Arch Linux を必要に応じてカスタマイズできる非常に基本的なインストールです。" - -msgid "Provides a selection of various server packages to install and enable, e.g. httpd, nginx, mariadb" -msgstr "さまざまなサーバー パッケージの選択肢を提供します。e.g. httpd, nginx, mariadb" - -msgid "Choose which servers to install, if none then a minimal installation will be done" -msgstr "インストールするサーバーを選択。存在しない場合は最小限のインストールが実行されます" - -msgid "Installs a minimal system as well as xorg and graphics drivers." -msgstr "最小限のシステムと xorg およびグラフィックドライバーをインストール。" - -msgid "Press Enter to continue." -msgstr "Enter キーで続行します。" - -msgid "Would you like to chroot into the newly created installation and perform post-installation configuration?" -msgstr "新しく作成したインストールに chroot して、インストール後の設定を実行しますか?" - -msgid "Are you sure you want to reset this setting?" -msgstr "この設定をリセットしてもよろしいですか?" - -msgid "Select one or more hard drives to use and configure\n" -msgstr "使用・設定する 1 つ以上のハードドライブを選択\n" - -msgid "Any modifications to the existing setting will reset the disk layout!" -msgstr "既存の設定を変更すると、ディスクレイアウトがリセットされます!" - -msgid "If you reset the harddrive selection this will also reset the current disk layout. Are you sure?" -msgstr "ハードドライブの選択をリセットすると、現在のディスクレイアウトもリセットされます。よろしいですか?" - -msgid "Save and exit" -msgstr "保存して終了" - -msgid "" -"{}\n" -"contains queued partitions, this will remove those, are you sure?" -msgstr "" -"{}\n" -"キューに入れられたパーティションが含まれています。削除しますがよろしいですか?" - -msgid "No audio server" -msgstr "オーディオサーバーなし" - -msgid "(default)" -msgstr "(デフォルト)" - -msgid "Use ESC to skip" -msgstr "Esc でスキップ" - -msgid "" -"Use CTRL+C to reset current selection\n" -"\n" -msgstr "" -"Ctrl+C で現在の選択をリセット\n" -"\n" - -msgid "Copy to: " -msgstr "コピー先: " - -msgid "Edit: " -msgstr "編集: " - -msgid "Key: " -msgstr "キー: " - -msgid "Edit {}: " -msgstr "編集 {}: " - -msgid "Add: " -msgstr "追加: " - -msgid "Value: " -msgstr "値: " - -msgid "You can skip selecting a drive and partitioning and use whatever drive-setup is mounted at /mnt (experimental)" -msgstr "ドライブ選択とパーティション作成をスキップして、/mnt にマウントしているドライブのセットアップを使用できます(実験的)" - -msgid "Select one of the disks or skip and use /mnt as default" -msgstr "いずれかのディスクを選択するか、スキップして /mnt をデフォルトとして使用" - -msgid "Select which partitions to mark for formatting:" -msgstr "フォーマットするパーティションを選択:" - -msgid "Use HSM to unlock encrypted drive" -msgstr "HSM を使用して暗号化されたドライブのロックを解除" - -msgid "Device" -msgstr "デバイス" - -msgid "Size" -msgstr "サイズ" - -msgid "Free space" -msgstr "空き容量" - -msgid "Bus-type" -msgstr "Bus タイプ" - -msgid "Either root-password or at least 1 user with sudo privileges must be specified" -msgstr "root パスワードか、1人以上の sudo 権限を持つユーザーを指定する必要があります" - -msgid "Enter username (leave blank to skip): " -msgstr "ユーザー名を入力(無記入でスキップ): " - -msgid "The username you entered is invalid. Try again" -msgstr "入力したユーザー名は無効です。もう1度やり直してください" - -msgid "Should \"{}\" be a superuser (sudo)?" -msgstr "\"{}\" はスーパーユーザーに昇格しますか(sudo)?" - -msgid "Select which partitions to encrypt" -msgstr "暗号化するパーティションを選択" - -msgid "very weak" -msgstr "非常に弱い" - -msgid "weak" -msgstr "弱い" - -msgid "moderate" -msgstr "中程度" - -msgid "strong" -msgstr "強い" - -msgid "Add subvolume" -msgstr "サブボリュームを追加" - -msgid "Edit subvolume" -msgstr "サブボリュームを編集" - -msgid "Delete subvolume" -msgstr "サブボリュームを削除" - -msgid "Configured {} interfaces" -msgstr "設定した {} インターフェース" - -msgid "This option enables the number of parallel downloads that can occur during installation" -msgstr "このオプションは、インストール中に実行できる並列ダウンロードの数を有効にします" - -msgid "" -"Enter the number of parallel downloads to be enabled.\n" -" (Enter a value between 1 to {})\n" -"Note:" -msgstr "" -"有効にする並列ダウンロードの数を入力してください。\n" -" (1 から {} の値を入力)\n" -"注意:" - -msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" -msgstr " - 最大値 : {} ({} 個の並列ダウンロードを許可して、1度に {} 個のダウンロードを許可する)" - -msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" -msgstr " - 最小値 : 1 (1 個の並列ダウンロードを許可して、1度に 2 個のダウンロードを許可する)" - -msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" -msgstr " - 無効/デフォルト : 0 (並列ダウンロードを無効にして、1度に 1 個のみダウンロードを許可する)" - -#, python-brace-format -msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" -msgstr "無効な入力です!有効な入力を使用して再試行してください [1 - {max_downloads}、0 で無効]" - -msgid "Parallel Downloads" -msgstr "並行ダウンロード" - -msgid "Pacman" -msgstr "Pacman" - -msgid "Color" -msgstr "カラー" - -#, python-brace-format -msgid "Enter the number of parallel downloads (1-{})" -msgstr "並列ダウンロード数を入力 (1-{})" - -msgid "Enable colored output for pacman" -msgstr "pacman でカラー出力を有効にする" - -msgid "ESC to skip" -msgstr "Esc でスキップ" - -msgid "CTRL+C to reset" -msgstr "Ctrl+C でリセット" - -msgid "TAB to select" -msgstr "Tab で選択" - -msgid "[Default value: 0] > " -msgstr "[デフォルト値: 0] > " - -msgid "To be able to use this translation, please install a font manually that supports the language." -msgstr "この翻訳を使用できるようにするには、その言語をサポートするフォントを手動でインストールしてください。" - -msgid "The font should be stored as {}" -msgstr "フォントは {} として保存する必要があります" - -msgid "Archinstall requires root privileges to run. See --help for more." -msgstr "Archinstall を実行するには root 権限が必要です。詳細については --help を参照してください。" - -msgid "Select an execution mode" -msgstr "実行モードを選択" - -#, python-brace-format -msgid "Unable to fetch profile from specified url: {}" -msgstr "指定された URL からプロファイルを取得できません: {}" - -#, python-brace-format -msgid "Profiles must have unique name, but profile definitions with duplicate name found: {}" -msgstr "プロファイルには一意の名前が必要ですが、重複した名前のプロファイル定義が見つかりました: {}" - -msgid "Select one or more devices to use and configure" -msgstr "使用・設定する 1 つ以上のデバイスを選択" - -msgid "If you reset the device selection this will also reset the current disk layout. Are you sure?" -msgstr "デバイスの選択をリセットすると、現在のディスクレイアウトもリセットされます。よろしいですか?" - -msgid "Existing Partitions" -msgstr "既存のパーティション" - -msgid "Select a partitioning option" -msgstr "パーティション作成のオプションを選択" - -msgid "Enter the root directory of the mounted devices: " -msgstr "マウントしているデバイスのルートディレクトリを入力: " - -#, python-brace-format -msgid "Minimum capacity for /home partition: {}GiB\n" -msgstr "/home パーティションの最小容量: {}GiB\n" - -#, python-brace-format -msgid "Minimum capacity for Arch Linux partition: {}GiB" -msgstr "Arch Linux パーティションの最小容量: {}GiB" - -msgid "This is a list of pre-programmed profiles_bck, they might make it easier to install things like desktop environments" -msgstr "これは事前にプログラムされたプロファイルのリストです。デスクトップ環境などのインストールが簡単になる可能性があります" - -msgid "Current profile selection" -msgstr "現在のプロファイルの選択" - -msgid "Remove all newly added partitions" -msgstr "新しく追加されたパーティションをすべて削除" - -msgid "Assign mountpoint" -msgstr "マウントポイントを割り当てる" - -msgid "Mark/Unmark to be formatted (wipes data)" -msgstr "フォーマット対象としてマーク/マーク解除(データを消去)" - -msgid "Mark/Unmark as bootable" -msgstr "ブータブルとしてマーク/マーク解除" - -msgid "Change filesystem" -msgstr "ファイルシステムを変更" - -msgid "Mark/Unmark as compressed" -msgstr "圧縮対象としてマーク/マーク解除" - -msgid "Set subvolumes" -msgstr "サブボリュームを設定" - -msgid "Delete partition" -msgstr "パーティションを削除" - -msgid "Partition" -msgstr "パーティション" - -msgid "This partition is currently encrypted, to format it a filesystem has to be specified" -msgstr "このパーティションは現在暗号化されています。フォーマットするにはファイルシステムを指定してください" - -msgid "Partition mount-points are relative to inside the installation, the boot would be /boot as an example." -msgstr "パーティションのマウントポイントはインストールにおける相対的なもので、例として boot は /boot になります。" - -msgid "If mountpoint /boot is set, then the partition will also be marked as bootable." -msgstr "マウントポイントに /boot が設定された場合、パーティションはブータブルとしてマークされます。" - -msgid "Mountpoint: " -msgstr "マウントポイント: " - -msgid "Current free sectors on device {}:" -msgstr "デバイス {} の現在の空きセクター:" - -msgid "Total sectors: {}" -msgstr "総セクター数: {}" - -msgid "Enter the start sector (default: {}): " -msgstr "開始セクターを入力(デフォルト: {}): " - -msgid "Enter the end sector of the partition (percentage or block number, default: {}): " -msgstr "パーティションの終了セクターを入力(パーセンテージかブロック番号。デフォルト: {}): " - -msgid "This will remove all newly added partitions, continue?" -msgstr "これは新しく追加されたパーティションをすべて削除します。続けますか?" - -#, python-brace-format -msgid "Partition management: {}" -msgstr "パーティションを管理: {}" - -#, python-brace-format -msgid "Total length: {}" -msgstr "全体のサイズ: {}" - -msgid "Encryption type" -msgstr "暗号化のタイプ" - -msgid "Iteration time" -msgstr "イテレーション時間" - -msgid "Enter iteration time for LUKS encryption (in milliseconds)" -msgstr "LUKS 暗号化のイテレーション時間(ミリ秒単位)を入力" - -msgid "Higher values increase security but slow down boot time" -msgstr "値を大きくするとセキュリティは向上しますが、起動時間が遅くなります" - -msgid "Default: 10000ms, Recommended range: 1000-60000" -msgstr "デフォルト: 10000ms, 推奨範囲: 1000-60000" - -msgid "Iteration time cannot be empty" -msgstr "イテレーション時間は空にできません" - -msgid "Iteration time must be at least 100ms" -msgstr "イテレーション時間は最低 100ms にしてください" - -msgid "Iteration time must be at most 120000ms" -msgstr "イテレーション時間は最大 120000ms にしてください" - -msgid "Please enter a valid number" -msgstr "有効な数字を入力してください" - -msgid "Partitions" -msgstr "パーティション" - -msgid "No HSM devices available" -msgstr "利用可能な HSM デバイスがありません" - -msgid "Partitions to be encrypted" -msgstr "暗号化するパーティション" - -msgid "Select disk encryption option" -msgstr "ディスクの暗号化オプションを選択" - -msgid "Select a FIDO2 device to use for HSM" -msgstr "HSM に使用する FIDO2 デバイスを選択" - -msgid "Use a best-effort default partition layout" -msgstr "ベストエフォートのデフォルトパーティションレイアウトを使用" - -msgid "Manual Partitioning" -msgstr "手動でパーティションを作成" - -msgid "Pre-mounted configuration" -msgstr "現在のマウント設定" - -msgid "Unknown" -msgstr "不明" - -msgid "Partition encryption" -msgstr "パーティションの暗号化" - -#, python-brace-format -msgid " ! Formatting {} in " -msgstr " ! {} のフォーマットまで " - -msgid "← Back" -msgstr "← 戻る" - -msgid "Disk encryption" -msgstr "ディスクの暗号化" - -msgid "Configuration" -msgstr "設定" - -msgid "Password" -msgstr "パスワード" - -msgid "All settings will be reset, are you sure?" -msgstr "すべての設定がリセットされます。よろしいですか?" - -msgid "Back" -msgstr "戻る" - -msgid "Please chose which greeter to install for the chosen profiles: {}" -msgstr "選択したプロファイルにインストールするグリーターを選択: {}" - -#, python-brace-format -msgid "Environment type: {}" -msgstr "環境タイプ: {}" - -msgid "The proprietary Nvidia driver is not supported by Sway. It is likely that you will run into issues, are you okay with that?" -msgstr "プロプライエタリの Nvidia ドライバーは Sway ではサポートされていません。問題が発生する可能性がありますが、よろしいですか?" - -msgid "Installed packages" -msgstr "インストールするパッケージ" - -msgid "Add profile" -msgstr "プロファイルを追加" - -msgid "Edit profile" -msgstr "プロファイルを編集" - -msgid "Delete profile" -msgstr "プロファイルを削除" - -msgid "Profile name: " -msgstr "プロファイル名: " - -msgid "The profile name you entered is already in use. Try again" -msgstr "入力したプロファイル名はすでに使用されています。もう1度やり直してください" - -msgid "Packages to be install with this profile (space separated, leave blank to skip): " -msgstr "このプロファイルでインストールするパッケージ(スペースで区切る。無記入でスキップ): " - -msgid "Services to be enabled with this profile (space separated, leave blank to skip): " -msgstr "このプロファイルで有効にするサービス(スペースで区切る。未記入でスキップ): " - -msgid "Should this profile be enabled for installation?" -msgstr "このプロファイルのインストールを有効にしますか?" - -msgid "Create your own" -msgstr "自分で作成" - -msgid "" -"\n" -"Select a graphics driver or leave blank to install all open-source drivers" -msgstr "" -"\n" -"グラフィックドライバーを選択。無記入ですべてのオープンソースドライバーをインストール" - -msgid "Sway needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" -msgstr "Sway はお使いの Seat(キーボード、マウスなどのハードウェアデバイス群)にアクセスする必要があります" - -msgid "" -"\n" -"\n" -"Choose an option to give Sway access to your hardware" -msgstr "" -"\n" -"\n" -"Sway にハードウェアへのアクセスを許可するオプションを選択" - -msgid "Graphics driver" -msgstr "グラフィックドライバー" - -msgid "Greeter" -msgstr "グリーター" - -msgid "Please chose which greeter to install" -msgstr "インストールするグリーターを選択" - -msgid "This is a list of pre-programmed default_profiles" -msgstr "これは、事前にプログラムされた default_profile のリストです" - -msgid "Disk configuration" -msgstr "ディスクの設定" - -msgid "Profiles" -msgstr "プロファイル" - -msgid "Finding possible directories to save configuration files ..." -msgstr "設定ファイルを保存できるディレクトリを検索しています..." - -msgid "Select directory (or directories) for saving configuration files" -msgstr "設定ファイルを保存するディレクトリを選択" - -msgid "Add a custom mirror" -msgstr "カスタムミラーを追加" - -msgid "Change custom mirror" -msgstr "カスタムミラーを変更" - -msgid "Delete custom mirror" -msgstr "カスタムミラーを削除" - -msgid "Enter name (leave blank to skip): " -msgstr "名前を入力(無記入でスキップ): " - -msgid "Enter url (leave blank to skip): " -msgstr "URL を入力(未記入でスキップ): " - -msgid "Select signature check option" -msgstr "署名チェックのオプションを選択" - -msgid "Select signature option" -msgstr "署名オプションを選択" - -msgid "Custom mirrors" -msgstr "カスタムミラー" - -msgid "Defined" -msgstr "定義済み" - -msgid "Save user configuration (including disk layout)" -msgstr "ユーザー設定を保存(ディスクレイアウトを含む)" - -msgid "" -"Enter a directory for the configuration(s) to be saved (tab completion enabled)\n" -"Save directory: " -msgstr "" -"設定を保存するディレクトリを入力(Tab で補完可能)\n" -"保存ディレクトリ: " - -msgid "" -"Do you want to save {} configuration file(s) in the following location?\n" -"\n" -"{}" -msgstr "" -"{} 設定ファイルを次の場所に保存しますか?\n" -"\n" -"{}" - -msgid "Saving {} configuration files to {}" -msgstr "{} 設定ファイルを {} に保存" - -msgid "Mirrors" -msgstr "ミラー" - -msgid "Mirror regions" -msgstr "ミラーの地域" - -msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" -msgstr " - 最大値 : {}({} 個の並列ダウンロードを許可し、1度に {max_downloads+1} 個のダウンロードを許可する)" - -msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" -msgstr "無効な入力です!有効な入力でやり直してください [1 から {}、または 0 で無効]" - -msgid "Locales" -msgstr "ロケール" - -msgid "Use NetworkManager (necessary to configure internet graphically in GNOME and KDE)" -msgstr "ネットワークマネージャーを使用(GNOME と KDE でインターネットをグラフィカルに設定するのに必要)" - -msgid "Total: {} / {}" -msgstr "全体: {} / {}" - -msgid "All entered values can be suffixed with a unit: B, KB, KiB, MB, MiB..." -msgstr "入力したすべての値に、B、KB、KiB、MB、MiB などの単位を付けることができます。" - -msgid "If no unit is provided, the value is interpreted as sectors" -msgstr "単位が指定されていない場合、値はセクターとして解釈されます" - -msgid "Enter start (default: sector {}): " -msgstr "開始値を入力(デフォルト: セクター {}): " - -msgid "Enter end (default: {}): " -msgstr "終了値を入力(デフォルト: {}): " - -msgid "Unable to determine fido2 devices. Is libfido2 installed?" -msgstr "fido2 デバイスを特定できません。lifido2 はインストールされていますか?" - -msgid "Path" -msgstr "パス" - -msgid "Manufacturer" -msgstr "メーカー" - -msgid "Product" -msgstr "製品" - -#, python-brace-format -msgid "Invalid configuration: {error}" -msgstr "無効な設定: {error}" - -msgid "Ready to install" -msgstr "インストール準備完了" - -msgid "Disks" -msgstr "ディスク" - -msgid "Packages" -msgstr "パッケージ" - -msgid "Network" -msgstr "ネットワーク" - -msgid "Locale" -msgstr "ロケール" - -msgid "Type" -msgstr "タイプ" - -msgid "This option enables the number of parallel downloads that can occur during package downloads" -msgstr "このオプションは、パッケージのダウンロード中に実行できる並列ダウンロードの数を設定します" - -msgid "" -"Enter the number of parallel downloads to be enabled.\n" -"\n" -"Note:\n" -msgstr "" -"並列ダウンロードの数を入力してください。\n" -"\n" -"注意:\n" - -#, python-brace-format -msgid " - Maximum recommended value : {} ( Allows {} parallel downloads at a time )" -msgstr " - 最大推奨値 : {} (1度に {} 個の並列ダウンロードを許可する)" - -msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )\n" -msgstr " - 無効/デフォルト : 0 (並列ダウンロードを無効にして、1度に 1 個のダウンロードのみ許可する)\n" - -msgid "Invalid input! Try again with a valid input [or 0 to disable]" -msgstr "無効な入力です!有効な入力でやり直してください(無効にする場合は 0)" - -msgid "Hyprland needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" -msgstr "Hyprland はお使いの Seat(キーボード、マウスなどのハードウェアデバイス群)にアクセスする必要があります" - -msgid "" -"\n" -"\n" -"Choose an option to give Hyprland access to your hardware" -msgstr "" -"\n" -"\n" -"Hyprland にハードウェアへのアクセスを許可するオプションを選択" - -msgid "All entered values can be suffixed with a unit: %, B, KB, KiB, MB, MiB..." -msgstr "入力したすべての値に、%、B、KB、KiB、MB、MiB などの単位を付けることができます。" - -msgid "Would you like to use unified kernel images?" -msgstr "Unified カーネルイメージを使用しますか?" - -msgid "Unified kernel images" -msgstr "Unified カーネルイメージ" - -msgid "Waiting for time sync (timedatectl show) to complete." -msgstr "時刻の同期(timedatectl show)が完了するのを待機しています。" - -msgid "Time syncronization not completing, while you wait - check the docs for workarounds: https://archinstall.readthedocs.io/" -msgstr "待機中に時刻同期が完了しません - 回避策についてはドキュメントを確認してください: https://archinstall.readthedocs.io/" - -msgid "Skipping waiting for automatic time sync (this can cause issues if time is out of sync during installation)" -msgstr "自動での時刻同期の待機をスキップします(インストール中に時刻が同期していない場合は、問題が発生する可能性があります)" - -msgid "Waiting for Arch Linux keyring sync (archlinux-keyring-wkd-sync) to complete." -msgstr "Arch Linux キーリングの同期(archlinux-keyring-wkd-sync)が完了するのを待っています。" - -msgid "Selected profiles: " -msgstr "選択したプロファイル: " - -msgid "Time synchronization not completing, while you wait - check the docs for workarounds: https://archinstall.readthedocs.io/" -msgstr "待機中に時刻同期が完了しません - 回避策についてはドキュメントを確認してください: https://archinstall.readthedocs.io/" - -msgid "Mark/Unmark as nodatacow" -msgstr "nodatacow としてマーク/マーク解除" - -msgid "Would you like to use compression or disable CoW?" -msgstr "圧縮を使用しますか、それとも CoW を無効にしますか?" - -msgid "Use compression" -msgstr "圧縮する" - -msgid "Disable Copy-on-Write" -msgstr "コピーオンライトを無効にする" - -msgid "Provides a selection of desktop environments and tiling window managers, e.g. GNOME, KDE Plasma, Sway" -msgstr "デスクトップ環境とタイルウィンドウマネージャーの選択を提供します。例: GNOME, KDE Plasma, Sway" - -#, python-brace-format -msgid "Configuration type: {}" -msgstr "設定タイプ: {}" - -msgid "LVM configuration type" -msgstr "LVM の設定タイプ" - -msgid "LVM disk encryption with more than 2 partitions is currently not supported" -msgstr "パーティションが2個を超える場合の LVM ディスク暗号化は、現在サポートしていません" - -msgid "Use NetworkManager (necessary to configure internet graphically in GNOME and KDE Plasma)" -msgstr "ネットワークマネージャーを使用(GNOME と KDE Plasma でインターネットをグラフィカルに設定するのに必要)" - -msgid "Select a LVM option" -msgstr "LVM のオプションを選択" - -msgid "Partitioning" -msgstr "パーティションを作成" - -msgid "Logical Volume Management (LVM)" -msgstr "論理ボリューム管理(LVM)" - -msgid "Physical volumes" -msgstr "物理ボリューム" - -msgid "Volumes" -msgstr "ボリューム" - -msgid "LVM volumes" -msgstr "LVM ボリューム" - -msgid "LVM volumes to be encrypted" -msgstr "暗号化する LVM ボリューム" - -msgid "Select which LVM volumes to encrypt" -msgstr "暗号化する LVM ボリュームを選択" - -msgid "Default layout" -msgstr "デフォルトのレイアウト" - -msgid "No Encryption" -msgstr "暗号化なし" - -msgid "LUKS" -msgstr "LUKS" - -msgid "LVM on LUKS" -msgstr "LUKS 上の LVM" - -msgid "LUKS on LVM" -msgstr "LVM 上の LUKS" - -msgid "Yes" -msgstr "Yes" - -msgid "No" -msgstr "No" - -msgid "Archinstall help" -msgstr "Archinstall ヘルプ" - -msgid " (default)" -msgstr " (デフォルト)" - -msgid "Press Ctrl+h for help" -msgstr "Ctrl+H でヘルプを表示" - -msgid "Choose an option to give Sway access to your hardware" -msgstr "Sway にハードウェアへのアクセスを許可するオプションを選択" - -msgid "Seat access" -msgstr "Seat アクセス" - -msgid "Mountpoint" -msgstr "マウントポイント" - -msgid "HSM" -msgstr "HSM" - -msgid "Enter disk encryption password (leave blank for no encryption)" -msgstr "ディスクの暗号化パスワードを入力(暗号化しない場合は無記入)" - -msgid "Disk encryption password" -msgstr "ディスク暗号化パスワード" - -msgid "Partition - New" -msgstr "パーティション - 新規" - -msgid "Filesystem" -msgstr "ファイルシステム" - -msgid "Invalid size" -msgstr "無効なサイズ" - -msgid "Start (default: sector {}): " -msgstr "開始値(デフォルト: セクター {}): " - -msgid "End (default: {}): " -msgstr "終了値(デフォルト: {}): " - -msgid "Subvolume name" -msgstr "サブボリューム名" - -msgid "Disk configuration type" -msgstr "ディスク設定のタイプ" - -msgid "Root mount directory" -msgstr "ルートマウントディレクトリ" - -msgid "Select language" -msgstr "言語を選択" - -msgid "Write additional packages to install (space separated, leave blank to skip)" -msgstr "追加でインストールするパッケージを書く(スペースで区切る。無記入でスキップ)" - -msgid "Invalid download number" -msgstr "ダウンロード数が無効です" - -msgid "Number downloads" -msgstr "ダウンロード数" - -msgid "The username you entered is invalid" -msgstr "入力したユーザー名は無効です" - -msgid "Username" -msgstr "ユーザー名" - -#, python-brace-format -msgid "Should \"{}\" be a superuser (sudo)?\n" -msgstr "\"{}\" はスーパーユーザーに昇格しますか(sudo)?\n" - -msgid "Interfaces" -msgstr "インターフェイス" - -msgid "You need to enter a valid IP in IP-config mode" -msgstr "IP設定モードで有効なIPを入力する必要があります" - -msgid "Modes" -msgstr "モード" - -msgid "IP address" -msgstr "IPアドレス" - -msgid "Enter your gateway (router) IP address (leave blank for none)" -msgstr "ゲートウェイ(ルーター)の IP アドレスを入力。無い場合は無記入" - -msgid "Gateway address" -msgstr "ゲートウェイアドレス" - -msgid "Enter your DNS servers with space separated (leave blank for none)" -msgstr "DNS サーバーをスペースで区切って入力(無い場合は無記入)" - -msgid "DNS servers" -msgstr "DNSサーバー" - -msgid "Configure interfaces" -msgstr "インターフェースを設定" - -msgid "Kernel" -msgstr "カーネル" - -msgid "UEFI is not detected and some options are disabled" -msgstr "UEFIが検出されず、一部のオプションが無効になります" - -msgid "Info" -msgstr "情報" - -msgid "The proprietary Nvidia driver is not supported by Sway." -msgstr "プロプライエタリの Nvidia ドライバーは Sway ではサポートされていません。" - -msgid "It is likely that you will run into issues, are you okay with that?" -msgstr "問題が発生する可能性が高いですが、よろしいですか?" - -msgid "Main profile" -msgstr "メインプロファイル" - -msgid "Confirm password" -msgstr "パスワードを確認" - -msgid "The confirmation password did not match, please try again" -msgstr "確認のパスワードが一致しませんでした。もう一度試してください" - -msgid "Not a valid directory" -msgstr "有効なディレクトリではありません" - -msgid "Would you like to continue?" -msgstr "続行しますか?" - -msgid "Directory" -msgstr "ディレクトリ" - -msgid "Enter a directory for the configuration(s) to be saved (tab completion enabled)" -msgstr "設定を保存するディレクトリを入力(Tab で補完可能)" - -#, python-brace-format -msgid "Do you want to save the configuration file(s) to {}?" -msgstr "設定ファイルを次の場所に保存しますか? {}" - -msgid "Enabled" -msgstr "有効" - -msgid "Disabled" -msgstr "無効" - -msgid "Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues" -msgstr "この問題(およびファイル)を https://github.com/archlinux/archinstall/issues に送信してください" - -msgid "Mirror name" -msgstr "ミラーの名前" - -msgid "Url" -msgstr "URL" - -msgid "Select signature check" -msgstr "署名チェックを選択" - -msgid "Select execution mode" -msgstr "実行モードを選択" - -msgid "Press ? for help" -msgstr "? を押すとヘルプを表示" - -msgid "Choose an option to give Hyprland access to your hardware" -msgstr "Hyprland にハードウェアへのアクセスを許可するオプションを選択" - -msgid "Additional repositories" -msgstr "追加リポジトリ" - -msgid "NTP" -msgstr "NTP" - -msgid "Swap on zram" -msgstr "zram のスワップ" - -msgid "Name" -msgstr "名前" - -msgid "Signature check" -msgstr "署名チェック" - -#, python-brace-format -msgid "Selected free space segment on device {}:" -msgstr "デバイス {} の選択された空きスペースセグメント:" - -#, python-brace-format -msgid "Size: {} / {}" -msgstr "サイズ: {} / {}" - -#, python-brace-format -msgid "Size (default: {}): " -msgstr "サイズ (デフォルト: {}): " - -msgid "HSM device" -msgstr "HSM デバイス" - -msgid "Some packages could not be found in the repository" -msgstr "リポジトリ内にいくつかのパッケージが見つかりませんでした" - -msgid "User" -msgstr "ユーザー" - -msgid "The specified configuration will be applied" -msgstr "指定された設定が適用されます" - -msgid "Wipe" -msgstr "消去" - -msgid "Mark/Unmark as XBOOTLDR" -msgstr "XBOOTLDR としてマーク/マーク解除" - -msgid "Loading packages..." -msgstr "パッケージを読み込んでいます..." - -msgid "Select any packages from the below list that should be installed additionally" -msgstr "追加でインストールする必要があるパッケージをリストから選択してください" - -msgid "Add a custom repository" -msgstr "カスタムリポジトリを追加" - -msgid "Change custom repository" -msgstr "カスタムリポジトリを変更" - -msgid "Delete custom repository" -msgstr "カスタムリポジトリを削除" - -msgid "Repository name" -msgstr "リポジトリ名" - -msgid "Add a custom server" -msgstr "カスタムサーバーを追加" - -msgid "Change custom server" -msgstr "カスタムサーバーを変更" - -msgid "Delete custom server" -msgstr "カスタムサーバーを削除" - -msgid "Server url" -msgstr "サーバー URL" - -msgid "Select regions" -msgstr "地域を選択" - -msgid "Add custom servers" -msgstr "カスタムサーバーを追加" - -msgid "Add custom repository" -msgstr "カスタムリポジトリを追加" - -msgid "Loading mirror regions..." -msgstr "ミラーの地域を読み込んでいます..." - -msgid "Mirrors and repositories" -msgstr "ミラーとリポジトリ" - -msgid "Selected mirror regions" -msgstr "選択されたミラーの地域" - -msgid "Custom servers" -msgstr "カスタムサーバー" - -msgid "Custom repositories" -msgstr "カスタムリポジトリ" - -msgid "Only ASCII characters are supported" -msgstr "ASCII 文字のみサポートされます" - -msgid "Show help" -msgstr "ヘルプを表示" - -msgid "Exit help" -msgstr "ヘルプを終了" - -msgid "Preview scroll up" -msgstr "プレビューを上にスクロール" - -msgid "Preview scroll down" -msgstr "プレビューを下にスクロール" - -msgid "Move up" -msgstr "上に移動" - -msgid "Move down" -msgstr "下に移動" - -msgid "Move right" -msgstr "右に移動" - -msgid "Move left" -msgstr "左に移動" - -msgid "Jump to entry" -msgstr "エントリーへジャンプ" - -msgid "Skip selection (if available)" -msgstr "選択をスキップ(利用可能な場合)" - -msgid "Reset selection (if available)" -msgstr "選択をリセット(利用可能な場合)" - -msgid "Select on single select" -msgstr "単一で選択" - -msgid "Select on multi select" -msgstr "複数で選択" - -msgid "Reset" -msgstr "リセット" - -msgid "Skip selection menu" -msgstr "選択メニューをスキップ" - -msgid "Start search mode" -msgstr "検索モードを開始" - -msgid "Exit search mode" -msgstr "検索モードを終了" - -msgid "General" -msgstr "一般" - -msgid "Navigation" -msgstr "ナビゲーション" - -msgid "Selection" -msgstr "選択" - -msgid "Search" -msgstr "検索" - -msgid "Down" -msgstr "下へ" - -msgid "Up" -msgstr "上へ" - -msgid "Confirm" -msgstr "確認" - -msgid "Focus right" -msgstr "右にフォーカス" - -msgid "Focus left" -msgstr "左にフォーカス" - -msgid "Toggle" -msgstr "切り替え" - -msgid "Show/Hide help" -msgstr "ヘルプを表示/隠す" - -msgid "Quit" -msgstr "終了" - -msgid "First" -msgstr "最初" - -msgid "Last" -msgstr "最後" - -msgid "Select" -msgstr "選択" - -msgid "Page Up" -msgstr "上のページへ" - -msgid "Page Down" -msgstr "下のページへ" - -msgid "Page up" -msgstr "上のページへ" - -msgid "Page down" -msgstr "下のページへ" - -msgid "Page Left" -msgstr "左のページへ" - -msgid "Page Right" -msgstr "右のページへ" - -msgid "Cursor up" -msgstr "カーソルを上へ" - -msgid "Cursor down" -msgstr "カースルを下へ" - -msgid "Cursor right" -msgstr "カーソルを右へ" - -msgid "Cursor left" -msgstr "カーソルを左へ" - -msgid "Top" -msgstr "一番上へ" - -msgid "Bottom" -msgstr "一番下へ" - -msgid "Home" -msgstr "ホーム" - -msgid "End" -msgstr "最後へ" - -msgid "Toggle option" -msgstr "オプションを切り替え" - -msgid "Scroll Up" -msgstr "上にスクロール" - -msgid "Scroll Down" -msgstr "下にスクロール" - -msgid "Scroll Left" -msgstr "左にスクロール" - -msgid "Scroll Right" -msgstr "右にスクロール" - -msgid "Scroll Home" -msgstr "ホームにスクロール" - -msgid "Scroll End" -msgstr "一番下にスクロール" - -msgid "Focus Next" -msgstr "次にフォーカス" - -msgid "Focus Previous" -msgstr "前にフォーカス" - -msgid "Copy selected text" -msgstr "選択したテキストをコピー" - -msgid "labwc needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" -msgstr "labwc はお使いの Seat(キーボード、マウスなどのハードウェアデバイス群)にアクセスする必要があります" - -msgid "Choose an option to give labwc access to your hardware" -msgstr "labwc にハードウェアへのアクセスを許可するオプションを選択" - -msgid "niri needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" -msgstr "niri はお使いの Seat(キーボード、マウスなどのハードウェアデバイス群)にアクセスする必要があります" - -msgid "Choose an option to give niri access to your hardware" -msgstr "niri にハードウェアへのアクセスを許可するオプションを選択" - -msgid "Mark/Unmark as ESP" -msgstr "ESP としてマーク/マーク解除" - -msgid "Package group:" -msgstr "パッケージグループ:" - -msgid "Exit archinstall" -msgstr "archinstall を終了" - -msgid "Reboot system" -msgstr "システムを再起動" - -msgid "chroot into installation for post-installation configurations" -msgstr "インストール後の設定を行うためインストールディレクトリに chroot する" - -msgid "Installation completed" -msgstr "インストール完了" - -msgid "What would you like to do next?" -msgstr "次は何をしますか?" - -#, python-brace-format -msgid "Select which mode to configure for \"{}\"" -msgstr "「{}」に設定するモードを選択" - -msgid "Incorrect credentials file decryption password" -msgstr "認証情報ファイルの復号化パスワードが正しくありません" - -msgid "Incorrect password" -msgstr "パスワードが間違っています" - -msgid "Credentials file decryption password" -msgstr "認証情報ファイルの復号化パスワード" - -msgid "Do you want to encrypt the user_credentials.json file?" -msgstr "user_credentials.json ファイルを暗号化しますか?" - -msgid "Credentials file encryption password" -msgstr "認証情報ファイルの暗号化パスワード" - -#, python-brace-format -msgid "Repositories: {}" -msgstr "リポジトリ: {}" - -msgid "New version available" -msgstr "新しいバージョンが利用可能" - -msgid "Passwordless login" -msgstr "パスワードなしのログイン" - -msgid "Second factor login" -msgstr "2要素ログイン" - -msgid "Bluetooth" -msgstr "Bluetooth" - -msgid "Would you like to configure Bluetooth?" -msgstr "Bluetooth を設定しますか?" - -msgid "Print service" -msgstr "印刷サービス" - -msgid "Would you like to configure the print service?" -msgstr "印刷サービスを設定しますか?" - -msgid "Power management" -msgstr "電力管理" - -msgid "Authentication" -msgstr "認証" - -msgid "Applications" -msgstr "アプリケーション" - -msgid "U2F login method: " -msgstr "U2F ログインメソッド: " - -msgid "Passwordless sudo: " -msgstr "パスワードなしの sudo: " - -#, python-brace-format -msgid "Btrfs snapshot type: {}" -msgstr "Btrfs スナップショットのタイプ: {}" - -msgid "Syncing the system..." -msgstr "システムを同期..." - -msgid "Value cannot be empty" -msgstr "値は空にできません" - -msgid "Snapshot type" -msgstr "スナップショットのタイプ" - -#, python-brace-format -msgid "Snapshot type: {}" -msgstr "スナップショットのタイプ: {}" - -msgid "U2F login setup" -msgstr "U2F ログインの設定" - -msgid "No U2F devices found" -msgstr "U2F デバイスが見つかりません" - -msgid "U2F Login Method" -msgstr "U2F ログインメソッド" - -msgid "Enable passwordless sudo?" -msgstr "パスワードなしの sudo を有効にしますか?" - -#, python-brace-format -msgid "Setting up U2F device for user: {}" -msgstr "ユーザー用 U2F デバイスの設定: {}" - -msgid "You may need to enter the PIN and then touch your U2F device to register it" -msgstr "PIN を入力したのち U2F デバイスをタッチして登録しなければならない場合があります" - -msgid "Starting device modifications in " -msgstr "次の場所でデバイスの変更を開始しています " - -msgid "No network connection found" -msgstr "ネットワーク接続が見つかりません" - -msgid "Would you like to connect to a Wifi?" -msgstr "Wi-Fi に接続しますか?" - -msgid "No wifi interface found" -msgstr "Wi-Fi インターフェースが見つかりません" - -msgid "Select wifi network to connect to" -msgstr "接続する Wi-Fi ネットワークを選択" - -msgid "Scanning wifi networks..." -msgstr "Wi-Fi ネットワークをスキャンしています..." - -msgid "No wifi networks found" -msgstr "Wi-Fi ネットワークが見つかりません" - -msgid "Failed setting up wifi" -msgstr "Wi-Fi の設定に失敗しました" - -msgid "Enter wifi password" -msgstr "Wi-Fi パスワードを入力" - -msgid "Ok" -msgstr "OK" - -msgid "Removable" -msgstr "リムーバブル" - -msgid "Install to removable location" -msgstr "リムーバブルな場所にインストールする" - -msgid "Will install to /EFI/BOOT/ (removable location)" -msgstr "/EFI/BOOT/ (リムーバブルな場所) にインストールする" - -msgid "Will install to standard location with NVRAM entry" -msgstr "NVRAM エントリーのある標準の場所にインストールする" - -msgid "Would you like to install the bootloader to the default removable media search location?" -msgstr "ブートローダーをデフォルトのリムーバブルメディアの検索場所にインストールしますか?" - -msgid "This installs the bootloader to /EFI/BOOT/BOOTX64.EFI (or similar) which is useful for:" -msgstr "ブートローダーが /EFI/BOOT/BOOTX64.EFI (または類似の場所) にインストールされ、次の場合に役立ちます:" - -msgid "USB drives or other portable external media." -msgstr "USB ドライブまたは他のポータブル外部メディア。" - -msgid "Systems where you want the disk to be bootable on any computer." -msgstr "ディスクをどのコンピューターでも起動できるようにするシステム。" - -msgid "Firmware that does not properly support NVRAM boot entries." -msgstr "NVRAM ブートエントリーを適切にサポートしていないファームウェア。" - -msgid "Will install to /EFI/BOOT/ (removable location, safe default)" -msgstr "/EFI/BOOT/(リムーバブルな場所、安全なデフォルト)にインストール" - -msgid "Will install to custom location with NVRAM entry" -msgstr "NVRAM エントリーを使用してカスタムした場所にインストール" - -msgid "Firmware that does not properly support NVRAM boot entries like most MSI motherboards," -msgstr "ほとんどの MSI マザーボードのように NVRAM ブートエントリーを適切にサポートしていないファームウェア、" - -msgid "most Apple Macs, many laptops..." -msgstr "ほとんどの Apple Mac、多くのラップトップ..." - -msgid "Language" -msgstr "言語" - -msgid "Compression algorithm" -msgstr "圧縮アルゴリズム" - -msgid "Only packages such as base, sudo, linux, linux-firmware, efibootmgr and optional profile packages are installed." -msgstr "base、sudo、linux、linux-firmware、efibootmgr などのパッケージとオプションのプロファイルパッケージのみがインストールされます。" - -msgid "Select zram compression algorithm:" -msgstr "zram 圧縮アルゴリズムを選択:" - -msgid "Use Network Manager (default backend)" -msgstr "Network Manager を使用(デフォルトのバックエンド)" - -msgid "Use Network Manager (iwd backend)" -msgstr "Network Manager を使用(iwd バックエンド)" - -msgid "Firewall" -msgstr "ファイアウォール" - -msgid "Additional fonts" -msgstr "追加フォント" - -msgid "Select font packages to install" -msgstr "インストールするフォントパッケージを選択" - -msgid "Unicode font coverage for most languages" -msgstr "ほとんどの言語をカバーする Unicode フォント" - -msgid "color emoji for browsers and apps" -msgstr "ブラウザやアプリ用のカラー絵文字" - -msgid "Chinese, Japanese, Korean characters" -msgstr "日本語、中国語、韓国語の文字" - -msgid "Select audio configuration" -msgstr "オーディオ設定を選択" - -msgid "Enter credentials file decryption password" -msgstr "認証情報ファイルの復号パスワードを入力" - -msgid "Enter root password" -msgstr "root パスワードを入力" - -msgid "Select bootloader to install" -msgstr "インストールするブートローダーを選択" - -msgid "Configuration preview" -msgstr "設定プレビュー" - -msgid "Enter a directory for the configuration(s) to be saved" -msgstr "設定を保存するディレクトリを入力" - -msgid "Select encryption type" -msgstr "暗号化のタイプを選択" - -msgid "Select disks for the installation" -msgstr "インストール用のディスクを選択" - -msgid "Enter a mountpoint" -msgstr "マウントポイントを入力" - -#, python-brace-format -msgid "Enter a size (default: {}): " -msgstr "サイズを入力(デフォルト: {}): " - -msgid "Enter subvolume name" -msgstr "サブボリューム名を入力" - -msgid "Enter subvolume mountpoint" -msgstr "サブボリュームのマウントポイントを入力" - -msgid "Select a disk configuration" -msgstr "ディスクの設定を選択" - -msgid "Enter root mount directory" -msgstr "ルートマウントディレクトリを入力" - -msgid "You will use whatever drive-setup is mounted at the specified directory" -msgstr "指定されたディレクトリにマウントされているドライブの設定を使用します" - -msgid "WARNING: Archinstall won't check the suitability of this setup" -msgstr "警告: Archinstall はこのセットアップの適合性をチェックしません" - -msgid "Select main filesystem" -msgstr "メインファイルシステムを選択" - -msgid "Enter a hostname" -msgstr "ホスト名を入力" - -msgid "Select timezone" -msgstr "タイムゾーンを選択" - -msgid "Enter the number of parallel downloads to be enabled" -msgstr "有効にする並列ダウンロード数を入力" - -#, python-brace-format -msgid "Value must be between 1 and {}" -msgstr "値は 1 から {} までの範囲にしてください" - -msgid "Select which kernel(s) to install" -msgstr "インストールするカーネルを選択" - -msgid "Enter a respository name" -msgstr "リポジトリ名を入力" - -msgid "Enter the repository url" -msgstr "リポジトリの URL を入力" - -msgid "Enter server url" -msgstr "サーバーの URL を入力" - -msgid "Select mirror regions to be enabled" -msgstr "有効にするミラー地域を選択" - -msgid "Select optional repositories to be enabled" -msgstr "有効にするオプションリポジトリを選択" - -msgid "Select an interface" -msgstr "インターフェースを選択" - -msgid "Choose network configuration" -msgstr "ネットワーク設定を選択" - -msgid "Recommended: Network Manager for desktop, Manual for server" -msgstr "推奨: デスクトップのネットワークマネージャー、サーバーのマニュアル" - -msgid "Warning: no network configuration selected. Network will need to be set up manually on the installed system." -msgstr "警告: ネットワーク設定が選択されていません。インストール後のシステムで、ネットワークを手動で設定する必要があります。" - -msgid "No packages found" -msgstr "パッケージが見つかりません" - -msgid "Select which greeter to install" -msgstr "インストールするグリーターを選択" - -msgid "Select a profile type" -msgstr "プロファイルのタイプを選択" - -msgid "Enter new password" -msgstr "新しいパスワードを入力" - -msgid "Enter a username" -msgstr "ユーザー名を入力" - -msgid "Enter a password" -msgstr "パスワードを入力" - -msgid "The password did not match, please try again" -msgstr "パスワードが一致しません。もう一度試してください" - -msgid "Password strength: Weak" -msgstr "パスワードの強度: 弱い" - -msgid "Password strength: Moderate" -msgstr "パスワードの強度: 中程度" - -msgid "Password strength: Strong" -msgstr "パスワードの強度: 強い" - -msgid "The selected desktop profile requires a regular user to log in via the greeter" -msgstr "選択されたデスクトッププロファイルでは、一般ユーザーがグリーター経由でログインする必要があります" - -#, python-brace-format -msgid "Environment type: {} {}" -msgstr "環境タイプ: {} {}" - -msgid "Input cannot be empty" -msgstr "入力は空にできません" - msgid "Recommended" msgstr "推奨" @@ -2203,30 +35,2365 @@ msgstr "グループ内のパッケージ" msgid "Minimal KDE Plasma installation" msgstr "最小限の KDE Plasma インストール" +msgid "Type" +msgstr "タイプ" + msgid "Description" msgstr "説明" msgid "Select a flavor of KDE Plasma to install" msgstr "インストールする KDE Plasma のバージョンを選択" +#, python-brace-format +msgid "{} needs access to your seat" +msgstr "{} はお使いの Seat へのアクセスを必要とします" + +msgid "collection of hardware devices i.e. keyboard, mouse" +msgstr "ハードウェアデバイス群。キーボード、マウスなど" + +#, python-brace-format +msgid "Choose an option how to give {} access to your hardware" +msgstr "{} にハードウェアへのアクセスを許可する方法を選択" + +#, python-brace-format +msgid "Environment type: {} {}" +msgstr "環境タイプ: {} {}" + +#, python-brace-format +msgid "Environment type: {}" +msgstr "環境タイプ: {}" + +msgid "Installed packages" +msgstr "インストールするパッケージ" + +msgid "Bluetooth" +msgstr "Bluetooth" + +msgid "Audio" +msgstr "オーディオ" + +msgid "Print service" +msgstr "印刷サービス" + +msgid "Power management" +msgstr "電力管理" + +msgid "Firewall" +msgstr "ファイアウォール" + +msgid "Additional fonts" +msgstr "追加フォント" + +msgid "Enabled" +msgstr "有効" + +msgid "Disabled" +msgstr "無効" + +msgid "Would you like to configure Bluetooth?" +msgstr "Bluetooth を設定しますか?" + +msgid "Would you like to configure the print service?" +msgstr "印刷サービスを設定しますか?" + +msgid "Select audio configuration" +msgstr "オーディオ設定を選択" + +msgid "Select font packages to install" +msgstr "インストールするフォントパッケージを選択" + +msgid "ArchInstall Language" +msgstr "ArchInstall の言語" + +msgid "Version" +msgstr "バージョン" + +msgid "Installation Script" +msgstr "インストールスクリプト" + +msgid "Locales" +msgstr "ロケール" + +msgid "Disk configuration" +msgstr "ディスクの設定" + +msgid "Profile" +msgstr "プロファイル" + +msgid "Mirrors and repositories" +msgstr "ミラーとリポジトリ" + +msgid "Network" +msgstr "ネットワーク" + +msgid "Bootloader" +msgstr "ブートローダー" + +msgid "Application" +msgstr "アプリケーション" + +msgid "Authentication" +msgstr "認証" + +msgid "Swap" +msgstr "スワップ" + +msgid "Hostname" +msgstr "ホスト名" + +msgid "Kernels" +msgstr "カーネル" + +msgid "Automatic time sync (NTP)" +msgstr "時刻の自動同期(NTP)" + +msgid "Timezone" +msgstr "タイムゾーン" + +msgid "Services" +msgstr "サービス" + +msgid "Additional packages" +msgstr "追加パッケージ" + +msgid "Pacman" +msgstr "Pacman" + +msgid "Custom commands" +msgstr "カスタムコマンド" + +msgid "Users" +msgstr "ユーザー" + +msgid "Root encrypted password" +msgstr "Root 暗号化パスワード" + +msgid "Disk encryption password" +msgstr "ディスク暗号化パスワード" + +msgid "Incorrect credentials file decryption password" +msgstr "認証情報ファイルの復号化パスワードが正しくありません" + +msgid "Enter credentials file decryption password" +msgstr "認証情報ファイルの復号パスワードを入力" + +msgid "Incorrect password" +msgstr "パスワードが間違っています" + +#, python-brace-format +msgid "Setting up U2F login: {}" +msgstr "U2F ログインの設定: {}" + +#, python-brace-format +msgid "Setting up U2F device for user: {}" +msgstr "ユーザー用 U2F デバイスの設定: {}" + +msgid "You may need to enter the PIN and then touch your U2F device to register it" +msgstr "PIN を入力したのち U2F デバイスをタッチして登録しなければならない場合があります" + +msgid "Root password" +msgstr "root パスワード" + +msgid "User account" +msgstr "ユーザーアカウント" + +msgid "U2F login setup" +msgstr "U2F ログインの設定" + +msgid "U2F login method: " +msgstr "U2F ログインメソッド: " + +msgid "Passwordless sudo: " +msgstr "パスワードなしの sudo: " + +msgid "No U2F devices found" +msgstr "U2F デバイスが見つかりません" + +msgid "Enter root password" +msgstr "root パスワードを入力" + +msgid "Enable passwordless sudo?" +msgstr "パスワードなしの sudo を有効にしますか?" + +msgid "Unified kernel images" +msgstr "Unified カーネルイメージ" + +msgid "Install to removable location" +msgstr "リムーバブルな場所にインストールする" + +msgid "Will install to /EFI/BOOT/ (removable location, safe default)" +msgstr "/EFI/BOOT/(リムーバブルな場所、安全なデフォルト)にインストール" + +msgid "Will install to custom location with NVRAM entry" +msgstr "NVRAM エントリーを使用してカスタムした場所にインストール" + +msgid "Would you like to use unified kernel images?" +msgstr "Unified カーネルイメージを使用しますか?" + +msgid "Would you like to install the bootloader to the default removable media search location?" +msgstr "ブートローダーをデフォルトのリムーバブルメディアの検索場所にインストールしますか?" + +msgid "This installs the bootloader to /EFI/BOOT/BOOTX64.EFI (or similar) which is useful for:" +msgstr "ブートローダーが /EFI/BOOT/BOOTX64.EFI (または類似の場所) にインストールされ、次の場合に役立ちます:" + +msgid "Firmware that does not properly support NVRAM boot entries like most MSI motherboards," +msgstr "ほとんどの MSI マザーボードのように NVRAM ブートエントリーを適切にサポートしていないファームウェア、" + +msgid "most Apple Macs, many laptops..." +msgstr "ほとんどの Apple Mac、多くのラップトップ..." + +msgid "USB drives or other portable external media." +msgstr "USB ドライブまたは他のポータブル外部メディア。" + +msgid "Systems where you want the disk to be bootable on any computer." +msgstr "ディスクをどのコンピューターでも起動できるようにするシステム。" + +msgid "Select bootloader to install" +msgstr "インストールするブートローダーを選択" + +msgid "UEFI is not detected and some options are disabled" +msgstr "UEFIが検出されず、一部のオプションが無効になります" + +msgid "The specified configuration will be applied" +msgstr "指定された設定が適用されます" + +msgid "Would you like to continue?" +msgstr "続行しますか?" + +msgid "Configuration preview" +msgstr "設定プレビュー" + +msgid "Warning: no network configuration selected. Network will need to be set up manually on the installed system." +msgstr "警告: ネットワーク設定が選択されていません。インストール後のシステムで、ネットワークを手動で設定する必要があります。" + +msgid "No configuration" +msgstr "設定なし" + +msgid "Save user configuration (including disk layout)" +msgstr "ユーザー設定を保存(ディスクレイアウトを含む)" + +msgid "Save user credentials" +msgstr "ユーザーの認証情報を保存" + +msgid "Save all" +msgstr "すべて保存" + +msgid "Enter a directory for the configuration(s) to be saved" +msgstr "設定を保存するディレクトリを入力" + +#, python-brace-format +msgid "Do you want to save the configuration file(s) to {}?" +msgstr "設定ファイルを次の場所に保存しますか? {}" + +msgid "Do you want to encrypt the user_credentials.json file?" +msgstr "user_credentials.json ファイルを暗号化しますか?" + +msgid "Credentials file encryption password" +msgstr "認証情報ファイルの暗号化パスワード" + +msgid "Partitioning" +msgstr "パーティションを作成" + +msgid "Disk encryption" +msgstr "ディスクの暗号化" + +#, python-brace-format +msgid "Configuration type: {}" +msgstr "設定タイプ: {}" + +msgid "Mountpoint" +msgstr "マウントポイント" + +msgid "Configuration" +msgstr "設定" + +msgid "Wipe" +msgstr "消去" + +msgid "Physical volumes" +msgstr "物理ボリューム" + +msgid "Volumes" +msgstr "ボリューム" + +#, python-brace-format +msgid "Snapshot type: {}" +msgstr "スナップショットのタイプ: {}" + +msgid "LVM disk encryption with more than 2 partitions is currently not supported" +msgstr "パーティションが2個を超える場合の LVM ディスク暗号化は、現在サポートしていません" + +msgid "Encryption type" +msgstr "暗号化のタイプ" + +msgid "Password" +msgstr "パスワード" + +msgid "Iteration time" +msgstr "イテレーション時間" + +msgid "Select disks for the installation" +msgstr "インストール用のディスクを選択" + +msgid "Partitions" +msgstr "パーティション" + +msgid "Select a disk configuration" +msgstr "ディスクの設定を選択" + +msgid "Enter root mount directory" +msgstr "ルートマウントディレクトリを入力" + +msgid "You will use whatever drive-setup is mounted at the specified directory" +msgstr "指定されたディレクトリにマウントされているドライブの設定を使用します" + +msgid "WARNING: Archinstall won't check the suitability of this setup" +msgstr "警告: Archinstall はこのセットアップの適合性をチェックしません" + +msgid "Select main filesystem" +msgstr "メインファイルシステムを選択" + +msgid "Would you like to use compression or disable CoW?" +msgstr "圧縮を使用しますか、それとも CoW を無効にしますか?" + +msgid "Use compression" +msgstr "圧縮する" + +msgid "Disable Copy-on-Write" +msgstr "コピーオンライトを無効にする" + +msgid "Would you like to use BTRFS subvolumes with a default structure?" +msgstr "デフォルトの設定で Btrfs サブボリュームを使用しますか?" + +msgid "Would you like to create a separate partition for /home?" +msgstr "/home 用に別のパーティションを作成しますか?" + +msgid "The selected drives do not have the minimum capacity required for an automatic suggestion\n" +msgstr "選択したドライブには、自動提案に必要な最小容量がありません\n" + +#, python-brace-format +msgid "Minimum capacity for /home partition: {}GiB\n" +msgstr "/home パーティションの最小容量: {}GiB\n" + +#, python-brace-format +msgid "Minimum capacity for Arch Linux partition: {}GiB" +msgstr "Arch Linux パーティションの最小容量: {}GiB" + +msgid "Encryption password" +msgstr "暗号化パスワード" + +msgid "LVM volumes" +msgstr "LVM ボリューム" + +msgid "HSM" +msgstr "HSM" + +msgid "Partitions to be encrypted" +msgstr "暗号化するパーティション" + +msgid "LVM volumes to be encrypted" +msgstr "暗号化する LVM ボリューム" + +msgid "HSM device" +msgstr "HSM デバイス" + +msgid "Select encryption type" +msgstr "暗号化のタイプを選択" + +msgid "Enter disk encryption password (leave blank for no encryption)" +msgstr "ディスクの暗号化パスワードを入力(暗号化しない場合は無記入)" + +msgid "Select a FIDO2 device to use for HSM" +msgstr "HSM に使用する FIDO2 デバイスを選択" + +msgid "Enter iteration time for LUKS encryption (in milliseconds)" +msgstr "LUKS 暗号化のイテレーション時間(ミリ秒単位)を入力" + +msgid "Higher values increase security but slow down boot time" +msgstr "値を大きくするとセキュリティは向上しますが、起動時間が遅くなります" + +#, python-brace-format +msgid "Default: {}ms, Recommended range: 1000-60000" +msgstr "デフォルト: {}ms, 推奨範囲: 1000-60000" + +msgid "Iteration time must be at least 100ms" +msgstr "イテレーション時間は最低 100ms にしてください" + +msgid "Iteration time must be at most 120000ms" +msgstr "イテレーション時間は最大 120000ms にしてください" + +msgid "Please enter a valid number" +msgstr "有効な数字を入力してください" + +msgid "Suggest partition layout" +msgstr "パーティションレイアウトを提案" + +msgid "Remove all newly added partitions" +msgstr "新しく追加されたパーティションをすべて削除" + +msgid "Assign mountpoint" +msgstr "マウントポイントを割り当てる" + +msgid "Mark/Unmark to be formatted (wipes data)" +msgstr "フォーマット対象としてマーク/マーク解除(データを消去)" + +msgid "Mark/Unmark as bootable" +msgstr "ブータブルとしてマーク/マーク解除" + +msgid "Mark/Unmark as ESP" +msgstr "ESP としてマーク/マーク解除" + +msgid "Mark/Unmark as XBOOTLDR" +msgstr "XBOOTLDR としてマーク/マーク解除" + +msgid "Change filesystem" +msgstr "ファイルシステムを変更" + +msgid "Mark/Unmark as compressed" +msgstr "圧縮対象としてマーク/マーク解除" + +msgid "Mark/Unmark as nodatacow" +msgstr "nodatacow としてマーク/マーク解除" + +msgid "Set subvolumes" +msgstr "サブボリュームを設定" + +msgid "Delete partition" +msgstr "パーティションを削除" + +#, python-brace-format +msgid "Partition management: {}" +msgstr "パーティションを管理: {}" + +#, python-brace-format +msgid "Total length: {}" +msgstr "全体のサイズ: {}" + +msgid "Partition - New" +msgstr "パーティション - 新規" + +msgid "Partition" +msgstr "パーティション" + +msgid "This partition is currently encrypted, to format it a filesystem has to be specified" +msgstr "このパーティションは現在暗号化されています。フォーマットするにはファイルシステムを指定してください" + +msgid "Partition mount-points are relative to inside the installation, the boot would be /boot as an example." +msgstr "パーティションのマウントポイントはインストールにおける相対的なもので、例として boot は /boot になります。" + +msgid "Enter a mountpoint" +msgstr "マウントポイントを入力" + +msgid "Invalid size" +msgstr "無効なサイズ" + +#, python-brace-format +msgid "Selected free space segment on device {}:" +msgstr "デバイス {} の選択された空きスペースセグメント:" + +#, python-brace-format +msgid "Size: {} / {}" +msgstr "サイズ: {} / {}" + +msgid "All entered values can be suffixed with a unit: %, B, KB, KiB, MB, MiB..." +msgstr "入力したすべての値に、%、B、KB、KiB、MB、MiB などの単位を付けることができます。" + +msgid "If no unit is provided, the value is interpreted as sectors" +msgstr "単位が指定されていない場合、値はセクターとして解釈されます" + +#, python-brace-format +msgid "Enter a size (default: {}): " +msgstr "サイズを入力(デフォルト: {}): " + +msgid "This will remove all newly added partitions, continue?" +msgstr "これは新しく追加されたパーティションをすべて削除します。続けますか?" + +msgid "Add subvolume" +msgstr "サブボリュームを追加" + +msgid "Edit subvolume" +msgstr "サブボリュームを編集" + +msgid "Delete subvolume" +msgstr "サブボリュームを削除" + +msgid "Value cannot be empty" +msgstr "値は空にできません" + +msgid "Enter subvolume name" +msgstr "サブボリューム名を入力" + +msgid "Subvolume name" +msgstr "サブボリューム名" + +msgid "Enter subvolume mountpoint" +msgstr "サブボリュームのマウントポイントを入力" + +msgid "Exit archinstall" +msgstr "archinstall を終了" + +msgid "Reboot system" +msgstr "システムを再起動" + +msgid "chroot into installation for post-installation configurations" +msgstr "インストール後の設定を行うためインストールディレクトリに chroot する" + +msgid "Would you like to use automatic time synchronization (NTP) with the default time servers?\n" +msgstr "デフォルトのタイムサーバーで時刻の自動同期(NTP)を使用しますか?\n" + +msgid "" +"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" +msgstr "" +"NTP が機能するには、ハードウェアクロックおよびその他の設定後のステップが必要になる場合があります。\n" +"詳細については Arch wiki を確認してください" + +msgid "Enter a hostname" +msgstr "ホスト名を入力" + +msgid "Select timezone" +msgstr "タイムゾーンを選択" + +msgid "What would you like to do next?" +msgstr "次は何をしますか?" + +msgid "Select which kernel(s) to install" +msgstr "インストールするカーネルを選択" + +msgid "For the best compatibility with your AMD hardware, you may want to use either the all open-source or AMD / ATI options." +msgstr "AMD ハードウェアとの互換性を最大限に高めるには、すべてのオープンソースまたは AMD/ATI オプションのいずれかを使用することをお勧めします。" + +msgid "For the best compatibility with your Intel hardware, you may want to use either the all open-source or Intel options.\n" +msgstr "Intel ハードウェアとの互換性を最大限に高めるには、すべてのオープンソースまたは Intel オプションのいずれかを使用することをお勧めします。\n" + +msgid "For the best compatibility with your Nvidia hardware, you may want to use the Nvidia proprietary driver.\n" +msgstr "Nvidia ハードウェアとの互換性を最大限に高めるには、Nvidia 独自のドライバーを使用することをお勧めします。\n" + +msgid "Would you like to use swap on zram?" +msgstr "zram でスワップを使用しますか?" + +msgid "Select zram compression algorithm:" +msgstr "zram 圧縮アルゴリズムを選択:" + +msgid "Archinstall language" +msgstr "Archinstall の言語" + +msgid "Applications" +msgstr "アプリケーション" + +msgid "Network configuration" +msgstr "ネットワーク設定" + +msgid "Save configuration" +msgstr "設定を保存" + +msgid "Install" +msgstr "インストール" + +msgid "Abort" +msgstr "中止" + +msgid "Either root-password or at least 1 user with sudo privileges must be specified" +msgstr "root パスワードか、1人以上の sudo 権限を持つユーザーを指定する必要があります" + +msgid "The selected desktop profile requires a regular user to log in via the greeter" +msgstr "選択されたデスクトッププロファイルでは、一般ユーザーがグリーター経由でログインする必要があります" + +msgid "Language" +msgstr "言語" + +msgid "NTP" +msgstr "NTP" + +msgid "LVM configuration type" +msgstr "LVM の設定タイプ" + +#, python-brace-format +msgid "Btrfs snapshot type: {}" +msgstr "Btrfs スナップショットのタイプ: {}" + +msgid "Swap on zram" +msgstr "Zram 上でスワップ" + +msgid "Compression algorithm" +msgstr "圧縮アルゴリズム" + +msgid "Parallel Downloads" +msgstr "並行ダウンロード" + +msgid "Color" +msgstr "カラー出力" + +msgid "Kernel" +msgstr "カーネル" + +msgid "Missing configurations:\n" +msgstr "設定が存在しません:\n" + +#, python-brace-format +msgid "Invalid configuration: {}" +msgstr "無効な設定: {}" + +msgid "Ready to install" +msgstr "インストールの準備が完了" + +msgid "Profiles" +msgstr "プロファイル" + +msgid "Graphics driver" +msgstr "グラフィックドライバー" + +msgid "Greeter" +msgstr "グリーター" + +msgid "Selected mirror regions" +msgstr "選択されたミラーの地域" + +msgid "Custom servers" +msgstr "カスタムサーバー" + +msgid "Optional repositories" +msgstr "オプションリポジトリ" + +msgid "Custom repositories" +msgstr "カスタムリポジトリ" + +#, python-brace-format +msgid "[!] A log file has been created here: {}" +msgstr "[!] ここにログファイルが作成されました: {}" + +msgid "Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues" +msgstr "この問題(およびファイル)を https://github.com/archlinux/archinstall/issues に送信してください" + +msgid "Syncing the system..." +msgstr "システムを同期..." + +msgid "Waiting for time sync (timedatectl show) to complete." +msgstr "時刻の同期(timedatectl show)が完了するのを待機しています。" + +msgid "Time synchronization not completing, while you wait - check the docs for workarounds: https://archinstall.readthedocs.io/" +msgstr "待機中に時刻同期が完了しません - 回避策についてはドキュメントを確認してください: https://archinstall.readthedocs.io/" + +msgid "Skipping waiting for automatic time sync (this can cause issues if time is out of sync during installation)" +msgstr "自動での時刻同期の待機をスキップします(インストール中に時刻が同期していない場合は、問題が発生する可能性があります)" + +msgid "Waiting for Arch Linux keyring sync (archlinux-keyring-wkd-sync) to complete." +msgstr "Arch Linux キーリングの同期(archlinux-keyring-wkd-sync)が完了するのを待っています。" + +msgid "Keyboard layout" +msgstr "キーボードレイアウト" + +msgid "Locale language" +msgstr "ロケール言語" + +msgid "Locale encoding" +msgstr "ロケールエンコーディング" + +msgid "Console font" +msgstr "コンソールフォント" + +msgid "Back" +msgstr "戻る" + +msgid "Are you sure you want to reset this setting?" +msgstr "この設定をリセットしてもよろしいですか?" + +msgid "Confirm and exit" +msgstr "確認して終了" + +msgid "Cancel" +msgstr "キャンセル" + +msgid "Password strength: Weak" +msgstr "パスワードの強度: 弱い" + +msgid "Password strength: Moderate" +msgstr "パスワードの強度: 中程度" + +msgid "Password strength: Strong" +msgstr "パスワードの強度: 強い" + +msgid "Confirm password" +msgstr "パスワードを確認" + +msgid "The password did not match, please try again" +msgstr "パスワードが一致しません。もう一度試してください" + +msgid "Not a valid directory" +msgstr "有効なディレクトリではありません" + +msgid "Do you really want to abort?" +msgstr "本当に中止しますか?" + +msgid "Add a custom repository" +msgstr "カスタムリポジトリを追加" + +msgid "Change custom repository" +msgstr "カスタムリポジトリを変更" + +msgid "Delete custom repository" +msgstr "カスタムリポジトリを削除" + +msgid "Enter a repository name" +msgstr "リポジトリ名を入力" + +msgid "Name" +msgstr "名前" + +msgid "Enter the repository url" +msgstr "リポジトリの URL を入力" + +msgid "Url" +msgstr "URL" + +msgid "Select signature check" +msgstr "署名チェックを選択" + +msgid "Signature check" +msgstr "署名チェック" + +msgid "Select signature option" +msgstr "署名オプションを選択" + +msgid "Add a custom server" +msgstr "カスタムサーバーを追加" + +msgid "Change custom server" +msgstr "カスタムサーバーを変更" + +msgid "Delete custom server" +msgstr "カスタムサーバーを削除" + +msgid "Enter server url" +msgstr "サーバーの URL を入力" + +msgid "Select regions" +msgstr "地域を選択" + +msgid "Add custom servers" +msgstr "カスタムサーバーを追加" + +msgid "Add custom repository" +msgstr "カスタムリポジトリを追加" + +msgid "Additional repositories" +msgstr "追加リポジトリ" + +msgid "Loading mirror regions..." +msgstr "ミラーの地域を読み込んでいます..." + +msgid "Select mirror regions to be enabled" +msgstr "有効にするミラー地域を選択" + +msgid "Select optional repositories to be enabled" +msgstr "有効にするオプションリポジトリを選択" + +msgid "Unicode font coverage for most languages" +msgstr "ほとんどの言語をカバーする Unicode フォント" + +msgid "color emoji for browsers and apps" +msgstr "ブラウザやアプリ用のカラー絵文字" + +msgid "Chinese, Japanese, Korean characters" +msgstr "日本語、中国語、韓国語の文字" + msgid "Arial/Times/Courier replacement, Cyrillic support for Steam/games" msgstr "Arial/Times/Courier フォントの代替、Steam/ゲームにおけるキリル文字のサポート" msgid "wide Unicode coverage, good fallback font" msgstr "Unicode を広くカバーする良い代替フォント" -#, python-brace-format -msgid "Setting up U2F login: {u2f_config.u2f_login_method.value}" -msgstr "U2F ログインの設定: {u2f_config.u2f_login_method.value}" +msgid "Zram enabled" +msgstr "Zram を有効にする" #, python-brace-format -msgid "Default: {DEFAULT_ITER_TIME}ms, Recommended range: 1000-60000" -msgstr "デフォルト: {DEFAULT_ITER_TIME}ms, 推奨範囲: 1000-60000" +msgid "Zram algorithm {}" +msgstr "Zram アルゴリズム {}" + +msgid "Bluetooth enabled" +msgstr "Bluetooth を有効にする" #, python-brace-format -msgid "Setting up U2F login: {}" -msgstr "U2F ログインの設定: {}" +msgid "Audio server \"{}\"" +msgstr "オーディオサーバー \"{}\"" #, python-brace-format -msgid "Default: {}ms, Recommended range: 1000-60000" -msgstr "デフォルト: {}ms, 推奨範囲: 1000-60000" +msgid "Power management \"{}\"" +msgstr "電力管理 \"{}\"" + +msgid "Print service enabled" +msgstr "印刷サービスを有効にする" + +#, python-brace-format +msgid "Firewall \"{}\"" +msgstr "ファイアウォール \"{}\"" + +#, python-brace-format +msgid "Extra fonts \"{}\"" +msgstr "追加フォント \"{}\"" + +msgid "Passwordless login" +msgstr "パスワードなしのログイン" + +msgid "Second factor login" +msgstr "2要素ログイン" + +msgid "Root password set" +msgstr "Root パスワードを設定" + +#, python-brace-format +msgid "Configured {} user(s)" +msgstr "{} 人のユーザーを設定" + +msgid "U2F set up" +msgstr "U2F を設定" + +#, python-brace-format +msgid "Bootloader \"{}\"" +msgstr "ブートローダー \"{}\"" + +msgid "UKI enabled" +msgstr "UKI を有効にする" + +msgid "Removable" +msgstr "リムーバブル" + +msgid "Use a best-effort default partition layout" +msgstr "ベストエフォートのデフォルトパーティションレイアウトを使用" + +msgid "Manual Partitioning" +msgstr "手動でパーティションを作成" + +msgid "Pre-mounted configuration" +msgstr "現在のマウント設定" + +msgid "Default" +msgstr "デフォルト" + +msgid "Manual" +msgstr "マニュアル" + +msgid "Pre-mount" +msgstr "プレマウント" + +#, python-brace-format +msgid "{} layout" +msgstr "{} レイアウト" + +#, python-brace-format +msgid "Devices {}" +msgstr "デバイス {}" + +msgid "LVM set up" +msgstr "LVM の設定" + +#, python-brace-format +msgid "{} encryption" +msgstr "{} 暗号化" + +#, python-brace-format +msgid "Btrfs snapshot \"{}\"" +msgstr "Btrfs スナップショット \"{}\"" + +msgid "Unknown" +msgstr "不明" + +msgid "Default layout" +msgstr "デフォルトのレイアウト" + +msgid "No Encryption" +msgstr "暗号化なし" + +msgid "LUKS" +msgstr "LUKS" + +msgid "LVM on LUKS" +msgstr "LUKS 上の LVM" + +msgid "LUKS on LVM" +msgstr "LVM 上の LUKS" + +#, python-brace-format +msgid "Keyboard layout \"{}\"" +msgstr "キーボードレイアウト \"{}\"" + +#, python-brace-format +msgid "Locale language \"{}\"" +msgstr "ロケール言語 \"{}\"" + +#, python-brace-format +msgid "Locale encoding \"{}\"" +msgstr "ロケールエンコーディング \"{}\"" + +#, python-brace-format +msgid "Console font \"{}\"" +msgstr "コンソールフォント \"{}\"" + +#, python-brace-format +msgid "Mirror regions \"{}\"" +msgstr "ミラーの地域 \"{}\"" + +#, python-brace-format +msgid "Optional repositories \"{}\"" +msgstr "オプションリポジトリ \"{}\"" + +msgid "Custom servers set up" +msgstr "カスタムサーバーを設定" + +msgid "Custom repositories set up" +msgstr "カスタムリポジトリを設定" + +msgid "Copy ISO network configuration to installation" +msgstr "ISO のネットワーク設定をインストール環境にコピー" + +msgid "Use Network Manager (default backend)" +msgstr "Network Manager を使用(デフォルトのバックエンド)" + +msgid "Use Network Manager (iwd backend)" +msgstr "Network Manager を使用(iwd バックエンド)" + +msgid "Use standalone iwd" +msgstr "スタンドアロンの iwd を使用" + +msgid "Manual configuration" +msgstr "手動設定" + +msgid "Package group:" +msgstr "パッケージグループ:" + +msgid "Color enabled" +msgstr "カラー出力を有効にする" + +#, python-brace-format +msgid "{} grphics driver" +msgstr "{} グラフィックドライバー" + +#, python-brace-format +msgid "{} greeter" +msgstr "{} グリーター" + +msgid "very weak" +msgstr "非常に弱い" + +msgid "weak" +msgstr "弱い" + +msgid "moderate" +msgstr "中程度" + +msgid "strong" +msgstr "強い" + +msgid "Add interface" +msgstr "インターフェイスを追加" + +msgid "Edit interface" +msgstr "インターフェイスを編集" + +msgid "Delete interface" +msgstr "インターフェイスを削除" + +msgid "Select an interface" +msgstr "インターフェースを選択" + +msgid "You need to enter a valid IP in IP-config mode" +msgstr "IP設定モードで有効なIPを入力する必要があります" + +#, python-brace-format +msgid "Select which mode to configure for \"{}\"" +msgstr "「{}」に設定するモードを選択" + +#, python-brace-format +msgid "Enter the IP and subnet for {} (example: 192.168.0.5/24): " +msgstr "{} の IP とサブネットを入力(例: 192.168.0.5/24): " + +msgid "Enter your gateway (router) IP address (leave blank for none)" +msgstr "ゲートウェイ(ルーター)の IP アドレスを入力。無い場合は無記入" + +msgid "Enter your DNS servers with space separated (leave blank for none)" +msgstr "DNS サーバーをスペースで区切って入力(無い場合は無記入)" + +msgid "Choose network configuration" +msgstr "ネットワーク設定を選択" + +msgid "Recommended: Network Manager for desktop, Manual for server" +msgstr "推奨: デスクトップのネットワークマネージャー、サーバーのマニュアル" + +msgid "Configure interfaces" +msgstr "インターフェースを設定" + +msgid "No network connection found" +msgstr "ネットワーク接続が見つかりません" + +msgid "Would you like to connect to a Wifi?" +msgstr "Wi-Fi に接続しますか?" + +msgid "No wifi interface found" +msgstr "Wi-Fi インターフェースが見つかりません" + +msgid "Select wifi network to connect to" +msgstr "接続する Wi-Fi ネットワークを選択" + +msgid "Scanning wifi networks..." +msgstr "Wi-Fi ネットワークをスキャンしています..." + +msgid "No wifi networks found" +msgstr "Wi-Fi ネットワークが見つかりません" + +msgid "Failed setting up wifi" +msgstr "Wi-Fi の設定に失敗しました" + +msgid "Enter wifi password" +msgstr "Wi-Fi パスワードを入力" + +#, python-brace-format +msgid "Repositories: {}" +msgstr "リポジトリ: {}" + +msgid "Loading packages..." +msgstr "パッケージを読み込んでいます..." + +msgid "No packages found" +msgstr "パッケージが見つかりません" + +msgid "Only packages such as base, sudo, linux, linux-firmware, efibootmgr and optional profile packages are installed." +msgstr "base、sudo、linux、linux-firmware、efibootmgr などのパッケージとオプションのプロファイルパッケージのみがインストールされます。" + +msgid "Note: base-devel is no longer installed by default. Add it here if you need build tools." +msgstr "注意: base-devel はデフォルトではインストールされなくなりました。ビルドツールが必要な場合は、ここで追加してください。" + +msgid "Select any packages from the below list that should be installed additionally" +msgstr "追加でインストールする必要があるパッケージをリストから選択してください" + +msgid "Pacman is already running, waiting maximum 10 minutes for it to terminate." +msgstr "Pacman はすでに実行されており、終了するまで最大 10 分間待機します。" + +msgid "Pre-existing pacman lock never exited. Please clean up any existing pacman sessions before using archinstall." +msgstr "既存の pacman のロックが終了しませんでした。archinstall を使用する前に、既存の pacman セッションをすべてクリーンアップしてください。" + +#, python-brace-format +msgid "Enter the number of parallel downloads (1-{})" +msgstr "並列ダウンロード数を入力 (1-{})" + +#, python-brace-format +msgid "Value must be between 1 and {}" +msgstr "値は 1 から {} までの範囲にしてください" + +msgid "Enable colored output for pacman" +msgstr "pacman でカラー出力を有効にする" + +msgid "The proprietary Nvidia driver is not supported by Sway." +msgstr "プロプライエタリの Nvidia ドライバーは Sway ではサポートされていません。" + +msgid "It is likely that you will run into issues, are you okay with that?" +msgstr "問題が発生する可能性が高いですが、よろしいですか?" + +msgid "Selected profiles: " +msgstr "選択したプロファイル: " + +msgid "Select which greeter to install" +msgstr "インストールするグリーターを選択" + +msgid "Select a profile type" +msgstr "プロファイルのタイプを選択" + +#, python-brace-format +msgid "Unable to fetch profile from specified url: {}" +msgstr "指定された URL からプロファイルを取得できません: {}" + +#, python-brace-format +msgid "Profiles must have unique name, but profile definitions with duplicate name found: {}" +msgstr "プロファイルには一意の名前が必要ですが、重複した名前のプロファイル定義が見つかりました: {}" + +msgid "Add a user" +msgstr "ユーザーを追加" + +msgid "Change password" +msgstr "パスワードを変更" + +msgid "Promote/Demote user" +msgstr "ユーザーを昇格/降格" + +msgid "Delete User" +msgstr "ユーザーを削除" + +msgid "User" +msgstr "ユーザー" + +msgid "Enter new password" +msgstr "新しいパスワードを入力" + +msgid "The username you entered is invalid" +msgstr "入力したユーザー名は無効です" + +msgid "Enter a username" +msgstr "ユーザー名を入力" + +msgid "Username" +msgstr "ユーザー名" + +msgid "Enter a password" +msgstr "パスワードを入力" + +#, python-brace-format +msgid "Should \"{}\" be a superuser (sudo)?\n" +msgstr "\"{}\" はスーパーユーザーに昇格しますか(sudo)?\n" + +#, python-brace-format +msgid "About to upload \"{}\" to the publicly accessible {}" +msgstr "\"{}\" を公開アクセス可能な {} にアップロードしようとしています" + +msgid "Do you want to continue?" +msgstr "続行しますか?" + +#, python-brace-format +msgid "Log uploaded successfully. URL: {}" +msgstr "ログのアップロードに成功しました。URL: {}" + +msgid "Failed to upload log." +msgstr "ログのアップロードに失敗しました。" + +msgid "Archinstall requires root privileges to run. See --help for more." +msgstr "Archinstall を実行するには root 権限が必要です。詳細については --help を参照してください。" + +msgid "New version available" +msgstr "新しいバージョンが利用可能" + +msgid "Starting device modifications in " +msgstr "次の場所でデバイスの変更を開始しています " + +msgid "Ok" +msgstr "OK" + +msgid "Input cannot be empty" +msgstr "入力は空にできません" + +msgid "Yes" +msgstr "Yes" + +msgid "No" +msgstr "No" + +msgid " (default)" +msgstr " (デフォルト)" + +#~ msgid "[!] A log file has been created here: {} {}" +#~ msgstr "[!] ここにログファイルが作成されました: {} {}" + +#~ msgid " Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues" +#~ msgstr " この問題(およびファイル)を https://github.com/archlinux/archinstall/issues に送信してください" + +#~ msgid "And one more time for verification: " +#~ msgstr "確認のためにもう1度: " + +#~ msgid "Desired hostname for the installation: " +#~ msgstr "インストール時のホスト名: " + +#~ msgid "Username for required superuser with sudo privileges: " +#~ msgstr "sudo 権限を持つスーパーユーザーのユーザー名: " + +#~ msgid "Any additional users to install (leave blank for no users): " +#~ msgstr "インストールする追加のユーザー(ユーザーがない場合は無記入): " + +#~ msgid "Should this user be a superuser (sudoer)?" +#~ msgstr "このユーザーはスーパーユーザーに昇格しますか(sudoer)?" + +#~ msgid "Select a timezone" +#~ msgstr "タイムゾーンを選択" + +#~ msgid "Would you like to use GRUB as a bootloader instead of systemd-boot?" +#~ msgstr "systemd-boot の代わりに GRUB をブートローダーとして使用しますか?" + +#~ msgid "Choose a bootloader" +#~ msgstr "ブートローダーを選択" + +#~ msgid "Choose an audio server" +#~ msgstr "オーディオサーバーを選択" + +#~ msgid "Only packages such as base, base-devel, linux, linux-firmware, efibootmgr and optional profile packages are installed." +#~ msgstr "base, base-devel, linux, linux-firmware, efibootmgr などのパッケージとオプションのプロファイルパッケージのみがインストールされます。" + +#~ msgid "If you desire a web browser, such as firefox or chromium, you may specify it in the following prompt." +#~ msgstr "firefox や chromium などのウェブブラウザーをインストールする場合は、次のプロンプトで指定できます。" + +#~ msgid "Write additional packages to install (space separated, leave blank to skip): " +#~ msgstr "追加でインストールするパッケージを書く(スペースで区切る。無記入でスキップ): " + +#~ msgid "Use NetworkManager (necessary for configuring internet graphically in GNOME and KDE)" +#~ msgstr "ネットワークマネージャーを使用(GNOME と KDE でインターネットをグラフィカルに設定するのに必要)" + +#~ msgid "Select one network interface to configure" +#~ msgstr "設定するネットワークインターフェイスを 1 つ選択" + +#~ msgid "Select which mode to configure for \"{}\" or skip to use default mode \"{}\"" +#~ msgstr "どのモードを \"{}\" に設定するかを選択。スキップでデフォルトモード \"{}\" を使用" + +#~ msgid "Enter your gateway (router) IP address or leave blank for none: " +#~ msgstr "ゲートウェイ(ルーター)の IP アドレスを入力。無い場合は無記入: " + +#~ msgid "Enter your DNS servers (space separated, blank for none): " +#~ msgstr "DNS サーバーを入力(スペースで区切る。無い場合は無記入): " + +#~ msgid "Select which filesystem your main partition should use" +#~ msgstr "メインパーティションで使用するファイルシステムを選択" + +#~ msgid "Current partition layout" +#~ msgstr "現在のパーティションレイアウト" + +#~ msgid "" +#~ "Select what to do with\n" +#~ "{}" +#~ msgstr "" +#~ "何をするか選択\n" +#~ "{}" + +#~ msgid "Enter a desired filesystem type for the partition" +#~ msgstr "パーティションのファイルシステムを入力" + +#~ msgid "Enter the start location (in parted units: s, GB, %, etc. ; default: {}): " +#~ msgstr "開始場所を入力(単位: s, GB, % など。デフォルト: {}): " + +#~ msgid "Enter the end location (in parted units: s, GB, %, etc. ; ex: {}): " +#~ msgstr "終了場所を入力(単位: s, GB, % など。例: {}): " + +#~ msgid "{} contains queued partitions, this will remove those, are you sure?" +#~ msgstr "{} にはキューに入っているパーティションが含まれます。それらが削除されますがよろしいですか?" + +#~ msgid "" +#~ "{}\n" +#~ "\n" +#~ "Select by index which partitions to delete" +#~ msgstr "" +#~ "{}\n" +#~ "\n" +#~ "削除するパーティションをインデックスで選択" + +#~ msgid "" +#~ "{}\n" +#~ "\n" +#~ "Select by index which partition to mount where" +#~ msgstr "" +#~ "{}\n" +#~ "\n" +#~ "どのパーティションをどこにマウントするかをインデックスで選択" + +#~ msgid " * Partition mount-points are relative to inside the installation, the boot would be /boot as an example." +#~ msgstr "* パーティションのマウントポイントはインストールにおける相対的なものであり、例として boot は /boot になります。" + +#~ msgid "Select where to mount partition (leave blank to remove mountpoint): " +#~ msgstr "パーティションをマウントする場所を選択(無記入でマウントポイントを削除): " + +#~ msgid "" +#~ "{}\n" +#~ "\n" +#~ "Select which partition to mask for formatting" +#~ msgstr "" +#~ "{}\n" +#~ "\n" +#~ "フォーマット対象としてマークするパーティションを選択" + +#~ msgid "" +#~ "{}\n" +#~ "\n" +#~ "Select which partition to mark as encrypted" +#~ msgstr "" +#~ "{}\n" +#~ "\n" +#~ "暗号化対象としてマークするパーティションを選択" + +#~ msgid "" +#~ "{}\n" +#~ "\n" +#~ "Select which partition to mark as bootable" +#~ msgstr "" +#~ "{}\n" +#~ "\n" +#~ "ブータブルとしてマークするパーティションを選択" + +#~ msgid "" +#~ "{}\n" +#~ "\n" +#~ "Select which partition to set a filesystem on" +#~ msgstr "" +#~ "{}\n" +#~ "\n" +#~ "ファイルシステムを設定するパーティションを選択" + +#~ msgid "Enter a desired filesystem type for the partition: " +#~ msgstr "パーティションのファイルシステムを入力: " + +#~ msgid "Wipe all selected drives and use a best-effort default partition layout" +#~ msgstr "選択したすべてのドライブを消去し、ベストエフォートのデフォルトパーティションレイアウトを使用する" + +#~ msgid "Select what to do with each individual drive (followed by partition usage)" +#~ msgstr "個々のドライブをどうするかを選択(次にパーティションの使用方法が続く)" + +#~ msgid "Select what you wish to do with the selected block devices" +#~ msgstr "選択したブロックデバイスで何をするかを選択" + +#~ msgid "This is a list of pre-programmed profiles, they might make it easier to install things like desktop environments" +#~ msgstr "これは事前にプログラムされたプロファイルのリストです。デスクトップ環境などのインストールが簡単になる可能性があります" + +#~ msgid "Select keyboard layout" +#~ msgstr "キーボードレイアウトを選択" + +#~ msgid "Select one of the regions to download packages from" +#~ msgstr "パッケージをダウンロードする地域を 1 つ選択" + +#~ msgid "Select one or more hard drives to use and configure" +#~ msgstr "使用・設定する 1 つ以上のハードドライブを選択" + +#~ msgid "" +#~ "\n" +#~ "\n" +#~ "Select a graphics driver or leave blank to install all open-source drivers" +#~ msgstr "" +#~ "\n" +#~ "\n" +#~ "グラフィックドライバーを選択するか、無記入ですべてのオープンソースドライバーをインストール" + +#~ msgid "All open-source (default)" +#~ msgstr "すべてのオープンソース(デフォルト)" + +#~ msgid "Choose which kernels to use or leave blank for default \"{}\"" +#~ msgstr "使用するカーネルを選択。無記入でデフォルトの \"{}\"" + +#~ msgid "Choose which locale language to use" +#~ msgstr "使用するロケール言語を選択" + +#~ msgid "Choose which locale encoding to use" +#~ msgstr "使用するロケールエンコーディングを選択" + +#~ msgid "Select one of the values shown below: " +#~ msgstr "以下の値のいずれかを選択: " + +#~ msgid "Select one or more of the options below: " +#~ msgstr "以下のオプションを 1 つ以上選択: " + +#~ msgid "Adding partition...." +#~ msgstr "パーティションを追加...." + +#~ msgid "You need to enter a valid fs-type in order to continue. See `man parted` for valid fs-type's." +#~ msgstr "続行するには、有効な fs-type を入力する必要があります。有効な fs-type については、 `man parted` を参照してください。" + +#~ msgid "Error: Listing profiles on URL \"{}\" resulted in:" +#~ msgstr "エラー: URL \"{}\" のプロファイルをリストすると、次の結果が発生:" + +#~ msgid "Error: Could not decode \"{}\" result as JSON:" +#~ msgstr "エラー: \"{}\" の結果を JSON としてデコードできませんでした:" + +#~ msgid "Mirror region" +#~ msgstr "ミラーの地域" + +#~ msgid "Drive(s)" +#~ msgstr "ドライブ" + +#~ msgid "Disk layout" +#~ msgstr "ディスクレイアウト" + +#~ msgid "Superuser account" +#~ msgstr "スーパーユーザーアカウント" + +#~ msgid "Install ({} config(s) missing)" +#~ msgstr "インストール({} 個の設定がありません)" + +#~ msgid "" +#~ "You decided to skip harddrive selection\n" +#~ "and will use whatever drive-setup is mounted at {} (experimental)\n" +#~ "WARNING: Archinstall won't check the suitability of this setup\n" +#~ "Do you wish to continue?" +#~ msgstr "" +#~ "ハードドライブの選択をスキップし、\n" +#~ "{} にマウントしているドライブのセットアップを使用します(実験的)\n" +#~ "警告: Archinstall はこのセットアップの適合性をチェックしません\n" +#~ "続行しますか?" + +#~ msgid "Re-using partition instance: {}" +#~ msgstr "パーティションインスタンスの再利用: {}" + +#~ msgid "Create a new partition" +#~ msgstr "新しいパーティションを作成" + +#~ msgid "Delete a partition" +#~ msgstr "パーティションを削除" + +#~ msgid "Clear/Delete all partitions" +#~ msgstr "すべてのパーティションをクリア/削除" + +#~ msgid "Assign mount-point for a partition" +#~ msgstr "パーティションにマウントポイントを割り当てる" + +#~ msgid "Mark/Unmark a partition to be formatted (wipes data)" +#~ msgstr "フォーマットするパーティションとしてマーク/マーク解除(データを消去)" + +#~ msgid "Mark/Unmark a partition as encrypted" +#~ msgstr "暗号化するパーティションとしてマーク/マーク解除" + +#~ msgid "Mark/Unmark a partition as bootable (automatic for /boot)" +#~ msgstr "ブータブルパーティションとしてマーク/マーク解除(/boot の場合は自動)" + +#~ msgid "Set desired filesystem for a partition" +#~ msgstr "パーティションのファイルシステムを設定" + +#~ msgid "Not configured, unavailable unless setup manually" +#~ msgstr "未設定。手動で設定しない限り使用できません" + +#~ msgid "Set/Modify the below options" +#~ msgstr "以下のオプションを設定/変更" + +#~ msgid "" +#~ "Use ESC to skip\n" +#~ "\n" +#~ msgstr "" +#~ "Esc でスキップ\n" +#~ "\n" + +#~ msgid "Enter a password: " +#~ msgstr "パスワードを入力: " + +#~ msgid "Enter a encryption password for {}" +#~ msgstr "{} の暗号化パスワードを入力" + +#~ msgid "Enter disk encryption password (leave blank for no encryption): " +#~ msgstr "ディスクの暗号化パスワードを入力(暗号化しない場合は無記入): " + +#~ msgid "Create a required super-user with sudo privileges: " +#~ msgstr "sudo 権限を持つスーパーユーザーを作成: " + +#~ msgid "Enter root password (leave blank to disable root): " +#~ msgstr "root パスワードを入力(root を無効にする場合は無記入): " + +#~ msgid "Password for user \"{}\": " +#~ msgstr "ユーザー \"{}\" のパスワード: " + +#~ msgid "Verifying that additional packages exist (this might take a few seconds)" +#~ msgstr "追加のパッケージが存在することを確認(これには数秒かかる場合があります)" + +#~ msgid "Enter a username to create an additional user (leave blank to skip): " +#~ msgstr "ユーザー名を入力して追加ユーザーを作成(無記入でスキップ): " + +#~ msgid "Use ESC to skip\n" +#~ msgstr "Esc でスキップ\n" + +#~ msgid "" +#~ "\n" +#~ " Choose an object from the list, and select one of the available actions for it to execute" +#~ msgstr "" +#~ "\n" +#~ "リストからオブジェクトを選択し、そのオブジェクトで実行できるアクションの 1 つを選択" + +#~ msgid "Add" +#~ msgstr "追加" + +#~ msgid "Copy" +#~ msgstr "コピー" + +#~ msgid "Edit" +#~ msgstr "編集" + +#~ msgid "Delete" +#~ msgstr "削除" + +#~ msgid "Select an action for '{}'" +#~ msgstr "'{}' へのアクションを選択" + +#~ msgid "Copy to new key:" +#~ msgstr "新しいキーにコピー:" + +#~ msgid "Unknown nic type: {}. Possible values are {}" +#~ msgstr "不明な NIC タイプ: {}。可能な値は {}" + +#~ msgid "" +#~ "\n" +#~ "This is your chosen configuration:" +#~ msgstr "" +#~ "\n" +#~ "これが選択した設定です:" + +#~ msgid "Choose which optional additional repositories to enable" +#~ msgstr "オプションで有効にする追加リポジトリを選択" + +#~ msgid "" +#~ "\n" +#~ "Define a new user\n" +#~ msgstr "" +#~ "\n" +#~ "新しいユーザーを定義\n" + +#~ msgid "User Name : " +#~ msgstr "ユーザー名: " + +#~ msgid "Should {} be a superuser (sudoer)?" +#~ msgstr "{} はスーパーユーザーに昇格しますか(sudoer)?" + +#~ msgid "Define users with sudo privilege: " +#~ msgstr "sudo 権限を持つユーザーを定義: " + +#~ msgid "No network configuration" +#~ msgstr "ネットワーク設定なし" + +#~ msgid "Set desired subvolumes on a btrfs partition" +#~ msgstr "Btrfs パーティションに必要なサブボリュームを設定" + +#~ msgid "" +#~ "{}\n" +#~ "\n" +#~ "Select which partition to set subvolumes on" +#~ msgstr "" +#~ "{}\n" +#~ "\n" +#~ "サブボリュームを設定するパーティションを選択" + +#~ msgid "Manage btrfs subvolumes for current partition" +#~ msgstr "現在のパーティションの Btrfs サブボリュームを管理" + +#~ msgid "Save user configuration" +#~ msgstr "ユーザー設定を保存" + +#~ msgid "Save disk layout" +#~ msgstr "ディスクレイアウトを保存" + +#~ msgid "Choose which configuration to save" +#~ msgstr "保存する設定を選択" + +#~ msgid "Enter a directory for the configuration(s) to be saved: " +#~ msgstr "設定を保存するディレクトリを入力: " + +#~ msgid "Not a valid directory: {}" +#~ msgstr "有効なディレクトリではありません: {}" + +#~ msgid "The password you are using seems to be weak," +#~ msgstr "使用しているパスワードは弱いようです、" + +#~ msgid "are you sure you want to use it?" +#~ msgstr "本当に使用してもよろしいですか?" + +#~ msgid "Either root-password or at least 1 superuser must be specified" +#~ msgstr "root パスワードか、1人以上のスーパーユーザーを指定してください" + +#~ msgid "Manage superuser accounts: " +#~ msgstr "スーパーユーザーアカウントを管理: " + +#~ msgid "Manage ordinary user accounts: " +#~ msgstr "一般ユーザーのアカウントを管理: " + +#~ msgid " Subvolume :{:16}" +#~ msgstr " サブボリューム :{:16}" + +#~ msgid " mounted at {:16}" +#~ msgstr " マウント場所 {:16}" + +#~ msgid " with option {}" +#~ msgstr " 次のオプションで {}" + +#~ msgid "" +#~ "\n" +#~ " Fill the desired values for a new subvolume \n" +#~ msgstr "" +#~ "\n" +#~ " 新しいサブボリュームに必要な値を入力 \n" + +#~ msgid "Subvolume name " +#~ msgstr "サブボリューム名 " + +#~ msgid "Subvolume mountpoint" +#~ msgstr "サブボリュームのマウントポイント" + +#~ msgid "Subvolume options" +#~ msgstr "サブボリュームのオプション" + +#~ msgid "Save" +#~ msgstr "保存" + +#~ msgid "Subvolume name :" +#~ msgstr "サブボリューム名:" + +#~ msgid "Select a mount point :" +#~ msgstr "マウントポイントを選択:" + +#~ msgid "Select the desired subvolume options " +#~ msgstr "サブボリュームのオプションを選択" + +#~ msgid "Define users with sudo privilege, by username: " +#~ msgstr "sudo 権限を持つユーザーを、ユーザー名で定義: " + +#~ msgid "Would you like to use BTRFS compression?" +#~ msgstr "Btrfs の圧縮を使用しますか?" + +#~ msgid "Minimum capacity for /home partition: {}GB\n" +#~ msgstr "/home パーティションの最小容量: {}GB\n" + +#~ msgid "Minimum capacity for Arch Linux partition: {}GB" +#~ msgstr "Arch Linux パーティションの最小容量: {}GB" + +#~ msgid "Continue" +#~ msgstr "続行" + +#~ msgid "yes" +#~ msgstr "yes" + +#~ msgid "no" +#~ msgstr "no" + +#~ msgid "set: {}" +#~ msgstr "セット: {}" + +#~ msgid "Manual configuration setting must be a list" +#~ msgstr "手動設定はリストである必要があります" + +#~ msgid "No iface specified for manual configuration" +#~ msgstr "手動設定に iface が指定されていません" + +#~ msgid "Manual nic configuration with no auto DHCP requires an IP address" +#~ msgstr "自動 DHCP を使用しない手動 NIC 設定には、IP アドレスが必要です" + +#~ msgid "Select interface to add" +#~ msgstr "追加するインターフェースを選択" + +#~ msgid "Mark/Unmark a partition as compressed (btrfs only)" +#~ msgstr "圧縮するパーティションとしてマーク/マーク解除(Btrfs のみ)" + +#~ msgid "The password you are using seems to be weak, are you sure you want to use it?" +#~ msgstr "使用しているパスワードは弱いようですが、本当に使用してもよろしいですか?" + +#~ msgid "Provides a selection of desktop environments and tiling window managers, e.g. gnome, kde, sway" +#~ msgstr "デスクトップ環境とタイルウィンドウマネージャーの選択を提供します。e.g. gnome, kde, sway" + +#~ msgid "Select your desired desktop environment" +#~ msgstr "デスクトップ環境を選択" + +#~ msgid "A very basic installation that allows you to customize Arch Linux as you see fit." +#~ msgstr "Arch Linux を必要に応じてカスタマイズできる非常に基本的なインストールです。" + +#~ msgid "Provides a selection of various server packages to install and enable, e.g. httpd, nginx, mariadb" +#~ msgstr "さまざまなサーバー パッケージの選択肢を提供します。e.g. httpd, nginx, mariadb" + +#~ msgid "Choose which servers to install, if none then a minimal installation will be done" +#~ msgstr "インストールするサーバーを選択。存在しない場合は最小限のインストールが実行されます" + +#~ msgid "Installs a minimal system as well as xorg and graphics drivers." +#~ msgstr "最小限のシステムと xorg およびグラフィックドライバーをインストール。" + +#~ msgid "Press Enter to continue." +#~ msgstr "Enter キーで続行します。" + +#~ msgid "Would you like to chroot into the newly created installation and perform post-installation configuration?" +#~ msgstr "新しく作成したインストールに chroot して、インストール後の設定を実行しますか?" + +#~ msgid "Select one or more hard drives to use and configure\n" +#~ msgstr "使用・設定する 1 つ以上のハードドライブを選択\n" + +#~ msgid "Any modifications to the existing setting will reset the disk layout!" +#~ msgstr "既存の設定を変更すると、ディスクレイアウトがリセットされます!" + +#~ msgid "If you reset the harddrive selection this will also reset the current disk layout. Are you sure?" +#~ msgstr "ハードドライブの選択をリセットすると、現在のディスクレイアウトもリセットされます。よろしいですか?" + +#~ msgid "Save and exit" +#~ msgstr "保存して終了" + +#~ msgid "" +#~ "{}\n" +#~ "contains queued partitions, this will remove those, are you sure?" +#~ msgstr "" +#~ "{}\n" +#~ "キューに入れられたパーティションが含まれています。削除しますがよろしいですか?" + +#~ msgid "No audio server" +#~ msgstr "オーディオサーバーなし" + +#~ msgid "(default)" +#~ msgstr "(デフォルト)" + +#~ msgid "Use ESC to skip" +#~ msgstr "Esc でスキップ" + +#~ msgid "" +#~ "Use CTRL+C to reset current selection\n" +#~ "\n" +#~ msgstr "" +#~ "Ctrl+C で現在の選択をリセット\n" +#~ "\n" + +#~ msgid "Copy to: " +#~ msgstr "コピー先: " + +#~ msgid "Edit: " +#~ msgstr "編集: " + +#~ msgid "Key: " +#~ msgstr "キー: " + +#~ msgid "Edit {}: " +#~ msgstr "編集 {}: " + +#~ msgid "Add: " +#~ msgstr "追加: " + +#~ msgid "Value: " +#~ msgstr "値: " + +#~ msgid "You can skip selecting a drive and partitioning and use whatever drive-setup is mounted at /mnt (experimental)" +#~ msgstr "ドライブ選択とパーティション作成をスキップして、/mnt にマウントしているドライブのセットアップを使用できます(実験的)" + +#~ msgid "Select one of the disks or skip and use /mnt as default" +#~ msgstr "いずれかのディスクを選択するか、スキップして /mnt をデフォルトとして使用" + +#~ msgid "Select which partitions to mark for formatting:" +#~ msgstr "フォーマットするパーティションを選択:" + +#~ msgid "Use HSM to unlock encrypted drive" +#~ msgstr "HSM を使用して暗号化されたドライブのロックを解除" + +#~ msgid "Device" +#~ msgstr "デバイス" + +#~ msgid "Size" +#~ msgstr "サイズ" + +#~ msgid "Free space" +#~ msgstr "空き容量" + +#~ msgid "Bus-type" +#~ msgstr "Bus タイプ" + +#~ msgid "Enter username (leave blank to skip): " +#~ msgstr "ユーザー名を入力(無記入でスキップ): " + +#~ msgid "The username you entered is invalid. Try again" +#~ msgstr "入力したユーザー名は無効です。もう1度やり直してください" + +#~ msgid "Should \"{}\" be a superuser (sudo)?" +#~ msgstr "\"{}\" はスーパーユーザーに昇格しますか(sudo)?" + +#~ msgid "Select which partitions to encrypt" +#~ msgstr "暗号化するパーティションを選択" + +#~ msgid "Configured {} interfaces" +#~ msgstr "設定した {} インターフェース" + +#~ msgid "This option enables the number of parallel downloads that can occur during installation" +#~ msgstr "このオプションは、インストール中に実行できる並列ダウンロードの数を有効にします" + +#~ msgid "" +#~ "Enter the number of parallel downloads to be enabled.\n" +#~ " (Enter a value between 1 to {})\n" +#~ "Note:" +#~ msgstr "" +#~ "有効にする並列ダウンロードの数を入力してください。\n" +#~ " (1 から {} の値を入力)\n" +#~ "注意:" + +#~ msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {} downloads at a time )" +#~ msgstr " - 最大値 : {} ({} 個の並列ダウンロードを許可して、1度に {} 個のダウンロードを許可する)" + +#~ msgid " - Minimum value : 1 ( Allows 1 parallel download, allows 2 downloads at a time )" +#~ msgstr " - 最小値 : 1 (1 個の並列ダウンロードを許可して、1度に 2 個のダウンロードを許可する)" + +#~ msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )" +#~ msgstr " - 無効/デフォルト : 0 (並列ダウンロードを無効にして、1度に 1 個のみダウンロードを許可する)" + +#, python-brace-format +#~ msgid "Invalid input! Try again with a valid input [1 to {max_downloads}, or 0 to disable]" +#~ msgstr "無効な入力です!有効な入力を使用して再試行してください [1 - {max_downloads}、0 で無効]" + +#~ msgid "ESC to skip" +#~ msgstr "Esc でスキップ" + +#~ msgid "CTRL+C to reset" +#~ msgstr "Ctrl+C でリセット" + +#~ msgid "TAB to select" +#~ msgstr "Tab で選択" + +#~ msgid "[Default value: 0] > " +#~ msgstr "[デフォルト値: 0] > " + +#~ msgid "To be able to use this translation, please install a font manually that supports the language." +#~ msgstr "この翻訳を使用できるようにするには、その言語をサポートするフォントを手動でインストールしてください。" + +#~ msgid "The font should be stored as {}" +#~ msgstr "フォントは {} として保存する必要があります" + +#~ msgid "Select an execution mode" +#~ msgstr "実行モードを選択" + +#~ msgid "Select one or more devices to use and configure" +#~ msgstr "使用・設定する 1 つ以上のデバイスを選択" + +#~ msgid "If you reset the device selection this will also reset the current disk layout. Are you sure?" +#~ msgstr "デバイスの選択をリセットすると、現在のディスクレイアウトもリセットされます。よろしいですか?" + +#~ msgid "Existing Partitions" +#~ msgstr "既存のパーティション" + +#~ msgid "Select a partitioning option" +#~ msgstr "パーティション作成のオプションを選択" + +#~ msgid "Enter the root directory of the mounted devices: " +#~ msgstr "マウントしているデバイスのルートディレクトリを入力: " + +#~ msgid "This is a list of pre-programmed profiles_bck, they might make it easier to install things like desktop environments" +#~ msgstr "これは事前にプログラムされたプロファイルのリストです。デスクトップ環境などのインストールが簡単になる可能性があります" + +#~ msgid "Current profile selection" +#~ msgstr "現在のプロファイルの選択" + +#~ msgid "If mountpoint /boot is set, then the partition will also be marked as bootable." +#~ msgstr "マウントポイントに /boot が設定された場合、パーティションはブータブルとしてマークされます。" + +#~ msgid "Mountpoint: " +#~ msgstr "マウントポイント: " + +#~ msgid "Current free sectors on device {}:" +#~ msgstr "デバイス {} の現在の空きセクター:" + +#~ msgid "Total sectors: {}" +#~ msgstr "総セクター数: {}" + +#~ msgid "Enter the start sector (default: {}): " +#~ msgstr "開始セクターを入力(デフォルト: {}): " + +#~ msgid "Enter the end sector of the partition (percentage or block number, default: {}): " +#~ msgstr "パーティションの終了セクターを入力(パーセンテージかブロック番号。デフォルト: {}): " + +#~ msgid "Default: 10000ms, Recommended range: 1000-60000" +#~ msgstr "デフォルト: 10000ms, 推奨範囲: 1000-60000" + +#~ msgid "Iteration time cannot be empty" +#~ msgstr "イテレーション時間は空にできません" + +#~ msgid "No HSM devices available" +#~ msgstr "利用可能な HSM デバイスがありません" + +#~ msgid "Select disk encryption option" +#~ msgstr "ディスクの暗号化オプションを選択" + +#~ msgid "Partition encryption" +#~ msgstr "パーティションの暗号化" + +#, python-brace-format +#~ msgid " ! Formatting {} in " +#~ msgstr " ! {} のフォーマットまで " + +#~ msgid "← Back" +#~ msgstr "← 戻る" + +#~ msgid "All settings will be reset, are you sure?" +#~ msgstr "すべての設定がリセットされます。よろしいですか?" + +#~ msgid "Please chose which greeter to install for the chosen profiles: {}" +#~ msgstr "選択したプロファイルにインストールするグリーターを選択: {}" + +#~ msgid "The proprietary Nvidia driver is not supported by Sway. It is likely that you will run into issues, are you okay with that?" +#~ msgstr "プロプライエタリの Nvidia ドライバーは Sway ではサポートされていません。問題が発生する可能性がありますが、よろしいですか?" + +#~ msgid "Add profile" +#~ msgstr "プロファイルを追加" + +#~ msgid "Edit profile" +#~ msgstr "プロファイルを編集" + +#~ msgid "Delete profile" +#~ msgstr "プロファイルを削除" + +#~ msgid "Profile name: " +#~ msgstr "プロファイル名: " + +#~ msgid "The profile name you entered is already in use. Try again" +#~ msgstr "入力したプロファイル名はすでに使用されています。もう1度やり直してください" + +#~ msgid "Packages to be install with this profile (space separated, leave blank to skip): " +#~ msgstr "このプロファイルでインストールするパッケージ(スペースで区切る。無記入でスキップ): " + +#~ msgid "Services to be enabled with this profile (space separated, leave blank to skip): " +#~ msgstr "このプロファイルで有効にするサービス(スペースで区切る。未記入でスキップ): " + +#~ msgid "Should this profile be enabled for installation?" +#~ msgstr "このプロファイルのインストールを有効にしますか?" + +#~ msgid "Create your own" +#~ msgstr "自分で作成" + +#~ msgid "" +#~ "\n" +#~ "Select a graphics driver or leave blank to install all open-source drivers" +#~ msgstr "" +#~ "\n" +#~ "グラフィックドライバーを選択。無記入ですべてのオープンソースドライバーをインストール" + +#~ msgid "Sway needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" +#~ msgstr "Sway はお使いの Seat(キーボード、マウスなどのハードウェアデバイス群)にアクセスする必要があります" + +#~ msgid "" +#~ "\n" +#~ "\n" +#~ "Choose an option to give Sway access to your hardware" +#~ msgstr "" +#~ "\n" +#~ "\n" +#~ "Sway にハードウェアへのアクセスを許可するオプションを選択" + +#~ msgid "Please chose which greeter to install" +#~ msgstr "インストールするグリーターを選択" + +#~ msgid "This is a list of pre-programmed default_profiles" +#~ msgstr "これは、事前にプログラムされた default_profile のリストです" + +#~ msgid "Finding possible directories to save configuration files ..." +#~ msgstr "設定ファイルを保存できるディレクトリを検索しています..." + +#~ msgid "Select directory (or directories) for saving configuration files" +#~ msgstr "設定ファイルを保存するディレクトリを選択" + +#~ msgid "Add a custom mirror" +#~ msgstr "カスタムミラーを追加" + +#~ msgid "Change custom mirror" +#~ msgstr "カスタムミラーを変更" + +#~ msgid "Delete custom mirror" +#~ msgstr "カスタムミラーを削除" + +#~ msgid "Enter name (leave blank to skip): " +#~ msgstr "名前を入力(無記入でスキップ): " + +#~ msgid "Enter url (leave blank to skip): " +#~ msgstr "URL を入力(未記入でスキップ): " + +#~ msgid "Select signature check option" +#~ msgstr "署名チェックのオプションを選択" + +#~ msgid "Custom mirrors" +#~ msgstr "カスタムミラー" + +#~ msgid "Defined" +#~ msgstr "定義済み" + +#~ msgid "" +#~ "Enter a directory for the configuration(s) to be saved (tab completion enabled)\n" +#~ "Save directory: " +#~ msgstr "" +#~ "設定を保存するディレクトリを入力(Tab で補完可能)\n" +#~ "保存ディレクトリ: " + +#~ msgid "" +#~ "Do you want to save {} configuration file(s) in the following location?\n" +#~ "\n" +#~ "{}" +#~ msgstr "" +#~ "{} 設定ファイルを次の場所に保存しますか?\n" +#~ "\n" +#~ "{}" + +#~ msgid "Saving {} configuration files to {}" +#~ msgstr "{} 設定ファイルを {} に保存" + +#~ msgid "Mirrors" +#~ msgstr "ミラー" + +#~ msgid "Mirror regions" +#~ msgstr "ミラーの地域" + +#~ msgid " - Maximum value : {} ( Allows {} parallel downloads, allows {max_downloads+1} downloads at a time )" +#~ msgstr " - 最大値 : {}({} 個の並列ダウンロードを許可し、1度に {max_downloads+1} 個のダウンロードを許可する)" + +#~ msgid "Invalid input! Try again with a valid input [1 to {}, or 0 to disable]" +#~ msgstr "無効な入力です!有効な入力でやり直してください [1 から {}、または 0 で無効]" + +#~ msgid "Use NetworkManager (necessary to configure internet graphically in GNOME and KDE)" +#~ msgstr "ネットワークマネージャーを使用(GNOME と KDE でインターネットをグラフィカルに設定するのに必要)" + +#~ msgid "Total: {} / {}" +#~ msgstr "全体: {} / {}" + +#~ msgid "All entered values can be suffixed with a unit: B, KB, KiB, MB, MiB..." +#~ msgstr "入力したすべての値に、B、KB、KiB、MB、MiB などの単位を付けることができます。" + +#~ msgid "Enter start (default: sector {}): " +#~ msgstr "開始値を入力(デフォルト: セクター {}): " + +#~ msgid "Enter end (default: {}): " +#~ msgstr "終了値を入力(デフォルト: {}): " + +#~ msgid "Unable to determine fido2 devices. Is libfido2 installed?" +#~ msgstr "fido2 デバイスを特定できません。lifido2 はインストールされていますか?" + +#~ msgid "Path" +#~ msgstr "パス" + +#~ msgid "Manufacturer" +#~ msgstr "メーカー" + +#~ msgid "Product" +#~ msgstr "製品" + +#~ msgid "Disks" +#~ msgstr "ディスク" + +#~ msgid "Packages" +#~ msgstr "パッケージ" + +#~ msgid "Locale" +#~ msgstr "ロケール" + +#~ msgid "This option enables the number of parallel downloads that can occur during package downloads" +#~ msgstr "このオプションは、パッケージのダウンロード中に実行できる並列ダウンロードの数を設定します" + +#~ msgid "" +#~ "Enter the number of parallel downloads to be enabled.\n" +#~ "\n" +#~ "Note:\n" +#~ msgstr "" +#~ "並列ダウンロードの数を入力してください。\n" +#~ "\n" +#~ "注意:\n" + +#, python-brace-format +#~ msgid " - Maximum recommended value : {} ( Allows {} parallel downloads at a time )" +#~ msgstr " - 最大推奨値 : {} (1度に {} 個の並列ダウンロードを許可する)" + +#~ msgid " - Disable/Default : 0 ( Disables parallel downloading, allows only 1 download at a time )\n" +#~ msgstr " - 無効/デフォルト : 0 (並列ダウンロードを無効にして、1度に 1 個のダウンロードのみ許可する)\n" + +#~ msgid "Invalid input! Try again with a valid input [or 0 to disable]" +#~ msgstr "無効な入力です!有効な入力でやり直してください(無効にする場合は 0)" + +#~ msgid "Hyprland needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" +#~ msgstr "Hyprland はお使いの Seat(キーボード、マウスなどのハードウェアデバイス群)にアクセスする必要があります" + +#~ msgid "" +#~ "\n" +#~ "\n" +#~ "Choose an option to give Hyprland access to your hardware" +#~ msgstr "" +#~ "\n" +#~ "\n" +#~ "Hyprland にハードウェアへのアクセスを許可するオプションを選択" + +#~ msgid "Time syncronization not completing, while you wait - check the docs for workarounds: https://archinstall.readthedocs.io/" +#~ msgstr "待機中に時刻同期が完了しません - 回避策についてはドキュメントを確認してください: https://archinstall.readthedocs.io/" + +#~ msgid "Provides a selection of desktop environments and tiling window managers, e.g. GNOME, KDE Plasma, Sway" +#~ msgstr "デスクトップ環境とタイルウィンドウマネージャーの選択を提供します。例: GNOME, KDE Plasma, Sway" + +#~ msgid "Use NetworkManager (necessary to configure internet graphically in GNOME and KDE Plasma)" +#~ msgstr "ネットワークマネージャーを使用(GNOME と KDE Plasma でインターネットをグラフィカルに設定するのに必要)" + +#~ msgid "Select a LVM option" +#~ msgstr "LVM のオプションを選択" + +#~ msgid "Logical Volume Management (LVM)" +#~ msgstr "論理ボリューム管理(LVM)" + +#~ msgid "Select which LVM volumes to encrypt" +#~ msgstr "暗号化する LVM ボリュームを選択" + +#~ msgid "Archinstall help" +#~ msgstr "Archinstall ヘルプ" + +#~ msgid "Press Ctrl+h for help" +#~ msgstr "Ctrl+H でヘルプを表示" + +#~ msgid "Choose an option to give Sway access to your hardware" +#~ msgstr "Sway にハードウェアへのアクセスを許可するオプションを選択" + +#~ msgid "Seat access" +#~ msgstr "Seat アクセス" + +#~ msgid "Filesystem" +#~ msgstr "ファイルシステム" + +#~ msgid "Start (default: sector {}): " +#~ msgstr "開始値(デフォルト: セクター {}): " + +#~ msgid "End (default: {}): " +#~ msgstr "終了値(デフォルト: {}): " + +#~ msgid "Disk configuration type" +#~ msgstr "ディスク設定のタイプ" + +#~ msgid "Root mount directory" +#~ msgstr "ルートマウントディレクトリ" + +#~ msgid "Select language" +#~ msgstr "言語を選択" + +#~ msgid "Write additional packages to install (space separated, leave blank to skip)" +#~ msgstr "追加でインストールするパッケージを書く(スペースで区切る。無記入でスキップ)" + +#~ msgid "Invalid download number" +#~ msgstr "ダウンロード数が無効です" + +#~ msgid "Number downloads" +#~ msgstr "ダウンロード数" + +#~ msgid "Interfaces" +#~ msgstr "インターフェイス" + +#~ msgid "Modes" +#~ msgstr "モード" + +#~ msgid "IP address" +#~ msgstr "IPアドレス" + +#~ msgid "Gateway address" +#~ msgstr "ゲートウェイアドレス" + +#~ msgid "DNS servers" +#~ msgstr "DNSサーバー" + +#~ msgid "Info" +#~ msgstr "情報" + +#~ msgid "Main profile" +#~ msgstr "メインプロファイル" + +#~ msgid "The confirmation password did not match, please try again" +#~ msgstr "確認のパスワードが一致しませんでした。もう一度試してください" + +#~ msgid "Directory" +#~ msgstr "ディレクトリ" + +#~ msgid "Enter a directory for the configuration(s) to be saved (tab completion enabled)" +#~ msgstr "設定を保存するディレクトリを入力(Tab で補完可能)" + +#~ msgid "Mirror name" +#~ msgstr "ミラーの名前" + +#~ msgid "Select execution mode" +#~ msgstr "実行モードを選択" + +#~ msgid "Press ? for help" +#~ msgstr "? を押すとヘルプを表示" + +#~ msgid "Choose an option to give Hyprland access to your hardware" +#~ msgstr "Hyprland にハードウェアへのアクセスを許可するオプションを選択" + +#, python-brace-format +#~ msgid "Size (default: {}): " +#~ msgstr "サイズ (デフォルト: {}): " + +#~ msgid "Some packages could not be found in the repository" +#~ msgstr "リポジトリ内にいくつかのパッケージが見つかりませんでした" + +#~ msgid "Repository name" +#~ msgstr "リポジトリ名" + +#~ msgid "Server url" +#~ msgstr "サーバー URL" + +#~ msgid "Only ASCII characters are supported" +#~ msgstr "ASCII 文字のみサポートされます" + +#~ msgid "Show help" +#~ msgstr "ヘルプを表示" + +#~ msgid "Exit help" +#~ msgstr "ヘルプを終了" + +#~ msgid "Preview scroll up" +#~ msgstr "プレビューを上にスクロール" + +#~ msgid "Preview scroll down" +#~ msgstr "プレビューを下にスクロール" + +#~ msgid "Move up" +#~ msgstr "上に移動" + +#~ msgid "Move down" +#~ msgstr "下に移動" + +#~ msgid "Move right" +#~ msgstr "右に移動" + +#~ msgid "Move left" +#~ msgstr "左に移動" + +#~ msgid "Jump to entry" +#~ msgstr "エントリーへジャンプ" + +#~ msgid "Skip selection (if available)" +#~ msgstr "選択をスキップ(利用可能な場合)" + +#~ msgid "Reset selection (if available)" +#~ msgstr "選択をリセット(利用可能な場合)" + +#~ msgid "Select on single select" +#~ msgstr "単一で選択" + +#~ msgid "Select on multi select" +#~ msgstr "複数で選択" + +#~ msgid "Reset" +#~ msgstr "リセット" + +#~ msgid "Skip selection menu" +#~ msgstr "選択メニューをスキップ" + +#~ msgid "Start search mode" +#~ msgstr "検索モードを開始" + +#~ msgid "Exit search mode" +#~ msgstr "検索モードを終了" + +#~ msgid "General" +#~ msgstr "一般" + +#~ msgid "Navigation" +#~ msgstr "ナビゲーション" + +#~ msgid "Selection" +#~ msgstr "選択" + +#~ msgid "Search" +#~ msgstr "検索" + +#~ msgid "Down" +#~ msgstr "下へ" + +#~ msgid "Up" +#~ msgstr "上へ" + +#~ msgid "Confirm" +#~ msgstr "確認" + +#~ msgid "Focus right" +#~ msgstr "右にフォーカス" + +#~ msgid "Focus left" +#~ msgstr "左にフォーカス" + +#~ msgid "Toggle" +#~ msgstr "切り替え" + +#~ msgid "Show/Hide help" +#~ msgstr "ヘルプを表示/隠す" + +#~ msgid "Quit" +#~ msgstr "終了" + +#~ msgid "First" +#~ msgstr "最初" + +#~ msgid "Last" +#~ msgstr "最後" + +#~ msgid "Select" +#~ msgstr "選択" + +#~ msgid "Page Up" +#~ msgstr "上のページへ" + +#~ msgid "Page Down" +#~ msgstr "下のページへ" + +#~ msgid "Page up" +#~ msgstr "上のページへ" + +#~ msgid "Page down" +#~ msgstr "下のページへ" + +#~ msgid "Page Left" +#~ msgstr "左のページへ" + +#~ msgid "Page Right" +#~ msgstr "右のページへ" + +#~ msgid "Cursor up" +#~ msgstr "カーソルを上へ" + +#~ msgid "Cursor down" +#~ msgstr "カースルを下へ" + +#~ msgid "Cursor right" +#~ msgstr "カーソルを右へ" + +#~ msgid "Cursor left" +#~ msgstr "カーソルを左へ" + +#~ msgid "Top" +#~ msgstr "一番上へ" + +#~ msgid "Bottom" +#~ msgstr "一番下へ" + +#~ msgid "Home" +#~ msgstr "ホーム" + +#~ msgid "End" +#~ msgstr "最後へ" + +#~ msgid "Toggle option" +#~ msgstr "オプションを切り替え" + +#~ msgid "Scroll Up" +#~ msgstr "上にスクロール" + +#~ msgid "Scroll Down" +#~ msgstr "下にスクロール" + +#~ msgid "Scroll Left" +#~ msgstr "左にスクロール" + +#~ msgid "Scroll Right" +#~ msgstr "右にスクロール" + +#~ msgid "Scroll Home" +#~ msgstr "ホームにスクロール" + +#~ msgid "Scroll End" +#~ msgstr "一番下にスクロール" + +#~ msgid "Focus Next" +#~ msgstr "次にフォーカス" + +#~ msgid "Focus Previous" +#~ msgstr "前にフォーカス" + +#~ msgid "Copy selected text" +#~ msgstr "選択したテキストをコピー" + +#~ msgid "labwc needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" +#~ msgstr "labwc はお使いの Seat(キーボード、マウスなどのハードウェアデバイス群)にアクセスする必要があります" + +#~ msgid "Choose an option to give labwc access to your hardware" +#~ msgstr "labwc にハードウェアへのアクセスを許可するオプションを選択" + +#~ msgid "niri needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)" +#~ msgstr "niri はお使いの Seat(キーボード、マウスなどのハードウェアデバイス群)にアクセスする必要があります" + +#~ msgid "Choose an option to give niri access to your hardware" +#~ msgstr "niri にハードウェアへのアクセスを許可するオプションを選択" + +#~ msgid "Installation completed" +#~ msgstr "インストール完了" + +#~ msgid "Credentials file decryption password" +#~ msgstr "認証情報ファイルの復号化パスワード" + +#~ msgid "Snapshot type" +#~ msgstr "スナップショットのタイプ" + +#~ msgid "U2F Login Method" +#~ msgstr "U2F ログインメソッド" + +#~ msgid "Will install to /EFI/BOOT/ (removable location)" +#~ msgstr "/EFI/BOOT/ (リムーバブルな場所) にインストールする" + +#~ msgid "Will install to standard location with NVRAM entry" +#~ msgstr "NVRAM エントリーのある標準の場所にインストールする" + +#~ msgid "Firmware that does not properly support NVRAM boot entries." +#~ msgstr "NVRAM ブートエントリーを適切にサポートしていないファームウェア。" + +#~ msgid "Enter the number of parallel downloads to be enabled" +#~ msgstr "有効にする並列ダウンロード数を入力" + +#, python-brace-format +#~ msgid "Setting up U2F login: {u2f_config.u2f_login_method.value}" +#~ msgstr "U2F ログインの設定: {u2f_config.u2f_login_method.value}" + +#, python-brace-format +#~ msgid "Default: {DEFAULT_ITER_TIME}ms, Recommended range: 1000-60000" +#~ msgstr "デフォルト: {DEFAULT_ITER_TIME}ms, 推奨範囲: 1000-60000" diff --git a/archinstall/locales/locales_generator.sh b/archinstall/locales/locales_generator.sh index 7ce2ea19..18977dfc 100755 --- a/archinstall/locales/locales_generator.sh +++ b/archinstall/locales/locales_generator.sh @@ -1,48 +1,109 @@ #!/usr/bin/env bash set -euo pipefail -cd $(dirname "$0")/.. +cd "$(dirname "$0")/.." -function update_lang() { - file=${1} +usage() { + echo "Usage: ${0} " + echo "" + echo "Commands:" + echo " all Regenerate base.pot and update all languages" + echo " Regenerate base.pot and update a single language" + echo " check Run translation validation checks" + echo " -h, --help Show this help" +} +generate_pot() { + find . -type f -iname '*.py' | sort \ + | xargs xgettext --no-location --omit-header --keyword='tr' \ + -d base -o locales/base.pot +} + +update_lang() { + local file=${1} echo "Updating: ${file}" + local path path=$(dirname "${file}") msgmerge --quiet --no-location --width 512 --backup none --update "${file}" locales/base.pot msgfmt -o "${path}/base.mo" "${file}" } - -function generate_all() { +cmd_generate_all() { + generate_pot for file in $(find locales/ -name "base.po"); do update_lang "${file}" done } -function generate_single_lang() { - lang_file="locales/${1}/LC_MESSAGES/base.po" - +cmd_generate_single() { + local lang_file="locales/${1}/LC_MESSAGES/base.po" if [ ! -f "${lang_file}" ]; then echo "Language files not found: ${lang_file}" exit 1 fi - + generate_pot update_lang "${lang_file}" } +cmd_check_po_syntax() { + echo "Checking .po syntax..." + local failed=0 + while IFS= read -r po; do + if ! msgfmt --check --output-file=/dev/null "$po" 2>&1; then + echo "FAIL: $po" + failed=1 + fi + done < <(find locales/ -name '*.po') + if [ "$failed" -eq 1 ]; then + echo "ERROR: some .po files have syntax errors" >&2 + return 1 + fi + echo "All .po files passed syntax check." +} + +cmd_check_no_tr_fstring() { + echo "Checking for tr(f-string) anti-pattern..." + if grep -rnE "tr\(\s*f['\"]" . --include='*.py'; then + echo "ERROR: use tr('...{}').format(...) instead of tr(f'...')" >&2 + return 1 + fi + echo "No tr(f-string) anti-pattern found." +} + +cmd_check_pot_freshness() { + # msgcmp (not diff) because base.pot carries legacy stale entries from + # --join-existing; diff would always fail until a full cleanup is done. + echo "Checking base.pot for missing strings..." + find . -type f -iname '*.py' | sort \ + | xargs xgettext --no-location --omit-header --keyword='tr' \ + -d base -o /tmp/generated.pot + if ! msgcmp --use-untranslated locales/base.pot /tmp/generated.pot; then + echo "ERROR: base.pot is missing strings - run: locales_generator.sh all" >&2 + return 1 + fi + echo "base.pot contains all translatable strings." +} + +cmd_check() { + local failed=0 + cmd_check_po_syntax || failed=1 + cmd_check_no_tr_fstring || failed=1 + cmd_check_pot_freshness || failed=1 + if [ "$failed" -eq 1 ]; then + echo "Some translation checks failed." >&2 + exit 1 + fi + echo "All translation checks passed." +} if [ $# -eq 0 ]; then - echo "Usage: ${0} " - echo "Special case 'all' for builds all languages." + usage exit 1 fi -lang=${1} - -# Update the base file containing all translatable strings -find . -type f -iname "*.py" | xargs xgettext --join-existing --no-location --omit-header --keyword='tr' -d base -o locales/base.pot - -case "${lang}" in - "all") generate_all;; - *) generate_single_lang "${lang}" +case "${1}" in + check) cmd_check ;; + all) cmd_generate_all ;; + -h|--help) usage ;; + *) cmd_generate_single "${1}" ;; esac diff --git a/archinstall/main.py b/archinstall/main.py index 9b91681b..e38b3d48 100644 --- a/archinstall/main.py +++ b/archinstall/main.py @@ -8,13 +8,13 @@ import time import traceback from pathlib import Path -from archinstall.lib.args import ArchConfigHandler +from archinstall.lib.args import ArchConfigHandler, SubCommand from archinstall.lib.disk.utils import disk_layouts from archinstall.lib.hardware import SysInfo +from archinstall.lib.log import debug, error, info, logger, share_install_log, warn from archinstall.lib.menu.helpers import Confirmation from archinstall.lib.network.wifi_handler import WifiHandler from archinstall.lib.networking import ping -from archinstall.lib.output import debug, error, info, share_install_log, warn from archinstall.lib.packages.util import check_version_upgrade from archinstall.lib.pacman.pacman import Pacman from archinstall.lib.translationhandler import tr, translation_handler @@ -75,17 +75,36 @@ def _list_scripts() -> str: return '\n'.join(lines) -def _tui_confirm(header: str) -> bool: - async def _ask() -> bool: +def _share_log_command() -> None: + paste_url: str = 'https://paste.rs' + log_path = logger.path + max_size = 10 * 1024 * 1024 # max supported size by paste.rs + content = logger.get_content(max_bytes=max_size).decode() + + header = tr('About to upload "{}" to the publicly accessible {}').format(log_path, paste_url) + '\n\n' + header += tr('Do you want to continue?') + + group = MenuItemGroup.yes_no() + group.set_preview_for_all(lambda _: content) + + async def _confirm() -> bool: result = await Confirmation( - group=MenuItemGroup.yes_no(), header=header, allow_skip=False, - preset=False, + group=group, + preview_header='Log content', + preview_location='bottom', ).show() return result.get_value() - return tui.run(_ask) + result = tui.run(_confirm) + + if result is True: + res = share_install_log(paste_url=paste_url, max_bytes=max_size) + if res is not None: + info(tr('Log uploaded successfully. URL: {}').format(res)) + else: + error(tr('Failed to upload log.')) def run() -> int: @@ -94,15 +113,19 @@ def run() -> int: OR straight as a module: python -m archinstall In any case we will be attempting to load the provided script to be run from the scripts/ folder """ - if 'share-log' in sys.argv: - return share_install_log(confirm=_tui_confirm) - arch_config_handler = ArchConfigHandler() if '--help' in sys.argv or '-h' in sys.argv: arch_config_handler.print_help() return 0 + match arch_config_handler.args.command: + case SubCommand.SHARE_LOG: + _share_log_command() + exit(0) + case None: + pass + script = arch_config_handler.get_script() if script == 'list': diff --git a/archinstall/scripts/guided.py b/archinstall/scripts/guided.py index 8f0f6019..29573a5f 100644 --- a/archinstall/scripts/guided.py +++ b/archinstall/scripts/guided.py @@ -12,13 +12,13 @@ from archinstall.lib.disk.utils import disk_layouts from archinstall.lib.general.general_menu import PostInstallationAction, select_post_installation from archinstall.lib.global_menu import GlobalMenu from archinstall.lib.installer import Installer, accessibility_tools_in_use, run_custom_user_commands +from archinstall.lib.log import debug, error, info from archinstall.lib.menu.util import delayed_warning from archinstall.lib.mirror.mirror_handler import MirrorListHandler from archinstall.lib.models import Bootloader from archinstall.lib.models.device import DiskLayoutType, EncryptionType from archinstall.lib.models.users import User from archinstall.lib.network.network_handler import install_network_config -from archinstall.lib.output import debug, error, info from archinstall.lib.packages.util import check_version_upgrade from archinstall.lib.profile.profiles_handler import profile_handler from archinstall.lib.translationhandler import tr diff --git a/archinstall/scripts/minimal.py b/archinstall/scripts/minimal.py index 3d41386b..a58963f2 100644 --- a/archinstall/scripts/minimal.py +++ b/archinstall/scripts/minimal.py @@ -4,12 +4,12 @@ from archinstall.lib.configuration import ConfigurationOutput from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu from archinstall.lib.disk.filesystem import FilesystemHandler from archinstall.lib.installer import Installer +from archinstall.lib.log import debug, error, info from archinstall.lib.menu.util import delayed_warning from archinstall.lib.models import Bootloader from archinstall.lib.models.profile import ProfileConfiguration from archinstall.lib.models.users import Password, User from archinstall.lib.network.network_handler import install_network_config -from archinstall.lib.output import debug, error, info from archinstall.lib.profile.profiles_handler import profile_handler from archinstall.lib.translationhandler import tr from archinstall.tui.components import tui diff --git a/archinstall/scripts/only_hd.py b/archinstall/scripts/only_hd.py index 5df72965..c7349c51 100644 --- a/archinstall/scripts/only_hd.py +++ b/archinstall/scripts/only_hd.py @@ -7,8 +7,8 @@ from archinstall.lib.disk.filesystem import FilesystemHandler from archinstall.lib.disk.utils import disk_layouts from archinstall.lib.global_menu import GlobalMenu from archinstall.lib.installer import Installer +from archinstall.lib.log import debug, error from archinstall.lib.menu.util import delayed_warning -from archinstall.lib.output import debug, error from archinstall.lib.translationhandler import tr from archinstall.tui.components import tui diff --git a/archinstall/tui/components.py b/archinstall/tui/components.py index e458caaf..bea36394 100644 --- a/archinstall/tui/components.py +++ b/archinstall/tui/components.py @@ -19,7 +19,7 @@ from textual.widgets.option_list import Option from textual.widgets.selection_list import Selection from textual.worker import WorkerCancelled -from archinstall.lib.output import debug +from archinstall.lib.log import debug from archinstall.lib.translationhandler import tr from archinstall.tui.menu_item import MenuItem, MenuItemGroup, MsgLevelType, PreviewResult from archinstall.tui.result import Result, ResultType diff --git a/pyproject.toml b/pyproject.toml index 13e0933f..ccbee27b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ dependencies = [ "pyparted==3.13.0", "pydantic==2.13.4", "cryptography==48.0.0", - "textual==8.2.5", + "textual==8.2.7", "markdown-it-py==4.0.0", "linkify-it-py==2.1.0", ] @@ -37,9 +37,10 @@ dev = [ "mypy==2.1.0", "flake8==7.3.0", "pre-commit==4.6.0", - "ruff==0.15.12", + "ruff==0.15.14", "pylint==4.0.5", "pytest==9.0.3", + "hypothesis>=6.152.4", ] doc = ["sphinx"] @@ -60,6 +61,7 @@ include-package-data = true "**/*.po", "**/*.pot", "**/*.json", + "**/*.kdl", ] [tool.setuptools.package-dir] @@ -68,7 +70,10 @@ archinstall = "archinstall" [tool.mypy] python_version = "3.14" files = "." -exclude = "^build/" +exclude = [ + "^build/", + "^test_tooling/", +] disallow_any_explicit = false disallow_any_expr = false disallow_any_unimported = true diff --git a/build_iso.sh b/test_tooling/mkarchiso/build_iso.sh similarity index 100% rename from build_iso.sh rename to test_tooling/mkarchiso/build_iso.sh diff --git a/test_tooling/mkosi/README.md b/test_tooling/mkosi/README.md new file mode 100644 index 00000000..d26d0d9f --- /dev/null +++ b/test_tooling/mkosi/README.md @@ -0,0 +1,12 @@ +# To build + + mkosi build -B + +# To run + + mkosi qemu \ + --drive=archinstall_small:25G \ + -- \ + -device nvme,serial=archinstall_small,drive=archinstall_small + +*note: in order to boot the installation, we need to disable UKI being added to -kernel. I don't know of a way to do this yet, unless we tinker with mkosi/qemu.py - https://github.com/Torxed/mkosi/commit/6f3c20802bd73f88b672cc96ef0db1e542084316 - in which case we could do: `mkosi qemu --drive=archinstall_small:25G -- -device nvme,serial=archinstall_small,drive=archinstall_small,bootindex=0 -kernel none` but it still won't boot properly.* \ No newline at end of file diff --git a/test_tooling/mkosi/mkosi.cache/.gitkeep b/test_tooling/mkosi/mkosi.cache/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test_tooling/mkosi/mkosi.conf b/test_tooling/mkosi/mkosi.conf new file mode 100644 index 00000000..fdc36613 --- /dev/null +++ b/test_tooling/mkosi/mkosi.conf @@ -0,0 +1,50 @@ +[Distribution] +Distribution=arch +# LocalMirror=file:///var/lib/localmirror + +[Output] +Format=uki +# Format=disk + +[Include] +Include=mkosi-vm + +[Validation] +SecureBoot=false +SecureBootAutoEnroll=false +Sign=false +# Signing artifacts (hashsums etc) using a GPG key: +# Key=D4B58E897A929F2E +# Signing secure boot using PIV on yubikey: +# SecureBoot=true +# SecureBootKey=pkcs11: +# SecureBootCertificate=secureboot.crt + +[Content] +Packages= + pacman + archlinux-keyring + amd-ucode + intel-ucode +# tpm2-tss +# libfido2 +# libp11-kit +WithDocs=false +RootPassword=toor +Timezone=Europe/Stockholm +Keymap=sv-latin1 +InitrdProfiles=network + +[Config] +Profiles=archinstall + +[Build] +Incremental=true +ToolsTree=default +ToolsTreeProfiles=devel,misc,package-manager,runtime,gui +WithNetwork=yes + +[Runtime] +Console=gui +CPUs=4 +RAM=8G diff --git a/test_tooling/mkosi/mkosi.extra/etc/systemd/network/20-ethernet.network b/test_tooling/mkosi/mkosi.extra/etc/systemd/network/20-ethernet.network new file mode 100644 index 00000000..478a55da --- /dev/null +++ b/test_tooling/mkosi/mkosi.extra/etc/systemd/network/20-ethernet.network @@ -0,0 +1,24 @@ +[Match] +# Matching with "Type=ether" causes issues with containers because it also matches virtual Ethernet interfaces (veth*). +# See https://bugs.archlinux.org/task/70892 +# Instead match by globbing the network interface name. +Name=en* +Name=eth* + +[Link] +RequiredForOnline=routable + +[Network] +DHCP=yes +MulticastDNS=yes + +# systemd-networkd does not set per-interface-type default route metrics +# https://github.com/systemd/systemd/issues/17698 +# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband. +# Use values from NetworkManager. From nm_device_get_route_metric_default in +# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c +[DHCPv4] +RouteMetric=100 + +[IPv6AcceptRA] +RouteMetric=100 \ No newline at end of file diff --git a/test_tooling/mkosi/mkosi.extra/etc/systemd/system/getty@tty1.service.d/autologin.conf b/test_tooling/mkosi/mkosi.extra/etc/systemd/system/getty@tty1.service.d/autologin.conf new file mode 100644 index 00000000..161d4952 --- /dev/null +++ b/test_tooling/mkosi/mkosi.extra/etc/systemd/system/getty@tty1.service.d/autologin.conf @@ -0,0 +1,3 @@ +[Service] +ExecStart= +ExecStart=-/usr/bin/agetty --noreset --noclear --autologin root - ${TERM} \ No newline at end of file diff --git a/test_tooling/mkosi/mkosi.extra/root/.profile b/test_tooling/mkosi/mkosi.extra/root/.profile new file mode 100644 index 00000000..c8d1791b --- /dev/null +++ b/test_tooling/mkosi/mkosi.extra/root/.profile @@ -0,0 +1,5 @@ +cd archinstall-git +rm -rf dist + +uv build --no-build-isolation --wheel +uv pip install dist/*.whl --break-system-packages --system --no-build --no-deps \ No newline at end of file diff --git a/test_tooling/mkosi/mkosi.extra/usr/lib/systemd/system-preset/5-archinstall.preset b/test_tooling/mkosi/mkosi.extra/usr/lib/systemd/system-preset/5-archinstall.preset new file mode 100644 index 00000000..8423c627 --- /dev/null +++ b/test_tooling/mkosi/mkosi.extra/usr/lib/systemd/system-preset/5-archinstall.preset @@ -0,0 +1 @@ +enable systemd-networkd.service \ No newline at end of file diff --git a/test_tooling/mkosi/mkosi.output/.gitkeep b/test_tooling/mkosi/mkosi.output/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test_tooling/mkosi/mkosi.postinst.chroot b/test_tooling/mkosi/mkosi.postinst.chroot new file mode 100755 index 00000000..096857e8 --- /dev/null +++ b/test_tooling/mkosi/mkosi.postinst.chroot @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +git clone https://github.com/archlinux/archinstall.git /root/archinstall-git +(cd /root/archinstall-git && git checkout master) + +# TODO: Set geo-mirrors statically instead +curl -s "https://archlinux.org/mirrorlist/?country=SE&protocol=https&use_mirror_status=on" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 5 - > /etc/pacman.d/mirrorlist + +pacman-key --init +pacman-key --populate archlinux \ No newline at end of file diff --git a/test_tooling/mkosi/mkosi.profiles/archinstall b/test_tooling/mkosi/mkosi.profiles/archinstall new file mode 100644 index 00000000..75628b61 --- /dev/null +++ b/test_tooling/mkosi/mkosi.profiles/archinstall @@ -0,0 +1,56 @@ +[Content] +Packages= + acpid + intel-media-driver + linux-firmware + linux-firmware-intel + ca-certificates-mozilla + ca-certificates-utils + nano + gvfs + noto-fonts + cantarell-fonts + ttf-dejavu + polkit + bash + bzip2 + coreutils + file + filesystem + findutils + gawk + gcc-libs + gettext + glibc + grep + gzip + iproute2 + iputils + licenses + pciutils + procps-ng + psmisc + sed + tar + linux + diffutils + less + strace + util-linux + xz + pacman-contrib + gcc + git + pkgconfig + python + python-pip + python-uv + python-setuptools + python-pyparted + python-pydantic + python-textual + dosfstools + btrfs-progs + arch-install-scripts +WithDocs=false +KernelCommandLine=quiet splash \ No newline at end of file diff --git a/test_tooling/mkosi/mkosi.version b/test_tooling/mkosi/mkosi.version new file mode 100644 index 00000000..ca7bf83a --- /dev/null +++ b/test_tooling/mkosi/mkosi.version @@ -0,0 +1 @@ +13 \ No newline at end of file diff --git a/test_tooling/qemu/README.md b/test_tooling/qemu/README.md new file mode 100644 index 00000000..e36ccfa1 --- /dev/null +++ b/test_tooling/qemu/README.md @@ -0,0 +1,18 @@ +# Qemu helper + +Can be used with the `mkosi` test tooling + +After `mkosi -B build` has been executed, run the following: + + python test_tooling/qemu/qemu.py \ + --uki ./test_tooling/mkosi/mkosi.output/image_13.efi \ + --harddrive ~/test.qcow2:15G \ + --harddrive ~/test_large.qcow2:25G + +And install using `archinstall`, after the machine has been shutdown, run: + + python test_tooling/qemu/qemu.py \ + --harddrive ~/test.qcow2:15G \ + --harddrive ~/test_large.qcow2:25G + +As this will boot EFI mode with just the harddrives to verify the installation. \ No newline at end of file diff --git a/test_tooling/qemu/qemu.py b/test_tooling/qemu/qemu.py new file mode 100644 index 00000000..c8307771 --- /dev/null +++ b/test_tooling/qemu/qemu.py @@ -0,0 +1,483 @@ +import getpass +import grp +import hashlib +import os +import pathlib +import re +import shlex +import shutil +import subprocess +import sys +import time +from argparse import ArgumentParser +from collections.abc import Iterator +from select import EPOLLHUP, EPOLLIN, epoll +from shutil import which +from types import TracebackType +from typing import Any, Self, override + + +class RequirementError(Exception): + pass + + +class ArgumentError(Exception): + pass + + +def get_master(interface): + master_path = pathlib.Path(f'/sys/class/net/{interface}/master') + return master_path.readlink().name if master_path.exists() else None + + +def gray(text): + return f'\033[38;5;246m{text}\033[0m' + + +def orange(text): + return f'\033[38;5;208m{text}\033[0m' + + +def red(text): + return f'\033[31m{text}\033[0m' + + +sudo_password = None # Gets populated later +harddrives = {} +username = getpass.getuser() +groupname = grp.getgrgid(os.getgid()).gr_name + +# https://stackoverflow.com/a/43627833/929999 +_VT100_ESCAPE_REGEX = r'\x1B\[[?0-9;]*[a-zA-Z]' +_VT100_ESCAPE_REGEX_BYTES = _VT100_ESCAPE_REGEX.encode() + +parser = ArgumentParser(description='A set of common parameters for the tooling', add_help=True) + +# Defaults to the order of which the harddrives are defined. +boot_option = parser.add_mutually_exclusive_group() +boot_option.add_argument('--uki', help='Boot a UKI (EFI) image') +boot_option.add_argument('--kernel', help='Boot a Linux kernel') +boot_option.add_argument('--iso', help='Boot a ISO 9660') + +networking = parser.add_argument_group('Networking', "Disables the default '-net nic -net user' network behavior of Qemu.") +networking.add_argument('--tap', nargs='?', help='Configures a TAP interface and passes it in as a virtio-net-pci.', default=None, type=str) +networking.add_argument('--tap-mac', nargs='?', help='MAC for the --tap interface', default='52:54:00:00:00:02') +networking.add_argument('--bridge', nargs='?', help='Configures a bridge, to which the --tap is added.', default=None, type=str) +networking.add_argument('--bridge-mac', nargs='?', help='MAC for the interface', default=None) +networking.add_argument('--bridge-master', nargs='?', help="Which interface to set as 'master' on the bridge.", default=None, type=str) + +hardware = parser.add_argument_group('Hardware', 'General hardware specs for the virtual machine') +# To override the use of EFI boot (will not work with --uki for obvious reasons) +hardware.add_argument('--bios', action='store_true', help='Disables EFI (edk2/ovmf) and uses BIOS support instead', default=False) +hardware.add_argument('--memory', nargs='?', help='Ammount of memory to supply the machine', default=8192) +hardware.add_argument('--harddrive', action='append', help='Sets up one or more virtio-scsi-pci, size is defined by --harddrive test.qcow2:15G', type=str) +hardware.add_argument('--cpu', help='Sets the number of cores to allocate (default nproc -1)', type=str, default=os.cpu_count() - 1 if os.cpu_count() else 1) +hardware.add_argument('--resolution', help="Sets Qemu's VGA resolution", type=str, default='1920x1107') + +kernel = parser.add_argument_group('Kernel', '--kernel specific arguments') +kernel.add_argument('--initrd', nargs='?', help='Defines which ISO to run (skips build all together)', default=None, type=pathlib.Path) + +args, unknowns = parser.parse_known_args() # pylint: disable=redefined-outer-name + +if args.bios and args.uki: + raise ArgumentError('Cannot boot a --uki image with --bios mode (at least not that I know of).') + +if args.uki is None and args.kernel is None and args.iso is None and args.harddrive is None: + raise ArgumentError('Cannot boot this machine, define at least one of: --uki, --kernel, --iso, --harddrive') + +if args.bridge is None and args.bridge_master: + raise ArgumentError('Cannot use --bridge-master without defining --bridge') + +if args.bridge is None and args.bridge_mac: + raise ArgumentError('Cannot use --bridge-mac without defining --bridge') +elif args.bridge and args.bridge_mac is None: + args.bridge_mac = '52:54:00:00:00:1' + +if args.tap and not args.bridge and get_master(args.tap) is None: + # We'll allow it, because maybe we're tesing what happens without networking, but the NIC exists. + # Or the user has some creative iptables/nftables forwarding. + print(orange('--tap does not have a master, consider adding --bridge or manual set a master using ip-link(8).')) + +if args.tap is None and args.bridge: + print(orange("--bridge* arguments will be ignored since there's no --tap defined")) +elif args.tap and args.tap_mac is None: + args.tap_mac = '52:54:00:00:00:2' + + +class SysCallError(Exception): + def __init__(self, message: str, exit_code: int | None = None, worker_log: bytes = b'') -> None: + super().__init__(message) + self.message = message + self.exit_code = exit_code + self.worker_log = worker_log + + +def clear_vt100_escape_codes(data: bytes) -> bytes: + return re.sub(_VT100_ESCAPE_REGEX_BYTES, b'', data) + + +def locate_binary(name: str) -> str: + if path := which(name): + return path + raise RequirementError(f'Binary {name} does not exist.') + + +def _pid_exists(pid: int) -> bool: + try: + return any(subprocess.check_output(['ps', '--no-headers', '-o', 'pid', '-p', str(pid)]).strip()) + except subprocess.CalledProcessError: + return False + + +class SysCommandWorker: + def __init__( + self, + cmd: str | list[str], + peek_output: bool | None = False, + environment_vars: dict[str, str] | None = None, + working_directory: str = './', + remove_vt100_escape_codes_from_lines: bool = True, + ): + if isinstance(cmd, str): + cmd = shlex.split(cmd) + + if cmd and not cmd[0].startswith(('/', './')): # Path() does not work well + cmd[0] = locate_binary(cmd[0]) + + self.cmd = cmd + self.peek_output = peek_output + # define the standard locale for command outputs. For now the C ascii one. Can be overridden + self.environment_vars = {'LC_ALL': 'C'} + if environment_vars: + self.environment_vars.update(environment_vars) + + self.working_directory = working_directory + + self.exit_code: int | None = None + self._trace_log = b'' + self._trace_log_pos = 0 + self.poll_object = epoll() + self.child_fd: int | None = None + self.started = False + self.ended = False + self.remove_vt100_escape_codes_from_lines: bool = remove_vt100_escape_codes_from_lines + + def __contains__(self, key: bytes) -> bool: + """ + Contains will also move the current buffert position forward. + This is to avoid re-checking the same data when looking for output. + """ + assert isinstance(key, bytes) + + index = self._trace_log.find(key, self._trace_log_pos) + if index >= 0: + self._trace_log_pos += index + len(key) + return True + + return False + + def __iter__(self, *args: str, **kwargs: dict[str, Any]) -> Iterator[bytes]: # pylint: disable=redefined-outer-name + last_line = self._trace_log.rfind(b'\n') + lines = filter(None, self._trace_log[self._trace_log_pos : last_line].splitlines()) + for line in lines: + if self.remove_vt100_escape_codes_from_lines: + line = clear_vt100_escape_codes(line) + + yield line + b'\n' + + self._trace_log_pos = last_line + + @override + def __repr__(self) -> str: + self.make_sure_we_are_executing() + return str(self._trace_log) + + @override + def __str__(self) -> str: + try: + return self._trace_log.decode('utf-8') + except UnicodeDecodeError: + return str(self._trace_log) + + def __enter__(self) -> Self: + return self + + def __exit__(self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None) -> None: + # b''.join(sys_command('sync')) # No need to, since the underlying fs() object will call sync. + # TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager + + if self.child_fd: + try: + os.close(self.child_fd) + except Exception: + pass + + if self.peek_output: + # To make sure any peaked output didn't leave us hanging + # on the same line we were on. + sys.stdout.write('\n') + sys.stdout.flush() + + if exc_type is not None: + print(gray(str(exc_value))) + + if self.exit_code != 0: + raise SysCallError( + f'{self.cmd} exited with abnormal exit code [{self.exit_code}]: {str(self)[-500:]}', + self.exit_code, + worker_log=self._trace_log, + ) + + def is_alive(self) -> bool: + self.poll() + + if self.started and not self.ended: + return True + + return False + + def write(self, data: bytes, line_ending: bool = True) -> int: + assert isinstance(data, bytes) # TODO: Maybe we can support str as well and encode it + + self.make_sure_we_are_executing() + + if self.child_fd: + return os.write(self.child_fd, data + (b'\n' if line_ending else b'')) + + return 0 + + def make_sure_we_are_executing(self) -> bool: + if not self.started: + return self.execute() + return True + + def tell(self) -> int: + self.make_sure_we_are_executing() + return self._trace_log_pos + + def seek(self, pos: int) -> None: + self.make_sure_we_are_executing() + # Safety check to ensure 0 < pos < len(tracelog) + self._trace_log_pos = min(max(0, pos), len(self._trace_log)) + + def peak(self, output: str | bytes) -> bool: + if self.peek_output: + if isinstance(output, bytes): + try: + output = output.decode('UTF-8') + except UnicodeDecodeError: + return False + + sys.stdout.write(output) + sys.stdout.flush() + + return True + + def poll(self) -> None: + self.make_sure_we_are_executing() + + if self.child_fd: + got_output = False + for _fileno, _event in self.poll_object.poll(0.1): + try: + output = os.read(self.child_fd, 8192) + got_output = True + self.peak(output) + self._trace_log += output + except OSError: + self.ended = True + break + + if self.ended or (not got_output and not _pid_exists(self.pid)): + self.ended = True + try: + wait_status = os.waitpid(self.pid, 0)[1] + self.exit_code = os.waitstatus_to_exitcode(wait_status) + except ChildProcessError: + try: + wait_status = os.waitpid(self.child_fd, 0)[1] + self.exit_code = os.waitstatus_to_exitcode(wait_status) + except ChildProcessError: + self.exit_code = 1 + + def execute(self) -> bool: + import pty + + if (old_dir := os.getcwd()) != self.working_directory: + os.chdir(str(self.working_directory)) + + # Note: If for any reason, we get a Python exception between here + # and until os.close(), the traceback will get locked inside + # stdout of the child_fd object. `os.read(self.child_fd, 8192)` is the + # only way to get the traceback without losing it. + + self.pid, self.child_fd = pty.fork() + + # https://stackoverflow.com/questions/4022600/python-pty-fork-how-does-it-work + if not self.pid: + try: + os.execve(self.cmd[0], list(self.cmd), {**os.environ, **self.environment_vars}) + except FileNotFoundError: + print(red(f'{self.cmd[0]} does not exist.')) + self.exit_code = 1 + return False + else: + # Only parent process moves back to the original working directory + os.chdir(old_dir) + + self.started = True + self.poll_object.register(self.child_fd, EPOLLIN | EPOLLHUP) + + return True + + def decode(self, encoding: str = 'UTF-8') -> str: + return self._trace_log.decode(encoding) + + +def ensure_sudo(): + global sudo_password # pylint: disable=global-statement + + if sudo_password is None: + if (sudo_password := getpass.getpass(f'[sudo] password for {username}: ')) == '': + raise ValueError('Certain commands need sudo to work and no sudo password was given.') + + +def setup_networking(): + if args.tap: + if pathlib.Path(f'/sys/class/net/{args.tap}').exists() is False: + print(gray(f'Creating {args.tap} for user {username} and group {groupname}')) + handle, pw_prompted = SysCommandWorker(f'sudo ip tuntap add dev {args.tap} mode tap user {username} group {groupname}'), False + while handle.is_alive(): + if b'password for' in handle and pw_prompted is False: + ensure_sudo() + handle.write(bytes(sudo_password, 'UTF-8')) + pw_prompted = True + + if args.bridge: + if pathlib.Path(f'/sys/class/net/{args.bridge}').exists() is False: + print(gray(f'Creating {args.bridge}')) + handle, pw_prompted = SysCommandWorker(f'sudo ip link add name {args.bridge} type bridge'), False + while handle.is_alive(): + if b'password for' in handle and pw_prompted is False: + ensure_sudo() + handle.write(bytes(sudo_password, 'UTF-8')) + pw_prompted = True + + if args.bridge_mac: + handle, pw_prompted = SysCommandWorker(f'sudo ip link set dev {args.bridge} address {args.bridge_mac}'), False + print(gray(f'Setting bridge {args.bridge} MAC address to {args.bridge_mac}')) + while handle.is_alive(): + if b'password for' in handle and pw_prompted is False: + ensure_sudo() + handle.write(bytes(sudo_password, 'UTF-8')) + pw_prompted = True + + if args.bridge_master and get_master(args.bridge) != args.bridge_master: + handle, pw_prompted = SysCommandWorker(f'sudo ip link set dev {args.bridge_master} master {args.bridge}'), False + print(gray(f'Setting interface {args.bridge_master} master to {args.bridge}')) + while handle.is_alive(): + if b'password for' in handle and pw_prompted is False: + ensure_sudo() + handle.write(bytes(sudo_password, 'UTF-8')) + pw_prompted = True + + print(gray(f'Setting interface {args.tap} master to {args.bridge}')) + handle, pw_prompted = SysCommandWorker(f'sudo ip link set dev {args.tap} master {args.bridge}'), False + while handle.is_alive(): + if b'password for' in handle and pw_prompted is False: + ensure_sudo() + handle.write(bytes(sudo_password, 'UTF-8')) + pw_prompted = True + + print(gray(f'Bringing up bridge {args.bridge}')) + handle, pw_prompted = SysCommandWorker(f'sudo ip link set dev {args.bridge} up'), False + while handle.is_alive(): + if b'password for' in handle and pw_prompted is False: + ensure_sudo() + handle.write(bytes(sudo_password, 'UTF-8')) + pw_prompted = True + + print(gray(f'Bringing interface {args.tap} up')) + handle, pw_prompted = SysCommandWorker(f'sudo ip link set dev {args.tap} up'), False + while handle.is_alive(): + if b'password for' in handle and pw_prompted is False: + ensure_sudo() + handle.write(bytes(sudo_password, 'UTF-8')) + pw_prompted = True + + +def setup_disks(): + if args.harddrive: + for harddrive_arg in args.harddrive: + path, size = harddrive_arg.split(':') + path = pathlib.Path(path.strip()).expanduser().resolve().absolute() + harddrives[path] = size.strip() + + if path.exists() is False: + handle = SysCommandWorker(f'qemu-img create -f qcow2 {hdd} {size}') + while handle.is_alive(): + time.sleep(0.01) + + if handle.exit_code != 0: + raise ValueError(f'Could not create harddrive {hdd}: {handle}') + + +setup_networking() +setup_disks() + +if args.uki or args.bios is False: + disk_paths_hash = hashlib.sha1((''.join(sorted([str(x) for x in harddrives.keys()]))).encode()).hexdigest() + + shutil.copy2('/usr/share/ovmf/x64/OVMF_CODE.secboot.4m.fd', f'./OVMF_CODE.secboot.4m.fd.{disk_paths_hash}') + shutil.copy2('/usr/share/ovmf/x64/OVMF_VARS.4m.fd', f'./OVMF_VARS.4m.fd.{disk_paths_hash}') + +boot_index = 0 +qemu = 'qemu-system-x86_64' +qemu += ' -cpu host' +qemu += ' -enable-kvm' +qemu += ' -machine q35,accel=kvm' +qemu += ' -object rng-random,filename=/dev/urandom,id=rng0' +qemu += ' -device virtio-rng-pci,rng=rng0' +qemu += ' -global driver=cfi.pflash01,property=secure,value=on' +qemu += f' -smp {args.cpu},sockets=1,dies=1,cores={args.cpu},threads=1' +# qemu += f' -vga vga' +qemu += f' -device VGA,edid=on,xres={args.resolution.split("x")[0]},yres={args.resolution.split("x")[1]}' +qemu += ' -device intel-iommu,device-iotlb=on,caching-mode=on' +qemu += f' -m {args.memory}' +if args.bios is False: + qemu += f' -drive if=pflash,format=raw,readonly=on,file=./OVMF_CODE.secboot.4m.fd.{disk_paths_hash}' + qemu += f' -drive if=pflash,format=raw,file=./OVMF_VARS.4m.fd.{disk_paths_hash}' +if args.uki: + qemu += f' -kernel {args.uki}' + boot_index += 1 +scsi_index = 0 +for scsi_index, hdd in enumerate(harddrives.keys()): + # qemu += f' -device virtio-scsi-pci,bus=pcie.0,id=scsi{index}' + # qemu += f' -device scsi-hd,drive=hdd{index},bus=scsi{index}.0,id=scsi{index}.0,bootindex={hdd_boot_priority+index}' + # qemu += f' -drive file={hdd},if=none,format=qcow2,discard=unmap,aio=native,cache=none,id=hdd{index}' + qemu += f' -device virtio-scsi-pci,bus=pcie.0,id=scsi{scsi_index},addr=0x{scsi_index + 8}' + qemu += f' -device scsi-hd,drive=libvirt-{scsi_index}-format,bus=scsi{scsi_index}.0,id=scsi{scsi_index}-0-0-0,channel=0,scsi-id=0,lun=0,device_id=drive-scsi0-0-0-0,bootindex={boot_index},write-cache=on' # noqa: E501 + qemu += f' -blockdev \'{{"driver":"file","filename":"{hdd}","aio":"threads","node-name":"libvirt-{scsi_index}-storage","cache":{{"direct":false,"no-flush":false}},"auto-read-only":true,"discard":"unmap"}}\'' # noqa: E501 + qemu += f' -blockdev \'{{"node-name":"libvirt-{scsi_index}-format","read-only":false,"discard":"unmap","cache":{{"direct":true,"no-flush":false}},"driver":"qcow2","file":"libvirt-{scsi_index}-storage","backing":null}}\'' # noqa: E501 + boot_index += 1 +if args.iso: + qemu += f' -device virtio-scsi-pci,bus=pcie.0,id=scsi{scsi_index + 1}' + qemu += f' -device scsi-cd,drive=cdrom0,bus=scsi{scsi_index + 1}.0,bootindex={boot_index}' + qemu += f' -drive file={args.iso},media=cdrom,if=none,format=raw,cache=none,id=cdrom0' + boot_index += 1 + +# if args.vfio: +# qemu += f' -drive file={args.vfio},index=2,media=cdrom' + +if args.tap: + qemu += f' -device virtio-net-pci,mac={args.tap_mac},id=network0,netdev=network0.0,status=on,bus=pcie.0' + qemu += f' -netdev tap,ifname={args.tap},id=network0.0,script=no,downscript=no' + +print(gray(qemu)) + +qemu_session = subprocess.run(shlex.split(qemu), check=True, capture_output=True) + +if qemu_session.stdout: + print(qemu_session.stdout.decode()) +if qemu_session.returncode != 0: + print(red(qemu_session.stderr.decode())) diff --git a/tests/test_share_log.py b/tests/test_share_log.py index c1c3ca84..1a19ba26 100644 --- a/tests/test_share_log.py +++ b/tests/test_share_log.py @@ -1,94 +1,127 @@ # pylint: disable=redefined-outer-name +import string import urllib.error from io import BytesIO from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import patch import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st -from archinstall.lib.output import share_install_log +from archinstall.lib.log import share_install_log + +urls = st.builds( + '{}://{}.{}/{}'.format, + st.sampled_from(['http', 'https']), + st.text(alphabet=string.ascii_lowercase, min_size=3, max_size=10), + st.sampled_from(['com', 'net', 'org', 'rs']), + st.text(alphabet=string.ascii_lowercase + string.digits, min_size=0, max_size=8), +) + +max_bytes = st.one_of(st.none(), st.integers(min_value=1, max_value=130)) + +random_paths = st.lists( + st.text( + alphabet=string.ascii_lowercase + string.digits, + min_size=1, + max_size=10, + ), + min_size=1, + max_size=5, +).map(lambda parts: Path(*parts)) -@pytest.fixture() +@pytest.fixture def log_file(tmp_path: Path) -> Path: log_dir = tmp_path / 'archinstall' log_dir.mkdir() return log_dir / 'install.log' -def _fake_logger(log_file: Path) -> MagicMock: - mock = MagicMock() - mock.path = log_file - return mock +# def _fake_logger(log_file: Path) -> MagicMock: +# mock = MagicMock() +# mock.path = log_file +# return mock -def test_file_not_found(tmp_path: Path) -> None: - missing = tmp_path / 'no-such' / 'install.log' - with patch('archinstall.lib.output.logger', _fake_logger(missing)): - assert share_install_log() == 1 +@given(paste_url=urls, max_byte=max_bytes, sub_path=random_paths) +@settings(max_examples=3, suppress_health_check=[HealthCheck.function_scoped_fixture]) +def test_file_not_found( + tmp_path: Path, + sub_path: Path, + paste_url: str, + max_byte: int | None, +) -> None: + missing_log = tmp_path / sub_path / 'install.log' + + with patch('archinstall.lib.log.logger._path', new=missing_log): + assert share_install_log(paste_url, max_byte) is None -def test_empty_file(log_file: Path) -> None: +@given(paste_url=urls, max_byte=max_bytes) +@settings(max_examples=3, suppress_health_check=[HealthCheck.function_scoped_fixture]) +def test_empty_file(log_file: Path, paste_url: str, max_byte: int | None) -> None: log_file.write_bytes(b'') - with patch('archinstall.lib.output.logger', _fake_logger(log_file)): - assert share_install_log() == 1 + + with patch('archinstall.lib.log.logger._path', new=log_file.parent): + # with patch('archinstall.lib.log.logger', _fake_logger(log_file)): + assert share_install_log(paste_url, max_byte) is None -def test_user_cancels(log_file: Path) -> None: +@given(paste_url=urls, resp_url=urls, max_byte=max_bytes) +@settings(max_examples=3, suppress_health_check=[HealthCheck.function_scoped_fixture]) +def test_successful_upload(log_file: Path, resp_url: str, paste_url: str, max_byte: int | None) -> None: log_file.write_text('some log content') - with patch('archinstall.lib.output.logger', _fake_logger(log_file)): - assert share_install_log(confirm=lambda _: False) == 1 - - -def test_successful_upload(log_file: Path) -> None: - log_file.write_text('some log content') - fake_response = BytesIO(b'https://paste.rs/abc.def') + fake_response = BytesIO(resp_url.encode()) with ( - patch('archinstall.lib.output.logger', _fake_logger(log_file)), - patch('urllib.request.urlopen', return_value=fake_response) as mock_open, + patch('archinstall.lib.log.logger._path', new=log_file.parent), + patch('urllib.request.urlopen', return_value=fake_response), ): - result = share_install_log() - - assert result == 0 - req = mock_open.call_args[0][0] - assert req.data == b'some log content' + result = share_install_log(paste_url, max_byte) + assert result == resp_url -def test_truncation(log_file: Path) -> None: - max_size = 100 +@given(paste_url=urls, resp_url=urls, max_byte=max_bytes) +@settings(max_examples=3, suppress_health_check=[HealthCheck.function_scoped_fixture]) +def test_truncation(log_file: Path, resp_url: str, paste_url: str, max_byte: int | None) -> None: content = b'A' * 50 + b'B' * 80 log_file.write_bytes(content) - fake_response = BytesIO(b'https://paste.rs/abc.def') + fake_response = BytesIO(resp_url.encode()) + + exptected_byte = len(content) if max_byte is None else max_byte with ( - patch('archinstall.lib.output.logger', _fake_logger(log_file)), + patch('archinstall.lib.log.logger._path', new=log_file.parent), patch('urllib.request.urlopen', return_value=fake_response) as mock_open, ): - result = share_install_log(max_size=max_size) - - assert result == 0 - req = mock_open.call_args[0][0] - assert len(req.data) == max_size - assert req.data == content[-max_size:] + _ = share_install_log(paste_url, max_byte) + req = mock_open.call_args[0][0] + assert len(req.data) == exptected_byte + assert req.data == content[-exptected_byte:] -def test_network_error(log_file: Path) -> None: +@given(paste_url=urls, max_byte=max_bytes) +@settings(max_examples=3, suppress_health_check=[HealthCheck.function_scoped_fixture]) +def test_network_error(log_file: Path, paste_url: str, max_byte: int | None) -> None: log_file.write_text('some log content') with ( - patch('archinstall.lib.output.logger', _fake_logger(log_file)), + patch('archinstall.lib.log.logger._path', new=log_file.parent), patch('urllib.request.urlopen', side_effect=urllib.error.URLError('no network')), ): - assert share_install_log() == 1 + assert share_install_log(paste_url, max_byte) is None -def test_unexpected_response(log_file: Path) -> None: +@given(paste_url=urls, max_byte=max_bytes) +@settings(max_examples=3, suppress_health_check=[HealthCheck.function_scoped_fixture]) +def test_unexpected_response(log_file: Path, paste_url: str, max_byte: int | None) -> None: log_file.write_text('some log content') fake_response = BytesIO(b'ERROR: something went wrong') with ( - patch('archinstall.lib.output.logger', _fake_logger(log_file)), + patch('archinstall.lib.log.logger._path', new=log_file.parent), patch('urllib.request.urlopen', return_value=fake_response), ): - assert share_install_log() == 1 + assert share_install_log(paste_url, max_byte) is None