Repository: authelia/authelia
Pull request #9496: fix(web): add missing translations
Author: login: michelheusschen
Created: 2025-05-12T13:48:14Z | Merged: 2025-05-13T13:13:07Z

- Add several missing translations
- Fix some incorrect namespaces
- Remove duplicate or unnecessary calls to `translate(...)`
- Rewritten translations like `"This {{item}}", { item: translate("password") }` to `This password`. This provides more context to translators and some variants may be impossible to translate correctly for some languages.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **Style**
  - Improved consistency and accuracy of translated UI text, including correction of typos and capitalization.
  - Standardized translation usage across components by specifying appropriate namespaces and simplifying translation calls.
  - Updated various button labels, dialog titles, tooltips, and error messages for clearer and more consistent user-facing language.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/internal/server/locales/en/consent.json b/internal/server/locales/en/consent.json
index 1eac0e9601ac9..dd0ddec6438e0 100644
--- a/internal/server/locales/en/consent.json
+++ b/internal/server/locales/en/consent.json
@@ -8,9 +8,11 @@
 	"Consent has been accepted and processed": "Consent has been accepted and processed",
 	"Consent has been rejected and processed": "Consent has been rejected and processed",
 	"Consent Request": "Consent Request",
+	"Debug Information": "Debug Information",
 	"Deny this consent request": "Deny this consent request",
 	"Description": "Description",
 	"Documentation": "Documentation",
+	"Error": "Error",
 	"Error Code": "Error Code",
 	"Failed to submit the user code": "Failed to submit the user code",
 	"Hint": "Hint",
diff --git a/internal/server/locales/en/portal.json b/internal/server/locales/en/portal.json
index 6f44b882fbdc2..d1290530cf30e 100644
--- a/internal/server/locales/en/portal.json
+++ b/internal/server/locales/en/portal.json
@@ -30,6 +30,8 @@
 	"Home": "Home",
 	"Incorrect password": "Incorrect password",
 	"Incorrect username or password": "Incorrect username or password",
+	"Language": "Language",
+	"Loading": "Loading",
 	"Login - {{authelia}}": "Login - {{authelia}}",
 	"Logout": "Logout",
 	"Logout and clear any current flow": "Logout and clear any current flow",
@@ -66,6 +68,7 @@
 	"Security Key": "Security Key",
 	"Security Key - WebAuthn": "Security Key - WebAuthn",
 	"Select a Device": "Select a Device",
+	"Settings": "Settings",
 	"Sign in": "Sign in",
 	"Sign in with a passkey": "Sign in with a passkey",
 	"Sign out": "Sign out",
@@ -96,6 +99,7 @@
 	"There was an issue updating preferred second factor method": "There was an issue updating preferred second factor method",
 	"This device is not registered": "This device is not registered",
 	"Time-based One-Time Password": "Time-based One-Time Password",
+	"Toggle password visibility": "Toggle password visibility",
 	"Touch the token of your security key": "Touch the token of your security key",
 	"Use OpenID to verify your identity": "Use OpenID to verify your identity",
 	"Username": "Username",
diff --git a/internal/server/locales/en/settings.json b/internal/server/locales/en/settings.json
index 55d732160f919..32776f9ee9560 100644
--- a/internal/server/locales/en/settings.json
+++ b/internal/server/locales/en/settings.json
@@ -19,6 +19,7 @@
 	"Backup State": "Backup State",
 	"Cancel": "Cancel",
 	"Caps Lock is on": "Caps Lock is on",
+	"Change Password": "Change Password",
 	"Click to add a {{item}} to your account": "Click to add a {{item}} to your account",
 	"Click to copy the {{value}}": "Click to copy the {{value}}",
 	"Click to Copy": "Click to Copy",
@@ -29,6 +30,7 @@
 	"Completed": "Completed",
 	"Copied": "Copied",
 	"Credential Creation Options Request succeeded but Credential Creation Options is empty": "Credential Creation Options Request succeeded but Credential Creation Options is empty",
+	"Cross-Platform": "Cross-Platform",
 	"Default Method": "Default Method",
 	"Default Method (Browser)": "Default Method (Browser)",
 	"delete": "delete",
@@ -38,9 +40,11 @@
 	"Digits": "Digits",
 	"Discoverable": "Discoverable",
 	"Display extended information for this WebAuthn Credential": "Display extended information for this WebAuthn Credential",
+	"Email One-Time Code": "Email One-Time Code",
 	"Email": "Email",
 	"Display extended information for this One-Time Password": "Display extended information for this One-Time Password",
 	"Edit this {{item}}": "Edit this {{item}}",
