Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translate the user configuration #727

Merged
merged 1 commit into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion web/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import React, { useEffect, useState } from "react";
import { Outlet } from "react-router-dom";

import { _ } from "~/i18n";
import { useInstallerClient } from "~/context/installer";
import { STARTUP, INSTALL } from "~/client/phase";
import { BUSY } from "~/client/status";
Expand Down Expand Up @@ -86,7 +87,7 @@ function App() {
<Sidebar>
<ChangeProductLink />
<IssuesLink />
<Disclosure label="Diagnostic tools" data-keep-sidebar-open>
<Disclosure label={_("Diagnostic tools")} data-keep-sidebar-open>
<ShowLogButton />
<LogsButton data-keep-sidebar-open="true" />
<ShowTerminalButton />
Expand Down
44 changes: 24 additions & 20 deletions web/src/components/users/FirstUser.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
*/

import React, { useState, useEffect } from "react";
import { useCancellablePromise } from "~/utils";

import { _ } from "~/i18n";
import { useCancellablePromise } from "~/utils";
import { useInstallerClient } from "~/context/installer";
import {
Alert,
Expand All @@ -40,9 +41,10 @@ import { RowActions, PasswordAndConfirmationInput, Popup } from '~/components/co
const UserNotDefined = ({ actionCb }) => {
return (
<div className="stack">
<div className="bold">No user defined yet</div>
<div>Please, be aware that a user must be defined before installing the system to be able to log into it.</div>
<Button variant="primary" onClick={actionCb}>Define a user now</Button>
<div className="bold">{_("No user defined yet")}</div>
<div>{_("Please, be aware that a user must be defined before installing the system to be able to log into it.")}</div>
{/* TRANSLATORS: push button label */}
<Button variant="primary" onClick={actionCb}>{_("Define a user now")}</Button>
</div>
);
};
Expand All @@ -52,8 +54,8 @@ const UserData = ({ user, actions }) => {
<TableComposable variant="compact">
<Thead>
<Tr>
<Th width={25}>Fullname</Th>
<Th>Username</Th>
<Th width={25}>{_("Full name")}</Th>
<Th>{_("Username")}</Th>
<Th />
</Tr>
</Thead>
Expand Down Expand Up @@ -165,11 +167,11 @@ export default function FirstUser() {

const actions = [
{
title: "Edit",
title: _("Edit"),
onClick: (e) => openForm(e, EDIT_MODE)
},
{
title: "Discard",
title: _("Discard"),
onClick: remove,
className: "danger-action"
}
Expand All @@ -186,42 +188,43 @@ export default function FirstUser() {
{ isUserDefined ? <UserData user={user} actions={actions} /> : <UserNotDefined actionCb={openForm} /> }
{ /* TODO: Extract this form to a component, if possible */ }
{ isFormOpen &&
<Popup isOpen title={isEditing ? "Edit user account" : "Create user account"}>
<Popup isOpen title={isEditing ? _("Edit user account") : _("Create user account")}>
<Form id="createUser" onSubmit={(e) => accept("createUser", e)}>
{ showErrors() &&
<Alert variant="warning" isInline title="Something went wrong">
<Alert variant="warning" isInline title={_("Something went wrong")}>
{ errors.map((e, i) => <p key={`error_${i}`}>{e}</p>) }
</Alert> }

<FormGroup fieldId="userFullName" label="Full name">
<FormGroup fieldId="userFullName" label={_("Full name")}>
<TextInput
id="userFullName"
name="fullName"
aria-label="User fullname"
aria-label={_("User full name")}
value={formValues.fullName}
label="User full name"
label={_("User full name")}
onChange={handleInputChange}
/>
</FormGroup>

<FormGroup fieldId="userName" label="Username" isRequired>
<FormGroup fieldId="userName" label={_("Username")} isRequired>
<TextInput
id="userName"
name="userName"
aria-label="Username"
aria-label={_("Username")}
value={formValues.userName}
label="Username"
label={_("Username")}
isRequired
onChange={handleInputChange}
/>
</FormGroup>

{ isEditing &&
<Checkbox
aria-label="Edit password too"
aria-label={_("Edit password too")}
id="edit-password"
name="edit-password"
label="Edit password too"
// TRANSLATORS: check box label
label={_("Edit password too")}
isChecked={isSettingPassword}
onChange={toggleShowPasswordField}
/> }
Expand All @@ -236,10 +239,11 @@ export default function FirstUser() {
/> }

<Checkbox
aria-label="user autologin"
aria-label={_("user autologin")}
id="autologin"
name="autologin"
label="Auto-login"
// TRANSLATORS: check box label
label={_("Auto-login")}
isChecked={formValues.autologin}
onChange={handleInputChange}
/>
Expand Down
39 changes: 22 additions & 17 deletions web/src/components/users/RootAuthMethods.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,20 @@ import { TableComposable, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-tab
import { Em, RowActions } from '~/components/core';
import { RootPasswordPopup, RootSSHKeyPopup } from '~/components/users';

import { _ } from "~/i18n";
import { useCancellablePromise } from "~/utils";
import { useInstallerClient } from "~/context/installer";

const MethodsNotDefined = ({ setPassword, setSSHKey }) => {
return (
<div className="stack">
<div className="bold">No root authentication method defined yet</div>
<div>Please, define at least one authentication method for logging into the system as root.</div>
<div className="bold">{_("No root authentication method defined yet")}</div>
<div>{_("Please, define at least one authentication method for logging into the system as root.")}</div>
<div className="split">
<Button variant="primary" onClick={setPassword}>Set a password</Button>
<Button variant="secondary" onClick={setSSHKey}>Upload a SSH Public Key</Button>
{/* TRANSLATORS: push button label */}
<Button variant="primary" onClick={setPassword}>{_("Set a password")}</Button>
{/* TRANSLATORS: push button label */}
<Button variant="secondary" onClick={setSSHKey}>{_("Upload a SSH Public Key")}</Button>
</div>
</div>
);
Expand Down Expand Up @@ -84,24 +87,24 @@ export default function RootAuthMethods() {

const passwordActions = [
{
title: isPasswordDefined ? "Change" : "Set",
title: isPasswordDefined ? _("Change") : _("Set"),
onClick: openPasswordForm

},
isPasswordDefined && {
title: "Discard",
title: _("Discard"),
onClick: () => client.removeRootPassword(),
className: "danger-action"
}
].filter(Boolean);

const sshKeyActions = [
{
title: isSSHKeyDefined ? "Change" : "Set",
title: isSSHKeyDefined ? _("Change") : _("Set"),
onClick: openSSHKeyForm
},
sshKey && {
title: "Discard",
title: _("Discard"),
onClick: () => client.setRootSSHKey(""),
className: "danger-action"
}
Expand All @@ -119,12 +122,12 @@ export default function RootAuthMethods() {

const PasswordLabel = () => {
return isPasswordDefined
? "Already set"
: "Not set";
? _("Already set")
: _("Not set");
};

const SSHKeyLabel = () => {
if (!isSSHKeyDefined) return "Not set";
if (!isSSHKeyDefined) return _("Not set");

const trailingChars = Math.min(sshKey.length - sshKey.lastIndexOf(" "), 30);

Expand All @@ -144,21 +147,23 @@ export default function RootAuthMethods() {
<TableComposable variant="compact" gridBreakPoint="grid-md">
<Thead>
<Tr>
<Th width={25}>Method</Th>
<Th>Status</Th>
{/* TRANSLATORS: table header, user authentication method */}
<Th width={25}>{_("Method")}</Th>
{/* TRANSLATORS: table header */}
<Th>{_("Status")}</Th>
<Th />
</Tr>
</Thead>
<Tbody>
<Tr>
<Td dataLabel="Method">Password</Td>
<Td dataLabel="Method">{_("Password")}</Td>
<Td dataLabel="Status"><PasswordLabel /></Td>
<Td isActionCell>
<RowActions actions={passwordActions} id="actions-for-root-password" />
</Td>
</Tr>
<Tr>
<Td dataLabel="Method">SSH Key</Td>
<Td dataLabel="Method">{_("SSH Key")}</Td>
<Td dataLabel="Status"><SSHKeyLabel /></Td>
<Td isActionCell>
<RowActions actions={sshKeyActions} id="actions-for-root-sshKey" />
Expand All @@ -175,14 +180,14 @@ export default function RootAuthMethods() {
{ isPasswordFormOpen &&
<RootPasswordPopup
isOpen
title={isPasswordDefined ? "Change the root password" : "Set a root password"}
title={isPasswordDefined ? _("Change the root password") : _("Set a root password")}
onClose={closePasswordForm}
/> }

{ isSSHKeyFormOpen &&
<RootSSHKeyPopup
isOpen
title={isSSHKeyDefined ? "Edit the SSH Public Key for root" : "Add a SSH Public Key for root" }
title={isSSHKeyDefined ? _("Edit the SSH Public Key for root") : _("Add a SSH Public Key for root")}
currentKey={sshKey}
onClose={closeSSHKeyForm}
/>}
Expand Down
3 changes: 2 additions & 1 deletion web/src/components/users/RootPasswordPopup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import React, { useState } from "react";
import { Form } from "@patternfly/react-core";
import { PasswordAndConfirmationInput, Popup } from '~/components/core';

import { _ } from "~/i18n";
import { useInstallerClient } from "~/context/installer";

/**
Expand All @@ -38,7 +39,7 @@ import { useInstallerClient } from "~/context/installer";
* @param {function} props.onClose - the function to be called when the dialog is closed
*/
export default function RootPasswordPopup({
title = "Root password",
title = _("Root password"),
isOpen,
onClose
}) {
Expand Down
13 changes: 9 additions & 4 deletions web/src/components/users/RootSSHKeyPopup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import React, { useState } from "react";
import { Form, FormGroup, FileUpload } from "@patternfly/react-core";

import { _ } from "~/i18n";
import { Popup } from '~/components/core';
import { useInstallerClient } from "~/context/installer";

Expand All @@ -38,7 +40,7 @@ import { useInstallerClient } from "~/context/installer";
* @param {function} props.onClose - the function to be called when the dialog is closed
*/
export default function RootSSHKeyPopup({
title = "Set root SSH public key",
title = _("Set root SSH public key"),
currentKey = "",
isOpen,
onClose
Expand Down Expand Up @@ -66,13 +68,16 @@ export default function RootSSHKeyPopup({
return (
<Popup isOpen={isOpen} title={title}>
<Form id="root-ssh-key" onSubmit={accept}>
<FormGroup fieldId="sshKey" label="Root SSH public key">
<FormGroup fieldId="sshKey" label={_("Root SSH public key")}>
<FileUpload
id="sshKey"
type="text"
value={sshKey}
filenamePlaceholder="Upload, paste, or drop a SSH public key"
browseButtonText="Upload"
filenamePlaceholder={_("Upload, paste, or drop an SSH public key")}
// TRANSLATORS: push button label
browseButtonText={_("Upload")}
// TRANSLATORS: push button label, clears the related input field
clearButtonText={_("Clear")}
isLoading={isLoading}
onDataChange={setSSHKey}
onTextChange={setSSHKey}
Expand Down
8 changes: 5 additions & 3 deletions web/src/components/users/UsersPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,18 @@
*/

import React from "react";

import { _ } from "~/i18n";
import { Page, Section } from "~/components/core";
import { FirstUser, RootAuthMethods } from "~/components/users";

export default function UsersPage() {
return (
<Page title="Users" icon="manage_accounts" actionLabel="Back" actionVariant="secondary">
<Section title="User" icon="person">
<Page title={_("Users")} icon="manage_accounts" actionLabel={_("Back")} actionVariant="secondary">
<Section title={_("User")} icon="person">
<FirstUser />
</Section>
<Section title="Root authentication" icon="badge">
<Section title={_("Root authentication")} icon="badge">
<RootAuthMethods />
</Section>
</Page>
Expand Down
Loading