diff --git a/CMakeLists.txt b/CMakeLists.txt index 15f40803e..c8b233f50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,15 +135,15 @@ set( CALAMARES_DESCRIPTION_SUMMARY # NOTE: update these lines by running `txstats.py`, or for full automation # `txstats.py -e`. See also # -# Total 81 languages -set( _tx_complete az az_AZ ca de fa fi_FI he hr ja ko lt pt_PT si - sq tr_TR uk zh_TW ) -set( _tx_good as be ca@valencia cs_CZ da fr fur hi it_IT ml nl - pt_BR ru sk sv tg vi zh_CN ) +# Total 74 languages +set( _tx_complete az az_AZ ca de fa fi_FI he hi hr ja ko lt pt_BR + pt_PT si sq sv tr_TR uk zh_TW ) +set( _tx_good as be ca@valencia cs_CZ da fr fur it_IT ml nl ru sk + tg vi zh_CN ) set( _tx_ok ar ast bg bn el en_GB es es_MX et eu gl hu id is mr nb pl ro sl sr sr@latin th ) -set( _tx_incomplete en_HK en_IN eo es_PE es_PR fr_CH gu hi_IN id_ID - ie kk kn ko_KR lo lv mk ne ne_NP te te_IN ur zh zh_HK ) +set( _tx_incomplete eo es_PR gu ie kk kn lo lv mk ne ne_NP ta_IN te + ur zh zh_HK ) ### Required versions # diff --git a/README.md b/README.md index 8fa2dfda7..3e79d9a72 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![Current issue](https://img.shields.io/badge/issue-in_progress-FE9B48)](https://github.com/calamares/calamares/labels/hacking%3A%20in-progress) [![GitHub release](https://img.shields.io/github/release/calamares/calamares.svg)](https://github.com/calamares/calamares/releases) [![GitHub Build Status](https://img.shields.io/github/workflow/status/calamares/calamares/ci?label=GH%20build)](https://github.com/calamares/calamares/actions?query=workflow%3Aci) -[![GitHub license](https://img.shields.io/github/license/calamares/calamares.svg)](https://github.com/calamares/calamares/blob/calamares/LICENSE) +[![GitHub license](https://img.shields.io/github/license/calamares/calamares.svg)](https://github.com/calamares/calamares/blob/calamares/LICENSES/GPL-3.0-or-later.txt) | [Report a Bug](https://github.com/calamares/calamares/issues/new) | [Translate](https://www.transifex.com/projects/p/calamares/) | [Contribute](CONTRIBUTING.md) | [Matrix: #calamares:kde.org](https://webchat.kde.org/#/room/%23calamares:kde.org) | [IRC: Libera.Chat #calamares](https://kiwiirc.com/client/irc.libera.chat/#calamares) | [Wiki](https://github.com/calamares/calamares/wiki) | diff --git a/lang/calamares_en_GB.ts b/lang/calamares_en_GB.ts index 3578d4554..b8ddc023f 100644 --- a/lang/calamares_en_GB.ts +++ b/lang/calamares_en_GB.ts @@ -1989,7 +1989,7 @@ The installer will quit and all changes will be lost. Configuration Error - + Configuration Error diff --git a/lang/calamares_hi.ts b/lang/calamares_hi.ts index 7f20e8bcd..16eee77b5 100644 --- a/lang/calamares_hi.ts +++ b/lang/calamares_hi.ts @@ -689,27 +689,27 @@ The installer will quit and all changes will be lost. Successfully unmounted %1. - + %1 को माउंट से हटाना सफल। Successfully disabled swap %1. - + %1 स्वैप निष्क्रिय करना सफल। Successfully cleared swap %1. - + %1 स्वैप रिक्त करना सफल। Successfully closed mapper device %1. - + प्रतिचित्रण उपकरण %1 बंद करना सफल। Successfully disabled volume group %1. - + वॉल्यूम समूह %1 निष्क्रिय करना सफल। diff --git a/lang/calamares_id.ts b/lang/calamares_id.ts index d3a29ac42..a8b1d4cbf 100644 --- a/lang/calamares_id.ts +++ b/lang/calamares_id.ts @@ -6,7 +6,7 @@ Manage auto-mount settings - + Kelola pengaturan mount otomatis @@ -114,12 +114,12 @@ Uploads the session log to the configured pastebin. - + Unggah catatan sesi ke pastebin yang telah dikonfigurasi. Send Session Log - + Kirim Catatan Sesi @@ -165,7 +165,7 @@ Programmed job failure was explicitly requested. - + Kegagalan pekerjaan diprogram diminta secara eksplisit. @@ -189,7 +189,7 @@ Run command '%1' in target system. - Jalankan perintah '%1' di dalam sistem target. + Jalankan perintah '%1' pada sistem target. @@ -245,7 +245,7 @@ QML Step <i>%1</i>. - + QML Langkah <i>%1</i>. @@ -277,7 +277,7 @@ System-requirements checking is complete. - + Pengecekan kebutuhan sistem telah selesai. @@ -295,7 +295,7 @@ Would you like to paste the install log to the web? - Maukah anda untuk menempelkan log instalasi ke situs? + Maukah anda menempelkan log instalasi ke situs? @@ -429,7 +429,7 @@ Link copied to clipboard &Done - &Kelar + &Selesai @@ -1054,12 +1054,12 @@ Instalasi dapat dilanjutkan, namun beberapa fitur akan dinonfungsikan. Label for the filesystem - + Label untuk filesystem FS Label: - + Label FS: @@ -1418,12 +1418,12 @@ Instalasi dapat dilanjutkan, namun beberapa fitur akan dinonfungsikan. Label for the filesystem - + Label untuk filesystem FS Label: - + Label FS: @@ -1582,7 +1582,7 @@ Instalasi dapat dilanjutkan, namun beberapa fitur akan dinonfungsikan. Format partition %1 (file system: %2, size: %3 MiB) on %4. - + Format partisi %1 (file system: %2, ukuran %3 MiB) pada %4. @@ -1645,12 +1645,12 @@ Instalasi dapat dilanjutkan, namun beberapa fitur akan dinonfungsikan. is running the installer as an administrator (root) - + menjalankan installer sebagai administrator (root) The setup program is not running with administrator rights. - + Installer tidak dijalankan dengan kewenangan administrator. @@ -1699,7 +1699,7 @@ Instalasi dapat dilanjutkan, namun beberapa fitur akan dinonfungsikan. Could not open file <code>%1</code>. - + Tidak dapat membuka berkas <code>%1</code>. @@ -1712,7 +1712,7 @@ Instalasi dapat dilanjutkan, namun beberapa fitur akan dinonfungsikan. Creating initramfs with mkinitcpio. - + Membuat initramfs menggunakan mkinitcpio. @@ -1720,7 +1720,7 @@ Instalasi dapat dilanjutkan, namun beberapa fitur akan dinonfungsikan. Creating initramfs. - + Membuat initramfs. @@ -2031,12 +2031,12 @@ Instalasi dapat dilanjutkan, namun beberapa fitur akan dinonfungsikan. Browser software - Peramban perangkat lunak + Perangkat lunak peramban Browser package - Peramban paket + Paket peramban @@ -2046,12 +2046,12 @@ Instalasi dapat dilanjutkan, namun beberapa fitur akan dinonfungsikan. Kernel - Inti + Kernel Services - Jasa + Servis @@ -2587,12 +2587,12 @@ Instalasi dapat dilanjutkan, namun beberapa fitur akan dinonfungsikan. Repeat Password - + Ulangi Kata Sandi When this box is checked, password-strength checking is done and you will not be able to use a weak password. - + Ketikan kotak ini dicentang, pengecekan kekuatan kata sandi akan dilakukan dan anda tidak akan dapat menggunakan kata sandi yang lemah. @@ -4252,7 +4252,7 @@ Keluaran: root is not allowed as username. - + root tidak boleh digunakan sebagai nama pengguna. @@ -4287,7 +4287,7 @@ Keluaran: Repeat Password - + Ulangi Kata Sandi @@ -4297,27 +4297,27 @@ Keluaran: Validate passwords quality - + Validasi kualitas kata sandi When this box is checked, password-strength checking is done and you will not be able to use a weak password. - + Ketikan kotak ini dicentang, pengecekan kekuatan kata sandi akan dilakukan dan anda tidak akan dapat menggunakan kata sandi yang lemah. Log in automatically without asking for the password - + Masuk ke dalam sesi secara otomatis tanpa menanyakan kata sandi Only letters, numbers, underscore and hyphen are allowed, minimal of two characters. - + Hanya huruf, angka, garis bawah, dan tanda hubung yang diperbolehkan, minimal dua karakter. Reuse user password as root password - + Gunakan kata sandi pengguna sebagai kata sandi root @@ -4332,12 +4332,12 @@ Keluaran: Root Password - + Kata Sandi Root Repeat Root Password - + Ulangi Kata Sandi diff --git a/lang/calamares_ro.ts b/lang/calamares_ro.ts index a6872e55b..39573886d 100644 --- a/lang/calamares_ro.ts +++ b/lang/calamares_ro.ts @@ -1991,7 +1991,7 @@ Programul de instalare va ieși, iar toate modificările vor fi pierdute. Configuration Error - + Eroare de configurare diff --git a/lang/calamares_ta_IN.ts b/lang/calamares_ta_IN.ts new file mode 100644 index 000000000..165321f17 --- /dev/null +++ b/lang/calamares_ta_IN.ts @@ -0,0 +1,4377 @@ + + + + + AutoMountManagementJob + + + Manage auto-mount settings + + + + + BootInfoWidget + + + The <strong>boot environment</strong> of this system.<br><br>Older x86 systems only support <strong>BIOS</strong>.<br>Modern systems usually use <strong>EFI</strong>, but may also show up as BIOS if started in compatibility mode. + + + + + This system was started with an <strong>EFI</strong> boot environment.<br><br>To configure startup from an EFI environment, this installer must deploy a boot loader application, like <strong>GRUB</strong> or <strong>systemd-boot</strong> on an <strong>EFI System Partition</strong>. This is automatic, unless you choose manual partitioning, in which case you must choose it or create it on your own. + + + + + This system was started with a <strong>BIOS</strong> boot environment.<br><br>To configure startup from a BIOS environment, this installer must install a boot loader, like <strong>GRUB</strong>, either at the beginning of a partition or on the <strong>Master Boot Record</strong> near the beginning of the partition table (preferred). This is automatic, unless you choose manual partitioning, in which case you must set it up on your own. + + + + + BootLoaderModel + + + Master Boot Record of %1 + + + + + Boot Partition + இயக்கப் பகுதிப்பிரிப்பு + + + + System Partition + + + + + Do not install a boot loader + + + + + %1 (%2) + + + + + Calamares::BlankViewStep + + + Blank Page + + + + + Calamares::DebugWindow + + + Form + + + + + GlobalStorage + + + + + JobQueue + + + + + Modules + + + + + Type: + + + + + + none + + + + + Interface: + + + + + Crashes Calamares, so that Dr. Konqui can look at it. + + + + + Reloads the stylesheet from the branding directory. + + + + + Uploads the session log to the configured pastebin. + + + + + Send Session Log + + + + + Reload Stylesheet + + + + + Displays the tree of widget names in the log (for stylesheet debugging). + + + + + Widget Tree + + + + + Debug information + + + + + Calamares::ExecutionViewStep + + + Set up + + + + + Install + + + + + Calamares::FailJob + + + Job failed (%1) + + + + + Programmed job failure was explicitly requested. + + + + + Calamares::JobThread + + + Done + + + + + Calamares::NamedJob + + + Example job (%1) + + + + + Calamares::ProcessJob + + + Run command '%1' in target system. + + + + + Run command '%1'. + + + + + Running command %1 %2 + + + + + Calamares::PythonJob + + + Running %1 operation. + + + + + Bad working directory path + + + + + Working directory %1 for python job %2 is not readable. + + + + + Bad main script file + + + + + Main script file %1 for python job %2 is not readable. + + + + + Boost.Python error in job "%1". + + + + + Calamares::QmlViewStep + + + Loading ... + + + + + QML Step <i>%1</i>. + + + + + Loading failed. + + + + + Calamares::RequirementsChecker + + + Requirements checking for module <i>%1</i> is complete. + + + + + Waiting for %n module(s). + + + + + + + + (%n second(s)) + + + + + + + + System-requirements checking is complete. + + + + + Calamares::ViewManager + + + Setup Failed + + + + + Installation Failed + + + + + Would you like to paste the install log to the web? + + + + + Error + + + + + &Yes + + + + + &No + + + + + &Close + + + + + Install Log Paste URL + + + + + The upload was unsuccessful. No web-paste was done. + + + + + Install log posted to + +%1 + +Link copied to clipboard + + + + + Calamares Initialization Failed + + + + + %1 can not be installed. Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution. + + + + + <br/>The following modules could not be loaded: + + + + + Continue with setup? + + + + + Continue with installation? + + + + + The %1 setup program is about to make changes to your disk in order to set up %2.<br/><strong>You will not be able to undo these changes.</strong> + + + + + The %1 installer is about to make changes to your disk in order to install %2.<br/><strong>You will not be able to undo these changes.</strong> + + + + + &Set up now + + + + + &Install now + + + + + Go &back + + + + + &Set up + + + + + &Install + + + + + Setup is complete. Close the setup program. + + + + + The installation is complete. Close the installer. + + + + + Cancel setup without changing the system. + + + + + Cancel installation without changing the system. + + + + + &Next + + + + + &Back + + + + + &Done + + + + + &Cancel + + + + + Cancel setup? + + + + + Cancel installation? + + + + + Do you really want to cancel the current setup process? +The setup program will quit and all changes will be lost. + + + + + Do you really want to cancel the current install process? +The installer will quit and all changes will be lost. + + + + + CalamaresPython::Helper + + + Unknown exception type + + + + + unparseable Python error + + + + + unparseable Python traceback + + + + + Unfetchable Python error. + + + + + CalamaresWindow + + + %1 Setup Program + + + + + %1 Installer + + + + + ChangeFilesystemLabelJob + + + Set filesystem label on %1. + + + + + Set filesystem label <strong>%1</strong> to partition <strong>%2</strong>. + + + + + The installer failed to update partition table on disk '%1'. + + + + + CheckerContainer + + + Gathering system information... + + + + + ChoicePage + + + Form + + + + + Select storage de&vice: + + + + + + + + Current: + + + + + After: + + + + + <strong>Manual partitioning</strong><br/>You can create or resize partitions yourself. + + + + + Reuse %1 as home partition for %2. + + + + + <strong>Select a partition to shrink, then drag the bottom bar to resize</strong> + + + + + %1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4. + + + + + Boot loader location: + + + + + <strong>Select a partition to install on</strong> + + + + + An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. + + + + + The EFI system partition at %1 will be used for starting %2. + + + + + EFI system partition: + + + + + This storage device does not seem to have an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + + + + <strong>Erase disk</strong><br/>This will <font color="red">delete</font> all data currently present on the selected storage device. + + + + + + + + <strong>Install alongside</strong><br/>The installer will shrink a partition to make room for %1. + + + + + + + + <strong>Replace a partition</strong><br/>Replaces a partition with %1. + + + + + This storage device has %1 on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device already has an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device has multiple operating systems on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device already has an operating system on it, but the partition table <strong>%1</strong> is different from the needed <strong>%2</strong>.<br/> + + + + + This storage device has one of its partitions <strong>mounted</strong>. + + + + + This storage device is a part of an <strong>inactive RAID</strong> device. + + + + + No Swap + + + + + Reuse Swap + + + + + Swap (no Hibernate) + + + + + Swap (with Hibernate) + + + + + Swap to file + + + + + ClearMountsJob + + + Successfully unmounted %1. + + + + + Successfully disabled swap %1. + + + + + Successfully cleared swap %1. + + + + + Successfully closed mapper device %1. + + + + + Successfully disabled volume group %1. + + + + + Clear mounts for partitioning operations on %1 + + + + + Clearing mounts for partitioning operations on %1. + + + + + Cleared all mounts for %1 + + + + + ClearTempMountsJob + + + Clear all temporary mounts. + + + + + Clearing all temporary mounts. + + + + + Cannot get list of temporary mounts. + + + + + Cleared all temporary mounts. + + + + + CommandList + + + + Could not run command. + + + + + The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined. + + + + + The command needs to know the user's name, but no username is defined. + + + + + Config + + + Set keyboard model to %1.<br/> + + + + + Set keyboard layout to %1/%2. + + + + + Set timezone to %1/%2. + + + + + The system language will be set to %1. + + + + + The numbers and dates locale will be set to %1. + + + + + Network Installation. (Disabled: Incorrect configuration) + + + + + Network Installation. (Disabled: Received invalid groups data) + + + + + Network Installation. (Disabled: Internal error) + + + + + Network Installation. (Disabled: No package list) + + + + + Package selection + + + + + Network Installation. (Disabled: Unable to fetch package lists, check your network connection) + + + + + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. + + + + + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. + + + + + This program will ask you some questions and set up %2 on your computer. + + + + + <h1>Welcome to the Calamares setup program for %1</h1> + + + + + <h1>Welcome to %1 setup</h1> + + + + + <h1>Welcome to the Calamares installer for %1</h1> + + + + + <h1>Welcome to the %1 installer</h1> + + + + + Your username is too long. + + + + + '%1' is not allowed as username. + + + + + Your username must start with a lowercase letter or underscore. + + + + + Only lowercase letters, numbers, underscore and hyphen are allowed. + + + + + Your hostname is too short. + + + + + Your hostname is too long. + + + + + '%1' is not allowed as hostname. + + + + + Only letters, numbers, underscore and hyphen are allowed. + + + + + Your passwords do not match! + + + + + OK! + + + + + Setup Failed + + + + + Installation Failed + + + + + The setup of %1 did not complete successfully. + + + + + The installation of %1 did not complete successfully. + + + + + Setup Complete + + + + + Installation Complete + + + + + The setup of %1 is complete. + + + + + The installation of %1 is complete. + + + + + Package Selection + + + + + Please pick a product from the list. The selected product will be installed. + + + + + Install option: <strong>%1</strong> + + + + + None + + + + + Summary + + + + + This is an overview of what will happen once you start the setup procedure. + + + + + This is an overview of what will happen once you start the install procedure. + + + + + ContextualProcessJob + + + Contextual Processes Job + + + + + CreatePartitionDialog + + + Create a Partition + + + + + Si&ze: + + + + + MiB + + + + + Partition &Type: + + + + + &Primary + + + + + E&xtended + + + + + Fi&le System: + + + + + LVM LV name + + + + + &Mount Point: + + + + + Flags: + + + + + Label for the filesystem + + + + + FS Label: + + + + + En&crypt + + + + + Logical + + + + + Primary + + + + + GPT + + + + + Mountpoint already in use. Please select another one. + + + + + CreatePartitionJob + + + Create new %1MiB partition on %3 (%2) with entries %4. + + + + + Create new %1MiB partition on %3 (%2). + + + + + Create new %2MiB partition on %4 (%3) with file system %1. + + + + + Create new <strong>%1MiB</strong> partition on <strong>%3</strong> (%2) with entries <em>%4</em>. + + + + + Create new <strong>%1MiB</strong> partition on <strong>%3</strong> (%2). + + + + + Create new <strong>%2MiB</strong> partition on <strong>%4</strong> (%3) with file system <strong>%1</strong>. + + + + + + Creating new %1 partition on %2. + + + + + The installer failed to create partition on disk '%1'. + + + + + CreatePartitionTableDialog + + + Create Partition Table + + + + + Creating a new partition table will delete all existing data on the disk. + + + + + What kind of partition table do you want to create? + + + + + Master Boot Record (MBR) + + + + + GUID Partition Table (GPT) + + + + + CreatePartitionTableJob + + + Create new %1 partition table on %2. + + + + + Create new <strong>%1</strong> partition table on <strong>%2</strong> (%3). + + + + + Creating new %1 partition table on %2. + + + + + The installer failed to create a partition table on %1. + + + + + CreateUserJob + + + Create user %1 + + + + + Create user <strong>%1</strong>. + + + + + Preserving home directory + + + + + + Creating user %1 + + + + + Configuring user %1 + + + + + Setting file permissions + + + + + CreateVolumeGroupDialog + + + Create Volume Group + + + + + CreateVolumeGroupJob + + + Create new volume group named %1. + + + + + Create new volume group named <strong>%1</strong>. + + + + + Creating new volume group named %1. + + + + + The installer failed to create a volume group named '%1'. + + + + + DeactivateVolumeGroupJob + + + + Deactivate volume group named %1. + + + + + Deactivate volume group named <strong>%1</strong>. + + + + + The installer failed to deactivate a volume group named %1. + + + + + DeletePartitionJob + + + Delete partition %1. + + + + + Delete partition <strong>%1</strong>. + + + + + Deleting partition %1. + + + + + The installer failed to delete partition %1. + + + + + DeviceInfoWidget + + + This device has a <strong>%1</strong> partition table. + + + + + This is a <strong>loop</strong> device.<br><br>It is a pseudo-device with no partition table that makes a file accessible as a block device. This kind of setup usually only contains a single filesystem. + + + + + This installer <strong>cannot detect a partition table</strong> on the selected storage device.<br><br>The device either has no partition table, or the partition table is corrupted or of an unknown type.<br>This installer can create a new partition table for you, either automatically, or through the manual partitioning page. + + + + + <br><br>This is the recommended partition table type for modern systems which start from an <strong>EFI</strong> boot environment. + + + + + <br><br>This partition table type is only advisable on older systems which start from a <strong>BIOS</strong> boot environment. GPT is recommended in most other cases.<br><br><strong>Warning:</strong> the MBR partition table is an obsolete MS-DOS era standard.<br>Only 4 <em>primary</em> partitions may be created, and of those 4, one can be an <em>extended</em> partition, which may in turn contain many <em>logical</em> partitions. + + + + + The type of <strong>partition table</strong> on the selected storage device.<br><br>The only way to change the partition table type is to erase and recreate the partition table from scratch, which destroys all data on the storage device.<br>This installer will keep the current partition table unless you explicitly choose otherwise.<br>If unsure, on modern systems GPT is preferred. + + + + + DeviceModel + + + %1 - %2 (%3) + device[name] - size[number] (device-node[name]) + + + + + %1 - (%2) + device[name] - (device-node[name]) + + + + + DracutLuksCfgJob + + + Write LUKS configuration for Dracut to %1 + + + + + Skip writing LUKS configuration for Dracut: "/" partition is not encrypted + + + + + Failed to open %1 + + + + + DummyCppJob + + + Dummy C++ Job + + + + + EditExistingPartitionDialog + + + Edit Existing Partition + + + + + Content: + + + + + &Keep + + + + + Format + + + + + Warning: Formatting the partition will erase all existing data. + + + + + &Mount Point: + + + + + Si&ze: + + + + + MiB + + + + + Fi&le System: + + + + + Flags: + + + + + Label for the filesystem + + + + + FS Label: + + + + + Mountpoint already in use. Please select another one. + + + + + EncryptWidget + + + Form + + + + + En&crypt system + + + + + Passphrase + + + + + Confirm passphrase + + + + + + Please enter the same passphrase in both boxes. + + + + + FillGlobalStorageJob + + + Set partition information + + + + + Install %1 on <strong>new</strong> %2 system partition with features <em>%3</em> + + + + + Install %1 on <strong>new</strong> %2 system partition. + + + + + Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong> and features <em>%3</em>. + + + + + Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong>%3. + + + + + Install %2 on %3 system partition <strong>%1</strong> with features <em>%4</em>. + + + + + Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong> and features <em>%4</em>. + + + + + Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong>%4. + + + + + Install %2 on %3 system partition <strong>%1</strong>. + + + + + Install boot loader on <strong>%1</strong>. + + + + + Setting up mount points. + + + + + FinishedPage + + + Form + + + + + &Restart now + + + + + <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. + + + + + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the setup program.</p></body></html> + + + + + <h1>All done.</h1><br/>%1 has been installed on your computer.<br/>You may now restart into your new system, or continue using the %2 Live environment. + + + + + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the installer.</p></body></html> + + + + + <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. + + + + + <h1>Installation Failed</h1><br/>%1 has not been installed on your computer.<br/>The error message was: %2. + + + + + FinishedQmlViewStep + + + Finish + + + + + FinishedViewStep + + + Finish + + + + + FormatPartitionJob + + + Format partition %1 (file system: %2, size: %3 MiB) on %4. + + + + + Format <strong>%3MiB</strong> partition <strong>%1</strong> with file system <strong>%2</strong>. + + + + + Formatting partition %1 with file system %2. + + + + + The installer failed to format partition %1 on disk '%2'. + + + + + GeneralRequirements + + + has at least %1 GiB available drive space + + + + + There is not enough drive space. At least %1 GiB is required. + + + + + has at least %1 GiB working memory + + + + + The system does not have enough working memory. At least %1 GiB is required. + + + + + is plugged in to a power source + + + + + The system is not plugged in to a power source. + + + + + is connected to the Internet + + + + + The system is not connected to the Internet. + + + + + is running the installer as an administrator (root) + + + + + The setup program is not running with administrator rights. + + + + + The installer is not running with administrator rights. + + + + + has a screen large enough to show the whole installer + + + + + The screen is too small to display the setup program. + + + + + The screen is too small to display the installer. + + + + + HostInfoJob + + + Collecting information about your machine. + + + + + IDJob + + + + + + OEM Batch Identifier + + + + + Could not create directories <code>%1</code>. + + + + + Could not open file <code>%1</code>. + + + + + Could not write to file <code>%1</code>. + + + + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + + + InteractiveTerminalPage + + + Konsole not installed + + + + + Please install KDE Konsole and try again! + + + + + Executing script: &nbsp;<code>%1</code> + + + + + InteractiveTerminalViewStep + + + Script + + + + + KeyboardQmlViewStep + + + Keyboard + + + + + KeyboardViewStep + + + Keyboard + + + + + LCLocaleDialog + + + System locale setting + + + + + The system locale setting affects the language and character set for some command line user interface elements.<br/>The current setting is <strong>%1</strong>. + + + + + &Cancel + + + + + &OK + + + + + LicensePage + + + Form + + + + + <h1>License Agreement</h1> + + + + + I accept the terms and conditions above. + + + + + Please review the End User License Agreements (EULAs). + + + + + This setup procedure will install proprietary software that is subject to licensing terms. + + + + + If you do not agree with the terms, the setup procedure cannot continue. + + + + + This setup procedure can install proprietary software that is subject to licensing terms in order to provide additional features and enhance the user experience. + + + + + If you do not agree with the terms, proprietary software will not be installed, and open source alternatives will be used instead. + + + + + LicenseViewStep + + + License + + + + + LicenseWidget + + + URL: %1 + + + + + <strong>%1 driver</strong><br/>by %2 + %1 is an untranslatable product name, example: Creative Audigy driver + + + + + <strong>%1 graphics driver</strong><br/><font color="Grey">by %2</font> + %1 is usually a vendor name, example: Nvidia graphics driver + + + + + <strong>%1 browser plugin</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1 codec</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1 package</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1</strong><br/><font color="Grey">by %2</font> + + + + + File: %1 + + + + + Hide license text + + + + + Show the license text + + + + + Open license agreement in browser. + + + + + LocalePage + + + Region: + + + + + Zone: + + + + + + &Change... + + + + + LocaleQmlViewStep + + + Location + + + + + LocaleTests + + + Quit + + + + + LocaleViewStep + + + Location + + + + + LuksBootKeyFileJob + + + Configuring LUKS key file. + + + + + + No partitions are defined. + + + + + + + Encrypted rootfs setup error + + + + + Root partition %1 is LUKS but no passphrase has been set. + + + + + Could not create LUKS key file for root partition %1. + + + + + Could not configure LUKS key file on partition %1. + + + + + MachineIdJob + + + Generate machine-id. + + + + + Configuration Error + + + + + No root mount point is set for MachineId. + + + + + Map + + + Timezone: %1 + + + + + Please select your preferred location on the map so the installer can suggest the locale + and timezone settings for you. You can fine-tune the suggested settings below. Search the map by dragging + to move and using the +/- buttons to zoom in/out or use mouse scrolling for zooming. + + + + + NetInstallViewStep + + + Package selection + + + + + Office software + + + + + Office package + + + + + Browser software + + + + + Browser package + + + + + Web browser + + + + + Kernel + + + + + Services + + + + + Login + + + + + Desktop + + + + + Applications + + + + + Communication + + + + + Development + + + + + Office + + + + + Multimedia + + + + + Internet + + + + + Theming + + + + + Gaming + + + + + Utilities + + + + + NotesQmlViewStep + + + Notes + + + + + OEMPage + + + Ba&tch: + + + + + <html><head/><body><p>Enter a batch-identifier here. This will be stored in the target system.</p></body></html> + + + + + <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> + + + + + OEMViewStep + + + OEM Configuration + + + + + Set the OEM Batch Identifier to <code>%1</code>. + + + + + Offline + + + Select your preferred Region, or use the default settings. + + + + + + + Timezone: %1 + + + + + Select your preferred Zone within your Region. + + + + + Zones + + + + + You can fine-tune Language and Locale settings below. + + + + + PWQ + + + Password is too short + + + + + Password is too long + + + + + Password is too weak + + + + + Memory allocation error when setting '%1' + + + + + Memory allocation error + + + + + The password is the same as the old one + + + + + The password is a palindrome + + + + + The password differs with case changes only + + + + + The password is too similar to the old one + + + + + The password contains the user name in some form + + + + + The password contains words from the real name of the user in some form + + + + + The password contains forbidden words in some form + + + + + The password contains too few digits + + + + + The password contains too few uppercase letters + + + + + The password contains fewer than %n lowercase letters + + + + + + + + The password contains too few lowercase letters + + + + + The password contains too few non-alphanumeric characters + + + + + The password is too short + + + + + The password does not contain enough character classes + + + + + The password contains too many same characters consecutively + + + + + The password contains too many characters of the same class consecutively + + + + + The password contains fewer than %n digits + + + + + + + + The password contains fewer than %n uppercase letters + + + + + + + + The password contains fewer than %n non-alphanumeric characters + + + + + + + + The password is shorter than %n characters + + + + + + + + The password is a rotated version of the previous one + + + + + The password contains fewer than %n character classes + + + + + + + + The password contains more than %n same characters consecutively + + + + + + + + The password contains more than %n characters of the same class consecutively + + + + + + + + The password contains monotonic sequence longer than %n characters + + + + + + + + The password contains too long of a monotonic character sequence + + + + + No password supplied + + + + + Cannot obtain random numbers from the RNG device + + + + + Password generation failed - required entropy too low for settings + + + + + The password fails the dictionary check - %1 + + + + + The password fails the dictionary check + + + + + Unknown setting - %1 + + + + + Unknown setting + + + + + Bad integer value of setting - %1 + + + + + Bad integer value + + + + + Setting %1 is not of integer type + + + + + Setting is not of integer type + + + + + Setting %1 is not of string type + + + + + Setting is not of string type + + + + + Opening the configuration file failed + + + + + The configuration file is malformed + + + + + Fatal failure + + + + + Unknown error + + + + + Password is empty + + + + + PackageChooserPage + + + Form + + + + + Product Name + + + + + TextLabel + + + + + Long Product Description + + + + + Package Selection + + + + + Please pick a product from the list. The selected product will be installed. + + + + + PackageChooserQmlViewStep + + + Packages + + + + + PackageChooserViewStep + + + Packages + + + + + PackageModel + + + Name + + + + + Description + + + + + Page_Keyboard + + + Form + + + + + Keyboard Model: + + + + + Type here to test your keyboard + + + + + Page_UserSetup + + + Form + + + + + What is your name? + + + + + Your Full Name + + + + + What name do you want to use to log in? + + + + + login + + + + + What is the name of this computer? + + + + + <small>This name will be used if you make the computer visible to others on a network.</small> + + + + + Computer Name + + + + + Choose a password to keep your account safe. + + + + + + <small>Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.</small> + + + + + + Password + + + + + + Repeat Password + + + + + When this box is checked, password-strength checking is done and you will not be able to use a weak password. + + + + + Require strong passwords. + + + + + Log in automatically without asking for the password. + + + + + Use the same password for the administrator account. + + + + + Choose a password for the administrator account. + + + + + + <small>Enter the same password twice, so that it can be checked for typing errors.</small> + + + + + PartitionLabelsView + + + Root + + + + + Home + + + + + Boot + + + + + EFI system + + + + + Swap + + + + + New partition for %1 + + + + + New partition + + + + + %1 %2 + size[number] filesystem[name] + + + + + PartitionModel + + + + Free Space + + + + + + New partition + + + + + Name + + + + + File System + + + + + File System Label + + + + + Mount Point + + + + + Size + + + + + PartitionPage + + + Form + + + + + Storage de&vice: + + + + + &Revert All Changes + + + + + New Partition &Table + + + + + Cre&ate + + + + + &Edit + + + + + &Delete + + + + + New Volume Group + + + + + Resize Volume Group + + + + + Deactivate Volume Group + + + + + Remove Volume Group + + + + + I&nstall boot loader on: + + + + + Are you sure you want to create a new partition table on %1? + + + + + Can not create new partition + + + + + The partition table on %1 already has %2 primary partitions, and no more can be added. Please remove one primary partition and add an extended partition, instead. + + + + + PartitionViewStep + + + Gathering system information... + + + + + Partitions + + + + + Current: + + + + + After: + + + + + No EFI system partition configured + + + + + EFI system partition configured incorrectly + + + + + An EFI system partition is necessary to start %1.<br/><br/>To configure an EFI system partition, go back and select or create a suitable filesystem. + + + + + The filesystem must be mounted on <strong>%1</strong>. + + + + + The filesystem must have type FAT32. + + + + + The filesystem must be at least %1 MiB in size. + + + + + The filesystem must have flag <strong>%1</strong> set. + + + + + You can continue without setting up an EFI system partition but your system may fail to start. + + + + + Option to use GPT on BIOS + + + + + A GPT partition table is the best option for all systems. This installer supports such a setup for BIOS systems too.<br/><br/>To configure a GPT partition table on BIOS, (if not done so already) go back and set the partition table to GPT, next create a 8 MB unformatted partition with the <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT. + + + + + Boot partition not encrypted + + + + + A separate boot partition was set up together with an encrypted root partition, but the boot partition is not encrypted.<br/><br/>There are security concerns with this kind of setup, because important system files are kept on an unencrypted partition.<br/>You may continue if you wish, but filesystem unlocking will happen later during system startup.<br/>To encrypt the boot partition, go back and recreate it, selecting <strong>Encrypt</strong> in the partition creation window. + + + + + has at least one disk device available. + + + + + There are no partitions to install on. + + + + + PlasmaLnfJob + + + Plasma Look-and-Feel Job + + + + + + Could not select KDE Plasma Look-and-Feel package + + + + + PlasmaLnfPage + + + Form + + + + + Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is set up. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. + + + + + Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is installed. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. + + + + + PlasmaLnfViewStep + + + Look-and-Feel + + + + + PreserveFiles + + + Saving files for later ... + + + + + No files configured to save for later. + + + + + Not all of the configured files could be preserved. + + + + + ProcessResult + + + +There was no output from the command. + + + + + +Output: + + + + + + External command crashed. + + + + + Command <i>%1</i> crashed. + + + + + External command failed to start. + + + + + Command <i>%1</i> failed to start. + + + + + Internal error when starting command. + + + + + Bad parameters for process job call. + + + + + External command failed to finish. + + + + + Command <i>%1</i> failed to finish in %2 seconds. + + + + + External command finished with errors. + + + + + Command <i>%1</i> finished with exit code %2. + + + + + QObject + + + %1 (%2) + + + + + unknown + + + + + extended + + + + + unformatted + + + + + swap + + + + + + Default + + + + + + + + File not found + + + + + Path <pre>%1</pre> must be an absolute path. + + + + + Directory not found + + + + + + Could not create new random file <pre>%1</pre>. + + + + + No product + + + + + No description provided. + + + + + (no mount point) + + + + + Unpartitioned space or unknown partition table + + + + + Recommended + + + <p>This computer does not satisfy some of the recommended requirements for setting up %1.<br/> + Setup can continue, but some features might be disabled.</p> + + + + + RemoveUserJob + + + Remove live user from target system + + + + + RemoveVolumeGroupJob + + + + Remove Volume Group named %1. + + + + + Remove Volume Group named <strong>%1</strong>. + + + + + The installer failed to remove a volume group named '%1'. + + + + + ReplaceWidget + + + Form + + + + + Select where to install %1.<br/><font color="red">Warning: </font>this will delete all files on the selected partition. + + + + + The selected item does not appear to be a valid partition. + + + + + %1 cannot be installed on empty space. Please select an existing partition. + + + + + %1 cannot be installed on an extended partition. Please select an existing primary or logical partition. + + + + + %1 cannot be installed on this partition. + + + + + Data partition (%1) + + + + + Unknown system partition (%1) + + + + + %1 system partition (%2) + + + + + <strong>%4</strong><br/><br/>The partition %1 is too small for %2. Please select a partition with capacity at least %3 GiB. + + + + + <strong>%2</strong><br/><br/>An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. + + + + + + + <strong>%3</strong><br/><br/>%1 will be installed on %2.<br/><font color="red">Warning: </font>all data on partition %2 will be lost. + + + + + The EFI system partition at %1 will be used for starting %2. + + + + + EFI system partition: + + + + + Requirements + + + <p>This computer does not satisfy the minimum requirements for installing %1.<br/> + Installation cannot continue.</p> + + + + + <p>This computer does not satisfy some of the recommended requirements for setting up %1.<br/> + Setup can continue, but some features might be disabled.</p> + + + + + ResizeFSJob + + + Resize Filesystem Job + + + + + Invalid configuration + + + + + The file-system resize job has an invalid configuration and will not run. + + + + + KPMCore not Available + + + + + Calamares cannot start KPMCore for the file-system resize job. + + + + + + + + + Resize Failed + + + + + The filesystem %1 could not be found in this system, and cannot be resized. + + + + + The device %1 could not be found in this system, and cannot be resized. + + + + + + The filesystem %1 cannot be resized. + + + + + + The device %1 cannot be resized. + + + + + The filesystem %1 must be resized, but cannot. + + + + + The device %1 must be resized, but cannot + + + + + ResizePartitionJob + + + Resize partition %1. + + + + + Resize <strong>%2MiB</strong> partition <strong>%1</strong> to <strong>%3MiB</strong>. + + + + + Resizing %2MiB partition %1 to %3MiB. + + + + + The installer failed to resize partition %1 on disk '%2'. + + + + + ResizeVolumeGroupDialog + + + Resize Volume Group + + + + + ResizeVolumeGroupJob + + + + Resize volume group named %1 from %2 to %3. + + + + + Resize volume group named <strong>%1</strong> from <strong>%2</strong> to <strong>%3</strong>. + + + + + The installer failed to resize a volume group named '%1'. + + + + + ResultsListDialog + + + For best results, please ensure that this computer: + + + + + System requirements + + + + + ScanningDialog + + + Scanning storage devices... + + + + + Partitioning + + + + + SetHostNameJob + + + Set hostname %1 + + + + + Set hostname <strong>%1</strong>. + + + + + Setting hostname %1. + + + + + + Internal Error + + + + + + Cannot write hostname to target system + + + + + SetKeyboardLayoutJob + + + Set keyboard model to %1, layout to %2-%3 + + + + + Failed to write keyboard configuration for the virtual console. + + + + + + + Failed to write to %1 + + + + + Failed to write keyboard configuration for X11. + + + + + Failed to write keyboard configuration to existing /etc/default directory. + + + + + SetPartFlagsJob + + + Set flags on partition %1. + + + + + Set flags on %1MiB %2 partition. + + + + + Set flags on new partition. + + + + + Clear flags on partition <strong>%1</strong>. + + + + + Clear flags on %1MiB <strong>%2</strong> partition. + + + + + Clear flags on new partition. + + + + + Flag partition <strong>%1</strong> as <strong>%2</strong>. + + + + + Flag %1MiB <strong>%2</strong> partition as <strong>%3</strong>. + + + + + Flag new partition as <strong>%1</strong>. + + + + + Clearing flags on partition <strong>%1</strong>. + + + + + Clearing flags on %1MiB <strong>%2</strong> partition. + + + + + Clearing flags on new partition. + + + + + Setting flags <strong>%2</strong> on partition <strong>%1</strong>. + + + + + Setting flags <strong>%3</strong> on %1MiB <strong>%2</strong> partition. + + + + + Setting flags <strong>%1</strong> on new partition. + + + + + The installer failed to set flags on partition %1. + + + + + SetPasswordJob + + + Set password for user %1 + + + + + Setting password for user %1. + + + + + Bad destination system path. + + + + + rootMountPoint is %1 + + + + + Cannot disable root account. + + + + + passwd terminated with error code %1. + + + + + Cannot set password for user %1. + + + + + usermod terminated with error code %1. + + + + + SetTimezoneJob + + + Set timezone to %1/%2 + + + + + Cannot access selected timezone path. + + + + + Bad path: %1 + + + + + Cannot set timezone. + + + + + Link creation failed, target: %1; link name: %2 + + + + + Cannot set timezone, + + + + + Cannot open /etc/timezone for writing + + + + + SetupGroupsJob + + + Preparing groups. + + + + + + Could not create groups in target system + + + + + These groups are missing in the target system: %1 + + + + + SetupSudoJob + + + Configure <pre>sudo</pre> users. + + + + + Cannot chmod sudoers file. + + + + + Cannot create sudoers file for writing. + + + + + ShellProcessJob + + + Shell Processes Job + + + + + SlideCounter + + + %L1 / %L2 + slide counter, %1 of %2 (numeric) + + + + + StandardButtons + + + &OK + + + + + &Yes + + + + + &No + + + + + &Cancel + + + + + &Close + + + + + TrackingInstallJob + + + Installation feedback + + + + + Sending installation feedback. + + + + + Internal error in install-tracking. + + + + + HTTP request timed out. + + + + + TrackingKUserFeedbackJob + + + KDE user feedback + + + + + Configuring KDE user feedback. + + + + + + Error in KDE user feedback configuration. + + + + + Could not configure KDE user feedback correctly, script error %1. + + + + + Could not configure KDE user feedback correctly, Calamares error %1. + + + + + TrackingMachineUpdateManagerJob + + + Machine feedback + + + + + Configuring machine feedback. + + + + + + Error in machine feedback configuration. + + + + + Could not configure machine feedback correctly, script error %1. + + + + + Could not configure machine feedback correctly, Calamares error %1. + + + + + TrackingPage + + + Form + + + + + Placeholder + + + + + <html><head/><body><p>Click here to send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> + + + + + <html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">Click here for more information about user feedback</span></a></p></body></html> + + + + + Tracking helps %1 to see how often it is installed, what hardware it is installed on and which applications are used. To see what will be sent, please click the help icon next to each area. + + + + + By selecting this you will send information about your installation and hardware. This information will only be sent <b>once</b> after the installation finishes. + + + + + By selecting this you will periodically send information about your <b>machine</b> installation, hardware and applications, to %1. + + + + + By selecting this you will regularly send information about your <b>user</b> installation, hardware, applications and application usage patterns, to %1. + + + + + TrackingViewStep + + + Feedback + + + + + UsersPage + + + <small>If more than one person will use this computer, you can create multiple accounts after setup.</small> + + + + + <small>If more than one person will use this computer, you can create multiple accounts after installation.</small> + + + + + UsersQmlViewStep + + + Users + + + + + UsersViewStep + + + Users + + + + + VariantModel + + + Key + Column header for key/value + + + + + Value + Column header for key/value + + + + + VolumeGroupBaseDialog + + + Create Volume Group + + + + + List of Physical Volumes + + + + + Volume Group Name: + + + + + Volume Group Type: + + + + + Physical Extent Size: + + + + + MiB + + + + + Total Size: + + + + + Used Size: + + + + + Total Sectors: + + + + + Quantity of LVs: + + + + + WelcomePage + + + Form + + + + + + Select application and system language + + + + + &About + + + + + Open donations website + + + + + &Donate + + + + + Open help and support website + + + + + &Support + + + + + Open issues and bug-tracking website + + + + + &Known issues + + + + + Open release notes website + + + + + &Release notes + + + + + <h1>Welcome to the Calamares setup program for %1.</h1> + + + + + <h1>Welcome to %1 setup.</h1> + + + + + <h1>Welcome to the Calamares installer for %1.</h1> + + + + + <h1>Welcome to the %1 installer.</h1> + + + + + %1 support + + + + + About %1 setup + + + + + About %1 installer + + + + + <h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Thanks to <a href="https://calamares.io/team/">the Calamares team</a> and the <a href="https://www.transifex.com/calamares/calamares/">Calamares translators team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> development is sponsored by <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software. + + + + + WelcomeQmlViewStep + + + Welcome + + + + + WelcomeViewStep + + + Welcome + + + + + about + + + <h1>%1</h1><br/> + <strong>%2<br/> + for %3</strong><br/><br/> + Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/> + Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/> + Thanks to <a href='https://calamares.io/team/'>the Calamares team</a> + and the <a href='https://www.transifex.com/calamares/calamares/'>Calamares + translators team</a>.<br/><br/> + <a href='https://calamares.io/'>Calamares</a> + development is sponsored by <br/> + <a href='http://www.blue-systems.com/'>Blue Systems</a> - + Liberating Software. + + + + + Back + + + + + calamares-sidebar + + + Show debug information + + + + + finishedq + + + Installation Completed + + + + + %1 has been installed on your computer.<br/> + You may now restart into your new system, or continue using the Live environment. + + + + + Close Installer + + + + + Restart System + + + + + <p>A full log of the install is available as installation.log in the home directory of the Live user.<br/> + This log is copied to /var/log/installation.log of the target system.</p> + + + + + i18n + + + <h1>Languages</h1> </br> + The system locale setting affects the language and character set for some command line user interface elements. The current setting is <strong>%1</strong>. + + + + + <h1>Locales</h1> </br> + The system locale setting affects the numbers and dates format. The current setting is <strong>%1</strong>. + + + + + Back + + + + + keyboardq + + + To activate keyboard preview, select a layout. + + + + + Keyboard Model: + + + + + Layouts + + + + + Type here to test your keyboard + + + + + Variants + + + + + localeq + + + Change + + + + + notesqml + + + <h3>%1</h3> + <p>These are example release notes.</p> + + + + + packagechooserq + + + LibreOffice is a powerful and free office suite, used by millions of people around the world. It includes several applications that make it the most versatile Free and Open Source office suite on the market.<br/> + Default option. + + + + + LibreOffice + + + + + If you don't want to install an office suite, just select No Office Suite. You can always add one (or more) later on your installed system as the need arrives. + + + + + No Office Suite + + + + + Create a minimal Desktop install, remove all extra applications and decide later on what you would like to add to your system. Examples of what won't be on such an install, there will be no Office Suite, no media players, no image viewer or print support. It will be just a desktop, file browser, package manager, text editor and simple web-browser. + + + + + Minimal Install + + + + + Please select an option for your install, or use the default: LibreOffice included. + + + + + release_notes + + + <h3>%1</h3> + <p>This an example QML file, showing options in RichText with Flickable content.</p> + + <p>QML with RichText can use HTML tags, Flickable content is useful for touchscreens.</p> + + <p><b>This is bold text</b></p> + <p><i>This is italic text</i></p> + <p><u>This is underlined text</u></p> + <p><center>This text will be center-aligned.</center></p> + <p><s>This is strikethrough</s></p> + + <p>Code example: + <code>ls -l /home</code></p> + + <p><b>Lists:</b></p> + <ul> + <li>Intel CPU systems</li> + <li>AMD CPU systems</li> + </ul> + + <p>The vertical scrollbar is adjustable, current width set to 10.</p> + + + + + Back + + + + + usersq + + + Pick your user name and credentials to login and perform admin tasks + + + + + What is your name? + + + + + Your Full Name + + + + + What name do you want to use to log in? + + + + + Login Name + + + + + If more than one person will use this computer, you can create multiple accounts after installation. + + + + + Only lowercase letters, numbers, underscore and hyphen are allowed. + + + + + root is not allowed as username. + + + + + What is the name of this computer? + + + + + Computer Name + + + + + This name will be used if you make the computer visible to others on a network. + + + + + localhost is not allowed as hostname. + + + + + Choose a password to keep your account safe. + + + + + Password + + + + + Repeat Password + + + + + Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals. + + + + + Validate passwords quality + + + + + When this box is checked, password-strength checking is done and you will not be able to use a weak password. + + + + + Log in automatically without asking for the password + + + + + Only letters, numbers, underscore and hyphen are allowed, minimal of two characters. + + + + + Reuse user password as root password + + + + + Use the same password for the administrator account. + + + + + Choose a root password to keep your account safe. + + + + + Root Password + + + + + Repeat Root Password + + + + + Enter the same password twice, so that it can be checked for typing errors. + + + + + welcomeq + + + <h3>Welcome to the %1 <quote>%2</quote> installer</h3> + <p>This program will ask you some questions and set up %1 on your computer.</p> + + + + + About + + + + + Support + + + + + Known issues + + + + + Release notes + + + + + Donate + + + + diff --git a/lang/calamares_vi.ts b/lang/calamares_vi.ts index 9e59b527d..14d93dade 100644 --- a/lang/calamares_vi.ts +++ b/lang/calamares_vi.ts @@ -6,7 +6,7 @@ Manage auto-mount settings - + Quản lý cài đặt tự động gắn kết(auto-mount) @@ -104,22 +104,22 @@ Crashes Calamares, so that Dr. Konqui can look at it. - + Gây crash Calamares, để Dr. Konqui có thể xem nó. Reloads the stylesheet from the branding directory. - + Tải lại stylesheet từ thư mục branding Uploads the session log to the configured pastebin. - + Đăng tải log của phiên này lên pastebin đã được cấu hình Send Session Log - + Gửi log của phiên này @@ -129,7 +129,7 @@ Displays the tree of widget names in the log (for stylesheet debugging). - + Hiễn thị cây của tên widget trong log(để gỡ lỗi stylesheet) diff --git a/lang/python/en_GB/LC_MESSAGES/python.po b/lang/python/en_GB/LC_MESSAGES/python.po index 34fcd2d7a..c2d93d0f8 100644 --- a/lang/python/en_GB/LC_MESSAGES/python.po +++ b/lang/python/en_GB/LC_MESSAGES/python.po @@ -5,6 +5,7 @@ # # Translators: # Jason Collins , 2018 +# Karthik Balan, 2021 # #, fuzzy msgid "" @@ -13,7 +14,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-02 15:45+0100\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Jason Collins , 2018\n" +"Last-Translator: Karthik Balan, 2021\n" "Language-Team: English (United Kingdom) (https://www.transifex.com/calamares/teams/20061/en_GB/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -35,7 +36,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:86 #: src/modules/luksopenswaphookcfg/main.py:90 msgid "Configuration Error" -msgstr "" +msgstr "Configuration Error " #: src/modules/initramfscfg/main.py:86 src/modules/fstab/main.py:356 #: src/modules/initcpiocfg/main.py:228 src/modules/mount/main.py:145 @@ -61,7 +62,7 @@ msgstr "" #: src/modules/bootloader/main.py:508 msgid "Bootloader installation error" -msgstr "" +msgstr "Bootloader installation error" #: src/modules/bootloader/main.py:509 msgid "" @@ -91,7 +92,7 @@ msgstr "" #: src/modules/displaymanager/main.py:526 msgid "Cannot write KDM configuration file" -msgstr "" +msgstr "Cannot write KDM configuration file" #: src/modules/displaymanager/main.py:527 msgid "KDM config file {!s} does not exist" @@ -145,7 +146,7 @@ msgstr "" #: src/modules/services-openrc/main.py:29 msgid "Configure OpenRC services" -msgstr "" +msgstr "Configure OpenRC services" #: src/modules/services-openrc/main.py:57 msgid "Cannot add service {name!s} to run-level {level!s}." @@ -173,7 +174,7 @@ msgstr "" #: src/modules/services-openrc/main.py:101 msgid "Target runlevel does not exist" -msgstr "" +msgstr "Target runlevel does not exist" #: src/modules/services-openrc/main.py:102 msgid "" @@ -193,7 +194,7 @@ msgstr "" #: src/modules/networkcfg/main.py:29 msgid "Saving network configuration." -msgstr "" +msgstr "Saving network configuration " #: src/modules/packages/main.py:50 src/modules/packages/main.py:59 #: src/modules/packages/main.py:69 @@ -222,7 +223,7 @@ msgstr[1] "Removing %(num)d packages." #: src/modules/packages/main.py:638 src/modules/packages/main.py:650 #: src/modules/packages/main.py:678 msgid "Package Manager error" -msgstr "" +msgstr "Package Manager error" #: src/modules/packages/main.py:639 msgid "" diff --git a/lang/python/hi/LC_MESSAGES/python.po b/lang/python/hi/LC_MESSAGES/python.po index c80f08842..00914664c 100644 --- a/lang/python/hi/LC_MESSAGES/python.po +++ b/lang/python/hi/LC_MESSAGES/python.po @@ -319,7 +319,7 @@ msgstr "systemd लक्ष्य {name!s}सक्रिय क #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." -msgstr "" +msgstr "systemd टाइमर {name!s}सक्रिय करना विफल।" #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -399,6 +399,8 @@ msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." msgstr "" +"unsqaushfs खोजने में विफल, सुनिश्चित करें कि squashfs-tools पैकेज इंस्टॉल " +"है।" #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/lang/python/pl/LC_MESSAGES/python.po b/lang/python/pl/LC_MESSAGES/python.po index ea9756e2b..7d4100a03 100644 --- a/lang/python/pl/LC_MESSAGES/python.po +++ b/lang/python/pl/LC_MESSAGES/python.po @@ -4,7 +4,7 @@ # FIRST AUTHOR , YEAR. # # Translators: -# Marcin Mikołajczak , 2017 +# marcin mikołajczak , 2017 # KagiSame, 2018 # Piotr Strębski , 2020 # Jacob B. , 2021 diff --git a/lang/python/ro/LC_MESSAGES/python.po b/lang/python/ro/LC_MESSAGES/python.po index ab6e35e7f..91be0dd5a 100644 --- a/lang/python/ro/LC_MESSAGES/python.po +++ b/lang/python/ro/LC_MESSAGES/python.po @@ -6,6 +6,7 @@ # Translators: # Jobava Jobava , 2018 # Sebastian Brici , 2018 +# Chele Ion , 2021 # #, fuzzy msgid "" @@ -14,7 +15,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-02 15:45+0100\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Sebastian Brici , 2018\n" +"Last-Translator: Chele Ion , 2021\n" "Language-Team: Romanian (https://www.transifex.com/calamares/teams/20061/ro/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -24,7 +25,7 @@ msgstr "" #: src/modules/initramfscfg/main.py:32 msgid "Configuring initramfs." -msgstr "" +msgstr "Configurare initramfs" #: src/modules/initramfscfg/main.py:85 src/modules/initramfscfg/main.py:89 #: src/modules/fstab/main.py:355 src/modules/fstab/main.py:361 @@ -36,21 +37,21 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:86 #: src/modules/luksopenswaphookcfg/main.py:90 msgid "Configuration Error" -msgstr "" +msgstr "Eroare de configurare" #: src/modules/initramfscfg/main.py:86 src/modules/fstab/main.py:356 #: src/modules/initcpiocfg/main.py:228 src/modules/mount/main.py:145 #: src/modules/rawfs/main.py:165 src/modules/openrcdmcryptcfg/main.py:73 #: src/modules/luksopenswaphookcfg/main.py:87 msgid "No partitions are defined for
{!s}
to use." -msgstr "" +msgstr "Nu sunt partiţii definite ca 1{!s}1 ." #: src/modules/initramfscfg/main.py:90 src/modules/fstab/main.py:362 #: src/modules/networkcfg/main.py:106 src/modules/initcpiocfg/main.py:232 #: src/modules/localecfg/main.py:136 src/modules/openrcdmcryptcfg/main.py:77 #: src/modules/luksopenswaphookcfg/main.py:91 msgid "No root mount point is given for
{!s}
to use." -msgstr "" +msgstr "Nu este definită o partiţie rădăcină pentru 1{!s}1 ." #: src/modules/grubcfg/main.py:28 msgid "Configure GRUB." diff --git a/lang/python/ta_IN/LC_MESSAGES/python.po b/lang/python/ta_IN/LC_MESSAGES/python.po new file mode 100644 index 000000000..666703faf --- /dev/null +++ b/lang/python/ta_IN/LC_MESSAGES/python.po @@ -0,0 +1,387 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-11-02 15:45+0100\n" +"PO-Revision-Date: 2017-08-09 10:34+0000\n" +"Language-Team: Tamil (India) (https://www.transifex.com/calamares/teams/20061/ta_IN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta_IN\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/modules/initramfscfg/main.py:32 +msgid "Configuring initramfs." +msgstr "" + +#: src/modules/initramfscfg/main.py:85 src/modules/initramfscfg/main.py:89 +#: src/modules/fstab/main.py:355 src/modules/fstab/main.py:361 +#: src/modules/fstab/main.py:388 src/modules/networkcfg/main.py:105 +#: src/modules/initcpiocfg/main.py:227 src/modules/initcpiocfg/main.py:231 +#: src/modules/localecfg/main.py:135 src/modules/mount/main.py:144 +#: src/modules/rawfs/main.py:164 src/modules/openrcdmcryptcfg/main.py:72 +#: src/modules/openrcdmcryptcfg/main.py:76 +#: src/modules/luksopenswaphookcfg/main.py:86 +#: src/modules/luksopenswaphookcfg/main.py:90 +msgid "Configuration Error" +msgstr "" + +#: src/modules/initramfscfg/main.py:86 src/modules/fstab/main.py:356 +#: src/modules/initcpiocfg/main.py:228 src/modules/mount/main.py:145 +#: src/modules/rawfs/main.py:165 src/modules/openrcdmcryptcfg/main.py:73 +#: src/modules/luksopenswaphookcfg/main.py:87 +msgid "No partitions are defined for
{!s}
to use." +msgstr "" + +#: src/modules/initramfscfg/main.py:90 src/modules/fstab/main.py:362 +#: src/modules/networkcfg/main.py:106 src/modules/initcpiocfg/main.py:232 +#: src/modules/localecfg/main.py:136 src/modules/openrcdmcryptcfg/main.py:77 +#: src/modules/luksopenswaphookcfg/main.py:91 +msgid "No root mount point is given for
{!s}
to use." +msgstr "" + +#: src/modules/grubcfg/main.py:28 +msgid "Configure GRUB." +msgstr "" + +#: src/modules/bootloader/main.py:43 +msgid "Install bootloader." +msgstr "" + +#: src/modules/bootloader/main.py:508 +msgid "Bootloader installation error" +msgstr "" + +#: src/modules/bootloader/main.py:509 +msgid "" +"The bootloader could not be installed. The installation command " +"
{!s}
returned error code {!s}." +msgstr "" + +#: src/modules/fstab/main.py:29 +msgid "Writing fstab." +msgstr "" + +#: src/modules/fstab/main.py:389 +msgid "No
{!s}
configuration is given for
{!s}
to use." +msgstr "" + +#: src/modules/dracut/main.py:27 +msgid "Creating initramfs with dracut." +msgstr "" + +#: src/modules/dracut/main.py:49 +msgid "Failed to run dracut on the target" +msgstr "" + +#: src/modules/dracut/main.py:50 src/modules/mkinitfs/main.py:50 +msgid "The exit code was {}" +msgstr "" + +#: src/modules/displaymanager/main.py:526 +msgid "Cannot write KDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:527 +msgid "KDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:588 +msgid "Cannot write LXDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:589 +msgid "LXDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:672 +msgid "Cannot write LightDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:673 +msgid "LightDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:747 +msgid "Cannot configure LightDM" +msgstr "" + +#: src/modules/displaymanager/main.py:748 +msgid "No LightDM greeter installed." +msgstr "" + +#: src/modules/displaymanager/main.py:779 +msgid "Cannot write SLIM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:780 +msgid "SLIM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:906 +msgid "No display managers selected for the displaymanager module." +msgstr "" + +#: src/modules/displaymanager/main.py:907 +msgid "" +"The displaymanagers list is empty or undefined in both globalstorage and " +"displaymanager.conf." +msgstr "" + +#: src/modules/displaymanager/main.py:989 +msgid "Display manager configuration was incomplete" +msgstr "" + +#: src/modules/services-openrc/main.py:29 +msgid "Configure OpenRC services" +msgstr "" + +#: src/modules/services-openrc/main.py:57 +msgid "Cannot add service {name!s} to run-level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:59 +msgid "Cannot remove service {name!s} from run-level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:61 +msgid "" +"Unknown service-action {arg!s} for service {name!s} in run-" +"level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:93 +#: src/modules/services-systemd/main.py:59 +msgid "Cannot modify service" +msgstr "" + +#: src/modules/services-openrc/main.py:94 +msgid "" +"rc-update {arg!s} call in chroot returned error code {num!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:101 +msgid "Target runlevel does not exist" +msgstr "" + +#: src/modules/services-openrc/main.py:102 +msgid "" +"The path for runlevel {level!s} is {path!s}, which does not " +"exist." +msgstr "" + +#: src/modules/services-openrc/main.py:110 +msgid "Target service does not exist" +msgstr "" + +#: src/modules/services-openrc/main.py:111 +msgid "" +"The path for service {name!s} is {path!s}, which does not " +"exist." +msgstr "" + +#: src/modules/networkcfg/main.py:29 +msgid "Saving network configuration." +msgstr "" + +#: src/modules/packages/main.py:50 src/modules/packages/main.py:59 +#: src/modules/packages/main.py:69 +msgid "Install packages." +msgstr "" + +#: src/modules/packages/main.py:57 +#, python-format +msgid "Processing packages (%(count)d / %(total)d)" +msgstr "" + +#: src/modules/packages/main.py:62 +#, python-format +msgid "Installing one package." +msgid_plural "Installing %(num)d packages." +msgstr[0] "" +msgstr[1] "" + +#: src/modules/packages/main.py:65 +#, python-format +msgid "Removing one package." +msgid_plural "Removing %(num)d packages." +msgstr[0] "" +msgstr[1] "" + +#: src/modules/packages/main.py:638 src/modules/packages/main.py:650 +#: src/modules/packages/main.py:678 +msgid "Package Manager error" +msgstr "" + +#: src/modules/packages/main.py:639 +msgid "" +"The package manager could not prepare updates. The command
{!s}
" +"returned error code {!s}." +msgstr "" + +#: src/modules/packages/main.py:651 +msgid "" +"The package manager could not update the system. The command
{!s}
" +" returned error code {!s}." +msgstr "" + +#: src/modules/packages/main.py:679 +msgid "" +"The package manager could not make changes to the installed system. The " +"command
{!s}
returned error code {!s}." +msgstr "" + +#: src/modules/plymouthcfg/main.py:27 +msgid "Configure Plymouth theme" +msgstr "" + +#: src/modules/initcpiocfg/main.py:28 +msgid "Configuring mkinitcpio." +msgstr "" + +#: src/modules/localecfg/main.py:30 +msgid "Configuring locales." +msgstr "" + +#: src/modules/mount/main.py:30 +msgid "Mounting partitions." +msgstr "" + +#: src/modules/rawfs/main.py:26 +msgid "Installing data." +msgstr "" + +#: src/modules/dummypython/main.py:35 +msgid "Dummy python job." +msgstr "" + +#: src/modules/dummypython/main.py:37 src/modules/dummypython/main.py:93 +#: src/modules/dummypython/main.py:94 +msgid "Dummy python step {}" +msgstr "" + +#: src/modules/hwclock/main.py:26 +msgid "Setting hardware clock." +msgstr "" + +#: src/modules/umount/main.py:31 +msgid "Unmount file systems." +msgstr "" + +#: src/modules/openrcdmcryptcfg/main.py:26 +msgid "Configuring OpenRC dmcrypt service." +msgstr "" + +#: src/modules/services-systemd/main.py:26 +msgid "Configure systemd services" +msgstr "" + +#: src/modules/services-systemd/main.py:60 +msgid "" +"systemctl {arg!s} call in chroot returned error code {num!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:63 +#: src/modules/services-systemd/main.py:69 +msgid "Cannot enable systemd service {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:65 +msgid "Cannot enable systemd target {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:67 +msgid "Cannot enable systemd timer {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:71 +msgid "Cannot disable systemd target {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:73 +msgid "Cannot mask systemd unit {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:75 +msgid "" +"Unknown systemd commands {command!s} and " +"{suffix!s} for unit {name!s}." +msgstr "" + +#: src/modules/mkinitfs/main.py:27 +msgid "Creating initramfs with mkinitfs." +msgstr "" + +#: src/modules/mkinitfs/main.py:49 +msgid "Failed to run mkinitfs on the target" +msgstr "" + +#: src/modules/unpackfs/main.py:34 +msgid "Filling up filesystems." +msgstr "" + +#: src/modules/unpackfs/main.py:254 +msgid "rsync failed with error code {}." +msgstr "" + +#: src/modules/unpackfs/main.py:299 +msgid "Unpacking image {}/{}, file {}/{}" +msgstr "" + +#: src/modules/unpackfs/main.py:314 +msgid "Starting to unpack {}" +msgstr "" + +#: src/modules/unpackfs/main.py:323 src/modules/unpackfs/main.py:465 +msgid "Failed to unpack image \"{}\"" +msgstr "" + +#: src/modules/unpackfs/main.py:430 +msgid "No mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:431 +msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:436 +msgid "Bad mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:437 +msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:453 src/modules/unpackfs/main.py:457 +#: src/modules/unpackfs/main.py:463 src/modules/unpackfs/main.py:478 +msgid "Bad unsquash configuration" +msgstr "" + +#: src/modules/unpackfs/main.py:454 +msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel" +msgstr "" + +#: src/modules/unpackfs/main.py:458 +msgid "The source filesystem \"{}\" does not exist" +msgstr "" + +#: src/modules/unpackfs/main.py:464 +msgid "" +"Failed to find unsquashfs, make sure you have the squashfs-tools package " +"installed." +msgstr "" + +#: src/modules/unpackfs/main.py:479 +msgid "The destination \"{}\" in the target system is not a directory" +msgstr "" + +#: src/modules/luksopenswaphookcfg/main.py:26 +msgid "Configuring encrypted swap." +msgstr "" diff --git a/lang/python/vi/LC_MESSAGES/python.po b/lang/python/vi/LC_MESSAGES/python.po index 900b99454..8948806ae 100644 --- a/lang/python/vi/LC_MESSAGES/python.po +++ b/lang/python/vi/LC_MESSAGES/python.po @@ -5,7 +5,7 @@ # # Translators: # T. Tran , 2020 -# Th1nhhdk, 2021 +# th1nhhdk , 2021 # #, fuzzy msgid "" @@ -14,7 +14,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-02 15:45+0100\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Th1nhhdk, 2021\n" +"Last-Translator: th1nhhdk , 2021\n" "Language-Team: Vietnamese (https://www.transifex.com/calamares/teams/20061/vi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" diff --git a/src/modules/README.md b/src/modules/README.md index 7b4d4b3a3..09696e66b 100644 --- a/src/modules/README.md +++ b/src/modules/README.md @@ -86,18 +86,18 @@ it needs those keys. ### Emergency Modules -Only C++ modules and job modules may be emergency modules. If, during an -*exec* step in the sequence, a module fails, installation as a whole fails -and the install is aborted. If there are emergency modules in the **same** -exec block, those will be executed before the installation is aborted. -Non-emergency modules are not executed. +If, during an *exec* step in the sequence, a module fails, installation as +a whole fails and the install is aborted. If there are emergency modules +in the **same** exec block, those will be executed before the installation +is aborted. Non-emergency modules are not executed. If an emergency-module fails while processing emergency-modules for another failed module, that failure is ignored and emergency-module processing continues. Use the EMERGENCY keyword in the CMake description of a C++ module -to generate a suitable `module.desc`. +to generate a suitable `module.desc`. For Python modules, manually add +`emergency: true` to `module.desc`. A module that is marked as an emergency module in its module.desc must **also** set the *emergency* key to *true* in its configuration file diff --git a/src/modules/luksopenswaphookcfg/CMakeLists.txt b/src/modules/luksopenswaphookcfg/CMakeLists.txt new file mode 100644 index 000000000..caede06a7 --- /dev/null +++ b/src/modules/luksopenswaphookcfg/CMakeLists.txt @@ -0,0 +1,22 @@ +# === This file is part of Calamares - === +# +# SPDX-FileCopyrightText: 2021 Adriaan de Groot +# SPDX-License-Identifier: BSD-2-Clause +# + +# Because LUKS Open Swap Hook (Job) is such a mouthful, we'll +# use LOSH all over the place as a shorthand. +calamares_add_plugin( luksopenswaphookcfg + TYPE job + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + LOSHJob.cpp + SHARED_LIB +) + +calamares_add_test( + luksopenswaphooktest + SOURCES + LOSHJob.cpp + Tests.cpp +) diff --git a/src/modules/luksopenswaphookcfg/LOSHInfo.h b/src/modules/luksopenswaphookcfg/LOSHInfo.h new file mode 100644 index 000000000..1a87f4e61 --- /dev/null +++ b/src/modules/luksopenswaphookcfg/LOSHInfo.h @@ -0,0 +1,66 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ +#ifndef LUKSOPENSWAPHOOKCFG_LOSHINFO_H +#define LUKSOPENSWAPHOOKCFG_LOSHINFO_H + +#include + +/** @brief Information needed to create a suitable config file + * + * The LUKS swap configuration has a handful of keys that need to + * be written to the config file. This struct holds those keys + * and can find the key values from Global Storage (where the + * *partition* module sets them). + */ +struct LOSHInfo +{ + // Member names copied from Python code + QString swap_outer_uuid; + QString swap_mapper_name; + QString mountable_keyfile_device; + QString swap_device_path; + QString keyfile_device_mount_options; + + bool isValid() const { return !swap_device_path.isEmpty(); } + + /** @brief Helper method for doing key-value replacements + * + * Given a named @p key (e.g. "duck", or "swap_device"), returns the + * value set for that key. Invalid keys (e.g. "duck") return an empty string. + */ + QString replacementFor( const QString& key ) const + { + if ( key == QStringLiteral( "swap_device" ) ) + { + return swap_device_path; + } + if ( key == QStringLiteral( "crypt_swap_name" ) ) + { + return swap_mapper_name; + } + if ( key == QStringLiteral( "keyfile_device" ) ) + { + return mountable_keyfile_device; + } + if ( key == QStringLiteral( "keyfile_filename" ) ) + { + return QStringLiteral( "crypto_keyfile.bin" ); + } + if ( key == QStringLiteral( "keyfile_device_mount_options" ) ) + { + return keyfile_device_mount_options; + } + return QString(); + } + + /** @brief Creates a struct from information already set in GS + * + */ + static LOSHInfo fromGlobalStorage(); +}; + +#endif diff --git a/src/modules/luksopenswaphookcfg/LOSHJob.cpp b/src/modules/luksopenswaphookcfg/LOSHJob.cpp new file mode 100644 index 000000000..42f160460 --- /dev/null +++ b/src/modules/luksopenswaphookcfg/LOSHJob.cpp @@ -0,0 +1,181 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ +#include "LOSHJob.h" + +#include "LOSHInfo.h" + +#include "GlobalStorage.h" +#include "JobQueue.h" +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" +#include "utils/Permissions.h" +#include "utils/PluginFactory.h" +#include "utils/String.h" +#include "utils/Variant.h" + +#include +#include +#include +#include + +LOSHJob::LOSHJob( QObject* parent ) + : Calamares::CppJob( parent ) +{ +} + +LOSHJob::~LOSHJob() {} + + +QString +LOSHJob::prettyName() const +{ + return tr( "Configuring encrypted swap." ); +} + +STATICTEST QString +get_assignment_part( const QString& line ) +{ + static QRegularExpression re( "^[# \\t]*([A-Za-z_]+)[ \\t]*=" ); + auto m = re.match( line ); + if ( m.hasMatch() ) + { + return m.captured( 1 ); + } + return QString(); +} + +/** Writes the config file at @p path + * + * NOTE: @p path is relative to the target system, not an absolute path. + */ +STATICTEST void +write_openswap_conf( const QString& path, QStringList& contents, const LOSHInfo& info ) +{ + if ( info.isValid() ) + { + for ( auto& line : contents ) + { + const QString key = get_assignment_part( line ); + QString replacement = info.replacementFor( key ); + if ( !replacement.isEmpty() ) + { + line.clear(); + line.append( QStringLiteral( "%1=%2" ).arg( key, replacement ) ); + } + } + cDebug() << "Writing" << contents.length() << "line configuration to" << path; + // \n between each two lines, and a \n at the end + CalamaresUtils::System::instance()->createTargetFile( + path, contents.join( '\n' ).append( '\n' ).toUtf8(), CalamaresUtils::System::WriteMode::Overwrite ); + } + else + { + cDebug() << "Will not write an invalid configuration to" << path; + } +} + +Calamares::JobResult +LOSHJob::exec() +{ + const auto* sys = CalamaresUtils::System::instance(); + if ( !sys ) + { + return Calamares::JobResult::internalError( + "LuksOpenSwapHook", tr( "No target system available." ), Calamares::JobResult::InvalidConfiguration ); + } + + Calamares::GlobalStorage* gs + = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + if ( !gs || gs->value( "rootMountPoint" ).toString().isEmpty() ) + { + return Calamares::JobResult::internalError( + "LuksOpenSwapHook", tr( "No rootMountPoint is set." ), Calamares::JobResult::InvalidConfiguration ); + } + if ( m_configFilePath.isEmpty() ) + { + return Calamares::JobResult::internalError( + "LuksOpenSwapHook", tr( "No configFilePath is set." ), Calamares::JobResult::InvalidConfiguration ); + } + + QStringList contents = sys->readTargetFile( m_configFilePath ); + if ( contents.isEmpty() ) + { + contents << QStringLiteral( "# swap_device=" ) << QStringLiteral( "# crypt_swap_name=" ) + << QStringLiteral( "# keyfile_device=" ) << QStringLiteral( "# keyfile_filename=" ) + << QStringLiteral( "# keyfile_device_mount_options" ); + } + + write_openswap_conf( m_configFilePath, contents, LOSHInfo::fromGlobalStorage() ); + return Calamares::JobResult::ok(); +} + +void +LOSHJob::setConfigurationMap( const QVariantMap& configurationMap ) +{ + m_configFilePath = CalamaresUtils::getString( + configurationMap, QStringLiteral( "configFilePath" ), QStringLiteral( "/etc/openswap.conf" ) ); +} + +STATICTEST void +globalStoragePartitionInfo( Calamares::GlobalStorage* gs, LOSHInfo& info ) +{ + if ( !gs ) + { + return; + } + QVariantList l = gs->value( "partitions" ).toList(); + if ( l.isEmpty() ) + { + return; + } + + for ( const auto& pv : l ) + { + const QVariantMap partition = pv.toMap(); + if ( !partition.isEmpty() ) + { + QString mountPoint = partition.value( "mountPoint" ).toString(); + QString fileSystem = partition.value( "fs" ).toString(); + QString luksMapperName = partition.value( "luksMapperName" ).toString(); + // if partition["fs"] == "linuxswap" and "luksMapperName" in partition: + if ( fileSystem == QStringLiteral( "linuxswap" ) && !luksMapperName.isEmpty() ) + { + info.swap_outer_uuid = partition.value( "luksUuid" ).toString(); + info.swap_mapper_name = luksMapperName; + } + else if ( mountPoint == QStringLiteral( "/" ) && !luksMapperName.isEmpty() ) + { + + info.mountable_keyfile_device = QStringLiteral( "/dev/mapper/" ) + luksMapperName; + } + } + } + + if ( !info.mountable_keyfile_device.isEmpty() && !info.swap_outer_uuid.isEmpty() ) + { + info.swap_device_path = QStringLiteral( "/dev/disk/by-uuid/" ) + info.swap_outer_uuid; + } + + QString btrfsRootSubvolume = gs->value( "btrfsRootSubvolume" ).toString(); + if ( !btrfsRootSubvolume.isEmpty() ) + { + CalamaresUtils::removeLeading( btrfsRootSubvolume, '/' ); + info.keyfile_device_mount_options + = QStringLiteral( "keyfile_device_mount_options=--options=subvol=" ) + btrfsRootSubvolume; + } +} + +LOSHInfo +LOSHInfo::fromGlobalStorage() +{ + LOSHInfo i {}; + globalStoragePartitionInfo( + Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr, i ); + return i; +} + +CALAMARES_PLUGIN_FACTORY_DEFINITION( LOSHJobFactory, registerPlugin< LOSHJob >(); ) diff --git a/src/modules/luksopenswaphookcfg/LOSHJob.h b/src/modules/luksopenswaphookcfg/LOSHJob.h new file mode 100644 index 000000000..4a435a935 --- /dev/null +++ b/src/modules/luksopenswaphookcfg/LOSHJob.h @@ -0,0 +1,37 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ +#ifndef LUKSOPENSWAPHOOKCFG_LOSHJOB_H +#define LUKSOPENSWAPHOOKCFG_LOSHJOB_H + +#include "CppJob.h" +#include "DllMacro.h" +#include "utils/PluginFactory.h" + +#include +#include + +class PLUGINDLLEXPORT LOSHJob : public Calamares::CppJob +{ + Q_OBJECT + +public: + explicit LOSHJob( QObject* parent = nullptr ); + ~LOSHJob() override; + + QString prettyName() const override; + + Calamares::JobResult exec() override; + + void setConfigurationMap( const QVariantMap& configurationMap ) override; + +private: + QString m_configFilePath; +}; + +CALAMARES_PLUGIN_FACTORY_DECLARATION( LOSHJobFactory ) + +#endif diff --git a/src/modules/luksopenswaphookcfg/Tests.cpp b/src/modules/luksopenswaphookcfg/Tests.cpp new file mode 100644 index 000000000..840bd9355 --- /dev/null +++ b/src/modules/luksopenswaphookcfg/Tests.cpp @@ -0,0 +1,253 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "LOSHInfo.h" +#include "LOSHJob.h" + +#include "GlobalStorage.h" +#include "JobQueue.h" +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" + +#include + +// LOSH = LUKS Open Swap Hook (Job) + +// Implementation details +extern QString get_assignment_part( const QString& line ); +extern void write_openswap_conf( const QString& path, QStringList& contents, const LOSHInfo& info ); + +class LOSHTests : public QObject +{ + Q_OBJECT +public: + LOSHTests(); + ~LOSHTests() override {} + +private Q_SLOTS: + void initTestCase(); + + void testAssignmentExtraction_data(); + void testAssignmentExtraction(); + + void testLOSHInfo(); + void testConfigWriting(); + void testJob(); +}; + +LOSHTests::LOSHTests() {} + +void +LOSHTests::initTestCase() +{ + Logger::setupLogLevel( Logger::LOGDEBUG ); + cDebug() << "LOSH test started."; +} + + +void +LOSHTests::testAssignmentExtraction_data() +{ + QTest::addColumn< QString >( "line" ); + QTest::addColumn< QString >( "match" ); + + QTest::newRow( "empty" ) << QString() << QString(); + QTest::newRow( "comment-only1" ) << QStringLiteral( "# " ) << QString(); + QTest::newRow( "comment-only2" ) << QStringLiteral( "###" ) << QString(); + QTest::newRow( "comment-only3" ) << QStringLiteral( "# # #" ) << QString(); + + QTest::newRow( "comment-text" ) << QStringLiteral( "# NOTE:" ) << QString(); + QTest::newRow( "comment-story" ) << QStringLiteral( "# This is a shell comment" ) << QString(); + // We look for assignments, but only for single-words + QTest::newRow( "comment-space-eq" ) << QStringLiteral( "# Check that a = b" ) << QString(); + + + QTest::newRow( "assignment1" ) << QStringLiteral( "a=1" ) << QStringLiteral( "a" ); + QTest::newRow( "assignment2" ) << QStringLiteral( "a = 1" ) << QStringLiteral( "a" ); + QTest::newRow( "assignment3" ) << QStringLiteral( "# a=1" ) << QStringLiteral( "a" ); + QTest::newRow( "assignment4" ) << QStringLiteral( "cows = 12" ) << QStringLiteral( "cows" ); + QTest::newRow( "assignment5" ) << QStringLiteral( "# # cows=1" ) << QStringLiteral( "cows" ); + QTest::newRow( "assignment6" ) << QStringLiteral( "# moose='cool' # not cows" ) << QStringLiteral( "moose" ); + QTest::newRow( "assignment7" ) << QStringLiteral( " moose=cows=42" ) << QStringLiteral( "moose" ); + QTest::newRow( "assignment8" ) << QStringLiteral( "#swap_device=/dev/something" ) + << QStringLiteral( "swap_device" ); + QTest::newRow( "assignment9" ) << QStringLiteral( "# swap_device=/dev/something" ) + << QStringLiteral( "swap_device" ); + QTest::newRow( "assignment10" ) << QStringLiteral( "swap_device=/dev/something" ) + << QStringLiteral( "swap_device" ); +} + +void +LOSHTests::testAssignmentExtraction() +{ + QFETCH( QString, line ); + QFETCH( QString, match ); + + QCOMPARE( get_assignment_part( line ), match ); +} + +static CalamaresUtils::System* +file_setup( const QTemporaryDir& tempRoot ) +{ + CalamaresUtils::System* ss = CalamaresUtils::System::instance(); + if ( !ss ) + { + ss = new CalamaresUtils::System( true ); + } + + Calamares::GlobalStorage* gs + = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + if ( !gs ) + { + cDebug() << "Creating new JobQueue"; + (void)new Calamares::JobQueue(); + gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + } + if ( gs ) + { + // Working with a rootMountPoint set + gs->insert( "rootMountPoint", tempRoot.path() ); + } + return ss; +} + +static void +make_valid_loshinfo( LOSHInfo& i ) +{ + i.swap_outer_uuid = QStringLiteral( "UUID-0000" ); + i.swap_mapper_name = QStringLiteral( "/dev/mapper/0000" ); + i.swap_device_path = QStringLiteral( "/dev/sda0" ); + i.mountable_keyfile_device = QStringLiteral( "/dev/ada0p0s0" ); +} + +void +LOSHTests::testLOSHInfo() +{ + LOSHInfo i {}; + QVERIFY( !i.isValid() ); + + make_valid_loshinfo( i ); + QVERIFY( i.isValid() ); + QCOMPARE( i.replacementFor( QStringLiteral( "swap_device" ) ), QStringLiteral( "/dev/sda0" ) ); + QCOMPARE( i.replacementFor( QStringLiteral( "duck" ) ), QString() ); +} + + +void +LOSHTests::testConfigWriting() +{ + QTemporaryDir tempRoot( QDir::tempPath() + QStringLiteral( "/test-job-XXXXXX" ) ); + QVERIFY( tempRoot.isValid() ); + auto* ss = file_setup( tempRoot ); + QVERIFY( ss ); + QVERIFY( Calamares::JobQueue::instance()->globalStorage() ); + QVERIFY( QFile::exists( tempRoot.path() ) ); + QVERIFY( QFileInfo( tempRoot.path() ).isDir() ); + + const QString targetFilePath = QStringLiteral( "losh.conf" ); + const QString filePath = tempRoot.filePath( targetFilePath ); + QStringList contents { QStringLiteral( "# Calamares demo" ), + QStringLiteral( "# swap_device=a thing" ), + QStringLiteral( "# duck duck swap_device=another" ) }; + + // When the information is invalid, file contents are unchanged, + // and no file is written either. + LOSHInfo i {}; + QVERIFY( !i.isValid() ); + QVERIFY( !QFile::exists( filePath ) ); + write_openswap_conf( targetFilePath, contents, i ); // Invalid i + QVERIFY( !QFile::exists( filePath ) ); + QCOMPARE( contents.length(), 3 ); + QCOMPARE( contents.at( 1 ).left( 4 ), QStringLiteral( "# s" ) ); + + // Can we write there at all? + QFile derp( filePath ); + QVERIFY( derp.open( QIODevice::WriteOnly ) ); + QVERIFY( derp.write( "xx", 2 ) ); + derp.close(); + QVERIFY( QFile::exists( filePath ) ); + QVERIFY( QFile::remove( filePath ) ); + + // Once the information is valid, though, the file is written + make_valid_loshinfo( i ); + QVERIFY( i.isValid() ); + QVERIFY( !QFile::exists( filePath ) ); + write_openswap_conf( targetFilePath, contents, i ); // Now it is valid + QVERIFY( QFile::exists( filePath ) ); + QCOMPARE( contents.length(), 3 ); + QCOMPARE( i.swap_device_path, QStringLiteral( "/dev/sda0" ) ); // expected key value + QCOMPARE( contents.at( 1 ), QStringLiteral( "swap_device=/dev/sda0" ) ); // expected line + + // readLine() returns with newlines-added + QFile f( filePath ); + QVERIFY( f.open( QIODevice::ReadOnly ) ); + QCOMPARE( f.readLine(), QStringLiteral( "# Calamares demo\n" ) ); + QCOMPARE( f.readLine(), QStringLiteral( "swap_device=/dev/sda0\n" ) ); + QCOMPARE( f.readLine(), QStringLiteral( "# duck duck swap_device=another\n" ) ); + QCOMPARE( f.readLine(), QString() ); + QVERIFY( f.atEnd() ); + + // Note how the contents is updated on every write_openswap_conf() + i.swap_device_path = QStringLiteral( "/dev/zram/0.zram" ); + write_openswap_conf( targetFilePath, contents, i ); // Still valid + QCOMPARE( contents.length(), 3 ); + QCOMPARE( i.swap_device_path, QStringLiteral( "/dev/zram/0.zram" ) ); // expected key value + QCOMPARE( contents.at( 1 ), QStringLiteral( "swap_device=/dev/zram/0.zram" ) ); // expected line +} + + +void +LOSHTests::testJob() +{ + QTemporaryDir tempRoot( QDir::tempPath() + QStringLiteral( "/test-job-XXXXXX" ) ); + QVERIFY( tempRoot.isValid() ); + auto* ss = file_setup( tempRoot ); + QVERIFY( ss ); + Calamares::GlobalStorage* gs + = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + QVERIFY( gs ); + + { + QDir d( tempRoot.path() ); + d.mkdir( "etc" ); + } + + QVERIFY( !LOSHInfo::fromGlobalStorage().isValid() ); + QVariantList outerPartition; + QVariantMap innerPartition; + innerPartition.insert( "mountPoint", "/" ); + innerPartition.insert( "fs", "ext4" ); + innerPartition.insert( "luksMapperName", "root" ); + innerPartition.insert( "luksUUID", "0000" ); + outerPartition.append( innerPartition ); + innerPartition.remove( "mountPoint" ); + innerPartition.insert( "fs", "linuxswap" ); + innerPartition.insert( "luksMapperName", "swap" ); + innerPartition.insert( "luksUuid", "0001" ); + outerPartition.append( innerPartition ); + gs->insert( "partitions", outerPartition ); + QVERIFY( LOSHInfo::fromGlobalStorage().isValid() ); + + LOSHJob j; + j.setConfigurationMap( QVariantMap() ); + auto jobresult = j.exec(); + QVERIFY( jobresult ); + + { + QFile f( tempRoot.filePath( "etc/openswap.conf" ) ); + QVERIFY( f.exists() ); + QVERIFY( f.open( QIODevice::ReadOnly ) ); + cDebug() << f.readAll(); + } +} + + +QTEST_GUILESS_MAIN( LOSHTests ) + +#include "utils/moc-warnings.h" + +#include "Tests.moc" diff --git a/src/modules/luksopenswaphookcfg/main.py b/src/modules/luksopenswaphookcfg/main.py deleted file mode 100644 index aaac8a31a..000000000 --- a/src/modules/luksopenswaphookcfg/main.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2016 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import libcalamares -import os.path - - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Configuring encrypted swap.") - - -def write_openswap_conf(partitions, root_mount_point, openswap_conf_path): - swap_outer_uuid = "" - swap_mapper_name = "" - mountable_keyfile_device = "" - - for partition in partitions: - if partition["fs"] == "linuxswap" and "luksMapperName" in partition: - swap_outer_uuid = partition["luksUuid"] - swap_mapper_name = partition["luksMapperName"] - - elif partition["mountPoint"] == "/" and "luksMapperName" in partition: - mountable_keyfile_device = ( - "/dev/mapper/{!s}".format(partition["luksMapperName"]) - ) - - if not mountable_keyfile_device or not swap_outer_uuid: - return None - - swap_device_path = "/dev/disk/by-uuid/{!s}".format(swap_outer_uuid) - - lines = [] - with open(os.path.join(root_mount_point, - openswap_conf_path), 'r') as openswap_file: - lines = [x.strip() for x in openswap_file.readlines()] - - for i in range(len(lines)): - if lines[i].startswith("swap_device"): - lines[i] = "swap_device={!s}".format(swap_device_path) - - elif lines[i].startswith("crypt_swap_name"): - lines[i] = "crypt_swap_name={!s}".format(swap_mapper_name) - - elif lines[i].startswith("keyfile_device"): - lines[i] = "keyfile_device={!s}".format(mountable_keyfile_device) - - elif lines[i].startswith("keyfile_filename"): - lines[i] = "keyfile_filename=crypto_keyfile.bin" - - elif lines[i].startswith("#keyfile_device_mount_options"): - if libcalamares.globalstorage.contains("btrfsRootSubvolume"): - btrfs_root_subvolume = libcalamares.globalstorage.value("btrfsRootSubvolume") - lines[i] = "keyfile_device_mount_options=--options=subvol=" + btrfs_root_subvolume.lstrip("/") - - with open(os.path.join(root_mount_point, - openswap_conf_path), 'w') as openswap_file: - openswap_file.write("\n".join(lines) + "\n") - - return None - - -def run(): - """ - This module sets up the openswap hook for a resumable encrypted swap. - :return: - """ - - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - openswap_conf_path = libcalamares.job.configuration["configFilePath"] - partitions = libcalamares.globalstorage.value("partitions") - - if not partitions: - libcalamares.utils.warning("partitions is empty, {!s}".format(partitions)) - return (_("Configuration Error"), - _("No partitions are defined for
{!s}
to use.").format("luksopenswaphookcfg")) - if not root_mount_point: - libcalamares.utils.warning("rootMountPoint is empty, {!s}".format(root_mount_point)) - return (_("Configuration Error"), - _("No root mount point is given for
{!s}
to use.").format("luksopenswaphookcfg")) - - openswap_conf_path = openswap_conf_path.lstrip('/') - - return write_openswap_conf(partitions, root_mount_point, openswap_conf_path) diff --git a/src/modules/luksopenswaphookcfg/module.desc b/src/modules/luksopenswaphookcfg/module.desc deleted file mode 100644 index 919a92792..000000000 --- a/src/modules/luksopenswaphookcfg/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "luksopenswaphookcfg" -interface: "python" -script: "main.py" diff --git a/src/modules/partition/core/DeviceList.cpp b/src/modules/partition/core/DeviceList.cpp index c7de12e88..adbbddd68 100644 --- a/src/modules/partition/core/DeviceList.cpp +++ b/src/modules/partition/core/DeviceList.cpp @@ -11,6 +11,7 @@ #include "DeviceList.h" #include "partition/PartitionIterator.h" +#include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" #include @@ -40,16 +41,30 @@ hasRootPartition( Device* device ) return false; } +/** @brief Check if @p path holds an iso9660 filesystem + * + * The @p path should point to a device; blkid is used to check the FS type. + */ static bool blkIdCheckIso9660( const QString& path ) { - QProcess blkid; - blkid.start( "blkid", { path } ); - blkid.waitForFinished(); - QString output = QString::fromLocal8Bit( blkid.readAllStandardOutput() ); - return output.contains( "iso9660" ); + // If blkid fails, there's no output, but we don't care + auto r = CalamaresUtils::System::runCommand( { "blkid", path }, std::chrono::seconds( 30 ) ); + return r.getOutput().contains( "iso9660" ); } +/// @brief Convenience to check if @p partition holds an iso9660 filesystem +static bool +blkIdCheckIso9660P( const Partition* partition ) +{ + return blkIdCheckIso9660( partition->partitionPath() ); +} + +/** @brief Check if the @p device is an iso9660 device + * + * An iso9660 device is **probably** a CD-ROM. If the device holds an + * iso9660 FS, or any of its partitions do, then we call it an iso9660 device. + */ static bool isIso9660( const Device* device ) { @@ -65,13 +80,8 @@ isIso9660( const Device* device ) if ( device->partitionTable() && !device->partitionTable()->children().isEmpty() ) { - for ( const Partition* partition : device->partitionTable()->children() ) - { - if ( blkIdCheckIso9660( partition->partitionPath() ) ) - { - return true; - } - } + const auto& p = device->partitionTable()->children(); + return std::any_of( p.cbegin(), p.cend(), blkIdCheckIso9660P ); } return false; } diff --git a/src/modules/partition/core/KPMHelpers.cpp b/src/modules/partition/core/KPMHelpers.cpp index ed105e28b..d5086ef21 100644 --- a/src/modules/partition/core/KPMHelpers.cpp +++ b/src/modules/partition/core/KPMHelpers.cpp @@ -15,8 +15,8 @@ #include "partition/PartitionIterator.h" #include "utils/Logger.h" +#include "utils/String.h" -// KPMcore #include #include #include @@ -127,4 +127,23 @@ clonePartition( Device* device, Partition* partition ) partition->activeFlags() ); } +Calamares::JobResult +execute( Operation& operation, const QString& failureMessage ) +{ + operation.setStatus( Operation::StatusRunning ); + + Report report( nullptr ); + if ( operation.execute( report ) ) + { + return Calamares::JobResult::ok(); + } + + // Remove the === lines from the report by trimming them to empty + QStringList l = report.toText().split( '\n' ); + std::for_each( l.begin(), l.end(), []( QString& s ) { CalamaresUtils::removeLeading( s, '=' ); } ); + + return Calamares::JobResult::error( failureMessage, l.join( '\n' ) ); +} + + } // namespace KPMHelpers diff --git a/src/modules/partition/core/KPMHelpers.h b/src/modules/partition/core/KPMHelpers.h index 89a019f6c..2f867bc25 100644 --- a/src/modules/partition/core/KPMHelpers.h +++ b/src/modules/partition/core/KPMHelpers.h @@ -11,11 +11,13 @@ #ifndef KPMHELPERS_H #define KPMHELPERS_H -// KPMcore +#include "Job.h" + #include #include +#include +#include -// Qt #include #include @@ -72,6 +74,24 @@ Partition* createNewEncryptedPartition( PartitionNode* parent, Partition* clonePartition( Device* device, Partition* partition ); +/** @brief Return a result for an @p operation + * + * Executes the operation, and if successful, returns a success result. + * Otherwise returns an error using @p failureMessage as the primary part + * of the error, and details obtained from the operation. + */ +Calamares::JobResult execute( Operation& operation, const QString& failureMessage ); +/** @brief Return a result for an @p operation + * + * It's acceptable to use an rvalue: the operation-running is the effect + * you're interested in, rather than keeping the temporary around. + */ +static inline Calamares::JobResult +execute( Operation&& operation, const QString& failureMessage ) +{ + return execute( operation, failureMessage ); +} + } // namespace KPMHelpers #endif /* KPMHELPERS_H */ diff --git a/src/modules/partition/jobs/CreatePartitionJob.cpp b/src/modules/partition/jobs/CreatePartitionJob.cpp index 3e51ed598..fe7c6f350 100644 --- a/src/modules/partition/jobs/CreatePartitionJob.cpp +++ b/src/modules/partition/jobs/CreatePartitionJob.cpp @@ -11,7 +11,9 @@ #include "CreatePartitionJob.h" +#include "core/KPMHelpers.h" #include "core/PartitionInfo.h" + #include "partition/FileSystem.h" #include "partition/PartitionQuery.h" #include "utils/CalamaresUtilsSystem.h" @@ -273,17 +275,9 @@ CreatePartitionJob::exec() return createZfs( m_partition, m_device ); } - Report report( nullptr ); - NewOperation op( *m_device, m_partition ); - op.setStatus( Operation::StatusRunning ); - - QString message = tr( "The installer failed to create partition on disk '%1'." ).arg( m_device->name() ); - if ( op.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - - return Calamares::JobResult::error( message, report.toText() ); + return KPMHelpers::execute( + NewOperation( *m_device, m_partition ), + tr( "The installer failed to create partition on disk '%1'." ).arg( m_device->name() ) ); } void diff --git a/src/modules/partition/jobs/CreatePartitionTableJob.cpp b/src/modules/partition/jobs/CreatePartitionTableJob.cpp index 118ec8823..3b9415d1a 100644 --- a/src/modules/partition/jobs/CreatePartitionTableJob.cpp +++ b/src/modules/partition/jobs/CreatePartitionTableJob.cpp @@ -12,9 +12,11 @@ #include "CreatePartitionTableJob.h" #include "partition/PartitionIterator.h" +#include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" -// KPMcore +#include "core/KPMHelpers.h" + #include #include #include @@ -63,8 +65,6 @@ CreatePartitionTableJob::prettyStatusMessage() const Calamares::JobResult CreatePartitionTableJob::exec() { - Report report( nullptr ); - QString message = tr( "The installer failed to create a partition table on %1." ).arg( m_device->name() ); PartitionTable* table = m_device->partitionTable(); @@ -76,30 +76,16 @@ CreatePartitionTableJob::exec() cDebug() << Logger::SubEntry << ( ( *it ) ? ( *it )->deviceNode() : QString( "" ) ); } - QProcess lsblk; - lsblk.setProgram( "lsblk" ); - lsblk.setProcessChannelMode( QProcess::MergedChannels ); - lsblk.start(); - lsblk.waitForFinished(); - cDebug() << Logger::SubEntry << "lsblk output:\n" << Logger::NoQuote << lsblk.readAllStandardOutput(); + auto lsblkResult = CalamaresUtils::System::runCommand( { "lsblk" }, std::chrono::seconds( 30 ) ); + cDebug() << Logger::SubEntry << "lsblk output:\n" << Logger::NoQuote << lsblkResult.getOutput(); - QProcess mount; - mount.setProgram( "mount" ); // Debug output only, not mounting something - mount.setProcessChannelMode( QProcess::MergedChannels ); - mount.start(); - mount.waitForFinished(); - cDebug() << Logger::SubEntry << "mount output:\n" << Logger::NoQuote << mount.readAllStandardOutput(); + auto mountResult = CalamaresUtils::System::runCommand( { "mount" }, std::chrono::seconds( 30 ) ); + cDebug() << Logger::SubEntry << "mount output:\n" << Logger::NoQuote << mountResult.getOutput(); } - CreatePartitionTableOperation op( *m_device, table ); - op.setStatus( Operation::StatusRunning ); - - if ( op.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - - return Calamares::JobResult::error( message, report.toText() ); + return KPMHelpers::execute( + CreatePartitionTableOperation( *m_device, table ), + tr( "The installer failed to create a partition table on %1." ).arg( m_device->name() ) ); } void diff --git a/src/modules/partition/jobs/CreateVolumeGroupJob.cpp b/src/modules/partition/jobs/CreateVolumeGroupJob.cpp index 36d79b7b7..683913b7f 100644 --- a/src/modules/partition/jobs/CreateVolumeGroupJob.cpp +++ b/src/modules/partition/jobs/CreateVolumeGroupJob.cpp @@ -9,7 +9,8 @@ #include "CreateVolumeGroupJob.h" -// KPMcore +#include "core/KPMHelpers.h" + #include #include #include @@ -46,19 +47,8 @@ CreateVolumeGroupJob::prettyStatusMessage() const Calamares::JobResult CreateVolumeGroupJob::exec() { - Report report( nullptr ); - - CreateVolumeGroupOperation op( m_vgName, m_pvList, m_peSize ); - - op.setStatus( Operation::StatusRunning ); - - QString message = tr( "The installer failed to create a volume group named '%1'." ).arg( m_vgName ); - if ( op.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - - return Calamares::JobResult::error( message, report.toText() ); + return KPMHelpers::execute( CreateVolumeGroupOperation( m_vgName, m_pvList, m_peSize ), + tr( "The installer failed to create a volume group named '%1'." ).arg( m_vgName ) ); } void diff --git a/src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp b/src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp index 92086015d..65920a84e 100644 --- a/src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp +++ b/src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp @@ -9,6 +9,8 @@ #include "DeactivateVolumeGroupJob.h" +#include "core/KPMHelpers.h" + #include #include #include @@ -39,18 +41,12 @@ DeactivateVolumeGroupJob::prettyStatusMessage() const Calamares::JobResult DeactivateVolumeGroupJob::exec() { - Report report( nullptr ); - DeactivateVolumeGroupOperation op( *m_device ); - - op.setStatus( Operation::OperationStatus::StatusRunning ); - - QString message = tr( "The installer failed to deactivate a volume group named %1." ).arg( m_device->name() ); - if ( op.execute( report ) ) + auto r = KPMHelpers::execute( + op, tr( "The installer failed to deactivate a volume group named %1." ).arg( m_device->name() ) ); + if ( r ) { op.preview(); - return Calamares::JobResult::ok(); } - - return Calamares::JobResult::error( message, report.toText() ); + return r; } diff --git a/src/modules/partition/jobs/DeletePartitionJob.cpp b/src/modules/partition/jobs/DeletePartitionJob.cpp index a678b5e90..d61bb955e 100644 --- a/src/modules/partition/jobs/DeletePartitionJob.cpp +++ b/src/modules/partition/jobs/DeletePartitionJob.cpp @@ -10,9 +10,11 @@ */ #include "DeletePartitionJob.h" + +#include "core/KPMHelpers.h" + #include "utils/CalamaresUtilsSystem.h" -// KPMcore #include #include #include @@ -45,7 +47,7 @@ removePartition( Partition* partition ) auto r = CalamaresUtils::System::instance()->runCommand( { "sfdisk", "--delete", "--force", partition->devicePath(), QString::number( partition->number() ) }, std::chrono::seconds( 5 ) ); - if ( r.getExitCode() !=0 || r.getOutput().contains("failed") ) + if ( r.getExitCode() != 0 || r.getOutput().contains( "failed" ) ) { return Calamares::JobResult::error( QCoreApplication::translate( DeletePartitionJob::staticMetaObject.className(), "Deletion Failed" ), @@ -96,17 +98,8 @@ DeletePartitionJob::exec() return removePartition( m_partition ); } - Report report( nullptr ); - DeleteOperation op( *m_device, m_partition ); - op.setStatus( Operation::StatusRunning ); - - QString message = tr( "The installer failed to delete partition %1." ).arg( m_partition->devicePath() ); - if ( op.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - - return Calamares::JobResult::error( message, report.toText() ); + return KPMHelpers::execute( DeleteOperation( *m_device, m_partition ), + tr( "The installer failed to delete partition %1." ).arg( m_partition->devicePath() ) ); } void diff --git a/src/modules/partition/jobs/FormatPartitionJob.cpp b/src/modules/partition/jobs/FormatPartitionJob.cpp index 4dadacf9c..1ccc6e617 100644 --- a/src/modules/partition/jobs/FormatPartitionJob.cpp +++ b/src/modules/partition/jobs/FormatPartitionJob.cpp @@ -11,6 +11,8 @@ #include "FormatPartitionJob.h" +#include "core/KPMHelpers.h" + #include "partition/FileSystem.h" #include "utils/Logger.h" @@ -65,17 +67,7 @@ FormatPartitionJob::prettyStatusMessage() const Calamares::JobResult FormatPartitionJob::exec() { - Report report( nullptr ); // Root of the report tree, no parent - CreateFileSystemOperation op( *m_device, *m_partition, m_partition->fileSystem().type() ); - op.setStatus( Operation::StatusRunning ); - - QString message = tr( "The installer failed to format partition %1 on disk '%2'." ) - .arg( m_partition->partitionPath(), m_device->name() ); - - if ( op.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - - return Calamares::JobResult::error( message, report.toText() ); + return KPMHelpers::execute( CreateFileSystemOperation( *m_device, *m_partition, m_partition->fileSystem().type() ), + tr( "The installer failed to format partition %1 on disk '%2'." ) + .arg( m_partition->partitionPath(), m_device->name() ) ); } diff --git a/src/modules/partition/jobs/RemoveVolumeGroupJob.cpp b/src/modules/partition/jobs/RemoveVolumeGroupJob.cpp index 3c4e7b036..227351064 100644 --- a/src/modules/partition/jobs/RemoveVolumeGroupJob.cpp +++ b/src/modules/partition/jobs/RemoveVolumeGroupJob.cpp @@ -9,6 +9,8 @@ #include "RemoveVolumeGroupJob.h" +#include "core/KPMHelpers.h" + #include #include #include @@ -39,17 +41,7 @@ RemoveVolumeGroupJob::prettyStatusMessage() const Calamares::JobResult RemoveVolumeGroupJob::exec() { - Report report( nullptr ); - - RemoveVolumeGroupOperation op( *m_device ); - - op.setStatus( Operation::OperationStatus::StatusRunning ); - - QString message = tr( "The installer failed to remove a volume group named '%1'." ).arg( m_device->name() ); - if ( op.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - - return Calamares::JobResult::error( message, report.toText() ); + return KPMHelpers::execute( + RemoveVolumeGroupOperation( *m_device ), + tr( "The installer failed to remove a volume group named '%1'." ).arg( m_device->name() ) ); } diff --git a/src/modules/partition/jobs/ResizePartitionJob.cpp b/src/modules/partition/jobs/ResizePartitionJob.cpp index 87b87c1c0..fe1ceca4c 100644 --- a/src/modules/partition/jobs/ResizePartitionJob.cpp +++ b/src/modules/partition/jobs/ResizePartitionJob.cpp @@ -11,9 +11,10 @@ #include "ResizePartitionJob.h" +#include "core/KPMHelpers.h" + #include "utils/Units.h" -// KPMcore #include #include #include @@ -66,23 +67,16 @@ ResizePartitionJob::prettyStatusMessage() const Calamares::JobResult ResizePartitionJob::exec() { - Report report( nullptr ); // Restore partition sectors that were modified for preview m_partition->setFirstSector( m_oldFirstSector ); m_partition->setLastSector( m_oldLastSector ); + ResizeOperation op( *m_device, *m_partition, m_newFirstSector, m_newLastSector ); - op.setStatus( Operation::StatusRunning ); connect( &op, &Operation::progress, this, &ResizePartitionJob::iprogress ); - - QString errorMessage = tr( "The installer failed to resize partition %1 on disk '%2'." ) - .arg( m_partition->partitionPath() ) - .arg( m_device->name() ); - if ( op.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - - return Calamares::JobResult::error( errorMessage, report.toText() ); + return KPMHelpers::execute( op, + tr( "The installer failed to resize partition %1 on disk '%2'." ) + .arg( m_partition->partitionPath() ) + .arg( m_device->name() ) ); } void diff --git a/src/modules/partition/jobs/ResizeVolumeGroupJob.cpp b/src/modules/partition/jobs/ResizeVolumeGroupJob.cpp index 1aa4541b8..f7a21d80d 100644 --- a/src/modules/partition/jobs/ResizeVolumeGroupJob.cpp +++ b/src/modules/partition/jobs/ResizeVolumeGroupJob.cpp @@ -9,7 +9,8 @@ #include "ResizeVolumeGroupJob.h" -// KPMcore +#include "core/KPMHelpers.h" + #include #include #include @@ -51,19 +52,9 @@ ResizeVolumeGroupJob::prettyStatusMessage() const Calamares::JobResult ResizeVolumeGroupJob::exec() { - Report report( nullptr ); - - ResizeVolumeGroupOperation op( *m_device, m_partitionList ); - - op.setStatus( Operation::OperationStatus::StatusRunning ); - - QString message = tr( "The installer failed to resize a volume group named '%1'." ).arg( m_device->name() ); - if ( op.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - - return Calamares::JobResult::error( message, report.toText() ); + return KPMHelpers::execute( + ResizeVolumeGroupOperation( *m_device, m_partitionList ), + tr( "The installer failed to resize a volume group named '%1'." ).arg( m_device->name() ) ); } QString diff --git a/src/modules/partition/jobs/SetPartitionFlagsJob.cpp b/src/modules/partition/jobs/SetPartitionFlagsJob.cpp index de77d86f8..507773288 100644 --- a/src/modules/partition/jobs/SetPartitionFlagsJob.cpp +++ b/src/modules/partition/jobs/SetPartitionFlagsJob.cpp @@ -13,6 +13,8 @@ #include "SetPartitionFlagsJob.h" +#include "core/KPMHelpers.h" + #include "partition/FileSystem.h" #include "utils/Logger.h" #include "utils/Units.h" @@ -148,17 +150,8 @@ SetPartFlagsJob::exec() cDebug() << "Setting flags on" << m_device->deviceNode() << "partition" << partition()->deviceNode() << Logger::DebugList( flagsList ); - Report report( nullptr ); SetPartFlagsOperation op( *m_device, *partition(), m_flags ); - op.setStatus( Operation::StatusRunning ); connect( &op, &Operation::progress, this, &SetPartFlagsJob::iprogress ); - - QString errorMessage - = tr( "The installer failed to set flags on partition %1." ).arg( m_partition->partitionPath() ); - if ( op.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - - return Calamares::JobResult::error( errorMessage, report.toText() ); + return KPMHelpers::execute( + op, tr( "The installer failed to set flags on partition %1." ).arg( m_partition->partitionPath() ) ); }