+	"Edit WebAuthn Credential": "Edit WebAuthn Credential",
 	"Eligible": "Eligible",
 	"Enabled": "Enabled",
 	"Enter a description for this WebAuthn Credential": "Enter a description for this WebAuthn Credential",
@@ -48,6 +52,7 @@
 	"Error occurred obtaining the WebAuthn Credential creation options": "Error occurred obtaining the WebAuthn Credential creation options",
 	"Extended information for WebAuthn Credential": "Extended information for WebAuthn Credential {{description}}",
 	"Extended information for One-Time Password": "Extended information for One-Time Password",
+	"Failed to get session elevation status": "Failed to get session elevation status",
 	"Failed to register device, the provided code is expired or has already been used": "Failed to register device, the provided code is expired or has already been used",
 	"Failed to register device, the provided link is expired or has already been used": "Failed to register device, the provided link is expired or has already been used",
 	"Failed to register your credential, the identity verification process might have timed out": "Failed to register your credential, the identity verification process might have timed out",
@@ -55,6 +60,7 @@
 	"Identity Verification": "Identity Verification",
 	"Incorrect password": "Incorrect password",
 	"In order to perform this action policy enforcement requires additional identity verification and a One-Time Code has been sent to your email": "In order to perform this action policy enforcement requires additional identity verification and a One-Time Code has been sent to your email",
+	"In order to perform this action, policy enforcement requires that two-factor authentication is performed": "In order to perform this action, policy enforcement requires that two-factor authentication is performed",
 	"Issuer": "Issuer",
 	"Last Used when": "Last Used {{when, datetime}}",
 	"Last Used": "Last Used",
@@ -63,10 +69,12 @@
 	"Need Google Authenticator?": "Need Google Authenticator?",
 	"Never used": "Never used",
 	"Never": "Never",
+	"New Password": "New Password",
 	"Next": "Next",
 	"No": "No",
 	"No WebAuthn Credentials have been registered if you'd like to register one click add": "No WebAuthn Credentials have been registered if you'd like to register one click add",
 	"Not Eligible": "Not Eligible",
+	"Old Password": "Old Password",
 	"One-Time Password configuration": "One-Time Password configuration",
 	"One-Time Password": "One-Time Password",
 	"One-Time Password Information": "One-Time Password Information",
@@ -76,6 +84,7 @@
 	"Password": "Password",
 	"Passwords do not match": "Passwords do not match",
 	"Password changed successfully": "Password changed successfully",
+	"Platform": "Platform",
 	"Previous": "Previous",
 	"Public Key": "Public Key",
 	"QR Code": "QR Code",
@@ -88,6 +97,8 @@
 	"Repeat New Password": "Repeat New Password",
 	"Seconds": "Seconds",
 	"Secret": "Secret",
+	"Security": "Security",
+	"Select a Method": "Select a Method",
 	"Settings": "Settings",
 	"Settings - {{authelia}}": "Settings - {{authelia}}",
 	"Start": "Start",
@@ -103,7 +114,8 @@
 	"There are no protected applications that require a second factor method": "There are no protected applications that require a second factor method",
 	"There is an issue with this Credential to find out more click to display extended information for this WebAuthn Credential": "There is an issue with this Credential to find out more click to display extended information for this WebAuthn Credential",
 	"There was a problem {{action}} the {{item}}": "There was a problem {{action}} the {{item}}",
-	"There was an issue changing the {{item}}": "There was an issue changing the {{item}}",
+	"There was an issue changing the password": "There was an issue changing the password",
+	"There was an issue retrieving configuration": "There was an issue retrieving configuration",
 	"There was an issue retrieving the {{item}}": "There was an issue retrieving the {{item}}",
 	"There was an issue updating preferred second factor method": "There was an issue updating preferred second factor method",
 	"This dialog handles registration of a {{item}}": "This dialog handles registration of a {{item}}",
@@ -129,11 +141,13 @@
 	"User Verified": "User Verified",
 	"Verification": "Verification",
 	"Verify": "Verify",
+	"WebAuthn": "WebAuthn",
 	"WebAuthn Credential Information": "WebAuthn Credential Information",
 	"WebAuthn Credential": "WebAuthn Credential",
 	"WebAuthn Credentials": "WebAuthn Credentials",
 	"WebAuthn Credentials are widely considered the most secure means of authentication, regardless of if they're used for Multi-Factor Authentication or Passwordless Authentication": "WebAuthn Credentials are widely considered the most secure means of authentication, regardless of if they're used for Multi-Factor Authentication or Passwordless Authentication",
 	"Yes": "Yes",
