From 5ac5eee64910b2a444ff481bb20494376b90eed5 Mon Sep 17 00:00:00 2001 From: Balsa Asanovic Date: Mon, 29 Jan 2024 00:11:22 +0100 Subject: [PATCH 01/53] added username suggestion based on full name Three suggestions are given: name+surname nameInitial+surname name+surnameInitial --- web/src/components/users/FirstUser.jsx | 58 +++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/web/src/components/users/FirstUser.jsx b/web/src/components/users/FirstUser.jsx index ace01e94d2..689b2d4263 100644 --- a/web/src/components/users/FirstUser.jsx +++ b/web/src/components/users/FirstUser.jsx @@ -32,6 +32,10 @@ import { FormGroup, TextInput, Skeleton, + Menu, + MenuContent, + MenuList, + MenuItem } from "@patternfly/react-core"; import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table'; @@ -97,6 +101,8 @@ export default function FirstUser() { const [isFormOpen, setIsFormOpen] = useState(false); const [isValidPassword, setIsValidPassword] = useState(true); const [isSettingPassword, setIsSettingPassword] = useState(false); + const [showSuggestions, setShowSuggestions] = useState(false); + const [insideDropDown, setInsideDropDown] = useState(false); useEffect(() => { cancellablePromise(client.users.getUser()).then(userValues => { @@ -166,6 +172,26 @@ export default function FirstUser() { setFormValues({ ...formValues, [name]: value }); }; + const suggestUsernames = (fullName) => { + const cleanedName = fullName.replace(/[^\p{L}\p{N} ]/gu, "").toLowerCase(); + const nameParts = cleanedName.split(/\s+/); + const suggestions = []; + + nameParts.forEach((namePart, index) => { + if (index === 0) { + suggestions.push(namePart); + suggestions.push(namePart[0]); + nameParts.length > 1 && suggestions.push(namePart); + } else { + suggestions[0] += namePart; + suggestions[1] += namePart; + suggestions[2] += namePart[0]; + } + }); + + return suggestions; + }; + const isUserDefined = user?.userName && user?.userName !== ""; const showErrors = () => ((errors || []).length > 0); @@ -210,7 +236,14 @@ export default function FirstUser() { /> - + setShowSuggestions(true)} + onBlur={() => !insideDropDown && setShowSuggestions(false)} + > + { showSuggestions && formValues.fullName && !formValues.userName && + setInsideDropDown(true)} + onMouseLeave={() => setInsideDropDown(false)} + > + + + { suggestUsernames(formValues.fullName).map((suggestion, index) => ( + { setInsideDropDown(false); setFormValues({ ...formValues, userName: suggestion }) }} + > + { /* TRANSLATORS: dropdown username suggestions */ } + { _("Use suggested username ") } + {suggestion} + + )) } + + + } { isEditing && From 5d3e42ff4952eedcd69680b1131c2d50cc83365b Mon Sep 17 00:00:00 2001 From: Balsa Asanovic Date: Mon, 29 Jan 2024 00:11:45 +0100 Subject: [PATCH 02/53] added classes for styling dropdown in username suggestions --- web/src/assets/styles/app.scss | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web/src/assets/styles/app.scss b/web/src/assets/styles/app.scss index 3a9ff7bdef..8aa9b4e838 100644 --- a/web/src/assets/styles/app.scss +++ b/web/src/assets/styles/app.scss @@ -172,3 +172,13 @@ button.kebab-toggler { gap: 0 1em; width: 100%; } + +.first-username-dropdown { + position: absolute; + width: 100%; +} + +.first-username-wrapper { + position: relative; + width: 100%; +} From 502a23092f908f4527cc2587fae8483f8a293737 Mon Sep 17 00:00:00 2001 From: Balsa Asanovic Date: Sun, 11 Feb 2024 19:43:42 +0100 Subject: [PATCH 03/53] removed trailing space from transalation Replace strong with bold tag --- web/src/components/users/FirstUser.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/src/components/users/FirstUser.jsx b/web/src/components/users/FirstUser.jsx index 689b2d4263..88ae2db4bf 100644 --- a/web/src/components/users/FirstUser.jsx +++ b/web/src/components/users/FirstUser.jsx @@ -269,8 +269,7 @@ export default function FirstUser() { onClick={() => { setInsideDropDown(false); setFormValues({ ...formValues, userName: suggestion }) }} > { /* TRANSLATORS: dropdown username suggestions */ } - { _("Use suggested username ") } - {suggestion} + { _("Use suggested username") } {suggestion} )) } From 1f9badfef262eedffec3f7d240c8d016d5580a98 Mon Sep 17 00:00:00 2001 From: Balsa Asanovic Date: Tue, 20 Feb 2024 00:33:12 +0100 Subject: [PATCH 04/53] moved suggestUsernames method to utils.js file --- web/src/components/users/FirstUser.jsx | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/web/src/components/users/FirstUser.jsx b/web/src/components/users/FirstUser.jsx index 88ae2db4bf..61a310e4f5 100644 --- a/web/src/components/users/FirstUser.jsx +++ b/web/src/components/users/FirstUser.jsx @@ -42,6 +42,8 @@ import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table'; import { RowActions, PasswordAndConfirmationInput, Popup } from '~/components/core'; +import { suggestUsernames } from '~/components/users/utils'; + const UserNotDefined = ({ actionCb }) => { return (
@@ -172,26 +174,6 @@ export default function FirstUser() { setFormValues({ ...formValues, [name]: value }); }; - const suggestUsernames = (fullName) => { - const cleanedName = fullName.replace(/[^\p{L}\p{N} ]/gu, "").toLowerCase(); - const nameParts = cleanedName.split(/\s+/); - const suggestions = []; - - nameParts.forEach((namePart, index) => { - if (index === 0) { - suggestions.push(namePart); - suggestions.push(namePart[0]); - nameParts.length > 1 && suggestions.push(namePart); - } else { - suggestions[0] += namePart; - suggestions[1] += namePart; - suggestions[2] += namePart[0]; - } - }); - - return suggestions; - }; - const isUserDefined = user?.userName && user?.userName !== ""; const showErrors = () => ((errors || []).length > 0); From 94dce4dfc5523cf954700364523e7cfaa41ac15d Mon Sep 17 00:00:00 2001 From: Balsa Asanovic Date: Tue, 20 Feb 2024 00:33:34 +0100 Subject: [PATCH 05/53] created utils.js file with method for username suggestion --- web/src/components/users/utils.js | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 web/src/components/users/utils.js diff --git a/web/src/components/users/utils.js b/web/src/components/users/utils.js new file mode 100644 index 0000000000..546bf79912 --- /dev/null +++ b/web/src/components/users/utils.js @@ -0,0 +1,71 @@ +/* + * Copyright (c) [2024] SUSE LLC + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, contact SUSE LLC. + * + * To contact SUSE LLC about this file by physical or electronic mail, you may + * find current contact information at www.suse.com. + */ + +/** + * Method which generates username suggestions based on first and last name. + * The method cleans the input name by removing non-alphanumeric characters (except spaces), + * splits the name into parts, and then generates suggestions based on these parts. + * + * @param {string} fullName The full name used to generate username suggestions. + * @returns {string[]} An array of username suggestions. + */ +const suggestUsernames = (fullName) => { + // Cleaning the name. + const cleanedName = fullName + .normalize('NFD') + .trim() + .replace(/[\u0300-\u036f]/g, '') // Replacing accented characters with English equivalents, eg. š with s. + .replace(/[^\p{L}\p{N} ]/gu, "") // Keep only letters, numbers and spaces. Covering the whole Unicode range, not just ASCII. + .toLowerCase(); + + // Split the cleaned name into parts. + const nameParts = cleanedName.split(/\s+/); + + const suggestions = []; + + nameParts.forEach((namePart, index) => { + if (index === 0) { + suggestions.push(namePart); + suggestions.push(namePart[0]); + suggestions.push(namePart[0]); + suggestions.push(namePart); + suggestions.push(namePart[0]); + suggestions.push(namePart); + } else { + if (index === 1) + suggestions[1] += namePart; + suggestions[2] += namePart; + suggestions[3] += namePart[0]; + if (index === nameParts.length - 1) + suggestions[4] += namePart; + else + suggestions[4] += namePart[0]; + suggestions[5] += namePart; + } + }); + + // using Set object to remove duplicates, then converting back to array + return [...new Set(suggestions)]; +}; + +export { + suggestUsernames +}; From b71102d797298cd12c65bcfb5397aaa237b653da Mon Sep 17 00:00:00 2001 From: Balsa Asanovic Date: Tue, 20 Feb 2024 00:33:49 +0100 Subject: [PATCH 06/53] unit tests for utils.js file --- web/src/components/users/utils.test.js | 60 ++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 web/src/components/users/utils.test.js diff --git a/web/src/components/users/utils.test.js b/web/src/components/users/utils.test.js new file mode 100644 index 0000000000..e3711388de --- /dev/null +++ b/web/src/components/users/utils.test.js @@ -0,0 +1,60 @@ +/* + * Copyright (c) [2024] SUSE LLC + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, contact SUSE LLC. + * + * To contact SUSE LLC about this file by physical or electronic mail, you may + * find current contact information at www.suse.com. + */ + +import { suggestUsernames } from "./utils"; + +describe('suggestUsernames', () => { + test('handles basic single name', () => { + expect(suggestUsernames('John')).toEqual(expect.arrayContaining(['john', 'j'])); + }); + + test('handles basic two-part name', () => { + expect(suggestUsernames('John Doe')).toEqual(expect.arrayContaining(['john', 'jdoe', 'johnd', 'johndoe'])); + }); + + test('handles name with middle initial', () => { + expect(suggestUsernames('John Q. Doe')).toEqual(expect.arrayContaining(['john', 'jq', 'jqdoe', 'johnqd', 'johnqdoe'])); + }); + + test('normalizes accented characters', () => { + expect(suggestUsernames('José María')).toEqual(expect.arrayContaining(['jose', 'jmaria', 'josem', 'josemaria'])); + }); + + test('removes hyphens and apostrophes', () => { + expect(suggestUsernames("Jean-Luc O'Neill")).toEqual(expect.arrayContaining(['jeanluc', 'joneill', 'jeanluco', 'jeanluconeill'])); + }); + + test('removes non-alphanumeric characters', () => { + expect(suggestUsernames("Anna*#& Maria$%^")).toEqual(expect.arrayContaining(['anna', 'amaria', 'annam', 'annamaria'])); + }); + + test('handles long name with multiple parts', () => { + expect(suggestUsernames("Maria del Carmen Fernandez Vega")).toEqual(expect.arrayContaining(['maria', 'mdel', 'mdelcarmenfernandezvega', 'mariadcfv', 'mdcfvega', 'mariadelcarmenfernandezvega'])); + }); + + test('handles empty or invalid input', () => { + expect(suggestUsernames("")).toEqual(expect.arrayContaining([])); + }); + + test('trims spaces and handles multiple spaces between names', () => { + expect(suggestUsernames(" John Doe ")).toEqual(expect.arrayContaining(['john', 'jdoe', 'johnd', 'johndoe'])); + }); +}); From 06a89e6c0160619eb02ff815bff1c30c48a696cb Mon Sep 17 00:00:00 2001 From: Balsa Asanovic Date: Sun, 25 Feb 2024 23:09:43 +0100 Subject: [PATCH 07/53] moved suggestions menu to internal component --- web/src/components/users/FirstUser.jsx | 66 +++++++++++++++++--------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/web/src/components/users/FirstUser.jsx b/web/src/components/users/FirstUser.jsx index 61a310e4f5..43138b9c92 100644 --- a/web/src/components/users/FirstUser.jsx +++ b/web/src/components/users/FirstUser.jsx @@ -40,7 +40,7 @@ import { import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table'; -import { RowActions, PasswordAndConfirmationInput, Popup } from '~/components/core'; +import { RowActions, PasswordAndConfirmationInput, Popup, If } from '~/components/core'; import { suggestUsernames } from '~/components/users/utils'; @@ -82,6 +82,32 @@ const UserData = ({ user, actions }) => { ); }; +const UsernameSuggestions = ({ entries, onSelect, setInsideDropDown }) => { + return ( + setInsideDropDown(true)} + onMouseLeave={() => setInsideDropDown(false)} + > + + + {entries.map((suggestion, index) => ( + onSelect(suggestion)} + > + { /* TRANSLATORS: dropdown username suggestions */} + {_("Use suggested username")} {suggestion} + + ))} + + + + ); +}; + const CREATE_MODE = 'create'; const EDIT_MODE = 'edit'; @@ -193,6 +219,12 @@ export default function FirstUser() { const usingValidPassword = formValues.password && formValues.password !== "" && isValidPassword; const submitDisable = formValues.userName === "" || (isSettingPassword && !usingValidPassword); + const displaySuggestions = !formValues.userName && formValues.fullName && showSuggestions; + const onSuggestionSelected = (suggestion) => { + setInsideDropDown(false); + setFormValues({ ...formValues, userName: suggestion }); + }; + if (isLoading) return ; return ( @@ -235,28 +267,16 @@ export default function FirstUser() { isRequired onChange={handleInputChange} /> - { showSuggestions && formValues.fullName && !formValues.userName && - setInsideDropDown(true)} - onMouseLeave={() => setInsideDropDown(false)} - > - - - { suggestUsernames(formValues.fullName).map((suggestion, index) => ( - { setInsideDropDown(false); setFormValues({ ...formValues, userName: suggestion }) }} - > - { /* TRANSLATORS: dropdown username suggestions */ } - { _("Use suggested username") } {suggestion} - - )) } - - - } + + } + /> { isEditing && From 11db225c6472d4a3a2b37e3e2e0e563619ec0643 Mon Sep 17 00:00:00 2001 From: Balsa Asanovic Date: Mon, 26 Feb 2024 23:10:54 +0100 Subject: [PATCH 08/53] updated the algorithm for suggestion to be more readable --- web/src/components/users/utils.js | 47 ++++++++++++++++--------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/web/src/components/users/utils.js b/web/src/components/users/utils.js index 546bf79912..ab982fba96 100644 --- a/web/src/components/users/utils.js +++ b/web/src/components/users/utils.js @@ -20,7 +20,7 @@ */ /** - * Method which generates username suggestions based on first and last name. + * Method which generates username suggestions based on given full name. * The method cleans the input name by removing non-alphanumeric characters (except spaces), * splits the name into parts, and then generates suggestions based on these parts. * @@ -37,33 +37,34 @@ const suggestUsernames = (fullName) => { .toLowerCase(); // Split the cleaned name into parts. - const nameParts = cleanedName.split(/\s+/); + const parts = cleanedName.split(/\s+/); + const suggestions = new Set(); - const suggestions = []; + const firstLetters = parts.map(p => p[0]).join(''); + const lastPosition = parts.length - 1; - nameParts.forEach((namePart, index) => { - if (index === 0) { - suggestions.push(namePart); - suggestions.push(namePart[0]); - suggestions.push(namePart[0]); - suggestions.push(namePart); - suggestions.push(namePart[0]); - suggestions.push(namePart); - } else { - if (index === 1) - suggestions[1] += namePart; - suggestions[2] += namePart; - suggestions[3] += namePart[0]; - if (index === nameParts.length - 1) - suggestions[4] += namePart; - else - suggestions[4] += namePart[0]; - suggestions[5] += namePart; - } + const [firstPart, ...allExceptFirst] = parts; + const [firstLetter, ...allExceptFirstLetter] = firstLetters; + const lastPart = parts[lastPosition]; + + // Just the first part of the name + suggestions.add(firstPart); + // The first letter of the first part plus all other parts + suggestions.add(firstLetter + allExceptFirst.join('')); + // The first part plus the first letters of all other parts + suggestions.add(firstPart + allExceptFirstLetter.join('')); + // The first letters except the last one plus the last part + suggestions.add(firstLetters.substring(0, lastPosition) + lastPart); + // All parts without spaces + suggestions.add(parts.join('')); + + // let's drop suggestions with less than 3 characters + suggestions.forEach(s => { + if (s.length < 3) suggestions.delete(s); }); // using Set object to remove duplicates, then converting back to array - return [...new Set(suggestions)]; + return [...suggestions]; }; export { From 3cbb67475e4a777440d442bc4e769cfc9d4405a8 Mon Sep 17 00:00:00 2001 From: Balsa Asanovic Date: Mon, 26 Feb 2024 23:11:22 +0100 Subject: [PATCH 09/53] updated tests for suggestions algorithm --- web/src/components/users/utils.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/components/users/utils.test.js b/web/src/components/users/utils.test.js index e3711388de..0b188a4537 100644 --- a/web/src/components/users/utils.test.js +++ b/web/src/components/users/utils.test.js @@ -23,7 +23,7 @@ import { suggestUsernames } from "./utils"; describe('suggestUsernames', () => { test('handles basic single name', () => { - expect(suggestUsernames('John')).toEqual(expect.arrayContaining(['john', 'j'])); + expect(suggestUsernames('John')).toEqual(expect.arrayContaining(['john'])); }); test('handles basic two-part name', () => { @@ -31,7 +31,7 @@ describe('suggestUsernames', () => { }); test('handles name with middle initial', () => { - expect(suggestUsernames('John Q. Doe')).toEqual(expect.arrayContaining(['john', 'jq', 'jqdoe', 'johnqd', 'johnqdoe'])); + expect(suggestUsernames('John Q. Doe')).toEqual(expect.arrayContaining(['john', 'jqdoe', 'johnqd', 'johnqdoe'])); }); test('normalizes accented characters', () => { @@ -47,7 +47,7 @@ describe('suggestUsernames', () => { }); test('handles long name with multiple parts', () => { - expect(suggestUsernames("Maria del Carmen Fernandez Vega")).toEqual(expect.arrayContaining(['maria', 'mdel', 'mdelcarmenfernandezvega', 'mariadcfv', 'mdcfvega', 'mariadelcarmenfernandezvega'])); + expect(suggestUsernames("Maria del Carmen Fernandez Vega")).toEqual(expect.arrayContaining(['maria', 'mdelcarmenfernandezvega', 'mariadcfv', 'mdcfvega', 'mariadelcarmenfernandezvega'])); }); test('handles empty or invalid input', () => { From bcbf3210a1bcedd54b5d2cf94aefeb16a7ed6c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 26 Feb 2024 17:18:16 +0000 Subject: [PATCH 10/53] service: rename rubygem-agama to rubygem-agama-yast --- service/{agama.gemspec => agama-yast.gemspec} | 6 +++--- service/package/gem2rpm.yml | 1 + .../{rubygem-agama.changes => rubygem-agama-yast.changes} | 0 3 files changed, 4 insertions(+), 3 deletions(-) rename service/{agama.gemspec => agama-yast.gemspec} (93%) rename service/package/{rubygem-agama.changes => rubygem-agama-yast.changes} (100%) diff --git a/service/agama.gemspec b/service/agama-yast.gemspec similarity index 93% rename from service/agama.gemspec rename to service/agama-yast.gemspec index 62dbdba14f..b1d50c280d 100644 --- a/service/agama.gemspec +++ b/service/agama-yast.gemspec @@ -21,7 +21,7 @@ # find current contact information at www.suse.com. Gem::Specification.new do |spec| - spec.name = "agama" + spec.name = "agama-yast" # in a git checkout? if File.exist?(File.join(__dir__, "../.git")) @@ -33,8 +33,8 @@ Gem::Specification.new do |spec| spec.version = "99.yupdate" end - spec.summary = "Agama Installer Service" - spec.description = "System service for Agama, an experimental YaST-based installer." + spec.summary = "YaST integration service for Agama" + spec.description = "D-Bus service exposing some YaST features that are useful for Agama." spec.author = "YaST Team" spec.email = "yast-devel@opensuse.org" spec.homepage = "https://github.com/openSUSE/agama" diff --git a/service/package/gem2rpm.yml b/service/package/gem2rpm.yml index 142916e9d2..fef1bc79db 100644 --- a/service/package/gem2rpm.yml +++ b/service/package/gem2rpm.yml @@ -23,6 +23,7 @@ :preamble: |- # Override build.rpm, see also https://github.com/openSUSE/obs-build/blob/master/configs/ %global rb_build_versions %{rb_default_ruby} + Provides: agama-yast BuildRequires: dbus-1-common Requires: dbus-1-common Requires: suseconnect-ruby-bindings diff --git a/service/package/rubygem-agama.changes b/service/package/rubygem-agama-yast.changes similarity index 100% rename from service/package/rubygem-agama.changes rename to service/package/rubygem-agama-yast.changes From 383262780212feeb07e7634b3f68e3d41642bfab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 26 Feb 2024 15:19:54 +0000 Subject: [PATCH 11/53] rust: rename agama-dbus-server to agama-server --- rust/Cargo.toml | 2 +- rust/{agama-dbus-server => agama-server}/Cargo.toml | 0 .../share/server-example.yaml | 0 .../src/agama-dbus-server.rs | 0 .../src/agama-web-server.rs | 0 rust/{agama-dbus-server => agama-server}/src/error.rs | 0 rust/{agama-dbus-server => agama-server}/src/l10n.rs | 0 rust/{agama-dbus-server => agama-server}/src/l10n/helpers.rs | 0 rust/{agama-dbus-server => agama-server}/src/l10n/keyboard.rs | 0 rust/{agama-dbus-server => agama-server}/src/l10n/locale.rs | 0 rust/{agama-dbus-server => agama-server}/src/l10n/timezone.rs | 0 rust/{agama-dbus-server => agama-server}/src/l10n/web.rs | 0 rust/{agama-dbus-server => agama-server}/src/lib.rs | 0 rust/{agama-dbus-server => agama-server}/src/network.rs | 0 .../{agama-dbus-server => agama-server}/src/network/action.rs | 0 .../src/network/adapter.rs | 0 rust/{agama-dbus-server => agama-server}/src/network/dbus.rs | 0 .../src/network/dbus/interfaces.rs | 0 .../src/network/dbus/interfaces/common.rs | 0 .../src/network/dbus/interfaces/connection_configs.rs | 0 .../src/network/dbus/interfaces/connections.rs | 0 .../src/network/dbus/interfaces/devices.rs | 0 .../src/network/dbus/interfaces/ip_config.rs | 0 .../src/network/dbus/service.rs | 0 .../src/network/dbus/tree.rs | 0 rust/{agama-dbus-server => agama-server}/src/network/error.rs | 0 rust/{agama-dbus-server => agama-server}/src/network/model.rs | 0 .../src/network/model/builder.rs | 0 rust/{agama-dbus-server => agama-server}/src/network/nm.rs | 0 .../src/network/nm/adapter.rs | 0 .../src/network/nm/client.rs | 0 .../src/network/nm/dbus.rs | 0 .../src/network/nm/error.rs | 0 .../src/network/nm/model.rs | 0 .../src/network/nm/proxies.rs | 0 .../{agama-dbus-server => agama-server}/src/network/system.rs | 0 rust/{agama-dbus-server => agama-server}/src/questions.rs | 0 .../src/questions/answers.rs | 0 rust/{agama-dbus-server => agama-server}/src/web.rs | 0 rust/{agama-dbus-server => agama-server}/src/web/auth.rs | 0 rust/{agama-dbus-server => agama-server}/src/web/config.rs | 0 rust/{agama-dbus-server => agama-server}/src/web/docs.rs | 0 rust/{agama-dbus-server => agama-server}/src/web/event.rs | 0 rust/{agama-dbus-server => agama-server}/src/web/http.rs | 0 rust/{agama-dbus-server => agama-server}/src/web/progress.rs | 0 rust/{agama-dbus-server => agama-server}/src/web/service.rs | 0 rust/{agama-dbus-server => agama-server}/src/web/state.rs | 0 rust/{agama-dbus-server => agama-server}/src/web/ws.rs | 0 rust/{agama-dbus-server => agama-server}/tests/common/mod.rs | 0 rust/{agama-dbus-server => agama-server}/tests/l10n.rs | 0 rust/{agama-dbus-server => agama-server}/tests/network.rs | 0 rust/{agama-dbus-server => agama-server}/tests/service.rs | 0 rust/package/_service | 4 ++-- 53 files changed, 3 insertions(+), 3 deletions(-) rename rust/{agama-dbus-server => agama-server}/Cargo.toml (100%) rename rust/{agama-dbus-server => agama-server}/share/server-example.yaml (100%) rename rust/{agama-dbus-server => agama-server}/src/agama-dbus-server.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/agama-web-server.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/error.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/l10n.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/l10n/helpers.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/l10n/keyboard.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/l10n/locale.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/l10n/timezone.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/l10n/web.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/lib.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/action.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/adapter.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/dbus.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/dbus/interfaces.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/dbus/interfaces/common.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/dbus/interfaces/connection_configs.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/dbus/interfaces/connections.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/dbus/interfaces/devices.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/dbus/interfaces/ip_config.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/dbus/service.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/dbus/tree.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/error.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/model.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/model/builder.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/nm.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/nm/adapter.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/nm/client.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/nm/dbus.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/nm/error.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/nm/model.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/nm/proxies.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/network/system.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/questions.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/questions/answers.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/web.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/web/auth.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/web/config.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/web/docs.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/web/event.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/web/http.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/web/progress.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/web/service.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/web/state.rs (100%) rename rust/{agama-dbus-server => agama-server}/src/web/ws.rs (100%) rename rust/{agama-dbus-server => agama-server}/tests/common/mod.rs (100%) rename rust/{agama-dbus-server => agama-server}/tests/l10n.rs (100%) rename rust/{agama-dbus-server => agama-server}/tests/network.rs (100%) rename rust/{agama-dbus-server => agama-server}/tests/service.rs (100%) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 36ab33dc58..6885b0b788 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,7 +1,7 @@ [workspace] members = [ "agama-cli", - "agama-dbus-server", + "agama-server", "agama-derive", "agama-lib", "agama-locale-data", diff --git a/rust/agama-dbus-server/Cargo.toml b/rust/agama-server/Cargo.toml similarity index 100% rename from rust/agama-dbus-server/Cargo.toml rename to rust/agama-server/Cargo.toml diff --git a/rust/agama-dbus-server/share/server-example.yaml b/rust/agama-server/share/server-example.yaml similarity index 100% rename from rust/agama-dbus-server/share/server-example.yaml rename to rust/agama-server/share/server-example.yaml diff --git a/rust/agama-dbus-server/src/agama-dbus-server.rs b/rust/agama-server/src/agama-dbus-server.rs similarity index 100% rename from rust/agama-dbus-server/src/agama-dbus-server.rs rename to rust/agama-server/src/agama-dbus-server.rs diff --git a/rust/agama-dbus-server/src/agama-web-server.rs b/rust/agama-server/src/agama-web-server.rs similarity index 100% rename from rust/agama-dbus-server/src/agama-web-server.rs rename to rust/agama-server/src/agama-web-server.rs diff --git a/rust/agama-dbus-server/src/error.rs b/rust/agama-server/src/error.rs similarity index 100% rename from rust/agama-dbus-server/src/error.rs rename to rust/agama-server/src/error.rs diff --git a/rust/agama-dbus-server/src/l10n.rs b/rust/agama-server/src/l10n.rs similarity index 100% rename from rust/agama-dbus-server/src/l10n.rs rename to rust/agama-server/src/l10n.rs diff --git a/rust/agama-dbus-server/src/l10n/helpers.rs b/rust/agama-server/src/l10n/helpers.rs similarity index 100% rename from rust/agama-dbus-server/src/l10n/helpers.rs rename to rust/agama-server/src/l10n/helpers.rs diff --git a/rust/agama-dbus-server/src/l10n/keyboard.rs b/rust/agama-server/src/l10n/keyboard.rs similarity index 100% rename from rust/agama-dbus-server/src/l10n/keyboard.rs rename to rust/agama-server/src/l10n/keyboard.rs diff --git a/rust/agama-dbus-server/src/l10n/locale.rs b/rust/agama-server/src/l10n/locale.rs similarity index 100% rename from rust/agama-dbus-server/src/l10n/locale.rs rename to rust/agama-server/src/l10n/locale.rs diff --git a/rust/agama-dbus-server/src/l10n/timezone.rs b/rust/agama-server/src/l10n/timezone.rs similarity index 100% rename from rust/agama-dbus-server/src/l10n/timezone.rs rename to rust/agama-server/src/l10n/timezone.rs diff --git a/rust/agama-dbus-server/src/l10n/web.rs b/rust/agama-server/src/l10n/web.rs similarity index 100% rename from rust/agama-dbus-server/src/l10n/web.rs rename to rust/agama-server/src/l10n/web.rs diff --git a/rust/agama-dbus-server/src/lib.rs b/rust/agama-server/src/lib.rs similarity index 100% rename from rust/agama-dbus-server/src/lib.rs rename to rust/agama-server/src/lib.rs diff --git a/rust/agama-dbus-server/src/network.rs b/rust/agama-server/src/network.rs similarity index 100% rename from rust/agama-dbus-server/src/network.rs rename to rust/agama-server/src/network.rs diff --git a/rust/agama-dbus-server/src/network/action.rs b/rust/agama-server/src/network/action.rs similarity index 100% rename from rust/agama-dbus-server/src/network/action.rs rename to rust/agama-server/src/network/action.rs diff --git a/rust/agama-dbus-server/src/network/adapter.rs b/rust/agama-server/src/network/adapter.rs similarity index 100% rename from rust/agama-dbus-server/src/network/adapter.rs rename to rust/agama-server/src/network/adapter.rs diff --git a/rust/agama-dbus-server/src/network/dbus.rs b/rust/agama-server/src/network/dbus.rs similarity index 100% rename from rust/agama-dbus-server/src/network/dbus.rs rename to rust/agama-server/src/network/dbus.rs diff --git a/rust/agama-dbus-server/src/network/dbus/interfaces.rs b/rust/agama-server/src/network/dbus/interfaces.rs similarity index 100% rename from rust/agama-dbus-server/src/network/dbus/interfaces.rs rename to rust/agama-server/src/network/dbus/interfaces.rs diff --git a/rust/agama-dbus-server/src/network/dbus/interfaces/common.rs b/rust/agama-server/src/network/dbus/interfaces/common.rs similarity index 100% rename from rust/agama-dbus-server/src/network/dbus/interfaces/common.rs rename to rust/agama-server/src/network/dbus/interfaces/common.rs diff --git a/rust/agama-dbus-server/src/network/dbus/interfaces/connection_configs.rs b/rust/agama-server/src/network/dbus/interfaces/connection_configs.rs similarity index 100% rename from rust/agama-dbus-server/src/network/dbus/interfaces/connection_configs.rs rename to rust/agama-server/src/network/dbus/interfaces/connection_configs.rs diff --git a/rust/agama-dbus-server/src/network/dbus/interfaces/connections.rs b/rust/agama-server/src/network/dbus/interfaces/connections.rs similarity index 100% rename from rust/agama-dbus-server/src/network/dbus/interfaces/connections.rs rename to rust/agama-server/src/network/dbus/interfaces/connections.rs diff --git a/rust/agama-dbus-server/src/network/dbus/interfaces/devices.rs b/rust/agama-server/src/network/dbus/interfaces/devices.rs similarity index 100% rename from rust/agama-dbus-server/src/network/dbus/interfaces/devices.rs rename to rust/agama-server/src/network/dbus/interfaces/devices.rs diff --git a/rust/agama-dbus-server/src/network/dbus/interfaces/ip_config.rs b/rust/agama-server/src/network/dbus/interfaces/ip_config.rs similarity index 100% rename from rust/agama-dbus-server/src/network/dbus/interfaces/ip_config.rs rename to rust/agama-server/src/network/dbus/interfaces/ip_config.rs diff --git a/rust/agama-dbus-server/src/network/dbus/service.rs b/rust/agama-server/src/network/dbus/service.rs similarity index 100% rename from rust/agama-dbus-server/src/network/dbus/service.rs rename to rust/agama-server/src/network/dbus/service.rs diff --git a/rust/agama-dbus-server/src/network/dbus/tree.rs b/rust/agama-server/src/network/dbus/tree.rs similarity index 100% rename from rust/agama-dbus-server/src/network/dbus/tree.rs rename to rust/agama-server/src/network/dbus/tree.rs diff --git a/rust/agama-dbus-server/src/network/error.rs b/rust/agama-server/src/network/error.rs similarity index 100% rename from rust/agama-dbus-server/src/network/error.rs rename to rust/agama-server/src/network/error.rs diff --git a/rust/agama-dbus-server/src/network/model.rs b/rust/agama-server/src/network/model.rs similarity index 100% rename from rust/agama-dbus-server/src/network/model.rs rename to rust/agama-server/src/network/model.rs diff --git a/rust/agama-dbus-server/src/network/model/builder.rs b/rust/agama-server/src/network/model/builder.rs similarity index 100% rename from rust/agama-dbus-server/src/network/model/builder.rs rename to rust/agama-server/src/network/model/builder.rs diff --git a/rust/agama-dbus-server/src/network/nm.rs b/rust/agama-server/src/network/nm.rs similarity index 100% rename from rust/agama-dbus-server/src/network/nm.rs rename to rust/agama-server/src/network/nm.rs diff --git a/rust/agama-dbus-server/src/network/nm/adapter.rs b/rust/agama-server/src/network/nm/adapter.rs similarity index 100% rename from rust/agama-dbus-server/src/network/nm/adapter.rs rename to rust/agama-server/src/network/nm/adapter.rs diff --git a/rust/agama-dbus-server/src/network/nm/client.rs b/rust/agama-server/src/network/nm/client.rs similarity index 100% rename from rust/agama-dbus-server/src/network/nm/client.rs rename to rust/agama-server/src/network/nm/client.rs diff --git a/rust/agama-dbus-server/src/network/nm/dbus.rs b/rust/agama-server/src/network/nm/dbus.rs similarity index 100% rename from rust/agama-dbus-server/src/network/nm/dbus.rs rename to rust/agama-server/src/network/nm/dbus.rs diff --git a/rust/agama-dbus-server/src/network/nm/error.rs b/rust/agama-server/src/network/nm/error.rs similarity index 100% rename from rust/agama-dbus-server/src/network/nm/error.rs rename to rust/agama-server/src/network/nm/error.rs diff --git a/rust/agama-dbus-server/src/network/nm/model.rs b/rust/agama-server/src/network/nm/model.rs similarity index 100% rename from rust/agama-dbus-server/src/network/nm/model.rs rename to rust/agama-server/src/network/nm/model.rs diff --git a/rust/agama-dbus-server/src/network/nm/proxies.rs b/rust/agama-server/src/network/nm/proxies.rs similarity index 100% rename from rust/agama-dbus-server/src/network/nm/proxies.rs rename to rust/agama-server/src/network/nm/proxies.rs diff --git a/rust/agama-dbus-server/src/network/system.rs b/rust/agama-server/src/network/system.rs similarity index 100% rename from rust/agama-dbus-server/src/network/system.rs rename to rust/agama-server/src/network/system.rs diff --git a/rust/agama-dbus-server/src/questions.rs b/rust/agama-server/src/questions.rs similarity index 100% rename from rust/agama-dbus-server/src/questions.rs rename to rust/agama-server/src/questions.rs diff --git a/rust/agama-dbus-server/src/questions/answers.rs b/rust/agama-server/src/questions/answers.rs similarity index 100% rename from rust/agama-dbus-server/src/questions/answers.rs rename to rust/agama-server/src/questions/answers.rs diff --git a/rust/agama-dbus-server/src/web.rs b/rust/agama-server/src/web.rs similarity index 100% rename from rust/agama-dbus-server/src/web.rs rename to rust/agama-server/src/web.rs diff --git a/rust/agama-dbus-server/src/web/auth.rs b/rust/agama-server/src/web/auth.rs similarity index 100% rename from rust/agama-dbus-server/src/web/auth.rs rename to rust/agama-server/src/web/auth.rs diff --git a/rust/agama-dbus-server/src/web/config.rs b/rust/agama-server/src/web/config.rs similarity index 100% rename from rust/agama-dbus-server/src/web/config.rs rename to rust/agama-server/src/web/config.rs diff --git a/rust/agama-dbus-server/src/web/docs.rs b/rust/agama-server/src/web/docs.rs similarity index 100% rename from rust/agama-dbus-server/src/web/docs.rs rename to rust/agama-server/src/web/docs.rs diff --git a/rust/agama-dbus-server/src/web/event.rs b/rust/agama-server/src/web/event.rs similarity index 100% rename from rust/agama-dbus-server/src/web/event.rs rename to rust/agama-server/src/web/event.rs diff --git a/rust/agama-dbus-server/src/web/http.rs b/rust/agama-server/src/web/http.rs similarity index 100% rename from rust/agama-dbus-server/src/web/http.rs rename to rust/agama-server/src/web/http.rs diff --git a/rust/agama-dbus-server/src/web/progress.rs b/rust/agama-server/src/web/progress.rs similarity index 100% rename from rust/agama-dbus-server/src/web/progress.rs rename to rust/agama-server/src/web/progress.rs diff --git a/rust/agama-dbus-server/src/web/service.rs b/rust/agama-server/src/web/service.rs similarity index 100% rename from rust/agama-dbus-server/src/web/service.rs rename to rust/agama-server/src/web/service.rs diff --git a/rust/agama-dbus-server/src/web/state.rs b/rust/agama-server/src/web/state.rs similarity index 100% rename from rust/agama-dbus-server/src/web/state.rs rename to rust/agama-server/src/web/state.rs diff --git a/rust/agama-dbus-server/src/web/ws.rs b/rust/agama-server/src/web/ws.rs similarity index 100% rename from rust/agama-dbus-server/src/web/ws.rs rename to rust/agama-server/src/web/ws.rs diff --git a/rust/agama-dbus-server/tests/common/mod.rs b/rust/agama-server/tests/common/mod.rs similarity index 100% rename from rust/agama-dbus-server/tests/common/mod.rs rename to rust/agama-server/tests/common/mod.rs diff --git a/rust/agama-dbus-server/tests/l10n.rs b/rust/agama-server/tests/l10n.rs similarity index 100% rename from rust/agama-dbus-server/tests/l10n.rs rename to rust/agama-server/tests/l10n.rs diff --git a/rust/agama-dbus-server/tests/network.rs b/rust/agama-server/tests/network.rs similarity index 100% rename from rust/agama-dbus-server/tests/network.rs rename to rust/agama-server/tests/network.rs diff --git a/rust/agama-dbus-server/tests/service.rs b/rust/agama-server/tests/service.rs similarity index 100% rename from rust/agama-dbus-server/tests/service.rs rename to rust/agama-server/tests/service.rs diff --git a/rust/package/_service b/rust/package/_service index 74597e457b..04b7d36141 100644 --- a/rust/package/_service +++ b/rust/package/_service @@ -7,8 +7,8 @@ master rust enable - package/agama-cli.changes - package/agama-cli.spec + package/agama.changes + package/agama.spec agama/rust From 14ed20265920013a402ffc2cbb553fe603f65e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 26 Feb 2024 16:06:23 +0000 Subject: [PATCH 12/53] rust: reorganize the packaging --- .../{agama-cli.changes => agama.changes} | 0 rust/package/{agama-cli.spec => agama.spec} | 51 ++++++++----------- 2 files changed, 22 insertions(+), 29 deletions(-) rename rust/package/{agama-cli.changes => agama.changes} (100%) rename rust/package/{agama-cli.spec => agama.spec} (80%) diff --git a/rust/package/agama-cli.changes b/rust/package/agama.changes similarity index 100% rename from rust/package/agama-cli.changes rename to rust/package/agama.changes diff --git a/rust/package/agama-cli.spec b/rust/package/agama.spec similarity index 80% rename from rust/package/agama-cli.spec rename to rust/package/agama.spec index b180f26aa7..418b94e034 100644 --- a/rust/package/agama-cli.spec +++ b/rust/package/agama.spec @@ -15,11 +15,11 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # -Name: agama-cli +Name: agama # This will be set by osc services, that will run after this. Version: 0 Release: 0 -Summary: Agama command line interface +Summary: Agama Installer # If you know the license, put it's SPDX string here. # Alternately, you can use cargo lock2rpmprovides to help generate this. License: GPL-2.0-only @@ -30,49 +30,42 @@ BuildRequires: cargo-packaging BuildRequires: pkgconfig(openssl) # used in tests for dbus service BuildRequires: python-langtable-data -BuildRequires: timezone BuildRequires: dbus-1-common +Requires: dbus-1-common # required by agama-dbus-server integration tests BuildRequires: dbus-1-daemon BuildRequires: clang-devel BuildRequires: pkgconfig(pam) +# required by autoinstallation Requires: jsonnet Requires: lshw # required by "agama logs store" Requires: bzip2 Requires: tar # required for translating the keyboards descriptions +BuildRequires: xkeyboard-config-lang Requires: xkeyboard-config-lang # required for getting the list of timezones Requires: timezone +BuildRequires: timezone +# dependency on the YaST part of Agama +Requires: agama-yast %description -Command line program to interact with the agama service. - -%package -n agama-dbus-server -# This will be set by osc services, that will run after this. -Version: 0 -Release: 0 -Summary: Agama Rust D-Bus service -License: GPL-2.0-only -Url: https://github.com/opensuse/agama -Requires: python-langtable-data -Requires: dbus-1-common +Agama is a service-based Linux installer. It is composed of an HTTP-based API, +a web user interface, a command-line interface and a D-Bus service which exposes +part of the YaST libraries. -%description -n agama-dbus-server -D-Bus service for agama project. It provides localization, networking and questions services. - -%package -n agama-web-server +%package -n agama-cli # This will be set by osc services, that will run after this. Version: 0 Release: 0 -Summary: Agama web server +Summary: Agama command-line interface License: GPL-2.0-only Url: https://github.com/opensuse/agama -Requires: agama-dbus-server -%description -n agama-web-server -Agama project web server. It provides a web-based API to Agama. +%description -n agama-cli +Command line program to interact with the Agama installer. %prep %autosetup -a1 -n agama @@ -95,23 +88,23 @@ install -m 0644 --target-directory=%{buildroot}%{_datadir}/dbus-1/agama-services %check +PATH=$PWD/share/bin:$PATH %ifarch aarch64 /usr/bin/cargo auditable test -j1 --offline --no-fail-fast %else +echo $PATH %{cargo_test} %endif %files -%{_bindir}/agama -%dir %{_datadir}/agama-cli -%{_datadir}/agama-cli/profile.schema.json - -%files -n agama-dbus-server %{_bindir}/agama-dbus-server +%{_bindir}/agama-web-server %{_datadir}/dbus-1/agama-services %{_pam_vendordir}/agama -%files -n agama-web-server -%{_bindir}/agama-web-server +%files -n agama-cli +%{_bindir}/agama +%dir %{_datadir}/agama-cli +%{_datadir}/agama-cli/profile.schema.json %changelog From 10def5c139534a3d9f8981d22d7eec5c0fe94619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 27 Feb 2024 11:33:07 +0000 Subject: [PATCH 13/53] rust: re-enable LocalesDatabase tests --- rust/agama-server/src/l10n/locale.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/rust/agama-server/src/l10n/locale.rs b/rust/agama-server/src/l10n/locale.rs index 630c844144..65d76ec1e4 100644 --- a/rust/agama-server/src/l10n/locale.rs +++ b/rust/agama-server/src/l10n/locale.rs @@ -117,7 +117,6 @@ mod tests { use super::LocalesDatabase; use agama_locale_data::LocaleCode; - #[ignore] #[test] fn test_read_locales() { let mut db = LocalesDatabase::new(); @@ -129,7 +128,6 @@ mod tests { assert_eq!(&found.territory, "Spanien"); } - #[ignore] #[test] fn test_locale_exists() { let mut db = LocalesDatabase::new(); From 6480258386864a30736326b43c16a116d4f7317c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 27 Feb 2024 11:38:33 +0000 Subject: [PATCH 14/53] rust: avoid warning messages when compiling mod.rs * See https://users.rust-lang.org/t/invalid-dead-code-warning-for-submodule-in-integration-test/80259. --- rust/agama-server/tests/l10n.rs | 2 +- rust/agama-server/tests/network.rs | 2 +- rust/agama-server/tests/service.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/agama-server/tests/l10n.rs b/rust/agama-server/tests/l10n.rs index 6ad7e352a0..f2d0291c29 100644 --- a/rust/agama-server/tests/l10n.rs +++ b/rust/agama-server/tests/l10n.rs @@ -1,4 +1,4 @@ -mod common; +pub mod common; use agama_dbus_server::l10n::web::l10n_service; use axum::{ diff --git a/rust/agama-server/tests/network.rs b/rust/agama-server/tests/network.rs index 2261746325..ed4b0037b2 100644 --- a/rust/agama-server/tests/network.rs +++ b/rust/agama-server/tests/network.rs @@ -1,4 +1,4 @@ -mod common; +pub mod common; use self::common::{async_retry, DBusServer}; use agama_dbus_server::network::{ diff --git a/rust/agama-server/tests/service.rs b/rust/agama-server/tests/service.rs index aac1b2922b..6179484be8 100644 --- a/rust/agama-server/tests/service.rs +++ b/rust/agama-server/tests/service.rs @@ -1,4 +1,4 @@ -mod common; +pub mod common; use agama_dbus_server::{ service, From 325bc6fc7a93d59290d51d86bd6ff2aebad03fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 27 Feb 2024 14:03:38 +0000 Subject: [PATCH 15/53] Update Copyright headers --- rust/package/agama.spec | 4 ++-- service/agama-yast.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/package/agama.spec b/rust/package/agama.spec index 418b94e034..926ab05b07 100644 --- a/rust/package/agama.spec +++ b/rust/package/agama.spec @@ -1,7 +1,7 @@ # -# spec file for package agama-cli +# spec file for package agama # -# Copyright (c) 2023 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2023-2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed diff --git a/service/agama-yast.gemspec b/service/agama-yast.gemspec index b1d50c280d..d93dfdd3fd 100644 --- a/service/agama-yast.gemspec +++ b/service/agama-yast.gemspec @@ -1,7 +1,7 @@ # frozen_string_literal: true # -# Copyright (c) [2022] SUSE LLC +# Copyright (c) 2022-2024 SUSE LLC # # All Rights Reserved. # From ac16e4ecb5c396981c05f41ae65cebb31be1a6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 27 Feb 2024 15:43:44 +0000 Subject: [PATCH 16/53] Adapt GitHub Actions to the new package names --- .github/workflows/obs-release.yml | 2 +- .github/workflows/obs-service-shared.yml | 4 ++-- .github/workflows/obs-staging-rust.yml | 2 +- .github/workflows/obs-staging-service.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/obs-release.yml b/.github/workflows/obs-release.yml index c31034c5fd..77d1f0049a 100644 --- a/.github/workflows/obs-release.yml +++ b/.github/workflows/obs-release.yml @@ -20,7 +20,7 @@ jobs: with: install_packages: obs-service-cargo_audit obs-service-cargo_vendor project_name: systemsmanagement:Agama:Devel - package_name: agama-cli + package_name: agama update_web: uses: ./.github/workflows/obs-staging-shared.yml diff --git a/.github/workflows/obs-service-shared.yml b/.github/workflows/obs-service-shared.yml index ab99479bc4..a7f4871fd0 100644 --- a/.github/workflows/obs-service-shared.yml +++ b/.github/workflows/obs-service-shared.yml @@ -62,7 +62,7 @@ jobs: OBS_USER: ${{ secrets.OBS_USER }} OBS_PASSWORD: ${{ secrets.OBS_PASSWORD }} - - name: Commit the rubygem-agama package to ${{ inputs.project_name }} + - name: Commit the rubygem-agama-yast package to ${{ inputs.project_name }} run: rake osc:commit working-directory: ./service env: @@ -71,7 +71,7 @@ jobs: SKIP_OSC_BUILD: 1 OBS_PROJECT: ${{ inputs.project_name }} - - name: Submit the rubygem-agama package + - name: Submit the rubygem-agama-yast package # only when a tag has been pushed if: ${{ github.ref_type == 'tag' }} # the package has been comitted in the previous step, just submit it diff --git a/.github/workflows/obs-staging-rust.yml b/.github/workflows/obs-staging-rust.yml index b83f6759f7..0e804b3c2f 100644 --- a/.github/workflows/obs-staging-rust.yml +++ b/.github/workflows/obs-staging-rust.yml @@ -17,4 +17,4 @@ jobs: with: install_packages: obs-service-cargo_audit obs-service-cargo_vendor project_name: systemsmanagement:Agama:Staging - package_name: agama-cli + package_name: agama diff --git a/.github/workflows/obs-staging-service.yml b/.github/workflows/obs-staging-service.yml index 5d3cb47bf5..342f2e38f0 100644 --- a/.github/workflows/obs-staging-service.yml +++ b/.github/workflows/obs-staging-service.yml @@ -1,4 +1,4 @@ -name: Submit rubygem-agama +name: Submit rubygem-agama-yast on: # runs on pushes targeting the default branch From 7aff6f282d312fb21edd5c3e65a36c0473fd7242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 27 Feb 2024 15:46:09 +0000 Subject: [PATCH 17/53] Update documentation with new package names --- PACKAGING.md | 20 +++++++++++--------- README.md | 12 ++++++------ setup-services.sh | 2 +- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/PACKAGING.md b/PACKAGING.md index 58cee4ee62..60314c10ec 100644 --- a/PACKAGING.md +++ b/PACKAGING.md @@ -23,10 +23,11 @@ The Agama packages are available in two OBS projects: You can find more details the automatic OBS synchronization in the [obs_integration.md](doc/obs_integration.md) file. -The process to build each package is slightly different depending on the technology we are using. -While the Ruby-based one (`rubygem-agama`) is built as any other YaST package, the web UI -(`cockpit-agama`) and the CLI (`agama-cli`) rely on [OBS source -services](https://openbuildservice.org/help/manuals/obs-user-guide/cha.obs.source_service.html). +The process to build each package is slightly different depending on the +technology we are using. While the Ruby-based one (`rubygem-agama-yast`) is +built as any other YaST package, Agama server (`agama`), the CLI (`agama-cli`), +and the web UI (`cockpit-agama`) rely on +[OBS source services](https://openbuildservice.org/help/manuals/obs-user-guide/cha.obs.source_service.html). ## Versioning Policy @@ -71,8 +72,8 @@ for manual update. ### Service You can check the current package in -[systemsmanagement:Agama:Staging/rubygem-agama]( -https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/rubygem-agama). +[systemsmanagement:Agama:Staging/rubygem-agama-yast]( +https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/rubygem-agama-yast). Use `rake` to update the package in OBS as you would do with any other YaST package: @@ -108,10 +109,11 @@ respect such a tag. (e.g. `2.1+42`). You can read more about the overall approach of this package in the following article: [Git work flows in the upcoming 2.7 release](https://openbuildservice.org/2016/04/08/new_git_in_27/). -### Command-line Interface +### Server and command-line Interface -The current package is [systemsmanagement:Agama:Staging/agama-cli]( -https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/agama-cli). +The current package is [systemsmanagement:Agama:Staging/agama]( +https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/agama), +which includes `agama` and `agama-cli` as a subpackage. To manually update the package in the build service, run the following commands: diff --git a/README.md b/README.md index 970385403e..6fd9ba799c 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,14 @@ **[OBS systemsmanagement:Agama:Staging](https://build.opensuse.org/project/show/systemsmanagement:Agama:Staging)** -[![Submit agama-cli](https://github.com/openSUSE/agama/actions/workflows/obs-staging-rust.yml/badge.svg)](https://github.com/openSUSE/agama/actions/workflows/obs-staging-rust.yml) +[![Submit agama](https://github.com/openSUSE/agama/actions/workflows/obs-staging-rust.yml/badge.svg)](https://github.com/openSUSE/agama/actions/workflows/obs-staging-rust.yml) [![Submit cockpit-agama](https://github.com/openSUSE/agama/actions/workflows/obs-staging-web.yml/badge.svg)](https://github.com/openSUSE/agama/actions/workflows/obs-staging-web.yml) -[![Submit rubygem-agama](https://github.com/openSUSE/agama/actions/workflows/obs-staging-service.yml/badge.svg)](https://github.com/openSUSE/agama/actions/workflows/obs-staging-service.yml) +[![Submit rubygem-agama-yast](https://github.com/openSUSE/agama/actions/workflows/obs-staging-service.yml/badge.svg)](https://github.com/openSUSE/agama/actions/workflows/obs-staging-service.yml) [![Submit cockpit-agama-playwright](https://github.com/openSUSE/agama/actions/workflows/obs-staging-playwright.yml/badge.svg)](https://github.com/openSUSE/agama/actions/workflows/obs-staging-playwright.yml) -[![OBS Staging/agama-cli](https://img.shields.io/obs/systemsmanagement:Agama:Staging/agama-cli/openSUSE_Tumbleweed/x86_64?label=Package%20agama-cli)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/agama-cli) +[![OBS Staging/agama](https://img.shields.io/obs/systemsmanagement:Agama:Staging/agama/openSUSE_Tumbleweed/x86_64?label=Package%20agama)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/agama) [![OBS Staging/cockpit-agama](https://img.shields.io/obs/systemsmanagement:Agama:Staging/cockpit-agama/openSUSE_Tumbleweed/x86_64?label=Package%20cockpit-agama)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/cockpit-agama) -[![OBS Staging/rubygem-agama](https://img.shields.io/obs/systemsmanagement:Agama:Staging/rubygem-agama/openSUSE_Tumbleweed/x86_64?label=Package%20rubygem-agama)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/rubygem-agama) +[![OBS Staging/rubygem-agama-yast](https://img.shields.io/obs/systemsmanagement:Agama:Staging/rubygem-agama-yast/openSUSE_Tumbleweed/x86_64?label=Package%20rubygem-agama-yast)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/rubygem-agama-yast) [![OBS Staging/agama-products-opensuse](https://img.shields.io/obs/systemsmanagement%3AAgama%3AStaging/agama-products-opensuse/openSUSE_Tumbleweed/x86_64?label=Package%20agama-products-opensuse)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/agama-products-opensuse) [![OBS Staging/cockpit-agama-playwright](https://img.shields.io/obs/systemsmanagement:Agama:Staging/cockpit-agama-playwright/openSUSE_Tumbleweed/x86_64?label=Package%20cockpit-agama-playwright)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/cockpit-agama-playwright) [![OBS Staging/agama-live](https://img.shields.io/obs/systemsmanagement:Agama:Staging/agama-live:openSUSE/images/x86_64?label=Live%20ISO)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/agama-live) @@ -35,9 +35,9 @@ ![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/openSUSE/agama?label=Version&sort=semver) [![Release](https://github.com/openSUSE/agama/actions/workflows/obs-release.yml/badge.svg)](https://github.com/openSUSE/agama/actions/workflows/obs-release.yml) -[![OBS Devel/agama-cli](https://img.shields.io/obs/systemsmanagement:Agama:Devel/agama-cli/openSUSE_Tumbleweed/x86_64?label=Package%20agama-cli)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Devel/agama-cli) +[![OBS Devel/agama](https://img.shields.io/obs/systemsmanagement:Agama:Devel/agama/openSUSE_Tumbleweed/x86_64?label=Package%20agama)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Devel/agama) [![OBS Devel/cockpit-agama](https://img.shields.io/obs/systemsmanagement:Agama:Devel/cockpit-agama/openSUSE_Tumbleweed/x86_64?label=Package%20cockpit-agama)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Devel/cockpit-agama) -[![OBS Devel/rubygem-agama](https://img.shields.io/obs/systemsmanagement:Agama:Devel/rubygem-agama/openSUSE_Tumbleweed/x86_64?label=Package%20rubygem-agama)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Devel/rubygem-agama) +[![OBS Devel/rubygem-agama-yast](https://img.shields.io/obs/systemsmanagement:Agama:Devel/rubygem-agama-yast/openSUSE_Tumbleweed/x86_64?label=Package%20rubygem-agama-yast)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Devel/rubygem-agama-yast) [![OBS Devel/agama-live](https://img.shields.io/obs/systemsmanagement:Agama:Devel/agama-live:openSUSE/images/x86_64?label=Live%20ISO)](https://build.opensuse.org/package/show/systemsmanagement:Agama:Devel/agama-live) # Agama: A Service-based Linux Installer diff --git a/setup-services.sh b/setup-services.sh index 4f54260ce4..ee647418d1 100755 --- a/setup-services.sh +++ b/setup-services.sh @@ -121,7 +121,7 @@ fi # Only install cargo if it is not available (avoid conflicts with rustup) which cargo || $SUDO zypper --non-interactive install cargo -# Packages required by Rust code (see ./rust/package/agama-cli.spec) +# Packages required by Rust code (see ./rust/package/agama.spec) $SUDO zypper --non-interactive install \ bzip2 \ clang-devel \ From f15e694f2a9dec52aa0c23096d7334b62f9d11c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 27 Feb 2024 16:03:18 +0000 Subject: [PATCH 18/53] Update changes files --- rust/package/agama.changes | 8 ++++++++ service/package/rubygem-agama-yast.changes | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/rust/package/agama.changes b/rust/package/agama.changes index ef6dccebab..656cd074eb 100644 --- a/rust/package/agama.changes +++ b/rust/package/agama.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Tue Feb 27 15:55:28 UTC 2024 - Imobach Gonzalez Sosa + +- Reorganize RPM packages (gh#openSUSE/agama#1056): + * agama is now the main package and it contains agama-dbus-server + and agama-web-server. + * agama-cli is a subpackage. + ------------------------------------------------------------------- Wed Feb 7 11:49:02 UTC 2024 - Imobach Gonzalez Sosa diff --git a/service/package/rubygem-agama-yast.changes b/service/package/rubygem-agama-yast.changes index 8c07ea0b36..5f51032451 100644 --- a/service/package/rubygem-agama-yast.changes +++ b/service/package/rubygem-agama-yast.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue Feb 27 15:53:46 UTC 2024 - Imobach Gonzalez Sosa + +- Rename the gem to agama-yast and the package to + rubygem-agama-yast (gh#openSUSE/agama#1056). + ------------------------------------------------------------------- Tue Feb 20 13:15:15 UTC 2024 - José Iván López González From 71c12520462492cebcc42d227938cad95b6143f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 27 Feb 2024 16:05:11 +0000 Subject: [PATCH 19/53] Add a conflict with the agama-dbus-server package --- rust/package/agama.spec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/package/agama.spec b/rust/package/agama.spec index 926ab05b07..51edf53679 100644 --- a/rust/package/agama.spec +++ b/rust/package/agama.spec @@ -26,6 +26,7 @@ License: GPL-2.0-only Url: https://github.com/opensuse/agama Source0: agama.tar Source1: vendor.tar.zst + BuildRequires: cargo-packaging BuildRequires: pkgconfig(openssl) # used in tests for dbus service @@ -51,6 +52,9 @@ BuildRequires: timezone # dependency on the YaST part of Agama Requires: agama-yast +# conflicts with the old packages +Conflicts: agama-dbus-server + %description Agama is a service-based Linux installer. It is composed of an HTTP-based API, a web user interface, a command-line interface and a D-Bus service which exposes From 3bbfbb24249a9aa4923bae5f781be6c0a09d900f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Wed, 28 Feb 2024 16:45:45 +0000 Subject: [PATCH 20/53] Update from code review Co-authored-by: Josef Reidinger --- PACKAGING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PACKAGING.md b/PACKAGING.md index 60314c10ec..08fb248b25 100644 --- a/PACKAGING.md +++ b/PACKAGING.md @@ -109,7 +109,7 @@ respect such a tag. (e.g. `2.1+42`). You can read more about the overall approach of this package in the following article: [Git work flows in the upcoming 2.7 release](https://openbuildservice.org/2016/04/08/new_git_in_27/). -### Server and command-line Interface +### Server and Command-line Interface The current package is [systemsmanagement:Agama:Staging/agama]( https://build.opensuse.org/package/show/systemsmanagement:Agama:Staging/agama), From 75b978130ea1d68d3d6f0a96234bdfaadb7fc1f5 Mon Sep 17 00:00:00 2001 From: Balsa Asanovic Date: Wed, 28 Feb 2024 23:27:44 +0100 Subject: [PATCH 21/53] logged changes --- web/package/cockpit-agama.changes | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/web/package/cockpit-agama.changes b/web/package/cockpit-agama.changes index 792f22ff75..7899366961 100644 --- a/web/package/cockpit-agama.changes +++ b/web/package/cockpit-agama.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed Feb 28 22:26:23 UTC 2024 - Balsa Asanovic + +- Added auto suggestion of usernames during user creation based + on given full name. (gh#openSUSE/agama#1022). + ------------------------------------------------------------------- Mon Feb 26 20:46:45 UTC 2024 - Josef Reidinger From 6402b605cb37efddb09fc991121372ea63cc5636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Wed, 28 Feb 2024 18:24:21 +0000 Subject: [PATCH 22/53] Add a missing runtime dependency on langtable-data --- rust/package/agama.spec | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rust/package/agama.spec b/rust/package/agama.spec index 51edf53679..2eeddf579f 100644 --- a/rust/package/agama.spec +++ b/rust/package/agama.spec @@ -30,7 +30,6 @@ Source1: vendor.tar.zst BuildRequires: cargo-packaging BuildRequires: pkgconfig(openssl) # used in tests for dbus service -BuildRequires: python-langtable-data BuildRequires: dbus-1-common Requires: dbus-1-common # required by agama-dbus-server integration tests @@ -49,6 +48,9 @@ Requires: xkeyboard-config-lang # required for getting the list of timezones Requires: timezone BuildRequires: timezone +# required for getting the languages information +BuildRequires: python-langtable-data +Requires: python-langtable-data # dependency on the YaST part of Agama Requires: agama-yast From eb79c6f29163f1b0377fd56d2ed4c4a82c4b3c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20D=C3=ADaz?= <1691872+dgdavid@users.noreply.github.com> Date: Thu, 29 Feb 2024 08:47:25 +0000 Subject: [PATCH 23/53] Disable cspell in test file It's a test that have a lot of unknown words because they are username suggestions. It makes sense to disable the spell checker in this case. --- web/src/components/users/utils.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/src/components/users/utils.test.js b/web/src/components/users/utils.test.js index 0b188a4537..1049e3b171 100644 --- a/web/src/components/users/utils.test.js +++ b/web/src/components/users/utils.test.js @@ -19,6 +19,8 @@ * find current contact information at www.suse.com. */ +/* cspell:disable */ + import { suggestUsernames } from "./utils"; describe('suggestUsernames', () => { From 4a9a42f7c08e9031b47c00805b75f3877c03bd1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?= Date: Fri, 1 Mar 2024 11:00:08 +0000 Subject: [PATCH 24/53] [web] Indicate whether the system is transactional --- .../components/storage/ProposalPage.test.jsx | 7 +++ .../storage/ProposalSettingsSection.jsx | 33 ++++++++-- .../storage/ProposalSettingsSection.test.jsx | 33 ++++++++++ web/src/components/storage/utils.js | 37 ++++++++++- web/src/components/storage/utils.test.js | 61 ++++++++++++++++++- 5 files changed, 162 insertions(+), 9 deletions(-) diff --git a/web/src/components/storage/ProposalPage.test.jsx b/web/src/components/storage/ProposalPage.test.jsx index 5a2993b413..3b8464f84b 100644 --- a/web/src/components/storage/ProposalPage.test.jsx +++ b/web/src/components/storage/ProposalPage.test.jsx @@ -39,6 +39,13 @@ jest.mock("@patternfly/react-core", () => { jest.mock("~/components/core/Sidebar", () => () =>
Agama sidebar
); jest.mock("~/components/storage/ProposalPageMenu", () => () =>
ProposalPage Options
); +jest.mock("~/context/product", () => ({ + ...jest.requireActual("~/context/product"), + useProduct: () => ({ + selectedProduct : { name: "Test" } + }) +})); + const vda = { sid: "59", type: "disk", diff --git a/web/src/components/storage/ProposalSettingsSection.jsx b/web/src/components/storage/ProposalSettingsSection.jsx index 1ce78674db..453bb366c6 100644 --- a/web/src/components/storage/ProposalSettingsSection.jsx +++ b/web/src/components/storage/ProposalSettingsSection.jsx @@ -21,12 +21,14 @@ import React, { useEffect, useState } from "react"; import { Checkbox, Form, Skeleton, Switch, Tooltip } from "@patternfly/react-core"; +import { sprintf } from "sprintf-js"; import { _ } from "~/i18n"; import { If, PasswordAndConfirmationInput, Section, Popup } from "~/components/core"; import { Icon } from "~/components/layout"; import { noop } from "~/utils"; -import { hasFS } from "~/components/storage/utils"; +import { hasFS, isTransactionalSystem } from "~/components/storage/utils"; +import { useProduct } from "~/context/product"; /** * @typedef {import ("~/client/storage").ProposalManager.ProposalSettings} ProposalSettings @@ -147,7 +149,9 @@ const SnapshotsField = ({ const forcedSnapshots = !configurableSnapshots && hasFS(rootVolume, "Btrfs") && rootVolume.snapshots; const SnapshotsToggle = () => { - const explanation = _("Uses Btrfs for the root file system allowing to boot to a previous version of the system after configuration changes or software upgrades."); + const explanation = _("Uses Btrfs for the root file system allowing to boot to a previous \ +version of the system after configuration changes or software upgrades."); + return ( <> { onChange({ encryptionPassword: password, encryptionMethod: method }); }; @@ -312,12 +318,29 @@ export default function ProposalSettingsSection({ const encryption = settings.encryptionPassword !== undefined && settings.encryptionPassword.length > 0; + const transactional = isTransactionalSystem(settings?.volumes || []); + return ( <>
- + +
+ {/* TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) */} + {sprintf(_("%s is an immutable system with atomic updates using a read-only Btrfs \ +root file system."), selectedProduct.name)} +
+
+ } + else={ + + } /> { }; }); +jest.mock("~/context/product", () => ({ + ...jest.requireActual("~/context/product"), + useProduct: () => ({ + selectedProduct : { name: "Test" } + }) +})); + let props; beforeEach(() => { props = {}; }); +const rootVolume = { mountPath: "/", fsType: "Btrfs", outline: { snapshotsConfigurable: true } }; + +describe("if the system is not transactional", () => { + beforeEach(() => { + props.settings = { volumes: [rootVolume] }; + }); + + it("renders the snapshots switch", () => { + plainRender(); + + screen.getByRole("checkbox", { name: "Use Btrfs Snapshots" }); + }); +}); + +describe("if the system is transactional", () => { + beforeEach(() => { + props.settings = { volumes: [{ ...rootVolume, transactional: true }] }; + }); + + it("renders explanation about transactional system", () => { + plainRender(); + + screen.getByText("Transactional system"); + }); +}); + describe("Encryption field", () => { describe("if encryption password setting is not set yet", () => { beforeEach(() => { diff --git a/web/src/components/storage/utils.js b/web/src/components/storage/utils.js index 621e5194dc..e7175f9b7f 100644 --- a/web/src/components/storage/utils.js +++ b/web/src/components/storage/utils.js @@ -1,5 +1,5 @@ /* - * Copyright (c) [2023] SUSE LLC + * Copyright (c) [2023-2024] SUSE LLC * * All Rights Reserved. * @@ -149,6 +149,36 @@ const hasFS = (volume, fs) => { return volFS.toLowerCase() === fs.toLocaleLowerCase(); }; +/** + * Checks whether the given volume has snapshots. + * + * @param {import(~/clients/storage).Volume} volume + * @returns {boolean} + */ +const hasSnapshots = (volume) => { + return hasFS(volume, "btrfs") && volume.snapshots; +}; + +/** + * Checks whether the given volume defines a transactional root. + * + * @param {import(~/clients/storage).Volume} volume + * @returns {boolean} + */ +const isTransactionalRoot = (volume) => { + return volume.mountPath === "/" && volume.transactional; +}; + +/** + * Checks whether the given volumes defines a transactional system. + * + * @param {import(~/clients/storage).Volume[]} volumes + * @returns {boolean} + */ +const isTransactionalSystem = (volumes) => { + return volumes.find(v => isTransactionalRoot(v)) !== undefined; +}; + export { DEFAULT_SIZE_UNIT, SIZE_METHODS, @@ -157,5 +187,8 @@ export { deviceSize, parseToBytes, splitSize, - hasFS + hasFS, + hasSnapshots, + isTransactionalRoot, + isTransactionalSystem }; diff --git a/web/src/components/storage/utils.test.js b/web/src/components/storage/utils.test.js index 052e69bbf7..a973e27a0a 100644 --- a/web/src/components/storage/utils.test.js +++ b/web/src/components/storage/utils.test.js @@ -1,5 +1,5 @@ /* - * Copyright (c) [2023] SUSE LLC + * Copyright (c) [2023-2024] SUSE LLC * * All Rights Reserved. * @@ -19,7 +19,16 @@ * find current contact information at www.suse.com. */ -import { deviceSize, deviceLabel, parseToBytes, splitSize, hasFS } from "./utils"; +import { + deviceSize, + deviceLabel, + parseToBytes, + splitSize, + hasFS, + hasSnapshots, + isTransactionalRoot, + isTransactionalSystem +} from "./utils"; describe("deviceSize", () => { it("returns the size with units", () => { @@ -100,3 +109,51 @@ describe("hasFS", () => { expect(hasFS({ fsType: "Btrfs" }, "EXT4")).toBe(false); }); }); + +describe("hasSnapshots", () => { + it("returns false if the volume has not Btrfs file system", () => { + expect(hasSnapshots({ fsType: "EXT4", snapshots: true })).toBe(false); + }); + + it("returns false if the volume has not snapshots enabled", () => { + expect(hasSnapshots({ fsType: "Btrfs", snapshots: false })).toBe(false); + }); + + it("returns true if the volume has Btrfs file system and snapshots enabled", () => { + expect(hasSnapshots({ fsType: "Btrfs", snapshots: true })).toBe(true); + }); +}); + +describe("isTransactionalRoot", () => { + it("returns false if the volume is not root", () => { + expect(isTransactionalRoot({ mountPath: "/home", transactional: true })).toBe(false); + }); + + it("returns false if the volume has not transactional enabled", () => { + expect(isTransactionalRoot({ mountPath: "/", transactional: false })).toBe(false); + }); + + it("returns true if the volume is root and has transactional enabled", () => { + expect(isTransactionalRoot({ mountPath: "/", transactional: true })).toBe(true); + }); +}); + +describe("isTransactionalSystem", () => { + it("returns false if volumes does not include a transactional root", () => { + expect(isTransactionalSystem([])).toBe(false); + + const volumes = [ + { mountPath: "/" }, + { mountPath: "/home", transactional: true } + ]; + expect(isTransactionalSystem(volumes)).toBe(false); + }); + + it("returns true if volumes includes a transactional root", () => { + const volumes = [ + { mountPath: "EXT4" }, + { mountPath: "/", transactional: true } + ]; + expect(isTransactionalSystem(volumes)).toBe(true); + }); +}); From 9c9fba42672ff9f408f989f5de79a1dd80ba576d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?= Date: Fri, 1 Mar 2024 11:00:47 +0000 Subject: [PATCH 25/53] [web] Do not show snapshots flag for transactional --- .../components/storage/ProposalVolumes.jsx | 10 ++++----- .../storage/ProposalVolumes.test.jsx | 22 ++++--------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/web/src/components/storage/ProposalVolumes.jsx b/web/src/components/storage/ProposalVolumes.jsx index 8b6398b43a..be080ece93 100644 --- a/web/src/components/storage/ProposalVolumes.jsx +++ b/web/src/components/storage/ProposalVolumes.jsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2022-2023] SUSE LLC + * Copyright (c) [2022-2024] SUSE LLC * * All Rights Reserved. * @@ -34,7 +34,7 @@ import { _ } from "~/i18n"; import { Em, If, Popup, RowActions, Tip } from '~/components/core'; import { Icon } from '~/components/layout'; import { VolumeForm } from '~/components/storage'; -import { deviceSize } from '~/components/storage/utils'; +import { deviceSize, hasSnapshots, isTransactionalRoot } from '~/components/storage/utils'; import { noop } from "~/utils"; /** @@ -200,8 +200,8 @@ const VolumeRow = ({ columns, volume, options, isLoading, onEdit, onDelete }) => }; const Details = ({ volume, options }) => { - const hasSnapshots = volume.fsType === "Btrfs" && volume.snapshots; - const transactional = volume.fsType === "Btrfs" && volume.transactional; + const snapshots = hasSnapshots(volume); + const transactional = isTransactionalRoot(volume); // TRANSLATORS: the filesystem uses a logical volume (LVM) const text = `${volume.fsType} ${options.lvm ? _("logical volume") : _("partition")}`; @@ -215,7 +215,7 @@ const VolumeRow = ({ columns, volume, options, isLoading, onEdit, onDelete }) => {/* TRANSLATORS: filesystem flag, it uses an encryption */} {_("encrypted")}} /> {/* TRANSLATORS: filesystem flag, it allows creating snapshots */} - {_("with snapshots")}} /> + {_("with snapshots")}} /> {/* TRANSLATORS: flag for transactional file system */} {_("transactional")}} /> diff --git a/web/src/components/storage/ProposalVolumes.test.jsx b/web/src/components/storage/ProposalVolumes.test.jsx index 68197b189e..d3b799fb74 100644 --- a/web/src/components/storage/ProposalVolumes.test.jsx +++ b/web/src/components/storage/ProposalVolumes.test.jsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2022-2023] SUSE LLC + * Copyright (c) [2022-2024] SUSE LLC * * All Rights Reserved. * @@ -217,9 +217,9 @@ describe("if there are volumes", () => { within(popup).getByText("Edit file system"); }); - describe("and there is transactional Btrfs volume", () => { + describe("and there is transactional Btrfs root volume", () => { beforeEach(() => { - props.volumes = [{ ...volumes.root, transactional: true }]; + props.volumes = [{ ...volumes.root, snapshots: true, transactional: true }]; }); it("renders 'transactional' legend as part of its information", async () => { @@ -233,7 +233,7 @@ describe("if there are volumes", () => { describe("and there is Btrfs volume using snapshots", () => { beforeEach(() => { - props.volumes = [{ ...volumes.root, snapshots: true }]; + props.volumes = [{ ...volumes.root, snapshots: true, transactional: false }]; }); it("renders 'with snapshots' legend as part of its information", async () => { @@ -244,20 +244,6 @@ describe("if there are volumes", () => { within(volumes).getByRole("row", { name: "/ Btrfs partition with snapshots 1 KiB - 2 KiB" }); }); }); - - describe("and there is a transactional Btrfs volume using snapshots", () => { - beforeEach(() => { - props.volumes = [{ ...volumes.root, transactional: true, snapshots: true }]; - }); - - it("renders 'with snapshots' and 'transactional' legends as part of its information", async () => { - plainRender(); - - const [, volumes] = await screen.findAllByRole("rowgroup"); - - within(volumes).getByRole("row", { name: "/ Btrfs partition with snapshots transactional 1 KiB - 2 KiB" }); - }); - }); }); describe("if there are not volumes", () => { From e3aabaa64e9f9279751d974b71fbee73f597c169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?= Date: Fri, 1 Mar 2024 11:01:19 +0000 Subject: [PATCH 26/53] [web] Changelog --- web/package/cockpit-agama.changes | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/web/package/cockpit-agama.changes b/web/package/cockpit-agama.changes index 7899366961..87fbb37d54 100644 --- a/web/package/cockpit-agama.changes +++ b/web/package/cockpit-agama.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Mar 1 10:56:35 UTC 2024 - José Iván López González + +- Indicate whether the system is transactional + (gh#openSUSE/agama/1063). + ------------------------------------------------------------------- Wed Feb 28 22:26:23 UTC 2024 - Balsa Asanovic From cdfd4c00a0ad6dd02087a2f02c88b690842475bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?= Date: Fri, 1 Mar 2024 14:15:42 +0000 Subject: [PATCH 27/53] [web] Import types --- web/src/components/storage/utils.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/web/src/components/storage/utils.js b/web/src/components/storage/utils.js index e7175f9b7f..d2322bc167 100644 --- a/web/src/components/storage/utils.js +++ b/web/src/components/storage/utils.js @@ -25,6 +25,11 @@ import xbytes from "xbytes"; import { N_ } from "~/i18n"; +/** + * @typedef {import ("~/client/storage").Volume} Volume + * @typedef {import ("~/clients/storage").StorageDevice} StorageDevice + */ + /** * @typedef {Object} SizeObject * @@ -125,7 +130,7 @@ const parseToBytes = (size) => { /** * Generates the label for the given device * - * @param {import(~/clients/storage).StorageDevice} device + * @param {StorageDevice} device * @returns {string} */ const deviceLabel = (device) => { @@ -139,7 +144,7 @@ const deviceLabel = (device) => { * Checks if volume uses given fs. This method works same as in backend * case insensitive. * - * @param {import(~/clients/storage).Volume} volume + * @param {Volume} volume * @param {string} fs - Filesystem name to check. * @returns {boolean} true when volume uses given fs */ @@ -152,7 +157,7 @@ const hasFS = (volume, fs) => { /** * Checks whether the given volume has snapshots. * - * @param {import(~/clients/storage).Volume} volume + * @param {Volume} volume * @returns {boolean} */ const hasSnapshots = (volume) => { @@ -162,7 +167,7 @@ const hasSnapshots = (volume) => { /** * Checks whether the given volume defines a transactional root. * - * @param {import(~/clients/storage).Volume} volume + * @param {Volume} volume * @returns {boolean} */ const isTransactionalRoot = (volume) => { @@ -172,7 +177,7 @@ const isTransactionalRoot = (volume) => { /** * Checks whether the given volumes defines a transactional system. * - * @param {import(~/clients/storage).Volume[]} volumes + * @param {Volume[]} volumes * @returns {boolean} */ const isTransactionalSystem = (volumes) => { From e75dcf828439fb265128943bb18eb0cd605f850b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Thu, 29 Feb 2024 06:19:28 +0000 Subject: [PATCH 28/53] rust: add a software service * By now it only implements a list of products. --- rust/agama-lib/src/product.rs | 2 +- rust/agama-server/src/agama-web-server.rs | 2 +- rust/agama-server/src/lib.rs | 1 + rust/agama-server/src/software.rs | 2 + rust/agama-server/src/software/web.rs | 73 +++++++++++++++++++++++ rust/agama-server/src/web.rs | 6 +- 6 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 rust/agama-server/src/software.rs create mode 100644 rust/agama-server/src/software/web.rs diff --git a/rust/agama-lib/src/product.rs b/rust/agama-lib/src/product.rs index e85173f6c9..8b352f602d 100644 --- a/rust/agama-lib/src/product.rs +++ b/rust/agama-lib/src/product.rs @@ -5,6 +5,6 @@ mod proxies; mod settings; mod store; -pub use client::ProductClient; +pub use client::{Product, ProductClient}; pub use settings::ProductSettings; pub use store::ProductStore; diff --git a/rust/agama-server/src/agama-web-server.rs b/rust/agama-server/src/agama-web-server.rs index d8a16fc565..56343bfdf5 100644 --- a/rust/agama-server/src/agama-web-server.rs +++ b/rust/agama-server/src/agama-web-server.rs @@ -45,7 +45,7 @@ async fn serve_command(address: &str) -> anyhow::Result<()> { run_monitor(tx.clone()).await?; let config = web::ServiceConfig::load().unwrap(); - let service = web::service(config, tx); + let service = web::service(config, tx).await; axum::serve(listener, service) .await .expect("could not mount app on listener"); diff --git a/rust/agama-server/src/lib.rs b/rust/agama-server/src/lib.rs index 421b9e3efd..1a5c30c1a2 100644 --- a/rust/agama-server/src/lib.rs +++ b/rust/agama-server/src/lib.rs @@ -2,5 +2,6 @@ pub mod error; pub mod l10n; pub mod network; pub mod questions; +pub mod software; pub mod web; pub use web::service; diff --git a/rust/agama-server/src/software.rs b/rust/agama-server/src/software.rs new file mode 100644 index 0000000000..d74ed1900c --- /dev/null +++ b/rust/agama-server/src/software.rs @@ -0,0 +1,2 @@ +pub mod web; +pub use web::software_service; diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs new file mode 100644 index 0000000000..29e6c285d7 --- /dev/null +++ b/rust/agama-server/src/software/web.rs @@ -0,0 +1,73 @@ +//! This module implements the web API for the software module. +//! +//! It is a wrapper around the YaST D-Bus API. + +use crate::web::EventsSender; +use agama_lib::{connection, product::Product, software::proxies::SoftwareProductProxy}; +use axum::{ + extract::State, + http::StatusCode, + response::{IntoResponse, Response}, + routing::get, + Json, Router, +}; +use serde_json::json; +use thiserror::Error; + +#[derive(Clone)] +struct SoftwareState<'a> { + software: SoftwareProductProxy<'a>, +} + +#[derive(Error, Debug)] +pub enum SoftwareError { + #[error("Service error: {0}")] + Error(#[from] zbus::Error), +} + +impl IntoResponse for SoftwareError { + fn into_response(self) -> Response { + let body = json!({ + "error": self.to_string() + }); + (StatusCode::BAD_REQUEST, Json(body)).into_response() + } +} + +/// Sets up and returns the axum service for the software module. +/// +/// * `events`: channel to send the events to the main service. +pub async fn software_service(_events: EventsSender) -> Router { + let connection = connection().await.unwrap(); + let proxy = SoftwareProductProxy::new(&connection).await.unwrap(); + let state = SoftwareState { software: proxy }; + Router::new() + .route("/products", get(products)) + .with_state(state) +} + +/// Returns the list of available products. +/// +/// * `state`: service state. +async fn products<'a>( + State(state): State>, +) -> Result>, SoftwareError> { + let products = state.software.available_products().await?; + let products = products + .into_iter() + .map(|(id, name, data)| { + let description = data + .get("description") + .and_then(|d| d.downcast_ref::()) + .unwrap_or(""); + + Product { + id, + name, + description: description.to_string(), + } + }) + .collect(); + + Ok(Json(products)) +} diff --git a/rust/agama-server/src/web.rs b/rust/agama-server/src/web.rs index 7cbb1ec6b8..82b0c0c02a 100644 --- a/rust/agama-server/src/web.rs +++ b/rust/agama-server/src/web.rs @@ -21,6 +21,7 @@ pub use docs::ApiDoc; pub use event::{Event, EventsReceiver, EventsSender}; use crate::l10n::web::l10n_service; +use crate::software::web::software_service; use axum::Router; pub use service::MainServiceBuilder; @@ -30,9 +31,10 @@ use self::progress::EventsProgressPresenter; /// /// * `config`: service configuration. /// * `events`: D-Bus connection. -pub fn service(config: ServiceConfig, events: EventsSender) -> Router { +pub async fn service(config: ServiceConfig, events: EventsSender) -> Router { MainServiceBuilder::new(events.clone()) - .add_service("/l10n", l10n_service(events)) + .add_service("/l10n", l10n_service(events.clone())) + .add_service("/software", software_service(events).await) .with_config(config) .build() } From d424b689bbccde8bccb1ce666ef7a6e1fdd68ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Thu, 29 Feb 2024 09:47:35 +0000 Subject: [PATCH 29/53] rust: add support to select a product via HTTP --- rust/agama-lib/src/product/client.rs | 5 ++++- rust/agama-server/src/software/web.rs | 20 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index 106166b621..e7fcc49e6f 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -8,7 +8,7 @@ use zbus::Connection; use super::proxies::RegistrationProxy; /// Represents a software product -#[derive(Debug, Serialize)] +#[derive(Default, Debug, Serialize)] pub struct Product { /// Product ID (eg., "ALP", "Tumbleweed", etc.) pub id: String, @@ -16,6 +16,8 @@ pub struct Product { pub name: String, /// Product description pub description: String, + /// Whether the product is selected + pub selected: bool, } /// D-Bus client for the software service @@ -48,6 +50,7 @@ impl<'a> ProductClient<'a> { id, name, description: description.to_string(), + ..Default::default() } }) .collect(); diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 29e6c285d7..1e46eb3791 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -5,10 +5,10 @@ use crate::web::EventsSender; use agama_lib::{connection, product::Product, software::proxies::SoftwareProductProxy}; use axum::{ - extract::State, + extract::{Path, State}, http::StatusCode, response::{IntoResponse, Response}, - routing::get, + routing::{get, put}, Json, Router, }; use serde_json::json; @@ -43,6 +43,7 @@ pub async fn software_service(_events: EventsSender) -> Router { let state = SoftwareState { software: proxy }; Router::new() .route("/products", get(products)) + .route("/products/:id/select", put(select_product)) .with_state(state) } @@ -53,6 +54,7 @@ async fn products<'a>( State(state): State>, ) -> Result>, SoftwareError> { let products = state.software.available_products().await?; + let selected_product = state.software.selected_product().await?; let products = products .into_iter() .map(|(id, name, data)| { @@ -60,14 +62,28 @@ async fn products<'a>( .get("description") .and_then(|d| d.downcast_ref::()) .unwrap_or(""); + let selected = selected_product == id; Product { id, name, description: description.to_string(), + selected, } }) .collect(); Ok(Json(products)) } + +/// Selects a product. +/// +/// * `state`: service state. +/// * `id`: product ID. +async fn select_product<'a>( + State(state): State>, + Path(id): Path, +) -> Result<(), SoftwareError> { + state.software.select_product(&id).await?; + Ok(()) +} From 57cac7f97ff9638c2697c34daeae249cf5cb4bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Thu, 29 Feb 2024 12:00:30 +0000 Subject: [PATCH 30/53] rust: emit product changes --- rust/agama-server/src/software.rs | 2 +- rust/agama-server/src/software/web.rs | 14 +++++++++++++- rust/agama-server/src/web.rs | 14 +++++++------- rust/agama-server/src/web/event.rs | 1 + 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/rust/agama-server/src/software.rs b/rust/agama-server/src/software.rs index d74ed1900c..9f234e6cff 100644 --- a/rust/agama-server/src/software.rs +++ b/rust/agama-server/src/software.rs @@ -1,2 +1,2 @@ pub mod web; -pub use web::software_service; +pub use web::{software_monitor, software_service}; diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 1e46eb3791..62a069f3e0 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -2,7 +2,7 @@ //! //! It is a wrapper around the YaST D-Bus API. -use crate::web::EventsSender; +use crate::web::{Event, EventsSender}; use agama_lib::{connection, product::Product, software::proxies::SoftwareProductProxy}; use axum::{ extract::{Path, State}, @@ -13,6 +13,7 @@ use axum::{ }; use serde_json::json; use thiserror::Error; +use tokio_stream::StreamExt; #[derive(Clone)] struct SoftwareState<'a> { @@ -34,6 +35,17 @@ impl IntoResponse for SoftwareError { } } +pub async fn software_monitor(events: EventsSender) { + let connection = connection().await.unwrap(); + let proxy = SoftwareProductProxy::new(&connection).await.unwrap(); + let mut stream = proxy.receive_selected_product_changed().await; + while let Some(change) = stream.next().await { + if let Ok(id) = change.get().await { + _ = events.send(Event::ProductChanged { id }); + } + } +} + /// Sets up and returns the axum service for the software module. /// /// * `events`: channel to send the events to the main service. diff --git a/rust/agama-server/src/web.rs b/rust/agama-server/src/web.rs index 82b0c0c02a..5940a2336a 100644 --- a/rust/agama-server/src/web.rs +++ b/rust/agama-server/src/web.rs @@ -4,6 +4,11 @@ //! * Emit relevant events via websocket. //! * Serve the code for the web user interface (not implemented yet). +use self::progress::EventsProgressPresenter; +use crate::l10n::web::l10n_service; +use crate::software::web::{software_monitor, software_service}; +use axum::Router; + mod auth; mod config; mod docs; @@ -19,14 +24,8 @@ pub use auth::generate_token; pub use config::ServiceConfig; pub use docs::ApiDoc; pub use event::{Event, EventsReceiver, EventsSender}; - -use crate::l10n::web::l10n_service; -use crate::software::web::software_service; -use axum::Router; pub use service::MainServiceBuilder; -use self::progress::EventsProgressPresenter; - /// Returns a service that implements the web-based Agama API. /// /// * `config`: service configuration. @@ -45,7 +44,7 @@ pub async fn service(config: ServiceConfig, events: EventsSender) -> Router { /// /// * `events`: channel to send the events to. pub async fn run_monitor(events: EventsSender) -> Result<(), ServiceError> { - let presenter = EventsProgressPresenter::new(events); + let presenter = EventsProgressPresenter::new(events.clone()); let connection = connection().await?; let mut monitor = ProgressMonitor::new(connection).await?; tokio::spawn(async move { @@ -53,5 +52,6 @@ pub async fn run_monitor(events: EventsSender) -> Result<(), ServiceError> { eprintln!("Could not monitor the D-Bus server: {}", error); } }); + tokio::spawn(async move { software_monitor(events.clone()).await }); Ok(()) } diff --git a/rust/agama-server/src/web/event.rs b/rust/agama-server/src/web/event.rs index 76db326bc4..409adec0d0 100644 --- a/rust/agama-server/src/web/event.rs +++ b/rust/agama-server/src/web/event.rs @@ -7,6 +7,7 @@ use tokio::sync::broadcast::{Receiver, Sender}; pub enum Event { LocaleChanged { locale: String }, Progress(Progress), + ProductChanged { id: String }, } pub type EventsSender = Sender; From fc3e12aaf93bbb8a96b7c17a0bdb72bea531709f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Fri, 1 Mar 2024 11:44:02 +0000 Subject: [PATCH 31/53] rust: move software config to a separate resource --- rust/agama-lib/src/product/client.rs | 3 -- rust/agama-server/src/software/web.rs | 53 +++++++++++++++++++++------ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index e7fcc49e6f..b7b848ac32 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -16,8 +16,6 @@ pub struct Product { pub name: String, /// Product description pub description: String, - /// Whether the product is selected - pub selected: bool, } /// D-Bus client for the software service @@ -50,7 +48,6 @@ impl<'a> ProductClient<'a> { id, name, description: description.to_string(), - ..Default::default() } }) .collect(); diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 62a069f3e0..ec792fd752 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -5,12 +5,13 @@ use crate::web::{Event, EventsSender}; use agama_lib::{connection, product::Product, software::proxies::SoftwareProductProxy}; use axum::{ - extract::{Path, State}, + extract::State, http::StatusCode, response::{IntoResponse, Response}, routing::{get, put}, Json, Router, }; +use serde::{Deserialize, Serialize}; use serde_json::json; use thiserror::Error; use tokio_stream::StreamExt; @@ -18,6 +19,24 @@ use tokio_stream::StreamExt; #[derive(Clone)] struct SoftwareState<'a> { software: SoftwareProductProxy<'a>, + connection: zbus::Connection, +} + +#[derive(Clone, Serialize, Deserialize)] +struct SoftwareConfig { + patterns: Option>, + product: Option, +} + +impl SoftwareConfig { + pub async fn from_dbus(connection: &zbus::Connection) -> Result { + let software = SoftwareProductProxy::new(&connection).await?; + let product = software.selected_product().await?; + Ok(SoftwareConfig { + patterns: Some(vec![]), + product: Some(product), + }) + } } #[derive(Error, Debug)] @@ -52,10 +71,13 @@ pub async fn software_monitor(events: EventsSender) { pub async fn software_service(_events: EventsSender) -> Router { let connection = connection().await.unwrap(); let proxy = SoftwareProductProxy::new(&connection).await.unwrap(); - let state = SoftwareState { software: proxy }; + let state = SoftwareState { + connection, + software: proxy, + }; Router::new() .route("/products", get(products)) - .route("/products/:id/select", put(select_product)) + .route("/config", put(set_config).get(get_config)) .with_state(state) } @@ -66,7 +88,6 @@ async fn products<'a>( State(state): State>, ) -> Result>, SoftwareError> { let products = state.software.available_products().await?; - let selected_product = state.software.selected_product().await?; let products = products .into_iter() .map(|(id, name, data)| { @@ -74,13 +95,11 @@ async fn products<'a>( .get("description") .and_then(|d| d.downcast_ref::()) .unwrap_or(""); - let selected = selected_product == id; Product { id, name, description: description.to_string(), - selected, } }) .collect(); @@ -88,14 +107,26 @@ async fn products<'a>( Ok(Json(products)) } -/// Selects a product. +/// Sets the software configuration. /// /// * `state`: service state. -/// * `id`: product ID. -async fn select_product<'a>( +/// * `config`: software configuration. +async fn set_config<'a>( State(state): State>, - Path(id): Path, + Json(config): Json, ) -> Result<(), SoftwareError> { - state.software.select_product(&id).await?; + if let Some(product) = config.product { + state.software.select_product(&product).await?; + } Ok(()) } + +/// Returns the software configuration +/// +/// * `state` : service state. +async fn get_config<'a>( + State(state): State>, +) -> Result, SoftwareError> { + let config = SoftwareConfig::from_dbus(&state.connection).await?; + Ok(Json(config)) +} From 2b5be300b7296b5902ed760196db62a635a622e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Fri, 1 Mar 2024 12:02:19 +0000 Subject: [PATCH 32/53] rust: share the SoftwareProductProxy --- rust/agama-server/src/software/web.rs | 29 +++++++++------------------ 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index ec792fd752..9ef7c35ec8 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -18,8 +18,7 @@ use tokio_stream::StreamExt; #[derive(Clone)] struct SoftwareState<'a> { - software: SoftwareProductProxy<'a>, - connection: zbus::Connection, + product: SoftwareProductProxy<'a>, } #[derive(Clone, Serialize, Deserialize)] @@ -28,17 +27,6 @@ struct SoftwareConfig { product: Option, } -impl SoftwareConfig { - pub async fn from_dbus(connection: &zbus::Connection) -> Result { - let software = SoftwareProductProxy::new(&connection).await?; - let product = software.selected_product().await?; - Ok(SoftwareConfig { - patterns: Some(vec![]), - product: Some(product), - }) - } -} - #[derive(Error, Debug)] pub enum SoftwareError { #[error("Service error: {0}")] @@ -71,10 +59,7 @@ pub async fn software_monitor(events: EventsSender) { pub async fn software_service(_events: EventsSender) -> Router { let connection = connection().await.unwrap(); let proxy = SoftwareProductProxy::new(&connection).await.unwrap(); - let state = SoftwareState { - connection, - software: proxy, - }; + let state = SoftwareState { product: proxy }; Router::new() .route("/products", get(products)) .route("/config", put(set_config).get(get_config)) @@ -87,7 +72,7 @@ pub async fn software_service(_events: EventsSender) -> Router { async fn products<'a>( State(state): State>, ) -> Result>, SoftwareError> { - let products = state.software.available_products().await?; + let products = state.product.available_products().await?; let products = products .into_iter() .map(|(id, name, data)| { @@ -116,7 +101,7 @@ async fn set_config<'a>( Json(config): Json, ) -> Result<(), SoftwareError> { if let Some(product) = config.product { - state.software.select_product(&product).await?; + state.product.select_product(&product).await?; } Ok(()) } @@ -127,6 +112,10 @@ async fn set_config<'a>( async fn get_config<'a>( State(state): State>, ) -> Result, SoftwareError> { - let config = SoftwareConfig::from_dbus(&state.connection).await?; + let product = state.product.selected_product().await?; + let config = SoftwareConfig { + patterns: Some(vec![]), + product: Some(product), + }; Ok(Json(config)) } From 5edea12a7a3c3b0e2d4ff2273aa6cafbefe8e7eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Fri, 1 Mar 2024 12:21:53 +0000 Subject: [PATCH 33/53] rust: use the software client in the web API --- rust/agama-lib/src/product/client.rs | 1 + rust/agama-server/src/software/web.rs | 37 ++++++++++----------------- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index b7b848ac32..ba7934419e 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -19,6 +19,7 @@ pub struct Product { } /// D-Bus client for the software service +#[derive(Clone)] pub struct ProductClient<'a> { product_proxy: SoftwareProductProxy<'a>, registration_proxy: RegistrationProxy<'a>, diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 9ef7c35ec8..f98522113b 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -3,7 +3,12 @@ //! It is a wrapper around the YaST D-Bus API. use crate::web::{Event, EventsSender}; -use agama_lib::{connection, product::Product, software::proxies::SoftwareProductProxy}; +use agama_lib::{ + connection, + error::ServiceError, + product::{Product, ProductClient}, + software::proxies::SoftwareProductProxy, +}; use axum::{ extract::State, http::StatusCode, @@ -18,7 +23,7 @@ use tokio_stream::StreamExt; #[derive(Clone)] struct SoftwareState<'a> { - product: SoftwareProductProxy<'a>, + client: ProductClient<'a>, } #[derive(Clone, Serialize, Deserialize)] @@ -30,7 +35,7 @@ struct SoftwareConfig { #[derive(Error, Debug)] pub enum SoftwareError { #[error("Service error: {0}")] - Error(#[from] zbus::Error), + Error(#[from] ServiceError), } impl IntoResponse for SoftwareError { @@ -58,8 +63,8 @@ pub async fn software_monitor(events: EventsSender) { /// * `events`: channel to send the events to the main service. pub async fn software_service(_events: EventsSender) -> Router { let connection = connection().await.unwrap(); - let proxy = SoftwareProductProxy::new(&connection).await.unwrap(); - let state = SoftwareState { product: proxy }; + let client = ProductClient::new(connection).await.unwrap(); + let state = SoftwareState { client }; Router::new() .route("/products", get(products)) .route("/config", put(set_config).get(get_config)) @@ -72,23 +77,7 @@ pub async fn software_service(_events: EventsSender) -> Router { async fn products<'a>( State(state): State>, ) -> Result>, SoftwareError> { - let products = state.product.available_products().await?; - let products = products - .into_iter() - .map(|(id, name, data)| { - let description = data - .get("description") - .and_then(|d| d.downcast_ref::()) - .unwrap_or(""); - - Product { - id, - name, - description: description.to_string(), - } - }) - .collect(); - + let products = state.client.products().await?; Ok(Json(products)) } @@ -101,7 +90,7 @@ async fn set_config<'a>( Json(config): Json, ) -> Result<(), SoftwareError> { if let Some(product) = config.product { - state.product.select_product(&product).await?; + state.client.select_product(&product).await?; } Ok(()) } @@ -112,7 +101,7 @@ async fn set_config<'a>( async fn get_config<'a>( State(state): State>, ) -> Result, SoftwareError> { - let product = state.product.selected_product().await?; + let product = state.client.product().await?; let config = SoftwareConfig { patterns: Some(vec![]), product: Some(product), From 9c65f8566b97b1a9178ead2bb09adfbc9cccb76a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Fri, 1 Mar 2024 14:46:22 +0000 Subject: [PATCH 34/53] rust: add patterns support to the HTTP API --- rust/agama-lib/src/software.rs | 2 +- rust/agama-lib/src/software/client.rs | 35 ++++++++++++- rust/agama-server/src/software/web.rs | 71 ++++++++++++++++++++++++--- 3 files changed, 97 insertions(+), 11 deletions(-) diff --git a/rust/agama-lib/src/software.rs b/rust/agama-lib/src/software.rs index 53f2d6bf51..ccdc1fce18 100644 --- a/rust/agama-lib/src/software.rs +++ b/rust/agama-lib/src/software.rs @@ -5,6 +5,6 @@ pub mod proxies; mod settings; mod store; -pub use client::SoftwareClient; +pub use client::{Pattern, SelectionReason, SoftwareClient}; pub use settings::SoftwareSettings; pub use store::SoftwareStore; diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index 0670467b02..d3a49d4196 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -1,6 +1,7 @@ use super::proxies::Software1Proxy; use crate::error::ServiceError; use serde::Serialize; +use std::collections::HashMap; use zbus::Connection; /// Represents a software product @@ -20,7 +21,26 @@ pub struct Pattern { pub order: String, } +/// Represents the reason why a pattern is selected. +#[derive(Clone, Copy)] +pub enum SelectionReason { + /// The pattern was selected by the user. + User = 0, + /// The pattern was selected automatically. + Auto = 1, +} + +impl From for SelectionReason { + fn from(value: u8) -> Self { + match value { + 0 => Self::User, + _ => Self::Auto, + } + } +} + /// D-Bus client for the software service +#[derive(Clone)] pub struct SoftwareClient<'a> { software_proxy: Software1Proxy<'a>, } @@ -55,18 +75,29 @@ impl<'a> SoftwareClient<'a> { /// Returns the ids of patterns selected by user pub async fn user_selected_patterns(&self) -> Result, ServiceError> { - const USER_SELECTED: u8 = 0; let patterns: Vec = self .software_proxy .selected_patterns() .await? .into_iter() - .filter(|(_id, reason)| *reason == USER_SELECTED) + .filter(|(_id, reason)| *reason == SelectionReason::User as u8) .map(|(id, _reason)| id) .collect(); Ok(patterns) } + /// Returns the selected pattern and the reason each one selected. + pub async fn selected_patterns( + &self, + ) -> Result, ServiceError> { + let patterns = self.software_proxy.selected_patterns().await?; + let patterns = patterns + .into_iter() + .map(|(id, reason)| (id, reason.into())) + .collect(); + Ok(patterns) + } + /// Selects patterns by user pub async fn select_patterns(&self, patterns: &[String]) -> Result<(), ServiceError> { let patterns: Vec<&str> = patterns.iter().map(AsRef::as_ref).collect(); diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index f98522113b..66a14a2055 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -7,7 +7,7 @@ use agama_lib::{ connection, error::ServiceError, product::{Product, ProductClient}, - software::proxies::SoftwareProductProxy, + software::{proxies::SoftwareProductProxy, Pattern, SelectionReason, SoftwareClient}, }; use axum::{ extract::State, @@ -23,7 +23,8 @@ use tokio_stream::StreamExt; #[derive(Clone)] struct SoftwareState<'a> { - client: ProductClient<'a>, + product: ProductClient<'a>, + software: SoftwareClient<'a>, } #[derive(Clone, Serialize, Deserialize)] @@ -63,10 +64,12 @@ pub async fn software_monitor(events: EventsSender) { /// * `events`: channel to send the events to the main service. pub async fn software_service(_events: EventsSender) -> Router { let connection = connection().await.unwrap(); - let client = ProductClient::new(connection).await.unwrap(); - let state = SoftwareState { client }; + let product = ProductClient::new(connection.clone()).await.unwrap(); + let software = SoftwareClient::new(connection).await.unwrap(); + let state = SoftwareState { product, software }; Router::new() .route("/products", get(products)) + .route("/patterns", get(patterns)) .route("/config", put(set_config).get(get_config)) .with_state(state) } @@ -77,10 +80,56 @@ pub async fn software_service(_events: EventsSender) -> Router { async fn products<'a>( State(state): State>, ) -> Result>, SoftwareError> { - let products = state.client.products().await?; + let products = state.product.products().await?; Ok(Json(products)) } +/// Represents a pattern. +/// +/// It augments the information coming from the D-Bus client. +#[derive(Serialize)] +pub struct PatternItem { + #[serde(flatten)] + pattern: Pattern, + status: PatternStatus, +} + +/// Pattern status. +#[derive(Serialize, Clone, Copy)] +enum PatternStatus { + Available, + UserSelected, + AutoSelected, +} + +impl From for PatternStatus { + fn from(value: SelectionReason) -> Self { + match value { + SelectionReason::User => Self::UserSelected, + SelectionReason::Auto => Self::AutoSelected, + } + } +} + +async fn patterns<'a>( + State(state): State>, +) -> Result>, SoftwareError> { + let patterns = state.software.patterns(true).await?; + let selected = state.software.selected_patterns().await?; + let items = patterns + .into_iter() + .map(|pattern| { + let status: PatternStatus = selected + .get(&pattern.id) + .map(|r| (*r).into()) + .unwrap_or(PatternStatus::Available); + PatternItem { pattern, status } + }) + .collect(); + + Ok(Json(items)) +} + /// Sets the software configuration. /// /// * `state`: service state. @@ -90,8 +139,13 @@ async fn set_config<'a>( Json(config): Json, ) -> Result<(), SoftwareError> { if let Some(product) = config.product { - state.client.select_product(&product).await?; + state.product.select_product(&product).await?; + } + + if let Some(patterns) = config.patterns { + state.software.select_patterns(&patterns).await?; } + Ok(()) } @@ -101,9 +155,10 @@ async fn set_config<'a>( async fn get_config<'a>( State(state): State>, ) -> Result, SoftwareError> { - let product = state.client.product().await?; + let product = state.product.product().await?; + let patterns = state.software.user_selected_patterns().await?; let config = SoftwareConfig { - patterns: Some(vec![]), + patterns: Some(patterns), product: Some(product), }; Ok(Json(config)) From 0cbb4367558d697c95e411617b72712b8da80b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Fri, 1 Mar 2024 17:01:46 +0000 Subject: [PATCH 35/53] rust: emit patterns selection changes --- rust/agama-server/src/software/web.rs | 23 ++++++++++++++++++++--- rust/agama-server/src/web.rs | 4 ++-- rust/agama-server/src/web/event.rs | 1 + 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 66a14a2055..3c680a5492 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -7,7 +7,10 @@ use agama_lib::{ connection, error::ServiceError, product::{Product, ProductClient}, - software::{proxies::SoftwareProductProxy, Pattern, SelectionReason, SoftwareClient}, + software::{ + proxies::{Software1Proxy, SoftwareProductProxy}, + Pattern, SelectionReason, SoftwareClient, + }, }; use axum::{ extract::State, @@ -48,8 +51,12 @@ impl IntoResponse for SoftwareError { } } -pub async fn software_monitor(events: EventsSender) { - let connection = connection().await.unwrap(); +pub async fn software_monitor(connection: zbus::Connection, events: EventsSender) { + tokio::spawn(monitor_product_changed(connection.clone(), events.clone())); + tokio::spawn(monitor_patterns_changed(connection.clone(), events.clone())); +} + +async fn monitor_product_changed(connection: zbus::Connection, events: EventsSender) { let proxy = SoftwareProductProxy::new(&connection).await.unwrap(); let mut stream = proxy.receive_selected_product_changed().await; while let Some(change) = stream.next().await { @@ -59,6 +66,16 @@ pub async fn software_monitor(events: EventsSender) { } } +async fn monitor_patterns_changed(connection: zbus::Connection, events: EventsSender) { + let proxy = Software1Proxy::new(&connection).await.unwrap(); + let mut stream = proxy.receive_selected_patterns_changed().await; + while let Some(change) = stream.next().await { + if let Ok(patterns) = change.get().await { + _ = events.send(Event::PatternsChanged); + } + } +} + /// Sets up and returns the axum service for the software module. /// /// * `events`: channel to send the events to the main service. diff --git a/rust/agama-server/src/web.rs b/rust/agama-server/src/web.rs index 5940a2336a..4f52e2a3aa 100644 --- a/rust/agama-server/src/web.rs +++ b/rust/agama-server/src/web.rs @@ -46,12 +46,12 @@ pub async fn service(config: ServiceConfig, events: EventsSender) -> Router { pub async fn run_monitor(events: EventsSender) -> Result<(), ServiceError> { let presenter = EventsProgressPresenter::new(events.clone()); let connection = connection().await?; - let mut monitor = ProgressMonitor::new(connection).await?; + let mut monitor = ProgressMonitor::new(connection.clone()).await?; tokio::spawn(async move { if let Err(error) = monitor.run(presenter).await { eprintln!("Could not monitor the D-Bus server: {}", error); } }); - tokio::spawn(async move { software_monitor(events.clone()).await }); + software_monitor(connection, events.clone()).await; Ok(()) } diff --git a/rust/agama-server/src/web/event.rs b/rust/agama-server/src/web/event.rs index 409adec0d0..d810007c82 100644 --- a/rust/agama-server/src/web/event.rs +++ b/rust/agama-server/src/web/event.rs @@ -8,6 +8,7 @@ pub enum Event { LocaleChanged { locale: String }, Progress(Progress), ProductChanged { id: String }, + PatternsChanged, } pub type EventsSender = Sender; From 35ffb0e6cbaed9124f5f59a438a01f5873a51d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Sat, 2 Mar 2024 10:09:33 +0000 Subject: [PATCH 36/53] rust: emit stream events in a single place --- rust/agama-server/src/software.rs | 2 +- rust/agama-server/src/software/web.rs | 46 ++++++++++++++++----------- rust/agama-server/src/web.rs | 19 +++++++++-- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/rust/agama-server/src/software.rs b/rust/agama-server/src/software.rs index 9f234e6cff..b882542d90 100644 --- a/rust/agama-server/src/software.rs +++ b/rust/agama-server/src/software.rs @@ -1,2 +1,2 @@ pub mod web; -pub use web::{software_monitor, software_service}; +pub use web::{software_service, software_stream}; diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 3c680a5492..3168a5927c 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -22,7 +22,7 @@ use axum::{ use serde::{Deserialize, Serialize}; use serde_json::json; use thiserror::Error; -use tokio_stream::StreamExt; +use tokio_stream::{Stream, StreamExt}; #[derive(Clone)] struct SoftwareState<'a> { @@ -51,29 +51,39 @@ impl IntoResponse for SoftwareError { } } -pub async fn software_monitor(connection: zbus::Connection, events: EventsSender) { - tokio::spawn(monitor_product_changed(connection.clone(), events.clone())); - tokio::spawn(monitor_patterns_changed(connection.clone(), events.clone())); +pub async fn software_stream(connection: zbus::Connection) -> impl Stream { + StreamExt::merge( + product_changed_stream(connection.clone()).await, + patterns_changed_stream(connection.clone()).await, + ) } -async fn monitor_product_changed(connection: zbus::Connection, events: EventsSender) { +async fn product_changed_stream(connection: zbus::Connection) -> impl Stream { let proxy = SoftwareProductProxy::new(&connection).await.unwrap(); - let mut stream = proxy.receive_selected_product_changed().await; - while let Some(change) = stream.next().await { - if let Ok(id) = change.get().await { - _ = events.send(Event::ProductChanged { id }); - } - } + proxy + .receive_selected_product_changed() + .await + .then(|change| async move { + if let Ok(id) = change.get().await { + return Some(Event::ProductChanged { id }); + } + None + }) + .filter_map(|e| e) } -async fn monitor_patterns_changed(connection: zbus::Connection, events: EventsSender) { +async fn patterns_changed_stream(connection: zbus::Connection) -> impl Stream { let proxy = Software1Proxy::new(&connection).await.unwrap(); - let mut stream = proxy.receive_selected_patterns_changed().await; - while let Some(change) = stream.next().await { - if let Ok(patterns) = change.get().await { - _ = events.send(Event::PatternsChanged); - } - } + proxy + .receive_selected_patterns_changed() + .await + .then(|change| async move { + if let Ok(_pattens) = change.get().await { + return Some(Event::PatternsChanged); + } + None + }) + .filter_map(|e| e) } /// Sets up and returns the axum service for the software module. diff --git a/rust/agama-server/src/web.rs b/rust/agama-server/src/web.rs index 4f52e2a3aa..1b2da2e713 100644 --- a/rust/agama-server/src/web.rs +++ b/rust/agama-server/src/web.rs @@ -6,7 +6,7 @@ use self::progress::EventsProgressPresenter; use crate::l10n::web::l10n_service; -use crate::software::web::{software_monitor, software_service}; +use crate::software::web::{software_service, software_stream}; use axum::Router; mod auth; @@ -25,6 +25,7 @@ pub use config::ServiceConfig; pub use docs::ApiDoc; pub use event::{Event, EventsReceiver, EventsSender}; pub use service::MainServiceBuilder; +use tokio_stream::StreamExt; /// Returns a service that implements the web-based Agama API. /// @@ -52,6 +53,20 @@ pub async fn run_monitor(events: EventsSender) -> Result<(), ServiceError> { eprintln!("Could not monitor the D-Bus server: {}", error); } }); - software_monitor(connection, events.clone()).await; + tokio::spawn(run_events_monitor(connection, events.clone())); + Ok(()) } + +/// Emits the events from the system streams through the events channel. +/// +/// * `connection`: D-Bus connection. +/// * `events`: channel to send the events to. +pub async fn run_events_monitor(connection: zbus::Connection, events: EventsSender) { + let stream = software_stream(connection).await; + tokio::pin!(stream); + let e = events.clone(); + while let Some(event) = stream.next().await { + _ = e.send(event); + } +} From 4f209f601bddc14216b85f5c3c408e50ccad4e89 Mon Sep 17 00:00:00 2001 From: YaST Bot Date: Sun, 3 Mar 2024 02:43:51 +0000 Subject: [PATCH 37/53] Update web PO files Agama-weblate commit: a787199033d6c1cd1ffb1b9d9fe19fdec544ee5c --- web/po/cs.po | 169 +++++----- web/po/de.po | 738 ++++++++++++++++++++++-------------------- web/po/es.po | 258 ++++++++------- web/po/fr.po | 181 ++++++----- web/po/id.po | 181 ++++++----- web/po/ja.po | 198 +++++++----- web/po/ka.po | 171 +++++----- web/po/mk.po | 170 +++++----- web/po/nl.po | 172 +++++----- web/po/pt_BR.po | 172 +++++----- web/po/ru.po | 170 +++++----- web/po/sv.po | 207 +++++++----- web/po/uk.po | 169 +++++----- web/src/manifest.json | 3 +- 14 files changed, 1678 insertions(+), 1281 deletions(-) diff --git a/web/po/cs.po b/web/po/cs.po index 4257f9c802..8b89a6254c 100644 --- a/web/po/cs.po +++ b/web/po/cs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" "PO-Revision-Date: 2023-12-31 20:39+0000\n" "Last-Translator: Ladislav Slezák \n" "Language-Team: Czech TPM can verify the integrity of the " @@ -1266,27 +1266,53 @@ msgid "" "first run." msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +msgid "Use Btrfs Snapshots" +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:239 msgid "Change encryption settings" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "" +#: src/components/storage/ProposalSettingsSection.jsx:330 +msgid "Transactional system" +msgstr "" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "" @@ -1330,7 +1356,7 @@ msgstr "" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "" @@ -1478,9 +1504,6 @@ msgstr "" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "" @@ -1494,8 +1517,8 @@ msgid "Edit file system" msgstr "" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "" @@ -1507,77 +1530,70 @@ msgstr "" msgid "Select a value" msgstr "" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "" -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" msgstr "" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr "" #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "" #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr "" #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "" -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "" #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1585,57 +1601,57 @@ msgid "" msgstr "" #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "" @@ -1958,82 +1974,91 @@ msgstr "" msgid "Targets" msgstr "" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." msgstr "" -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." msgstr "" #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "" diff --git a/web/po/de.po b/web/po/de.po index 077d1dc8fc..c3b1bb863f 100644 --- a/web/po/de.po +++ b/web/po/de.po @@ -7,9 +7,9 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" -"PO-Revision-Date: 2023-12-31 20:39+0000\n" -"Last-Translator: anonymous \n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" +"PO-Revision-Date: 2024-03-01 23:42+0000\n" +"Last-Translator: Ettore Atalan \n" "Language-Team: German \n" "Language: de\n" @@ -23,7 +23,7 @@ msgstr "" #: src/DevServerWrapper.jsx:82 #, c-format msgid "The server at %s is not reachable." -msgstr "" +msgstr "Der Server unter %s ist nicht erreichbar." #. TRANSLATORS: error message #: src/DevServerWrapper.jsx:88 @@ -33,18 +33,18 @@ msgstr "" #. TRANSLATORS: button label #: src/DevServerWrapper.jsx:104 msgid "Try Again" -msgstr "" +msgstr "Erneut versuchen" #: src/components/core/About.jsx:43 src/components/core/About.jsx:48 msgid "About Agama" -msgstr "" +msgstr "Über Agama" #. TRANSLATORS: content of the "About" popup (1/2) #: src/components/core/About.jsx:53 msgid "" -"Agama is an experimental installer for (open)SUSE systems. It still under " +"Agama is an experimental installer for (open)SUSE systems. It is still under " "development so, please, do not use it in production environments. If you " -"want to give it a try, we recommend to use a virtual machine to prevent any " +"want to give it a try, we recommend using a virtual machine to prevent any " "possible data loss." msgstr "" @@ -62,12 +62,12 @@ msgstr "" #: src/components/network/WifiSelector.jsx:151 #: src/components/product/ProductPage.jsx:239 msgid "Close" -msgstr "" +msgstr "Schließen" #. TRANSLATORS: page title #: src/components/core/DBusError.jsx:34 msgid "D-Bus Error" -msgstr "" +msgstr "D-Bus-Fehler" #: src/components/core/DBusError.jsx:38 msgid "Cannot connect to D-Bus" @@ -81,19 +81,19 @@ msgstr "" #. TRANSLATORS: button label #: src/components/core/DBusError.jsx:51 msgid "Reload" -msgstr "" +msgstr "Neu laden" #: src/components/core/DevelopmentInfo.jsx:55 msgid "Cockpit server" -msgstr "" +msgstr "Cockpit-Server" #: src/components/core/FileViewer.jsx:65 msgid "Reading file..." -msgstr "" +msgstr "Datei wird gelesen ..." #: src/components/core/FileViewer.jsx:71 msgid "Cannot read the file" -msgstr "" +msgstr "Die Datei kann nicht gelesen werden" #: src/components/core/InstallButton.jsx:37 msgid "" @@ -103,7 +103,7 @@ msgstr "" #: src/components/core/InstallButton.jsx:49 msgid "Confirm Installation" -msgstr "" +msgstr "Installation bestätigen" #: src/components/core/InstallButton.jsx:55 msgid "" @@ -119,16 +119,17 @@ msgstr "" #: src/components/core/InstallButton.jsx:65 src/components/core/Popup.jsx:128 #: src/components/network/WifiConnectionForm.jsx:136 msgid "Cancel" -msgstr "" +msgstr "Abbrechen" #. TRANSLATORS: button label #: src/components/core/InstallButton.jsx:69 msgid "Continue" -msgstr "" +msgstr "Fortsetzen" #: src/components/core/InstallButton.jsx:78 +#, fuzzy msgid "Problems Found" -msgstr "" +msgstr "Gefundene Probleme" #: src/components/core/InstallButton.jsx:82 msgid "" @@ -144,17 +145,17 @@ msgstr "" #: src/components/product/ProductPage.jsx:207 #: src/components/storage/ProposalDeviceSection.jsx:169 #: src/components/storage/ProposalDeviceSection.jsx:364 -#: src/components/storage/ProposalSettingsSection.jsx:211 +#: src/components/storage/ProposalSettingsSection.jsx:275 #: src/components/storage/ProposalVolumes.jsx:148 #: src/components/storage/ProposalVolumes.jsx:283 #: src/components/storage/ZFCPPage.jsx:511 msgid "Accept" -msgstr "" +msgstr "Annehmen" #. TRANSLATORS: button label #: src/components/core/InstallButton.jsx:140 msgid "Install" -msgstr "" +msgstr "Installieren" #: src/components/core/InstallationFinished.jsx:41 msgid "TPM sealing requires the new system to be booted directly." @@ -168,11 +169,11 @@ msgstr "" #: src/components/core/InstallationFinished.jsx:50 msgid "Hide details" -msgstr "" +msgstr "Details ausblenden" #: src/components/core/InstallationFinished.jsx:50 msgid "See more details" -msgstr "" +msgstr "Siehe weitere Details" #. TRANSLATORS: Do not translate 'abbr' and 'title', they are part of the HTML markup #: src/components/core/InstallationFinished.jsx:55 @@ -186,23 +187,25 @@ msgstr "" #. TRANSLATORS: page title #: src/components/core/InstallationFinished.jsx:88 msgid "Installation Finished" -msgstr "" +msgstr "Installation abgeschlossen" #: src/components/core/InstallationFinished.jsx:91 msgid "Congratulations!" -msgstr "" +msgstr "Gratulation!" #: src/components/core/InstallationFinished.jsx:96 msgid "The installation on your machine is complete." -msgstr "" +msgstr "Die Installation auf Ihrem Rechner ist abgeschlossen." #: src/components/core/InstallationFinished.jsx:100 msgid "At this point you can power off the machine." -msgstr "" +msgstr "Nun können Sie den Rechner ausschalten." #: src/components/core/InstallationFinished.jsx:101 msgid "At this point you can reboot the machine to log in to the new system." msgstr "" +"Nun können Sie den Rechner neu starten, um sich bei dem neuen System " +"anzumelden." #: src/components/core/InstallationFinished.jsx:113 msgid "Finish" @@ -221,15 +224,15 @@ msgstr "" #: src/components/software/PatternSelector.jsx:215 #: src/components/software/PatternSelector.jsx:216 msgid "Search" -msgstr "" +msgstr "Suchen" #: src/components/core/LogsButton.jsx:98 msgid "Collecting logs..." -msgstr "" +msgstr "Protokolle werden gesammelt ..." #: src/components/core/LogsButton.jsx:98 msgid "Download logs" -msgstr "" +msgstr "Protokolle herunterladen" #: src/components/core/LogsButton.jsx:106 msgid "" @@ -243,11 +246,11 @@ msgstr "" #: src/components/core/Page.jsx:93 src/components/users/UsersPage.jsx:30 msgid "Back" -msgstr "" +msgstr "Zurück" #: src/components/core/Page.jsx:201 msgid "Show global options" -msgstr "" +msgstr "Globale Optionen anzeigen" #: src/components/core/Page.jsx:215 msgid "Page Actions" @@ -255,7 +258,7 @@ msgstr "" #: src/components/core/PasswordAndConfirmationInput.jsx:35 msgid "Passwords do not match" -msgstr "" +msgstr "Passwörter stimmen nicht überein" #: src/components/core/PasswordAndConfirmationInput.jsx:56 #: src/components/network/WifiConnectionForm.jsx:125 @@ -263,19 +266,19 @@ msgstr "" #: src/components/storage/iscsi/AuthFields.jsx:100 #: src/components/users/RootAuthMethods.jsx:163 msgid "Password" -msgstr "" +msgstr "Passwort" #: src/components/core/PasswordAndConfirmationInput.jsx:60 msgid "User password" -msgstr "" +msgstr "Benutzerpasswort" #: src/components/core/PasswordAndConfirmationInput.jsx:69 msgid "Password confirmation" -msgstr "" +msgstr "Passwort bestätigen" #: src/components/core/PasswordAndConfirmationInput.jsx:74 msgid "User password confirmation" -msgstr "" +msgstr "Benutzerpasswort bestätigen" #: src/components/core/PasswordInput.jsx:59 msgid "Password visibility button" @@ -283,14 +286,14 @@ msgstr "" #: src/components/core/Popup.jsx:90 msgid "Confirm" -msgstr "" +msgstr "Bestätigen" #. TRANSLATORS: dropdown label #: src/components/core/RowActions.jsx:66 #: src/components/storage/ProposalVolumes.jsx:119 #: src/components/storage/ProposalVolumes.jsx:310 msgid "Actions" -msgstr "" +msgstr "Aktionen" #: src/components/core/SectionSkeleton.jsx:29 msgid "Waiting" @@ -299,66 +302,67 @@ msgstr "" #. TRANSLATORS: button label #: src/components/core/ShowLogButton.jsx:47 msgid "Show Logs" -msgstr "" +msgstr "Protokolle anzeigen" #. TRANSLATORS: popup dialog title #: src/components/core/ShowLogButton.jsx:53 msgid "YaST Logs" -msgstr "" +msgstr "YaST-Protokolle" #. TRANSLATORS: button label #: src/components/core/ShowTerminalButton.jsx:48 msgid "Open Terminal" -msgstr "" +msgstr "Terminal öffnen" #. TRANSLATORS: sidebar header #: src/components/core/Sidebar.jsx:113 src/components/core/Sidebar.jsx:121 msgid "Installer Options" -msgstr "" +msgstr "Installationsprogrammoptionen" #: src/components/core/Sidebar.jsx:128 msgid "Hide installer options" -msgstr "" +msgstr "Installationsprogrammoptionen ausblenden" #: src/components/core/Sidebar.jsx:136 msgid "Diagnostic tools" -msgstr "" +msgstr "Diagnosewerkzeuge" #. TRANSLATORS: Titles used for the popup displaying found section issues #: src/components/core/ValidationErrors.jsx:53 msgid "Software issues" -msgstr "" +msgstr "Softwareprobleme" #: src/components/core/ValidationErrors.jsx:54 msgid "Product issues" -msgstr "" +msgstr "Produktprobleme" #: src/components/core/ValidationErrors.jsx:55 msgid "Storage issues" -msgstr "" +msgstr "Speicherungsprobleme" #: src/components/core/ValidationErrors.jsx:57 +#, fuzzy msgid "Found Issues" -msgstr "" +msgstr "Gefundene Probleme" #. TRANSLATORS: %d is replaced with the number of errors found #: src/components/core/ValidationErrors.jsx:77 #, c-format msgid "%d error found" msgid_plural "%d errors found" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d Fehler gefunden" +msgstr[1] "%d Fehler gefunden" #. TRANSLATORS: label for keyboard layout selection #: src/components/l10n/InstallerKeymapSwitcher.jsx:53 #: src/components/l10n/L10nPage.jsx:357 msgid "Keyboard" -msgstr "" +msgstr "Tastatur" #. TRANSLATORS: label for keyboard layout selection #: src/components/l10n/InstallerKeymapSwitcher.jsx:61 msgid "keyboard" -msgstr "" +msgstr "Tastatur" #. TRANSLATORS: #: src/components/l10n/InstallerKeymapSwitcher.jsx:70 @@ -380,16 +384,16 @@ msgstr "" #: src/components/l10n/L10nPage.jsx:384 #: src/components/overview/L10nSection.jsx:52 msgid "Localization" -msgstr "" +msgstr "Lokalisierung" #: src/components/l10n/InstallerLocaleSwitcher.jsx:66 #: src/components/l10n/L10nPage.jsx:246 msgid "Language" -msgstr "" +msgstr "Sprache" #: src/components/l10n/InstallerLocaleSwitcher.jsx:74 msgid "language" -msgstr "" +msgstr "Sprache" #. TRANSLATORS: placeholder text for search input in the keyboard selector. #: src/components/l10n/KeymapSelector.jsx:53 @@ -402,58 +406,58 @@ msgstr "" #: src/components/l10n/L10nPage.jsx:66 src/components/l10n/L10nPage.jsx:140 msgid "Select time zone" -msgstr "" +msgstr "Zeitzone auswählen" #: src/components/l10n/L10nPage.jsx:67 #, c-format msgid "%s will use the selected time zone." -msgstr "" +msgstr "%s wird die ausgewählte Zeitzone verwenden." #: src/components/l10n/L10nPage.jsx:128 msgid "Time zone" -msgstr "" +msgstr "Zeitzone" #: src/components/l10n/L10nPage.jsx:134 msgid "Change time zone" -msgstr "" +msgstr "Zeitzone ändern" #: src/components/l10n/L10nPage.jsx:139 msgid "Time zone not selected yet" -msgstr "" +msgstr "Zeitzone ist noch nicht ausgewählt" #: src/components/l10n/L10nPage.jsx:182 src/components/l10n/L10nPage.jsx:258 msgid "Select language" -msgstr "" +msgstr "Sprache auswählen" #: src/components/l10n/L10nPage.jsx:183 #, c-format msgid "%s will use the selected language." -msgstr "" +msgstr "%s wird die ausgewählte Sprache verwenden." #: src/components/l10n/L10nPage.jsx:252 msgid "Change language" -msgstr "" +msgstr "Sprache ändern" #: src/components/l10n/L10nPage.jsx:257 msgid "Language not selected yet" -msgstr "" +msgstr "Sprache ist noch nicht ausgewählt" #: src/components/l10n/L10nPage.jsx:295 src/components/l10n/L10nPage.jsx:369 msgid "Select keyboard" -msgstr "" +msgstr "Tastatur auswählen" #: src/components/l10n/L10nPage.jsx:296 #, c-format msgid "%s will use the selected keyboard." -msgstr "" +msgstr "%s wird die ausgewählte Tastatur verwenden." #: src/components/l10n/L10nPage.jsx:363 msgid "Change keyboard" -msgstr "" +msgstr "Tastatur ändern" #: src/components/l10n/L10nPage.jsx:368 msgid "Keyboard not selected yet" -msgstr "" +msgstr "Tastatur ist noch nicht ausgewählt" #: src/components/l10n/LocaleSelector.jsx:53 msgid "Filter by language, territory or locale code" @@ -461,7 +465,7 @@ msgstr "" #: src/components/l10n/LocaleSelector.jsx:64 msgid "Available locales" -msgstr "" +msgstr "Verfügbare Sprachumgebungen" #. TRANSLATORS: placeholder text for search input in the timezone selector. #: src/components/l10n/TimezoneSelector.jsx:75 @@ -470,47 +474,47 @@ msgstr "" #: src/components/l10n/TimezoneSelector.jsx:86 msgid "Available time zones" -msgstr "" +msgstr "Verfügbare Zeitzonen" #: src/components/layout/Loading.jsx:30 msgid "Loading installation environment, please wait." -msgstr "" +msgstr "Installationsumgebung wird geladen, bitte warten." #. TRANSLATORS: button label #: src/components/network/AddressesDataList.jsx:81 #: src/components/network/DnsDataList.jsx:87 msgid "Remove" -msgstr "" +msgstr "Entfernen" #. TRANSLATORS: input field name #: src/components/network/AddressesDataList.jsx:93 #: src/components/network/AddressesDataList.jsx:94 #: src/components/network/IpAddressInput.jsx:33 msgid "IP Address" -msgstr "" +msgstr "IP-Adresse" #. TRANSLATORS: input field name #: src/components/network/AddressesDataList.jsx:102 #: src/components/network/AddressesDataList.jsx:103 msgid "Prefix length or netmask" -msgstr "" +msgstr "Präfixlänge oder Netzmaske" #: src/components/network/AddressesDataList.jsx:119 msgid "Add an address" -msgstr "" +msgstr "Adresse hinzufügen" #. TRANSLATORS: button label #: src/components/network/AddressesDataList.jsx:119 msgid "Add another address" -msgstr "" +msgstr "Weitere Adresse hinzufügen" #: src/components/network/AddressesDataList.jsx:124 msgid "Addresses" -msgstr "" +msgstr "Adressen" #: src/components/network/AddressesDataList.jsx:129 msgid "Addresses data list" -msgstr "" +msgstr "Adressdatenliste" #. TRANSLATORS: input field for the iSCSI initiator name #. TRANSLATORS: table header @@ -523,67 +527,67 @@ msgstr "" #: src/components/storage/iscsi/NodesPresenter.jsx:100 #: src/components/storage/iscsi/NodesPresenter.jsx:121 msgid "Name" -msgstr "" +msgstr "Name" #. TRANSLATORS: table header #: src/components/network/ConnectionsTable.jsx:59 #: src/components/network/ConnectionsTable.jsx:87 msgid "IP addresses" -msgstr "" +msgstr "IP-Adressen" #: src/components/network/ConnectionsTable.jsx:67 #: src/components/storage/ProposalVolumes.jsx:234 #: src/components/storage/iscsi/InitiatorPresenter.jsx:49 #: src/components/storage/iscsi/NodesPresenter.jsx:73 -#: src/components/users/FirstUser.jsx:174 +#: src/components/users/FirstUser.jsx:208 msgid "Edit" -msgstr "" +msgstr "Bearbeiten" #. TRANSLATORS: %s is replaced by a network connection name #: src/components/network/ConnectionsTable.jsx:70 #, c-format msgid "Edit connection %s" -msgstr "" +msgstr "Verbindung %s bearbeiten" #: src/components/network/ConnectionsTable.jsx:74 msgid "Forget" -msgstr "" +msgstr "Vergessen" #. TRANSLATORS: %s is replaced by a network connection name #: src/components/network/ConnectionsTable.jsx:77 #, c-format msgid "Forget connection %s" -msgstr "" +msgstr "Verbindung %s vergessen" #. TRANSLATORS: %s is replaced by a network connection name #: src/components/network/ConnectionsTable.jsx:92 #, c-format msgid "Actions for connection %s" -msgstr "" +msgstr "Aktionen für Verbindung %s" #. TRANSLATORS: input field name #: src/components/network/DnsDataList.jsx:78 #: src/components/network/DnsDataList.jsx:79 msgid "Server IP" -msgstr "" +msgstr "Server-IP" #: src/components/network/DnsDataList.jsx:96 msgid "Add DNS" -msgstr "" +msgstr "DNS hinzufügen" #. TRANSLATORS: button label #: src/components/network/DnsDataList.jsx:96 msgid "Add another DNS" -msgstr "" +msgstr "Weiteren DNS hinzufügen" #: src/components/network/DnsDataList.jsx:101 msgid "DNS" -msgstr "" +msgstr "DNS" #. TRANSLATORS: input field name #: src/components/network/IpPrefixInput.jsx:33 msgid "IP prefix or netmask" -msgstr "" +msgstr "IP-Präfix oder Netzmaske" #. TRANSLATORS: error message #: src/components/network/IpSettingsForm.jsx:87 @@ -595,39 +599,42 @@ msgstr "" #: src/components/storage/iscsi/EditNodeForm.jsx:50 #, c-format msgid "Edit %s" -msgstr "" +msgstr "%s bearbeiten" #. TRANSLATORS: network connection mode (automatic via DHCP or manual with static IP) #: src/components/network/IpSettingsForm.jsx:136 #: src/components/network/IpSettingsForm.jsx:141 #: src/components/network/IpSettingsForm.jsx:143 msgid "Mode" -msgstr "" +msgstr "Modus" #: src/components/network/IpSettingsForm.jsx:147 msgid "Automatic (DHCP)" -msgstr "" +msgstr "Automatisch (DHCP)" #. TRANSLATORS: manual network configuration mode with a static IP address #: src/components/network/IpSettingsForm.jsx:149 #: src/components/storage/iscsi/NodeStartupOptions.js:25 msgid "Manual" -msgstr "" +msgstr "Manuell" #. TRANSLATORS: network gateway configuration #: src/components/network/IpSettingsForm.jsx:164 #: src/components/network/IpSettingsForm.jsx:167 msgid "Gateway" -msgstr "" +msgstr "Gateway" #: src/components/network/NetworkPage.jsx:38 msgid "No wired connections found." -msgstr "" +msgstr "Keine kabelgebundenen Verbindungen gefunden." #: src/components/network/NetworkPage.jsx:53 +#, fuzzy msgid "" "The system has not been configured for connecting to a WiFi network yet." msgstr "" +"Das System wurde noch nicht für die Verbindung mit einem WiFi-Netzwerk " +"konfiguriert." #: src/components/network/NetworkPage.jsx:54 msgid "" @@ -636,43 +643,46 @@ msgid "" msgstr "" #: src/components/network/NetworkPage.jsx:58 +#, fuzzy msgid "No WiFi connections found." -msgstr "" +msgstr "Keine WiFi-Verbindungen gefunden." #. TRANSLATORS: button label #: src/components/network/NetworkPage.jsx:70 #: src/components/network/NetworkPageMenu.jsx:46 #: src/components/network/WifiSelector.jsx:134 +#, fuzzy msgid "Connect to a Wi-Fi network" -msgstr "" +msgstr "Mit einem Wi-Fi-Netzwerk verbinden" #. TRANSLATORS: page title #. TRANSLATORS: page section title #: src/components/network/NetworkPage.jsx:169 #: src/components/overview/NetworkSection.jsx:83 msgid "Network" -msgstr "" +msgstr "Netzwerk" #. TRANSLATORS: page section #: src/components/network/NetworkPage.jsx:171 msgid "Wired networks" -msgstr "" +msgstr "Kabelgebundene Netzwerke" #. TRANSLATORS: page section #: src/components/network/NetworkPage.jsx:176 +#, fuzzy msgid "WiFi networks" -msgstr "" +msgstr "WiFi-Netzwerke" #. TRANSLATORS: WiFi authentication mode #: src/components/network/WifiConnectionForm.jsx:43 #: src/components/storage/iscsi/InitiatorPresenter.jsx:72 msgid "None" -msgstr "" +msgstr "Kein" #. TRANSLATORS: WiFi authentication mode #: src/components/network/WifiConnectionForm.jsx:45 msgid "WPA & WPA2 Personal" -msgstr "" +msgstr "WPA & WPA2 Personal" #: src/components/network/WifiConnectionForm.jsx:91 #: src/components/product/ProductPage.jsx:128 @@ -680,9 +690,9 @@ msgstr "" #: src/components/storage/ZFCPDiskForm.jsx:112 #: src/components/storage/iscsi/DiscoverForm.jsx:108 #: src/components/storage/iscsi/LoginForm.jsx:72 -#: src/components/users/FirstUser.jsx:198 +#: src/components/users/FirstUser.jsx:238 msgid "Something went wrong" -msgstr "" +msgstr "Etwas ist schiefgelaufen" #: src/components/network/WifiConnectionForm.jsx:92 msgid "Please, review provided settings and try again." @@ -692,51 +702,51 @@ msgstr "" #: src/components/network/WifiConnectionForm.jsx:97 #: src/components/network/WifiConnectionForm.jsx:101 msgid "SSID" -msgstr "" +msgstr "SSID" #. TRANSLATORS: Wifi security configuration (password protected or not) #: src/components/network/WifiConnectionForm.jsx:109 #: src/components/network/WifiConnectionForm.jsx:112 msgid "Security" -msgstr "" +msgstr "Sicherheit" #. TRANSLATORS: WiFi password #: src/components/network/WifiConnectionForm.jsx:121 msgid "WPA Password" -msgstr "" +msgstr "WPA-Passwort" #. TRANSLATORS: button label, connect to a WiFi network #: src/components/network/WifiConnectionForm.jsx:133 msgid "Connect" -msgstr "" +msgstr "Verbinden" #. TRANSLATORS: button label #: src/components/network/WifiHiddenNetworkForm.jsx:50 msgid "Connect to hidden network" -msgstr "" +msgstr "Mit verborgenem Netzwerk verbinden" #. TRANSLATORS: Wifi network status #: src/components/network/WifiNetworkListItem.jsx:41 #: src/components/network/WifiNetworkListItem.jsx:99 msgid "Connecting" -msgstr "" +msgstr "Wird verbunden" #. TRANSLATORS: Wifi network status #: src/components/network/WifiNetworkListItem.jsx:44 msgid "Connected" -msgstr "" +msgstr "Verbunden" #. TRANSLATORS: Wifi network status #: src/components/network/WifiNetworkListItem.jsx:47 msgid "Disconnecting" -msgstr "" +msgstr "Wird getrennt" #. TRANSLATORS: iSCSI connection status #. TRANSLATORS: Wifi network status #: src/components/network/WifiNetworkListItem.jsx:50 #: src/components/storage/iscsi/NodesPresenter.jsx:63 msgid "Disconnected" -msgstr "" +msgstr "Getrennt" #. TRANSLATORS: %s is replaced by a WiFi network name #: src/components/network/WifiNetworkListItem.jsx:97 @@ -747,18 +757,18 @@ msgstr "" #. TRANSLATORS: menu label, remove the selected WiFi network settings #: src/components/network/WifiNetworkMenu.jsx:55 msgid "Forget network" -msgstr "" +msgstr "Netzwerk vergessen" #. TRANSLATORS: %s will be replaced by a language name and territory, example: #. "English (United States)". #: src/components/overview/L10nSection.jsx:34 #, c-format msgid "The system will use %s as its default language." -msgstr "" +msgstr "Das System wird %s als Standardsprache verwenden." #: src/components/overview/NetworkSection.jsx:59 msgid "No network connections detected" -msgstr "" +msgstr "Keine Netzwerkverbindungen erkannt" #. TRANSLATORS: header for the list of active network connections, #. %d is replaced by the number of active connections @@ -766,47 +776,47 @@ msgstr "" #, c-format msgid "%d connection set:" msgid_plural "%d connections set:" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d Verbindung festgelegt:" +msgstr[1] "%d Verbindungen festgelegt:" #. TRANSLATORS: page title #: src/components/overview/OverviewPage.jsx:48 msgid "Installation Summary" -msgstr "" +msgstr "Zusammenfassung der Installation" #. TRANSLATORS: %s is replaced by a product name (e.g., SUSE ALP-Dolomite) #: src/components/overview/ProductSection.jsx:48 #, c-format msgid "%s (registered)" -msgstr "" +msgstr "%s (registriert)" #. TRANSLATORS: page title #. TRANSLATORS: page section #: src/components/overview/ProductSection.jsx:71 #: src/components/product/ProductPage.jsx:435 msgid "Product" -msgstr "" +msgstr "Produkt" #: src/components/overview/SoftwareSection.jsx:38 msgid "Reading software repositories" -msgstr "" +msgstr "Software-Repositorien werden gelesen" #. TRANSLATORS: clickable link label #: src/components/overview/SoftwareSection.jsx:133 msgid "Refresh the repositories" -msgstr "" +msgstr "Repositorien auffrischen" #. TRANSLATORS: page title #. TRANSLATORS: page section #: src/components/overview/SoftwareSection.jsx:143 #: src/components/software/SoftwarePage.jsx:81 msgid "Software" -msgstr "" +msgstr "Software" #: src/components/overview/StorageSection.jsx:42 #: src/components/storage/ProposalDeviceSection.jsx:129 msgid "No device selected yet" -msgstr "" +msgstr "Noch kein Gerät ausgewählt" #. TRANSLATORS: %s will be replaced by the device name and its size, #. example: "/dev/sda, 20 GiB" @@ -845,17 +855,17 @@ msgstr "" #: src/components/overview/StorageSection.jsx:208 #: src/components/storage/ProposalPage.jsx:239 msgid "Storage" -msgstr "" +msgstr "Speicherung" #. TRANSLATORS: %s will be replaced by the user name #: src/components/overview/UsersSection.jsx:80 #, c-format msgid "User %s will be created" -msgstr "" +msgstr "Benutzer %s wird erstellt" #: src/components/overview/UsersSection.jsx:87 msgid "No user defined yet" -msgstr "" +msgstr "Noch kein Benutzer definiert" #: src/components/overview/UsersSection.jsx:101 msgid "Root authentication set for using both, password and public SSH Key" @@ -877,28 +887,28 @@ msgstr "" #: src/components/overview/UsersSection.jsx:120 #: src/components/users/UsersPage.jsx:30 msgid "Users" -msgstr "" +msgstr "Benutzer" #: src/components/product/ProductPage.jsx:63 #: src/components/product/ProductSelectionPage.jsx:65 msgid "Choose a product" -msgstr "" +msgstr "Produkt auswählen" #: src/components/product/ProductPage.jsx:122 #, c-format msgid "Register %s" -msgstr "" +msgstr "%s registrieren" #: src/components/product/ProductPage.jsx:188 #, c-format msgid "Deregister %s" -msgstr "" +msgstr "%s deregistrieren" #. TRANSLATORS: %s is replaced by a product name (e.g., SUSE ALP-Dolomite) #: src/components/product/ProductPage.jsx:202 #, c-format msgid "Do you want to deregister %s?" -msgstr "" +msgstr "Möchten Sie %s deregistrieren?" #: src/components/product/ProductPage.jsx:227 msgid "Registered warning" @@ -909,22 +919,24 @@ msgstr "" #, c-format msgid "The product %s must be deregistered before selecting a new product." msgstr "" +"Das Produkt %s muss deregistriert werden, bevor ein neues Produkt ausgewählt " +"werden kann." #: src/components/product/ProductPage.jsx:263 msgid "Change product" -msgstr "" +msgstr "Produkt ändern" #: src/components/product/ProductPage.jsx:305 msgid "Register" -msgstr "" +msgstr "Registrieren" #: src/components/product/ProductPage.jsx:337 msgid "Deregister product" -msgstr "" +msgstr "Produkt deregistrieren" #: src/components/product/ProductPage.jsx:370 msgid "Code:" -msgstr "" +msgstr "Code:" #: src/components/product/ProductPage.jsx:374 msgid "Email:" @@ -933,19 +945,19 @@ msgstr "" #. TRANSLATORS: section title. #: src/components/product/ProductPage.jsx:390 msgid "Registration" -msgstr "" +msgstr "Registrierung" #: src/components/product/ProductPage.jsx:399 msgid "This product requires registration." -msgstr "" +msgstr "Dieses Produkt erfordert eine Registrierung." #: src/components/product/ProductPage.jsx:405 msgid "This product does not require registration." -msgstr "" +msgstr "Dieses Produkt erfordert keine Registrierung." #: src/components/product/ProductRegistrationForm.jsx:63 msgid "Registration code" -msgstr "" +msgstr "Registrierungscode" #: src/components/product/ProductRegistrationForm.jsx:66 msgid "Email" @@ -953,69 +965,69 @@ msgstr "" #: src/components/product/ProductSelectionPage.jsx:58 msgid "Loading available products, please wait..." -msgstr "" +msgstr "Verfügbare Produkte werden geladen, bitte warten ..." #. TRANSLATORS: page title #: src/components/product/ProductSelectionPage.jsx:63 msgid "Product selection" -msgstr "" +msgstr "Produktauswahl" #: src/components/product/ProductSelectionPage.jsx:72 msgid "Select" -msgstr "" +msgstr "Auswählen" #: src/components/product/ProductSelector.jsx:36 msgid "No products available for selection" -msgstr "" +msgstr "Keine Produkte zur Auswahl verfügbar" #: src/components/product/ProductSelector.jsx:42 msgid "Available products" -msgstr "" +msgstr "Verfügbare Produkte" #: src/components/questions/GenericQuestion.jsx:35 #: src/components/questions/LuksActivationQuestion.jsx:60 msgid "Question" -msgstr "" +msgstr "Frage" #. TRANSLATORS: error message, user entered a wrong password #: src/components/questions/LuksActivationQuestion.jsx:34 msgid "Given encryption password didn't work" -msgstr "" +msgstr "Das angegebene Verschlüsselungspasswort hat nicht funktioniert" #: src/components/questions/LuksActivationQuestion.jsx:59 msgid "Encrypted Device" -msgstr "" +msgstr "Verschlüsseltes Gerät" #. TRANSLATORS: field label #: src/components/questions/LuksActivationQuestion.jsx:69 msgid "Encryption Password" -msgstr "" +msgstr "Verschlüsselungspasswort" #. TRANSLATORS: pattern status, selected to install (by user) #: src/components/software/PatternItem.jsx:63 msgid "selected" -msgstr "" +msgstr "ausgewählt" #. TRANSLATORS: pattern status, selected to install (by dependencies) #: src/components/software/PatternItem.jsx:66 msgid "automatically selected" -msgstr "" +msgstr "automatisch ausgewählt" #. TRANSLATORS: pattern status, not selected to install #: src/components/software/PatternItem.jsx:69 msgid "not selected" -msgstr "" +msgstr "nicht ausgewählt" #: src/components/software/PatternSelector.jsx:210 msgid "Software summary and filter options" -msgstr "" +msgstr "Software-Zusammenfassung und Filteroptionen" #. TRANSLATORS: %s will be replaced by the estimated installation size, #. example: "728.8 MiB" #: src/components/software/UsedSize.jsx:32 #, c-format msgid "Installation will take %s" -msgstr "" +msgstr "Installation wird %s in Anspruch nehmen" #: src/components/storage/DASDFormatProgress.jsx:61 msgid "Waiting for progress report" @@ -1035,21 +1047,21 @@ msgstr "" #: src/components/storage/iscsi/InitiatorPresenter.jsx:71 #: src/components/storage/iscsi/NodesPresenter.jsx:103 msgid "No" -msgstr "" +msgstr "Nein" #: src/components/storage/DASDTable.jsx:57 #: src/components/storage/ZFCPPage.jsx:318 #: src/components/storage/iscsi/InitiatorPresenter.jsx:71 #: src/components/storage/iscsi/NodesPresenter.jsx:103 msgid "Yes" -msgstr "" +msgstr "Ja" #: src/components/storage/DASDTable.jsx:64 #: src/components/storage/ZFCPDiskForm.jsx:118 #: src/components/storage/ZFCPPage.jsx:301 #: src/components/storage/ZFCPPage.jsx:361 msgid "Channel ID" -msgstr "" +msgstr "Kanalkennung" #. TRANSLATORS: table header #: src/components/storage/DASDTable.jsx:65 @@ -1058,17 +1070,17 @@ msgstr "" #: src/components/storage/iscsi/NodesPresenter.jsx:125 #: src/components/users/RootAuthMethods.jsx:157 msgid "Status" -msgstr "" +msgstr "Status" #. TRANSLATORS: The storage "Device" section's title #: src/components/storage/DASDTable.jsx:66 #: src/components/storage/ProposalDeviceSection.jsx:423 msgid "Device" -msgstr "" +msgstr "Gerät" #: src/components/storage/DASDTable.jsx:67 msgid "Type" -msgstr "" +msgstr "Art" #: src/components/storage/DASDTable.jsx:68 msgid "Diag" @@ -1076,7 +1088,7 @@ msgstr "" #: src/components/storage/DASDTable.jsx:69 msgid "Formatted" -msgstr "" +msgstr "Formatiert" #: src/components/storage/DASDTable.jsx:70 msgid "Partition Info" @@ -1091,13 +1103,13 @@ msgstr "" #: src/components/storage/DASDTable.jsx:111 #: src/components/storage/ZFCPPage.jsx:332 msgid "Activate" -msgstr "" +msgstr "Aktivieren" #. TRANSLATORS: drop down menu action, deactivate the device #: src/components/storage/DASDTable.jsx:113 #: src/components/storage/ZFCPPage.jsx:374 msgid "Deactivate" -msgstr "" +msgstr "Deaktivieren" #. TRANSLATORS: drop down menu action, enable DIAG access method #: src/components/storage/DASDTable.jsx:116 @@ -1158,7 +1170,7 @@ msgstr[1] "" #. "delete partition A", "create partition B with filesystem C", ... #: src/components/storage/ProposalActionsSection.jsx:124 msgid "Planned Actions" -msgstr "" +msgstr "Geplante Aktionen" #. TRANSLATORS: The storage "Planned Actions" section's description #: src/components/storage/ProposalActionsSection.jsx:126 @@ -1177,11 +1189,11 @@ msgstr "" #: src/components/storage/ProposalDeviceSection.jsx:147 #: src/components/storage/ProposalDeviceSection.jsx:245 msgid "Installation device" -msgstr "" +msgstr "Installationsgerät" #: src/components/storage/ProposalDeviceSection.jsx:153 msgid "No devices found." -msgstr "" +msgstr "Keine Geräte gefunden." #: src/components/storage/ProposalDeviceSection.jsx:242 msgid "Devices for creating the volume group" @@ -1204,7 +1216,7 @@ msgstr "" #: src/components/storage/ProposalDeviceSection.jsx:326 #: src/components/storage/ProposalDeviceSection.jsx:346 msgid "LVM settings" -msgstr "" +msgstr "LVM-Einstellungen" #: src/components/storage/ProposalDeviceSection.jsx:333 msgid "Waiting for information about LVM" @@ -1228,11 +1240,11 @@ msgstr "" #: src/components/storage/ProposalFileSystemsSection.jsx:70 msgid "File systems" -msgstr "" +msgstr "Dateisysteme" #: src/components/storage/ProposalPageMenu.jsx:40 msgid "Manage and format" -msgstr "" +msgstr "Verwalten und formatieren" #: src/components/storage/ProposalPageMenu.jsx:58 msgid "Activate disks" @@ -1240,7 +1252,7 @@ msgstr "" #: src/components/storage/ProposalPageMenu.jsx:60 msgid "zFCP" -msgstr "" +msgstr "zFCP" #: src/components/storage/ProposalPageMenu.jsx:76 msgid "Connect to iSCSI targets" @@ -1248,12 +1260,12 @@ msgstr "" #: src/components/storage/ProposalPageMenu.jsx:78 msgid "iSCSI" -msgstr "" +msgstr "iSCSI" #. TRANSLATORS: The word 'directly' is key here. For example, booting to the installer media and then choosing #. 'Boot from Hard Disk' from there will not work. Keep it sort (this is a hint in a form) but keep it clear. #. Do not translate 'abbr' and 'title', they are part of the HTML markup. -#: src/components/storage/ProposalSettingsSection.jsx:86 +#: src/components/storage/ProposalSettingsSection.jsx:89 msgid "" "The password will not be needed to boot and access the data if the TPM can verify the integrity of the " @@ -1261,51 +1273,84 @@ msgid "" "first run." msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" +msgstr "TPM zur automatischen Entschlüsselung bei jedem Bootvorgang verwenden" + +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:159 +msgid "Use Btrfs Snapshots" +msgstr "Btrfs-Schnappschüsse verwenden" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "Btrfs-Schnappschüsse sind für das Produkt erforderlich." + +#: src/components/storage/ProposalSettingsSection.jsx:239 msgid "Change encryption settings" -msgstr "" +msgstr "Verschlüsselungseinstellungen ändern" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" -msgstr "" +msgstr "Verschlüsselungseinstellungen" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" -msgstr "" +msgstr "Verschlüsselung verwenden" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" +msgstr "Einstellungen" + +#: src/components/storage/ProposalSettingsSection.jsx:330 +#, fuzzy +msgid "Transactional system" +msgstr "transaktional" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." msgstr "" #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" -msgstr "" +msgstr "Aktuellen Inhalt löschen" #: src/components/storage/ProposalSpacePolicySection.jsx:51 msgid "All partitions will be removed and any data in the disks will be lost." msgstr "" +"Alle Partitionen werden entfernt und alle Daten auf den Festplatten gehen " +"verloren." #: src/components/storage/ProposalSpacePolicySection.jsx:55 msgid "Shrink existing partitions" -msgstr "" +msgstr "Vorhandene Partitionen verkleinern" #: src/components/storage/ProposalSpacePolicySection.jsx:56 msgid "The data is kept, but the current partitions will be resized as needed." msgstr "" +"Die Daten bleiben erhalten, aber die Größe der aktuellen Partitionen wird " +"nach Bedarf geändert." #: src/components/storage/ProposalSpacePolicySection.jsx:60 msgid "Use available space" -msgstr "" +msgstr "Verfügbaren Speicherplatz verwenden" #: src/components/storage/ProposalSpacePolicySection.jsx:61 msgid "" "The data is kept. Only the space not assigned to any partition will be used." msgstr "" +"Die Daten werden beibehalten. Nur der Speicherplatz, der keiner Partition " +"zugewiesen ist, wird verwendet." #: src/components/storage/ProposalSpacePolicySection.jsx:65 msgid "Custom" @@ -1317,42 +1362,42 @@ msgstr "" #: src/components/storage/ProposalSpacePolicySection.jsx:72 msgid "Used device" -msgstr "" +msgstr "Verwendetes Gerät" #: src/components/storage/ProposalSpacePolicySection.jsx:73 msgid "Current content" -msgstr "" +msgstr "Aktueller Inhalt" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" -msgstr "" +msgstr "Größe" #: src/components/storage/ProposalSpacePolicySection.jsx:75 #: src/components/storage/ProposalVolumes.jsx:308 msgid "Details" -msgstr "" +msgstr "Details" #: src/components/storage/ProposalSpacePolicySection.jsx:76 msgid "Action" -msgstr "" +msgstr "Aktion" #. TRANSLATORS: %s is replaced by partition table type (e.g., GPT) #: src/components/storage/ProposalSpacePolicySection.jsx:110 #, c-format msgid "%s partition table" -msgstr "" +msgstr "%s-Partitionstabelle" #: src/components/storage/ProposalSpacePolicySection.jsx:121 msgid "EFI system partition" -msgstr "" +msgstr "EFI-Systempartition" #. TRANSLATORS: %s is replaced by a file system type (e.g., btrfs). #: src/components/storage/ProposalSpacePolicySection.jsx:124 #, c-format msgid "%s file system" -msgstr "" +msgstr "%s-Dateisystem" #. TRANSLATORS: %s is replaced by a LVM volume group name (e.g., /dev/vg0). #: src/components/storage/ProposalSpacePolicySection.jsx:131 @@ -1364,23 +1409,23 @@ msgstr "" #: src/components/storage/ProposalSpacePolicySection.jsx:134 #, c-format msgid "Member of RAID %s" -msgstr "" +msgstr "Mitglied von RAID %s" #: src/components/storage/ProposalSpacePolicySection.jsx:136 msgid "Not identified" -msgstr "" +msgstr "Nicht erkannt" #. TRANSLATORS: %s is replaced by a disk size (e.g., 20 GiB) #: src/components/storage/ProposalSpacePolicySection.jsx:173 #, c-format msgid "%s unused" -msgstr "" +msgstr "%s nicht verwendet" #. TRANSLATORS: %s is replaced by a disk size (e.g., 2 GiB) #: src/components/storage/ProposalSpacePolicySection.jsx:186 #, c-format msgid "Shrinkable by %s" -msgstr "" +msgstr "Verkleinerbar um %s" #. TRANSLATORS: %s is replaced by a device name (e.g., /dev/sda) #: src/components/storage/ProposalSpacePolicySection.jsx:221 @@ -1392,15 +1437,15 @@ msgstr "" #: src/components/storage/ProposalVolumes.jsx:229 #: src/components/storage/iscsi/NodesPresenter.jsx:77 msgid "Delete" -msgstr "" +msgstr "Löschen" #: src/components/storage/ProposalSpacePolicySection.jsx:228 msgid "Allow resize" -msgstr "" +msgstr "Größenänderung erlauben" #: src/components/storage/ProposalSpacePolicySection.jsx:230 msgid "Do not modify" -msgstr "" +msgstr "Nicht verändern" #: src/components/storage/ProposalSpacePolicySection.jsx:382 msgid "Actions to find space" @@ -1426,7 +1471,7 @@ msgstr "" #. TRANSLATORS: list item, this affects the computed partition size limits #: src/components/storage/ProposalVolumes.jsx:63 msgid "The configuration of snapshots" -msgstr "" +msgstr "Die Konfiguration der Schnappschüsse" #. TRANSLATORS: list item, this affects the computed partition size limits #. %s is replaced by a list of the volumes (like "/home, /boot") @@ -1438,24 +1483,24 @@ msgstr "" #. TRANSLATORS: dropdown menu label #: src/components/storage/ProposalVolumes.jsx:129 msgid "Reset to defaults" -msgstr "" +msgstr "Auf Standardeinstellungen zurücksetzen" #. TRANSLATORS: dropdown menu label #: src/components/storage/ProposalVolumes.jsx:137 #: src/components/storage/ProposalVolumes.jsx:141 msgid "Add file system" -msgstr "" +msgstr "Dateisystem hinzufügen" #. TRANSLATORS: minimum device size, %s is replaced by size string, e.g. "17.5 GiB" #: src/components/storage/ProposalVolumes.jsx:191 #, c-format msgid "At least %s" -msgstr "" +msgstr "Mindestens %s" #. TRANSLATORS: device flag, the partition size is automatically computed #: src/components/storage/ProposalVolumes.jsx:197 msgid "auto" -msgstr "" +msgstr "automatisch" #. TRANSLATORS: the filesystem uses a logical volume (LVM) #: src/components/storage/ProposalVolumes.jsx:207 @@ -1464,175 +1509,170 @@ msgstr "" #: src/components/storage/ProposalVolumes.jsx:207 msgid "partition" -msgstr "" +msgstr "Partition" #. TRANSLATORS: filesystem flag, it uses an encryption #: src/components/storage/ProposalVolumes.jsx:216 msgid "encrypted" -msgstr "" +msgstr "verschlüsselt" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" -msgstr "" +msgstr "mit Schnappschüssen" #. TRANSLATORS: flag for transactional file system #: src/components/storage/ProposalVolumes.jsx:220 msgid "transactional" -msgstr "" +msgstr "transaktional" #: src/components/storage/ProposalVolumes.jsx:275 msgid "Edit file system" -msgstr "" +msgstr "Dateisystem bearbeiten" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" -msgstr "" +msgstr "Einhängepunkt" #: src/components/storage/ProposalVolumes.jsx:345 msgid "Table with mount points" -msgstr "" +msgstr "Tabelle mit Einhängepunkten" #: src/components/storage/VolumeForm.jsx:102 msgid "Select a value" -msgstr "" - -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" +msgstr "Wert auswählen" #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "" +"Die Optionen für den Dateisystemtyp hängen vom Produkt und dem Einhängepunkt " +"ab." -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" -msgstr "" +msgstr "Weitere Informationen zu Dateisystemtypen" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" -msgstr "" +msgstr "Dateisystemtyp" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" -msgstr "" +msgstr "die Konfiguration von Schnappschüssen" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " -msgstr "" +msgstr ", " #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." -msgstr "" +msgstr "Die endgültige Größe hängt von %s ab." #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " -msgstr "" +msgstr " und " #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." -msgstr "" +msgstr "Automatisch berechnete Größe entsprechend dem ausgewählten Produkt." -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." -msgstr "" +msgstr "Exakte Größe des Dateisystems." #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" -msgstr "" +msgstr "Exakte Größe" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" -msgstr "" +msgstr "Größeneinheit" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " "be as big as possible." msgstr "" +"Begrenzungen für die Größe des Dateisystems. Die endgültige Größe wird ein " +"Wert zwischen dem angegebenen Minimum und Maximum sein. Wenn kein Maximum " +"angegeben wird, wird das Dateisystem so groß wie möglich." #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" -msgstr "" +msgstr "Minimum" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" -msgstr "" +msgstr "Gewünschte Mindestgröße" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" -msgstr "" +msgstr "Einheit für die Mindestgröße" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" -msgstr "" +msgstr "Maximum" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" -msgstr "" +msgstr "Gewünschte Maximalgröße" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" -msgstr "" +msgstr "Einheit für die Maximalgröße" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" -msgstr "" +msgstr "Automatisch" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" -msgstr "" +msgstr "Bereich" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" -msgstr "" +msgstr "Ein Größenwert ist erforderlich" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" -msgstr "" +msgstr "Mindestgröße ist erforderlich" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" -msgstr "" +msgstr "Das Maximum muss größer sein als das Minimum" #: src/components/storage/ZFCPDiskForm.jsx:113 msgid "The zFCP disk was not activated." @@ -1656,11 +1696,11 @@ msgstr "" #: src/components/storage/ZFCPPage.jsx:314 msgid "Activated" -msgstr "" +msgstr "Aktiviert" #: src/components/storage/ZFCPPage.jsx:314 msgid "Deactivated" -msgstr "" +msgstr "Deaktiviert" #: src/components/storage/ZFCPPage.jsx:417 msgid "No zFCP controllers found." @@ -1673,7 +1713,7 @@ msgstr "" #. TRANSLATORS: button label #: src/components/storage/ZFCPPage.jsx:420 msgid "Read zFCP devices" -msgstr "" +msgstr "zFCP-Geräte lesen" #. TRANSLATORS: the text in the square brackets [] will be displayed in bold #: src/components/storage/ZFCPPage.jsx:429 @@ -1713,12 +1753,12 @@ msgstr "" #. TRANSLATORS: button label #: src/components/storage/ZFCPPage.jsx:572 msgid "Activate new disk" -msgstr "" +msgstr "Neue Festplatte aktivieren" #. TRANSLATORS: section title #: src/components/storage/ZFCPPage.jsx:584 msgid "Disks" -msgstr "" +msgstr "Festplatten" #. TRANSLATORS: page title #: src/components/storage/ZFCPPage.jsx:731 @@ -1740,11 +1780,11 @@ msgstr "" #: src/components/storage/device-utils.jsx:92 #, c-format msgid "Software %s" -msgstr "" +msgstr "Software %s" #: src/components/storage/device-utils.jsx:97 msgid "SD Card" -msgstr "" +msgstr "SD-Karte" #. TRANSLATORS: %s is replaced by the device transport name, e.g. USB, SATA, SCSI... #: src/components/storage/device-utils.jsx:99 @@ -1756,13 +1796,13 @@ msgstr "" #: src/components/storage/device-utils.jsx:118 #, c-format msgid "Members: %s" -msgstr "" +msgstr "Mitglieder: %s" #. TRANSLATORS: RAID details, %s is replaced by list of devices used by the array #: src/components/storage/device-utils.jsx:127 #, c-format msgid "Devices: %s" -msgstr "" +msgstr "Geräte: %s" #. TRANSLATORS: multipath details, %s is replaced by list of connections used by the device #: src/components/storage/device-utils.jsx:136 @@ -1775,25 +1815,26 @@ msgstr "" #: src/components/storage/device-utils.jsx:160 #, c-format msgid "%s with %d partitions" -msgstr "" +msgstr "%s mit %d Partitionen" #. TRANSLATORS: status message, no existing content was found on the disk, #. i.e. the disk is completely empty #: src/components/storage/device-utils.jsx:184 msgid "No content found" -msgstr "" +msgstr "Kein Inhalt gefunden" #: src/components/storage/device-utils.jsx:258 msgid "Available devices" -msgstr "" +msgstr "Verfügbare Geräte" #: src/components/storage/iscsi/AuthFields.jsx:70 +#, fuzzy msgid "Only available if authentication by target is provided" -msgstr "" +msgstr "Nur verfügbar, wenn Authentifizierung durch das Ziel angeboten wird" #: src/components/storage/iscsi/AuthFields.jsx:77 msgid "Authentication by target" -msgstr "" +msgstr "Authentifizierung durch das Ziel" #: src/components/storage/iscsi/AuthFields.jsx:80 #: src/components/storage/iscsi/AuthFields.jsx:85 @@ -1802,17 +1843,17 @@ msgstr "" #: src/components/storage/iscsi/AuthFields.jsx:117 #: src/components/storage/iscsi/AuthFields.jsx:119 msgid "User name" -msgstr "" +msgstr "Benutzername" #: src/components/storage/iscsi/AuthFields.jsx:91 #: src/components/storage/iscsi/AuthFields.jsx:124 msgid "Incorrect user name" -msgstr "" +msgstr "Falscher Benutzername" #: src/components/storage/iscsi/AuthFields.jsx:105 #: src/components/storage/iscsi/AuthFields.jsx:139 msgid "Incorrect password" -msgstr "" +msgstr "Falsches Passwort" #: src/components/storage/iscsi/AuthFields.jsx:108 msgid "Authentication by initiator" @@ -1834,28 +1875,28 @@ msgstr "" #: src/components/storage/iscsi/DiscoverForm.jsx:115 msgid "IP address" -msgstr "" +msgstr "IP-Adresse" #. TRANSLATORS: network address #: src/components/storage/iscsi/DiscoverForm.jsx:122 #: src/components/storage/iscsi/DiscoverForm.jsx:124 msgid "Address" -msgstr "" +msgstr "Adresse" #: src/components/storage/iscsi/DiscoverForm.jsx:129 msgid "Incorrect IP address" -msgstr "" +msgstr "Falsche IP-Adresse" #. TRANSLATORS: network port number #: src/components/storage/iscsi/DiscoverForm.jsx:133 #: src/components/storage/iscsi/DiscoverForm.jsx:140 #: src/components/storage/iscsi/DiscoverForm.jsx:142 msgid "Port" -msgstr "" +msgstr "Port" #: src/components/storage/iscsi/DiscoverForm.jsx:147 msgid "Incorrect port" -msgstr "" +msgstr "Falscher Port" #: src/components/storage/iscsi/InitiatorForm.jsx:42 msgid "Edit iSCSI Initiator" @@ -1873,7 +1914,7 @@ msgstr "" #: src/components/storage/iscsi/NodesPresenter.jsx:103 #: src/components/storage/iscsi/NodesPresenter.jsx:124 msgid "iBFT" -msgstr "" +msgstr "iBFT" #: src/components/storage/iscsi/InitiatorPresenter.jsx:72 #: src/components/storage/iscsi/InitiatorPresenter.jsx:87 @@ -1903,26 +1944,26 @@ msgstr "" #: src/components/storage/iscsi/NodeStartupOptions.js:27 msgid "Automatic" -msgstr "" +msgstr "Automatisch" #. TRANSLATORS: iSCSI connection status, %s is replaced by node label #: src/components/storage/iscsi/NodesPresenter.jsx:67 #, c-format msgid "Connected (%s)" -msgstr "" +msgstr "Verbunden (%s)" #: src/components/storage/iscsi/NodesPresenter.jsx:82 msgid "Login" -msgstr "" +msgstr "Anmelden" #: src/components/storage/iscsi/NodesPresenter.jsx:86 msgid "Logout" -msgstr "" +msgstr "Abmelden" #: src/components/storage/iscsi/NodesPresenter.jsx:101 #: src/components/storage/iscsi/NodesPresenter.jsx:122 msgid "Portal" -msgstr "" +msgstr "Portal" #: src/components/storage/iscsi/NodesPresenter.jsx:102 #: src/components/storage/iscsi/NodesPresenter.jsx:123 @@ -1951,86 +1992,95 @@ msgstr "" #. TRANSLATORS: iSCSI targets section title #: src/components/storage/iscsi/TargetsSection.jsx:167 msgid "Targets" -msgstr "" +msgstr "Ziele" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" -msgstr "" +msgstr "KiB" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" -msgstr "" +msgstr "MiB" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" -msgstr "" +msgstr "GiB" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" -msgstr "" +msgstr "TiB" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" -msgstr "" +msgstr "PiB" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." -msgstr "" +msgstr "Noch kein Benutzer definiert." -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." msgstr "" #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" -msgstr "" +msgstr "Vollständiger Name" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" +msgstr "Benutzername" + +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" msgstr "" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" -msgstr "" +msgstr "Verwerfen" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" -msgstr "" +msgstr "Benutzerkonto erstellen" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" -msgstr "" +msgstr "Benutzerkonto bearbeiten" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" -msgstr "" +msgstr "Vollständiger Name des Benutzers" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" -msgstr "" +msgstr "Auch Passwort bearbeiten" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" -msgstr "" +msgstr "Automatisches Anmelden" #: src/components/users/RootAuthMethods.jsx:35 msgid "No root authentication method defined yet." @@ -2055,30 +2105,30 @@ msgstr "" #: src/components/users/RootAuthMethods.jsx:94 #: src/components/users/RootAuthMethods.jsx:107 msgid "Change" -msgstr "" +msgstr "Ändern" #: src/components/users/RootAuthMethods.jsx:94 #: src/components/users/RootAuthMethods.jsx:107 msgid "Set" -msgstr "" +msgstr "Festlegen" #: src/components/users/RootAuthMethods.jsx:129 msgid "Already set" -msgstr "" +msgstr "Bereits festgelegt" #: src/components/users/RootAuthMethods.jsx:130 #: src/components/users/RootAuthMethods.jsx:134 msgid "Not set" -msgstr "" +msgstr "Nicht festgelegt" #. TRANSLATORS: table header, user authentication method #: src/components/users/RootAuthMethods.jsx:155 msgid "Method" -msgstr "" +msgstr "Methode" #: src/components/users/RootAuthMethods.jsx:170 msgid "SSH Key" -msgstr "" +msgstr "SSH-Schlüssel" #: src/components/users/RootAuthMethods.jsx:187 msgid "Change the root password" diff --git a/web/po/es.po b/web/po/es.po index cf07647938..8eebd1aea2 100644 --- a/web/po/es.po +++ b/web/po/es.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" -"PO-Revision-Date: 2024-02-09 13:42+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" +"PO-Revision-Date: 2024-02-25 20:42+0000\n" "Last-Translator: Victor hck \n" "Language-Team: Spanish \n" @@ -41,10 +41,11 @@ msgstr "Acerca de Agama" #. TRANSLATORS: content of the "About" popup (1/2) #: src/components/core/About.jsx:53 +#, fuzzy msgid "" -"Agama is an experimental installer for (open)SUSE systems. It still under " +"Agama is an experimental installer for (open)SUSE systems. It is still under " "development so, please, do not use it in production environments. If you " -"want to give it a try, we recommend to use a virtual machine to prevent any " +"want to give it a try, we recommend using a virtual machine to prevent any " "possible data loss." msgstr "" "Agama es un instalador experimental para sistemas (open)SUSE. Aún está en " @@ -157,7 +158,7 @@ msgstr "" #: src/components/product/ProductPage.jsx:207 #: src/components/storage/ProposalDeviceSection.jsx:169 #: src/components/storage/ProposalDeviceSection.jsx:364 -#: src/components/storage/ProposalSettingsSection.jsx:211 +#: src/components/storage/ProposalSettingsSection.jsx:275 #: src/components/storage/ProposalVolumes.jsx:148 #: src/components/storage/ProposalVolumes.jsx:283 #: src/components/storage/ZFCPPage.jsx:511 @@ -561,7 +562,7 @@ msgstr "Direcciones IP" #: src/components/storage/ProposalVolumes.jsx:234 #: src/components/storage/iscsi/InitiatorPresenter.jsx:49 #: src/components/storage/iscsi/NodesPresenter.jsx:73 -#: src/components/users/FirstUser.jsx:174 +#: src/components/users/FirstUser.jsx:208 msgid "Edit" msgstr "Editar" @@ -708,7 +709,7 @@ msgstr "WPA y WPA2 personales" #: src/components/storage/ZFCPDiskForm.jsx:112 #: src/components/storage/iscsi/DiscoverForm.jsx:108 #: src/components/storage/iscsi/LoginForm.jsx:72 -#: src/components/users/FirstUser.jsx:198 +#: src/components/users/FirstUser.jsx:238 msgid "Something went wrong" msgstr "Algo salió mal" @@ -1004,9 +1005,8 @@ msgid "No products available for selection" msgstr "No hay productos disponibles para seleccionar" #: src/components/product/ProductSelector.jsx:42 -#, fuzzy msgid "Available products" -msgstr "Idiomas disponibles" +msgstr "Productos disponibles" #: src/components/questions/GenericQuestion.jsx:35 #: src/components/questions/LuksActivationQuestion.jsx:60 @@ -1198,15 +1198,14 @@ msgstr "Acciones planeadas" #. TRANSLATORS: The storage "Planned Actions" section's description #: src/components/storage/ProposalActionsSection.jsx:126 -#, fuzzy msgid "Actions to create the file systems and to ensure the new system boots." msgstr "" -"Acciones para crear los sistemas de archivos y garantizar que el sistema " -"arranque." +"Acciones para crear los sistemas de archivos y garantizar que el nuevo " +"sistema arranque." #: src/components/storage/ProposalDeviceSection.jsx:135 msgid "Waiting for information about selected device" -msgstr "" +msgstr "Esperando información sobre el dispositivo seleccionado" #: src/components/storage/ProposalDeviceSection.jsx:138 msgid "Select the device for installing the system." @@ -1249,7 +1248,7 @@ msgstr "Ajustes LVM" #: src/components/storage/ProposalDeviceSection.jsx:333 msgid "Waiting for information about LVM" -msgstr "" +msgstr "Esperando información sobre LVM" #: src/components/storage/ProposalDeviceSection.jsx:339 msgid "Use logical volume management (LVM)" @@ -1266,11 +1265,12 @@ msgid "" "Select the main disk or LVM " "Volume Group for installation." msgstr "" +"Seleccione el disco principal o LVM grupo de volúmenes para instalación." #: src/components/storage/ProposalFileSystemsSection.jsx:70 -#, fuzzy msgid "File systems" -msgstr "Tipo de sistema de archivos" +msgstr "Sistemas de archivos" #: src/components/storage/ProposalPageMenu.jsx:40 msgid "Manage and format" @@ -1295,7 +1295,7 @@ msgstr "iSCSI" #. TRANSLATORS: The word 'directly' is key here. For example, booting to the installer media and then choosing #. 'Boot from Hard Disk' from there will not work. Keep it sort (this is a hint in a form) but keep it clear. #. Do not translate 'abbr' and 'title', they are part of the HTML markup. -#: src/components/storage/ProposalSettingsSection.jsx:86 +#: src/components/storage/ProposalSettingsSection.jsx:89 msgid "" "The password will not be needed to boot and access the data if the TPM can verify the integrity of the " @@ -1307,27 +1307,55 @@ msgstr "" "integridad del sistema. El sellado TPM requiere que el nuevo sistema se " "inicie directamente en su primera ejecución." -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "Utilice el TPM para descifrar automáticamente en cada arranque" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +#, fuzzy +msgid "Use Btrfs Snapshots" +msgstr "con instantáneas" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:239 msgid "Change encryption settings" msgstr "Cambiar las configuraciones de cifrado" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "Configuraciones del cifrado" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "Usar cifrado" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "Ajustes" +#: src/components/storage/ProposalSettingsSection.jsx:330 +#, fuzzy +msgid "Transactional system" +msgstr "transaccional" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "Eliminar el contenido actual" @@ -1343,46 +1371,41 @@ msgid "Shrink existing partitions" msgstr "Reducir las particiones existentes" #: src/components/storage/ProposalSpacePolicySection.jsx:56 -#, fuzzy msgid "The data is kept, but the current partitions will be resized as needed." msgstr "" "Los datos se conservan, pero las particiones actuales cambiarán de tamaño " -"según sea necesario para crear espacio suficiente." +"según sea necesario." #: src/components/storage/ProposalSpacePolicySection.jsx:60 msgid "Use available space" msgstr "Utilice el espacio disponible" #: src/components/storage/ProposalSpacePolicySection.jsx:61 -#, fuzzy msgid "" "The data is kept. Only the space not assigned to any partition will be used." msgstr "" -"Los datos se conservan y las particiones existentes no se modificarán. Sólo " -"se utilizará el espacio que no esté asignado a ninguna partición." +"Los datos se conservan. Sólo se utilizará el espacio que no esté asignado a " +"ninguna partición." #: src/components/storage/ProposalSpacePolicySection.jsx:65 -#, fuzzy msgid "Custom" -msgstr "Dispositivos personalizados" +msgstr "Personalizado" #: src/components/storage/ProposalSpacePolicySection.jsx:66 msgid "Select what to do with each partition." -msgstr "" +msgstr "Seleccione qué hacer con cada partición." #: src/components/storage/ProposalSpacePolicySection.jsx:72 -#, fuzzy msgid "Used device" -msgstr "Leer dispositivos zFCP" +msgstr "Dispositivo usado" #: src/components/storage/ProposalSpacePolicySection.jsx:73 -#, fuzzy msgid "Current content" -msgstr "Eliminar el contenido actual" +msgstr "Contenido actual" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "Tamaño" @@ -1392,60 +1415,58 @@ msgid "Details" msgstr "Detalles" #: src/components/storage/ProposalSpacePolicySection.jsx:76 -#, fuzzy msgid "Action" -msgstr "Acciones" +msgstr "Acción" #. TRANSLATORS: %s is replaced by partition table type (e.g., GPT) #: src/components/storage/ProposalSpacePolicySection.jsx:110 -#, fuzzy, c-format +#, c-format msgid "%s partition table" -msgstr "partición" +msgstr "%s tabla de partición" #: src/components/storage/ProposalSpacePolicySection.jsx:121 -#, fuzzy msgid "EFI system partition" -msgstr "partición" +msgstr "partición del sistema EFI" #. TRANSLATORS: %s is replaced by a file system type (e.g., btrfs). #: src/components/storage/ProposalSpacePolicySection.jsx:124 -#, fuzzy, c-format +#, c-format msgid "%s file system" -msgstr "Agregar sistema de archivos" +msgstr "%s sistema de archivos" #. TRANSLATORS: %s is replaced by a LVM volume group name (e.g., /dev/vg0). #: src/components/storage/ProposalSpacePolicySection.jsx:131 #, c-format msgid "LVM physical volume of %s" -msgstr "" +msgstr "Volumen físico LVM de %s" #. TRANSLATORS: %s is replaced by a RAID name (e.g., /dev/md0). #: src/components/storage/ProposalSpacePolicySection.jsx:134 -#, fuzzy, c-format +#, c-format msgid "Member of RAID %s" -msgstr "Miembros: %s" +msgstr "Miembro de RAID %s" #: src/components/storage/ProposalSpacePolicySection.jsx:136 msgid "Not identified" -msgstr "" +msgstr "No identificado" #. TRANSLATORS: %s is replaced by a disk size (e.g., 20 GiB) #: src/components/storage/ProposalSpacePolicySection.jsx:173 #, c-format msgid "%s unused" -msgstr "" +msgstr "%s no usado" #. TRANSLATORS: %s is replaced by a disk size (e.g., 2 GiB) #: src/components/storage/ProposalSpacePolicySection.jsx:186 #, c-format msgid "Shrinkable by %s" -msgstr "" +msgstr "Se puede reducir a %s" #. TRANSLATORS: %s is replaced by a device name (e.g., /dev/sda) #: src/components/storage/ProposalSpacePolicySection.jsx:221 #, c-format msgid "Space action selector for %s" -msgstr "" +msgstr "Selector de acción en el espacio para %s" #: src/components/storage/ProposalSpacePolicySection.jsx:224 #: src/components/storage/ProposalVolumes.jsx:229 @@ -1455,20 +1476,18 @@ msgstr "Eliminar" #: src/components/storage/ProposalSpacePolicySection.jsx:228 msgid "Allow resize" -msgstr "" +msgstr "Permitir cambio de tamaño" #: src/components/storage/ProposalSpacePolicySection.jsx:230 msgid "Do not modify" -msgstr "" +msgstr "No modificar" #: src/components/storage/ProposalSpacePolicySection.jsx:382 -#, fuzzy msgid "Actions to find space" -msgstr "Acciones para la conexión %s" +msgstr "Acciones para encontrar espacio" #. TRANSLATORS: The storage "Find Space" section's title #: src/components/storage/ProposalSpacePolicySection.jsx:452 -#, fuzzy msgid "Find Space" msgstr "Encontrar espacio" @@ -1478,6 +1497,9 @@ msgid "" "Allocating the file systems might need to find free space in the devices " "listed below. Choose how to do it." msgstr "" +"Es posible que para asignar los sistemas de archivos sea necesario encontrar " +"espacio libre en los dispositivos que se enumeran a continuación. Elige cómo " +"hacerlo." #. TRANSLATORS: header for a list of items #: src/components/storage/ProposalVolumes.jsx:59 @@ -1534,9 +1556,6 @@ msgstr "cifrado" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "con instantáneas" @@ -1550,8 +1569,8 @@ msgid "Edit file system" msgstr "Editar sistema de archivos" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "Punto de montaje" @@ -1563,17 +1582,8 @@ msgstr "Tabla con puntos de montaje" msgid "Select a value" msgstr "Seleccionar un valor" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" -"Permite revertir cualquier cambio realizado en el sistema y restaurar su " -"estado anterior" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." @@ -1581,63 +1591,63 @@ msgstr "" "Las opciones para el tipo de sistema de archivos dependen del producto y del " "punto de montaje." -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" msgstr "Más información para los tipos de sistemas de archivos" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "Tipo de sistema de archivos" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "la configuración de las instantáneas" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "la presencia del sistema de archivos para %s" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr ", " #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "El tamaño final depende de %s." #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr " y " #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "Tamaño calculado automáticamente según el producto seleccionado." -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "Tamaño exacto para el sistema de archivos." #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "Tamaño exacto" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "Unidad de tamaño" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1648,57 +1658,57 @@ msgstr "" "de archivos será lo más grande posible." #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "Mínimo" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "Tamaño mínimo deseado" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "Unidad para el tamaño mínimo" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "Máximo" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "Tamaño máximo deseado" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "Unidad para el tamaño máximo" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "Automático" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "Fijado" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "Rango" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "Se requiere un valor de tamaño" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "Se requiere un tamaño mínimo" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "El máximo debe ser mayor que el mínimo" @@ -2027,31 +2037,31 @@ msgstr "Descubrir" msgid "Targets" msgstr "Objetivos" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "KB" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "MB" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "GB" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "TB" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "PB" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." msgstr "Ningún usuario definido todavía." -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." @@ -2060,51 +2070,60 @@ msgstr "" "para poder iniciar sesión en él." #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "Definir un usuario ahora" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "Nombre completo" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "Nombre de usuario" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "Descartar" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "Crear cuenta de usuario" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "Editar cuenta de usuario" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "Nombre completo del usuario" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "Editar contraseña también" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "inicio de sesión automático del usuario" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "Inicio de sesión automático" @@ -2208,6 +2227,13 @@ msgstr "Usuario" msgid "Root authentication" msgstr "Autenticación de root" +#~ msgid "" +#~ "Allows rolling back any change done to the system and restoring its " +#~ "previous state" +#~ msgstr "" +#~ "Permite revertir cualquier cambio realizado en el sistema y restaurar su " +#~ "estado anterior" + #~ msgid "Devices will not be modified until installation starts." #~ msgstr "" #~ "Los dispositivos no se modificarán hasta que comience la instalación." diff --git a/web/po/fr.po b/web/po/fr.po index 16590e40d9..3bcabedf7b 100644 --- a/web/po/fr.po +++ b/web/po/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" "PO-Revision-Date: 2024-01-23 12:59+0000\n" "Last-Translator: faila fail \n" "Language-Team: French TPM can verify the integrity of the " @@ -1320,27 +1321,55 @@ msgstr "" "l'intégrité du système. Le scellement par TPM exige que le nouveau système " "soit démarré directement lors de sa première exécution." -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "Utiliser le TPM pour décrypter automatiquement à chaque démarrage" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +#, fuzzy +msgid "Use Btrfs Snapshots" +msgstr "avec des clichés" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:239 msgid "Change encryption settings" msgstr "Modifier les paramètres de chiffrement" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "Paramètres de chiffrement" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "Utiliser le chiffrement" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "Paramètres" +#: src/components/storage/ProposalSettingsSection.jsx:330 +#, fuzzy +msgid "Transactional system" +msgstr "transactionnel" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "Supprimer le contenu actuel" @@ -1395,7 +1424,7 @@ msgstr "Supprimer le contenu actuel" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "Taille" @@ -1547,9 +1576,6 @@ msgstr "chiffré" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "avec des clichés" @@ -1563,8 +1589,8 @@ msgid "Edit file system" msgstr "Modifier le système de fichiers" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "Point de montage" @@ -1576,17 +1602,8 @@ msgstr "Table avec points de montage" msgid "Select a value" msgstr "Sélectionner une valeur" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" -"Permet la réinitialisation de toute modification apportée au système et le " -"rétablissement de son état antérieur" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." @@ -1594,64 +1611,64 @@ msgstr "" "Les options pour le type de système de fichiers varient en fonction du " "produit et du point de montage." -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" msgstr "Plus d'informations sur les différents systèmes de fichiers" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "Type de système de fichiers" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "la configuration des clichés" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "la présence du système de fichiers pour %s" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr ", " #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "La taille définitive dépend de %s." #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr " et " #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "" "La taille est automatiquement calculée en fonction du produit sélectionné." -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "Taille exacte du système de fichiers." #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "Taille exacte" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "Unité de mesure" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1662,57 +1679,57 @@ msgstr "" "n'est indiqué, le système de fichiers sera aussi grand que possible." #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "Minimum" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "Taille minimale souhaitée" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "Unité de la taille minimale" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "Maximum" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "Taille maximale désirée" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "Unité de la taille maximale" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "Auto" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "Fixe" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "Portée" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "Une valeur de taille est requise" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "Une taille minimale est requise" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "Le maximum doit être supérieur au minimum" @@ -2041,31 +2058,31 @@ msgstr "Découvrir" msgid "Targets" msgstr "Cibles" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "KiB" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "MiB" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "GiB" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "TiB" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "PiB" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." msgstr "Aucun utilisateur n'a été défini." -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." @@ -2074,51 +2091,60 @@ msgstr "" "système pour pouvoir s'y connecter." #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "Définir un utilisateur maintenant" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "Nom complet" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "Nom d'utilisateur" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "Rejeter" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "Créer un compte utilisateur" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "Modifier un compte utilisateur" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "Nom complet de l'utilisateur" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "Modifier également le mot de passe" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "connexion automatique de l'utilisateur" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "connexion automatique" @@ -2222,6 +2248,13 @@ msgstr "Utilisateur" msgid "Root authentication" msgstr "Authentification root" +#~ msgid "" +#~ "Allows rolling back any change done to the system and restoring its " +#~ "previous state" +#~ msgstr "" +#~ "Permet la réinitialisation de toute modification apportée au système et " +#~ "le rétablissement de son état antérieur" + #~ msgid "Devices will not be modified until installation starts." #~ msgstr "" #~ "Les périphériques ne seront pas modifiés tant que l'installation n'aura " diff --git a/web/po/id.po b/web/po/id.po index b31b978f88..9f8a56fb26 100644 --- a/web/po/id.po +++ b/web/po/id.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" "PO-Revision-Date: 2024-02-21 04:42+0000\n" "Last-Translator: Arif Budiman \n" "Language-Team: Indonesian TPM can verify the integrity of the " @@ -1291,28 +1292,56 @@ msgid "" "first run." msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +#, fuzzy +msgid "Use Btrfs Snapshots" +msgstr "dengan snapshot" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:239 #, fuzzy msgid "Change encryption settings" msgstr "Pengaturan enkripsi" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "Pengaturan enkripsi" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "Gunakan enkripsi" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "Pengaturan" +#: src/components/storage/ProposalSettingsSection.jsx:330 +#, fuzzy +msgid "Transactional system" +msgstr "transaksional" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "Hapus konten saat ini" @@ -1365,7 +1394,7 @@ msgstr "Hapus konten saat ini" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "Ukuran" @@ -1517,9 +1546,6 @@ msgstr "dienkripsi" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "dengan snapshot" @@ -1533,8 +1559,8 @@ msgid "Edit file system" msgstr "Edit sistem berkas" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "Titik pemasangan" @@ -1547,79 +1573,70 @@ msgstr "Tabel dengan titik pemasangan" msgid "Select a value" msgstr "Pilih bahasa" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" -"Memungkinkan untuk mengembalikan setiap perubahan yang dilakukan pada sistem " -"dan memulihkan kondisi sebelumnya" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "Opsi untuk jenis sistem berkas tergantung pada produk dan titik mount." -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" msgstr "Info lebih lanjut untuk jenis sistem berkas" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "Jenis sistem berkas" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "konfigurasi snapshot" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "keberadaan sistem berkas untuk %s" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr ", " #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "Ukuran akhir tergantung pada %s." #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr " dan " #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "Ukuran yang dihitung secara otomatis menurut produk yang dipilih." -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "Ukuran yang tepat untuk sistem berkas." #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "Ukuran yang tepat" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "Satuan ukuran" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1630,57 +1647,57 @@ msgstr "" "diberikan, maka sistem berkas akan sebesar mungkin." #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "Minimum" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "Ukuran minimum yang diinginkan" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "Satuan untuk ukuran minimum" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "Maksimum" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "Ukuran maksimum yang diinginkan" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "Satuan untuk ukuran maksimum" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "Otomatis" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "Tetap" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "Rentang" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "Diperlukan nilai ukuran" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "Diperlukan ukuran minimum" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "Maksimum harus lebih besar dari minimum" @@ -2007,31 +2024,31 @@ msgstr "Temukan" msgid "Targets" msgstr "Target" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "KiB" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "MiB" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "GiB" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "TiB" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "PiB" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." msgstr "Belum ada pengguna yang ditetapkan." -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." @@ -2040,51 +2057,60 @@ msgstr "" "agar dapat masuk ke dalamnya." #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "Tentukan pengguna sekarang" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "Nama lengkap" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "Nama pengguna" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "Buang" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "Buat akun pengguna" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "Edit akun pengguna" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "Nama lengkap pengguna" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "Edit kata sandi juga" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "autologin pengguna" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "Masuk otomatis" @@ -2188,6 +2214,13 @@ msgstr "Pengguna" msgid "Root authentication" msgstr "Autentikasi root" +#~ msgid "" +#~ "Allows rolling back any change done to the system and restoring its " +#~ "previous state" +#~ msgstr "" +#~ "Memungkinkan untuk mengembalikan setiap perubahan yang dilakukan pada " +#~ "sistem dan memulihkan kondisi sebelumnya" + #~ msgid "Devices will not be modified until installation starts." #~ msgstr "Perangkat tidak akan dimodifikasi hingga penginstalan dimulai." diff --git a/web/po/ja.po b/web/po/ja.po index 7b0a3648f2..b9d7c92779 100644 --- a/web/po/ja.po +++ b/web/po/ja.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" -"PO-Revision-Date: 2024-02-22 01:00+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" +"PO-Revision-Date: 2024-02-29 04:42+0000\n" "Last-Translator: Yasuhiko Kamata \n" "Language-Team: Japanese \n" @@ -42,9 +42,9 @@ msgstr "Agama について" #. TRANSLATORS: content of the "About" popup (1/2) #: src/components/core/About.jsx:53 msgid "" -"Agama is an experimental installer for (open)SUSE systems. It still under " +"Agama is an experimental installer for (open)SUSE systems. It is still under " "development so, please, do not use it in production environments. If you " -"want to give it a try, we recommend to use a virtual machine to prevent any " +"want to give it a try, we recommend using a virtual machine to prevent any " "possible data loss." msgstr "" "Agama は (open)SUSE システム向けの実験中インストーラです。現在もなお開発途上" @@ -156,7 +156,7 @@ msgstr "" #: src/components/product/ProductPage.jsx:207 #: src/components/storage/ProposalDeviceSection.jsx:169 #: src/components/storage/ProposalDeviceSection.jsx:364 -#: src/components/storage/ProposalSettingsSection.jsx:211 +#: src/components/storage/ProposalSettingsSection.jsx:275 #: src/components/storage/ProposalVolumes.jsx:148 #: src/components/storage/ProposalVolumes.jsx:283 #: src/components/storage/ZFCPPage.jsx:511 @@ -557,7 +557,7 @@ msgstr "IP アドレス" #: src/components/storage/ProposalVolumes.jsx:234 #: src/components/storage/iscsi/InitiatorPresenter.jsx:49 #: src/components/storage/iscsi/NodesPresenter.jsx:73 -#: src/components/users/FirstUser.jsx:174 +#: src/components/users/FirstUser.jsx:208 msgid "Edit" msgstr "編集" @@ -706,7 +706,7 @@ msgstr "WPA および WPA2 Personal" #: src/components/storage/ZFCPDiskForm.jsx:112 #: src/components/storage/iscsi/DiscoverForm.jsx:108 #: src/components/storage/iscsi/LoginForm.jsx:72 -#: src/components/users/FirstUser.jsx:198 +#: src/components/users/FirstUser.jsx:238 msgid "Something went wrong" msgstr "何らかの問題が発生しました" @@ -1186,15 +1186,14 @@ msgstr "処理の計画" #. TRANSLATORS: The storage "Planned Actions" section's description #: src/components/storage/ProposalActionsSection.jsx:126 -#, fuzzy msgid "Actions to create the file systems and to ensure the new system boots." msgstr "" -"ファイルシステムを作成するための処理とシステムが起動できるようにするための処" -"理です。" +"ファイルシステムを作成し、新しいシステムが起動できるようにするための処理で" +"す。" #: src/components/storage/ProposalDeviceSection.jsx:135 msgid "Waiting for information about selected device" -msgstr "" +msgstr "選択したデバイスに関する情報を待機しています" #: src/components/storage/ProposalDeviceSection.jsx:138 msgid "Select the device for installing the system." @@ -1237,7 +1236,7 @@ msgstr "LVM 設定" #: src/components/storage/ProposalDeviceSection.jsx:333 msgid "Waiting for information about LVM" -msgstr "" +msgstr "LVM に関する情報を待機しています" #: src/components/storage/ProposalDeviceSection.jsx:339 msgid "Use logical volume management (LVM)" @@ -1254,11 +1253,12 @@ msgid "" "Select the main disk or LVM " "Volume Group for installation." msgstr "" +"インストール先のメインディスクもしくは LVM ボリュームグループを選択してください。" #: src/components/storage/ProposalFileSystemsSection.jsx:70 -#, fuzzy msgid "File systems" -msgstr "ファイルシステムの種類" +msgstr "ファイルシステム" #: src/components/storage/ProposalPageMenu.jsx:40 msgid "Manage and format" @@ -1283,7 +1283,7 @@ msgstr "iSCSI" #. TRANSLATORS: The word 'directly' is key here. For example, booting to the installer media and then choosing #. 'Boot from Hard Disk' from there will not work. Keep it sort (this is a hint in a form) but keep it clear. #. Do not translate 'abbr' and 'title', they are part of the HTML markup. -#: src/components/storage/ProposalSettingsSection.jsx:86 +#: src/components/storage/ProposalSettingsSection.jsx:89 msgid "" "The password will not be needed to boot and access the data if the TPM can verify the integrity of the " @@ -1295,27 +1295,56 @@ msgstr "" "シーリングを使用するには、新しいシステムの初回起動時に直接起動を行う必要があ" "ります。" -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "毎回の起動時に TPM を利用して自動的に暗号化解除する" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" +"ルートファイルシステムに btrfs を使用することで、設定変更前やソフトウエアの" +"アップグレード前に戻して起動し直すことができるようになります。" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +msgid "Use Btrfs Snapshots" +msgstr "btrfs スナップショットを使用する" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "btrfs のスナップショットは製品側の要件で必須となっています。" + +#: src/components/storage/ProposalSettingsSection.jsx:239 msgid "Change encryption settings" msgstr "暗号化設定の変更" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "暗号化の設定" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "暗号化を使用する" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "設定" +#: src/components/storage/ProposalSettingsSection.jsx:330 +#, fuzzy +msgid "Transactional system" +msgstr "トランザクション型" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "現在の内容を全て削除" @@ -1365,7 +1394,7 @@ msgstr "現在の内容" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "サイズ" @@ -1457,6 +1486,8 @@ msgid "" "Allocating the file systems might need to find free space in the devices " "listed below. Choose how to do it." msgstr "" +"ファイルシステムを割り当てるには、下記のデバイス内に空き領域を確保する必要が" +"あるかもしれません。ここではその方法を選択します。" #. TRANSLATORS: header for a list of items #: src/components/storage/ProposalVolumes.jsx:59 @@ -1513,9 +1544,6 @@ msgstr "暗号化" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "スナップショット有り" @@ -1529,8 +1557,8 @@ msgid "Edit file system" msgstr "ファイルシステムの編集" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "マウントポイント" @@ -1542,79 +1570,71 @@ msgstr "マウントポイントの一覧" msgid "Select a value" msgstr "値の選択" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" -"システムに実施された任意の変更を巻き戻し、以前の状態を復元できるようにします" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "" "ファイルシステムに対する選択肢は、製品とマウントポイントごとに異なります。" -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" msgstr "ファイルシステムの種類に関する詳細" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "ファイルシステムの種類" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "スナップショットの設定" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "%s に対するファイルシステムの存在" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr ", " #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "最終的なサイズは %s に依存します。" #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr " および " #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "選択した製品に合わせてサイズを自動計算します。" -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "ファイルシステムに対して正確なサイズを設定します。" #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "正確なサイズ" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "サイズの単位" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1625,57 +1645,57 @@ msgstr "" "きくなるように設定されます。" #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "最小" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "最小必須サイズ" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "最小サイズの単位" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "最大" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "最大要求サイズ" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "最大サイズの単位" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "自動" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "固定値" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "範囲" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "サイズを指定する必要があります" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "最小サイズを指定する必要があります" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "最大サイズは最小サイズより大きくなければなりません" @@ -2003,31 +2023,31 @@ msgstr "検索" msgid "Targets" msgstr "ターゲット" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "KiB" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "MiB" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "GiB" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "TiB" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "PiB" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." msgstr "ユーザを設定していません。" -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." @@ -2036,51 +2056,60 @@ msgstr "" "しておかなければならないことに注意してください。" #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "今すぐユーザを設定する" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "フルネーム" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "ユーザ名" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "破棄" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "ユーザアカウントの作成" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "ユーザアカウントの編集" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "ユーザのフルネーム" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "パスワードも編集する" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "ユーザの自動ログイン" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "自動ログイン" @@ -2182,6 +2211,13 @@ msgstr "ユーザ" msgid "Root authentication" msgstr "root の認証" +#~ msgid "" +#~ "Allows rolling back any change done to the system and restoring its " +#~ "previous state" +#~ msgstr "" +#~ "システムに実施された任意の変更を巻き戻し、以前の状態を復元できるようにしま" +#~ "す" + #~ msgid "Devices will not be modified until installation starts." #~ msgstr "インストールを開始するまではデバイスへの書き込みは行われません。" diff --git a/web/po/ka.po b/web/po/ka.po index f01517eac0..c5e8a088fb 100644 --- a/web/po/ka.po +++ b/web/po/ka.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" "PO-Revision-Date: 2024-02-17 05:42+0000\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian TPM can verify the integrity of the " @@ -1262,27 +1262,55 @@ msgid "" "first run." msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +#, fuzzy +msgid "Use Btrfs Snapshots" +msgstr "სწრაფი ასლებით" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:239 msgid "Change encryption settings" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "დაშიფვრის პარამეტრები" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "დაშიფვრის გამოყენება" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "მორგება" +#: src/components/storage/ProposalSettingsSection.jsx:330 +#, fuzzy +msgid "Transactional system" +msgstr "ტრანზაქციული" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "" @@ -1328,7 +1356,7 @@ msgstr "" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "ზომა" @@ -1479,9 +1507,6 @@ msgstr "დაშიფრულია" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "სწრაფი ასლებით" @@ -1495,8 +1520,8 @@ msgid "Edit file system" msgstr "" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "მიმაგრების წერტილი" @@ -1508,77 +1533,70 @@ msgstr "" msgid "Select a value" msgstr "" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "" -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" msgstr "" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr ", " #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "" #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr " და " #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "" -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "" #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "ზუსტი ზომა" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "ზომის ერთეული" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1586,57 +1604,57 @@ msgid "" msgstr "" #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "მინიმუმი" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "მაქსიმუმი" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "ავტო" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "ფიქსირებული" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "დიაპაზონი" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "" @@ -1959,82 +1977,91 @@ msgstr "აღმოაჩინეთ" msgid "Targets" msgstr "სამიზნეები" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "კიბ" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "მიბ" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "გიბ" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "ტიბ" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "პიბ" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." msgstr "" -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." msgstr "" #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "სრული სახელი" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "მომხმარებლის სახელი" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "გაუქმება" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "მომხმარებლის ანგარიშის შექმნა" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "მომხმარებლის ანგარიშის ჩასწორება" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "მომხმარებლის ავტოშესვლა" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "ავტომატური შესვლა" diff --git a/web/po/mk.po b/web/po/mk.po index 862b488ff9..c2b9071792 100644 --- a/web/po/mk.po +++ b/web/po/mk.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" "PO-Revision-Date: 2023-12-31 20:39+0000\n" "Last-Translator: Kristijan Fremen Velkovski \n" "Language-Team: Macedonian TPM can verify the integrity of the " @@ -1266,27 +1267,53 @@ msgid "" "first run." msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +msgid "Use Btrfs Snapshots" +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:239 msgid "Change encryption settings" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "" +#: src/components/storage/ProposalSettingsSection.jsx:330 +msgid "Transactional system" +msgstr "" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "" @@ -1330,7 +1357,7 @@ msgstr "" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "" @@ -1478,9 +1505,6 @@ msgstr "" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "" @@ -1494,8 +1518,8 @@ msgid "Edit file system" msgstr "" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "" @@ -1507,77 +1531,70 @@ msgstr "" msgid "Select a value" msgstr "" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "" -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" msgstr "" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr "" #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "" #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr "" #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "" -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "" #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1585,57 +1602,57 @@ msgid "" msgstr "" #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "" @@ -1958,82 +1975,91 @@ msgstr "" msgid "Targets" msgstr "" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." msgstr "" -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." msgstr "" #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "" diff --git a/web/po/nl.po b/web/po/nl.po index 838c726062..66740ce157 100644 --- a/web/po/nl.po +++ b/web/po/nl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" "PO-Revision-Date: 2023-12-31 20:39+0000\n" "Last-Translator: anonymous \n" "Language-Team: Dutch TPM can verify the integrity of the " @@ -1316,28 +1317,56 @@ msgid "" "first run." msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +#, fuzzy +msgid "Use Btrfs Snapshots" +msgstr "met snapshots" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:239 #, fuzzy msgid "Change encryption settings" msgstr "Encryptie instellingen" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "Encryptie instellingen" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "Gebruik encryptie" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "Instellingen" +#: src/components/storage/ProposalSettingsSection.jsx:330 +#, fuzzy +msgid "Transactional system" +msgstr "Voer een actie uit" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "" @@ -1384,7 +1413,7 @@ msgstr "" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "Grootte" @@ -1535,9 +1564,6 @@ msgstr "versleuteld" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "met snapshots" @@ -1552,8 +1578,8 @@ msgid "Edit file system" msgstr "Wijzig bestandssysteem" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "Koppelpunt" @@ -1566,78 +1592,71 @@ msgstr "Tabel met koppelpunten" msgid "Select a value" msgstr "taal" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "" -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 #, fuzzy msgid "More info for file system types" msgstr "Bestandssysteem type" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "Bestandssysteem type" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "de configuratie van snapshots" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "de aanwezigheid van het bestandssysteem voor %s" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr ", " #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "De uiteindelijke grootte hangt af van %s." #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr " en " #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "Automatisch berekend aan de hand van het geselecteerde product." -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "Exacte grootte voor het bestandssysteem." #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "Exacte grootte" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "Grootte eenheid" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1648,57 +1667,57 @@ msgstr "" "geen maximum is gegeven dan zal het bestandssysteem zo groot mogelijk zijn." #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "Minimum" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "Minimum gewenste grootte" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "Eenheid voor gewenste grootte" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "Maximum" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "Maximaal gewenste grootte" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "Eenheid voor maximale grootte" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "Auto" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "Vast" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "Reikwijdte" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "Een grootheids waarde is nodig" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "Minimum grootte is vereist" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "Maximum moet groter zijn dan het minimum" @@ -2028,32 +2047,32 @@ msgstr "Detecteer" msgid "Targets" msgstr "Doelen" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "KiB" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "MiB" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "GiB" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "TiB" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "PiB" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 #, fuzzy msgid "No user defined yet." msgstr "Nog geen gebruiker gedefinieerd" -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." @@ -2062,51 +2081,60 @@ msgstr "" "het systeem in te kunnen loggen." #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "Definieer nu een gebruiker" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "Volledige naam" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "Gebruikersnaam" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "Niet opslaan" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "Maak gebruikersaccount" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "Wijziging gebruikersaccount" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "Volledige naam gebruiker" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "Wijzig ook het wachtwoord" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "gebruiker autologin" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "Auto-login" diff --git a/web/po/pt_BR.po b/web/po/pt_BR.po index 02502adb73..efa789e203 100644 --- a/web/po/pt_BR.po +++ b/web/po/pt_BR.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" "PO-Revision-Date: 2023-12-31 20:39+0000\n" "Last-Translator: anonymous \n" "Language-Team: Portuguese (Brazil) TPM can verify the integrity of the " @@ -1293,28 +1294,56 @@ msgid "" "first run." msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +#, fuzzy +msgid "Use Btrfs Snapshots" +msgstr "com instantâneos" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:239 #, fuzzy msgid "Change encryption settings" msgstr "Usar criptografia" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "Usar criptografia" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "Configurações" +#: src/components/storage/ProposalSettingsSection.jsx:330 +#, fuzzy +msgid "Transactional system" +msgstr "transacional" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "" @@ -1358,7 +1387,7 @@ msgstr "" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "Tamanho" @@ -1509,9 +1538,6 @@ msgstr "criptografado" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "com instantâneos" @@ -1525,8 +1551,8 @@ msgid "Edit file system" msgstr "Editar sistema de arquivos" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "Ponto de montagem" @@ -1539,78 +1565,71 @@ msgstr "Tabela com pontos de montagem" msgid "Select a value" msgstr "Selecionar idioma" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "" -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 #, fuzzy msgid "More info for file system types" msgstr "Tipo de sistema de arquivos" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "Tipo de sistema de arquivos" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "a configuração de instantâneos" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "a presença do sistema de arquivos para %s" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr ", " #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "O tamanho final depende de %s." #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr " e " #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "Tamanho calculado automaticamente de acordo com o produto selecionado." -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "Tamanho exato do sistema de arquivos." #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1618,57 +1637,57 @@ msgid "" msgstr "" #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "Mínimo" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "Máximo" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "Automático" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "Fixo" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "Intervalo" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "" @@ -1995,83 +2014,92 @@ msgstr "Discover" msgid "Targets" msgstr "Destinos" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "KiB" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "MiB" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "GiB" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "TiB" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "PiB" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 #, fuzzy msgid "No user defined yet." msgstr "Nenhum usuário definido ainda" -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." msgstr "" #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "Nome completo" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "Nome de usuário" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "Descartar" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "Criar conta de usuário" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "" diff --git a/web/po/ru.po b/web/po/ru.po index e525a627cf..4b40ce460c 100644 --- a/web/po/ru.po +++ b/web/po/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" "PO-Revision-Date: 2023-12-31 20:39+0000\n" "Last-Translator: Milachew \n" "Language-Team: Russian TPM can verify the integrity of the " @@ -1307,27 +1308,53 @@ msgid "" "first run." msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +msgid "Use Btrfs Snapshots" +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:239 msgid "Change encryption settings" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "" +#: src/components/storage/ProposalSettingsSection.jsx:330 +msgid "Transactional system" +msgstr "" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "" @@ -1371,7 +1398,7 @@ msgstr "" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "" @@ -1521,9 +1548,6 @@ msgstr "" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "" @@ -1537,8 +1561,8 @@ msgid "Edit file system" msgstr "" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "" @@ -1551,77 +1575,70 @@ msgstr "" msgid "Select a value" msgstr "Язык" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "" -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" msgstr "" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr "" #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "" #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr "" #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "" -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "" #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1629,57 +1646,57 @@ msgid "" msgstr "" #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "" @@ -2004,82 +2021,91 @@ msgstr "" msgid "Targets" msgstr "" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." msgstr "" -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." msgstr "" #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "" diff --git a/web/po/sv.po b/web/po/sv.po index 4cc1e63cdb..ccba7c776b 100644 --- a/web/po/sv.po +++ b/web/po/sv.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" -"PO-Revision-Date: 2024-02-21 12:42+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" +"PO-Revision-Date: 2024-02-29 07:42+0000\n" "Last-Translator: Luna Jernberg \n" "Language-Team: Swedish \n" @@ -42,15 +42,15 @@ msgstr "Om Agama" #. TRANSLATORS: content of the "About" popup (1/2) #: src/components/core/About.jsx:53 msgid "" -"Agama is an experimental installer for (open)SUSE systems. It still under " +"Agama is an experimental installer for (open)SUSE systems. It is still under " "development so, please, do not use it in production environments. If you " -"want to give it a try, we recommend to use a virtual machine to prevent any " +"want to give it a try, we recommend using a virtual machine to prevent any " "possible data loss." msgstr "" -"Agama är ett experimentellt installationsprogram för (open)SUSE system. Det " -"är fortfarande under utveckling så, snälla, använd det inte i " -"produktionsmiljöer. Om du vill prova att använda det så rekommenderar vi att " -"du använder en virtuell maskin för att förhindra eventuell dataförlust." +"Agama är en experimentellt installationsprogram för (open) SUSE-system. Det " +"är fortfarande under utveckling, så använd det inte i produktionsmiljöer. Om " +"du vill ge det ett försök rekommenderar vi att du använder en virtuell " +"maskin för att förhindra eventuell dataförlust." #. TRANSLATORS: content of the "About" popup (2/2) #. %s is replaced by the project URL @@ -155,7 +155,7 @@ msgstr "" #: src/components/product/ProductPage.jsx:207 #: src/components/storage/ProposalDeviceSection.jsx:169 #: src/components/storage/ProposalDeviceSection.jsx:364 -#: src/components/storage/ProposalSettingsSection.jsx:211 +#: src/components/storage/ProposalSettingsSection.jsx:275 #: src/components/storage/ProposalVolumes.jsx:148 #: src/components/storage/ProposalVolumes.jsx:283 #: src/components/storage/ZFCPPage.jsx:511 @@ -558,7 +558,7 @@ msgstr "IP adresser" #: src/components/storage/ProposalVolumes.jsx:234 #: src/components/storage/iscsi/InitiatorPresenter.jsx:49 #: src/components/storage/iscsi/NodesPresenter.jsx:73 -#: src/components/users/FirstUser.jsx:174 +#: src/components/users/FirstUser.jsx:208 msgid "Edit" msgstr "Redigera" @@ -706,7 +706,7 @@ msgstr "WPA & WPA2 Personal" #: src/components/storage/ZFCPDiskForm.jsx:112 #: src/components/storage/iscsi/DiscoverForm.jsx:108 #: src/components/storage/iscsi/LoginForm.jsx:72 -#: src/components/users/FirstUser.jsx:198 +#: src/components/users/FirstUser.jsx:238 msgid "Something went wrong" msgstr "Något gick fel" @@ -1190,15 +1190,13 @@ msgstr "Planerade åtgärder" #. TRANSLATORS: The storage "Planned Actions" section's description #: src/components/storage/ProposalActionsSection.jsx:126 -#, fuzzy msgid "Actions to create the file systems and to ensure the new system boots." msgstr "" -"Åtgärder för att skapa filsystemen och för att säkerställa att systemet " -"startar." +"Åtgärder för att skapa filsystemen och se till att det nya systemet startar." #: src/components/storage/ProposalDeviceSection.jsx:135 msgid "Waiting for information about selected device" -msgstr "" +msgstr "Väntar på information om den valda enheten" #: src/components/storage/ProposalDeviceSection.jsx:138 msgid "Select the device for installing the system." @@ -1241,7 +1239,7 @@ msgstr "LVM-inställningar" #: src/components/storage/ProposalDeviceSection.jsx:333 msgid "Waiting for information about LVM" -msgstr "" +msgstr "Väntar på information om LVM" #: src/components/storage/ProposalDeviceSection.jsx:339 msgid "Use logical volume management (LVM)" @@ -1258,11 +1256,12 @@ msgid "" "Select the main disk or LVM " "Volume Group for installation." msgstr "" +"Välj huvuddisk eller LVM " +"volymgrupp för installation." #: src/components/storage/ProposalFileSystemsSection.jsx:70 -#, fuzzy msgid "File systems" -msgstr "Filsystem typ" +msgstr "Filsystem" #: src/components/storage/ProposalPageMenu.jsx:40 msgid "Manage and format" @@ -1287,7 +1286,7 @@ msgstr "iSCSI" #. TRANSLATORS: The word 'directly' is key here. For example, booting to the installer media and then choosing #. 'Boot from Hard Disk' from there will not work. Keep it sort (this is a hint in a form) but keep it clear. #. Do not translate 'abbr' and 'title', they are part of the HTML markup. -#: src/components/storage/ProposalSettingsSection.jsx:86 +#: src/components/storage/ProposalSettingsSection.jsx:89 msgid "" "The password will not be needed to boot and access the data if the TPM can verify the integrity of the " @@ -1299,27 +1298,57 @@ msgstr "" "integritet. TPM-försegling kräver att det nya systemet startas upp direkt " "vid första körningen." -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "Använd TPM för att dekryptera automatiskt vid varje uppstart" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" +"Använder Btrfs för rootfilsystemet, vilket gör det möjligt att starta upp en " +"tidigare version av systemet före konfigurationsändringar eller " +"programvaruuppgraderingar." + +#: src/components/storage/ProposalSettingsSection.jsx:159 +msgid "Use Btrfs Snapshots" +msgstr "Använd Btrfs ögonblicksavbilder" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "Btrfs ögonblicksavbilder krävs för produkt." + +#: src/components/storage/ProposalSettingsSection.jsx:239 msgid "Change encryption settings" msgstr "Ändra krypteringsinställningar" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "Krypteringsinställningar" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "Använd kryptering" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "Inställningar" +#: src/components/storage/ProposalSettingsSection.jsx:330 +#, fuzzy +msgid "Transactional system" +msgstr "transaktionell" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "Radera nuvarande innehåll" @@ -1369,7 +1398,7 @@ msgstr "Nuvarande innehåll" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "Storlek" @@ -1461,6 +1490,8 @@ msgid "" "Allocating the file systems might need to find free space in the devices " "listed below. Choose how to do it." msgstr "" +"Att allokera filsystemen kan behöva hitta ledigt utrymme i enheterna som " +"anges nedan. Välj hur du vill göra det." #. TRANSLATORS: header for a list of items #: src/components/storage/ProposalVolumes.jsx:59 @@ -1517,9 +1548,6 @@ msgstr "krypterad" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "med ögonblicksavbilder" @@ -1533,8 +1561,8 @@ msgid "Edit file system" msgstr "Redigera filsystem" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "Monteringspunkt" @@ -1546,80 +1574,71 @@ msgstr "Tabell med monteringspunkter" msgid "Select a value" msgstr "Välj ett värde" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" -"Tillåter att alla ändringar som gjorts i systemet rullas tillbaka och det " -"återställs till dess tidigare tillstånd" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "" "Alternativen för filsystemstypen beror på produkten och monteringspunkten." -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" msgstr "Mer information om filsystemtyper" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "Filsystem typ" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "konfigurationen av ögonblicksavbilder" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "närvaron av filsystemet för %s" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr ", " #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "Den slutliga storleken beror på %s." #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr " och " #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "Automatiskt beräknad storlek enligt vald produkt." -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "Exakt storlek för filsystemet." #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "Exakt storlek" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "Storleksenhet" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1630,57 +1649,57 @@ msgstr "" "filsystemet att vara så stort som möjligt." #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "Minst" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "Minsta önskade storlek" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "Enhet för minsta storlek" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "Maximal" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "Maximal önskad storlek" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "Enhet för maximal storlek" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "Auto" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "Fast" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "Räckvidd" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "Ett storleksvärde krävs" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "Minsta storlek krävs" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "Maximalt måste vara större än minimalt" @@ -2007,31 +2026,31 @@ msgstr "Upptäck" msgid "Targets" msgstr "Mål" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "KiB" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "MiB" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "GiB" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "TiB" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "PiB" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." msgstr "Ingen användare definierad ännu." -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." @@ -2040,51 +2059,60 @@ msgstr "" "installerar systemet för att kunna logga in till det." #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "Definera en användare nu" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "Fullständigt namn" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "Användarnamn" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "Kasta bort" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "Skapa anändarkonto" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "Redigera användarkonto" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "Användarens fullständiga namn" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "Redigera lösenord också" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "användare automatisk inloggning" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "Automatisk-inloggning" @@ -2188,6 +2216,13 @@ msgstr "Användare" msgid "Root authentication" msgstr "Rootautentisering" +#~ msgid "" +#~ "Allows rolling back any change done to the system and restoring its " +#~ "previous state" +#~ msgstr "" +#~ "Tillåter att alla ändringar som gjorts i systemet rullas tillbaka och det " +#~ "återställs till dess tidigare tillstånd" + #~ msgid "Devices will not be modified until installation starts." #~ msgstr "Enheter kommer inte att modifieras förrän installationen startar." diff --git a/web/po/uk.po b/web/po/uk.po index 6c640512e5..7325ccf845 100644 --- a/web/po/uk.po +++ b/web/po/uk.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 02:07+0000\n" +"POT-Creation-Date: 2024-03-03 02:07+0000\n" "PO-Revision-Date: 2023-12-31 20:39+0000\n" "Last-Translator: Milachew \n" "Language-Team: Ukrainian TPM can verify the integrity of the " @@ -1266,27 +1266,53 @@ msgid "" "first run." msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:104 +#: src/components/storage/ProposalSettingsSection.jsx:107 msgid "Use the TPM to decrypt automatically on each boot" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:175 +#: src/components/storage/ProposalSettingsSection.jsx:152 +msgid "" +"Uses Btrfs for the root file system allowing to boot to a previous version " +"of the system after configuration changes or software upgrades." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:159 +msgid "Use Btrfs Snapshots" +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:173 +msgid "Btrfs snapshots required by product." +msgstr "" + +#: src/components/storage/ProposalSettingsSection.jsx:239 msgid "Change encryption settings" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:180 -#: src/components/storage/ProposalSettingsSection.jsx:201 +#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:265 msgid "Encryption settings" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:194 +#: src/components/storage/ProposalSettingsSection.jsx:258 msgid "Use encryption" msgstr "" -#: src/components/storage/ProposalSettingsSection.jsx:244 +#: src/components/storage/ProposalSettingsSection.jsx:325 msgid "Settings" msgstr "" +#: src/components/storage/ProposalSettingsSection.jsx:330 +msgid "Transactional system" +msgstr "" + +#. TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) +#: src/components/storage/ProposalSettingsSection.jsx:333 +#, c-format +msgid "" +"%s is an immutable system with atomic updates using a read-only Btrfs root " +"file system." +msgstr "" + #: src/components/storage/ProposalSpacePolicySection.jsx:50 msgid "Delete current content" msgstr "" @@ -1330,7 +1356,7 @@ msgstr "" #: src/components/storage/ProposalSpacePolicySection.jsx:74 #: src/components/storage/ProposalVolumes.jsx:309 -#: src/components/storage/VolumeForm.jsx:795 +#: src/components/storage/VolumeForm.jsx:741 msgid "Size" msgstr "" @@ -1478,9 +1504,6 @@ msgstr "" #. TRANSLATORS: filesystem flag, it allows creating snapshots #: src/components/storage/ProposalVolumes.jsx:218 -#: src/components/storage/VolumeForm.jsx:172 -#: src/components/storage/VolumeForm.jsx:205 -#, c-format msgid "with snapshots" msgstr "" @@ -1494,8 +1517,8 @@ msgid "Edit file system" msgstr "" #: src/components/storage/ProposalVolumes.jsx:307 -#: src/components/storage/VolumeForm.jsx:780 -#: src/components/storage/VolumeForm.jsx:785 +#: src/components/storage/VolumeForm.jsx:726 +#: src/components/storage/VolumeForm.jsx:731 msgid "Mount point" msgstr "" @@ -1507,77 +1530,70 @@ msgstr "" msgid "Select a value" msgstr "" -#. TRANSLATORS: description of Btrfs snapshots feature. -#: src/components/storage/VolumeForm.jsx:212 -msgid "" -"Allows rolling back any change done to the system and restoring its previous " -"state" -msgstr "" - #. TRANSLATORS: info about possible file system types. -#: src/components/storage/VolumeForm.jsx:309 +#: src/components/storage/VolumeForm.jsx:255 msgid "" "The options for the file system type depends on the product and the mount " "point." msgstr "" -#: src/components/storage/VolumeForm.jsx:315 +#: src/components/storage/VolumeForm.jsx:261 msgid "More info for file system types" msgstr "" #. TRANSLATORS: label for the file system selector. -#: src/components/storage/VolumeForm.jsx:326 +#: src/components/storage/VolumeForm.jsx:272 msgid "File system type" msgstr "" #. TRANSLATORS: item which affects the final computed partition size -#: src/components/storage/VolumeForm.jsx:358 +#: src/components/storage/VolumeForm.jsx:304 msgid "the configuration of snapshots" msgstr "" #. TRANSLATORS: item which affects the final computed partition size #. %s is replaced by a list of mount points like "/home, /boot" -#: src/components/storage/VolumeForm.jsx:363 +#: src/components/storage/VolumeForm.jsx:309 #, c-format msgid "the presence of the file system for %s" msgstr "" #. TRANSLATORS: conjunction for merging two list items -#: src/components/storage/VolumeForm.jsx:365 +#: src/components/storage/VolumeForm.jsx:311 msgid ", " msgstr "" #. TRANSLATORS: the %s is replaced by the items which affect the computed size -#: src/components/storage/VolumeForm.jsx:368 +#: src/components/storage/VolumeForm.jsx:314 #, c-format msgid "The final size depends on %s." msgstr "" #. TRANSLATORS: conjunction for merging two texts -#: src/components/storage/VolumeForm.jsx:370 +#: src/components/storage/VolumeForm.jsx:316 msgid " and " msgstr "" #. TRANSLATORS: the partition size is automatically computed -#: src/components/storage/VolumeForm.jsx:375 +#: src/components/storage/VolumeForm.jsx:321 msgid "Automatically calculated size according to the selected product." msgstr "" -#: src/components/storage/VolumeForm.jsx:395 +#: src/components/storage/VolumeForm.jsx:341 msgid "Exact size for the file system." msgstr "" #. TRANSLATORS: requested partition size -#: src/components/storage/VolumeForm.jsx:407 +#: src/components/storage/VolumeForm.jsx:353 msgid "Exact size" msgstr "" #. TRANSLATORS: units selector (like KiB, MiB, GiB...) -#: src/components/storage/VolumeForm.jsx:422 +#: src/components/storage/VolumeForm.jsx:368 msgid "Size unit" msgstr "" -#: src/components/storage/VolumeForm.jsx:450 +#: src/components/storage/VolumeForm.jsx:396 msgid "" "Limits for the file system size. The final size will be a value between the " "given minimum and maximum. If no maximum is given then the file system will " @@ -1585,57 +1601,57 @@ msgid "" msgstr "" #. TRANSLATORS: the minimal partition size -#: src/components/storage/VolumeForm.jsx:457 +#: src/components/storage/VolumeForm.jsx:403 msgid "Minimum" msgstr "" #. TRANSLATORS: the minium partition size -#: src/components/storage/VolumeForm.jsx:467 +#: src/components/storage/VolumeForm.jsx:413 msgid "Minimum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:476 +#: src/components/storage/VolumeForm.jsx:422 msgid "Unit for the minimum size" msgstr "" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:487 +#: src/components/storage/VolumeForm.jsx:433 msgid "Maximum" msgstr "" #. TRANSLATORS: the maximum partition size -#: src/components/storage/VolumeForm.jsx:498 +#: src/components/storage/VolumeForm.jsx:444 msgid "Maximum desired size" msgstr "" -#: src/components/storage/VolumeForm.jsx:506 +#: src/components/storage/VolumeForm.jsx:452 msgid "Unit for the maximum size" msgstr "" #. TRANSLATORS: radio button label, fully automatically computed partition size, no user input -#: src/components/storage/VolumeForm.jsx:523 +#: src/components/storage/VolumeForm.jsx:469 msgid "Auto" msgstr "" #. TRANSLATORS: radio button label, exact partition size requested by user -#: src/components/storage/VolumeForm.jsx:525 +#: src/components/storage/VolumeForm.jsx:471 msgid "Fixed" msgstr "" #. TRANSLATORS: radio button label, automatically computed partition size within the user provided min and max limits -#: src/components/storage/VolumeForm.jsx:527 +#: src/components/storage/VolumeForm.jsx:473 msgid "Range" msgstr "" -#: src/components/storage/VolumeForm.jsx:735 +#: src/components/storage/VolumeForm.jsx:681 msgid "A size value is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:740 +#: src/components/storage/VolumeForm.jsx:686 msgid "Minimum size is required" msgstr "" -#: src/components/storage/VolumeForm.jsx:744 +#: src/components/storage/VolumeForm.jsx:690 msgid "Maximum must be greater than minimum" msgstr "" @@ -1958,82 +1974,91 @@ msgstr "" msgid "Targets" msgstr "" -#: src/components/storage/utils.js:44 +#: src/components/storage/utils.js:49 msgid "KiB" msgstr "" -#: src/components/storage/utils.js:45 +#: src/components/storage/utils.js:50 msgid "MiB" msgstr "" -#: src/components/storage/utils.js:46 +#: src/components/storage/utils.js:51 msgid "GiB" msgstr "" -#: src/components/storage/utils.js:47 +#: src/components/storage/utils.js:52 msgid "TiB" msgstr "" -#: src/components/storage/utils.js:48 +#: src/components/storage/utils.js:53 msgid "PiB" msgstr "" -#: src/components/users/FirstUser.jsx:44 +#: src/components/users/FirstUser.jsx:50 msgid "No user defined yet." msgstr "" -#: src/components/users/FirstUser.jsx:47 +#: src/components/users/FirstUser.jsx:53 msgid "" "Please, be aware that a user must be defined before installing the system to " "be able to log into it." msgstr "" #. TRANSLATORS: push button label -#: src/components/users/FirstUser.jsx:51 +#: src/components/users/FirstUser.jsx:57 msgid "Define a user now" msgstr "" -#: src/components/users/FirstUser.jsx:61 src/components/users/FirstUser.jsx:202 +#: src/components/users/FirstUser.jsx:67 src/components/users/FirstUser.jsx:242 msgid "Full name" msgstr "" -#: src/components/users/FirstUser.jsx:62 src/components/users/FirstUser.jsx:213 -#: src/components/users/FirstUser.jsx:217 -#: src/components/users/FirstUser.jsx:219 +#: src/components/users/FirstUser.jsx:68 src/components/users/FirstUser.jsx:256 +#: src/components/users/FirstUser.jsx:264 +#: src/components/users/FirstUser.jsx:266 msgid "Username" msgstr "" -#: src/components/users/FirstUser.jsx:178 +#: src/components/users/FirstUser.jsx:88 +msgid "Username suggestion dropdown" +msgstr "" + +#. TRANSLATORS: dropdown username suggestions +#: src/components/users/FirstUser.jsx:102 +msgid "Use suggested username" +msgstr "" + +#: src/components/users/FirstUser.jsx:212 #: src/components/users/RootAuthMethods.jsx:99 #: src/components/users/RootAuthMethods.jsx:111 msgid "Discard" msgstr "" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Create user account" msgstr "" -#: src/components/users/FirstUser.jsx:195 +#: src/components/users/FirstUser.jsx:235 msgid "Edit user account" msgstr "" -#: src/components/users/FirstUser.jsx:206 -#: src/components/users/FirstUser.jsx:208 +#: src/components/users/FirstUser.jsx:246 +#: src/components/users/FirstUser.jsx:248 msgid "User full name" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:227 -#: src/components/users/FirstUser.jsx:231 +#: src/components/users/FirstUser.jsx:284 +#: src/components/users/FirstUser.jsx:288 msgid "Edit password too" msgstr "" -#: src/components/users/FirstUser.jsx:244 +#: src/components/users/FirstUser.jsx:301 msgid "user autologin" msgstr "" #. TRANSLATORS: check box label -#: src/components/users/FirstUser.jsx:248 +#: src/components/users/FirstUser.jsx:305 msgid "Auto-login" msgstr "" diff --git a/web/src/manifest.json b/web/src/manifest.json index cd6a50b9a1..8450b73d9d 100644 --- a/web/src/manifest.json +++ b/web/src/manifest.json @@ -14,7 +14,6 @@ "fr-fr": "Français", "ja-jp": "日本語", "es-es": "Español", - "sv-se": "Svenska", - "nl-nl": "Nederlands" + "sv-se": "Svenska" } } \ No newline at end of file From 6340803a7b6be2d8d02dbfb2e0067cfdf4f7e3cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 4 Mar 2024 13:39:53 +0000 Subject: [PATCH 38/53] doc: update the OpenAPI documentation --- rust/Cargo.lock | 1 + rust/agama-lib/Cargo.toml | 1 + rust/agama-lib/src/product/client.rs | 2 +- rust/agama-lib/src/software/client.rs | 2 +- rust/agama-server/src/software/web.rs | 41 ++++++++++++++++++++------- rust/agama-server/src/web/docs.rs | 18 ++++++++++-- 6 files changed, 50 insertions(+), 15 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 8bef766f82..cc576c6eaf 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -112,6 +112,7 @@ dependencies = [ "tokio", "tokio-stream", "url", + "utoipa", "zbus", ] diff --git a/rust/agama-lib/Cargo.toml b/rust/agama-lib/Cargo.toml index 5ef8166609..40702e2fde 100644 --- a/rust/agama-lib/Cargo.toml +++ b/rust/agama-lib/Cargo.toml @@ -21,4 +21,5 @@ thiserror = "1.0.39" tokio = { version = "1.33.0", features = ["macros", "rt-multi-thread"] } tokio-stream = "0.1.14" url = "2.5.0" +utoipa = "4.2.0" zbus = { version = "3", default-features = false, features = ["tokio"] } diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index ba7934419e..2f4e18f432 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -8,7 +8,7 @@ use zbus::Connection; use super::proxies::RegistrationProxy; /// Represents a software product -#[derive(Default, Debug, Serialize)] +#[derive(Default, Debug, Serialize, utoipa::ToSchema)] pub struct Product { /// Product ID (eg., "ALP", "Tumbleweed", etc.) pub id: String, diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index d3a49d4196..401a9b7480 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use zbus::Connection; /// Represents a software product -#[derive(Debug, Serialize)] +#[derive(Debug, Serialize, utoipa::ToSchema)] pub struct Pattern { /// Pattern ID (eg., "aaa_base", "gnome") pub id: String, diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 3168a5927c..1d2f208288 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -1,6 +1,9 @@ //! This module implements the web API for the software module. //! -//! It is a wrapper around the YaST D-Bus API. +//! The module offers two public functions: +//! +//! * `software_service` which returns the Axum service. +//! * `software_stream` which offers an stream that emits the software events coming from D-Bus. use crate::web::{Event, EventsSender}; use agama_lib::{ @@ -51,6 +54,9 @@ impl IntoResponse for SoftwareError { } } +/// Returns an stream that emits software related events coming from D-Bus. +/// +/// * `connection`: D-Bus connection to listen for events. pub async fn software_stream(connection: zbus::Connection) -> impl Stream { StreamExt::merge( product_changed_stream(connection.clone()).await, @@ -87,8 +93,6 @@ async fn patterns_changed_stream(connection: zbus::Connection) -> impl Stream Router { let connection = connection().await.unwrap(); let product = ProductClient::new(connection.clone()).await.unwrap(); @@ -104,6 +108,9 @@ pub async fn software_service(_events: EventsSender) -> Router { /// Returns the list of available products. /// /// * `state`: service state. +#[utoipa::path(get, path = "/software/products", responses( + (status = 200, description = "List of known products") +))] async fn products<'a>( State(state): State>, ) -> Result>, SoftwareError> { @@ -114,8 +121,8 @@ async fn products<'a>( /// Represents a pattern. /// /// It augments the information coming from the D-Bus client. -#[derive(Serialize)] -pub struct PatternItem { +#[derive(Serialize, utoipa::ToSchema)] +pub struct PatternEntry { #[serde(flatten)] pattern: Pattern, status: PatternStatus, @@ -138,9 +145,15 @@ impl From for PatternStatus { } } +/// Returns the list of software patterns. +/// +/// * `state`: service state. +#[utoipa::path(get, path = "/software/patterns", responses( + (status = 200, description = "List of known software patterns") +))] async fn patterns<'a>( State(state): State>, -) -> Result>, SoftwareError> { +) -> Result>, SoftwareError> { let patterns = state.software.patterns(true).await?; let selected = state.software.selected_patterns().await?; let items = patterns @@ -150,7 +163,7 @@ async fn patterns<'a>( .get(&pattern.id) .map(|r| (*r).into()) .unwrap_or(PatternStatus::Available); - PatternItem { pattern, status } + PatternEntry { pattern, status } }) .collect(); @@ -161,8 +174,11 @@ async fn patterns<'a>( /// /// * `state`: service state. /// * `config`: software configuration. -async fn set_config<'a>( - State(state): State>, +#[utoipa::path(put, path = "/software/config", responses( + (status = 200, description = "Set the software configuration") +))] +async fn set_config( + State(state): State>, Json(config): Json, ) -> Result<(), SoftwareError> { if let Some(product) = config.product { @@ -179,8 +195,11 @@ async fn set_config<'a>( /// Returns the software configuration /// /// * `state` : service state. -async fn get_config<'a>( - State(state): State>, +#[utoipa::path(get, path = "/software/config", responses( + (status = 200, description = "Software configuration") +))] +async fn get_config( + State(state): State>, ) -> Result, SoftwareError> { let product = state.product.product().await?; let patterns = state.software.user_selected_patterns().await?; diff --git a/rust/agama-server/src/web/docs.rs b/rust/agama-server/src/web/docs.rs index 58a1de6aed..d7b46459ae 100644 --- a/rust/agama-server/src/web/docs.rs +++ b/rust/agama-server/src/web/docs.rs @@ -3,13 +3,27 @@ use utoipa::OpenApi; #[derive(OpenApi)] #[openapi( info(description = "Agama web API description"), - paths(super::http::ping, crate::l10n::web::locales), + paths( + super::http::ping, + crate::software::web::patterns, + crate::l10n::web::get_config, + crate::l10n::web::keymaps, + crate::l10n::web::locales, + crate::l10n::web::set_config, + crate::l10n::web::timezones, + crate::software::web::get_config, + crate::software::web::set_config, + crate::software::web::patterns, + ), components( schemas(super::http::PingResponse), schemas(crate::l10n::LocaleEntry), schemas(crate::l10n::web::LocaleConfig), schemas(crate::l10n::Keymap), - schemas(crate::l10n::TimezoneEntry) + schemas(crate::l10n::TimezoneEntry), + schemas(agama_lib::software::Pattern), + schemas(agama_lib::product::Product), + schemas(crate::software::web::PatternEntry) ) )] pub struct ApiDoc; From 0e0b0e3e8c8fdbef0a44743b8a501fd3edc532d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 4 Mar 2024 14:39:37 +0000 Subject: [PATCH 39/53] rust: refactor the CLI arguments handling --- rust/agama-server/src/agama-web-server.rs | 37 +++++++++++++++-------- rust/agama-server/src/software/web.rs | 24 +++++++-------- rust/agama-server/src/web.rs | 8 +++-- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/rust/agama-server/src/agama-web-server.rs b/rust/agama-server/src/agama-web-server.rs index 56343bfdf5..a0c29ce5d0 100644 --- a/rust/agama-server/src/agama-web-server.rs +++ b/rust/agama-server/src/agama-web-server.rs @@ -4,7 +4,8 @@ use agama_dbus_server::{ l10n::helpers, web::{self, run_monitor}, }; -use clap::{Parser, Subcommand}; +use agama_lib::connection_to; +use clap::{Args, Parser, Subcommand}; use tokio::sync::broadcast::channel; use tracing_subscriber::prelude::*; use utoipa::OpenApi; @@ -12,16 +13,22 @@ use utoipa::OpenApi; #[derive(Subcommand, Debug)] enum Commands { /// Start the API server. - Serve { - // Address to listen on (":::3000" listens for both IPv6 and IPv4 - // connections unless manually disabled in /proc/sys/net/ipv6/bindv6only) - #[arg(long, default_value = ":::3000")] - address: String, - }, + Serve(ServeArgs), /// Display the API documentation in OpenAPI format. Openapi, } +#[derive(Debug, Args)] +pub struct ServeArgs { + // Address to listen on (":::3000" listens for both IPv6 and IPv4 + // connections unless manually disabled in /proc/sys/net/ipv6/bindv6only) + #[arg(long, default_value = ":::3000")] + address: String, + // Agama D-Bus address + #[arg(long, default_value = "unix:path=/run/agama/bus")] + dbus_address: String, +} + #[derive(Parser, Debug)] #[command( version, @@ -33,22 +40,26 @@ struct Cli { } /// Start serving the API. -async fn serve_command(address: &str) -> anyhow::Result<()> { +/// +/// `args`: command-line arguments. +async fn serve_command(args: ServeArgs) -> anyhow::Result<()> { let journald = tracing_journald::layer().expect("could not connect to journald"); tracing_subscriber::registry().with(journald).init(); - let listener = tokio::net::TcpListener::bind(address) + let listener = tokio::net::TcpListener::bind(&args.address) .await - .unwrap_or_else(|_| panic!("could not listen on {}", address)); + .unwrap_or_else(|_| panic!("could not listen on {}", &args.address)); let (tx, _) = channel(16); run_monitor(tx.clone()).await?; - let config = web::ServiceConfig::load().unwrap(); - let service = web::service(config, tx).await; + let config = web::ServiceConfig::load()?; + let dbus = connection_to(&args.dbus_address).await?; + let service = web::service(config, tx, dbus).await; axum::serve(listener, service) .await .expect("could not mount app on listener"); + Ok(()) } @@ -60,7 +71,7 @@ fn openapi_command() -> anyhow::Result<()> { async fn run_command(cli: Cli) -> anyhow::Result<()> { match cli.command { - Commands::Serve { address } => serve_command(&address).await, + Commands::Serve(args) => serve_command(args).await, Commands::Openapi => openapi_command(), } } diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 1d2f208288..becfd5bc2a 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -5,9 +5,8 @@ //! * `software_service` which returns the Axum service. //! * `software_stream` which offers an stream that emits the software events coming from D-Bus. -use crate::web::{Event, EventsSender}; +use crate::web::Event; use agama_lib::{ - connection, error::ServiceError, product::{Product, ProductClient}, software::{ @@ -57,15 +56,15 @@ impl IntoResponse for SoftwareError { /// Returns an stream that emits software related events coming from D-Bus. /// /// * `connection`: D-Bus connection to listen for events. -pub async fn software_stream(connection: zbus::Connection) -> impl Stream { +pub async fn software_stream(dbus: zbus::Connection) -> impl Stream { StreamExt::merge( - product_changed_stream(connection.clone()).await, - patterns_changed_stream(connection.clone()).await, + product_changed_stream(dbus.clone()).await, + patterns_changed_stream(dbus.clone()).await, ) } -async fn product_changed_stream(connection: zbus::Connection) -> impl Stream { - let proxy = SoftwareProductProxy::new(&connection).await.unwrap(); +async fn product_changed_stream(dbus: zbus::Connection) -> impl Stream { + let proxy = SoftwareProductProxy::new(&dbus).await.unwrap(); proxy .receive_selected_product_changed() .await @@ -78,8 +77,8 @@ async fn product_changed_stream(connection: zbus::Connection) -> impl Stream impl Stream { - let proxy = Software1Proxy::new(&connection).await.unwrap(); +async fn patterns_changed_stream(dbus: zbus::Connection) -> impl Stream { + let proxy = Software1Proxy::new(&dbus).await.unwrap(); proxy .receive_selected_patterns_changed() .await @@ -93,10 +92,9 @@ async fn patterns_changed_stream(connection: zbus::Connection) -> impl Stream Router { - let connection = connection().await.unwrap(); - let product = ProductClient::new(connection.clone()).await.unwrap(); - let software = SoftwareClient::new(connection).await.unwrap(); +pub async fn software_service(dbus: zbus::Connection) -> Router { + let product = ProductClient::new(dbus.clone()).await.unwrap(); + let software = SoftwareClient::new(dbus).await.unwrap(); let state = SoftwareState { product, software }; Router::new() .route("/products", get(products)) diff --git a/rust/agama-server/src/web.rs b/rust/agama-server/src/web.rs index 1b2da2e713..d789bb0034 100644 --- a/rust/agama-server/src/web.rs +++ b/rust/agama-server/src/web.rs @@ -31,10 +31,14 @@ use tokio_stream::StreamExt; /// /// * `config`: service configuration. /// * `events`: D-Bus connection. -pub async fn service(config: ServiceConfig, events: EventsSender) -> Router { +pub async fn service( + config: ServiceConfig, + events: EventsSender, + dbus: zbus::Connection, +) -> Router { MainServiceBuilder::new(events.clone()) .add_service("/l10n", l10n_service(events.clone())) - .add_service("/software", software_service(events).await) + .add_service("/software", software_service(dbus).await) .with_config(config) .build() } From 6e9d476e9a162a725114b9d4f2ce7b720d466488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 4 Mar 2024 14:39:47 +0000 Subject: [PATCH 40/53] rust: fix service tests --- rust/agama-server/tests/service.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/rust/agama-server/tests/service.rs b/rust/agama-server/tests/service.rs index 6179484be8..59157d3bce 100644 --- a/rust/agama-server/tests/service.rs +++ b/rust/agama-server/tests/service.rs @@ -11,19 +11,20 @@ use axum::{ routing::get, Router, }; -use common::body_to_string; +use common::{body_to_string, DBusServer}; use std::error::Error; use tokio::{sync::broadcast::channel, test}; use tower::ServiceExt; -fn build_service() -> Router { +async fn build_service() -> Router { let (tx, _) = channel(16); - service(ServiceConfig::default(), tx) + let server = DBusServer::new().start().await.unwrap(); + service(ServiceConfig::default(), tx, server.connection()).await } #[test] async fn test_ping() -> Result<(), Box> { - let web_service = build_service(); + let web_service = build_service().await; let request = Request::builder().uri("/ping").body(Body::empty()).unwrap(); let response = web_service.oneshot(request).await.unwrap(); From 602a6f8a82bc6bedc2b6335c88df33c5aa2ff33c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 4 Mar 2024 14:46:55 +0000 Subject: [PATCH 41/53] rust: remove unneeded lifetime annotations --- rust/agama-server/src/software/web.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index becfd5bc2a..4fb8222fec 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -109,8 +109,8 @@ pub async fn software_service(dbus: zbus::Connection) -> Router { #[utoipa::path(get, path = "/software/products", responses( (status = 200, description = "List of known products") ))] -async fn products<'a>( - State(state): State>, +async fn products( + State(state): State>, ) -> Result>, SoftwareError> { let products = state.product.products().await?; Ok(Json(products)) @@ -149,8 +149,8 @@ impl From for PatternStatus { #[utoipa::path(get, path = "/software/patterns", responses( (status = 200, description = "List of known software patterns") ))] -async fn patterns<'a>( - State(state): State>, +async fn patterns( + State(state): State>, ) -> Result>, SoftwareError> { let patterns = state.software.patterns(true).await?; let selected = state.software.selected_patterns().await?; From 4417e43032fd1e395453e65b426bd1bfef20a48d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 4 Mar 2024 15:30:49 +0000 Subject: [PATCH 42/53] software web functions return an result --- rust/agama-server/src/software/web.rs | 34 ++++++++++++++++----------- rust/agama-server/src/web.rs | 12 ++++++---- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 4fb8222fec..c863184d41 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -5,7 +5,7 @@ //! * `software_service` which returns the Axum service. //! * `software_stream` which offers an stream that emits the software events coming from D-Bus. -use crate::web::Event; +use crate::{error::Error, web::Event}; use agama_lib::{ error::ServiceError, product::{Product, ProductClient}, @@ -56,16 +56,18 @@ impl IntoResponse for SoftwareError { /// Returns an stream that emits software related events coming from D-Bus. /// /// * `connection`: D-Bus connection to listen for events. -pub async fn software_stream(dbus: zbus::Connection) -> impl Stream { - StreamExt::merge( - product_changed_stream(dbus.clone()).await, - patterns_changed_stream(dbus.clone()).await, - ) +pub async fn software_stream(dbus: zbus::Connection) -> Result, Error> { + Ok(StreamExt::merge( + product_changed_stream(dbus.clone()).await?, + patterns_changed_stream(dbus.clone()).await?, + )) } -async fn product_changed_stream(dbus: zbus::Connection) -> impl Stream { - let proxy = SoftwareProductProxy::new(&dbus).await.unwrap(); - proxy +async fn product_changed_stream( + dbus: zbus::Connection, +) -> Result, Error> { + let proxy = SoftwareProductProxy::new(&dbus).await?; + let stream = proxy .receive_selected_product_changed() .await .then(|change| async move { @@ -74,12 +76,15 @@ async fn product_changed_stream(dbus: zbus::Connection) -> impl Stream impl Stream { - let proxy = Software1Proxy::new(&dbus).await.unwrap(); - proxy +async fn patterns_changed_stream( + dbus: zbus::Connection, +) -> Result, Error> { + let proxy = Software1Proxy::new(&dbus).await?; + let stream = proxy .receive_selected_patterns_changed() .await .then(|change| async move { @@ -88,7 +93,8 @@ async fn patterns_changed_stream(dbus: zbus::Connection) -> impl Stream Result<(), ServiceError> { /// /// * `connection`: D-Bus connection. /// * `events`: channel to send the events to. -pub async fn run_events_monitor(connection: zbus::Connection, events: EventsSender) { - let stream = software_stream(connection).await; +pub async fn run_events_monitor(dbus: zbus::Connection, events: EventsSender) -> Result<(), Error> { + let stream = software_stream(dbus).await?; tokio::pin!(stream); let e = events.clone(); while let Some(event) = stream.next().await { _ = e.send(event); } + Ok(()) } From 46795899728a4b36bc230bb58f9148c20cddce84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 4 Mar 2024 15:50:09 +0000 Subject: [PATCH 43/53] rust: add an endpoint /software/proposal --- rust/agama-lib/src/software/client.rs | 4 ++++ rust/agama-server/src/software/web.rs | 28 +++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index 401a9b7480..c866f8be34 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -111,4 +111,8 @@ impl<'a> SoftwareClient<'a> { Ok(()) } } + + pub async fn used_disk_space(&self) -> Result { + Ok(self.software_proxy.used_disk_space().await?) + } } diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index c863184d41..3d6f2cb25b 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -103,8 +103,9 @@ pub async fn software_service(dbus: zbus::Connection) -> Router { let software = SoftwareClient::new(dbus).await.unwrap(); let state = SoftwareState { product, software }; Router::new() - .route("/products", get(products)) .route("/patterns", get(patterns)) + .route("/products", get(products)) + .route("/proposal", get(proposal)) .route("/config", put(set_config).get(get_config)) .with_state(state) } @@ -196,7 +197,7 @@ async fn set_config( Ok(()) } -/// Returns the software configuration +/// Returns the software configuration. /// /// * `state` : service state. #[utoipa::path(get, path = "/software/config", responses( @@ -213,3 +214,26 @@ async fn get_config( }; Ok(Json(config)) } + +#[derive(Serialize, utoipa::ToSchema)] +/// Software proposal information. +struct SoftwareProposal { + /// Space required for installation. It is returned as a formatted string which includes + /// a number and a unit (e.g., "GiB"). + size: String, +} + +/// Returns the proposal information. +/// +/// At this point, only the required space is reported. +#[utoipa::path( + get, path = "/software/proposal", responses( + (status = 200, description = "Software proposal") +))] +async fn proposal( + State(state): State>, +) -> Result, SoftwareError> { + let size = state.software.used_disk_space().await?; + let proposal = SoftwareProposal { size }; + Ok(Json(proposal)) +} From 4896fb2ea44a5186f1b2a106191d32b3afb8b3fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 4 Mar 2024 21:40:27 +0000 Subject: [PATCH 44/53] rust: add an endpoint to start the software probing --- rust/agama-lib/src/software/client.rs | 5 +++++ rust/agama-server/src/software/web.rs | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index c866f8be34..63a4cd1214 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -115,4 +115,9 @@ impl<'a> SoftwareClient<'a> { pub async fn used_disk_space(&self) -> Result { Ok(self.software_proxy.used_disk_space().await?) } + + /// Starts the process to read the repositories data. + pub async fn probe(&self) -> Result<(), ServiceError> { + Ok(self.software_proxy.probe().await?) + } } diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 3d6f2cb25b..d9e4b335c8 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -18,7 +18,7 @@ use axum::{ extract::State, http::StatusCode, response::{IntoResponse, Response}, - routing::{get, put}, + routing::{get, post, put}, Json, Router, }; use serde::{Deserialize, Serialize}; @@ -107,6 +107,7 @@ pub async fn software_service(dbus: zbus::Connection) -> Router { .route("/products", get(products)) .route("/proposal", get(proposal)) .route("/config", put(set_config).get(get_config)) + .route("/probe", post(probe)) .with_state(state) } @@ -237,3 +238,15 @@ async fn proposal( let proposal = SoftwareProposal { size }; Ok(Json(proposal)) } + +/// Returns the proposal information. +/// +/// At this point, only the required space is reported. +#[utoipa::path( + post, path = "/software/probe", responses( + (status = 200, description = "Software proposal") +))] +async fn probe(State(state): State>) -> Result, SoftwareError> { + state.software.probe().await?; + Ok(Json(())) +} From 6d6ee2d96bbfd3091494f0957168fb04628cc6d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 4 Mar 2024 22:17:08 +0000 Subject: [PATCH 45/53] rust: PatternsChanged includes the list of patterns --- rust/agama-server/src/software/web.rs | 23 ++++++++++++++++++----- rust/agama-server/src/web/event.rs | 4 +++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index d9e4b335c8..5a9233cdcb 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -23,6 +23,7 @@ use axum::{ }; use serde::{Deserialize, Serialize}; use serde_json::json; +use std::collections::HashMap; use thiserror::Error; use tokio_stream::{Stream, StreamExt}; @@ -88,8 +89,10 @@ async fn patterns_changed_stream( .receive_selected_patterns_changed() .await .then(|change| async move { - if let Ok(_pattens) = change.get().await { - return Some(Event::PatternsChanged); + if let Ok(patterns) = change.get().await { + let patterns: HashMap = + patterns.into_iter().map(|(k, v)| (k, v.into())).collect(); + return Some(Event::PatternsChanged(patterns)); } None }) @@ -136,10 +139,10 @@ pub struct PatternEntry { /// Pattern status. #[derive(Serialize, Clone, Copy)] -enum PatternStatus { +pub enum PatternStatus { + UserSelected = 0, + AutoSelected = 1, Available, - UserSelected, - AutoSelected, } impl From for PatternStatus { @@ -151,6 +154,16 @@ impl From for PatternStatus { } } +impl From for PatternStatus { + fn from(value: u8) -> Self { + match value { + 0 => PatternStatus::UserSelected, + 1 => PatternStatus::AutoSelected, + _ => PatternStatus::Available, + } + } +} + /// Returns the list of software patterns. /// /// * `state`: service state. diff --git a/rust/agama-server/src/web/event.rs b/rust/agama-server/src/web/event.rs index d810007c82..8f6b3bb015 100644 --- a/rust/agama-server/src/web/event.rs +++ b/rust/agama-server/src/web/event.rs @@ -1,5 +1,7 @@ +use crate::software::web::PatternStatus; use agama_lib::progress::Progress; use serde::Serialize; +use std::collections::HashMap; use tokio::sync::broadcast::{Receiver, Sender}; #[derive(Clone, Serialize)] @@ -8,7 +10,7 @@ pub enum Event { LocaleChanged { locale: String }, Progress(Progress), ProductChanged { id: String }, - PatternsChanged, + PatternsChanged(HashMap), } pub type EventsSender = Sender; From ab55a05342340b3a71fe4300796eda86e3e8683c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Mon, 4 Mar 2024 22:24:02 +0000 Subject: [PATCH 46/53] rust: document used_disk_space --- rust/agama-lib/src/software/client.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index 63a4cd1214..b7f0a3a681 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -112,6 +112,9 @@ impl<'a> SoftwareClient<'a> { } } + /// Returns the required space for installing the selected patterns. + /// + /// It returns a formatted string including the size and the unit. pub async fn used_disk_space(&self) -> Result { Ok(self.software_proxy.used_disk_space().await?) } From c1b2853e0376326fef763de8ab57530ccdab49d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 5 Mar 2024 06:46:41 +0000 Subject: [PATCH 47/53] rust: merge PatternStatus and SelectedBy --- rust/agama-lib/src/software.rs | 2 +- rust/agama-lib/src/software/client.rs | 17 ++++++----- rust/agama-server/src/software/web.rs | 44 ++++++--------------------- rust/agama-server/src/web/event.rs | 5 ++- 4 files changed, 22 insertions(+), 46 deletions(-) diff --git a/rust/agama-lib/src/software.rs b/rust/agama-lib/src/software.rs index ccdc1fce18..43e2c1fd62 100644 --- a/rust/agama-lib/src/software.rs +++ b/rust/agama-lib/src/software.rs @@ -5,6 +5,6 @@ pub mod proxies; mod settings; mod store; -pub use client::{Pattern, SelectionReason, SoftwareClient}; +pub use client::{Pattern, SelectedBy, SoftwareClient}; pub use settings::SoftwareSettings; pub use store::SoftwareStore; diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index b7f0a3a681..239c1a16a4 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -22,19 +22,22 @@ pub struct Pattern { } /// Represents the reason why a pattern is selected. -#[derive(Clone, Copy)] -pub enum SelectionReason { +#[derive(Clone, Copy, Debug, Serialize)] +pub enum SelectedBy { /// The pattern was selected by the user. User = 0, /// The pattern was selected automatically. Auto = 1, + /// The pattern has not be selected. + None = 2, } -impl From for SelectionReason { +impl From for SelectedBy { fn from(value: u8) -> Self { match value { 0 => Self::User, - _ => Self::Auto, + 1 => Self::Auto, + _ => Self::None, } } } @@ -80,16 +83,14 @@ impl<'a> SoftwareClient<'a> { .selected_patterns() .await? .into_iter() - .filter(|(_id, reason)| *reason == SelectionReason::User as u8) + .filter(|(_id, reason)| *reason == SelectedBy::User as u8) .map(|(id, _reason)| id) .collect(); Ok(patterns) } /// Returns the selected pattern and the reason each one selected. - pub async fn selected_patterns( - &self, - ) -> Result, ServiceError> { + pub async fn selected_patterns(&self) -> Result, ServiceError> { let patterns = self.software_proxy.selected_patterns().await?; let patterns = patterns .into_iter() diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 5a9233cdcb..74bb2b2874 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -11,7 +11,7 @@ use agama_lib::{ product::{Product, ProductClient}, software::{ proxies::{Software1Proxy, SoftwareProductProxy}, - Pattern, SelectionReason, SoftwareClient, + Pattern, SelectedBy, SoftwareClient, }, }; use axum::{ @@ -90,7 +90,7 @@ async fn patterns_changed_stream( .await .then(|change| async move { if let Ok(patterns) = change.get().await { - let patterns: HashMap = + let patterns: HashMap = patterns.into_iter().map(|(k, v)| (k, v.into())).collect(); return Some(Event::PatternsChanged(patterns)); } @@ -134,34 +134,7 @@ async fn products( pub struct PatternEntry { #[serde(flatten)] pattern: Pattern, - status: PatternStatus, -} - -/// Pattern status. -#[derive(Serialize, Clone, Copy)] -pub enum PatternStatus { - UserSelected = 0, - AutoSelected = 1, - Available, -} - -impl From for PatternStatus { - fn from(value: SelectionReason) -> Self { - match value { - SelectionReason::User => Self::UserSelected, - SelectionReason::Auto => Self::AutoSelected, - } - } -} - -impl From for PatternStatus { - fn from(value: u8) -> Self { - match value { - 0 => PatternStatus::UserSelected, - 1 => PatternStatus::AutoSelected, - _ => PatternStatus::Available, - } - } + selected_by: SelectedBy, } /// Returns the list of software patterns. @@ -178,11 +151,14 @@ async fn patterns( let items = patterns .into_iter() .map(|pattern| { - let status: PatternStatus = selected + let selected_by: SelectedBy = selected .get(&pattern.id) - .map(|r| (*r).into()) - .unwrap_or(PatternStatus::Available); - PatternEntry { pattern, status } + .copied() + .unwrap_or(SelectedBy::None); + PatternEntry { + pattern, + selected_by, + } }) .collect(); diff --git a/rust/agama-server/src/web/event.rs b/rust/agama-server/src/web/event.rs index 8f6b3bb015..a84956c2f3 100644 --- a/rust/agama-server/src/web/event.rs +++ b/rust/agama-server/src/web/event.rs @@ -1,5 +1,4 @@ -use crate::software::web::PatternStatus; -use agama_lib::progress::Progress; +use agama_lib::{progress::Progress, software::SelectedBy}; use serde::Serialize; use std::collections::HashMap; use tokio::sync::broadcast::{Receiver, Sender}; @@ -10,7 +9,7 @@ pub enum Event { LocaleChanged { locale: String }, Progress(Progress), ProductChanged { id: String }, - PatternsChanged(HashMap), + PatternsChanged(HashMap), } pub type EventsSender = Sender; From 0a578737e0513a32a3d271bcbc7105214e9f89c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 5 Mar 2024 07:23:29 +0000 Subject: [PATCH 48/53] rust: handle errors when creating the service router --- rust/agama-server/src/agama-web-server.rs | 2 +- rust/agama-server/src/software/web.rs | 11 ++++++----- rust/agama-server/src/web.rs | 9 +++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/rust/agama-server/src/agama-web-server.rs b/rust/agama-server/src/agama-web-server.rs index a0c29ce5d0..af96034b34 100644 --- a/rust/agama-server/src/agama-web-server.rs +++ b/rust/agama-server/src/agama-web-server.rs @@ -55,7 +55,7 @@ async fn serve_command(args: ServeArgs) -> anyhow::Result<()> { let config = web::ServiceConfig::load()?; let dbus = connection_to(&args.dbus_address).await?; - let service = web::service(config, tx, dbus).await; + let service = web::service(config, tx, dbus).await?; axum::serve(listener, service) .await .expect("could not mount app on listener"); diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 74bb2b2874..1ea20c6500 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -101,17 +101,18 @@ async fn patterns_changed_stream( } /// Sets up and returns the axum service for the software module. -pub async fn software_service(dbus: zbus::Connection) -> Router { - let product = ProductClient::new(dbus.clone()).await.unwrap(); - let software = SoftwareClient::new(dbus).await.unwrap(); +pub async fn software_service(dbus: zbus::Connection) -> Result { + let product = ProductClient::new(dbus.clone()).await?; + let software = SoftwareClient::new(dbus).await?; let state = SoftwareState { product, software }; - Router::new() + let router = Router::new() .route("/patterns", get(patterns)) .route("/products", get(products)) .route("/proposal", get(proposal)) .route("/config", put(set_config).get(get_config)) .route("/probe", post(probe)) - .with_state(state) + .with_state(state); + Ok(router) } /// Returns the list of available products. diff --git a/rust/agama-server/src/web.rs b/rust/agama-server/src/web.rs index 5dafed8154..b088528589 100644 --- a/rust/agama-server/src/web.rs +++ b/rust/agama-server/src/web.rs @@ -38,12 +38,13 @@ pub async fn service( config: ServiceConfig, events: EventsSender, dbus: zbus::Connection, -) -> Router { - MainServiceBuilder::new(events.clone()) +) -> Result { + let router = MainServiceBuilder::new(events.clone()) .add_service("/l10n", l10n_service(events.clone())) - .add_service("/software", software_service(dbus).await) + .add_service("/software", software_service(dbus).await?) .with_config(config) - .build() + .build(); + Ok(router) } /// Starts monitoring the D-Bus service progress. From 9551eaec91eafe7c7855c51b4672db480a7c2328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 5 Mar 2024 10:08:03 +0000 Subject: [PATCH 49/53] rust: fix service tests --- rust/agama-server/tests/service.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rust/agama-server/tests/service.rs b/rust/agama-server/tests/service.rs index 59157d3bce..14c5c4ae0d 100644 --- a/rust/agama-server/tests/service.rs +++ b/rust/agama-server/tests/service.rs @@ -19,7 +19,9 @@ use tower::ServiceExt; async fn build_service() -> Router { let (tx, _) = channel(16); let server = DBusServer::new().start().await.unwrap(); - service(ServiceConfig::default(), tx, server.connection()).await + service(ServiceConfig::default(), tx, server.connection()) + .await + .unwrap() } #[test] From 6a6cf0613f66722acb48a53c050e2b8c54635f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 5 Mar 2024 10:59:00 +0000 Subject: [PATCH 50/53] rust: add missing elements to the OpenAPI documentation --- rust/agama-server/src/software/web.rs | 24 +++++++++++++++--------- rust/agama-server/src/web/docs.rs | 20 +++++++++++--------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 1ea20c6500..4bc6438d4e 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -33,8 +33,8 @@ struct SoftwareState<'a> { software: SoftwareClient<'a>, } -#[derive(Clone, Serialize, Deserialize)] -struct SoftwareConfig { +#[derive(Clone, Serialize, Deserialize, utoipa::ToSchema)] +pub struct SoftwareConfig { patterns: Option>, product: Option, } @@ -119,7 +119,8 @@ pub async fn software_service(dbus: zbus::Connection) -> Result), + (status = 400, description = "The D-Bus service could not perform the action") ))] async fn products( State(state): State>, @@ -142,7 +143,8 @@ pub struct PatternEntry { /// /// * `state`: service state. #[utoipa::path(get, path = "/software/patterns", responses( - (status = 200, description = "List of known software patterns") + (status = 200, description = "List of known software patterns", body = Vec), + (status = 400, description = "The D-Bus service could not perform the action") ))] async fn patterns( State(state): State>, @@ -171,7 +173,8 @@ async fn patterns( /// * `state`: service state. /// * `config`: software configuration. #[utoipa::path(put, path = "/software/config", responses( - (status = 200, description = "Set the software configuration") + (status = 200, description = "Set the software configuration"), + (status = 400, description = "The D-Bus service could not perform the action") ))] async fn set_config( State(state): State>, @@ -192,7 +195,8 @@ async fn set_config( /// /// * `state` : service state. #[utoipa::path(get, path = "/software/config", responses( - (status = 200, description = "Software configuration") + (status = 200, description = "Software configuration", body = SoftwareConfig), + (status = 400, description = "The D-Bus service could not perform the action") ))] async fn get_config( State(state): State>, @@ -208,7 +212,7 @@ async fn get_config( #[derive(Serialize, utoipa::ToSchema)] /// Software proposal information. -struct SoftwareProposal { +pub struct SoftwareProposal { /// Space required for installation. It is returned as a formatted string which includes /// a number and a unit (e.g., "GiB"). size: String, @@ -219,7 +223,7 @@ struct SoftwareProposal { /// At this point, only the required space is reported. #[utoipa::path( get, path = "/software/proposal", responses( - (status = 200, description = "Software proposal") + (status = 200, description = "Software proposal", body = SoftwareProposal) ))] async fn proposal( State(state): State>, @@ -234,7 +238,9 @@ async fn proposal( /// At this point, only the required space is reported. #[utoipa::path( post, path = "/software/probe", responses( - (status = 200, description = "Software proposal") + (status = 200, description = "Read repositories data"), + (status = 400, description = "The D-Bus service could not perform the action +") ))] async fn probe(State(state): State>) -> Result, SoftwareError> { state.software.probe().await?; diff --git a/rust/agama-server/src/web/docs.rs b/rust/agama-server/src/web/docs.rs index d7b46459ae..d5e1249e1c 100644 --- a/rust/agama-server/src/web/docs.rs +++ b/rust/agama-server/src/web/docs.rs @@ -4,26 +4,28 @@ use utoipa::OpenApi; #[openapi( info(description = "Agama web API description"), paths( - super::http::ping, - crate::software::web::patterns, crate::l10n::web::get_config, crate::l10n::web::keymaps, crate::l10n::web::locales, crate::l10n::web::set_config, crate::l10n::web::timezones, crate::software::web::get_config, - crate::software::web::set_config, crate::software::web::patterns, + crate::software::web::patterns, + crate::software::web::set_config, + super::http::ping, ), components( - schemas(super::http::PingResponse), - schemas(crate::l10n::LocaleEntry), - schemas(crate::l10n::web::LocaleConfig), + schemas(agama_lib::product::Product), + schemas(agama_lib::software::Pattern), schemas(crate::l10n::Keymap), + schemas(crate::l10n::LocaleEntry), schemas(crate::l10n::TimezoneEntry), - schemas(agama_lib::software::Pattern), - schemas(agama_lib::product::Product), - schemas(crate::software::web::PatternEntry) + schemas(crate::l10n::web::LocaleConfig), + schemas(crate::software::web::PatternEntry), + schemas(crate::software::web::SoftwareConfig), + schemas(crate::software::web::SoftwareProposal), + schemas(super::http::PingResponse), ) )] pub struct ApiDoc; From 7cbe2b79f384f20f8cf05c57b352f71cda5dbdef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 5 Mar 2024 11:00:37 +0000 Subject: [PATCH 51/53] rust: improve SoftwareError description --- rust/agama-server/src/software/web.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 4bc6438d4e..8a9f1f309a 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -41,7 +41,7 @@ pub struct SoftwareConfig { #[derive(Error, Debug)] pub enum SoftwareError { - #[error("Service error: {0}")] + #[error("Software service error: {0}")] Error(#[from] ServiceError), } From 4c0cb3bc69b89cda984a2c10c1332a311359886f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 5 Mar 2024 12:05:44 +0000 Subject: [PATCH 52/53] rust: handle invalid pattern selection reasons --- rust/agama-lib/src/software.rs | 2 +- rust/agama-lib/src/software/client.rs | 36 ++++++++++++++++++++------- rust/agama-server/src/software/web.rs | 28 +++++++++++++++++---- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/rust/agama-lib/src/software.rs b/rust/agama-lib/src/software.rs index 43e2c1fd62..9231b0e5ba 100644 --- a/rust/agama-lib/src/software.rs +++ b/rust/agama-lib/src/software.rs @@ -5,6 +5,6 @@ pub mod proxies; mod settings; mod store; -pub use client::{Pattern, SelectedBy, SoftwareClient}; +pub use client::{Pattern, SelectedBy, SoftwareClient, UnknownSelectedBy}; pub use settings::SoftwareSettings; pub use store::SoftwareStore; diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index 239c1a16a4..4769976847 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -22,7 +22,7 @@ pub struct Pattern { } /// Represents the reason why a pattern is selected. -#[derive(Clone, Copy, Debug, Serialize)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize)] pub enum SelectedBy { /// The pattern was selected by the user. User = 0, @@ -32,12 +32,18 @@ pub enum SelectedBy { None = 2, } -impl From for SelectedBy { - fn from(value: u8) -> Self { +#[derive(Debug, thiserror::Error)] +#[error("Unknown selected by value: '{0}'")] +pub struct UnknownSelectedBy(u8); + +impl TryFrom for SelectedBy { + type Error = UnknownSelectedBy; + + fn try_from(value: u8) -> Result { match value { - 0 => Self::User, - 1 => Self::Auto, - _ => Self::None, + 0 => Ok(Self::User), + 1 => Ok(Self::Auto), + _ => Err(UnknownSelectedBy(value)), } } } @@ -83,8 +89,14 @@ impl<'a> SoftwareClient<'a> { .selected_patterns() .await? .into_iter() - .filter(|(_id, reason)| *reason == SelectedBy::User as u8) - .map(|(id, _reason)| id) + .filter_map(|(id, reason)| match SelectedBy::try_from(reason) { + Ok(reason) if reason == SelectedBy::User => Some(id), + Ok(_reason) => None, + Err(e) => { + log::warn!("Ignoring pattern {}. Error: {}", &id, e); + None + } + }) .collect(); Ok(patterns) } @@ -94,7 +106,13 @@ impl<'a> SoftwareClient<'a> { let patterns = self.software_proxy.selected_patterns().await?; let patterns = patterns .into_iter() - .map(|(id, reason)| (id, reason.into())) + .filter_map(|(id, reason)| match SelectedBy::try_from(reason) { + Ok(reason) => Some((id, reason)), + Err(e) => { + log::warn!("Ignoring pattern {}. Error: {}", &id, e); + None + } + }) .collect(); Ok(patterns) } diff --git a/rust/agama-server/src/software/web.rs b/rust/agama-server/src/software/web.rs index 8a9f1f309a..d8575a3339 100644 --- a/rust/agama-server/src/software/web.rs +++ b/rust/agama-server/src/software/web.rs @@ -11,7 +11,7 @@ use agama_lib::{ product::{Product, ProductClient}, software::{ proxies::{Software1Proxy, SoftwareProductProxy}, - Pattern, SelectedBy, SoftwareClient, + Pattern, SelectedBy, SoftwareClient, UnknownSelectedBy, }, }; use axum::{ @@ -90,16 +90,34 @@ async fn patterns_changed_stream( .await .then(|change| async move { if let Ok(patterns) = change.get().await { - let patterns: HashMap = - patterns.into_iter().map(|(k, v)| (k, v.into())).collect(); - return Some(Event::PatternsChanged(patterns)); + return match reason_to_selected_by(patterns) { + Ok(patterns) => Some(patterns), + Err(error) => { + log::warn!("Ignoring the list of changed patterns. Error: {}", error); + None + } + }; } None }) - .filter_map(|e| e); + .filter_map(|e| e.map(Event::PatternsChanged)); Ok(stream) } +// Returns a hash replacing the selection "reason" from D-Bus with a SelectedBy variant. +fn reason_to_selected_by( + patterns: HashMap, +) -> Result, UnknownSelectedBy> { + let mut selected: HashMap = HashMap::new(); + for (id, reason) in patterns { + match SelectedBy::try_from(reason) { + Ok(selected_by) => selected.insert(id, selected_by), + Err(e) => return Err(e), + }; + } + Ok(selected) +} + /// Sets up and returns the axum service for the software module. pub async fn software_service(dbus: zbus::Connection) -> Result { let product = ProductClient::new(dbus.clone()).await?; From ae36e6fd775a09c1f590ef8cc73591d2340dc370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 5 Mar 2024 16:07:11 +0000 Subject: [PATCH 53/53] rust: fix the agama-server crate name --- rust/Cargo.lock | 86 +++++++++++----------- rust/agama-server/Cargo.toml | 2 +- rust/agama-server/src/agama-dbus-server.rs | 2 +- rust/agama-server/src/agama-web-server.rs | 4 +- rust/agama-server/tests/l10n.rs | 2 +- rust/agama-server/tests/network.rs | 10 +-- rust/agama-server/tests/service.rs | 2 +- 7 files changed, 54 insertions(+), 54 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index cc576c6eaf..7d48a4957c 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -41,49 +41,6 @@ dependencies = [ "zbus", ] -[[package]] -name = "agama-dbus-server" -version = "0.1.0" -dependencies = [ - "agama-lib", - "agama-locale-data", - "anyhow", - "async-trait", - "axum", - "axum-extra", - "chrono", - "cidr", - "clap", - "config", - "gettext-rs", - "http-body-util", - "jsonwebtoken", - "log", - "macaddr", - "once_cell", - "pam", - "rand", - "regex", - "serde", - "serde_json", - "serde_with", - "serde_yaml", - "simplelog", - "systemd-journal-logger", - "thiserror", - "tokio", - "tokio-stream", - "tower", - "tower-http", - "tracing", - "tracing-journald", - "tracing-subscriber", - "utoipa", - "uuid", - "zbus", - "zbus_macros", -] - [[package]] name = "agama-derive" version = "1.0.0" @@ -129,6 +86,49 @@ dependencies = [ "thiserror", ] +[[package]] +name = "agama-server" +version = "0.1.0" +dependencies = [ + "agama-lib", + "agama-locale-data", + "anyhow", + "async-trait", + "axum", + "axum-extra", + "chrono", + "cidr", + "clap", + "config", + "gettext-rs", + "http-body-util", + "jsonwebtoken", + "log", + "macaddr", + "once_cell", + "pam", + "rand", + "regex", + "serde", + "serde_json", + "serde_with", + "serde_yaml", + "simplelog", + "systemd-journal-logger", + "thiserror", + "tokio", + "tokio-stream", + "tower", + "tower-http", + "tracing", + "tracing-journald", + "tracing-subscriber", + "utoipa", + "uuid", + "zbus", + "zbus_macros", +] + [[package]] name = "agama-settings" version = "1.0.0" diff --git a/rust/agama-server/Cargo.toml b/rust/agama-server/Cargo.toml index 25cc8ccba5..def882c4a2 100644 --- a/rust/agama-server/Cargo.toml +++ b/rust/agama-server/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "agama-dbus-server" +name = "agama-server" version = "0.1.0" edition = "2021" rust-version.workspace = true diff --git a/rust/agama-server/src/agama-dbus-server.rs b/rust/agama-server/src/agama-dbus-server.rs index 3145228fd3..7643d6e0ec 100644 --- a/rust/agama-server/src/agama-dbus-server.rs +++ b/rust/agama-server/src/agama-dbus-server.rs @@ -1,4 +1,4 @@ -use agama_dbus_server::{ +use agama_server::{ l10n::{self, helpers}, network, questions, }; diff --git a/rust/agama-server/src/agama-web-server.rs b/rust/agama-server/src/agama-web-server.rs index af96034b34..53f1e217c1 100644 --- a/rust/agama-server/src/agama-web-server.rs +++ b/rust/agama-server/src/agama-web-server.rs @@ -1,10 +1,10 @@ use std::process::{ExitCode, Termination}; -use agama_dbus_server::{ +use agama_lib::connection_to; +use agama_server::{ l10n::helpers, web::{self, run_monitor}, }; -use agama_lib::connection_to; use clap::{Args, Parser, Subcommand}; use tokio::sync::broadcast::channel; use tracing_subscriber::prelude::*; diff --git a/rust/agama-server/tests/l10n.rs b/rust/agama-server/tests/l10n.rs index f2d0291c29..75d0e76109 100644 --- a/rust/agama-server/tests/l10n.rs +++ b/rust/agama-server/tests/l10n.rs @@ -1,6 +1,6 @@ pub mod common; -use agama_dbus_server::l10n::web::l10n_service; +use agama_server::l10n::web::l10n_service; use axum::{ body::Body, http::{Request, StatusCode}, diff --git a/rust/agama-server/tests/network.rs b/rust/agama-server/tests/network.rs index ed4b0037b2..e437331d9d 100644 --- a/rust/agama-server/tests/network.rs +++ b/rust/agama-server/tests/network.rs @@ -1,16 +1,16 @@ pub mod common; use self::common::{async_retry, DBusServer}; -use agama_dbus_server::network::{ - self, - model::{self, Ipv4Method, Ipv6Method}, - Adapter, NetworkAdapterError, NetworkService, NetworkState, -}; use agama_lib::network::{ settings::{self}, types::DeviceType, NetworkClient, }; +use agama_server::network::{ + self, + model::{self, Ipv4Method, Ipv6Method}, + Adapter, NetworkAdapterError, NetworkService, NetworkState, +}; use async_trait::async_trait; use cidr::IpInet; use std::error::Error; diff --git a/rust/agama-server/tests/service.rs b/rust/agama-server/tests/service.rs index 14c5c4ae0d..daa453af02 100644 --- a/rust/agama-server/tests/service.rs +++ b/rust/agama-server/tests/service.rs @@ -1,6 +1,6 @@ pub mod common; -use agama_dbus_server::{ +use agama_server::{ service, web::{generate_token, MainServiceBuilder, ServiceConfig}, };