Skip to content

Commit

Permalink
fix: translate storage component when UI language changes (#1644)
Browse files Browse the repository at this point in the history
## Problem

Some parts of the UI are not properly translated when the language of
the UI changes (see #1629).

## Solution

This is a fix for storage components which consist on not calling `_` at
module level.

## Testing

- Tested manually
  • Loading branch information
imobachgs authored Sep 27, 2024
2 parents ea95768 + 38ac30a commit e7a8f50
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 54 deletions.
6 changes: 6 additions & 0 deletions web/package/agama-web-ui.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Fri Sep 27 13:00:05 UTC 2024 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

- Properly translate the storage interface when switching
the language of the UI (gh#agama-project/agama#1629).

-------------------------------------------------------------------
Fri Sep 20 11:42:25 UTC 2024 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

Expand Down
23 changes: 10 additions & 13 deletions web/src/components/storage/EncryptionField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,18 @@ import { EncryptionMethods } from "~/types/storage";
import { _ } from "~/i18n";
import { noop } from "~/utils";

// Field texts at root level to avoid redefinitions every time the component
// is rendered.
const LABEL = _("Encryption");
const DESCRIPTION = _(
"Protection for the information stored at \
the device, including data, programs, and system files.",
);
const VALUES = {
const encryptionMethods = () => ({
disabled: _("disabled"),
[EncryptionMethods.LUKS2]: _("enabled"),
[EncryptionMethods.TPM]: _("using TPM unlocking"),
};
});

const Value = ({ isLoading, isEnabled, method }) => {
const values = encryptionMethods();
if (isLoading) return <Skeleton fontSize="sm" width="75%" />;
if (isEnabled) return VALUES[method];
if (isEnabled) return values[method];

return VALUES.disabled;
return values.disabled;
};

const Action = ({ isEnabled, isLoading, onClick }) => {
Expand Down Expand Up @@ -107,9 +101,12 @@ export default function EncryptionField({

return (
<Page.Section
title={LABEL}
title={_("Encryption")}
value={<Value isLoading={isLoading} isEnabled={isEnabled} method={method} />}
description={DESCRIPTION}
description={_(
"Protection for the information stored at \
the device, including data, programs, and system files.",
)}
pfCardBodyProps={{ isFilled: true }}
actions={<Action isEnabled={isEnabled} isLoading={isLoading} onClick={openDialog} />}
>
Expand Down
38 changes: 19 additions & 19 deletions web/src/components/storage/EncryptionSettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,6 @@ import { _ } from "~/i18n";
import { PasswordAndConfirmationInput, Popup } from "~/components/core";
import { EncryptionMethods } from "~/client/storage";

const DIALOG_TITLE = _("Encryption");
const DIALOG_DESCRIPTION = _(
"Full Disk Encryption (FDE) allows to protect the information stored \
at the device, including data, programs, and system files.",
);
// TRANSLATORS: "Trusted Platform Module" is the name of the technology and TPM its abbreviation
const TPM_LABEL = _("Use the Trusted Platform Module (TPM) to decrypt automatically on each boot");
// 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.
const TPM_EXPLANATION = _(
"The password will not be needed to boot and access the data if the \
TPM can verify the integrity of the system. TPM sealing requires the new system to be booted \
directly on its first run.",
);

export type EncryptionSetting = {
password: string;
method?: string;
Expand Down Expand Up @@ -114,12 +99,27 @@ export default function EncryptionSettingsDialog({
}
};

// TRANSLATORS: "Trusted Platform Module" is the name of the technology and TPM its abbreviation
const tpm_label = _(
"Use the Trusted Platform Module (TPM) to decrypt automatically on each boot",
);
// 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.
const tpm_explanation = _(
"The password will not be needed to boot and access the data if the \
TPM can verify the integrity of the system. TPM sealing requires the new system to be booted \
directly on its first run.",
);

const tpmAvailable = methods.includes(EncryptionMethods.TPM);

return (
<Popup
title={DIALOG_TITLE}
description={DIALOG_DESCRIPTION}
title={_("Encryption")}
description={_(
"Full Disk Encryption (FDE) allows to protect the information stored \
at the device, including data, programs, and system files.",
)}
isOpen={isOpen}
isLoading={isLoading}
>
Expand All @@ -140,8 +140,8 @@ export default function EncryptionSettingsDialog({
{tpmAvailable && (
<Checkbox
id="tpm_encryption_method"
label={TPM_LABEL}
description={TPM_EXPLANATION}
label={tpm_label}
description={tpm_explanation}
isChecked={method === EncryptionMethods.TPM}
isDisabled={!isEnabled}
onChange={changeMethod}
Expand Down
11 changes: 5 additions & 6 deletions web/src/components/storage/InstallationDeviceField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ import { deviceLabel } from "~/components/storage/utils";
import { sprintf } from "sprintf-js";
import { _ } from "~/i18n";

const LABEL = _("Installation device");
// TRANSLATORS: The storage "Installation device" field's description.
const DESCRIPTION = _("Main disk or LVM Volume Group for installation.");

/**
* Generates the target value.
*/
Expand Down Expand Up @@ -94,10 +90,13 @@ export default function InstallationDeviceField({
if (isLoading || !target) value = <Skeleton fontSize="sm" width="75%" />;
else value = targetValue(target, targetDevice, targetPVDevices);

// TRANSLATORS: The storage "Installation device" field's description.
const description = _("Main disk or LVM Volume Group for installation.");

return (
<Page.Section
title={LABEL}
description={DESCRIPTION}
title={_("Installation device")}
description={description}
actions={
isLoading ? (
<Skeleton fontSize="sm" width="100px" />
Expand Down
19 changes: 10 additions & 9 deletions web/src/components/storage/SnapshotsField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ import { hasFS } from "~/components/storage/utils";
import textStyles from "@patternfly/react-styles/css/utilities/Text/text";
import { Volume } from "~/types/storage";

const LABEL = _("Use Btrfs snapshots for the root file system");
const DESCRIPTION = _(
"Allows to boot to a previous version of the \
system after configuration changes or software upgrades.",
);

export type SnapshotsFieldProps = {
rootVolume: Volume;
onChange?: (config: SnapshotsConfig) => void;
Expand All @@ -51,6 +45,8 @@ export type SnapshotsConfig = {
export default function SnapshotsField({ rootVolume, onChange }: SnapshotsFieldProps) {
const isChecked = hasFS(rootVolume, "Btrfs") && rootVolume.snapshots;

const label = _("Use Btrfs snapshots for the root file system");

const switchState = () => {
if (onChange) onChange({ active: !isChecked });
};
Expand All @@ -59,14 +55,19 @@ export default function SnapshotsField({ rootVolume, onChange }: SnapshotsFieldP
<Split hasGutter>
<Switch
id="snapshots"
aria-label={LABEL}
aria-label={label}
isChecked={isChecked}
onChange={switchState}
hasCheckIcon
/>
<div>
<div>{LABEL}</div>
<div className={textStyles.color_200}>{DESCRIPTION}</div>
<div>{label}</div>
<div className={textStyles.color_200}>
{_(
"Allows to boot to a previous version of the \
system after configuration changes or software upgrades.",
)}
</div>
</div>
</Split>
);
Expand Down
14 changes: 7 additions & 7 deletions web/src/components/storage/VolumeLocationDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ import { sprintf } from "sprintf-js";
import { deviceChildren, volumeLabel } from "~/components/storage/utils";
import { StorageDevice, Volume, VolumeTarget } from "~/types/storage";

// TRANSLATORS: Description of the dialog for changing the location of a file system.
const DIALOG_DESCRIPTION = _(
"The file systems are allocated at the installation device by \
default. Indicate a custom location to create the file system at a specific device.",
);

const defaultTarget: (device: StorageDevice | undefined) => VolumeTarget = (
device,
): VolumeTarget => {
Expand Down Expand Up @@ -130,12 +124,18 @@ export default function VolumeLocationDialog({

if (!targetDevice) return null;

// TRANSLATORS: Description of the dialog for changing the location of a file system.
const dialogDescription = _(
"The file systems are allocated at the installation device by \
default. Indicate a custom location to create the file system at a specific device.",
);

return (
<Popup
// TRANSLATORS: Title of the dialog for changing the location of a file system. %s is replaced
// by a mount path (e.g., /home).
title={sprintf(_("Location for %s file system"), volumeLabel(volume))}
description={DIALOG_DESCRIPTION}
description={dialogDescription}
inlineSize="large"
blockSize="large"
isOpen={isOpen}
Expand Down

0 comments on commit e7a8f50

Please sign in to comment.