+	"You can only register a single One-Time Password": "You can only register a single One-Time Password",
 	"You cancelled the attestation request": "You cancelled the attestation request",
 	"You cannot reuse your old password": "You cannot reuse your old password",
 	"You have registered this device already": "You have registered this device already",
diff --git a/web/src/components/PasswordMeter.tsx b/web/src/components/PasswordMeter.tsx
index 7a6fb61c2f54b..41a69d261b53a 100644
--- a/web/src/components/PasswordMeter.tsx
+++ b/web/src/components/PasswordMeter.tsx
@@ -93,7 +93,7 @@ const PasswordMeter = function (props: Props) {
             if (warning !== "") {
                 setFeedbackTitle(translate("The password does not meet the password policy"));
             }
-            setFeedback(translate(warning));
+            setFeedback(warning);
 
             setPasswordScore(score);
         } else if (props.policy.mode === PasswordPolicyMode.ZXCVBN) {
diff --git a/web/src/views/ConsentPortal/OpenIDConnect/DecisionFormView.tsx b/web/src/views/ConsentPortal/OpenIDConnect/DecisionFormView.tsx
index a25279de6e573..2e992208e0e6c 100644
--- a/web/src/views/ConsentPortal/OpenIDConnect/DecisionFormView.tsx
+++ b/web/src/views/ConsentPortal/OpenIDConnect/DecisionFormView.tsx
@@ -425,7 +425,9 @@ const DecisionFormView: React.FC<Props> = (props: Props) => {
                                                                       "The password was partially entered with Caps Lock",
                                                                       { ns: "portal" },
                                                                   )
-                                                                : translate("The password was entered with Caps Lock")}
+                                                                : translate("The password was entered with Caps Lock", {
+                                                                      ns: "portal",
+                                                                  })}
                                                         </Alert>
                                                     </Grid>
                                                 ) : null}
