diff --git a/CHANGES-3.2 b/CHANGES-3.2 index f6222c231..6cf5a99ba 100644 --- a/CHANGES-3.2 +++ b/CHANGES-3.2 @@ -7,7 +7,7 @@ contributors are listed. Note that Calamares does not have a historical changelog -- this log starts with version 3.2.0. The release notes on the website will have to do for older versions. -# 3.2.46 (unreleased) # +# 3.2.48 (unreleased) # This release contains contributions from (alphabetically by first name): - No external contributors yet @@ -19,6 +19,71 @@ This release contains contributions from (alphabetically by first name): - No module changes yet +# 3.2.47 (2021-11-19) # + +This release contains contributions from (alphabetically by first name): + - Evan James + - Jonas Strassel + +## Core ## + - The translation for Sinhala (`si`) has reached 100%. Thank you to + හෙළබස and Sandaruwan, translators for Sinhala, for special effort + in completing that translation. + - Logging now supports Redacted names. This reduces the scope for + leaking names or other private information through the logs + (if they are posted to a pastebin). A name is redacted consistently + within one run of Calamares, but differently each time. + +## Modules ## + - *bootloader* with systemd-boot now handles root subvolumes better + (Thanks Evan) + - *displaymanager* supports the *greetd* display manager, which is a + kind of meta-DM itself, supporting multiple greeters. (Thanks Jonas) + - *finishedq* now has an extra example QML file that builds the UI in + a different fashion, demonstrating how a mobile-OS customization of + Calamares would present the "all done" message. + - *fstab* has an example configuration file that mentioned `space_cache` + as an option. Since 2014 there was only one possible value, so this + option matched the default-and-only value. Newer kernels with newer + btrfs versions have a `v2` option value as well. Remove the example + option, since the kernel automatically picks the right value, while + setting it to the wrong one may prevent the system from booting. + (Thanks Evan) + - The *partition* module no longer logs recognizable disk names or + UUIDs. These are redacted in the logs. #1593 + - The *partition* module, together with the new *zfs* module and changes + in *mount* and *bootloader* can install to ZFS **if** the distribution + kernel supports it. ZFS tools are required, as well as the relevant + kernel modules. See the `README.md` in the *zfs* module. (Thanks Evan) + + +# 3.2.46 (2021-11-09) # + +This release contains contributions from (alphabetically by first name): + - Philip Müller + +## Core ## + - A new core class `Runner` is now responsible for running commands + either in the host or in the target system. This is invisible for + end-users, but **does** expand the API available to consumers inside + Calamares modules. In particular, Python modules can now easily read + and respond to command output. #1740 + +## Modules ## + - *fstab* writes a slightly different message in `/etc/crypttab` + about the root filesystem. Since Calamares itself ignores the + (previous wording of) message, it was confusing. #1811 + - *packages* module has some support for reporting progress while + the packages are installed. This depends on the package-manager itself + reporting useful progress information **and** the *packages* module having + support-code to interpret that progress. A proof-of-concept for `pacman` + has been implemented. #1582 + - *partition* has a number of edge-cases for LVM and LUKS resolved. #1564 #1817 + - *partition* module once again always offers `/boot` as a mount-point, even + when EFI would want `/boot/efi`. (Thanks Phil) + - *summary* had a regression and showed some descriptive texts twice. + + # 3.2.45 (2021-10-31) # This release contains contributions from (alphabetically by first name): diff --git a/CMakeLists.txt b/CMakeLists.txt index b9d570ca4..67bb1f319 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ # TODO:3.3: Require CMake 3.12 cmake_minimum_required( VERSION 3.3 FATAL_ERROR ) project( CALAMARES - VERSION 3.2.46 + VERSION 3.2.48 LANGUAGES C CXX ) @@ -133,12 +133,12 @@ set( CALAMARES_DESCRIPTION_SUMMARY # `txstats.py -e`. See also # # Total 81 languages -set( _tx_complete az az_AZ ca cs_CZ fi_FI he hi hr ja ko lt pt_BR - pt_PT sq sv tr_TR uk zh_CN zh_TW ) -set( _tx_good as be ca@valencia da de fr fur it_IT ml nl ru sk tg - vi ) -set( _tx_ok ar ast bg bn el en_GB es es_MX et eu fa gl hu id is mr - nb pl ro si sl sr sr@latin th ) +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 ) +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 ) diff --git a/calamares.desktop b/calamares.desktop index f7efa41a6..761a7db01 100644 --- a/calamares.desktop +++ b/calamares.desktop @@ -71,8 +71,8 @@ GenericName[eu]=Sistema instalatzailea Comment[eu]=Calamares - sistema instalatzailea Name[fa]=نصب سامانه Icon[fa]=کالامارس -GenericName[fa]=نصب‌کنندهٔ سامانه -Comment[fa]=کالامارس — نصب‌کنندهٔ سامانه +GenericName[fa]=نصب‌کننده سامانه +Comment[fa]=کالامارس — نصب‌کننده سامانه Name[es_PR]=Instalar el sistema Name[fr]=Installer le système Icon[fr]=calamares diff --git a/ci/RELEASE.md b/ci/RELEASE.md index 5289da5af..28e97e4a6 100644 --- a/ci/RELEASE.md +++ b/ci/RELEASE.md @@ -29,7 +29,8 @@ * Double-check the *CALAMARES_VERSION* value at the top of `CMakeLists.txt`. * Set *CALAMARES_RELEASE_MODE* to `ON` in `CMakeLists.txt`. -* Edit `CHANGES` and set the date of the release. +* Edit `CHANGES-*` and set the date of the release. Pick the right + file for the release-stream. * Commit both. This is usually done with commit-message *Changes: pre-release housekeeping*. @@ -81,24 +82,12 @@ Follow the instructions printed by the release script. * Bump the version number in `CMakeLists.txt` in *CALAMARES_VERSION*. * Set *CALAMARES_RELEASE_MODE* back to `OFF`. -* Add a placeholder entry for the next release in `CHANGES` with date - text *not released yet*. +* Add a placeholder entry for the next release in `CHANGES-*` with date + text *not released yet*. See the text below, "Placeholder Release". + Add the placeholder to the right file for the release-stream. * Commit and push that, usually with the message *Changes: post-release housekeeping*. -``` -# 3.2.XX (unreleased) # - -This release contains contributions from (alphabetically by first name): - - No external contributors yet - -## Core ## - - No core changes yet - -## Modules ## - - No module changes yet -``` - # Related Material > This section isn't directly related to any specific release, @@ -139,3 +128,18 @@ ssb rsa3072/0xCFDDC96F12B1915C - Upload that public key to the relevant GitHub profile. - Upload that public key to the Calamares site. +## Placeholder Release Notes + +``` +# 3.2.XX (unreleased) # + +This release contains contributions from (alphabetically by first name): + - No external contributors yet + +## Core ## + - No core changes yet + +## Modules ## + - No module changes yet +``` + diff --git a/ci/configvalidator.py b/ci/configvalidator.py old mode 100644 new mode 100755 diff --git a/ci/libcalamares/utils.py b/ci/libcalamares/utils.py index 706e4a95a..b3676be0f 100644 --- a/ci/libcalamares/utils.py +++ b/ci/libcalamares/utils.py @@ -20,4 +20,8 @@ def target_env_call(_): return 0 def check_target_env_call(_): pass +def target_env_process_output(cmd, *args): return 0 + +def host_env_process_output(cmd, *args): return 0 + def mount(device, mountpoint, fstype, options): return 0 diff --git a/ci/txcheck.sh b/ci/txcheck.sh old mode 100644 new mode 100755 diff --git a/ci/txreduce.py b/ci/txreduce.py old mode 100644 new mode 100755 diff --git a/lang/calamares_az.ts b/lang/calamares_az.ts index 2cd7939e6..2e0af2c63 100644 --- a/lang/calamares_az.ts +++ b/lang/calamares_az.ts @@ -689,27 +689,27 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir. Successfully unmounted %1. - + %1 uğurla ayrıldı. Successfully disabled swap %1. - + %1 mübadilə bölməsi uğurla söndürüldü. Successfully cleared swap %1. - + %1 mübadilə bölməsi uğurla təmizləndi Successfully closed mapper device %1. - + Yerləşdirmə cihazı %1 uğurla bağlandı Successfully disabled volume group %1. - + Tutum qrupu %1, uğurla söndürüldü diff --git a/lang/calamares_az_AZ.ts b/lang/calamares_az_AZ.ts index 1899e20a0..d3d89768a 100644 --- a/lang/calamares_az_AZ.ts +++ b/lang/calamares_az_AZ.ts @@ -689,27 +689,27 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir. Successfully unmounted %1. - + %1 uğurla ayrıldı. Successfully disabled swap %1. - + %1 mübadilə bölməsi uğurla söndürüldü. Successfully cleared swap %1. - + %1 mübadilə bölməsi uğurla təmizləndi Successfully closed mapper device %1. - + Yerləşdirmə cihazı %1 uğurla bağlandı Successfully disabled volume group %1. - + Tutum qrupu %1, uğurla söndürüldü diff --git a/lang/calamares_ca.ts b/lang/calamares_ca.ts index 6facae9d1..cff953e30 100644 --- a/lang/calamares_ca.ts +++ b/lang/calamares_ca.ts @@ -689,27 +689,27 @@ L'instal·lador es tancarà i tots els canvis es perdran. Successfully unmounted %1. - + S'ha desmuntat correctament %1. Successfully disabled swap %1. - + S'ha inhabilitat correctament l'intercanvi %1. Successfully cleared swap %1. - + S'ha netejat correctament l'intercanvi %1. Successfully closed mapper device %1. - + El dispositiu de mapatge %1 s'ha tancat correctament. Successfully disabled volume group %1. - + El grup de volums %1 s'ha inhabilitat correctament. diff --git a/lang/calamares_fa.ts b/lang/calamares_fa.ts index 8f474fd2d..88e516fc8 100644 --- a/lang/calamares_fa.ts +++ b/lang/calamares_fa.ts @@ -6,7 +6,7 @@ Manage auto-mount settings - + مدیریت تنظیمات سوارشدن-خودکار @@ -104,22 +104,22 @@ Crashes Calamares, so that Dr. Konqui can look at it. - + کلامارس کرش میکنه، تا Dr. Konqui بتونه بهش یک نگاهی بندازه. Reloads the stylesheet from the branding directory. - + استایل های مسیر branding را بارگیری مجدد می‌کند. Uploads the session log to the configured pastebin. - + گزارش نشست را به pastebin تنظیم شده بارگذاری میکند. Send Session Log - + ارسال گزارش نشست @@ -129,7 +129,7 @@ Displays the tree of widget names in the log (for stylesheet debugging). - + نمایش درخت نام های ویجت ها در گزارش (برای دیباگ استایل ها). @@ -336,7 +336,11 @@ %1 Link copied to clipboard - + گزارش نصب به پیوند زیر پست شد + +%1 + +پیوند در کلیپ برد رونگاری شد @@ -504,17 +508,17 @@ The installer will quit and all changes will be lost. Set filesystem label on %1. - + تنظیم برچسب سامانه پرونده روی %1. Set filesystem label <strong>%1</strong> to partition <strong>%2</strong>. - + تنظیم عنوان سامانه پرونده <strong>%1</strong> به افراز <strong>%2</strong>. The installer failed to update partition table on disk '%1'. - + نصب کننده برای بروز کردن جدول افراز روی دیسک '%1' شکست خورد. @@ -642,17 +646,17 @@ The installer will quit and all changes will be lost. 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/> - + این دستگاه حافظه هم اکنون یک سیستم عامل روی خود دارد، اما جدول افراز <strong>%1</strong> با نیاز <strong>%2</strong> متفاوت است. This storage device has one of its partitions <strong>mounted</strong>. - + این دستگاه حافظه دارای یک افرازی بوده که هم اکنون <strong>سوارشده</strong> است. This storage device is a part of an <strong>inactive RAID</strong> device. - + یکی از بخش های این دستگاه حافظه عضوی از دستگاه <strong>RAID غیرفعال</strong> است. @@ -685,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 باموفقیت غیرفعال شد. @@ -805,12 +809,12 @@ The installer will quit and all changes will be lost. Network Installation. (Disabled: Internal error) - + نصب شبکه‌ای. (از کار افتاده: خطای داخلی) Network Installation. (Disabled: No package list) - + نصب شبکه ای. (از کار افتاده: بدون فهرست بسته) @@ -875,7 +879,7 @@ The installer will quit and all changes will be lost. '%1' is not allowed as username. - + '%1' بعنوان نام کاربر مجاز نیست. @@ -900,7 +904,7 @@ The installer will quit and all changes will be lost. '%1' is not allowed as hostname. - + '%1' بعنوان نام میزبان مجاز نیست. @@ -915,7 +919,7 @@ The installer will quit and all changes will be lost. OK! - + باشه! @@ -930,12 +934,12 @@ The installer will quit and all changes will be lost. The setup of %1 did not complete successfully. - + برپایی %1 با موفقیت کامل نشد. The installation of %1 did not complete successfully. - + نصب %1 با موفقیت کامل نشد. @@ -970,12 +974,12 @@ The installer will quit and all changes will be lost. Install option: <strong>%1</strong> - + گزینه نصب: <strong>%1</strong> None - + هیچ کدام @@ -985,12 +989,12 @@ The installer will quit and all changes will be lost. 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. - + این یک بررسی از مواردی که بعد از اینکه نصب را شروع کنید، انجام می شوند است. @@ -998,7 +1002,7 @@ The installer will quit and all changes will be lost. Contextual Processes Job - + پردازه های متنی @@ -1056,12 +1060,12 @@ The installer will quit and all changes will be lost. Label for the filesystem - + برچسب برای سامانه پرونده FS Label: - + برچسب سامانه پرونده: @@ -1094,12 +1098,12 @@ The installer will quit and all changes will be lost. Create new %1MiB partition on %3 (%2) with entries %4. - + ایجاد افراز %1 می‌ب جدید روی %3 (%2) با ورودی های %4. Create new %1MiB partition on %3 (%2). - + ایجاد افراز %1 می‌ب جدید روی %3 (%2). @@ -1109,12 +1113,12 @@ The installer will quit and all changes will be lost. Create new <strong>%1MiB</strong> partition on <strong>%3</strong> (%2) with entries <em>%4</em>. - + ایجاد افراز <strong>%1 می‌ب</strong> جدید روی <strong>%3</strong> (%2) با ورودی های <em>%4</em>. Create new <strong>%1MiB</strong> partition on <strong>%3</strong> (%2). - + ایجاد افراز <strong>%1</strong> می‌ب جدید روی <strong>%3</strong> (%2). @@ -1130,7 +1134,7 @@ The installer will quit and all changes will be lost. The installer failed to create partition on disk '%1'. - + نصب کننده برای ساختن افراز روی دیسک '%1' شکست خورد. @@ -1181,7 +1185,7 @@ The installer will quit and all changes will be lost. The installer failed to create a partition table on %1. - + نصب کننده برای ساختن جدول افراز روی %1 شکست خورد. @@ -1199,23 +1203,23 @@ The installer will quit and all changes will be lost. Preserving home directory - + حفظ مسیر خانگی Creating user %1 - + درحال ایجاد کاربر %1 Configuring user %1 - + درحال تنظیم کاربر %1 Setting file permissions - + درحال تنظیم مجوزهای پرونده @@ -1246,7 +1250,7 @@ The installer will quit and all changes will be lost. The installer failed to create a volume group named '%1'. - + نصب کننده برای ساخت گروه حجمی با نام '%1' شکست خورد. @@ -1265,7 +1269,7 @@ The installer will quit and all changes will be lost. The installer failed to deactivate a volume group named %1. - + نصب کننده برای ازکارانداختن گروه حجمی با نام '%1' شکست خورد. @@ -1288,7 +1292,7 @@ The installer will quit and all changes will be lost. The installer failed to delete partition %1. - + نصب کننده برای حذف افراز %1 شکست خورد. @@ -1349,7 +1353,7 @@ The installer will quit and all changes will be lost. Skip writing LUKS configuration for Dracut: "/" partition is not encrypted - + ردشدن از نوشتن تنظیمات LUKS برای Dracut: افراز "/" رمزگذاری نشده است @@ -1420,12 +1424,12 @@ The installer will quit and all changes will be lost. Label for the filesystem - + برچسب برای سامانه پرونده FS Label: - + برچسب سامانه پرونده: @@ -1472,47 +1476,47 @@ The installer will quit and all changes will be lost. Install %1 on <strong>new</strong> %2 system partition with features <em>%3</em> - + نصب %1 روی سامانه افراز %2 <strong>جدید</strong> با امکانات <em>%3</em>. Install %1 on <strong>new</strong> %2 system partition. - + نصب %1 روی سامانه افراز %2 <strong>جدید</strong>. Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong> and features <em>%3</em>. - + برپایی افراز <strong>جدید</strong> %2 با نقطه سوارشدن <strong>%1</strong> و امکانات <em>%3</em>. Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong>%3. - + برپایی افراز <strong>جدید</strong> %2 با نقطه سوارشدن <strong>%1</strong> %3. Install %2 on %3 system partition <strong>%1</strong> with features <em>%4</em>. - + نصب %2 روی <strong>%1</strong> سامانه افراز %3 با امکانات <em>%4</em>. Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong> and features <em>%4</em>. - + برپایی %3 افراز <strong>%1</strong> با نقطه سوارشدن <strong>%2</strong> و امکانات <em>%4</em>. Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong>%4. - + برپایی %3 افراز <strong>%1</strong> با نقطه سوارشدن <strong>%2</strong> %4. Install %2 on %3 system partition <strong>%1</strong>. - + نصب %2 روی <strong>%1</strong> سامانه افراز %3. Install boot loader on <strong>%1</strong>. - + نصب بوت لودر روی <strong>%1</strong>. @@ -1540,7 +1544,7 @@ The installer will quit and all changes will be lost. <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> - هنگامی که این کادر علامت گذاری شد ، هنگامی که بر روی انجام شده کلیک کنید یا برنامه نصب را ببندید ، سیستم شما بلافاصله راه اندازی می شود. + هنگامی که این کادر علامت گذاری شد ، هنگامی که بر روی انجام شده کلیک کنید یا برنامه برپاکننده را ببندید ، سیستم شما بلافاصله راه اندازی می شود. @@ -1555,12 +1559,12 @@ The installer will quit and all changes will be lost. <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. - + <h1>برپایی شکست خورد</h1><br/>%1 روی رایانه شما برپا نشد.<br/>پیام خطا: %2. <h1>Installation Failed</h1><br/>%1 has not been installed on your computer.<br/>The error message was: %2. - + <h1>نصب شکست خورد</h1><br/>%1 روی رایانه شما نصب نشد.<br/>پیام خطا: %2. @@ -1584,22 +1588,22 @@ The installer will quit and all changes will be lost. Format partition %1 (file system: %2, size: %3 MiB) on %4. - + فرمت افراز %1 (سامانه پروانه: %2، اندازه: %3مبی‌بایت) روی %4. Format <strong>%3MiB</strong> partition <strong>%1</strong> with file system <strong>%2</strong>. - + فرمت افراز<strong>%1</strong> با سایز <strong>%3مبی‌بایت</strong> با سامانه پرونده <strong>%2</strong>. Formatting partition %1 with file system %2. - + فرمت افراز %1 با سامانه پروند %2. The installer failed to format partition %1 on disk '%2'. - + نصب کننده برای فرمت افراز %1 روی دیسک '%2' شکست خورد. @@ -1607,22 +1611,22 @@ The installer will quit and all changes will be lost. has at least %1 GiB available drive space - + دارای حداقل %1 گی‌ب فضای کافی There is not enough drive space. At least %1 GiB is required. - + فضای کافی موجود نیست. حداقل %1 گی‌ب نیاز است. has at least %1 GiB working memory - + دارای حداقل %1 گی‌ب مموری کارکننده The system does not have enough working memory. At least %1 GiB is required. - + سامانه مموری کارکننده کافی ندارد. حداقل %1 گی‌ب نیاز است. @@ -1691,7 +1695,7 @@ The installer will quit and all changes will be lost. OEM Batch Identifier - + شناسه Batch اوئی‌ام @@ -1858,27 +1862,27 @@ The installer will quit and all changes will be lost. <strong>%1 graphics driver</strong><br/><font color="Grey">by %2</font> %1 is usually a vendor name, example: Nvidia graphics driver - + <strong>درایور گرافیک %1</strong><br/><font color="Grey">توسط %2</font> <strong>%1 browser plugin</strong><br/><font color="Grey">by %2</font> - + <strong>افزونه مرورگر %1</strong><br/><font color="Grey">توسط %2</font> <strong>%1 codec</strong><br/><font color="Grey">by %2</font> - + <strong>کدک %1</strong><br/><font color="Grey">توسط %2</font> <strong>%1 package</strong><br/><font color="Grey">by %2</font> - + <strong>بسته %1</strong><br/><font color="Grey">توسط %2</font> <strong>%1</strong><br/><font color="Grey">by %2</font> - + <strong>%1</strong><br/><font color="Grey">توسط %2</font> @@ -1933,7 +1937,7 @@ The installer will quit and all changes will be lost. Quit - + خروج @@ -1967,17 +1971,17 @@ The installer will quit and all changes will be lost. Root partition %1 is LUKS but no passphrase has been set. - + افراز روت %1 یک LUKS است، ولی هیچ گذرواژه ای تنظیم نشده است. Could not create LUKS key file for root partition %1. - + نمیتوان پرونده کلید LUKS را برای افراز روت %1 ایجاد کرد. Could not configure LUKS key file on partition %1. - + نمیتوان پرونده کلید LUKS را برای افراز روت %1 تنظیم کرد. @@ -2003,7 +2007,7 @@ The installer will quit and all changes will be lost. Timezone: %1 - + منطقه زمانی: %1 @@ -2124,17 +2128,17 @@ The installer will quit and all changes will be lost. Ba&tch: - + 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><p>اینجا یک شناسه batch وارد کنید. این مقدار در سامانه هدف ذخیره می‌شود.</p></body></html> <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> - + <html><head/><body><h1>تنظیمات اوئی‌ام</h1><p>کلامارس از تنظیمات اوئی‌ام هنگام تنظیم سامانه هدف استفده خواهد کرد.</p></body></html> @@ -2147,7 +2151,7 @@ The installer will quit and all changes will be lost. Set the OEM Batch Identifier to <code>%1</code>. - + تنظیم شناسه Batch اوئی‌ام به <code>%1</code>. @@ -2155,14 +2159,14 @@ The installer will quit and all changes will be lost. Select your preferred Region, or use the default settings. - + منطقه موردنظر خود را انتخاب کنید یا از تنظیمات پیشفرض استفاده کنید. Timezone: %1 - + منطقه زمانی: %1 @@ -2172,12 +2176,12 @@ The installer will quit and all changes will be lost. Zones - + مناطق You can fine-tune Language and Locale settings below. - + شما میتوانید زبان و زبان محلی را در تنظیمات زیر بطوردقیق تنظیم کنید. @@ -2255,9 +2259,9 @@ The installer will quit and all changes will be lost. The password contains fewer than %n lowercase letters - - - + + گذرواژه حاوی کمتر از %n حرف کوچک است + گذرواژه حاوی کمتر از %n حرف کوچک است @@ -2293,70 +2297,70 @@ The installer will quit and all changes will be lost. The password contains fewer than %n digits - - - + + گذرواژه حاوی کمتر از %n عدد است + گذرواژه حاوی کمتر از %n عدد است The password contains fewer than %n uppercase letters - - - + + گذرواژه حاوی کمتر از %n حرف بزرگ است + گذرواژه حاوی کمتر از %n حرف بزرگ است The password contains fewer than %n non-alphanumeric characters - - - + + گذرواژه حاوی کمتر از %n نویسه غیرالفبا است + گذرواژه حاوی کمتر از %n نویسه غیرالفبا است The password is shorter than %n characters - - - + + گذرواژه کوتاه تر از %n نویسه است + گذرواژه کوتاه تر از %n نویسه است The password is a rotated version of the previous one - + گذرواژه یک نسخه برعکس شده از قبلی است The password contains fewer than %n character classes - - - + + گذرواژه حاوی کمتر از %n کلاس نویسه است + گذرواژه حاوی کمتر از %n کلاس نویسه است The password contains more than %n same characters consecutively - - - + + گذرواژه حاوی بیش از %n نویسه پی در پی است + گذرواژه حاوی بیش از %n نویسه پی در پی است The password contains more than %n characters of the same class consecutively - - - + + گذرواژه حاوی بیش از%n نویسه پی در پی از همان کلاس است + گذرواژه حاوی بیش از%n نویسه پی در پی از همان کلاس است The password contains monotonic sequence longer than %n characters - - - + + گذرواژه حاوی یک توالی کاراکتر یکنواخت بیش از %n نویسه است + گذرواژه حاوی یک توالی کاراکتر یکنواخت بیش از %n نویسه است @@ -2382,7 +2386,7 @@ The installer will quit and all changes will be lost. The password fails the dictionary check - %1 - + گذرواژه در بررسی فرهنگ لفت ناموفق است - %1 @@ -2703,7 +2707,7 @@ The installer will quit and all changes will be lost. File System Label - + برچسب سامانه پرونده @@ -2824,37 +2828,37 @@ The installer will quit and all changes will be lost. EFI system partition configured incorrectly - + افراز سامانه EFI به نادرستی تنظیم شده است 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. - + یک افراز سامانه EFI نیازمندست که از %1 شروع شود.<br/><br/>برای تنظیم یک افراز سامانه EFI، به عقب بازگشته و یک سامانه پرونده مناسب انتخاب یا ایجاد کنید. The filesystem must be mounted on <strong>%1</strong>. - + سامانه پرونده باید روی <strong>%1</strong> سوارشده باشد. The filesystem must have type FAT32. - + سامانه پرونده باید دارای نوع FAT32 باشد. The filesystem must be at least %1 MiB in size. - + سامانه پرونده حداقل باید دارای %1مبی‌بایت حجم باشد. The filesystem must have flag <strong>%1</strong> set. - + سامانه پرونده باید پرچم <strong>%1</strong> را دارا باشد. You can continue without setting up an EFI system partition but your system may fail to start. - + شما میتوانید بدون برپاکردن افراز سامانه EFI ادامه دهید ولی ممکن است سامانه برای شروع با مشکل مواجه شود. @@ -2968,7 +2972,7 @@ Output: Command <i>%1</i> crashed. - + دستور <i>%1</i> شکست خورد. @@ -2978,7 +2982,7 @@ Output: Command <i>%1</i> failed to start. - + دستور <i>%1</i> برای شروع شکست خورد. @@ -2998,7 +3002,7 @@ Output: Command <i>%1</i> failed to finish in %2 seconds. - + دستور <i>%1</i> برای اتمام در %2 ثانیه شکست خورد. @@ -3008,7 +3012,7 @@ Output: Command <i>%1</i> finished with exit code %2. - + دستور <i>%1</i> با کد خروج %2 به پایان رسید. @@ -3055,18 +3059,18 @@ Output: Path <pre>%1</pre> must be an absolute path. - + مسیر <pre>%1</pre> باید یک مسیر مطلق باشد. Directory not found - + مسیر یافت نشد Could not create new random file <pre>%1</pre>. - + نمی توان پرونده تصادفی <pre>%1</pre> را ساخت. @@ -3095,7 +3099,8 @@ Output: <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> - + <p>رایانه شما نیازمندی‌های برپاسازی %1 را ندارد. +برپاسازی می‌تواند ادامه یابد، ولی ممکن است برخی ویژگی‌ها از کار افتاده باشند.</p> @@ -3112,17 +3117,17 @@ Output: Remove Volume Group named %1. - + حذف گروه حجمی با نام %1. Remove Volume Group named <strong>%1</strong>. - + حذف گروه حجمی با نام <strong>%1</strong>. The installer failed to remove a volume group named '%1'. - + نصب کننده برای حذف گروه حجمی با نام '%1' شکست خورد. @@ -3135,59 +3140,59 @@ Output: Select where to install %1.<br/><font color="red">Warning: </font>this will delete all files on the selected partition. - + انتخاب کنید که کجا %1 نصب شود.<br/><font color="red">اخطار:</font>این همه پرونده های افراز انتخاب شده را پاک خواهد کرد. The selected item does not appear to be a valid partition. - + بنظر نمی آید که گزینه انتخاب شده، افراز معتبری باشد. %1 cannot be installed on empty space. Please select an existing partition. - + %1 نمیتواند روی فضای خالی نصب شود. لطفا یک افراز موجود را برگزینید. %1 cannot be installed on an extended partition. Please select an existing primary or logical partition. - + %1 نمیتواند روی یک افراز extended نصب شود. لطفا یک افراز primary یا logical برگزینید. %1 cannot be installed on this partition. - + %1 نمیتواند روی این افراز نصب شود. Data partition (%1) - + داده افراز (%1) Unknown system partition (%1) - + سامانه افراز ناشناس (%1) %1 system partition (%2) - + سامانه افراز %1 (%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>%4</strong><br/><br/>افراز %1 برای %2 بسیار کوچک است. لطفا یک افراز با ظرفیت حداقل %3 گیبی‌بایت انتخاب کنید. <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>%2</strong><br/><br/>افراز سامانه EFI نمی‌تواند در هیچ جایی از این سیستم یافت شود. لطفا برگردید و از پارتیشن بندی دستی استفاده کنید تا %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. - + <strong>%3</strong><br/><br/>%1 روی %2 نصب خواهد شد.<br/><font color="red">اخطار:</font>همه داده های افراز %2 از دست خواهند رفت. @@ -3206,13 +3211,15 @@ Output: <p>This computer does not satisfy the minimum requirements for installing %1.<br/> Installation cannot continue.</p> - + <p>رایانه شما نیازمندی های نصب %1 را ندارد.<br/> +نصب نمیتواند ادامه یابد.</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> - + <p>رایانه شما نیازمندی‌های برپاسازی %1 را ندارد. +برپاسازی می‌تواند ادامه یابد، ولی ممکن است برخی ویژگی‌ها از کار افتاده باشند.</p> @@ -3240,7 +3247,7 @@ Output: Calamares cannot start KPMCore for the file-system resize job. - + کلامارس نمیتواند KPMCore را برای کار تغییراندازه فایل سیستم شروع کند. @@ -3254,24 +3261,24 @@ Output: The filesystem %1 could not be found in this system, and cannot be resized. - + فایل سیستم %1 روی این سامانه یافت نشد و نمیتواند تغییر اندازه دهد. The device %1 could not be found in this system, and cannot be resized. - + دستگاه %1 روی این سامانه یافت نشد و نمیتواند تغییراندازه دهد. The filesystem %1 cannot be resized. - + سیستم فایل %1 نمی تواند تغییر اندازه دهد. The device %1 cannot be resized. - + دستگاه %1 نمی تواند تغییر اندازه دهد. @@ -3281,7 +3288,7 @@ Output: The device %1 must be resized, but cannot - + دستگاه %1 باید تغییر اندازه دهد، اما نمی تواند. @@ -3294,17 +3301,17 @@ Output: Resize <strong>%2MiB</strong> partition <strong>%1</strong> to <strong>%3MiB</strong>. - + تغییر اندازه افراز <strong>%1</strong> از <strong>%2مبی‌بایت</strong> به <strong>%3مبی‌بایت</strong>. Resizing %2MiB partition %1 to %3MiB. - + درحال تغییر اندازه افراز %1 از %2مبی‌بایت به %3مبی‌بایت. The installer failed to resize partition %1 on disk '%2'. - + نصب کننده برای تغییر اندازه افراز %1 روی دیسک '%2' شکست خورد. @@ -3321,17 +3328,17 @@ Output: Resize volume group named %1 from %2 to %3. - + تغییر اندازه گروه حجمی با نام %1 از %2 به %3. Resize volume group named <strong>%1</strong> from <strong>%2</strong> to <strong>%3</strong>. - + تغییر اندازه گروه حجمی با نام <strong>%1</strong> از <strong>%2</strong> به <strong>%3</strong>. The installer failed to resize a volume group named '%1'. - + نصب کننده برای تغییر اندازه گروه حجمی با نام '%1' شکست خورد. @@ -3387,7 +3394,7 @@ Output: Cannot write hostname to target system - + عدم توانایی نوشتن نام میزبان به سامانه هدف @@ -3395,29 +3402,29 @@ Output: Set keyboard model to %1, layout to %2-%3 - + تنظیم مدل کیبورد به %1، چیدمان به %2-%3 Failed to write keyboard configuration for the virtual console. - + شکست در نوشتن تنظیمات کیبورد برای کنسول مجازی. Failed to write to %1 - + شکست در نوشتن %1 Failed to write keyboard configuration for X11. - + شکست در نوشتن تنظیمات کیبورد برای X11. Failed to write keyboard configuration to existing /etc/default directory. - + شکست در نوشتن تنظیمات کیبورد به مسیر /etc/default موجود. @@ -3425,27 +3432,27 @@ Output: Set flags on partition %1. - + تنظیم پرچم ها روی افراز %1. Set flags on %1MiB %2 partition. - + تنظیم پرچم ها روی افراز %2 با حجم %1مبی‌بایت. Set flags on new partition. - + تنظیم پرچم ها روی افراز جدید. Clear flags on partition <strong>%1</strong>. - + پاک کردن پرچم ها از افراز <strong>%1</strong>. Clear flags on %1MiB <strong>%2</strong> partition. - + پاک کردن پرچم ها از افراز <strong>%2</strong> با حجم %1مبی‌بایت. @@ -3455,27 +3462,27 @@ Output: Flag partition <strong>%1</strong> as <strong>%2</strong>. - + پرچم گذاری افراز <strong>%1</strong> بعنوان <strong>%2</strong>. Flag %1MiB <strong>%2</strong> partition as <strong>%3</strong>. - + پرچم گذاری افراز <strong>%2</strong> بعنوان <strong>%3</strong> با حجم %1 مبی‌بایت. Flag new partition as <strong>%1</strong>. - + درحال پرچم گذاری افراز جدید بعنوان <strong>%1</strong>. Clearing flags on partition <strong>%1</strong>. - + درحال پاک کردن پرچم ها از افراز <strong>%1</strong>. Clearing flags on %1MiB <strong>%2</strong> partition. - + درحال پاک کردن پرچم ها از افراز <strong>%2</strong> با حجم %1مبی‌بایت. @@ -3485,22 +3492,22 @@ Output: Setting flags <strong>%2</strong> on partition <strong>%1</strong>. - + درحال تنظیم پرچم های <strong>%2</strong> روی افراز <strong>%1</strong>. Setting flags <strong>%3</strong> on %1MiB <strong>%2</strong> partition. - + درحال تنظیم پرچم های <strong>%3</strong> روی افراز <strong>%2</strong> با حجم %1مبی‌بایت. Setting flags <strong>%1</strong> on new partition. - + درحال تنظیم پرچم های <strong>%1</strong> روی افراز جدید. The installer failed to set flags on partition %1. - + نصب کننده برای تنظیم پرچم ها روی افراز %1 شکست خورد. @@ -3513,12 +3520,12 @@ Output: Setting password for user %1. - + درحال تنظیم گذرواژه برای کاربر %1. Bad destination system path. - + مسیر مقصد سامانه بد است. @@ -3533,7 +3540,7 @@ Output: passwd terminated with error code %1. - + passwd با خطای %1 پایان یافت. @@ -3543,7 +3550,7 @@ Output: usermod terminated with error code %1. - + usermod با خطای %1 پایان یافت. @@ -3571,17 +3578,17 @@ Output: Link creation failed, target: %1; link name: %2 - + ساختن پیوند با خطا مواجه شد، هدف: %1؛ پیوند: %2 Cannot set timezone, - + نمی‌توان منطقه زمانی را تنظیم کرد، Cannot open /etc/timezone for writing - + عدم توانایی در باز کردن /etc/timezone برای نوشتن @@ -3589,18 +3596,18 @@ Output: Preparing groups. - + درحال آماده سازی گروه ها. Could not create groups in target system - + عدم توانایی در ساخت گروه ها در سامانه هدف These groups are missing in the target system: %1 - + این گروه ها در سامانه هدف یافت نشدند: %1 @@ -3608,7 +3615,7 @@ Output: Configure <pre>sudo</pre> users. - + کاربران با دسترسی <pre>sudo</pre> را تنظیم کنید. @@ -3626,7 +3633,7 @@ Output: Shell Processes Job - + پردازه های شل @@ -3635,7 +3642,7 @@ Output: %L1 / %L2 slide counter, %1 of %2 (numeric) - + %L1 از %L2 @@ -3681,7 +3688,7 @@ Output: Internal error in install-tracking. - + خطای داخلی در پیگیری نصب رخ داد. @@ -3694,28 +3701,28 @@ Output: KDE user feedback - + بازخورد کاربری KDE Configuring KDE user feedback. - + در حال تنظیم بازخورد کاربری KDE. Error in KDE user feedback configuration. - + خطایی در تنظیمات بازخورد کاربری KDE رخ داد. Could not configure KDE user feedback correctly, script error %1. - + عدم توانایی در تنظیم درست بازخورد کاربری KDE، برنامه با خطای %1 مواجه شد. Could not configure KDE user feedback correctly, Calamares error %1. - + عدم توانایی در تنظیم درست بازخورد کاربری KDE، کلامارس با خطای %1 مواجه شد. @@ -3723,28 +3730,28 @@ Output: Machine feedback - + بازخورد ماشین Configuring machine feedback. - + در حال تنظیم بازخورد ماشین. Error in machine feedback configuration. - + خطایی در تنظیمات بازخورد ماشین رخ داد. Could not configure machine feedback correctly, script error %1. - + عدم توانایی در تنظیم درست بازخورد ماشین، برنامه با خطای %1 مواجه شد. Could not configure machine feedback correctly, Calamares error %1. - + عدم توانایی در تنظیم درست بازخورد ماشین، کلامارس با خطای %1 مواجه شد. @@ -3762,12 +3769,12 @@ Output: <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> این گزینه را برای <span style=" font-weight:600;">نفرستادن هیچگونه اطلاعاتی</span> درباره نصب خودتان انتخاب کنید.</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> - + <html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">برای دریافت اطلاعات بیشتر درمورد بازخورد کاربران اینجا کلیک کنید</span></a></p></body></html> @@ -3777,17 +3784,17 @@ Output: 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. - + با انتخاب این گزینه، شما فقط یکبار داده هایی درباره نصب و سخت افزار خود ارسال می کنید. این داده ها فقط <b>یکبار</b> بعد از به پایان رسیدن نصب فرستاده می شوند. By selecting this you will periodically send information about your <b>machine</b> installation, hardware and applications, to %1. - + با انتخاب این گزینه، شما بطور دوره ای داده هایی درباره نصب <b>ماشین</b>، سخت افزار و برنامه ها را به %1 می فرستید. By selecting this you will regularly send information about your <b>user</b> installation, hardware, applications and application usage patterns, to %1. - + با انتخاب این گزینه، شما بطور منظم داده هایی درباره نصب <b>کاربر</b>، سخت افزار، برنامه ها و الگوی مصرفی برنامه ها را به %1 می فرستید. @@ -3803,12 +3810,12 @@ Output: <small>If more than one person will use this computer, you can create multiple accounts after setup.</small> - + <small>اگر بیش از یک نفر از این کامپیوتر استفاده می کنند، میتوانید حساب های دیگری بعد نصب ایجاد کنید.</small> <small>If more than one person will use this computer, you can create multiple accounts after installation.</small> - + <small>اگر بیش از یک نفر از این کامپیوتر استفاده می کنند، میتوانید حساب های دیگری بعد نصب ایجاد کنید.</small> @@ -3991,7 +3998,7 @@ Output: <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. - + <h1>%1</h1><br/><strong>%2<br/> برای %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/> سپاس از <a href='https://calamares.io/team/'>گروه کلامارس</a> و <a href='https://www.transifex.com/calamares/calamares/'>گروه ترجمه کلامارس</a>.<br/><br/> توسعه <a href='https://calamares.io/'>کلامارس</a> توسط <br/> <a href="http://www.blue-systems.com/"><a href='http://www.blue-systems.com/'>سیستم های آبی</a> - نرم افزار آزادی پشتیبانی شده است. @@ -4026,7 +4033,16 @@ Output: development is sponsored by <br/> <a href='http://www.blue-systems.com/'>Blue Systems</a> - Liberating Software. - + <h1>%1</h1><br/> + <strong>%2<br/> + برای %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/> + سپاس از <a href='https://calamares.io/team/'>گروه کلامارس</a> + و <a href='https://www.transifex.com/calamares/calamares/'>گروه ترجمه کلامارس</a>.<br/><br/> + توسعه <a href='https://calamares.io/'>کلامارس</a> توسط <br/> + <a href='http://www.blue-systems.com/'>سیستم های آبی</a> - + نرم افزار آزادی پشتیبانی شده است. @@ -4047,29 +4063,31 @@ Output: Installation Completed - + نصب کامل شد %1 has been installed on your computer.<br/> You may now restart into your new system, or continue using the Live environment. - + %1 روی رایانه شما نصب شد.<br/> +میتوانید به سامانه جدیدتان وارد شوید، یا به استفاده محیط زنده ادامه دهید. 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> - + <p>یک گزارش کامل از نصب در فایل installation.log درون مسیر خانه کاربر زنده موجود است.<br/> +این گزارش به مسیر /var/log/installation.log سامانه هدف نیز رونوشت شده است.</p> @@ -4078,13 +4096,15 @@ Output: <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>زبان ها</h1></br> + تنظیمات محلی سامانه روی زبان و مجموعه کارکتر برخی از عناصر رابط کاربری خط فرمان تاثیر می گذارد. تنظیمات فعلی <strong>%1</strong> است. <h1>Locales</h1> </br> The system locale setting affects the numbers and dates format. The current setting is <strong>%1</strong>. - + <h1>زبان های محلی</h1> </br> + تنظیمات زبان محلی سامانه قالب اعداد و تاریخ را تغییر می دهد. تنظیمات فعلی <strong>%1</strong> است. @@ -4097,7 +4117,7 @@ Output: To activate keyboard preview, select a layout. - + برای فعال کردن پیشنمایش صفحه کلید، یک چیدمان انتخاب کنید. @@ -4125,7 +4145,7 @@ Output: Change - + تغییر @@ -4134,7 +4154,8 @@ Output: <h3>%1</h3> <p>These are example release notes.</p> - + <h3>%1</h3> + <p>این ها یک سری یادداشت انتشار نمونه هستند.</p> @@ -4143,37 +4164,38 @@ Output: 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 یک مجموعه قدرتمند و آزاد از برنامه های اداری است، که توسط میلیون ها آدم در سراسر دنیا استفاده میشود. این مجموعه شامل برنامه های بسیاری هست که این مجموعه را یک مجموعه برنامه همه کاره آزاد و متن باز در بازار میکند.<br/> +گزینه پیشفرض LibreOffice - + 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. - + لطفا گزینه ای را برای نصب انتخاب کنید، یا از پیشفرض استفاده کنید: LibreOffice @@ -4215,7 +4237,7 @@ Output: Pick your user name and credentials to login and perform admin tasks - + نام کاربری و اطلاعات مهم خود را برای ورود و انجام وظایف مدیریت برگزینید @@ -4235,12 +4257,12 @@ Output: Login Name - + نام ورود If more than one person will use this computer, you can create multiple accounts after installation. - + اگر بیش از یک نفر از این کامپیوتر استفاده می کنند، میتوانید حساب های دیگری بعد نصب ایجاد کنید. @@ -4250,7 +4272,7 @@ Output: root is not allowed as username. - + عبارت root بعنوان نام کاربر مجاز نیست. @@ -4265,12 +4287,12 @@ Output: This name will be used if you make the computer visible to others on a network. - + اگر رایانه‌تان را روی یک شبکه برای دیگران نمایان کنید، از این نام استفاده می‌شود. localhost is not allowed as hostname. - + عبارت localhost بعنوان نام میزبان مجاز نیست. @@ -4295,7 +4317,7 @@ Output: Validate passwords quality - + اعتبارسنجی کیفیت گذرواژه @@ -4305,17 +4327,17 @@ Output: 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 - + استفاده گذرواژه کاربر بعنوان گذرواژه روت @@ -4325,22 +4347,22 @@ Output: 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. - + همان گذرواژه را دوباره وارد کنید تا بتواند برای خطاهای نوشتاری بررسی شود. @@ -4349,7 +4371,8 @@ Output: <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> - + <h3>به نصب کننده %1 <quote>%2</quote>خوش آمدید</h3> +<p>این برنامه از شما سوالایی میپرسد و %1 را روی رایانه شما نصب می کند.</p> diff --git a/lang/calamares_hr.ts b/lang/calamares_hr.ts index 214d1be93..62d1d1ef1 100644 --- a/lang/calamares_hr.ts +++ b/lang/calamares_hr.ts @@ -691,27 +691,27 @@ Instalacijski program će izaći i sve promjene će biti izgubljene. Successfully unmounted %1. - + Uspješno demontiran %1. Successfully disabled swap %1. - + Uspješno onemogućen swap %1. Successfully cleared swap %1. - + Uspješno obrisan swap %1. Successfully closed mapper device %1. - + Uspješno zatvoren device mapper %1. Successfully disabled volume group %1. - + Volume grupa %1 je uspješno onemogućena. diff --git a/lang/calamares_ko.ts b/lang/calamares_ko.ts index d93bde150..607f34e6c 100644 --- a/lang/calamares_ko.ts +++ b/lang/calamares_ko.ts @@ -687,27 +687,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_pt_PT.ts b/lang/calamares_pt_PT.ts index 802f0810e..dbbc088a9 100644 --- a/lang/calamares_pt_PT.ts +++ b/lang/calamares_pt_PT.ts @@ -689,27 +689,27 @@ O instalador será encerrado e todas as alterações serão perdidas. Successfully unmounted %1. - + % 1 desmontado com sucesso. Successfully disabled swap %1. - + Swap %1 desativada com sucesso. Successfully cleared swap %1. - + Swap % 1 limpa com sucesso. Successfully closed mapper device %1. - + Dispositivo mapeador % 1 fechado com sucesso. Successfully disabled volume group %1. - + Grupo de volume % 1 desativado com sucesso. diff --git a/lang/calamares_si.ts b/lang/calamares_si.ts index 309b4a953..3d68cc26e 100644 --- a/lang/calamares_si.ts +++ b/lang/calamares_si.ts @@ -689,27 +689,27 @@ The installer will quit and all changes will be lost. Successfully unmounted %1. - + %1 සාර්ථකව ඉවත් කරන ලදී. Successfully disabled swap %1. - + swap % 1 සාර්ථකව අක්‍රීය කරන ලදී. Successfully cleared swap %1. - + swap %1 සාර්ථකව හිස් කරන ලදී. Successfully closed mapper device %1. - + සිතියම් උපාංගය %1 සාර්ථකව වසා ඇත. Successfully disabled volume group %1. - + %1 වෙළුම් සමූහය සාර්ථකව ක්‍රියා කරයි. @@ -1315,17 +1315,17 @@ The installer will quit and all changes will be lost. <br><br>This is the recommended partition table type for modern systems which start from an <strong>EFI</strong> boot environment. - + <br><br><strong>EFI</strong> ඇරඹුම් පරිසරයකින් ආරම්භ වන නවීන පද්ධති සඳහා නිර්දේශිත කොටස් වගු වර්ගය මෙයයි. <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. - + <br><br>මෙම කොටස් වගු වර්ගය සුදුසු වන්නේ <strong>BIOS</strong> ඇරඹුම් පරිසරයකින් ආරම්භ වන පැරණි පද්ධති සඳහා පමණි. අනෙකුත් බොහෝ අවස්ථාවන්හිදී GPT නිර්දේශ කෙරේ. <br><br><strong>අවවාදයයි:</strong> MBR කොටස් වගුව යල් පැන ගිය MS-DOS යුගයේ සම්මතයකි. <br><em>ප්‍රධාන</em> කොටස් 4ක් පමණක් සෑදිය හැකි අතර, එම 4න් එකක් <strong>දීර්ඝ</strong> කළ කොටසක් විය හැක, එහි බොහෝ <strong>තාර්කික</strong> කොටස් අඩංගු විය හැක. 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. - + තෝරාගත් ගබඩා උපාංගයේ <strong>කොටස් වගුවේ</strong> වර්ගය. <br>කොටස් වගු වර්ගය වෙනස් කිරීමට ඇති එකම ක්‍රමය නම් ගබඩා උපාංගයේ ඇති සියලුම දත්ත විනාශ කරන කොටස් වගුව මුල සිට මකා ප්‍රතිනිර්මාණය කිරීමයි. <br>මෙම ස්ථාපකය ඔබ වෙනත් ආකාරයකින් තෝරා ගන්නේ නම් මිස වත්මන් කොටස් වගුව තබා ගනී. <br>විශ්වාස නැත්නම්, නවීන පද්ධති GPT මත මනාප වේ. @@ -1348,17 +1348,17 @@ The installer will quit and all changes will be lost. Write LUKS configuration for Dracut to %1 - + Dracut සඳහා LUKS වින්‍යාසය %1 වෙත ලියන්න Skip writing LUKS configuration for Dracut: "/" partition is not encrypted - + Dracut සඳහා LUKS වින්‍යාසය ලිවීම මඟ හරින්න: "/" කොටස සංකේතනය කර නොමැත Failed to open %1 - + %1 විවෘත කිරීමට අසමත් විය @@ -1366,7 +1366,7 @@ The installer will quit and all changes will be lost. Dummy C++ Job - + ව්‍යාජ C++ ක්‍රියවලියක් @@ -1374,27 +1374,27 @@ The installer will quit and all changes will be lost. Edit Existing Partition - + පවතින කොටසක් සංස්කරණය කරන්න Content: - + අන්තර්ගතය: &Keep - + තබා ගන්න (&K) Format - + මකා දමන්න Warning: Formatting the partition will erase all existing data. - + අවවාදයයි: කොටස මැකීමෙන් පවතින සියලුම දත්ත ඉවත්වනු ඇත. @@ -1447,23 +1447,23 @@ The installer will quit and all changes will be lost. En&crypt system - + පද්ධතිය සංකේතනය (&C) කරන්න Passphrase - + මුරපදය Confirm passphrase - + මුරපදය තහවුරු කරන්න Please enter the same passphrase in both boxes. - + කරුණාකර කොටු දෙකෙහිම එකම මුර-වැකිකඩ ඇතුලත් කරන්න. @@ -1471,57 +1471,57 @@ The installer will quit and all changes will be lost. Set partition information - + කොටස් තොරතුරු සකසන්න Install %1 on <strong>new</strong> %2 system partition with features <em>%3</em> - + <strong>%3</strong> විශේෂාංග සහිත <strong>නව</strong> %2 පද්ධති කොටසේ %1 ස්ථාපනය කරන්න Install %1 on <strong>new</strong> %2 system partition. - + <strong>නව</strong> %2 පද්ධති කොටසෙහි %1 ස්ථාපනය කරන්න. Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong> and features <em>%3</em>. - + <strong>නව</strong> %2 කොටස සවිකිරීමේ ලක්ෂ්‍යය <strong>%1</strong> සහ විශේෂාංග <strong>%3</strong> සමඟ සකසන්න Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong>%3. - + <strong>නව</strong> %2 කොටස සවිකිරීමේ ලක්ෂ්‍යය <strong>%1</strong>%3 සමඟ සකසන්න. Install %2 on %3 system partition <strong>%1</strong> with features <em>%4</em>. - + <strong>%4</strong> විශේෂාංග සහිත %3 පද්ධති කොටස <strong>%1</strong> මත %2 ස්ථාපනය කරන්න. Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong> and features <em>%4</em>. - + %3 කොටස සකසන්න <strong>%1</strong> සවිකිරීමේ ලක්ෂ්‍යය <strong>%2</strong> සහ විශේෂාංග <strong>%4</strong> සමඟින්. Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong>%4. - + %3 කොටස <strong>%1</strong> සවිකිරීමේ ලක්ෂ්‍යය <strong>%2</strong>%4 සමඟ සකසන්න. Install %2 on %3 system partition <strong>%1</strong>. - + %3 පද්ධති කොටස <strong>%1</strong> මත %2 ස්ථාපනය කරන්න. Install boot loader on <strong>%1</strong>. - + <strong>%1</strong> මත ඇරඹුම් කාරකය ස්ථාපනය කරන්න. Setting up mount points. - + සවි කිරීම් ස්ථාන සැකසීම. @@ -1534,37 +1534,37 @@ The installer will quit and all changes will be lost. &Restart now - + නැවත ආරම්භ කරන්න (&R) <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. - + <strong>සියල්ල සාර්ථකව අවසන් විය</strong>.<br>%1 ඔබගේ පරිගණකයේ පිහිටුවා ඇත.<br>ඔබට දැන් ඔබගේ නව පද්ධතිය භාවිතා කිරීමට පටන් ගත හැක. <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> - + <html><head/><body><p>මෙම කොටුව සලකුණු කළ විට, ඔබ <strong>Done</strong> මත ක්ලික් කළ විට හෝ සැකසුම් වැඩසටහන වසා දැමූ විට ඔබේ පද්ධතිය වහාම නැවත ආරම්භ වනු ඇත.</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. - + <strong>සියල්ල සාර්ථකව අවසන් විය</strong>.<br>%1 ඔබගේ පරිගණකයේ ස්ථාපනය කර ඇත.<br>ඔබට දැන් ඔබගේ නව පද්ධතියට නැවත ආරම්භ කළ හැක, නැතහොත් %2 සජීවී පරිසරය භාවිතා කිරීම දිගටම කරගෙනයා හැක. <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> - + <html><head/><body><p>මෙම කොටුව සලකුණු කළ විට, ඔබ <strong>Done</strong> මත ක්ලික් කළ විට හෝ ස්ථාපක වැඩසටහන වසා දැමූ විට ඔබේ පද්ධතිය වහාම නැවත ආරම්භ වනු ඇත.</p></body></html> <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. - + <strong>පිහිටුවීම අසාර්ථක විය</strong><br>% 1 ඔබේ පරිගණකයේ පිහිටුවා නැත. <br>දෝෂ පණිවිඩය වූයේ: %2. <h1>Installation Failed</h1><br/>%1 has not been installed on your computer.<br/>The error message was: %2. - + <strong>ස්ථාපනය අසාර්ථක විය</strong><br>%1 ඔබේ පරිගණකයේ ස්ථාපනය කර නැත. <br>දෝෂ පණිවිඩය වූයේ: %2. @@ -1572,7 +1572,7 @@ The installer will quit and all changes will be lost. Finish - + අවසන් @@ -1580,7 +1580,7 @@ The installer will quit and all changes will be lost. Finish - + අවසන් @@ -1588,22 +1588,22 @@ The installer will quit and all changes will be lost. Format partition %1 (file system: %2, size: %3 MiB) on %4. - + %4 මත කොටස %1 (ගොනු පද්ධතිය: %2, ප්‍රමාණය: %3 MiB) ආකෘතිකරණය කරන්න. Format <strong>%3MiB</strong> partition <strong>%1</strong> with file system <strong>%2</strong>. - + <strong>%3MiB</strong> කොටස <strong>%1</strong> ගොනු පද්ධතිය <strong>%2</strong> සමඟ ආකෘති කරන්න. Formatting partition %1 with file system %2. - + %2 ගොනු පද්ධතිය සමඟ %1 කොටස හැඩතල ගැන්වීම. The installer failed to format partition %1 on disk '%2'. - + ස්ථාපකය '%2' තැටියේ %1 කොටස හැඩතල ගැන්වීමට අසමත් විය. @@ -1611,72 +1611,72 @@ The installer will quit and all changes will be lost. has at least %1 GiB available drive space - + අවම වශයෙන් %1 GiB ලබා ගත හැකි ධාවකයේ ඉඩක් ඇත There is not enough drive space. At least %1 GiB is required. - + ප්‍රමාණවත් ධාවන ඉඩක් නොමැත. අවම වශයෙන් %1 GiB අවශ්‍ය වේ. has at least %1 GiB working memory - + අවම වශයෙන් %1 GiB ක්‍රියාකාරී මතකයක් ඇත The system does not have enough working memory. At least %1 GiB is required. - + පද්ධතියට ප්රමාණවත් ක්රියාකාරී මතකයක් නොමැත. අවම වශයෙන් %1 GiB අවශ්‍ය වේ. 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) - + ස්ථාපකය පරිපාලකයෙකු ලෙස ධාවනය කරයි (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. - + ස්ථාපකය වෙත පෙන්වීමට තිරය කුඩා වැඩිය. @@ -1684,7 +1684,7 @@ The installer will quit and all changes will be lost. Collecting information about your machine. - + ඔබගේ යන්ත්‍රය පිළිබඳ තොරතුරු රැස් කරමින් සිටී. @@ -1695,22 +1695,22 @@ The installer will quit and all changes will be lost. OEM Batch Identifier - + OEM කණ්ඩායම් හැඳුනුම්කාරකය Could not create directories <code>%1</code>. - + <code>%1</code> ගොනු තැනීමට නොහැකි විය. Could not open file <code>%1</code>. - + <code>%1</code> ගොනුව විවෘත කිරීමට නොහැකි විය. Could not write to file <code>%1</code>. - + <code>%1</code> ගොනුවට ලිවීමට නොහැකි විය. @@ -1718,7 +1718,7 @@ The installer will quit and all changes will be lost. Creating initramfs with mkinitcpio. - + mkinitcpio සමඟ initramfs නිර්මාණය කිරීම. @@ -1726,7 +1726,7 @@ The installer will quit and all changes will be lost. Creating initramfs. - + initramfs නිර්මාණය කිරීම. @@ -1734,17 +1734,17 @@ The installer will quit and all changes will be lost. Konsole not installed - + කොන්සෝල් ස්ථාපනය කර නැත Please install KDE Konsole and try again! - + කරුණාකර KDE කොන්සෝල් ස්ථාපනය කර නැවත උත්සාහ කරන්න! Executing script: &nbsp;<code>%1</code> - + ස්ක්‍රිප්ට් ක්‍රියාත්මක කරමින්: &nbsp;<code>%1</code><code> @@ -1752,7 +1752,7 @@ The installer will quit and all changes will be lost. Script - + ස්ක්‍රප්ට් @@ -1776,12 +1776,12 @@ The installer will quit and all changes will be lost. 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>. - + පද්ධති පෙදෙසි සැකසුම සමහර විධාන රේඛා පරිශීලක අතුරුමුහුණත් මූලද්‍රව්‍ය සඳහා භාෂාව සහ අක්ෂර කට්ටලයට බලපායි. <br/>වත්මන් සැකසුම <strong>%1</strong> වේ. @@ -1791,7 +1791,7 @@ The installer will quit and all changes will be lost. &OK - + හරි (&O) @@ -1804,37 +1804,37 @@ The installer will quit and all changes will be lost. <h1>License Agreement</h1> - + <h1>බලපත්ර එකගතාවය</h1> I accept the terms and conditions above. - + මම ඉහත නියමයන් සහ කොන්දේසි පිළිගනිමි. Please review the End User License Agreements (EULAs). - + කරුණාකර අවසන් පරිශීලක බලපත්‍ර ගිවිසුම් (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. - + ඔබ නියමයන් සමඟ එකඟ නොවන්නේ නම්, හිමිකාර මෘදුකාංග ස්ථාපනය නොකරනු ඇති අතර, ඒ වෙනුවට විවෘත මූලාශ්‍ර විකල්ප භාවිතා කරනු ඇත. @@ -1856,33 +1856,33 @@ The installer will quit and all changes will be lost. <strong>%1 driver</strong><br/>by %2 %1 is an untranslatable product name, example: Creative Audigy driver - + <strong>%1 ධාවකය</strong><br/>%2 කින් <strong>%1 graphics driver</strong><br/><font color="Grey">by %2</font> %1 is usually a vendor name, example: Nvidia graphics driver - + <strong>%1 චිත්‍රක ධාවකය</strong><br/><font color="Grey">%2 කින්</font> <strong>%1 browser plugin</strong><br/><font color="Grey">by %2</font> - + <strong>%1 බ්‍රවුසර ප්ලගිනය</strong><br/><font color="Grey"> %2 කින්</font> <strong>%1 codec</strong><br/><font color="Grey">by %2</font> - + <strong>%1 කෝඩෙක්</strong><br/><font color="Grey">%2 කින්</font> <strong>%1 package</strong><br/><font color="Grey">by %2</font> - + <strong>%1 පැකේජය</strong><br><font color="Grey">%2 කින්</font> <strong>%1</strong><br/><font color="Grey">by %2</font> - + <strong>%1</strong><br/><font color="Grey">%2 කින්</font> @@ -1892,17 +1892,17 @@ The installer will quit and all changes will be lost. Hide license text - + බලපත්‍ර පෙළ සඟවන්න Show the license text - + බලපත්ර පාඨය පෙන්වන්න Open license agreement in browser. - + බ්‍රවුසරයේ බලපත්‍ර ගිවිසුම විවෘත කරන්න. @@ -1910,12 +1910,12 @@ The installer will quit and all changes will be lost. Region: - + කලාපයේ: Zone: - + කලාපය: @@ -1953,35 +1953,35 @@ The installer will quit and all changes will be lost. Configuring LUKS key file. - + LUKS යතුරු ගොනුව වින්‍යාස කරමින්. No partitions are defined. - + කොටස් නිර්වචනය කර නොමැත. Encrypted rootfs setup error - + සංකේතනය කරන ලද rootfs පිහිටුවීමේ දෝෂයකි Root partition %1 is LUKS but no passphrase has been set. - + මූල කොටස %1 LUKS වන නමුත් මුර-වැකිකඩක් සකසා නොමැත. Could not create LUKS key file for root partition %1. - + මූල කොටස %1 සඳහා LUKS යතුරු ගොනුව සෑදිය නොහැක. Could not configure LUKS key file on partition %1. - + %1 කොටසේ LUKS යතුරු ගොනුව වින්‍යාස කිරීමට නොහැකි විය. @@ -1989,17 +1989,17 @@ The installer will quit and all changes will be lost. Generate machine-id. - + යන්ත්‍ර හැඳුනුම්පත ජනනය කරන්න. Configuration Error - + වින්‍යාස දෝෂය No root mount point is set for MachineId. - + MachineId සඳහා root mount point එකක් සකසා නැත. @@ -2007,14 +2007,16 @@ The installer will quit and all changes will be lost. Timezone: %1 - + වේලා කලාපය:% 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. - + කරුණාකර ස්ථාපකයට පෙදෙසිය යෝජනා කළ හැකි වන පරිදි සිතියමේ ඔබ කැමති ස්ථානය තෝරන්න + සහ ඔබ සඳහා වේලා කලාප සැකසීම්. ඔබට පහත යෝජිත සැකසුම් මනාව සකස් කළ හැක. ඇදගෙන යාමෙන් සිතියම සොයන්න + චලනය කිරීමට සහ විශාලනය කිරීමට හෝ විශාලනය කිරීම සඳහා මූසික අනුචලනය භාවිතා කිරීමට +/- බොත්තම් භාවිතා කරන්න. @@ -2052,7 +2054,7 @@ The installer will quit and all changes will be lost. Kernel - + කර්නලය @@ -2062,12 +2064,12 @@ The installer will quit and all changes will be lost. Login - + පිවිසෙන්න Desktop - + ඩෙස්ක්ටොප් @@ -2102,17 +2104,17 @@ The installer will quit and all changes will be lost. Theming - + තේමා කිරීම Gaming - + පරිගණක ක්රීඩා Utilities - + උපයෝගිතා @@ -2128,17 +2130,17 @@ The installer will quit and all changes will be lost. Ba&tch: - + කණ්ඩායම(&t): <html><head/><body><p>Enter a batch-identifier here. This will be stored in the target system.</p></body></html> - + <html><head/><body><p>මෙහි batch-identifier එකක් ඇතුළු කරන්න. මෙය ඉලක්ක පද්ධතිය තුළ ගබඩා කරනු ලැබේ.</p></body></html> <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> - + <html><head/><body><h1>OEM වින්‍යාසය</h1><p>Calamares ඉලක්ක පද්ධතිය වින්‍යාස කිරීමේදී OEM සැකසුම් භාවිතා කරනු ඇත.</p></body></html> @@ -2146,12 +2148,12 @@ The installer will quit and all changes will be lost. OEM Configuration - + OEM වින්‍යාසය Set the OEM Batch Identifier to <code>%1</code>. - + OEM Batch Identifier <code>%1</code> ලෙස සකසන්න. @@ -2159,29 +2161,29 @@ The installer will quit and all changes will be lost. Select your preferred Region, or use the default settings. - + ඔබ කැමති කලාපය තෝරන්න, නැතහොත් පෙරනිමි සැකසුම් භාවිතා කරන්න. Timezone: %1 - + වේලා කලාපය:% 1 Select your preferred Zone within your Region. - + ඔබ කැමති කලාපය තෝරන්න. Zones - + කලාපය: You can fine-tune Language and Locale settings below. - + ඔබට පහත භාෂාව සහ ස්ථාන සැකසීම් මනාව සකස් කළ හැක. @@ -2199,80 +2201,80 @@ The installer will quit and all changes will be lost. Password is too weak - + මුරපදය ඉතා දුර්වලයි Memory allocation error when setting '%1' - + '%1' සැකසීමේදී මතකය වෙන් කිරීමේ දෝෂයකි Memory allocation error - + මතකය වෙන් කිරීමේ දෝෂයකි The password is the same as the old one - + මුරපදය පැරණි එකට සමානයි The password is a palindrome - + මුරපදය 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 - - - + + මුරපදයේ කුඩා අකුරු %nකට වඩා අඩු ප්‍රමාණයක් ඇත + මුරපදයේ කුඩා අකුරු %n කට වඩා අඩු ප්‍රමාණයක් ඇත The password contains too few lowercase letters - + මුරපදයේ කුඩා අකුරු ඉතා ස්වල්පයක් ඇත The password contains too few non-alphanumeric characters - + මුරපදයේ අක්ෂරාංක නොවන අක්ෂර ඉතා ස්වල්පයක් අඩංගු වේ @@ -2282,181 +2284,181 @@ The installer will quit and all changes will be lost. 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 - - - + + මුරපදයේ ඉලක්කම් %n කට වඩා අඩු ප්‍රමාණයක් අඩංගු වේ + මුරපදයේ ඉලක්කම් %n කට වඩා අඩු ප්‍රමාණයක් අඩංගු වේ The password contains fewer than %n uppercase letters - - - + + මුරපදයේ ලොකු අකුරු %n කට වඩා අඩු ප්‍රමාණයක් ඇත + මුරපදයේ ලොකු අකුරු %n කට වඩා අඩු ප්‍රමාණයක් ඇත The password contains fewer than %n non-alphanumeric characters - - - + + මුරපදයේ අක්ෂරාංක නොවන අක්ෂර %n කට වඩා අඩු ප්‍රමාණයක් අඩංගු වේ + මුරපදයේ අක්ෂරාංක නොවන අක්ෂර %n කට වඩා අඩු ප්‍රමාණයක් අඩංගු වේ The password is shorter than %n characters - - - + + මුරපදය අක්ෂර %n ට වඩා කෙටිය + මුරපදය අක්ෂර %n ට වඩා කෙටිය The password is a rotated version of the previous one - + මුරපදය පෙර එකෙහි අනුවාදයකි The password contains fewer than %n character classes - - - + + මුරපදයේ අක්ෂර පන්ති %n කට වඩා අඩු ප්‍රමාණයක් අඩංගු වේ + මුරපදයේ අක්ෂර පන්ති %n කට වඩා අඩු ප්‍රමාණයක් අඩංගු වේ The password contains more than %n same characters consecutively - - - + + මුරපදයේ එක දිගට එකම අක්ෂර %nකට වඩා අඩංගු වේ + මුරපදයේ එක දිගට එකම අක්ෂර %nකට වඩා අඩංගු වේ The password contains more than %n characters of the same class consecutively - - - + + මුරපදයේ එක පන්තියේ අනුලකුණු %n කට වඩා එක දිගට අඩංගු වේ + මුරපදයේ එක පන්තියේ අනුලකුණු %n කට වඩා එක දිගට අඩංගු වේ The password contains monotonic sequence longer than %n characters - - - + + මුරපදයේ අක්ෂර %n කට වඩා දිග ඒකාකාරී අනුපිළිවෙලක් ඇත + මුරපදයේ අක්ෂර %n කට වඩා දිග ඒකාකාරී අනුපිළිවෙලක් ඇත The password contains too long of a monotonic character sequence - + මුරපදයේ ඒකාකාරී අක්ෂර අනුපිළිවෙලක් ඉතා දිගු වේ No password supplied - + මුරපදයක් සපයා නැත Cannot obtain random numbers from the RNG device - + RNG උපාංගයෙන් අහඹු අංක ලබා ගත නොහැක Password generation failed - required entropy too low for settings - + මුරපද උත්පාදනය අසාර්ථක විය - සැකසීම් සඳහා අවශ්‍ය එන්ට්‍රොපිය ඉතා අඩුය The password fails the dictionary check - %1 - + මුරපදය ශබ්ද කෝෂ පරීක්ෂාව අසමත් වේ - %1 The password fails the dictionary check - + මුරපදය ශබ්ද කෝෂ පරීක්ෂාව අසමත් වේ Unknown setting - %1 - + නොදන්නා සැකසුම - %1 Unknown setting - + නොදන්නා සැකසුමක් Bad integer value of setting - %1 - + සැකසුමෙහි නරක පූර්ණ සංඛ්‍යා අගය - % 1 Bad integer value - + සැකසුමෙහි නරක පූර්ණ සංඛ්‍යා අගයක් Setting %1 is not of integer type - + %1 සැකසීම පූර්ණ සංඛ්‍යා වර්ගයට අයත් නොවේ Setting is not of integer type - + සැකසීම නිඛිල ආකාරයේ නොවේ Setting %1 is not of string type - + %1 සැකසීම තන්තු වර්ගයට අයත් නොවේ Setting is not of string type - + සැකසීම තන්තු ආකාරයේ නොවේ Opening the configuration file failed - + වින්‍යාස ගොනුව විවෘත කිරීම අසාර්ථක විය The configuration file is malformed - + වින්‍යාස ගොනුව විකෘති වී ඇත Fatal failure - + දරුනු අසර්ථක වීමක් Unknown error - + නොදන්නා දෝෂයකි Password is empty - + මුරපදය හිස් ය @@ -2469,17 +2471,17 @@ The installer will quit and all changes will be lost. Product Name - + නිෂ්පාදන නාමය TextLabel - + අකුරු නාමකය Long Product Description - + දිගු නිෂ්පාදන විස්තරය @@ -2497,7 +2499,7 @@ The installer will quit and all changes will be lost. Packages - + පැකේජ @@ -2505,7 +2507,7 @@ The installer will quit and all changes will be lost. Packages - + පැකේජ @@ -2513,12 +2515,12 @@ The installer will quit and all changes will be lost. Name - + නම Description - + විස්තරය @@ -2531,12 +2533,12 @@ The installer will quit and all changes will be lost. Keyboard Model: - + යතුරුපුවරු ආකෘතිය: Type here to test your keyboard - + ඔබේ යතුරු පුවරුව පරීක්ෂා කිරීමට මෙහි ටයිප් කරන්න @@ -2549,91 +2551,91 @@ The installer will quit and all changes will be lost. 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> - + <small>ඔබ පරිගණකය ජාලයක අන් අයට පෙනෙන ලෙස සලස්වන්නේ නම් මෙම නම භාවිතා වේ.</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> - + <small>එකම මුරපදය දෙවරක් ඇතුල් කරන්න, එවිට එය ටයිප් කිරීමේ දෝෂ සඳහා පරීක්ෂා කළ හැක. හොඳ මුරපදයක අකුරු, ඉලක්කම් සහ විරාම ලකුණු මිශ්‍රණයක් අඩංගු වන අතර, අවම වශයෙන් අක්ෂර අටක්වත් දිග විය යුතු අතර නියමිත කාල පරාසයන්හිදී වෙනස් කළ යුතුය.</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> - + <small>එකම මුරපදය දෙවරක් ඇතුල් කරන්න, එවිට එය ටයිප් කිරීමේ දෝෂ සඳහා පරීක්ෂා කළ හැක.</small> @@ -2641,43 +2643,43 @@ The installer will quit and all changes will be lost. Root - + රූට් Home - + හෝම් Boot - + බූට් EFI system - + EFI පද්ධතිය Swap - + ස්වප් New partition for %1 - + %1 සඳහා නව කොටස New partition - + නව කොටස %1 %2 size[number] filesystem[name] - + %1 %2 @@ -2686,38 +2688,38 @@ The installer will quit and all changes will be lost. Free Space - + නිදහස් ඉඩ New partition - + නව කොටස Name - + නම File System - + ගොනු පද්ධතිය File System Label - + ගොනු පද්ධති ලේබලය Mount Point - + මවුන්ට් පොයින්ට් Size - + ප්‍රමානය @@ -2730,72 +2732,72 @@ The installer will quit and all changes will be lost. Storage de&vice: - + ගබඩා උපාංගය (&v): &Revert All Changes - + සියලුම වෙනස්කම් ආපසු හරවන්න (&R) New Partition &Table - + නව කොටස් වගුව (&T) Cre&ate - + නිර්මාණය කරන්න (&r) &Edit - + සංස්කරණය කරන්න (&E) &Delete - + මකන්න (&D) New Volume Group - + නව වෙළුම් සමූහය Resize Volume Group - + වෙළුම් සමූහය ප්‍රතිප්‍රමාණ කරන්න Deactivate Volume Group - + පරිමා සමූහය අක්‍රිය කරන්න Remove Volume Group - + වෙළුම් කණ්ඩායම ඉවත් කරන්න I&nstall boot loader on: - + ඇරඹුම් කාරකය ස්ථාපනය කරන්න (&n): Are you sure you want to create a new partition table on %1? - + ඔබට %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. - + %1 හි කොටස් වගුවෙහි දැනටමත් ප්‍රාථමික කොටස් %2ක් ඇති අතර, තවත් එකතු කළ නොහැක. කරුණාකර එක් ප්‍රාථමික කොටසක් ඉවත් කර ඒ වෙනුවට දිගු කොටසක් එක් කරන්න. @@ -2808,7 +2810,7 @@ The installer will quit and all changes will be lost. Partitions - + කොටස් @@ -2823,72 +2825,72 @@ The installer will quit and all changes will be lost. No EFI system partition configured - + EFI පද්ධති කොටසක් වින්‍යාස කර නොමැත EFI system partition configured incorrectly - + EFI පද්ධති කොටස වැරදි ලෙස වින්‍යාස කර ඇත 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. - + %1 ආරම්භ කිරීමට EFI පද්ධති කොටසක් අවශ්‍ය වේ. <br/><br/>EFI පද්ධති කොටසක් වින්‍යාස කිරීමට, ආපසු ගොස් සුදුසු ගොනු පද්ධතියක් තෝරන්න හෝ සාදන්න. The filesystem must be mounted on <strong>%1</strong>. - + ගොනු පද්ධතිය %1 මත සවිකර තිබිය යුතුය. The filesystem must have type FAT32. - + ගොනු පද්ධතියට FAT32 වර්ගය තිබිය යුතුය. The filesystem must be at least %1 MiB in size. - + ගොනු පද්ධතිය අවම වශයෙන් %1 MiB විශාලත්වයකින් යුක්ත විය යුතුය. The filesystem must have flag <strong>%1</strong> set. - + ගොනු පද්ධතියට ධජය <strong>%1</strong> කට්ටලයක් තිබිය යුතුය. You can continue without setting up an EFI system partition but your system may fail to start. - + ඔබට EFI පද්ධති කොටසක් සැකසීමෙන් තොරව ඉදිරියට යා හැකි නමුත් ඔබේ පද්ධතිය ආරම්භ කිරීමට අසමත් විය හැක. Option to use GPT on BIOS - + BIOS මත GPT භාවිතා කිරීමේ විකල්පය 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. - + GPT කොටස් වගුව සියලු පද්ධති සඳහා හොඳම විකල්පය වේ. මෙම ස්ථාපකය BIOS පද්ධති සඳහාද එවැනි සැකසුමකට සහය දක්වයි. <br/><br/>BIOS මත GPT කොටස් වගුවක් වින්‍යාස කිරීම සඳහා, (දැනටමත් එසේ කර නොමැති නම්) ආපසු ගොස් කොටස් වගුව GPT ලෙස සකසන්න, මීළඟට <strong>bios_grub</strong> ධජය සක්‍රීය කර ඇති 8 MB ආකෘතිකරණය නොකළ කොටසක් සාදන්න. <br/><br/>GPT සමඟින් BIOS පද්ධතියක %1 ආරම්භ කිරීමට හැඩතල ගැන්වීම නොකළ 8 MB කොටසක් අවශ්‍ය වේ. 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. - + එන්ක්‍රිප්ට් කරන ලද රූට් පාටිෂන් එකක් සමඟින් වෙනම ඇරඹුම් කොටසක් සකසා ඇත, නමුත් ඇරඹුම් කොටස සංකේතනය කර නොමැත. <br/<br/>වැදගත් පද්ධති ගොනු සංකේතනය නොකළ කොටසක තබා ඇති නිසා මෙවැනි සැකසුම සමඟ ආරක්ෂක ගැටළු ඇත. <br/>ඔබට අවශ්‍ය නම් ඔබට දිගටම කරගෙන යා හැක, නමුත් ගොනු පද්ධති අගුළු හැරීම පද්ධති ආරම්භයේදී පසුව සිදුවනු ඇත. <br/>ඇරඹුම් කොටස සංකේතනය කිරීමට, ආපසු ගොස් එය නැවත සාදන්න, කොටස් සෑදීමේ කවුළුව තුළ <strong>සංකේතනය</srong> තෝරන්න. has at least one disk device available. - + අවම වශයෙන් එක් තැටි උපාංගයක් තිබේ. There are no partitions to install on. - + ස්ථාපනය කිරීමට කොටස් නොමැත. @@ -2896,13 +2898,13 @@ The installer will quit and all changes will be lost. Plasma Look-and-Feel Job - + ප්ලාස්මා පෙනුම සහ හැඟීම රැකියාව Could not select KDE Plasma Look-and-Feel package - + KDE ප්ලාස්මා පෙනුම සහ දැනීම පැකේජය තේරීමට නොහැකි විය @@ -2915,12 +2917,12 @@ The installer will quit and all changes will be lost. 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. - + කරුණාකර KDE ප්ලාස්මා ඩෙස්ක්ටොප් එක සඳහා පෙනුම සහ හැඟීම තෝරන්න. ඔබට මෙම පියවර මඟ හැර පද්ධතිය සැකසූ පසු පෙනුම සහ හැඟීම වින්‍යාසගත කළ හැක. පෙනුම සහ හැඟීම තේරීමක් මත ක්ලික් කිරීමෙන් ඔබට එම පෙනුම සහ හැඟීම පිළිබඳ සජීවී පෙරදසුනක් ලබා දෙනු ඇත. 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. - + කරුණාකර KDE ප්ලාස්මා ඩෙස්ක්ටොප් එක සඳහා පෙනුම සහ හැඟීම තෝරන්න. ඔබට මෙම පියවර මඟ හැර පද්ධතිය ස්ථාපනය කළ පසු පෙනුම සහ හැඟීම වින්‍යාසගත කළ හැක. පෙනුම සහ හැඟීම තේරීමක් මත ක්ලික් කිරීමෙන් ඔබට එම පෙනුම සහ හැඟීම පිළිබඳ සජීවී පෙරදසුනක් ලබා දෙනු ඇත. @@ -2928,7 +2930,7 @@ The installer will quit and all changes will be lost. Look-and-Feel - + බලන්න සහ දැනෙන්න @@ -2936,17 +2938,17 @@ The installer will quit and all changes will be lost. Saving files for later ... - + පසු බාවිතට ගොනු සුරකමින් ... No files configured to save for later. - + පසුව සුරැකීමට ගොනු කිසිවක් වින්‍යාස කර නොමැත. Not all of the configured files could be preserved. - + වින්‍යාස කර ඇති සියලුම ගොනු සංරක්ෂණය කළ නොහැක. @@ -2955,64 +2957,67 @@ The installer will quit and all changes will be lost. There was no output from the command. - + +විධානයෙන් ප්‍රතිදානයක් නොතිබුණි. Output: - + +ප්‍රතිදානය: + External command crashed. - + බාහිර විධානය බිඳ වැටුණි. Command <i>%1</i> crashed. - + %1 විධානය බිඳ වැටුණි. External command failed to start. - + බාහිර විධානය ආරම්භ කිරීමට අසමත් විය. Command <i>%1</i> failed to start. - + %1 විධානය ආරම්භ කිරීමට අසමත් විය. 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. - + <i>%1</i> විධානය තත්පර %2කින් අවසන් කිරීමට අසමත් විය. External command finished with errors. - + බාහිර විධානය දෝෂ සහිතව අවසන් විය. Command <i>%1</i> finished with exit code %2. - + <i>%1</i> විධානය පිටවීමේ කේතය %2 සමඟ අවසන් විය. @@ -3025,28 +3030,28 @@ Output: unknown - + නොදන්නා extended - + දිගුව unformatted - + ආකෘතිකරණය නොකළ swap - + ස්වප් Default - + පෙරනිමිය @@ -3054,43 +3059,43 @@ Output: File not found - + ගොනුව හමු නොවිණි Path <pre>%1</pre> must be an absolute path. - + මාර්ගය <pre>%1</pre> නිරපේක්ෂ මාර්ගයක් විය යුතුය. Directory not found - + නාමාවලිය හමු නොවීය Could not create new random file <pre>%1</pre>. - + නව අහඹු <pre>%1</pre> ගොනුවක් තැනීමට නොහැකි විය. No product - + නිෂ්පාදනයක් නැත No description provided. - + විස්තරයක් සපයා නැත. (no mount point) - + (සවිකිරීම් ස්ථානයක් නොමැත) Unpartitioned space or unknown partition table - + කොටස් නොකළ ඉඩ හෝ නොදන්නා කොටස් වගුව @@ -3099,7 +3104,8 @@ Output: <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> - + <p>මෙම පරිගණකය %1 පිහිටුවීම සඳහා නිර්දේශිත සමහර අවශ්‍යතා සපුරාලන්නේ නැත.<br/> +පිහිටුවීම දිගටම කරගෙන යා හැක, නමුත් සමහර විශේෂාංග අබල විය හැක.</p> @@ -3107,7 +3113,7 @@ Output: Remove live user from target system - + ඉලක්ක පද්ධතියෙන් සජීවී පරිශීලකයා ඉවත් කරන්න @@ -3116,17 +3122,17 @@ Output: Remove Volume Group named %1. - + %1 නම් වූ වෙළුම් සමූහය ඉවත් කරන්න. Remove Volume Group named <strong>%1</strong>. - + <strong>%1</strong> නම් වූ වෙළුම් සමූහය ඉවත් කරන්න. The installer failed to remove a volume group named '%1'. - + ස්ථාපකය '%1' නම් වෙළුම් කණ්ඩායමක් ඉවත් කිරීමට අසමත් විය. @@ -3139,59 +3145,59 @@ Output: Select where to install %1.<br/><font color="red">Warning: </font>this will delete all files on the selected partition. - + %1 ස්ථාපනය කළ යුතු ස්ථානය තෝරන්න. <br/><font color='red'>අවවාදයයි: </font>මෙය තෝරාගත් කොටසේ ඇති සියලුම ගොනු මකා දමයි. The selected item does not appear to be a valid partition. - + තෝරාගත් අයිතමය වලංගු කොටසක් ලෙස නොපෙනේ. %1 cannot be installed on empty space. Please select an existing partition. - + %1 හිස් අවකාශයේ ස්ථාපනය කල නොහැක. කරුණාකර පවතින කොටසක් තෝරන්න. %1 cannot be installed on an extended partition. Please select an existing primary or logical partition. - + %1 දිගු කළ කොටසක ස්ථාපනය කල නොහැක. කරුණාකර පවතින ප්‍රාථමික හෝ තාර්කික කොටසක් තෝරන්න. %1 cannot be installed on this partition. - + %1 මෙම කොටසෙහි ස්ථාපනය කල නොහැක. Data partition (%1) - + දත්ත කොටස (%1) Unknown system partition (%1) - + නොදන්නා පද්ධති කොටස (%1) %1 system partition (%2) - + %1 පද්ධති කොටස (%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>%4</strong><br/><br/>%1 කොටස %2 සඳහා ඉතා කුඩාය. කරුණාකර අවම වශයෙන් %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>%2</strong><br/><br/>EFI පද්ධති කොටසක් මෙම පද්ධතියේ කොතැනකවත් සොයාගත නොහැක. කරුණාකර ආපසු ගොස් %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. - + <strong>%3</strong><br/><br/>%1 %2 මත ස්ථාපනය වනු ඇත.<br/><font color="red">අවවාදයයි:</font> %2 කොටසේ ඇති සියලුම දත්ත නැති වී යයි. @@ -3210,13 +3216,15 @@ Output: <p>This computer does not satisfy the minimum requirements for installing %1.<br/> Installation cannot continue.</p> - + <p>මෙම පරිගණකය %1 ස්ථාපනය සඳහා අවම අවශ්‍යතා සපුරාලන්නේ නැත.<br/> + ස්ථාපනය දිගටම කරගෙන යා නොහැක.</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> - + <p>මෙම පරිගණකය %1 පිහිටුවීම සඳහා නිර්දේශිත සමහර අවශ්‍යතා සපුරාලන්නේ නැත.<br/> + පිහිටුවීම දිගටම කරගෙන යා හැක, නමුත් සමහර විශේෂාංග අබල විය හැක.</p> @@ -3224,27 +3232,27 @@ Output: Resize Filesystem Job - + ගොනු පද්ධති කාර්යය ප්‍රමාණය වෙනස් කරන්න Invalid configuration - + වලංගු නොවන වින්‍යාසය The file-system resize job has an invalid configuration and will not run. - + ගොනු පද්ධති ප්‍රමාණය වෙනස් කිරීමේ කාර්යයට වලංගු නොවන වින්‍යාසයක් ඇති අතර එය ක්‍රියාත්මක නොවේ. KPMCore not Available - + KPMCore නොමැත Calamares cannot start KPMCore for the file-system resize job. - + ගොනු පද්ධති ප්‍රමාණය වෙනස් කිරීමේ කාර්යය සඳහා Calamares හට KPMCore ආරම්භ කළ නොහැක. @@ -3253,39 +3261,39 @@ Output: Resize Failed - + ප්‍රමාණය වෙනස් කිරීම අසාර්ථක විය The filesystem %1 could not be found in this system, and cannot be resized. - + ගොනු පද්ධතිය %1 මෙම පද්ධතිය තුළ සොයා ගත නොහැකි අතර, ප්‍රමාණය වෙනස් කළ නොහැක. The device %1 could not be found in this system, and cannot be resized. - + %1 උපාංගය මෙම පද්ධතිය තුළ සොයාගත නොහැකි වූ අතර, ප්‍රමාණය වෙනස් කළ නොහැක. The filesystem %1 cannot be resized. - + %1 ගොනු පද්ධතිය ප්‍රතිප්‍රමාණ කළ නොහැක. The device %1 cannot be resized. - + උපාංගය %1 ප්‍රමාණය වෙනස් කළ නොහැක. The filesystem %1 must be resized, but cannot. - + ගොනු පද්ධතිය %1 ප්‍රමාණය වෙනස් කළ යුතුය, නමුත් කළ නොහැක. The device %1 must be resized, but cannot - + උපාංගය %1 ප්‍රමාණය වෙනස් කළ යුතු නමුත් කළ නොහැක @@ -3293,22 +3301,22 @@ Output: Resize partition %1. - + %1 කොටස ප්‍රතිප්‍රමාණ කරන්න. Resize <strong>%2MiB</strong> partition <strong>%1</strong> to <strong>%3MiB</strong>. - + <strong>%2MiB</strong> කොටස <strong>%1</strong> සිට <strong>%3MiB</strong> දක්වා ප්‍රමාණය වෙනස් කරන්න. Resizing %2MiB partition %1 to %3MiB. - + %2MiB කොටස %1 සිට %3MiB දක්වා ප්‍රමාණය වෙනස් කිරීම. The installer failed to resize partition %1 on disk '%2'. - + '%2' තැටියේ %1 කොටස ප්‍රතිප්‍රමාණ කිරීමට ස්ථාපකය අසමත් විය. @@ -3316,7 +3324,7 @@ Output: Resize Volume Group - + වෙළුම් සමූහය ප්‍රතිප්‍රමාණ කරන්න @@ -3325,17 +3333,17 @@ Output: Resize volume group named %1 from %2 to %3. - + %2 සිට %3 දක්වා %1 ලෙස නම් කරන ලද වෙළුම් සමූහය ප්‍රතිප්‍රමාණ කරන්න. Resize volume group named <strong>%1</strong> from <strong>%2</strong> to <strong>%3</strong>. - + <strong>%2</strong> සිට <strong>%3</strong> දක්වා <strong>%1</strong> ලෙස නම් කරන ලද වෙළුම් සමූහය ප්‍රතිප්‍රමාණ කරන්න. The installer failed to resize a volume group named '%1'. - + ස්ථාපකය '%1' නම් වූ වෙළුම් සමූහයක් ප්‍රතිප්‍රමාණ කිරීමට අසමත් විය. @@ -3343,12 +3351,12 @@ Output: For best results, please ensure that this computer: - + හොඳම ප්‍රතිඵල සඳහා, කරුණාකර මෙම පරිගණකය සහතික කර ගන්න: System requirements - + පද්ධති අවශ්යතා @@ -3356,12 +3364,12 @@ Output: Scanning storage devices... - + ගබඩා උපාංග පරිලෝකනය කරමින්... Partitioning - + කොටස් කරමින් @@ -3369,29 +3377,29 @@ Output: Set hostname %1 - + ධාරක නාමය සකසන්න %1 Set hostname <strong>%1</strong>. - + ධාරක නාමය සකසන්න <strong>%1</strong>. Setting hostname %1. - + සත්කාරක නාමය %1 සැකසීම. Internal Error - + අභ්යන්තර දෝෂයකි Cannot write hostname to target system - + ඉලක්ක පද්ධතියට සත්කාරක නාමය ලිවිය නොහැක @@ -3399,29 +3407,29 @@ Output: Set keyboard model to %1, layout to %2-%3 - + යතුරුපුවරු ආකෘතිය %1 ලෙස සකසන්න, පිරිසැලසුම %2-%3 ලෙස සකසන්න Failed to write keyboard configuration for the virtual console. - + අතථ්‍ය කොන්සෝලය සඳහා යතුරුපුවරු වින්‍යාසය ලිවීමට අසමත් විය. Failed to write to %1 - + %1 වෙත ලිවීමට අසමත් විය Failed to write keyboard configuration for X11. - + X11 සඳහා යතුරුපුවරු වින්‍යාසය ලිවීමට අසමත් විය. Failed to write keyboard configuration to existing /etc/default directory. - + පවතින /etc/default බහලුම වෙත යතුරුපුවරු වින්‍යාසය ලිවීමට අසමත් විය. @@ -3429,82 +3437,82 @@ Output: Set flags on partition %1. - + %1 කොටසේ කොඩි සකසන්න. Set flags on %1MiB %2 partition. - + %1MiB %2 කොටස මත කොඩි සකසන්න. Set flags on new partition. - + නව කොටසේ කොඩි සකසන්න. Clear flags on partition <strong>%1</strong>. - + %1 කොටසේ කොඩි හිස් කරන්න. Clear flags on %1MiB <strong>%2</strong> partition. - + %1MiB %2 කොටසේ කොඩි හිස් කරන්න. Clear flags on new partition. - + නව කොටසේ කොඩි ඉවත් කරන්න. Flag partition <strong>%1</strong> as <strong>%2</strong>. - + %1 කොටස %2 ලෙස සලකුණු කරන්න. Flag %1MiB <strong>%2</strong> partition as <strong>%3</strong>. - + %1MiB <strong>%2</strong> කොටස <strong>%3</strong> ලෙස සලකුණු කරන්න. Flag new partition as <strong>%1</strong>. - + නව කොටස <strong>%1</strong> ලෙස සලකුණු කරන්න. Clearing flags on partition <strong>%1</strong>. - + %1 කොටසේ කොඩි ඉවත් කිරීම. Clearing flags on %1MiB <strong>%2</strong> partition. - + %1MiB <strong>%2</strong> කොටසේ කොඩි ඉවත් කිරීම. Clearing flags on new partition. - + නව කොටසේ කොඩි ඉවත් කිරීම. Setting flags <strong>%2</strong> on partition <strong>%1</strong>. - + <strong>%1</strong> කොටස මත කොඩි <strong>%2</strong> සැකසීම. Setting flags <strong>%3</strong> on %1MiB <strong>%2</strong> partition. - + %1MiB <strong>%2</strong> කොටස මත කොඩි <strong>%3</strong> සැකසීම. Setting flags <strong>%1</strong> on new partition. - + නව කොටසෙහි කොඩි <strong>%1</strong> සැකසීම. The installer failed to set flags on partition %1. - + ස්ථාපකය %1 කොටසෙහි කොඩි සැකසීමට අසමත් විය. @@ -3512,42 +3520,42 @@ Output: Set password for user %1 - + පරිශීලක %1 සඳහා මුරපදය සකසන්න Setting password for user %1. - + පරිශීලක %1 සඳහා මුරපදය සැකසීම. Bad destination system path. - + නරක ගමනාන්ත පද්ධති මාර්ගය. rootMountPoint is %1 - + මූලමවුන්ට්පොයින්ට් % 1 වේ Cannot disable root account. - + මූල ගිණුම අක්‍රිය කළ නොහැක. passwd terminated with error code %1. - + මුරපදය %1 දෝෂ කේතය සමඟ අවසන් විය. Cannot set password for user %1. - + පරිශීලක %1 සඳහා මුරපදය සැකසිය නොහැක. usermod terminated with error code %1. - + පරිශීලක මොඩ් දෝෂ කේතය % 1 සමඟ අවසන් කරන ලදී. @@ -3555,37 +3563,37 @@ Output: Set timezone to %1/%2 - + වේලා කලාපය %1/%2 ලෙස සකසන්න Cannot access selected timezone path. - + තෝරාගත් වේලා කලාප මාර්ගයට ප්‍රවේශ විය නොහැක. Bad path: %1 - + නරක මාර්ගය:%1 Cannot set timezone. - + වේලා කලාපයක් සැකසිය නොහැක. Link creation failed, target: %1; link name: %2 - + සබැඳි නිර්මාණය අසාර්ථක විය, ඉලක්කය: %1; සබැඳි නම: %2 Cannot set timezone, - + වේලා කලාපය සැකසිය නොහැක, Cannot open /etc/timezone for writing - + ලිවීම සඳහා /etc/timezone විවෘත කළ නොහැක @@ -3593,18 +3601,18 @@ Output: Preparing groups. - + කණ්ඩායම් සූදානම් කිරීම. Could not create groups in target system - + ඉලක්ක පද්ධතිය තුළ කණ්ඩායම් සෑදීමට නොහැකි විය These groups are missing in the target system: %1 - + ඉලක්ක පද්ධතිය තුළ මෙම කණ්ඩායම් අතුරුදහන් වී ඇත: %1 @@ -3612,17 +3620,17 @@ Output: Configure <pre>sudo</pre> users. - + <strong>sudo</strong> භාවිතා කරන්නන් වින්‍යාස කරන්න. Cannot chmod sudoers file. - + sudoers ගොනුව chmod කළ නොහැක. Cannot create sudoers file for writing. - + ලිවීම සඳහා sudoers ගොනුව සෑදිය නොහැක. @@ -3630,7 +3638,7 @@ Output: Shell Processes Job - + ෂෙල් ක්රියාවලීන් @@ -3639,7 +3647,7 @@ Output: %L1 / %L2 slide counter, %1 of %2 (numeric) - + %L1 / %L2 @@ -3647,7 +3655,7 @@ Output: &OK - + හරි (&O) @@ -3675,22 +3683,22 @@ Output: Installation feedback - + ස්ථාපන ප්‍රතිපෝෂණය Sending installation feedback. - + ස්ථාපන ප්‍රතිපෝෂණ යැවීම. Internal error in install-tracking. - + ස්ථාපන ලුහුබැඳීමේ අභ්‍යන්තර දෝෂයකි. HTTP request timed out. - + HTTP ඉල්ලීම කල් ඉකුත් විය. @@ -3698,28 +3706,28 @@ Output: KDE user feedback - + KDE පරිශීලක ප්‍රතිපෝෂණය Configuring KDE user feedback. - + KDE පරිශීලක ප්‍රතිපෝෂණ වින්‍යාස කිරීම. Error in KDE user feedback configuration. - + KDE පරිශීලක ප්‍රතිපෝෂණ වින්‍යාසයෙහි දෝෂයකි. Could not configure KDE user feedback correctly, script error %1. - + KDE පරිශීලක ප්‍රතිපෝෂණය නිවැරදිව වින්‍යාස කිරීමට නොහැකි විය, ස්ක්‍රිප්ට් දෝෂය %1. Could not configure KDE user feedback correctly, Calamares error %1. - + KDE පරිශීලක ප්‍රතිපෝෂණය නිවැරදිව වින්‍යාස කිරීමට නොහැකි විය, Calamares දෝෂය %1. @@ -3727,28 +3735,28 @@ Output: Machine feedback - + යන්ත්‍ර ප්‍රතිපෝෂණය Configuring machine feedback. - + යන්ත්‍ර ප්‍රතිපෝෂණ වින්‍යාස කිරීම. Error in machine feedback configuration. - + යන්ත්‍ර ප්‍රතිපෝෂණ වින්‍යාසය තුළ දෝෂයකි. Could not configure machine feedback correctly, script error %1. - + යන්ත්‍ර ප්‍රතිපෝෂණය නිවැරදිව වින්‍යාස කිරීමට නොහැකි විය, ස්ක්‍රිප්ට් දෝෂය %1. Could not configure machine feedback correctly, Calamares error %1. - + යන්ත්‍ර ප්‍රතිපෝෂණය නිවැරදිව වින්‍යාස කිරීමට නොහැකි විය, Calamares දෝෂය %1. @@ -3761,37 +3769,37 @@ Output: 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>ඔබගේ ස්ථාපනය පිළිබඳ <span style=" font-weight:600;">කිසිදු තොරතුරක්</span> නොයැවීමට මෙතන ක්ලික් කරන්න.</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> - + <html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">පරිශීලක ප්‍රතිපෝෂණ පිළිබඳ වැඩි විස්තර සඳහා මෙතැන ක්ලික් කරන්න</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. - + ලුහුබැඳීම %1 හට එය කොපමණ වාරයක් ස්ථාපනය කර ඇත්ද, කුමන දෘඩාංග මත ස්ථාපනය කර ඇත්ද සහ කුමන යෙදුම් භාවිතා කරන්නේද යන්න බැලීමට උපකාරී වේ. යවන්නේ කුමක් දැයි බැලීමට, එක් එක් ප්‍රදේශයට යාබදව ඇති උදවු නිරූපකය ක්ලික් කරන්න. 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. - + මෙය තේරීමෙන් ඔබ ඔබේ ස්ථාපනය සහ දෘඪාංග පිළිබඳ තොරතුරු එවනු ඇත. ස්ථාපනය අවසන් වූ පසු මෙම තොරතුරු <b>එක් වරක්</b> පමණක් යවනු ලැබේ. By selecting this you will periodically send information about your <b>machine</b> installation, hardware and applications, to %1. - + මෙය තේරීමෙන් ඔබ විසින් ඔබේ <b>යන්ත්‍ර</b> ස්ථාපනය, දෘඪාංග සහ යෙදුම් පිළිබඳ තොරතුරු වරින් වර %1 වෙත යවනු ලැබේ. By selecting this you will regularly send information about your <b>user</b> installation, hardware, applications and application usage patterns, to %1. - + මෙය තේරීමෙන් ඔබ ඔබේ <b>පරිශීලක</b> ස්ථාපනය, දෘඪාංග, යෙදුම්, සහ යෙදුම් භාවිත රටා, %1 වෙත නිතිපතා යවනු ලැබේ. @@ -3799,7 +3807,7 @@ Output: Feedback - + ප්‍රතිපෝෂණ @@ -3807,12 +3815,12 @@ Output: <small>If more than one person will use this computer, you can create multiple accounts after setup.</small> - + <small>එක් අයෙකුට වඩා මෙම පරිගණකය භාවිතා කරන්නේ නම්, සැකසීමෙන් පසු ඔබට ගිණුම් කිහිපයක් සෑදිය හැක.</small> <small>If more than one person will use this computer, you can create multiple accounts after installation.</small> - + <small>මෙම පරිගණකය එක් අයෙකුට වඩා භාවිතා කරන්නේ නම්, ස්ථාපනය කිරීමෙන් පසු ඔබට ගිණුම් කිහිපයක් සෑදිය හැක.</small> @@ -3820,7 +3828,7 @@ Output: Users - + පරිශීලකයන් @@ -3828,7 +3836,7 @@ Output: Users - + පරිශීලකයන් @@ -3837,13 +3845,13 @@ Output: Key Column header for key/value - + යතුර Value Column header for key/value - + අගය @@ -3856,22 +3864,22 @@ Output: List of Physical Volumes - + භෞතික වෙළුම් ලැයිස්තුව Volume Group Name: - + වෙළුම් සමූහයේ නම: Volume Group Type: - + වෙළුම් කණ්ඩායම් වර්ගය: Physical Extent Size: - + භෞතික ප්‍රමාණයේ ප්‍රමාණය: @@ -3881,22 +3889,22 @@ Output: Total Size: - + මුළු ප්‍රමාණය: Used Size: - + භාවිතා කළ ප්‍රමාණය: Total Sectors: - + මුළු අංශ: Quantity of LVs: - + LV ප්‍රමාණය: @@ -3910,92 +3918,92 @@ Output: Select application and system language - + යෙදුම් සහ පද්ධති භාෂාව තෝරන්න &About - + ගැන (&A) Open donations website - + පරිත්‍යාග වෙබ් අඩවිය විවෘත කරන්න &Donate - + පරිත්‍යාග කරන්න (&D) Open help and support website - + උදව් සහ සහාය වෙබ් අඩවිය විවෘත කරන්න &Support - + සහාය (&S) Open issues and bug-tracking website - + ගැටළු සහ දෝෂ ලුහුබැඳීමේ වෙබ් අඩවිය විවෘත කරන්න &Known issues - + දන්නා ගැටළු (&K) Open release notes website - + නිකුතු සටහන් වෙබ් අඩවිය විවෘත කරන්න &Release notes - + නිකුත් කිරීමේ සටහන් (&R) <h1>Welcome to the Calamares setup program for %1.</h1> - + <h1>%1 සඳහා Calamares සැකසුම් වැඩසටහන වෙත සාදරයෙන් පිළිගනිමු.</h1> <h1>Welcome to %1 setup.</h1> - + <h1>%1 පිහිටුවීමට සාදරයෙන් පිළිගනිමු.</h1> <h1>Welcome to the Calamares installer for %1.</h1> - + <h1>%1 සඳහා Calamares ස්ථාපකය වෙත සාදරයෙන් පිළිගනිමු.</h1> <h1>Welcome to the %1 installer.</h1> - + <h1>%1 ස්ථාපකය වෙත සාදරයෙන් පිළිගනිමු.</h1> %1 support - + %1 සහාය About %1 setup - + %1 පිහිටුවීම ගැන About %1 installer - + %1 ස්ථාපකය ගැන <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. - + <h1>%1</h1><br/><strong>%2<br/> සඳහා %3</strong><br/><br/>ප්‍රකාශන හිමිකම 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>ප්‍රකාශන හිමිකම 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/><a href="https://calamares.io/team/">Calamares කණ්ඩායමට</a> සහ <a href="https://www.transifex.com/calamares/calamares/">Calamares පරිවර්තකයන් සංවර්ධන කණ්ඩායමට</a> ස්තුතියි. <a href="https://calamares.io/">Calamares</a> සංවර්ධනය සඳහා අනුග්‍රහය දක්වන්නේ <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software විසිනි. @@ -4003,7 +4011,7 @@ Output: Welcome - + සාදරයෙන් පිළිගනිමු @@ -4011,7 +4019,7 @@ Output: Welcome - + සාදරයෙන් පිළිගනිමු @@ -4030,12 +4038,23 @@ Output: development is sponsored by <br/> <a href='http://www.blue-systems.com/'>Blue Systems</a> - Liberating Software. - + <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/> + <a href='https://calamares.io/team/'>Calamares කණ්ඩායමට</a> ස්තුතියි + සහ <a href='https://www.transifex.com/calamares/calamares/'>Calamares + පරිවර්තක කණ්ඩායම</a>.<br/><br/> + <a href='https://calamares.io/'>Calamares</a> + සංවර්ධනය අනුග්‍රහය දක්වනුයේ<br/> + <a href='http://www.blue-systems.com/'>Blue Systems</a> - + Liberating Software. Back - + ආපසු @@ -4043,7 +4062,7 @@ Output: Show debug information - + දෝශ නිරාකරණ තොරතුරු පෙන්වන්න @@ -4051,29 +4070,31 @@ Output: Installation Completed - + ස්ථාපනය අවසන් %1 has been installed on your computer.<br/> You may now restart into your new system, or continue using the Live environment. - + %1 ඔබේ පරිගණකයේ ස්ථාපනය කර ඇත.<br/> + ඔබට දැන් ඔබේ නව පද්ධතිය නැවත ආරම්භ කළ හැකිය, නැතහොත් සජීවී පරිසරය දිගටම භාවිතා කළ හැක. 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> - + <p>ස්ථාපනයේ සම්පූර්ණ ලොගයක් සජීවී පරිශීලකයාගේ මුල් නාමාවලියෙහි install.log ලෙස පවතී.<br/> + මෙම ලොගය ඉලක්ක පද්ධතියේ /var/log/installation.log වෙත පිටපත් කර ඇත.</p> @@ -4082,18 +4103,20 @@ Output: <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>භාෂා</h1> </br> + පද්ධති පෙදෙසි සැකසුම සමහර විධාන රේඛා පරිශීලක අතුරුමුහුණත් මූලද්‍රව්‍ය සඳහා භාෂාව සහ අක්ෂර කට්ටලයට බලපායි. වත්මන් සැකසුම <strong>%1</strong> වේ. <h1>Locales</h1> </br> The system locale setting affects the numbers and dates format. The current setting is <strong>%1</strong>. - + <h1>ප්‍රාදේශීය</h1> </br> + පද්ධති පෙදෙසි සැකසීම අංක සහ දින ආකෘතියට බලපායි. වත්මන් සැකසුම <strong>%1</strong> වේ. Back - + ආපසු @@ -4101,27 +4124,27 @@ Output: To activate keyboard preview, select a layout. - + යතුරුපුවරු පෙරදසුන සක්‍රිය කිරීමට, පිරිසැලසුමක් තෝරන්න. Keyboard Model: - + යතුරුපුවරු ආකෘතිය: Layouts - + පිරිසැලසුම් Type here to test your keyboard - + ඔබේ යතුරු පුවරුව පරීක්ෂා කිරීමට මෙහි ටයිප් කරන්න Variants - + ප්‍රභේද @@ -4129,7 +4152,7 @@ Output: Change - + වෙනස් කරන්න @@ -4138,7 +4161,8 @@ Output: <h3>%1</h3> <p>These are example release notes.</p> - + <h3>%1</h3> + <p>මේවා නිදසුන් නිකුත් කිරීමේ සටහන් වේ.</p> @@ -4147,37 +4171,38 @@ Output: 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 යනු ලොව පුරා සිටින මිලියන සංඛ්‍යාත ජනතාවක් විසින් භාවිතා කරන බලවත් සහ නිදහස් කාර්යාල කට්ටලයකි. වෙළඳපොලේ ඇති වඩාත්ම බහුකාර්ය නිදහස් සහ විවෘත මූලාශ්‍ර කාර්යාල කට්ටලය බවට පත් කරන යෙදුම් කිහිපයක් එයට ඇතුළත් වේ.<br/> + පෙරනිමි විකල්පය. LibreOffice - + 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 තෝරන්න. ඔබගේ ස්ථාපිත පද්ධතියට අවශ්‍යතාවය අනුව ඔබට සැම විටම එකක් (හෝ කිහිපයක්) පසුව එක් කළ හැක No Office Suite - + 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. - + අවම ඩෙස්ක්ටොප් ස්ථාපනයක් සාදන්න, සියලුම අමතර යෙදුම් ඉවත් කර ඔබ ඔබේ පද්ධතියට එකතු කිරීමට කැමති දේ පසුව තීරණය කරන්න. එවැනි ස්ථාපනයක සිදු නොවන දේ පිළිබඳ උදාහරණ, Office Suite එකක්, මාධ්‍ය වාදකයක්, රූප නරඹන්නාක් හෝ මුද්‍රණ සහායක් නොමැත. එය ඩෙස්ක්ටොප් එකක්, ගොනු බ්‍රවුසරයක්, පැකේජ කළමනාකරු, පෙළ සංස්කාරකයක් සහ සරල වෙබ් බ්‍රව්සරයක් පමණක් වනු ඇත. Minimal Install - + අවම ස්ථාපනය Please select an option for your install, or use the default: LibreOffice included. - + කරුණාකර ඔබගේ ස්ථාපනය සඳහා විකල්පයක් තෝරන්න, නැතහොත් පෙරනිමිය භාවිතා කරන්න: LibreOffice ඇතුළත්. @@ -4205,12 +4230,32 @@ Output: </ul> <p>The vertical scrollbar is adjustable, current width set to 10.</p> - + <h3>%1</h3> + <p>මෙය උදාහරණ QML ගොනුවකි, Flickable අන්තර්ගතය සහිත Rich Text විකල්ප පෙන්වයි.</p> + + <p>Rich Text සහිත QML හට HTML ටැග් භාවිතා කළ හැක, Flickable අන්තර්ගතය ස්පර්ශ තිර සඳහා ප්‍රයෝජනවත් වේ.</p> + + <p><b>මෙය තද පෙළකි</b></p> + <p><i>මෙය ඇල අකුරු වේ</i></p> + <p><u>මෙය යටින් ඉරි ඇඳ ඇති පාඨයකි</u></p> + <p><center>මෙම පාඨය මැදට පෙළගස්වනු ඇත.</center></p> + <p><s>මෙය මැදින් ඇදි ඉරකි.</s></p> + + <p>කේත උදාහරණය: + <code>ls -l /home</code></p> + + <p><b>ලැයිස්තු:</b></p> + <ul> + <li>Intel CPU පද්ධති</li> + <li>AMD CPU පද්ධති</li> + </ul> + + <p>සිරස් අනුචලන තීරුව වෙනස් කළ හැකි අතර, වත්මන් පළල 10 ලෙස සකසා ඇත.</p> Back - + ආපසු @@ -4218,32 +4263,32 @@ Output: 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. - + මෙම පරිගණකය එක් අයෙකුට වඩා භාවිතා කරන්නේ නම්, ස්ථාපනය කිරීමෙන් පසු ඔබට ගිණුම් කිහිපයක් සෑදිය හැක. @@ -4253,97 +4298,97 @@ Output: root is not allowed as username. - + root පරිශීලක නාමයක් ලෙස අවසර නැත. 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. - + localhost සත්කාරක නාමය ලෙස භාවිතයට අවසර නැත. 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 - + පරිශීලක මුරපදය root මුරපදය ලෙස නැවත භාවිතා කරන්න Use the same password for the administrator account. - + පරිපාලක ගිණුම සඳහා එකම මුරපදය භාවිතා කරන්න. Choose a root password to keep your account safe. - + ඔබගේ ගිණුම ආරක්ෂිතව තබා ගැනීමට root මුරපදයක් තෝරන්න. Root Password - + Root මුරපදය Repeat Root Password - + Root මුරපදය නැවත ඇතුල් කරන්න Enter the same password twice, so that it can be checked for typing errors. - + එකම මුරපදය දෙවරක් ඇතුල් කරන්න, එවිට එය ටයිප් කිරීමේ දෝෂ සඳහා පරීක්ෂා කළ හැක. @@ -4352,32 +4397,33 @@ Output: <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> - + <h3>%1 <quote>%2</quote> ස්ථාපකය වෙත සාදරයෙන් පිළිගනිමු</h3> + <p>මෙම වැඩසටහන ඔබෙන් ප්‍රශ්න කිහිපයක් අසන අතර ඔබේ පරිගණකයේ %1 පිහිටුවනු ඇත.</p> About - + ගැන Support - + සහාය Known issues - + දන්නා ගැටළු Release notes - + නිකුත් කිරීමේ සටහන් Donate - + පරිත්‍යාග කරන්න diff --git a/lang/calamares_tr_TR.ts b/lang/calamares_tr_TR.ts index 859b81538..52b9c70c3 100644 --- a/lang/calamares_tr_TR.ts +++ b/lang/calamares_tr_TR.ts @@ -690,27 +690,27 @@ Yükleyiciden çıkınca tüm değişiklikler kaybedilecek. Successfully unmounted %1. - + %1 bağlantısı başarıyla kaldırıldı. Successfully disabled swap %1. - + %1 takas alanı başarıyla devre dışı bırakıldı. Successfully cleared swap %1. - + %1 takas alanı başarıyla temizlendi. Successfully closed mapper device %1. - + %1 eşleyici aygıtı başarıyla kapatıldı. Successfully disabled volume group %1. - + %1 birim grubu başarıyla devre dışı bırakıldı. @@ -862,17 +862,17 @@ Kurulum devam edebilir fakat bazı özellikler devre dışı kalabilir. <h1>Welcome to %1 setup</h1> - <h1>%1 kurulumuna hoşgeldiniz</h1> + <h1>%1 kurulumuna hoş geldiniz</h1> <h1>Welcome to the Calamares installer for %1</h1> - <h1>%1 Calamares Sistem Yükleyiciye Hoşgeldiniz</h1> + <h1>%1 Calamares Sistem Yükleyiciye Hoş Geldiniz</h1> <h1>Welcome to the %1 installer</h1> - <h1>%1 Sistem Yükleyiciye Hoşgeldiniz</h1> + <h1>%1 Sistem Yükleyiciye Hoş Geldiniz</h1> @@ -3978,7 +3978,7 @@ Output: <h1>Welcome to %1 setup.</h1> - <h1>%1 Kurulumuna Hoşgeldiniz.</h1> + <h1>%1 Kurulumuna Hoş Geldiniz.</h1> @@ -4016,7 +4016,7 @@ Output: Welcome - Hoşgeldiniz + Hoş geldiniz @@ -4024,7 +4024,7 @@ Output: Welcome - Hoşgeldiniz + Hoş geldiniz diff --git a/lang/python/az/LC_MESSAGES/python.po b/lang/python/az/LC_MESSAGES/python.po index 3dc3ec79a..93d08bf80 100644 --- a/lang/python/az/LC_MESSAGES/python.po +++ b/lang/python/az/LC_MESSAGES/python.po @@ -323,7 +323,7 @@ msgstr "{name!s} systemd hədəfi aktiv edilmədi" #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." -msgstr "" +msgstr "{name!s} systemd taymeri aktiv edilə bilmir." #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -407,6 +407,7 @@ msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." msgstr "" +"Unsquashfs tapılmadı, squashfs-tools paketinin quraşdırıldığına əmin olun." #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/lang/python/az_AZ/LC_MESSAGES/python.po b/lang/python/az_AZ/LC_MESSAGES/python.po index eda09d8bf..99cfb8df4 100644 --- a/lang/python/az_AZ/LC_MESSAGES/python.po +++ b/lang/python/az_AZ/LC_MESSAGES/python.po @@ -323,7 +323,7 @@ msgstr "{name!s} systemd hədəfi aktiv edilmədi" #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." -msgstr "" +msgstr "{name!s} systemd taymeri aktiv edilə bilmir." #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -407,6 +407,7 @@ msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." msgstr "" +"Unsquashfs tapılmadı, squashfs-tools paketinin quraşdırıldığına əmin olun." #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/lang/python/ca/LC_MESSAGES/python.po b/lang/python/ca/LC_MESSAGES/python.po index 236391ceb..66068c65f 100644 --- a/lang/python/ca/LC_MESSAGES/python.po +++ b/lang/python/ca/LC_MESSAGES/python.po @@ -327,6 +327,7 @@ msgstr "No es pot habilitar la destinació de systemd {name!s}." #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." msgstr "" +"No es pot habilitar el temporitzador de systemd {name!s}." #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -406,6 +407,8 @@ msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." msgstr "" +"No s'ha pogut trobar unsquashfs, assegureu-vos que tingueu instal·lat el " +"paquet squashfs-tools." #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/lang/python/de/LC_MESSAGES/python.po b/lang/python/de/LC_MESSAGES/python.po index 0baff8013..ca828a606 100644 --- a/lang/python/de/LC_MESSAGES/python.po +++ b/lang/python/de/LC_MESSAGES/python.po @@ -329,7 +329,7 @@ msgstr "Das systemd-Ziel {name!s} kann nicht aktiviert werden." #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." -msgstr "" +msgstr "Systemd-Timer {name!s} kann nicht aktiviert werden." #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -412,6 +412,8 @@ msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." msgstr "" +"Unsquashfs nicht gefunden, stellen Sie sicher, dass das Paket squashfs-tools" +" installiert ist." #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/lang/python/fa/LC_MESSAGES/python.po b/lang/python/fa/LC_MESSAGES/python.po index 914c8c70c..4c9009666 100644 --- a/lang/python/fa/LC_MESSAGES/python.po +++ b/lang/python/fa/LC_MESSAGES/python.po @@ -6,6 +6,7 @@ # Translators: # Danial Behzadi , 2020 # alireza jamshidi , 2020 +# Mahdy Mirzade , 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: alireza jamshidi , 2020\n" +"Last-Translator: Mahdy Mirzade , 2021\n" "Language-Team: Persian (https://www.transifex.com/calamares/teams/20061/fa/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -62,13 +63,15 @@ msgstr "نصب بارکنندهٔ راه‌اندازی." #: src/modules/bootloader/main.py:508 msgid "Bootloader installation error" -msgstr "" +msgstr "خطای نصب بوت لودر" #: src/modules/bootloader/main.py:509 msgid "" "The bootloader could not be installed. The installation command " "
{!s}
returned error code {!s}." msgstr "" +"بوت لودر نتوانست نصب شود. دستور
{!s}
برای نصب با خطای {!s} مواجه " +"شد." #: src/modules/fstab/main.py:29 msgid "Writing fstab." @@ -77,6 +80,7 @@ msgstr "در حال نوشتن fstab." #: src/modules/fstab/main.py:389 msgid "No
{!s}
configuration is given for
{!s}
to use." msgstr "" +"هیچ تنظیمات
{!s}
برای استفاده برای
{!s}
داده نشده است." #: src/modules/dracut/main.py:27 msgid "Creating initramfs with dracut." @@ -139,6 +143,8 @@ msgid "" "The displaymanagers list is empty or undefined in both globalstorage and " "displaymanager.conf." msgstr "" +"فهرست مدیریت صفحه نمایش ها خالی بوده یا در محل ذخیره داده و " +"displaymanager.conf تعریف نشده است." #: src/modules/displaymanager/main.py:989 msgid "Display manager configuration was incomplete" @@ -161,6 +167,8 @@ msgid "" "Unknown service-action {arg!s} for service {name!s} in run-" "level {level!s}." msgstr "" +"دستور سرویس {arg!s} برای سرویس {name!s} در سطح اجرای {level!s}" +" ناشناخته است." #: src/modules/services-openrc/main.py:93 #: src/modules/services-systemd/main.py:59 @@ -171,6 +179,8 @@ msgstr "نمی‌توان خدمت را دستکاری کرد" msgid "" "rc-update {arg!s} call in chroot returned error code {num!s}." msgstr "" +"فراخوانی rc-update {arg!s} در chroot کد خطای {num!s} را " +"برگرداند." #: src/modules/services-openrc/main.py:101 msgid "Target runlevel does not exist" @@ -181,6 +191,8 @@ msgid "" "The path for runlevel {level!s} is {path!s}, which does not " "exist." msgstr "" +"مسیر برای سطح اجرای {level!s} برابر {path!s} است، که وجود " +"ندارد." #: src/modules/services-openrc/main.py:110 msgid "Target service does not exist" @@ -191,6 +203,7 @@ msgid "" "The path for service {name!s} is {path!s}, which does not " "exist." msgstr "" +"مسیر برای سرویس {name!s} برابر {path!s} است، که وجود ندارد." #: src/modules/networkcfg/main.py:29 msgid "Saving network configuration." @@ -223,25 +236,31 @@ msgstr[1] "در حال برداشتن %(num)d بسته." #: src/modules/packages/main.py:638 src/modules/packages/main.py:650 #: src/modules/packages/main.py:678 msgid "Package Manager error" -msgstr "" +msgstr "خطای مدیر بسته" #: src/modules/packages/main.py:639 msgid "" "The package manager could not prepare updates. The command
{!s}
" "returned error code {!s}." msgstr "" +"مدیر بسته نتوانست برای بروزرسانی ها آماده شود، دستور
{!s}
با خطای" +" {!s} مواجه شد." #: src/modules/packages/main.py:651 msgid "" "The package manager could not update the system. The command
{!s}
" " returned error code {!s}." msgstr "" +"مدیر بسته نتوانست سامانه را بروز کند. دستور
{!s}
با خطای {!s} " +"مواجه شد." #: 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 "" +"مدیر بسته نتوانست تغییرات را برای نصب سامانه انجام دهد. دستور " +"
{!s}
با خطای {!s} مواجه شد." #: src/modules/plymouthcfg/main.py:27 msgid "Configure Plymouth theme" @@ -306,7 +325,7 @@ msgstr "نمی‌توان هدف سیستم‌دی {name!s} را ب #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." -msgstr "" +msgstr "نمی‌توان تایمر سیستم‌دی {name!s} را به کار انداخت." #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -326,11 +345,11 @@ msgstr "" #: src/modules/mkinitfs/main.py:27 msgid "Creating initramfs with mkinitfs." -msgstr "" +msgstr "درحال ایجاد initramfs با mkinitfs." #: src/modules/mkinitfs/main.py:49 msgid "Failed to run mkinitfs on the target" -msgstr "" +msgstr "شکست در اجرا mkinitfs روی هدف" #: src/modules/unpackfs/main.py:34 msgid "Filling up filesystems." @@ -385,7 +404,7 @@ msgstr "سامانهٔ پروندهٔ مبدأ {} وجود ندارد" msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." -msgstr "" +msgstr "شکست در یافتن unsquashfs. مطمئن شوید بسته squashfs-tools نصب است." #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/lang/python/hr/LC_MESSAGES/python.po b/lang/python/hr/LC_MESSAGES/python.po index 796af7448..5be3da384 100644 --- a/lang/python/hr/LC_MESSAGES/python.po +++ b/lang/python/hr/LC_MESSAGES/python.po @@ -325,7 +325,7 @@ msgstr "Ne mogu omogućiti systemd cilj {name!s}." #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." -msgstr "" +msgstr "Nije moguće omogućiti systemd timer {name!s}." #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -405,6 +405,8 @@ msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." msgstr "" +"Neuspješno pronalaženje unsquashfs, provjerite imate li instaliran paket " +"squashfs-tools." #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/lang/python/ko/LC_MESSAGES/python.po b/lang/python/ko/LC_MESSAGES/python.po index 4e1aa1e1e..177ce25f7 100644 --- a/lang/python/ko/LC_MESSAGES/python.po +++ b/lang/python/ko/LC_MESSAGES/python.po @@ -307,7 +307,7 @@ msgstr "systemd 대상 {name! s}를 활성화 할 수 없습니다. #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." -msgstr "" +msgstr "시스템 타이머 {name!s}를 활성화할 수 없습니다." #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -386,7 +386,7 @@ msgstr "\"{}\" 소스 파일시스템은 존재하지 않습니다." msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." -msgstr "" +msgstr "unsquashfs를 찾지 못했습니다. squashfs-tools 패키지가 설치되어 있는지 확인하십시오." #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/lang/python/pt_PT/LC_MESSAGES/python.po b/lang/python/pt_PT/LC_MESSAGES/python.po index bbca55b84..7f10d0c95 100644 --- a/lang/python/pt_PT/LC_MESSAGES/python.po +++ b/lang/python/pt_PT/LC_MESSAGES/python.po @@ -329,7 +329,7 @@ msgstr "Não é possível ativar o destino do systemd {name!s}." #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." -msgstr "" +msgstr "Não é possível ativar o temporizador systemd {name!s}." #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -411,6 +411,8 @@ msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." msgstr "" +"Falha ao localizar o unsquashfs, certifique-se de que tem o pacote squashfs-" +"tools instalado." #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/lang/python/si/LC_MESSAGES/python.po b/lang/python/si/LC_MESSAGES/python.po index 545e074ca..76ce5f160 100644 --- a/lang/python/si/LC_MESSAGES/python.po +++ b/lang/python/si/LC_MESSAGES/python.po @@ -5,6 +5,7 @@ # # Translators: # හෙළබස, 2021 +# Sandaruwan Samaraweera, 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: හෙළබස, 2021\n" +"Last-Translator: Sandaruwan Samaraweera, 2021\n" "Language-Team: Sinhala (https://www.transifex.com/calamares/teams/20061/si/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -23,7 +24,7 @@ msgstr "" #: src/modules/initramfscfg/main.py:32 msgid "Configuring initramfs." -msgstr "" +msgstr "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 @@ -35,161 +36,169 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:86 #: src/modules/luksopenswaphookcfg/main.py:90 msgid "Configuration Error" -msgstr "" +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 "" +msgstr "{!s} සඳහා භාවිතා කිරීමට කිසිදු කොටස් නිර්වචනය කර නොමැත." #: 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 "{!s} සඳහා භාවිතා කිරීමට root mount point ලබා දී නොමැත." #: src/modules/grubcfg/main.py:28 msgid "Configure GRUB." -msgstr "" +msgstr "GRUB වින්‍යාස කරන්න." #: src/modules/bootloader/main.py:43 msgid "Install bootloader." -msgstr "" +msgstr "bootloader ස්ථාපනය කරන්න." #: src/modules/bootloader/main.py:508 msgid "Bootloader installation error" -msgstr "" +msgstr "Bootloader ස්ථාපනය කිරීමේ දෝෂයකි" #: src/modules/bootloader/main.py:509 msgid "" "The bootloader could not be installed. The installation command " "
{!s}
returned error code {!s}." msgstr "" +"ඇරඹුම් කාරකය ස්ථාපනය කල නොහැක. ස්ථාපන විධානය
{!s}
දෝෂ කේතය {!s} " +"ලබා දුන්නේය." #: src/modules/fstab/main.py:29 msgid "Writing fstab." -msgstr "" +msgstr "fstab ලියමින්." #: src/modules/fstab/main.py:389 msgid "No
{!s}
configuration is given for
{!s}
to use." msgstr "" +"භාවිතා කිරීමට
{!s}
සඳහා
{!s}
වින්‍යාසයක් ලබා දී නොමැත." #: src/modules/dracut/main.py:27 msgid "Creating initramfs with dracut." -msgstr "" +msgstr "dracut සමඟ initramfs නිර්මාණය කිරීම." #: src/modules/dracut/main.py:49 msgid "Failed to run dracut on the target" -msgstr "" +msgstr "ඉලක්කය මත ඩ්‍රැකට් ධාවනය කිරීමට අපොහොසත් විය" #: src/modules/dracut/main.py:50 src/modules/mkinitfs/main.py:50 msgid "The exit code was {}" -msgstr "" +msgstr "පිටවීමේ කේතය වූයේ {}" #: src/modules/displaymanager/main.py:526 msgid "Cannot write KDM configuration file" -msgstr "" +msgstr "KDM වින්‍යාස ගොනුව ලිවිය නොහැක" #: src/modules/displaymanager/main.py:527 msgid "KDM config file {!s} does not exist" -msgstr "" +msgstr "KDM වින්‍යාස ගොනුව {!s} නොපවතී" #: src/modules/displaymanager/main.py:588 msgid "Cannot write LXDM configuration file" -msgstr "" +msgstr "LXDM වින්‍යාස ගොනුව ලිවිය නොහැක" #: src/modules/displaymanager/main.py:589 msgid "LXDM config file {!s} does not exist" -msgstr "" +msgstr "LXDM වින්‍යාස ගොනුව {!s} නොපවතී" #: src/modules/displaymanager/main.py:672 msgid "Cannot write LightDM configuration file" -msgstr "" +msgstr "LightDM වින්‍යාස ගොනුව ලිවිය නොහැක" #: src/modules/displaymanager/main.py:673 msgid "LightDM config file {!s} does not exist" -msgstr "" +msgstr "LightDM වින්‍යාස ගොනුව {!s} නොපවතී" #: src/modules/displaymanager/main.py:747 msgid "Cannot configure LightDM" -msgstr "" +msgstr "LightDM වින්‍යාස කළ නොහැක" #: src/modules/displaymanager/main.py:748 msgid "No LightDM greeter installed." -msgstr "" +msgstr "LightDM ග්‍රීටර් ස්ථාපනය කර නැත." #: src/modules/displaymanager/main.py:779 msgid "Cannot write SLIM configuration file" -msgstr "" +msgstr "SLIM වින්‍යාස ගොනුව ලිවිය නොහැක" #: src/modules/displaymanager/main.py:780 msgid "SLIM config file {!s} does not exist" -msgstr "" +msgstr "SLIM වින්‍යාස ගොනුව {!s} නොපවතී" #: src/modules/displaymanager/main.py:906 msgid "No display managers selected for the displaymanager module." -msgstr "" +msgstr "සංදර්ශක කළමනාකරු මොඩියුලය සඳහා සංදර්ශක කළමනාකරුවන් තෝරාගෙන නොමැත." #: src/modules/displaymanager/main.py:907 msgid "" "The displaymanagers list is empty or undefined in both globalstorage and " "displaymanager.conf." msgstr "" +"ගෝලීය ගබඩාව සහ displaymanager.conf යන දෙකෙහිම සංදර්ශක කළමනාකරු ලැයිස්තුව " +"හිස් හෝ අර්ථ දක්වා නොමැත." #: src/modules/displaymanager/main.py:989 msgid "Display manager configuration was incomplete" -msgstr "" +msgstr "සංදර්ශක කළමනාකරු වින්‍යාසය අසම්පූර්ණ විය" #: src/modules/services-openrc/main.py:29 msgid "Configure OpenRC services" -msgstr "" +msgstr "OpenRC සේවා වින්‍යාස කරන්න" #: src/modules/services-openrc/main.py:57 msgid "Cannot add service {name!s} to run-level {level!s}." -msgstr "" +msgstr "ධාවන මට්ටම {level!s} වෙත සේවාව {name!s} එක් කළ නොහැක." #: src/modules/services-openrc/main.py:59 msgid "Cannot remove service {name!s} from run-level {level!s}." -msgstr "" +msgstr "ධාවන මට්ටමේ {level!s} වෙතින් සේවාව {name!s} ඉවත් කළ නොහැක." #: src/modules/services-openrc/main.py:61 msgid "" "Unknown service-action {arg!s} for service {name!s} in run-" "level {level!s}." msgstr "" +"{name!s} සේවාව සඳහා නොදන්නා සේවා-ක්‍රියාව {arg!s} ධාවන මට්ටමේ " +"{level!s}." #: src/modules/services-openrc/main.py:93 #: src/modules/services-systemd/main.py:59 msgid "Cannot modify service" -msgstr "" +msgstr "සේවාව වෙනස් කළ නොහැක" #: src/modules/services-openrc/main.py:94 msgid "" "rc-update {arg!s} call in chroot returned error code {num!s}." msgstr "" +"rc-update {arg!s} chroot හි ඇමතුම {num!s} දෝෂ කේතය ලබා දුන්නේය." #: src/modules/services-openrc/main.py:101 msgid "Target runlevel does not exist" -msgstr "" +msgstr "ඉලක්ක ධාවන මට්ටම නොපවතී" #: src/modules/services-openrc/main.py:102 msgid "" "The path for runlevel {level!s} is {path!s}, which does not " "exist." -msgstr "" +msgstr "ධාවන මට්ටම {level!s} සඳහා මාර්ගය {path!s}, එය නොපවතී." #: src/modules/services-openrc/main.py:110 msgid "Target service does not exist" -msgstr "" +msgstr "ඉලක්ක සේවාව නොපවතී" #: src/modules/services-openrc/main.py:111 msgid "" "The path for service {name!s} is {path!s}, which does not " "exist." -msgstr "" +msgstr "සේවාව සඳහා {name!s} මාර්ගය {path!s}, එය නොපවතී." #: src/modules/networkcfg/main.py:29 msgid "Saving network configuration." @@ -203,7 +212,7 @@ msgstr "ඇසුරුම් ස්ථාපනය කරන්න." #: src/modules/packages/main.py:57 #, python-format msgid "Processing packages (%(count)d / %(total)d)" -msgstr "" +msgstr "පැකේජ සැකසීම (%(count)d / %(total)d)" #: src/modules/packages/main.py:62 #, python-format @@ -222,41 +231,47 @@ msgstr[1] "ඇසුරුම් %(num)d ක් ඉවත් වෙමින්. #: src/modules/packages/main.py:638 src/modules/packages/main.py:650 #: src/modules/packages/main.py:678 msgid "Package Manager error" -msgstr "" +msgstr "පැකේජ කළමනාකරු දෝෂයකි" #: src/modules/packages/main.py:639 msgid "" "The package manager could not prepare updates. The command
{!s}
" "returned error code {!s}." msgstr "" +"පැකේජ කළමනාකරුට යාවත්කාලීන සකස් කිරීමට නොහැකි විය. විධානය
{!s}
" +"දෝෂ කේතය {!s} ලබා දුන්නේය." #: src/modules/packages/main.py:651 msgid "" "The package manager could not update the system. The command
{!s}
" " returned error code {!s}." msgstr "" +"පැකේජ කළමනාකරුට පද්ධතිය යාවත්කාලීන කළ නොහැකි විය. විධානය
{!s}
දෝෂ" +" කේතය {!s} ලබා දුන්නේය." #: 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 "" +"පැකේජ කළමනාකරුට ස්ථාපිත පද්ධතියට වෙනස්කම් සිදු කළ නොහැක. විධානය " +"
{!s}
දෝෂ කේතය {!s} ලබා දුන්නේය." #: src/modules/plymouthcfg/main.py:27 msgid "Configure Plymouth theme" -msgstr "" +msgstr "Plymouth තේමාව වින්‍යාස කරන්න" #: src/modules/initcpiocfg/main.py:28 msgid "Configuring mkinitcpio." -msgstr "" +msgstr "mkinitcpio වින්‍යාස කරමින්." #: src/modules/localecfg/main.py:30 msgid "Configuring locales." -msgstr "" +msgstr "ස්ථාන වින්‍යාස කිරීම." #: src/modules/mount/main.py:30 msgid "Mounting partitions." -msgstr "" +msgstr "කොටස් සවි කිරීම." #: src/modules/rawfs/main.py:26 msgid "Installing data." @@ -264,12 +279,12 @@ msgstr "දත්ත ස්ථාපනය වෙමින්." #: src/modules/dummypython/main.py:35 msgid "Dummy python job." -msgstr "" +msgstr "ඩමි python වැඩසටහන." #: src/modules/dummypython/main.py:37 src/modules/dummypython/main.py:93 #: src/modules/dummypython/main.py:94 msgid "Dummy python step {}" -msgstr "" +msgstr "ව්‍යාජ python පියවර {}" #: src/modules/hwclock/main.py:26 msgid "Setting hardware clock." @@ -277,115 +292,120 @@ msgstr "දෘඩාංග ඔරලෝසුව සැකසෙමින්." #: src/modules/umount/main.py:31 msgid "Unmount file systems." -msgstr "" +msgstr "ගොනු පද්ධති ඉවත් කරන්න." #: src/modules/openrcdmcryptcfg/main.py:26 msgid "Configuring OpenRC dmcrypt service." -msgstr "" +msgstr "OpenRC dmcrypt සේවාව වින්‍යාස කරමින්." #: src/modules/services-systemd/main.py:26 msgid "Configure systemd services" -msgstr "" +msgstr "systemd සේවා වින්‍යාස කරන්න" #: src/modules/services-systemd/main.py:60 msgid "" "systemctl {arg!s} call in chroot returned error code {num!s}." msgstr "" +"systemctl {arg!s} chroot වෙත ඇමතුමක් ලබා දුන් දෝෂ කේතය {num!s}." #: src/modules/services-systemd/main.py:63 #: src/modules/services-systemd/main.py:69 msgid "Cannot enable systemd service {name!s}." -msgstr "" +msgstr "systemd සේවාව {name!s} සබල කළ නොහැක." #: src/modules/services-systemd/main.py:65 msgid "Cannot enable systemd target {name!s}." -msgstr "" +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}." -msgstr "" +msgstr "systemd ඉලක්කය {name!s} අක්‍රිය කළ නොහැක." #: src/modules/services-systemd/main.py:73 msgid "Cannot mask systemd unit {name!s}." -msgstr "" +msgstr "systemd ඒකකය {name!s} වසන් කළ නොහැක." #: src/modules/services-systemd/main.py:75 msgid "" "Unknown systemd commands {command!s} and " "{suffix!s} for unit {name!s}." msgstr "" +"{name!s} ඒකකය සඳහා නොදන්නා systemd විධාන {command!s} සහ " +"{suffix!s}." #: src/modules/mkinitfs/main.py:27 msgid "Creating initramfs with mkinitfs." -msgstr "" +msgstr "mkinitfs සමඟ initramfs නිර්මාණය කිරීම." #: src/modules/mkinitfs/main.py:49 msgid "Failed to run mkinitfs on the target" -msgstr "" +msgstr "ඉලක්කය මත mkinitfs ධාවනය කිරීමට අසමත් විය" #: src/modules/unpackfs/main.py:34 msgid "Filling up filesystems." -msgstr "" +msgstr "ගොනු පද්ධති පිරවීම." #: src/modules/unpackfs/main.py:254 msgid "rsync failed with error code {}." -msgstr "" +msgstr "දෝෂ කේතය {} සමඟ rsync අසාර්ථක විය." #: src/modules/unpackfs/main.py:299 msgid "Unpacking image {}/{}, file {}/{}" -msgstr "" +msgstr "රූපය {}/{}, ගොනුව {}/{} අසුරමින්" #: src/modules/unpackfs/main.py:314 msgid "Starting to unpack {}" -msgstr "" +msgstr "ඉවත් කිරීමට පටන් ගනියි {}" #: src/modules/unpackfs/main.py:323 src/modules/unpackfs/main.py:465 msgid "Failed to unpack image \"{}\"" -msgstr "" +msgstr "\"{}\" රූපය ඉවත් කිරීමට අසමත් විය" #: src/modules/unpackfs/main.py:430 msgid "No mount point for root partition" -msgstr "" +msgstr "root කොටස සඳහා සවි කිරීමේ ලක්ෂ්‍යයක් නොමැත" #: src/modules/unpackfs/main.py:431 msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" -msgstr "" +msgstr "ගෝලීය ගබඩාවේ \"rootMountPoint\" යතුරක් අඩංගු නොවේ, කිසිවක් නොකරයි" #: src/modules/unpackfs/main.py:436 msgid "Bad mount point for root partition" -msgstr "" +msgstr "මූල කොටස සඳහා නරක සවි කිරීමේ ලක්ෂ්‍යය" #: src/modules/unpackfs/main.py:437 msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" -msgstr "" +msgstr "rootMountPoint යනු \"{}\", එය නොපවතින, කිසිවක් නොකරයි" #: 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 "" +msgstr "නරක unsquash වින්‍යාසය" #: src/modules/unpackfs/main.py:454 msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel" -msgstr "" +msgstr "\"{}\" ({}) සඳහා ගොනු පද්ධතිය ඔබගේ වත්මන් කර්නලයෙන් සහය නොදක්වයි" #: src/modules/unpackfs/main.py:458 msgid "The source filesystem \"{}\" does not exist" -msgstr "" +msgstr "මූලාශ්‍ර ගොනු පද්ධතිය \"{}\" නොපවතී" #: src/modules/unpackfs/main.py:464 msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." msgstr "" +"Unsquashfs සොයා ගැනීමට අපොහොසත් විය, ඔබ squashfs-tools පැකේජය ස්ථාපනය කර ඇති" +" බවට වග බලා ගන්න." #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" -msgstr "" +msgstr "ඉලක්ක පද්ධතියේ \"{}\" ගමනාන්තය නාමාවලියක් නොවේ" #: src/modules/luksopenswaphookcfg/main.py:26 msgid "Configuring encrypted swap." -msgstr "" +msgstr "සංකේතාත්මක swap වින්‍යාස කිරීම." diff --git a/lang/python/sv/LC_MESSAGES/python.po b/lang/python/sv/LC_MESSAGES/python.po index e91510fb2..86832e8a3 100644 --- a/lang/python/sv/LC_MESSAGES/python.po +++ b/lang/python/sv/LC_MESSAGES/python.po @@ -327,7 +327,7 @@ msgstr "Kunde inte aktivera systemd målsystem {name!s}." #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." -msgstr "" +msgstr "Kunde inte aktivera systemd timer {name!s}." #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -407,6 +407,8 @@ msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." msgstr "" +"Kunde inte hitta unsquashfs, se till att du har paketet squashfs-tools " +"installerat" #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/lang/python/tr_TR/LC_MESSAGES/python.po b/lang/python/tr_TR/LC_MESSAGES/python.po index 90d0345e6..df566cfec 100644 --- a/lang/python/tr_TR/LC_MESSAGES/python.po +++ b/lang/python/tr_TR/LC_MESSAGES/python.po @@ -322,7 +322,7 @@ msgstr "Systemd hedefi etkinleştirilemiyor {name!s}." #: src/modules/services-systemd/main.py:67 msgid "Cannot enable systemd timer {name!s}." -msgstr "" +msgstr "{name!s} sistem zamanlayıcısı etkinleştirilemiyor." #: src/modules/services-systemd/main.py:71 msgid "Cannot disable systemd target {name!s}." @@ -403,6 +403,7 @@ msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed." msgstr "" +"Unsquashfs bulunamadı, squashfs-tools paketinin kurulu olduğundan emin olun." #: src/modules/unpackfs/main.py:479 msgid "The destination \"{}\" in the target system is not a directory" diff --git a/settings.conf b/settings.conf index 57e58e732..10a058ce4 100644 --- a/settings.conf +++ b/settings.conf @@ -122,6 +122,7 @@ sequence: - summary - exec: - partition +# - zfs - mount - unpackfs - machineid diff --git a/src/libcalamares/Job.h b/src/libcalamares/Job.h index 58a9bba39..33965e15f 100644 --- a/src/libcalamares/Job.h +++ b/src/libcalamares/Job.h @@ -132,6 +132,11 @@ public: void setEmergency( bool e ) { m_emergency = e; } signals: + /** @brief Signals that the job has made progress + * + * The parameter @p percent should be between 0 (0%) and 1 (100%). + * Values outside of this range will be clamped. + */ void progress( qreal percent ); private: diff --git a/src/libcalamares/utils/Logger.cpp b/src/libcalamares/utils/Logger.cpp index 79ae873db..d35d6891b 100644 --- a/src/libcalamares/utils/Logger.cpp +++ b/src/libcalamares/utils/Logger.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -229,7 +231,7 @@ toString( const QVariant& v ) } QDebug& -operator<<( QDebug& s, const Redacted& l ) +operator<<( QDebug& s, const RedactedCommand& l ) { // Special case logging: don't log the (encrypted) password. if ( l.list.contains( "usermod" ) ) @@ -252,4 +254,33 @@ operator<<( QDebug& s, const Redacted& l ) return s; } +/** @brief Returns a stable-but-private hash of @p context and @p s + * + * Identical strings with the same context will be hashed the same, + * so that they can be logged and still recognized as the-same. + */ +static uint insertRedactedName( const QString& context, const QString& s ) +{ + static uint salt = QRandomGenerator::global()->generate(); // Just once + + uint val = qHash(context, salt); + return qHash(s, val); +} + +RedactedName::RedactedName( const QString& context, const QString& s ) + : m_id( insertRedactedName(context, s) ), + m_context(context) +{ +} + +RedactedName::RedactedName(const char *context, const QString& s ) + : RedactedName( QString::fromLatin1( context ), s ) +{ +} + +RedactedName::operator QString() const +{ + return QString( m_context + '$' + QString::number( m_id, 16 ) ); +} + } // namespace Logger diff --git a/src/libcalamares/utils/Logger.h b/src/libcalamares/utils/Logger.h index bf6b99d00..0d7d5c870 100644 --- a/src/libcalamares/utils/Logger.h +++ b/src/libcalamares/utils/Logger.h @@ -145,8 +145,8 @@ public: { } - const T& first; - const U& second; + const T first; + const U second; }; /** @@ -214,9 +214,9 @@ public: * since the log may get posted to bug reports, or stored in * the target system. */ -struct Redacted +struct RedactedCommand { - Redacted( const QStringList& l ) + RedactedCommand( const QStringList& l ) : list( l ) { } @@ -224,7 +224,30 @@ struct Redacted const QStringList& list; }; -QDebug& operator<<( QDebug& s, const Redacted& l ); +QDebug& operator<<( QDebug& s, const RedactedCommand& l ); + +/** @brief When logging "private" identifiers, keep them consistent but private + * + * Send a string to a logger in such a way that each time it is logged, + * it logs the same way, but without revealing the actual contents. + * This can be applied to user names, UUIDs, etc. + */ +struct RedactedName +{ + RedactedName( const char* context, const QString& s ); + RedactedName( const QString& context, const QString& s ); + + operator QString() const; + +private: + const uint m_id; + const QString m_context; +}; + +inline QDebug& operator<<( QDebug& s, const RedactedName& n ) +{ + return s << NoQuote << QString( n ) << Quote; +} /** * @brief Formatted logging of a pointer diff --git a/src/libcalamares/utils/Runner.cpp b/src/libcalamares/utils/Runner.cpp index e138b1c68..c7146c2d7 100644 --- a/src/libcalamares/utils/Runner.cpp +++ b/src/libcalamares/utils/Runner.cpp @@ -163,7 +163,7 @@ Calamares::Utils::Runner::run() } ); } - cDebug() << Logger::SubEntry << "Running" << Logger::Redacted( m_command ); + cDebug() << Logger::SubEntry << "Running" << Logger::RedactedCommand( m_command ); process.start(); if ( !process.waitForStarted() ) { @@ -225,13 +225,13 @@ Calamares::Utils::Runner::run() { if ( !output.isEmpty() ) { - cDebug() << Logger::SubEntry << "Target cmd:" << Logger::Redacted( m_command ) << "Exit code:" << r + cDebug() << Logger::SubEntry << "Target cmd:" << Logger::RedactedCommand( m_command ) << "Exit code:" << r << "output:\n" << Logger::NoQuote << output; } else { - cDebug() << Logger::SubEntry << "Target cmd:" << Logger::Redacted( m_command ) << "Exit code:" << r + cDebug() << Logger::SubEntry << "Target cmd:" << Logger::RedactedCommand( m_command ) << "Exit code:" << r << "(no output)"; } } diff --git a/src/modules/README.md b/src/modules/README.md index 683ca9bc3..7b4d4b3a3 100644 --- a/src/modules/README.md +++ b/src/modules/README.md @@ -398,7 +398,9 @@ target_env_process_output(["ls"]) ``` The functions return 0. If the exit code of *command* is not 0, an exception -is raised instead of returning 0. +is raised instead of returning 0. The exception is `subprocess.CalledProcessError` +(as if the *subprocess* module had been used), and the `returncode` member +of the exception object can be used to determine the exit code. Parameter *stdin* may be a string which is fed to the command as standard input. The *timeout* is in seconds, with 0 (or a negative number) treated as no-timeout. diff --git a/src/modules/bootloader/main.py b/src/modules/bootloader/main.py index 68cbddd0e..25c7e0d9b 100644 --- a/src/modules/bootloader/main.py +++ b/src/modules/bootloader/main.py @@ -92,6 +92,50 @@ def get_kernel_line(kernel_type): return "" +def get_zfs_root(): + """ + Looks in global storage to find the zfs root + + :return: A string containing the path to the zfs root or None if it is not found + """ + + zfs = libcalamares.globalstorage.value("zfsDatasets") + + if not zfs: + libcalamares.utils.warning("Failed to locate zfs dataset list") + return None + + # Find the root dataset + for dataset in zfs: + try: + if dataset["mountpoint"] == "/": + return dataset["zpool"] + "/" + dataset["dsName"] + except KeyError: + # This should be impossible + libcalamares.utils.warning("Internal error handling zfs dataset") + raise + + return None + + +def is_btrfs_root(partition): + """ Returns True if the partition object refers to a btrfs root filesystem + + :param partition: A partition map from global storage + :return: True if btrfs and root, False otherwise + """ + return partition["mountPoint"] == "/" and partition["fs"] == "btrfs" + + +def is_zfs_root(partition): + """ Returns True if the partition object refers to a zfs root filesystem + + :param partition: A partition map from global storage + :return: True if zfs and root, False otherwise + """ + return partition["mountPoint"] == "/" and partition["fs"] == "zfs" + + def create_systemd_boot_conf(install_path, efi_dir, uuid, entry, entry_name, kernel_type): """ Creates systemd-boot configuration files based on given parameters. @@ -133,11 +177,24 @@ def create_systemd_boot_conf(install_path, efi_dir, uuid, entry, entry_name, ker "root=/dev/mapper/" + partition["luksMapperName"]] - # systemd-boot with a BTRFS root filesystem needs to be told - # about the root subvolume. for partition in partitions: - if partition["mountPoint"] == "/" and partition["fs"] == "btrfs": - kernel_params.append("rootflags=subvol=@") + # systemd-boot with a BTRFS root filesystem needs to be told abouut the root subvolume. + # If a btrfs root subvolume wasn't set, it means the root is directly on the partition + # and this option isn't needed + if is_btrfs_root(partition): + btrfs_root_subvolume = libcalamares.globalstorage.value("btrfsRootSubvolume") + if btrfs_root_subvolume: + kernel_params.append("rootflags=subvol=" + btrfs_root_subvolume) + + # zfs needs to be told the location of the root dataset + if is_zfs_root(partition): + zfs_root_path = get_zfs_root() + if zfs_root_path is not None: + kernel_params.append("zfs=" + zfs_root_path) + else: + # Something is really broken if we get to this point + libcalamares.utils.warning("Internal error handling zfs dataset") + raise Exception("Internal zfs data missing, please contact your distribution") if cryptdevice_params: kernel_params.extend(cryptdevice_params) @@ -314,6 +371,76 @@ def get_grub_efi_parameters(): return None +def run_grub_mkconfig(partitions, output_file): + """ + Runs grub-mkconfig in the target environment + + :param partitions: The partitions list from global storage + :param output_file: A string containing the path to the generating grub config file + :return: + """ + + # zfs needs an environment variable set for grub-mkconfig + if any([is_zfs_root(partition) for partition in partitions]): + check_target_env_call(["sh", "-c", "ZPOOL_VDEV_NAME_PATH=1 " + + libcalamares.job.configuration["grubMkconfig"] + " -o " + output_file]) + else: + # The input file /etc/default/grub should already be filled out by the + # grubcfg job module. + check_target_env_call([libcalamares.job.configuration["grubMkconfig"], "-o", output_file]) + + +def run_grub_install(fw_type, partitions, efi_directory=None): + """ + Runs grub-install in the target environment + + :param fw_type: A string which is "efi" for UEFI installs. Any other value results in a BIOS install + :param partitions: The partitions list from global storage + :param efi_directory: The path of the efi directory relative to the root of the install + :return: + """ + + is_zfs = any([is_zfs_root(partition) for partition in partitions]) + + # zfs needs an environment variable set for grub + if is_zfs: + check_target_env_call(["sh", "-c", "echo ZPOOL_VDEV_NAME_PATH=1 >> /etc/environment"]) + + if fw_type == "efi": + efi_bootloader_id = efi_label() + efi_target, efi_grub_file, efi_boot_file = get_grub_efi_parameters() + + if is_zfs: + check_target_env_call(["sh", "-c", "ZPOOL_VDEV_NAME_PATH=1 " + libcalamares.job.configuration["grubInstall"] + + " --target=" + efi_target + " --efi-directory=" + efi_directory + + " --bootloader-id=" + efi_bootloader_id + " --force"]) + else: + check_target_env_call([libcalamares.job.configuration["grubInstall"], + "--target=" + efi_target, + "--efi-directory=" + efi_directory, + "--bootloader-id=" + efi_bootloader_id, + "--force"]) + else: + if libcalamares.globalstorage.value("bootLoader") is None: + return + + boot_loader = libcalamares.globalstorage.value("bootLoader") + if boot_loader["installPath"] is None: + return + + if is_zfs: + check_target_env_call(["sh", "-c", "ZPOOL_VDEV_NAME_PATH=1 " + + libcalamares.job.configuration["grubInstall"] + + " --target=i386-pc --recheck --force " + + boot_loader["installPath"]]) + else: + check_target_env_call([libcalamares.job.configuration["grubInstall"], + "--target=i386-pc", + "--recheck", + "--force", + boot_loader["installPath"]]) + + def install_grub(efi_directory, fw_type): """ Installs grub as bootloader, either in pc or efi mode. @@ -321,6 +448,12 @@ def install_grub(efi_directory, fw_type): :param efi_directory: :param fw_type: """ + # get the partition from global storage + partitions = libcalamares.globalstorage.value("partitions") + if not partitions: + libcalamares.utils.warning(_("Failed to install grub, no partitions defined in global storage")) + return + if fw_type == "efi": libcalamares.utils.debug("Bootloader: grub (efi)") install_path = libcalamares.globalstorage.value("rootMountPoint") @@ -333,11 +466,7 @@ def install_grub(efi_directory, fw_type): efi_target, efi_grub_file, efi_boot_file = get_grub_efi_parameters() - check_target_env_call([libcalamares.job.configuration["grubInstall"], - "--target=" + efi_target, - "--efi-directory=" + efi_directory, - "--bootloader-id=" + efi_bootloader_id, - "--force"]) + run_grub_install(fw_type, partitions, efi_directory) # VFAT is weird, see issue CAL-385 install_efi_directory_firmware = (vfat_correct_case( @@ -356,36 +485,21 @@ def install_grub(efi_directory, fw_type): os.makedirs(install_efi_boot_directory) # Workaround for some UEFI firmwares - FALLBACK = "installEFIFallback" - libcalamares.utils.debug("UEFI Fallback: " + str(libcalamares.job.configuration.get(FALLBACK, ""))) - if libcalamares.job.configuration.get(FALLBACK, True): + fallback = "installEFIFallback" + libcalamares.utils.debug("UEFI Fallback: " + str(libcalamares.job.configuration.get(fallback, ""))) + if libcalamares.job.configuration.get(fallback, True): libcalamares.utils.debug(" .. installing '{!s}' fallback firmware".format(efi_boot_file)) efi_file_source = os.path.join(install_efi_directory_firmware, - efi_bootloader_id, - efi_grub_file) - efi_file_target = os.path.join(install_efi_boot_directory, - efi_boot_file) + efi_bootloader_id, + efi_grub_file) + efi_file_target = os.path.join(install_efi_boot_directory, efi_boot_file) shutil.copy2(efi_file_source, efi_file_target) else: libcalamares.utils.debug("Bootloader: grub (bios)") - if libcalamares.globalstorage.value("bootLoader") is None: - return + run_grub_install(fw_type, partitions) - boot_loader = libcalamares.globalstorage.value("bootLoader") - if boot_loader["installPath"] is None: - return - - check_target_env_call([libcalamares.job.configuration["grubInstall"], - "--target=i386-pc", - "--recheck", - "--force", - boot_loader["installPath"]]) - - # The input file /etc/default/grub should already be filled out by the - # grubcfg job module. - check_target_env_call([libcalamares.job.configuration["grubMkconfig"], - "-o", libcalamares.job.configuration["grubCfg"]]) + run_grub_mkconfig(partitions, libcalamares.job.configuration["grubCfg"]) def install_secureboot(efi_directory): diff --git a/src/modules/displaymanager/displaymanager.conf b/src/modules/displaymanager/displaymanager.conf index 7175c112d..0fd2af163 100644 --- a/src/modules/displaymanager/displaymanager.conf +++ b/src/modules/displaymanager/displaymanager.conf @@ -23,6 +23,7 @@ displaymanagers: - mdm - lxdm - kdm + - greetd # Enable the following settings to force a desktop environment # in your displaymanager configuration file. This will attempt diff --git a/src/modules/displaymanager/displaymanager.schema.yaml b/src/modules/displaymanager/displaymanager.schema.yaml index fc28fd66d..89d657a3b 100644 --- a/src/modules/displaymanager/displaymanager.schema.yaml +++ b/src/modules/displaymanager/displaymanager.schema.yaml @@ -10,7 +10,7 @@ properties: type: array items: type: string - enum: [slim, sddm, lightdm, gdm, mdm, lxdm, kdm] + enum: [slim, sddm, lightdm, gdm, mdm, lxdm, kdm, greetd] minItems: 1 # Must be non-empty, if present at all defaultDesktopEnvironment: type: object diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 5fb228682..3cfdb069a 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -17,9 +17,7 @@ import abc import os -import re import libcalamares -import configparser from libcalamares.utils import gettext_path, gettext_languages @@ -796,6 +794,8 @@ class DMsddm(DisplayManager): executable = "sddm" def set_autologin(self, username, do_autologin, default_desktop_environment): + import configparser + # Systems with Sddm as Desktop Manager sddm_conf_path = os.path.join(self.root_mount_point, "etc/sddm.conf") @@ -835,6 +835,91 @@ class DMsddm(DisplayManager): pass +class DMgreetd(DisplayManager): + name = "greetd" + executable = "greetd" + greeter_user = "greeter" + greeter_group = "greetd" + config_data = {} + + def os_path(self, path): + return os.path.join(self.root_mount_point, path) + + def config_path(self): + return self.os_path("etc/greetd/config.toml") + + def environments_path(self): + return self.os_path("etc/greetd/environments") + + def config_load(self): + import toml + + if (os.path.exists(self.config_path())): + with open(self.config_path(), "r") as f: + self.config_data = toml.load(f) + + self.config_data['terminal'] = dict(vt = "next") + + default_session_group = self.config_data.get('default_session', None) + if not default_session_group: + self.config_data['default_session'] = {} + + self.config_data['default_session']['user'] = self.greeter_user + + return self.config_data + + def config_write(self): + import toml + with open(self.config_path(), "w") as f: + toml.dump(self.config_data, f) + + def basic_setup(self): + if libcalamares.utils.target_env_call( + ['getent', 'group', self.greeter_group] + ) != 0: + libcalamares.utils.target_env_call( + ['groupadd', self.greeter_group] + ) + + if libcalamares.utils.target_env_call( + ['getent', 'passwd', self.greeter_user] + ) != 0: + libcalamares.utils.target_env_call( + ['useradd', + '-c', '"Greeter User"', + '-g', self.greeter_group, + '-s', '/bin/bash', + self.greeter_user + ] + ) + + def desktop_environment_setup(self, default_desktop_environment): + with open(self.environments_path(), 'w') as envs_file: + envs_file.write(default_desktop_environment) + + def greeter_setup(self): + pass + + def set_autologin(self, username, do_autologin, default_desktop_environment): + self.config_load() + + de_command = default_desktop_environment.executable + if os.path.exists(self.os_path("usr/bin/gtkgreed")) and os.path.exists(self.os_path("usr/bin/cage")): + self.config_data['default_session']['command'] = "cage -s -- gtkgreet" + elif os.path.exists(self.os_path("usr/bin/tuigreet")): + tuigreet_base_cmd = "tuigreet --remember --time --issue --asterisks --cmd " + self.config_data['default_session']['command'] = tuigreet_base_cmd + de_command + elif os.path.exists(self.os_path("usr/bin/ddlm")): + self.config_data['default_session']['command'] = "ddlm --target " + de_command + else: + self.config_data['default_session']['command'] = "agreety --cmd " + de_command + + if do_autologin == True: + self.config_data['initial_session'] = dict(command = de_command, user = username) + + self.config_write() + + class DMsysconfig(DisplayManager): name = "sysconfig" executable = None diff --git a/src/modules/displaymanager/tests/1.global b/src/modules/displaymanager/tests/1.global new file mode 100644 index 000000000..ee06ccfe1 --- /dev/null +++ b/src/modules/displaymanager/tests/1.global @@ -0,0 +1,3 @@ +# SPDX-FileCopyrightText: no +# SPDX-License-Identifier: CC0-1.0 +rootMountPoint: /tmp diff --git a/src/modules/displaymanager/tests/CMakeTests.txt b/src/modules/displaymanager/tests/CMakeTests.txt new file mode 100644 index 000000000..70e3d580d --- /dev/null +++ b/src/modules/displaymanager/tests/CMakeTests.txt @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: no +# SPDX-License-Identifier: CC0-1.0 +# +# We have tests to load (some) of the DMs specifically, to test their +# configuration code. Those tests conventionally live in Python +# files here in the tests/ directory. Add them. +foreach(_dmname greetd sddm) + add_test( + NAME configure-displaymanager-${_dmname} + COMMAND env PYTHONPATH=.: python3 ${CMAKE_CURRENT_LIST_DIR}/test-dm-${_dmname}.py + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) +endforeach() diff --git a/src/modules/displaymanager/tests/test-dm-greetd.py b/src/modules/displaymanager/tests/test-dm-greetd.py new file mode 100644 index 000000000..d41c2dadf --- /dev/null +++ b/src/modules/displaymanager/tests/test-dm-greetd.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: no +# SPDX-License-Identifier: CC0-1.0 +# +# Calamares Boilerplate +import libcalamares +libcalamares.globalstorage = libcalamares.GlobalStorage(None) +libcalamares.globalstorage.insert("testing", True) + +# Module prep-work +from src.modules.displaymanager import main +default_desktop_environment = main.DesktopEnvironment("startplasma-x11", "kde-plasma.desktop") + +import os +os.makedirs("/tmp/etc/greetd/", exist_ok=True) +try: + os.remove("/tmp/etc/greetd/config.toml") +except FileNotFoundError as e: + pass + +# Specific DM test +d = main.DMgreetd("/tmp") +d.set_autologin("d", True, default_desktop_environment) +# .. and again (this time checks load/save) +d.set_autologin("d", True, default_desktop_environment) +d.set_autologin("d", True, default_desktop_environment) diff --git a/src/modules/displaymanager/tests/test-dm-sddm.py b/src/modules/displaymanager/tests/test-dm-sddm.py new file mode 100644 index 000000000..b5c334948 --- /dev/null +++ b/src/modules/displaymanager/tests/test-dm-sddm.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: no +# SPDX-License-Identifier: CC0-1.0 +# +# Calamares Boilerplate +import libcalamares +libcalamares.globalstorage = libcalamares.GlobalStorage(None) +libcalamares.globalstorage.insert("testing", True) + +# Module prep-work +from src.modules.displaymanager import main +default_desktop_environment = main.DesktopEnvironment("startplasma-x11", "kde-plasma.desktop") + +# Specific DM test +d = main.DMsddm("/tmp") +d.set_autologin("d", True, default_desktop_environment) +# .. and again (this time checks load/save) +d.set_autologin("d", True, default_desktop_environment) +d.set_autologin("d", True, default_desktop_environment) diff --git a/src/modules/finishedq/finishedq@mobile.qml b/src/modules/finishedq/finishedq@mobile.qml new file mode 100644 index 000000000..d1ed7d1b0 --- /dev/null +++ b/src/modules/finishedq/finishedq@mobile.qml @@ -0,0 +1,121 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 Anke Boersma + * SPDX-License-Identifier: GPL-3.0-or-later + * License-Filename: LICENSE + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import io.calamares.core 1.0 +import io.calamares.ui 1.0 + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.3 +import org.kde.kirigami 2.7 as Kirigami +import QtGraphicalEffects 1.0 +import QtQuick.Window 2.3 + +Page { + + id: finished + + width: parent.width + height: parent.height + + header: Kirigami.Heading { + width: parent.width + height: 100 + id: header + Layout.fillWidth: true + horizontalAlignment: Qt.AlignHCenter + color: Kirigami.Theme.textColor + level: 1 + text: qsTr("Installation Completed") + + Text { + anchors.top: header.bottom + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + font.pointSize: 12 + text: qsTr("%1 has been installed on your computer.
+ You may now restart your device.").arg(Branding.string(Branding.ProductName)) + } + + Image { + source: "seedling.svg" + anchors.top: header.bottom + anchors.topMargin: 80 + anchors.horizontalCenter: parent.horizontalCenter + width: 64 + height: 64 + mipmap: true + } + } + + RowLayout { + Layout.alignment: Qt.AlignRight|Qt.AlignVCenter + anchors.centerIn: parent + spacing: 6 + + Button { + id: button + text: qsTr("Close") + icon.name: "application-exit" + onClicked: { ViewManager.quit(); } + } + + Button { + text: qsTr("Restart") + icon.name: "system-reboot" + onClicked: { config.doRestart(true); } + } + } + + Item { + + Layout.fillHeight: true + Layout.fillWidth: true + anchors.bottom: parent.bottom + anchors.bottomMargin : 100 + anchors.horizontalCenter: parent.horizontalCenter + + ProgressBar { + id: autoRestartBar + value: 1.0 + anchors.horizontalCenter: parent.horizontalCenter + + } + + Timer { + id: autoRestartTimer + // This is in milliseconds and should be less than 1000 (because of logic in onTriggered) + interval: 100 + repeat: true + running: false + // Whenever the timer fires (1000 / interval times a second) count the progress bar down + // by 1%. When the bar is empty, try to restart normally; as a backup, when the bar + // is empty change settings and schedule it to quit 1000 milliseconds (1s) later. + onTriggered: { + autoRestartBar.value -= 0.01; + if (autoRestartBar.value <= 0.0) { + // First time through here, set the interval to 1000 so that the + // second time (1 second later) goes to quit(). + if ( interval > 999) { ViewManager.quit(); } + else { config.doRestart(true); running = false; interval = 1000; repeat = false; start(); } + } + } + } + } + + function onActivate() + { + autoRestartTimer.running = true + } + + function onLeave() + { + } +} diff --git a/src/modules/fstab/fstab.conf b/src/modules/fstab/fstab.conf index 44be02322..d35bebb03 100644 --- a/src/modules/fstab/fstab.conf +++ b/src/modules/fstab/fstab.conf @@ -11,9 +11,13 @@ # Mount options to use for all filesystems. If a specific filesystem # is listed here, use those options, otherwise use the *default* # options from this mapping. +# +# With kernels 5.15 and newer be cautious of adding the option space_cache +# to the btrfs mount options. The default in 5.15 changed to space_cache=v2. +# If space_cache or space_cache=v1 are specified, it may fail to remount. mountOptions: default: defaults,noatime - btrfs: defaults,noatime,space_cache,autodefrag,compress=zstd + btrfs: defaults,noatime,autodefrag,compress=zstd # Mount options to use for the EFI System Partition. If not defined, the # *mountOptions* for *vfat* are used, or if that is not set either, diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py index 5bc2d3344..3a2dbcf41 100644 --- a/src/modules/fstab/main.py +++ b/src/modules/fstab/main.py @@ -196,7 +196,7 @@ class FstabGenerator(object): dct = self.generate_fstab_line_info(mount_entry) if dct: self.print_fstab_line(dct, file=fstab_file) - else: + elif partition["fs"] != "zfs": # zfs partitions don't need an entry in fstab dct = self.generate_fstab_line_info(partition) if dct: self.print_fstab_line(dct, file=fstab_file) diff --git a/src/modules/grubcfg/main.py b/src/modules/grubcfg/main.py index 1d3460414..521293bf9 100644 --- a/src/modules/grubcfg/main.py +++ b/src/modules/grubcfg/main.py @@ -55,6 +55,32 @@ def get_grub_config_path(root_mount_point): return os.path.join(default_dir, default_config_file) +def get_zfs_root(): + """ + Looks in global storage to find the zfs root + + :return: A string containing the path to the zfs root or None if it is not found + """ + + zfs = libcalamares.globalstorage.value("zfsDatasets") + + if not zfs: + libcalamares.utils.warning("Failed to locate zfs dataset list") + return None + + # Find the root dataset + for dataset in zfs: + try: + if dataset["mountpoint"] == "/": + return dataset["zpool"] + "/" + dataset["dsName"] + except KeyError: + # This should be impossible + libcalamares.utils.warning("Internal error handling zfs dataset") + raise + + return None + + def modify_grub_default(partitions, root_mount_point, distributor): """ Configures '/etc/default/grub' for hibernation and plymouth. @@ -93,6 +119,8 @@ def modify_grub_default(partitions, root_mount_point, distributor): swap_outer_mappername = None no_save_default = False unencrypted_separate_boot = any(p["mountPoint"] == "/boot" and "luksMapperName" not in p for p in partitions) + # If there is no dracut, and the root partition is ZFS, this gets set below + zfs_root_path = None for partition in partitions: if partition["mountPoint"] in ("/", "/boot") and partition["fs"] in ("btrfs", "f2fs"): @@ -143,8 +171,15 @@ def modify_grub_default(partitions, root_mount_point, distributor): ) ] + if partition["fs"] == "zfs" and partition["mountPoint"] == "/": + zfs_root_path = get_zfs_root() + kernel_params = ["quiet"] + # Currently, grub doesn't detect this properly so it must be set manually + if zfs_root_path: + kernel_params.insert(0, "zfs=" + zfs_root_path) + if cryptdevice_params: kernel_params.extend(cryptdevice_params) diff --git a/src/modules/initcpiocfg/main.py b/src/modules/initcpiocfg/main.py index b89d0b0b9..8fc305829 100644 --- a/src/modules/initcpiocfg/main.py +++ b/src/modules/initcpiocfg/main.py @@ -150,6 +150,7 @@ def find_initcpio_features(partitions, root_mount_point): swap_uuid = "" uses_btrfs = False + uses_zfs = False uses_lvm2 = False encrypt_hook = False openswap_hook = False @@ -179,6 +180,9 @@ def find_initcpio_features(partitions, root_mount_point): if partition["fs"] == "btrfs": uses_btrfs = True + if partition["fs"] == "zfs": + uses_zfs = True + if "lvm2" in partition["fs"]: uses_lvm2 = True @@ -205,6 +209,9 @@ def find_initcpio_features(partitions, root_mount_point): if uses_lvm2: hooks.append("lvm2") + if uses_zfs: + hooks.append("zfs") + if swap_uuid != "": if encrypt_hook and openswap_hook: hooks.extend(["openswap"]) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 2e96b6036..900342e6d 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -20,12 +20,24 @@ import os import libcalamares import gettext + _ = gettext.translation("calamares-python", localedir=libcalamares.utils.gettext_path(), languages=libcalamares.utils.gettext_languages(), fallback=True).gettext +class ZfsException(Exception): + """Exception raised when there is a problem with zfs + + Attributes: + message -- explanation of the error + """ + + def __init__(self, message): + self.message = message + + def pretty_name(): return _("Mounting partitions.") @@ -47,20 +59,85 @@ def get_btrfs_subvolumes(partitions): if btrfs_subvolumes is None: libcalamares.utils.warning("No configuration for btrfsSubvolumes") if not btrfs_subvolumes: - btrfs_subvolumes = [ dict(mountPoint="/", subvolume="/@"), dict(mountPoint="/home", subvolume="/@home") ] + btrfs_subvolumes = [dict(mountPoint="/", subvolume="/@"), dict(mountPoint="/home", subvolume="/@home")] # Filter out the subvolumes which have a dedicated partition - non_root_partition_mounts = [ m for m in [ p.get("mountPoint", None) for p in partitions ] if m is not None and m != '/' ] - btrfs_subvolumes = list(filter(lambda s : s["mountPoint"] not in non_root_partition_mounts, btrfs_subvolumes)) + non_root_partition_mounts = [m for m in [p.get("mountPoint", None) for p in partitions] if + m is not None and m != '/'] + btrfs_subvolumes = list(filter(lambda s: s["mountPoint"] not in non_root_partition_mounts, btrfs_subvolumes)) # If we have a swap **file**, give it a separate subvolume. - swap_choice = libcalamares.globalstorage.value( "partitionChoices" ) - if swap_choice and swap_choice.get( "swap", None ) == "file": + swap_choice = libcalamares.globalstorage.value("partitionChoices") + if swap_choice and swap_choice.get("swap", None) == "file": btrfs_subvolumes.append({'mountPoint': '/swap', 'subvolume': '/@swap'}) return btrfs_subvolumes +def mount_zfs(root_mount_point, partition): + """ Mounts a zfs partition at @p root_mount_point + + :param root_mount_point: The absolute path to the root of the install + :param partition: The partition map from global storage for this partition + :return: + """ + # Get the list of zpools from global storage + zfs_pool_list = libcalamares.globalstorage.value("zfsPoolInfo") + if not zfs_pool_list: + libcalamares.utils.warning("Failed to locate zfsPoolInfo data in global storage") + raise ZfsException(_("Internal error mounting zfs datasets")) + + # Find the zpool matching this partition + for zfs_pool in zfs_pool_list: + if zfs_pool["mountpoint"] == partition["mountPoint"]: + pool_name = zfs_pool["poolName"] + ds_name = zfs_pool["dsName"] + + # import the zpool + try: + libcalamares.utils.host_env_process_output(["zpool", "import", "-N", "-R", root_mount_point, pool_name], None) + except subprocess.CalledProcessError: + raise ZfsException(_("Failed to import zpool")) + + # Get the encrpytion information from global storage + zfs_info_list = libcalamares.globalstorage.value("zfsInfo") + encrypt = False + if zfs_info_list: + for zfs_info in zfs_info_list: + if zfs_info["mountpoint"] == partition["mountPoint"] and zfs_info["encrypted"] is True: + encrypt = True + passphrase = zfs_info["passphrase"] + + if encrypt is True: + # The zpool is encrypted, we need to unlock it + try: + libcalamares.utils.host_env_process_output(["zfs", "load-key", pool_name], None, passphrase) + except subprocess.CalledProcessError: + raise ZfsException(_("Failed to unlock zpool")) + + if partition["mountPoint"] == '/': + # Get the zfs dataset list from global storage + zfs = libcalamares.globalstorage.value("zfsDatasets") + + if not zfs: + libcalamares.utils.warning("Failed to locate zfs dataset list") + raise ZfsException(_("Internal error mounting zfs datasets")) + + zfs.sort(key=lambda x: x["mountpoint"]) + for dataset in zfs: + try: + if dataset["canMount"] == "noauto" or dataset["canMount"] is True: + libcalamares.utils.host_env_process_output(["zfs", "mount", + dataset["zpool"] + '/' + dataset["dsName"]]) + except subprocess.CalledProcessError: + raise ZfsException(_("Failed to set zfs mountpoint")) + else: + try: + libcalamares.utils.host_env_process_output(["zfs", "mount", pool_name + '/' + ds_name]) + except subprocess.CalledProcessError: + raise ZfsException(_("Failed to set zfs mountpoint")) + + def mount_partition(root_mount_point, partition, partitions): """ Do a single mount of @p partition inside @p root_mount_point. @@ -96,11 +173,14 @@ def mount_partition(root_mount_point, partition, partitions): if "luksMapperName" in partition: device = os.path.join("/dev/mapper", partition["luksMapperName"]) - if libcalamares.utils.mount(device, - mount_point, - fstype, - partition.get("options", "")) != 0: - libcalamares.utils.warning("Cannot mount {}".format(device)) + if fstype == "zfs": + mount_zfs(root_mount_point, partition) + else: # fstype == "zfs" + if libcalamares.utils.mount(device, + mount_point, + fstype, + partition.get("options", "")) != 0: + libcalamares.utils.warning("Cannot mount {}".format(device)) # Special handling for btrfs subvolumes. Create the subvolumes listed in mount.conf if fstype == "btrfs" and partition["mountPoint"] == '/': @@ -111,9 +191,11 @@ def mount_partition(root_mount_point, partition, partitions): libcalamares.globalstorage.insert("btrfsSubvolumes", btrfs_subvolumes) # Create the subvolumes that are in the completed list for s in btrfs_subvolumes: - subprocess.check_call(['btrfs', 'subvolume', 'create', - root_mount_point + s['subvolume']]) - + subprocess.check_call(["btrfs", "subvolume", "create", + root_mount_point + s["subvolume"]]) + if s["mountPoint"] == "/": + # insert the root subvolume into global storage + libcalamares.globalstorage.insert("btrfsRootSubvolume", s["subvolume"]) subprocess.check_call(["umount", "-v", root_mount_point]) device = partition["device"] @@ -126,9 +208,9 @@ def mount_partition(root_mount_point, partition, partitions): mount_option = "subvol={}".format(s['subvolume']) subvolume_mountpoint = mount_point[:-1] + s['mountPoint'] if libcalamares.utils.mount(device, - subvolume_mountpoint, - fstype, - ",".join([mount_option, partition.get("options", "")])) != 0: + subvolume_mountpoint, + fstype, + ",".join([mount_option, partition.get("options", "")])) != 0: libcalamares.utils.warning("Cannot mount {}".format(device)) @@ -142,7 +224,7 @@ def run(): if not partitions: libcalamares.utils.warning("partitions is empty, {!s}".format(partitions)) return (_("Configuration Error"), - _("No partitions are defined for
{!s}
to use." ).format("mount")) + _("No partitions are defined for
{!s}
to use.").format("mount")) root_mount_point = tempfile.mkdtemp(prefix="calamares-root-") @@ -159,10 +241,13 @@ def run(): # This way, we ensure / is mounted before the rest, and every mount point # is created on the right partition (e.g. if a partition is to be mounted # under /tmp, we make sure /tmp is mounted before the partition) - mountable_partitions = [ p for p in partitions + extra_mounts if "mountPoint" in p and p["mountPoint"] ] + mountable_partitions = [p for p in partitions + extra_mounts if "mountPoint" in p and p["mountPoint"]] mountable_partitions.sort(key=lambda x: x["mountPoint"]) - for partition in mountable_partitions: - mount_partition(root_mount_point, partition, partitions) + try: + for partition in mountable_partitions: + mount_partition(root_mount_point, partition, partitions) + except ZfsException as ze: + return _("zfs mounting error"), ze.message libcalamares.globalstorage.insert("rootMountPoint", root_mount_point) diff --git a/src/modules/packages/main.py b/src/modules/packages/main.py index 7d383b552..98faa9b63 100644 --- a/src/modules/packages/main.py +++ b/src/modules/packages/main.py @@ -35,6 +35,10 @@ total_packages = 0 # For the entire job completed_packages = 0 # Done so far for this job group_packages = 0 # One group of packages from an -install or -remove entry +# A PM object may set this to a string (take care of translations!) +# to override the string produced by pretty_status_message() +custom_status_message = None + INSTALL = object() REMOVE = object() mode_packages = None # Changes to INSTALL or REMOVE @@ -51,6 +55,8 @@ def pretty_name(): def pretty_status_message(): + if custom_status_message is not None: + return custom_status_message if not group_packages: if (total_packages > 0): # Outside the context of an operation @@ -370,17 +376,44 @@ class PMPackageKit(PackageManager): class PMPacman(PackageManager): backend = "pacman" + def __init__(self): + import re + progress_match = re.compile("^\\((\\d+)/(\\d+)\\)") + def line_cb(line): + if line.startswith(":: "): + self.in_package_changes = "package changes" in line + else: + if self.in_package_changes and line.endswith("...\n"): + # Update the message, untranslated; do not change the + # progress percentage, since there may be more "installing..." + # lines in the output for the group, than packages listed + # explicitly. We don't know how to calculate proper progress. + global custom_status_message + custom_status_message = "pacman: " + line.strip() + libcalamares.job.setprogress(self.progress_fraction) + libcalamares.utils.debug(line) + + self.in_package_changes = False + self.line_cb = line_cb + + def reset_progress(self): + self.in_package_changes = False + # These are globals + self.progress_fraction = (completed_packages * 1.0 / total_packages) + def install(self, pkgs, from_local=False): if from_local: pacman_flags = "-U" else: pacman_flags = "-S" - check_target_env_call(["pacman", pacman_flags, - "--noconfirm"] + pkgs) + self.reset_progress() + libcalamares.utils.target_env_process_output(["pacman", pacman_flags, + "--noconfirm"] + pkgs, self.line_cb) def remove(self, pkgs): - check_target_env_call(["pacman", "-Rs", "--noconfirm"] + pkgs) + self.reset_progress() + libcalamares.utils.target_env_process_output(["pacman", "-Rs", "--noconfirm"] + pkgs, self.line_cb) def update_db(self): check_target_env_call(["pacman", "-Sy"]) diff --git a/src/modules/partition/Config.cpp b/src/modules/partition/Config.cpp index 05975213e..155622570 100644 --- a/src/modules/partition/Config.cpp +++ b/src/modules/partition/Config.cpp @@ -221,6 +221,14 @@ Config::setEraseFsTypeChoice( const QString& choice ) } } +bool +Config::acceptPartitionTableType( PartitionTable::TableType tableType ) const +{ + return m_requiredPartitionTableType.empty() + || m_requiredPartitionTableType.contains( PartitionTable::tableTypeToName( tableType ) ); +} + + static void fillGSConfigurationEFI( Calamares::GlobalStorage* gs, const QVariantMap& configurationMap ) { @@ -235,18 +243,18 @@ fillGSConfigurationEFI( Calamares::GlobalStorage* gs, const QVariantMap& configu if ( configurationMap.contains( "efiSystemPartitionSize" ) ) { const QString sizeString = CalamaresUtils::getString( configurationMap, "efiSystemPartitionSize" ); - CalamaresUtils::Partition::PartitionSize part_size - = CalamaresUtils::Partition::PartitionSize( sizeString ); - if (part_size.isValid()) + CalamaresUtils::Partition::PartitionSize part_size = CalamaresUtils::Partition::PartitionSize( sizeString ); + if ( part_size.isValid() ) { // Insert once as string, once as a size-in-bytes; // changes to these keys should be synchronized with PartUtils.cpp - gs->insert( "efiSystemPartitionSize", sizeString ); - gs->insert( "efiSystemPartitionSize_i", part_size.toBytes()); + gs->insert( "efiSystemPartitionSize", sizeString ); + gs->insert( "efiSystemPartitionSize_i", part_size.toBytes() ); - if (part_size.toBytes() != PartUtils::efiFilesystemMinimumSize()) + if ( part_size.toBytes() != PartUtils::efiFilesystemMinimumSize() ) { - cWarning() << "EFI partition size" << sizeString << "has been adjusted to" << PartUtils::efiFilesystemMinimumSize() << "bytes"; + cWarning() << "EFI partition size" << sizeString << "has been adjusted to" + << PartUtils::efiFilesystemMinimumSize() << "bytes"; } } else @@ -342,11 +350,9 @@ Config::setConfigurationMap( const QVariantMap& configurationMap ) setSwapChoice( m_initialSwapChoice ); m_allowManualPartitioning = CalamaresUtils::getBool( configurationMap, "allowManualPartitioning", true ); + m_requiredPartitionTableType = CalamaresUtils::getStringList( configurationMap, "requiredPartitionTableType" ); Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - m_requiredPartitionTableType = CalamaresUtils::getStringList( configurationMap, "requiredPartitionTableType" ); - gs->insert( "requiredPartitionTableType", m_requiredPartitionTableType ); - fillGSConfigurationEFI( gs, configurationMap ); fillConfigurationFSTypes( configurationMap ); } diff --git a/src/modules/partition/Config.h b/src/modules/partition/Config.h index 5f7e46821..2ac44b424 100644 --- a/src/modules/partition/Config.h +++ b/src/modules/partition/Config.h @@ -12,6 +12,7 @@ #include "utils/NamedEnum.h" +#include #include #include @@ -127,9 +128,18 @@ public: */ FileSystem::Type defaultFsType() const { return m_defaultFsType; } - ///@brief Is manual partitioning allowed (not explicitly disabled in the config file)? + /// @brief Is manual partitioning allowed (not explicitly disabled in the config file)? bool allowManualPartitioning() const { return m_allowManualPartitioning; } + /** @brief Will @p tableType be ok? + * + * If no required types are specified, it's ok, otherwise the + * type must be named in the list of required types. + */ + bool acceptPartitionTableType( PartitionTable::TableType tableType ) const; + /// @brief Returns list of acceptable types. May be empty. + QStringList partitionTableTypes() const { return m_requiredPartitionTableType; } + public Q_SLOTS: void setInstallChoice( int ); ///< Translates a button ID or so to InstallChoice void setInstallChoice( InstallChoice ); diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index 69a6db535..16e5a7ea1 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -257,14 +257,16 @@ PartitionCoreModule::doInit() cDebug() << Logger::SubEntry << "node\tcapacity\tname\tprettyName"; for ( auto device : devices ) { - cDebug() << Logger::SubEntry << Logger::Pointer( device ); if ( device ) { // Gives ownership of the Device* to the DeviceInfo object auto deviceInfo = new DeviceInfo( device ); m_deviceInfos << deviceInfo; - cDebug() << Logger::SubEntry << device->deviceNode() << device->capacity() << device->name() - << device->prettyName(); + cDebug() << Logger::SubEntry + << device->deviceNode() + << device->capacity() + << Logger::RedactedName( "DevName", device->name() ) + << Logger::RedactedName( "DevNamePretty", device->prettyName() ); } else { @@ -707,10 +709,10 @@ PartitionCoreModule::dumpQueue() const cDebug() << "# Queue:"; for ( auto info : m_deviceInfos ) { - cDebug() << Logger::SubEntry << "## Device:" << info->device->name(); + cDebug() << Logger::SubEntry << "## Device:" << info->device->deviceNode(); for ( const auto& job : info->jobs() ) { - cDebug() << Logger::SubEntry << "-" << job->prettyName(); + cDebug() << Logger::SubEntry << "-" << job->metaObject()->className(); } } } diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 8ae904e92..f60952643 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -296,7 +296,9 @@ PartitionLayout::createPartitions( Device* dev, } Partition* part = nullptr; - if ( luksPassphrase.isEmpty() ) + + // Encryption for zfs is handled in the zfs module + if ( luksPassphrase.isEmpty() || correctFS( entry.partFileSystem ) == FileSystem::Zfs ) { part = KPMHelpers::createNewPartition( parent, *dev, @@ -319,6 +321,24 @@ PartitionLayout::createPartitions( Device* dev, luksPassphrase, KPM_PARTITION_FLAG( None ) ); } + + // For zfs, we need to make the passphrase available to later modules + if ( correctFS( entry.partFileSystem ) == FileSystem::Zfs ) + { + Calamares::GlobalStorage* storage = Calamares::JobQueue::instance()->globalStorage(); + QList< QVariant > zfsInfoList; + QVariantMap zfsInfo; + + // Save the information subsequent modules will need + zfsInfo[ "encrypted" ] = !luksPassphrase.isEmpty(); + zfsInfo[ "passphrase" ] = luksPassphrase; + zfsInfo[ "mountpoint" ] = entry.partMountPoint; + + // Add it to the list and insert it into global storage + zfsInfoList.append( zfsInfo ); + storage->insert( "zfsInfo", zfsInfoList ); + } + PartitionInfo::setFormat( part, true ); PartitionInfo::setMountPoint( part, entry.partMountPoint ); if ( !entry.partLabel.isEmpty() ) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 5f3832fa0..9226eb3b6 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -42,7 +42,6 @@ #include "widgets/PrettyRadioButton.h" #include -#include #ifdef WITH_KPMCORE4API #include #endif @@ -90,7 +89,6 @@ ChoicePage::ChoicePage( Config* config, QWidget* parent ) auto gs = Calamares::JobQueue::instance()->globalStorage(); - m_requiredPartitionTableType = gs->value( "requiredPartitionTableType" ).toStringList(); m_enableEncryptionWidget = gs->value( "enableLuksAutomatedPartitioning" ).toBool(); // Set up drives combo @@ -1252,6 +1250,28 @@ operator<<( QDebug& s, PartitionIterator& it ) return s; } +QString +describePartitionTypes( const QStringList& types ) +{ + if ( types.empty() ) + { + return QCoreApplication::translate( + ChoicePage::staticMetaObject.className(), "any", "any partition-table type" ); + } + if ( types.size() == 1 ) + { + return types.first(); + } + if ( types.size() == 2 ) + { + return QCoreApplication::translate( + ChoicePage::staticMetaObject.className(), "%1 or %2", "partition-table types" ) + .arg( types.at( 0 ), types.at( 1 ) ); + } + // More than two, rather unlikely + return types.join( ", " ); +} + /** * @brief ChoicePage::setupActions happens every time a new Device* is selected in the * device picker. Sets up the text and visibility of the partitioning actions based @@ -1305,8 +1325,7 @@ ChoicePage::setupActions() if ( currentDevice->partitionTable() ) { tableType = currentDevice->partitionTable()->type(); - matchTableType = m_requiredPartitionTableType.size() == 0 - || m_requiredPartitionTableType.contains( PartitionTable::tableTypeToName( tableType ) ); + matchTableType = m_config->acceptPartitionTableType( tableType ); } for ( auto it = PartitionIterator::begin( currentDevice ); it != PartitionIterator::end( currentDevice ); ++it ) @@ -1487,11 +1506,11 @@ ChoicePage::setupActions() "but the partition table %1 is different from the " "needed %2.
" ) .arg( PartitionTable::tableTypeToName( tableType ) ) - .arg( m_requiredPartitionTableType.join( " or " ) ) ); + .arg( describePartitionTypes( m_config->partitionTableTypes() ) ) ); m_messageLabel->show(); cWarning() << "Partition table" << PartitionTable::tableTypeToName( tableType ) - << "does not match the requirement " << m_requiredPartitionTableType.join( " or " ) + << "does not match the requirement " << m_config->partitionTableTypes().join( ',' ) << ", ENABLING erase feature and DISABLING alongside, replace and manual features."; m_eraseButton->show(); m_alongsideButton->hide(); @@ -1642,7 +1661,8 @@ ChoicePage::updateSwapChoicesTr() } else { - cWarning() << "Box item" << index << m_eraseSwapChoiceComboBox->itemText( index ) << "has non-integer role."; + cWarning() << "Box item" << index << m_eraseSwapChoiceComboBox->itemText( index ) + << "has non-integer role."; } break; case SwapChoice::ReuseSwap: diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h index 3892b4a23..12222ac63 100644 --- a/src/modules/partition/gui/ChoicePage.h +++ b/src/modules/partition/gui/ChoicePage.h @@ -159,7 +159,6 @@ private: int m_lastSelectedDeviceIndex = -1; int m_lastSelectedActionIndex = -1; - QStringList m_requiredPartitionTableType; bool m_enableEncryptionWidget; QMutex m_coreMutex; diff --git a/src/modules/partition/gui/CreatePartitionDialog.cpp b/src/modules/partition/gui/CreatePartitionDialog.cpp index cdc9992b9..6bde9a148 100644 --- a/src/modules/partition/gui/CreatePartitionDialog.cpp +++ b/src/modules/partition/gui/CreatePartitionDialog.cpp @@ -23,6 +23,7 @@ #include "GlobalStorage.h" #include "JobQueue.h" +#include "Settings.h" #include "partition/FileSystem.h" #include "partition/PartitionQuery.h" #include "utils/Logger.h" @@ -104,7 +105,9 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device, QStringList fsNames; for ( auto fs : FileSystemFactory::map() ) { - if ( fs->supportCreate() != FileSystem::cmdSupportNone && fs->type() != FileSystem::Extended ) + // We need to ensure zfs is added to the list if the zfs module is enabled + if ( ( fs->type() == FileSystem::Type::Zfs && Calamares::Settings::instance()->isModuleEnabled( "zfs" ) ) + || ( fs->supportCreate() != FileSystem::cmdSupportNone && fs->type() != FileSystem::Extended ) ) { fsNames << userVisibleFS( fs ); // This is put into the combobox if ( fs->type() == defaultFSType ) @@ -240,7 +243,8 @@ CreatePartitionDialog::getNewlyCreatedPartition() // does so, to set up the partition for create-and-then-set-flags. Partition* partition = nullptr; QString luksPassphrase = m_ui->encryptWidget->passphrase(); - if ( m_ui->encryptWidget->state() == EncryptWidget::Encryption::Confirmed && !luksPassphrase.isEmpty() ) + if ( m_ui->encryptWidget->state() == EncryptWidget::Encryption::Confirmed && !luksPassphrase.isEmpty() + && fsType != FileSystem::Zfs ) { partition = KPMHelpers::createNewEncryptedPartition( m_parent, *m_device, m_role, fsType, fsLabel, first, last, luksPassphrase, PartitionTable::Flags() ); @@ -251,6 +255,31 @@ CreatePartitionDialog::getNewlyCreatedPartition() m_parent, *m_device, m_role, fsType, fsLabel, first, last, PartitionTable::Flags() ); } + // For zfs, we let the zfs module handle the encryption but we need to make the passphrase available to later modules + if ( fsType == FileSystem::Zfs ) + { + Calamares::GlobalStorage* storage = Calamares::JobQueue::instance()->globalStorage(); + QList< QVariant > zfsInfoList; + QVariantMap zfsInfo; + + // If this is not the first encrypted zfs partition, get the old list first + if ( storage->contains( "zfsInfo" ) ) + { + zfsInfoList = storage->value( "zfsInfo" ).toList(); + storage->remove( "zfsInfo" ); + } + + // Save the information subsequent modules will need + zfsInfo[ "encrypted" ] + = m_ui->encryptWidget->state() == EncryptWidget::Encryption::Confirmed && !luksPassphrase.isEmpty(); + zfsInfo[ "passphrase" ] = luksPassphrase; + zfsInfo[ "mountpoint" ] = selectedMountPoint( m_ui->mountPointComboBox ); + + // Add it to the list and insert it into global storage + zfsInfoList.append( zfsInfo ); + storage->insert( "zfsInfo", zfsInfoList ); + } + if ( m_device->type() == Device::Type::LVM_Device ) { partition->setPartitionPath( m_device->deviceNode() + QStringLiteral( "/" ) diff --git a/src/modules/partition/gui/EditExistingPartitionDialog.cpp b/src/modules/partition/gui/EditExistingPartitionDialog.cpp index 411d6d0dc..a3052b3b7 100644 --- a/src/modules/partition/gui/EditExistingPartitionDialog.cpp +++ b/src/modules/partition/gui/EditExistingPartitionDialog.cpp @@ -25,6 +25,7 @@ #include "GlobalStorage.h" #include "JobQueue.h" +#include "Settings.h" #include "partition/FileSystem.h" #include "utils/Logger.h" @@ -89,7 +90,9 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, QStringList fsNames; for ( auto fs : FileSystemFactory::map() ) { - if ( fs->supportCreate() != FileSystem::cmdSupportNone && fs->type() != FileSystem::Extended ) + // We need to ensure zfs is added to the list if the zfs module is enabled + if ( ( fs->type() == FileSystem::Type::Zfs && Calamares::Settings::instance()->isModuleEnabled( "zfs" ) ) + || ( fs->supportCreate() != FileSystem::cmdSupportNone && fs->type() != FileSystem::Extended ) ) { fsNames << userVisibleFS( fs ); // For the combo box } @@ -117,6 +120,12 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, m_ui->fileSystemLabel->setEnabled( m_ui->formatRadioButton->isChecked() ); m_ui->fileSystemComboBox->setEnabled( m_ui->formatRadioButton->isChecked() ); + // Force a format if the existing device is a zfs device since reusing a zpool isn't currently supported + m_ui->formatRadioButton->setChecked( m_partition->fileSystem().type() == FileSystem::Type::Zfs ); + m_ui->formatRadioButton->setEnabled( !( m_partition->fileSystem().type() == FileSystem::Type::Zfs ) ); + m_ui->keepRadioButton->setChecked( !( m_partition->fileSystem().type() == FileSystem::Type::Zfs ) ); + m_ui->keepRadioButton->setEnabled( !( m_partition->fileSystem().type() == FileSystem::Type::Zfs ) ); + setFlagList( *( m_ui->m_listFlags ), m_partition->availableFlags(), PartitionInfo::flags( m_partition ) ); } diff --git a/src/modules/partition/gui/PartitionDialogHelpers.cpp b/src/modules/partition/gui/PartitionDialogHelpers.cpp index 7ea57c565..65e88f898 100644 --- a/src/modules/partition/gui/PartitionDialogHelpers.cpp +++ b/src/modules/partition/gui/PartitionDialogHelpers.cpp @@ -2,7 +2,7 @@ * * SPDX-FileCopyrightText: 2014 Aurélien Gâteau * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot + * SPDX-FileCopyrightText: 2018-2021 Adriaan de Groot * SPDX-License-Identifier: GPL-3.0-or-later * * Calamares is Free Software: see the License-Identifier above. diff --git a/src/modules/partition/jobs/ClearMountsJob.cpp b/src/modules/partition/jobs/ClearMountsJob.cpp index 8b339dea4..831a1e868 100644 --- a/src/modules/partition/jobs/ClearMountsJob.cpp +++ b/src/modules/partition/jobs/ClearMountsJob.cpp @@ -215,6 +215,12 @@ getPVGroups( const QString& deviceName ) * meant **only** for debugging and is not displayed to the user, * which is why no translation is applied. * + * The MessageAndPath class stores a C-style pointer to a character + * array -- from QT_TRANSLATE_NOOP() -- and a path to substitute into it. + * + * When the tryX() functions return an "empty string", it is an + * empty MessageAndPath which acts like an empty string (in particular, + * isEmpty() is true). */ class MessageAndPath @@ -237,8 +243,14 @@ public: } private: +#if ( QT_VERSION < QT_VERSION_CHECK( 5, 15, 0 ) ) + // TODO: 3.3 remove because newer Qt does support constness + const char* m_message = nullptr; + QString m_path; +#else const char* const m_message = nullptr; QString const m_path; +#endif }; STATICTEST inline QDebug& diff --git a/src/modules/partition/jobs/CreatePartitionJob.cpp b/src/modules/partition/jobs/CreatePartitionJob.cpp index 241e0a451..83ebc0509 100644 --- a/src/modules/partition/jobs/CreatePartitionJob.cpp +++ b/src/modules/partition/jobs/CreatePartitionJob.cpp @@ -11,8 +11,10 @@ #include "CreatePartitionJob.h" +#include "core/PartitionInfo.h" #include "partition/FileSystem.h" #include "partition/PartitionQuery.h" +#include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" #include "utils/Units.h" @@ -24,9 +26,79 @@ #include #include +#include +#include + using CalamaresUtils::Partition::untranslatedFS; using CalamaresUtils::Partition::userVisibleFS; +/** @brief Create + * + * Uses sfdisk to remove @p partition. This should only be used in cases + * where using kpmcore to remove the partition would not be appropriate + * + */ +static Calamares::JobResult +createZfs( Partition* partition, Device* device ) +{ + auto r = CalamaresUtils::System::instance()->runCommand( + { "sh", + "-c", + "echo start=" + QString::number( partition->firstSector() ) + " size=" + + QString::number( partition->length() ) + " | sfdisk --append --force " + partition->devicePath() }, + std::chrono::seconds( 5 ) ); + if ( r.getExitCode() != 0 ) + { + return Calamares::JobResult::error( + QCoreApplication::translate( CreatePartitionJob::staticMetaObject.className(), + "Failed to create partition" ), + QCoreApplication::translate( CreatePartitionJob::staticMetaObject.className(), + "Failed to create zfs partition with output: " + + r.getOutput().toLocal8Bit() ) ); + } + + // Now we need to do some things that would normally be done by kpmcore + + // First we get the device node from the output and set it as the partition path + QRegularExpression re( QStringLiteral( "Created a new partition (\\d+)" ) ); + QRegularExpressionMatch rem = re.match( r.getOutput() ); + + QString deviceNode; + if ( rem.hasMatch() ) + { + if ( partition->devicePath().back().isDigit() ) + { + deviceNode = partition->devicePath() + QLatin1Char( 'p' ) + rem.captured( 1 ); + } + else + { + deviceNode = partition->devicePath() + rem.captured( 1 ); + } + } + + partition->setPartitionPath( deviceNode ); + + // If it is a gpt device, set the partition UUID + if ( device->partitionTable()->type() == PartitionTable::gpt && partition->uuid().isEmpty() ) + { + r = CalamaresUtils::System::instance()->runCommand( + { "sfdisk", "--list", "--output", "Device,UUID", partition->devicePath() }, std::chrono::seconds( 5 ) ); + if ( r.getExitCode() == 0 ) + { + QRegularExpression re( deviceNode + QStringLiteral( " +(.+)" ) ); + QRegularExpressionMatch rem = re.match( r.getOutput() ); + + if ( rem.hasMatch() ) + { + partition->setUUID( rem.captured( 1 ) ); + } + } + } + + return Calamares::JobResult::ok(); +} + + CreatePartitionJob::CreatePartitionJob( Device* device, Partition* partition ) : PartitionJob( partition ) , m_device( device ) @@ -194,6 +266,13 @@ CreatePartitionJob::prettyStatusMessage() const Calamares::JobResult CreatePartitionJob::exec() { + // kpmcore doesn't currently handle this case properly so for now, we manually create the partion + // The zfs module can later deal with creating a zpool in the partition + if ( m_partition->fileSystem().type() == FileSystem::Type::Zfs ) + { + return createZfs( m_partition, m_device ); + } + Report report( nullptr ); NewOperation op( *m_device, m_partition ); op.setStatus( Operation::StatusRunning ); diff --git a/src/modules/partition/jobs/FillGlobalStorageJob.cpp b/src/modules/partition/jobs/FillGlobalStorageJob.cpp index 40e67d620..5be353113 100644 --- a/src/modules/partition/jobs/FillGlobalStorageJob.cpp +++ b/src/modules/partition/jobs/FillGlobalStorageJob.cpp @@ -104,14 +104,19 @@ mapForPartition( Partition* partition, const QString& uuid ) // Debugging for inside the loop in createPartitionList(), // so indent a bit Logger::CDebug deb; - using TR = Logger::DebugRow< const char* const, const QString& >; + using TR = Logger::DebugRow< const char* const, const QString >; + // clang-format off deb << Logger::SubEntry << "mapping for" << partition->partitionPath() << partition->deviceNode() - << TR( "partlabel", map[ "partlabel" ].toString() ) << TR( "partuuid", map[ "partuuid" ].toString() ) - << TR( "parttype", map[ "parttype" ].toString() ) << TR( "partattrs", map[ "partattrs" ].toString() ) - << TR( "mountPoint:", PartitionInfo::mountPoint( partition ) ) << TR( "fs:", map[ "fs" ].toString() ) - << TR( "fsName", map[ "fsName" ].toString() ) << TR( "uuid", uuid ) + << TR( "partlabel", map[ "partlabel" ].toString() ) + << TR( "partition-uuid (partuuid)", Logger::RedactedName( "PartUUID", map[ "partuuid" ].toString() ) ) + << TR( "parttype", map[ "parttype" ].toString() ) + << TR( "partattrs", map[ "partattrs" ].toString() ) + << TR( "mountPoint:", PartitionInfo::mountPoint( partition ) ) + << TR( "fs:", map[ "fs" ].toString() ) + << TR( "fsName", map[ "fsName" ].toString() ) + << TR( "filesystem-uuid (uuid)", Logger::RedactedName( "FSUUID", uuid ) ) << TR( "claimed", map[ "claimed" ].toString() ); - + // clang-format on if ( partition->roles().has( PartitionRole::Luks ) ) { const FileSystem& fsRef = partition->fileSystem(); diff --git a/src/modules/partition/tests/ClearMountsJobTests.cpp b/src/modules/partition/tests/ClearMountsJobTests.cpp index e05af4897..3af400fde 100644 --- a/src/modules/partition/tests/ClearMountsJobTests.cpp +++ b/src/modules/partition/tests/ClearMountsJobTests.cpp @@ -19,6 +19,14 @@ QTEST_GUILESS_MAIN( ClearMountsJobTests ) /* Not exactly public API */ QStringList getPartitionsForDevice( const QString& deviceName ); +/* At one point, the partitions-list was read from /proc/partitions by + * running awk and grep, as below. Check that the current implementation + * matches that crufty one. + * + * Update 2021-11-02: the newer implementation prepends /dev/ to the + * names of the partitions, for simplicity elsewhere, so that needs + * to be added in to the awk(1) program, too. + */ QStringList getPartitionsForDevice_other( const QString& deviceName ) { @@ -26,7 +34,7 @@ getPartitionsForDevice_other( const QString& deviceName ) process.setProgram( "sh" ); process.setArguments( { "-c", - QString( "echo $(awk '{print $4}' /proc/partitions | sed -e '/name/d' -e '/^$/d' -e '/[1-9]/!d' | grep %1)" ) + QString( "echo $(awk '{print \"/dev/\"$4}' /proc/partitions | sed -e '/name/d' -e '/^$/d' -e '/[1-9]/!d' | grep %1)" ) .arg( deviceName ) } ); process.start(); process.waitForFinished(); diff --git a/src/modules/umount/main.py b/src/modules/umount/main.py index 0035a6b0f..77ea91e34 100644 --- a/src/modules/umount/main.py +++ b/src/modules/umount/main.py @@ -49,6 +49,27 @@ def list_mounts(root_mount_point): return lst +def export_zpools(root_mount_point): + """ Exports the zpools if defined in global storage + + :param root_mount_point: The absolute path to the root of the install + :return: + """ + try: + zfs_pool_list = libcalamares.globalstorage.value("zfsPoolInfo") + zfs_pool_list.sort(reverse=True, key=lambda x: x["poolName"]) + if zfs_pool_list: + for zfs_pool in zfs_pool_list: + try: + libcalamares.utils.host_env_process_output(['zpool', 'export', zfs_pool["poolName"]]) + except subprocess.CalledProcessError: + libcalamares.utils.warning("Failed to export zpool") + except Exception as e: + # If this fails it shouldn't cause the installation to fail + libcalamares.utils.warning("Received exception while exporting zpools: " + format(e)) + pass + + def run(): """ Unmounts given mountpoints in decreasing order. @@ -94,6 +115,8 @@ def run(): # in the exception object. subprocess.check_output(["umount", "-lv", mount_point], stderr=subprocess.STDOUT) + export_zpools(root_mount_point) + os.rmdir(root_mount_point) return None diff --git a/src/modules/zfs/CMakeLists.txt b/src/modules/zfs/CMakeLists.txt new file mode 100644 index 000000000..2feb911d0 --- /dev/null +++ b/src/modules/zfs/CMakeLists.txt @@ -0,0 +1,13 @@ +# === This file is part of Calamares - === +# +# SPDX-FileCopyrightText: 2020 Adriaan de Groot +# SPDX-License-Identifier: BSD-2-Clause +# +calamares_add_plugin( zfs + TYPE job + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + ZfsJob.cpp + SHARED_LIB +) + diff --git a/src/modules/zfs/README.md b/src/modules/zfs/README.md new file mode 100644 index 000000000..9138a0598 --- /dev/null +++ b/src/modules/zfs/README.md @@ -0,0 +1,18 @@ +## zfs Module Notes + + + +There are a few considerations to be aware of when enabling the zfs module +* You must provide zfs kernel modules or kernel support on the ISO for the zfs module to function +* Support for zfs in the partition module is conditional on the zfs module being enabled +* If you use grub with zfs, you must have `ZPOOL_VDEV_NAME_PATH=1` in your environment when running grub-install or grub-mkconfig. + * Calamares will ensure this happens during the bootloader module. + * It will also add it to `/etc/environment` so it will be available in the installation + * If you have an scripts or other processes that trigger grub-mkconfig during the install process, be sure to add that to the environment +* In most cases, you will need to enable services for zfs support appropriate to your distro. For example, when testing on Arch the following services were enabled: + * zfs.target + * zfs-import-cache + * zfs-mount + * zfs-import.target diff --git a/src/modules/zfs/ZfsJob.cpp b/src/modules/zfs/ZfsJob.cpp new file mode 100644 index 000000000..ce2eaf183 --- /dev/null +++ b/src/modules/zfs/ZfsJob.cpp @@ -0,0 +1,365 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 Evan James + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +#include "ZfsJob.h" + +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" +#include "utils/Variant.h" + +#include "GlobalStorage.h" +#include "JobQueue.h" +#include "Settings.h" + +#include + +#include + +/** @brief Returns the alphanumeric portion of a string + * + * @p input is the input string + * + */ +static QString +alphaNumeric( QString input ) +{ + return input.remove( QRegExp( "[^a-zA-Z\\d\\s]" ) ); +} + +/** @brief Returns the best available device for zpool creation + * + * zfs partitions generally don't have UUID until the zpool is created. Generally, + * they are formed using either the id or the partuuid. The id isn't stored by kpmcore + * so this function checks to see if we have a partuuid. If so, it forms a device path + * for it. As a backup, it uses the device name i.e. /dev/sdax. + * + * The function returns a fully qualified path to the device or an empty string if no device + * is found + * + * @p pMap is the partition map from global storage + * + */ +static QString +findBestZfsDevice( QVariantMap pMap ) +{ + // Find the best device identifier, if one isn't available, skip this partition + QString deviceName; + if ( pMap[ "partuuid" ].toString() != "" ) + { + return "/dev/disk/by-partuuid/" + pMap[ "partuuid" ].toString().toLower(); + } + else if ( pMap[ "device" ].toString() != "" ) + { + return pMap[ "device" ].toString().toLower(); + } + else + { + return QString(); + } +} + +/** @brief Converts the value in a QVariant to a string which is a valid option for canmount + * + * Storing "on" and "off" in QVariant results in a conversion to boolean. This function takes + * the Qvariant in @p canMount and converts it to a QString holding "on", "off" or the string + * value in the QVariant. + * + */ +static QString +convertCanMount( QVariant canMount ) +{ + if ( canMount == true ) + { + return "on"; + } + else if ( canMount == false ) + { + return "off"; + } + else + { + return canMount.toString(); + } +} + +ZfsJob::ZfsJob( QObject* parent ) + : Calamares::CppJob( parent ) +{ +} + +ZfsJob::~ZfsJob() {} + +QString +ZfsJob::prettyName() const +{ + return tr( "Create ZFS pools and datasets" ); +} + +void +ZfsJob::collectMountpoints( const QVariantList& partitions ) +{ + m_mountpoints.empty(); + for ( const QVariant& partition : partitions ) + { + if ( partition.canConvert( QVariant::Map ) ) + { + QString mountpoint = partition.toMap().value( "mountPoint" ).toString(); + if ( !mountpoint.isEmpty() ) + { + m_mountpoints.append( mountpoint ); + } + } + } +} + +bool +ZfsJob::isMountpointOverlapping( const QString& targetMountpoint ) const +{ + for ( const QString& mountpoint : m_mountpoints ) + { + if ( mountpoint != '/' && targetMountpoint.startsWith( mountpoint ) ) + { + return true; + } + } + return false; +} + + +ZfsResult +ZfsJob::createZpool( QString deviceName, QString poolName, QString poolOptions, bool encrypt, QString passphrase ) const +{ + // zfs doesn't wait for the devices so pause for 2 seconds to ensure we give time for the device files to be created + sleep( 2 ); + + QStringList command; + if ( encrypt ) + { + command = QStringList() << "zpool" + << "create" << poolOptions.split( ' ' ) << "-O" + << "encryption=aes-256-gcm" + << "-O" + << "keyformat=passphrase" << poolName << deviceName; + } + else + { + command = QStringList() << "zpool" + << "create" << poolOptions.split( ' ' ) << poolName << deviceName; + } + + auto r = CalamaresUtils::System::instance()->runCommand( + CalamaresUtils::System::RunLocation::RunInHost, command, QString(), passphrase, std::chrono::seconds( 10 ) ); + + if ( r.getExitCode() != 0 ) + { + cWarning() << "Failed to run zpool create. The output was: " + r.getOutput(); + return { false, tr( "Failed to create zpool on " ) + deviceName }; + } + + return { true, QString() }; +} + +Calamares::JobResult +ZfsJob::exec() +{ + QVariantList partitions; + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + if ( gs && gs->contains( "partitions" ) && gs->value( "partitions" ).canConvert( QVariant::List ) ) + { + partitions = gs->value( "partitions" ).toList(); + } + else + { + cWarning() << "No *partitions* defined."; + return Calamares::JobResult::internalError( tr( "Configuration Error" ), + tr( "No partitions are available for Zfs." ), + Calamares::JobResult::InvalidConfiguration ); + } + + const CalamaresUtils::System* system = CalamaresUtils::System::instance(); + + QVariantList poolNames; + + // Check to ensure the list of zfs info from the partition module is available and convert it to a list + if ( !gs->contains( "zfsInfo" ) && gs->value( "zfsInfo" ).canConvert( QVariant::List ) ) + { + return Calamares::JobResult::error( tr( "Internal data missing" ), tr( "Failed to create zpool" ) ); + } + QVariantList zfsInfoList = gs->value( "zfsInfo" ).toList(); + + for ( auto& partition : qAsConst( partitions ) ) + { + QVariantMap pMap; + if ( partition.canConvert( QVariant::Map ) ) + { + pMap = partition.toMap(); + } + + // If it isn't a zfs partition, ignore it + if ( pMap[ "fsName" ] != "zfs" ) + { + continue; + } + + // Find the best device identifier, if one isn't available, skip this partition + QString deviceName = findBestZfsDevice( pMap ); + if ( deviceName.isEmpty() ) + { + continue; + } + + // If the partition doesn't have a mountpoint, skip it + QString mountpoint = pMap[ "mountPoint" ].toString(); + if ( mountpoint.isEmpty() ) + { + continue; + } + + // Build a poolname off config pool name and the mountpoint, this is not ideal but should work until there is UI built for zfs + QString poolName = m_poolName; + if ( mountpoint != '/' ) + { + poolName += alphaNumeric( mountpoint ); + } + + // Look in the zfs info list to see if this partition should be encrypted + bool encrypt = false; + QString passphrase; + for ( const QVariant& zfsInfo : qAsConst( zfsInfoList ) ) + { + if ( zfsInfo.canConvert( QVariant::Map ) && zfsInfo.toMap().value( "encrypted" ).toBool() + && mountpoint == zfsInfo.toMap().value( "mountpoint" ) ) + { + encrypt = true; + passphrase = zfsInfo.toMap().value( "passphrase" ).toString(); + } + } + + // Create the zpool + ZfsResult zfsResult; + if ( encrypt ) + { + zfsResult = createZpool( deviceName, poolName, m_poolOptions, true, passphrase ); + } + else + { + zfsResult = createZpool( deviceName, poolName, m_poolOptions, false ); + } + + if ( !zfsResult.success ) + { + return Calamares::JobResult::error( tr( "Failed to create zpool" ), zfsResult.failureMessage ); + } + + // Save the poolname, dataset name and mountpoint. It will later be added to a list and placed in global storage. + // This will be used by later modules including mount and umount + QVariantMap poolNameEntry; + poolNameEntry[ "poolName" ] = poolName; + poolNameEntry[ "mountpoint" ] = mountpoint; + poolNameEntry[ "dsName" ] = "none"; + + // If the mountpoint is /, create datasets per the config file. If not, create a single dataset mounted at the partitions mountpoint + if ( mountpoint == '/' ) + { + collectMountpoints( partitions ); + QVariantList datasetList; + for ( const auto& dataset : qAsConst( m_datasets ) ) + { + QVariantMap datasetMap = dataset.toMap(); + + // Make sure all values are valid + if ( datasetMap[ "dsName" ].toString().isEmpty() || datasetMap[ "mountpoint" ].toString().isEmpty() + || datasetMap[ "canMount" ].toString().isEmpty() ) + { + cWarning() << "Bad dataset entry"; + continue; + } + + // We should skip this dataset if it conflicts with a permanent mountpoint + if ( isMountpointOverlapping( datasetMap[ "mountpoint" ].toString() ) ) + { + continue; + } + + QString canMount = convertCanMount( datasetMap[ "canMount" ].toString() ); + + // Create the dataset + auto r = system->runCommand( { QStringList() << "zfs" + << "create" << m_datasetOptions.split( ' ' ) << "-o" + << "canmount=" + canMount << "-o" + << "mountpoint=" + datasetMap[ "mountpoint" ].toString() + << poolName + "/" + datasetMap[ "dsName" ].toString() }, + std::chrono::seconds( 10 ) ); + if ( r.getExitCode() != 0 ) + { + cWarning() << "Failed to create dataset" << datasetMap[ "dsName" ].toString(); + continue; + } + + // Add the dataset to the list for global storage this information is used later to properly set + // the mount options on each dataset + datasetMap[ "zpool" ] = m_poolName; + datasetList.append( datasetMap ); + } + + // If the list isn't empty, add it to global storage + if ( !datasetList.isEmpty() ) + { + gs->insert( "zfsDatasets", datasetList ); + } + } + else + { + QString dsName = mountpoint; + dsName = alphaNumeric( mountpoint ); + auto r = system->runCommand( { QStringList() << "zfs" + << "create" << m_datasetOptions.split( ' ' ) << "-o" + << "canmount=on" + << "-o" + << "mountpoint=" + mountpoint << poolName + "/" + dsName }, + std::chrono::seconds( 10 ) ); + if ( r.getExitCode() != 0 ) + { + return Calamares::JobResult::error( tr( "Failed to create dataset" ), + tr( "The output was: " ) + r.getOutput() ); + } + poolNameEntry[ "dsName" ] = dsName; + } + + poolNames.append( poolNameEntry ); + + // Export the zpool so it can be reimported at the correct location later + auto r = system->runCommand( { "zpool", "export", poolName }, std::chrono::seconds( 10 ) ); + if ( r.getExitCode() != 0 ) + { + cWarning() << "Failed to export pool" << m_poolName; + } + } + + // Put the list of zpools into global storage + if ( !poolNames.isEmpty() ) + { + gs->insert( "zfsPoolInfo", poolNames ); + } + + return Calamares::JobResult::ok(); +} + + +void +ZfsJob::setConfigurationMap( const QVariantMap& map ) +{ + m_poolName = CalamaresUtils::getString( map, "poolName" ); + m_poolOptions = CalamaresUtils::getString( map, "poolOptions" ); + m_datasetOptions = CalamaresUtils::getString( map, "datasetOptions" ); + + m_datasets = CalamaresUtils::getList( map, "datasets" ); +} + +CALAMARES_PLUGIN_FACTORY_DEFINITION( ZfsJobFactory, registerPlugin< ZfsJob >(); ) diff --git a/src/modules/zfs/ZfsJob.h b/src/modules/zfs/ZfsJob.h new file mode 100644 index 000000000..58a6450ee --- /dev/null +++ b/src/modules/zfs/ZfsJob.h @@ -0,0 +1,89 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 Evan James + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +#ifndef ZFSJOB_H +#define ZFSJOB_H + +#include +#include +#include + +#include "CppJob.h" + +#include "utils/PluginFactory.h" + +#include "DllMacro.h" + +struct ZfsResult +{ + bool success; + QString failureMessage; // This message is displayed to the user and should be translated at the time of population +}; + +/** @brief Create zpools and zfs datasets + * + */ +class PLUGINDLLEXPORT ZfsJob : public Calamares::CppJob +{ + Q_OBJECT + +public: + explicit ZfsJob( QObject* parent = nullptr ); + ~ZfsJob() override; + + QString prettyName() const override; + + Calamares::JobResult exec() override; + + void setConfigurationMap( const QVariantMap& configurationMap ) override; + +private: + QString m_poolName; + QString m_poolOptions; + QString m_datasetOptions; + QStringList m_mountpoints; + + QList< QVariant > m_datasets; + + /** @brief Creates a zpool based on the provided arguments + * + * @p deviceName is a full path to the device the zpool should be created on + * @p poolName is a string containing the name of the pool to create + * @p poolOptions are the options to pass to zpool create + * @p encrypt is a boolean which determines if the pool should be encrypted + * @p passphrase is a string continaing the passphrase + * + */ + ZfsResult createZpool( QString deviceName, + QString poolName, + QString poolOptions, + bool encrypt, + QString passphrase = QString() ) const; + + /** @brief Collects all the mountpoints from the partitions + * + * Iterates over @p partitions to gather each mountpoint present + * in the list of maps and populates m_mountpoints + * + */ + void collectMountpoints( const QVariantList& partitions ); + + /** @brief Check to see if a given mountpoint overlaps with one of the defined moutnpoints + * + * Iterates over m_partitions and checks if @p targetMountpoint overlaps with them by comparing + * the beginning of targetMountpoint with all the values in m_mountpoints. Of course, / is excluded + * since all the mountpoints would begin with / + * + */ + bool isMountpointOverlapping( const QString& targetMountpoint ) const; +}; + +CALAMARES_PLUGIN_FACTORY_DECLARATION( ZfsJobFactory ) + +#endif // ZFSJOB_H diff --git a/src/modules/zfs/zfs.conf b/src/modules/zfs/zfs.conf new file mode 100644 index 000000000..f2f8f52b0 --- /dev/null +++ b/src/modules/zfs/zfs.conf @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: no +# SPDX-License-Identifier: CC0-1.0 +# +# The zfs module creates the zfs pools and datasets +# +# +# +--- +# The name to be used for the zpool +poolName: zpcala + +# A list of options that will be passed to zpool create +poolOptions: "-f -o ashift=12 -O mountpoint=none -O acltype=posixacl -O relatime=on" + +# A list of options that will be passed to zfs create when creating each dataset +# Do not include "canmount" or "mountpoint" as those are set below in the datasets array +datasetOptions: "-o compression=lz4 -o atime=off -o xattr=sa" + +# An array of datasets that will be created on the zpool mounted at / +datasets: + - dsName: ROOT + mountpoint: none + canMount: off + - dsName: ROOT/distro + mountpoint: none + canMount: off + - dsName: ROOT/distro/root + mountpoint: / + canMount: noauto + - dsName: ROOT/distro/home + mountpoint: /home + canMount: on + - dsName: ROOT/distro/varcache + mountpoint: /var/cache + canMount: on + - dsName: ROOT/distro/varlog + mountpoint: /var/log + canMount: on diff --git a/src/modules/zfs/zfs.schema.yaml b/src/modules/zfs/zfs.schema.yaml new file mode 100644 index 000000000..ddad6d77b --- /dev/null +++ b/src/modules/zfs/zfs.schema.yaml @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2020 Adriaan de Groot +# SPDX-License-Identifier: GPL-3.0-or-later +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/zfs +additionalProperties: false +type: object +properties: + poolName: { type: string } + poolOptions: { type: string } + datasetOptions: { type: string } + datasets: + type: array + items: + type: object + additionalProperties: false + properties: + dsName: { type: string } + mountpoint: { type: string } + # Nominally a string, but "on" and "off" are valid and get + # turned into a boolean in the YAML parser. + canMount: { anyOf: [ { type: string }, { type: boolean } ] } + required: [ dsName, mountpoint, canMount ] +required: [ poolName, datasets ]