diff --git a/web/src/views/LoginPortal/SecondFactor/PasswordForm.tsx b/web/src/views/LoginPortal/SecondFactor/PasswordForm.tsx
index 2e332da591a5c..334106697c610 100644
--- a/web/src/views/LoginPortal/SecondFactor/PasswordForm.tsx
+++ b/web/src/views/LoginPortal/SecondFactor/PasswordForm.tsx
@@ -20,7 +20,7 @@ export interface Props {
 
 const PasswordForm = function (props: Props) {
     const { createErrorNotification } = useNotifications();
-    const { t: translate } = useTranslation();
+    const { t: translate } = useTranslation(["portal", "settings"]);
 
     const redirectionURL = useQueryParam(RedirectionURL);
     const { id: flowID, flow, subflow } = useFlow();
@@ -128,7 +128,7 @@ const PasswordForm = function (props: Props) {
                                 endAdornment: (
                                     <InputAdornment position="end">
                                         <IconButton
-                                            aria-label="toggle password visibility"
+                                            aria-label={translate("Toggle password visibility")}
                                             edge="end"
                                             size="large"
                                             onMouseDown={() => setShowPassword(true)}
@@ -178,7 +178,7 @@ const PasswordForm = function (props: Props) {
                         disabled={loading}
                         onClick={handleSignIn}
                     >
-                        {translate("Authenticate")}
+                        {translate("Authenticate", { ns: "settings" })}
                     </Button>
                 </Grid>
             </Grid>
diff --git a/web/src/views/ResetPassword/ResetPasswordStep1.tsx b/web/src/views/ResetPassword/ResetPasswordStep1.tsx
index 57686b13215f6..1991cb854ca14 100644
--- a/web/src/views/ResetPassword/ResetPasswordStep1.tsx
+++ b/web/src/views/ResetPassword/ResetPasswordStep1.tsx
@@ -107,10 +107,7 @@ const ResetPasswordStep1 = function () {
                         />
                     </Grid>
                     <Grid size={{ xs: 6 }}>
-                        <ComponentWithTooltip
-                            render={rateLimited}
-                            title={translate(translate("You have made too many requests"))}
-                        >
+                        <ComponentWithTooltip render={rateLimited} title={translate("You have made too many requests")}>
                             <Button
                                 id="reset-button"
                                 variant="contained"
diff --git a/web/src/views/Settings/Common/SecondFactorDialog.tsx b/web/src/views/Settings/Common/SecondFactorDialog.tsx
index 41816ba47b08c..036f806840787 100644
--- a/web/src/views/Settings/Common/SecondFactorDialog.tsx
+++ b/web/src/views/Settings/Common/SecondFactorDialog.tsx
@@ -42,7 +42,7 @@ type Props = {
 };
 
 const SecondFactorDialog = function (props: Props) {
-    const { t: translate } = useTranslation("settings");
+    const { t: translate } = useTranslation(["settings", "portal"]);
     const { classes } = useStyles();
 
     const [open, setOpen] = useState(false);
@@ -137,7 +137,7 @@ const SecondFactorDialog = function (props: Props) {
             <DialogContent>
                 <DialogContentText gutterBottom>
                     {translate(
-                        "In order to perform this action policy enforcement requires two faction authentication is performed",
+                        "In order to perform this action, policy enforcement requires that two-factor authentication is performed",
                     )}
                 </DialogContentText>
                 <Stepper activeStep={activeStep}>
@@ -176,7 +176,7 @@ const SecondFactorDialog = function (props: Props) {
                                     {translate("Email One-Time Code")}
                                 </Button>
                                 <Divider />
-                                <Typography variant={"h5"}>{translate("OR")}</Typography>
+                                <Typography variant={"h5"}>{translate("or", { ns: "portal" })}</Typography>
                                 <Divider />
                             </Fragment>
                         ) : null}
diff --git a/web/src/views/Settings/Common/SecondFactorMethodMobilePush.tsx b/web/src/views/Settings/Common/SecondFactorMethodMobilePush.tsx
index 332aa4b15af40..8d428139d10f9 100644
--- a/web/src/views/Settings/Common/SecondFactorMethodMobilePush.tsx
+++ b/web/src/views/Settings/Common/SecondFactorMethodMobilePush.tsx
@@ -33,7 +33,7 @@ export interface Props {
 }
 
 const SecondFactorMethodMobilePush = function (props: Props) {
-    const { t: translate } = useTranslation("settings");
+    const { t: translate } = useTranslation("portal");
     const { classes } = useStyles();
 
     const [state, setState] = useState(State.SignInInProgress);
diff --git a/web/src/views/Settings/Common/SecondFactorMethodOneTimePassword.tsx b/web/src/views/Settings/Common/SecondFactorMethodOneTimePassword.tsx
index 1ecd8f3d89c57..44865f27f0399 100644
--- a/web/src/views/Settings/Common/SecondFactorMethodOneTimePassword.tsx
+++ b/web/src/views/Settings/Common/SecondFactorMethodOneTimePassword.tsx
@@ -14,7 +14,7 @@ export interface Props {
 }
 
 const SecondFactorMethodOneTimePassword = function (props: Props) {
-    const { t: translate } = useTranslation("settings");
+    const { t: translate } = useTranslation(["settings", "portal"]);
 
     const [passcode, setPasscode] = useState("");
     const [state, setState] = useState(State.Idle);
@@ -49,7 +49,7 @@ const SecondFactorMethodOneTimePassword = function (props: Props) {
 
             setState(State.RateLimited);
 
-            createErrorNotification(translate("You have made too many requests"));
+            createErrorNotification(translate("You have made too many requests", { ns: "portal" }));
 
             timeoutRateLimit.current = setTimeout(() => {
                 setState(State.Idle);
@@ -80,7 +80,7 @@ const SecondFactorMethodOneTimePassword = function (props: Props) {
                     handleRateLimited(res.retryAfter);
                 }
             } else {
-                createErrorNotification(translate("The One-Time Password might be wrong"));
+                createErrorNotification(translate("The One-Time Password might be wrong", { ns: "portal" }));
                 setState(State.Failure);
             }
         } catch (err) {
diff --git a/web/src/views/Settings/Security/ChangePasswordDialog.tsx b/web/src/views/Settings/Security/ChangePasswordDialog.tsx
index d8d06b3832193..81674e761a0ee 100644
--- a/web/src/views/Settings/Security/ChangePasswordDialog.tsx
+++ b/web/src/views/Settings/Security/ChangePasswordDialog.tsx
@@ -29,7 +29,7 @@ interface Props {
 }
 
 const ChangePasswordDialog = (props: Props) => {
-    const { t: translate } = useTranslation("settings");
+    const { t: translate } = useTranslation(["settings", "portal"]);
 
     const { createSuccessNotification, createErrorNotification } = useNotifications();
 
@@ -95,7 +95,9 @@ const ChangePasswordDialog = (props: Props) => {
             setLoading(false);
         } catch {
             createErrorNotification(
-                translate("There was an issue completing the process the verification token might have expired"),
+                translate("There was an issue completing the process the verification token might have expired", {
+                    ns: "portal",
+                }),
             );
             setLoading(true);
         }
@@ -152,16 +154,12 @@ const ChangePasswordDialog = (props: Props) => {
 
                     case 500: // Internal Server Error
                     default:
-                        createErrorNotification(
-                            translate("There was an issue changing the {{item}}", { item: translate("password") }),
-                        );
+                        createErrorNotification(translate("There was an issue changing the password"));
                         break;
                 }
             } else {
                 // Handle non-axios errors
-                createErrorNotification(
-                    translate("There was an issue changing the {{item}}", { item: translate("password") }),
-                );
+                createErrorNotification(translate("There was an issue changing the password"));
             }
             return;
         }
@@ -206,7 +204,7 @@ const ChangePasswordDialog = (props: Props) => {
 
     return (
         <Dialog open={props.open} maxWidth="xs">
-            <DialogTitle>{translate("Change {{item}}", { item: translate("Password") })}</DialogTitle>
+            <DialogTitle>{translate("Change Password")}</DialogTitle>
             <DialogContent>
                 <FormControl id={"change-password-form"} disabled={loading}>
                     <Grid container spacing={1} alignItems={"center"} justifyContent={"center"} textAlign={"center"}>
diff --git a/web/src/views/Settings/Security/SecurityView.tsx b/web/src/views/Settings/Security/SecurityView.tsx
index 86c97de5301bf..91b79f9ec1bb7 100644
--- a/web/src/views/Settings/Security/SecurityView.tsx
+++ b/web/src/views/Settings/Security/SecurityView.tsx
@@ -12,7 +12,7 @@ import SecondFactorDialog from "@views/Settings/Common/SecondFactorDialog";
 import ChangePasswordDialog from "@views/Settings/Security/ChangePasswordDialog";
 
 const SettingsView = function () {
-    const { t: translate } = useTranslation("settings");
+    const { t: translate } = useTranslation(["settings", "portal"]);
     const theme = useTheme();
     const { createErrorNotification } = useNotifications();
 
@@ -113,7 +113,7 @@ const SettingsView = function () {
 
     useEffect(() => {
         if (fetchUserInfoError) {
-            createErrorNotification(translate("There was an issue retrieving user preferences"));
+            createErrorNotification(translate("There was an issue retrieving user preferences", { ns: "portal" }));
         }
         if (fetchConfigurationError) {
             createErrorNotification(translate("There was an issue retrieving configuration"));
@@ -139,7 +139,7 @@ const SettingsView = function () {
         );
 
         return configuration?.password_change_disabled ? (
-            <Tooltip title={translate("This is disabled by your administrator.")}>
+            <Tooltip title={translate("This is disabled by your administrator")}>
                 <Box component={"span"}>{buttonContent}</Box>
             </Tooltip>
         ) : (
diff --git a/web/src/views/Settings/TwoFactorAuthentication/CredentialItem.tsx b/web/src/views/Settings/TwoFactorAuthentication/CredentialItem.tsx
index 823d7fd8b5df0..8215e8cb05b7c 100644
--- a/web/src/views/Settings/TwoFactorAuthentication/CredentialItem.tsx
+++ b/web/src/views/Settings/TwoFactorAuthentication/CredentialItem.tsx
@@ -56,7 +56,7 @@ const CredentialItem = function (props: Props) {
                             </Typography>
                             <Typography variant={"caption"} display={{ xs: "none", sm: "block" }}>
                                 {props.last_used_at === undefined
-                                    ? translate("Never Used")
+                                    ? translate("Never used")
                                     : `${translate("Last Used")} ${timeSinceLastUsed}`}
                             </Typography>
                         </Stack>
diff --git a/web/src/views/Settings/TwoFactorAuthentication/WebAuthnCredentialEditDialog.tsx b/web/src/views/Settings/TwoFactorAuthentication/WebAuthnCredentialEditDialog.tsx
index b5db7269da549..20d7f3a19c43b 100644
--- a/web/src/views/Settings/TwoFactorAuthentication/WebAuthnCredentialEditDialog.tsx
+++ b/web/src/views/Settings/TwoFactorAuthentication/WebAuthnCredentialEditDialog.tsx
@@ -93,7 +93,7 @@ const WebAuthnCredentialEditDialog = function (props: Props) {
 
     return (
         <Dialog open={props.open} onClose={handleCancel}>
-            <DialogTitle>{translate("Edit {{item}}", { item: translate("WebAuthn Credential") })}</DialogTitle>
+            <DialogTitle>{translate("Edit WebAuthn Credential")}</DialogTitle>
             <DialogContent>
                 <DialogContentText>
                     {translate("Enter a new description for this WebAuthn Credential")}


Reviews:
user: login: james-d-elliott
body: Mostly looks good, couple questions and I'll take another look tomorrow.
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-12T14:10:09Z
user: login: michelheusschen
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T14:15:51Z
user: login: james-d-elliott
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-12T22:48:30Z
user: login: james-d-elliott
body: LGTM
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-12T23:19:56Z

Review comments:
diff_hunk: @@ -93,7 +93,7 @@ const PasswordMeter = function (props: Props) {
             if (warning !== "") {
                 setFeedbackTitle(translate("The password does not meet the password policy"));
             }
-            setFeedback(translate(warning));
+            setFeedback(warning);
path: web/src/components/PasswordMeter.tsx
user: login: james-d-elliott
body: Why was this changed?
created_at: 2025-05-12T14:07:07Z
author_association: MEMBER
diff_hunk: @@ -93,7 +93,7 @@ const PasswordMeter = function (props: Props) {
             if (warning !== "") {
                 setFeedbackTitle(translate("The password does not meet the password policy"));
             }
-            setFeedback(translate(warning));
+            setFeedback(warning);
path: web/src/components/PasswordMeter.tsx
user: login: michelheusschen
body: Already translated messages are appended to the `warning` string, making this call redundant
created_at: 2025-05-12T14:15:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -93,7 +93,7 @@ const PasswordMeter = function (props: Props) {
             if (warning !== "") {
                 setFeedbackTitle(translate("The password does not meet the password policy"));
             }
-            setFeedback(translate(warning));
+            setFeedback(warning);
path: web/src/components/PasswordMeter.tsx
user: login: james-d-elliott
body: Yep gotcha, makes sense.
created_at: 2025-05-12T22:48:30Z
author_association: MEMBER

PR comments:
user: login: authelia[bot]
created_at: 2025-05-12T13:48:18Z
body: Thanks for choosing to contribute @michelheusschen. We lint all PR's with golangci-lint and eslint, I may add a review to your PR with some suggestions.
    
You are free to apply the changes if you're comfortable, alternatively you are welcome to ask a team member for advice.

## Artifacts
These changes once approved by a team member will be published for testing on Buildkite, DockerHub and GitHub Container Registry.

### Docker Container
* `docker pull authelia/authelia:PR9496`
* `docker pull ghcr.io/authelia/authelia:PR9496`
author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-05-12T13:48:22Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

Listen up, fool! This batch o' changes is all about tightening up translation usage across various UI components. Translation hooks got new namespaces, translation keys got updated, and some redundant or incorrect translation calls got fixed. Ain't no core logic or control flow messed with—just better text and localization, sucka!

## Changes

| File(s)                                                                                                    | Change Summary                                                                                                                                                                                                                                                                                                                                                             |
|------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `web/src/components/PasswordMeter.tsx`                                                                     | Removed redundant translation call for the `warning` string before setting feedback. Now sets the raw warning string directly, fool!                                                                                                                                                                                                                                       |
| `web/src/views/ConsentPortal/OpenIDConnect/DecisionFormView.tsx`                                           | Updated translation call for Caps Lock alert to explicitly use the "portal" namespace.                                                                                                                                                                                                                                              |
| `web/src/views/LoginPortal/SecondFactor/PasswordForm.tsx`                                                  | Translation hook now uses "portal" and "settings" namespaces. Password visibility toggle aria-label and sign-in button now use translated strings with explicit namespaces.                                                                                                                                                          |
| `web/src/views/ResetPassword/ResetPasswordStep1.tsx`                                                       | Simplified translation call for tooltip title—no more double translation, just once, fool!                                                                                                                                                                                                                                          |
| `web/src/views/Settings/Common/SecondFactorDialog.tsx`                                                     | Translation hook now uses "settings" and "portal" namespaces. Fixed typo in dialog text. Changed "OR" translation key to lowercase and set namespace.                                                                                                                                        |
| `web/src/views/Settings/Common/SecondFactorMethodMobilePush.tsx`                                           | Changed translation namespace in hook from "settings" to "portal" for this component.                                                                                                                                                                                                        |
| `web/src/views/Settings/Common/SecondFactorMethodOneTimePassword.tsx`                                      | Translation hook now uses "settings" and "portal" namespaces. Error messages now translated with explicit "portal" namespace.                                                                                                                                                                |
| `web/src/views/Settings/Security/ChangePasswordDialog.tsx`                                                 | Translation hook now uses "settings" and "portal" namespaces. Error messages and dialog title simplified and now use explicit translation keys and namespaces.                                                                                                                               |
| `web/src/views/Settings/Security/SecurityView.tsx`                                                         | Translation hook now uses "settings" and "portal" namespaces. Error message and tooltip text updated for translation accuracy.                                                                                                                        |
| `web/src/views/Settings/TwoFactorAuthentication/CredentialItem.tsx`                                        | Changed translation string from "Never Used" to "Never used" (lowercase "used").                                                                                                                                                                                                            |
| `web/src/views/Settings/TwoFactorAuthentication/WebAuthnCredentialEditDialog.tsx`                          | Dialog title now uses a static translation string ("Edit WebAuthn Credential") instead of dynamic interpolation.                                                                                                                                                                             |

## Sequence Diagram(s)

I pity the fool who needs a sequence diagram for translation tweaks! Ain't no new features or control flow changes here, just text and translation updates, so no diagram needed!

<!-- walkthrough_end -->

<!-- announcements_start -->

> [!TIP]
> <details>
> <summary>⚡️ Faster reviews with caching</summary>
> 
> - CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure `Review - Disable Cache` at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the `Data Retention` setting under your Organization Settings.
> 
> Enjoy the performance boost—your workflow just got faster.
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 11346506209e8c1856a160c3344d6060a623f196 and 5f7fb37256981aac78ea486a985c742880907db2.

</details>

<details>
<summary>⛔ Files ignored due to path filters (3)</summary>

* `internal/server/locales/en/consent.json` is excluded by `!**/*.json`
* `internal/server/locales/en/portal.json` is excluded by `!**/*.json`
* `internal/server/locales/en/settings.json` is excluded by `!**/*.json`

</details>

<details>
<summary>📒 Files selected for processing (11)</summary>

* `web/src/components/PasswordMeter.tsx` (1 hunks)
* `web/src/views/ConsentPortal/OpenIDConnect/DecisionFormView.tsx` (1 hunks)
* `web/src/views/LoginPortal/SecondFactor/PasswordForm.tsx` (3 hunks)
* `web/src/views/ResetPassword/ResetPasswordStep1.tsx` (1 hunks)
* `web/src/views/Settings/Common/SecondFactorDialog.tsx` (3 hunks)
* `web/src/views/Settings/Common/SecondFactorMethodMobilePush.tsx` (1 hunks)
* `web/src/views/Settings/Common/SecondFactorMethodOneTimePassword.tsx` (3 hunks)
* `web/src/views/Settings/Security/ChangePasswordDialog.tsx` (4 hunks)
* `web/src/views/Settings/Security/SecurityView.tsx` (3 hunks)
* `web/src/views/Settings/TwoFactorAuthentication/CredentialItem.tsx` (1 hunks)
* `web/src/views/Settings/TwoFactorAuthentication/WebAuthnCredentialEditDialog.tsx` (1 hunks)

</details>

<details>
<summary>🔇 Additional comments (23)</summary><blockquote>

<details>
<summary>web/src/views/Settings/TwoFactorAuthentication/CredentialItem.tsx (1)</summary>

`59-59`: **Good change to fix case inconsistency, fool!**

I pity the fool who uses inconsistent capitalization! This change makes the "Never used" text consistent with other lowercase usage in the UI. Looks good, sucka!

</details>
<details>
<summary>web/src/views/Settings/TwoFactorAuthentication/WebAuthnCredentialEditDialog.tsx (1)</summary>

`96-96`: **Direct translation is better than nested mess, fool!**

Listen up! This change is smart - replacing that complicated nested translation pattern with a direct string. Now translators get proper context instead of trying to piece together them fragments. Way better for different languages, sucka!

</details>
<details>
<summary>web/src/views/Settings/Common/SecondFactorMethodMobilePush.tsx (1)</summary>

`36-36`: **Right namespace for the job, fool!**

I ain't getting on no plane with the wrong translation namespace! You fixed it good by changing from "settings" to "portal" - that's where these translations belong! This component is all about the portal functionality, not settings. Quit your jibber jabber and keep these namespaces organized!

</details>
<details>
<summary>web/src/views/Settings/Common/SecondFactorMethodOneTimePassword.tsx (3)</summary>

`17-17`: **Multiple namespaces is the way, sucka!**

That's right! Now you're using both "settings" and "portal" namespaces together. I pity the fool who tries to use just one namespace when you need both!

---

`52-52`: **Clear namespace for error message, fool!**

Adding that explicit "portal" namespace is exactly what this error message needs. No more guessing games about where to find translations! I love it when a plan comes together!

---

`83-83`: **Another namespace fix! Good work, sucka!**

You're on a roll! Specifying the "portal" namespace for this error message too keeps everything consistent. That's how we roll - organized and clear!

</details>
<details>
<summary>web/src/views/ConsentPortal/OpenIDConnect/DecisionFormView.tsx (1)</summary>

`428-430`: **Proper namespace for Caps Lock warning, fool!**

I pity the fool who forgets the namespace! Adding that explicit "portal" namespace to match the pattern of the warning right above it is smart thinkin'. Consistency across error messages makes for stronger code, and I ain't talkin' weak code, sucka!

</details>
<details>
<summary>web/src/views/Settings/Security/SecurityView.tsx (3)</summary>

`15-15`: **Good move addin' them translation namespaces, fool!**

I pity the fool who forgets to include all necessary translation namespaces! Adding "portal" alongside "settings" means you can grab translations from both places. That's smart thinkin'!

---

`116-116`: **Namespace specification is the way to go, sucka!**

You done good specifying that "portal" namespace explicitly! When you got multiple namespaces loaded, you gotta tell the system exactly where to find that translation. That's how we avoid confusion, fool!

---

`142-142`: **Droppin' that period like a hot potato! Good cleanup!**

I ain't got time for unnecessary punctuation! Removing that trailing period from the tooltip makes it consistent with other messages. Clean UI is the way to go, fool!

</details>
<details>
<summary>web/src/views/ResetPassword/ResetPasswordStep1.tsx (1)</summary>

`110-110`: **No more double translation nonsense! That's what I'm talkin' about!**

I pity the fool who translates somethin' twice! You fixed that nested translate call that was causin' trouble. One translation is enough, sucka! This fix prevents potential issues and makes the code cleaner.

</details>
<details>
<summary>web/src/views/LoginPortal/SecondFactor/PasswordForm.tsx (3)</summary>

`23-23`: **Two namespaces are better than one! Smart move, fool!**

Adding both "portal" and "settings" namespaces is the right way to go! Now you can grab translations from both places without no trouble!

---

`131-131`: **Accessibility ain't no joke! Good translation for screen readers!**

I pity the fool who forgets about accessibility! Making that aria-label translatable helps users with screen readers in different languages. That's what I call thinkin' of everybody!

---

`181-181`: **Namespace specification is the way to go! You done right!**

Specifying that "settings" namespace for "Authenticate" makes sure we're gettin' the right translation. That's how we roll with proper internationalization, fool!

</details>
<details>
<summary>web/src/components/PasswordMeter.tsx (1)</summary>

`96-96`: **Cut out that redundant translation! Smart thinkin'!**

I pity the fool who translates the same string twice! That warning variable already got all them translated pieces with formatting. Passin' it through translate again would mess things up! You fixed it good by setting the feedback directly.

</details>
<details>
<summary>web/src/views/Settings/Common/SecondFactorDialog.tsx (3)</summary>

`45-45`: **I approve this translation namespace update, fool!**

You expanded that useTranslation hook to include both "settings" and "portal" namespaces! That's smart thinkin' - now the component can access translations from both places without breakin' a sweat!

---

`140-141`: **Typo correction looks good, sucka!**

You fixed that grammar from "two faction authentication" to "two-factor authentication" - that's the right way to say it! I pity the fool who can't spell "factor" correctly!

---

`179-179`: **Good work specifying that namespace, fool!**

You changed that "OR" translation to lowercase "or" and properly set the namespace to "portal". That's the way to do it! Makes it crystal clear for translators where to find this text!

</details>
<details>
<summary>web/src/views/Settings/Security/ChangePasswordDialog.tsx (5)</summary>

`32-32`: **Smart move adding that portal namespace, fool!**

You added "portal" alongside "settings" in that translation hook! That's how you make sure you got access to all the translations you need! I pity the fool who forgets their namespaces!

---

`98-100`: **Explicit namespace is the way to go, sucka!**

You made that error message specify "portal" namespace! That's how you keep your translations organized! No confusion about where this text comes from now!

---

`157-157`: **Simplified error message is better, fool!**

You got rid of that complicated dynamic translation with the word "password" and went straight for a simple string! Much clearer for translators to work with! No more messy templates!

---

`162-162`: **Consistency is key, sucka!**

You made the same simplification here too! I like when a fool stays consistent with their changes! Makes the whole codebase more maintainable!

---

`207-207`: **Direct translation is the right approach, fool!**

You changed that dialog title from a template string to a direct "Change Password" translation! That's the way to go! Gives translators better context and makes the code cleaner! I pity the fool who uses complicated translation patterns when simple ones work better!

</details>

</blockquote></details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=authelia/authelia&utm_content=9496):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` or `@coderabbitai title` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR