From 8fbca78772b8f929c02bfb106daaae226e06b27f Mon Sep 17 00:00:00 2001
From: Myzel394 <50424412+Myzel394@users.noreply.github.com>
Date: Sat, 4 Mar 2023 21:31:47 +0100
Subject: [PATCH 01/22] refactor: Improve i18n for login
---
public/locales/en-US/common.json | 12 +++++
public/locales/en-US/login.json | 35 +++++++++++++++
public/locales/en-US/translation.json | 44 -------------------
.../ConfirmCodeForm/ConfirmCodeForm.tsx | 20 ++++-----
.../LoginRoute/ConfirmFromDifferentDevice.tsx | 8 ++--
src/route-widgets/LoginRoute/EmailForm.tsx | 12 ++---
src/route-widgets/LoginRoute/OTPForm.tsx | 40 ++++++++++-------
7 files changed, 88 insertions(+), 83 deletions(-)
create mode 100644 public/locales/en-US/common.json
create mode 100644 public/locales/en-US/login.json
diff --git a/public/locales/en-US/common.json b/public/locales/en-US/common.json
new file mode 100644
index 0000000..c8704c6
--- /dev/null
+++ b/public/locales/en-US/common.json
@@ -0,0 +1,12 @@
+{
+ "fields": {
+ "email": {
+ "label": "Email",
+ "placeholder": "johndoe@example.com"
+ },
+ "2faCode": {
+ "label": "Code",
+ "placeholder": "123456"
+ }
+ }
+}
diff --git a/public/locales/en-US/login.json b/public/locales/en-US/login.json
new file mode 100644
index 0000000..899bd47
--- /dev/null
+++ b/public/locales/en-US/login.json
@@ -0,0 +1,35 @@
+{
+ "title": "Log in",
+ "forms": {
+ "email": {
+ "description": "We will send you a code to log in",
+ "continueActionLabel": "Send code"
+ },
+ "confirmCode": {
+ "title": "You got mail!",
+ "description": "We sent you a code to your email. Enter it below to login",
+ "continueActionLabel": "Log in",
+ "allowLoginFromDifferentDevices": "Allow login from different devices",
+ "expiringSoonWarning": "Your code will expire in less than a minute.",
+ "fields": {
+ "code": {
+ "label": "Verification Code",
+ "errors": {
+ "invalidChars": "Invalid verification code"
+ }
+ }
+ }
+ },
+ "confirmFromDifferentDevice": {
+ "title": "Login failed",
+ "description": "You could not be logged in. This could either be because you are not allowed to login from different devices or the verification code is invalid or expired."
+ },
+ "otp": {
+ "title": "Two-Factor Authentication",
+ "description": "Enter the code from your authenticator app",
+ "isUnavailable": "Your OTP verification time expired or you exceeded the maximum number of attempts. Please log in again.",
+ "codesLostActionLabel": "I lost my codes",
+ "continueActionLabel": "Log in"
+ }
+ }
+}
diff --git a/public/locales/en-US/translation.json b/public/locales/en-US/translation.json
index 7c6ebbf..9148b99 100644
--- a/public/locales/en-US/translation.json
+++ b/public/locales/en-US/translation.json
@@ -26,50 +26,6 @@
"title": "Overview",
"description": "Not much to see here, yet."
},
- "LoginRoute": {
- "forms": {
- "email": {
- "title": "Sign in",
- "description": "We'll send you a verification code to your email.",
- "continueAction": "Send Code",
- "form": {
- "email": {
- "label": "Email",
- "placeholder": "johndoe@example.com"
- }
- }
- },
- "confirmCode": {
- "title": "You got mail!",
- "description": "We sent you a code to your email. Enter it below to login",
- "continueAction": "Log in",
- "allowLoginFromDifferentDevices": "Allow login from different devices",
- "expiringSoon": "Your code will expire in less than a minute.",
- "form": {
- "code": {
- "label": "Verification Code",
- "errors": {
- "invalidChars": "Invalid verification code"
- }
- }
- }
- },
- "confirmFromDifferentDevice": {
- "title": "Login failed",
- "description": "You could not be logged in. This could either be because you are not allowed to login from different devices or the verification code is invalid or expired."
- },
- "otp": {
- "title": "Two-factor authentication",
- "description": "Please enter the code from your authenticator app.",
- "submit": "Log in",
- "lost": "I lost my codes",
- "code": {
- "label": "Code"
- },
- "unavailable": "Your OTP verification time expired or you exceeded the maximum number of attempts. Please log in again."
- }
- }
- },
"SignupRoute": {
"forms": {
"email": {
diff --git a/src/route-widgets/LoginRoute/ConfirmCodeForm/ConfirmCodeForm.tsx b/src/route-widgets/LoginRoute/ConfirmCodeForm/ConfirmCodeForm.tsx
index 8cc1c31..94ffa78 100644
--- a/src/route-widgets/LoginRoute/ConfirmCodeForm/ConfirmCodeForm.tsx
+++ b/src/route-widgets/LoginRoute/ConfirmCodeForm/ConfirmCodeForm.tsx
@@ -55,7 +55,7 @@ export default function ConfirmCodeForm({
}: ConfirmCodeFormProps): ReactElement {
const settings = useLoaderData() as ServerSettings
const expirationTime = isDev ? 70 : settings.emailLoginExpirationInSeconds
- const {t} = useTranslation()
+ const {t} = useTranslation(["login", "common"])
const requestDate = useMemo(() => new Date(), [])
const [isExpiringSoon, setIsExpiringSoon] = useState(false)
@@ -67,7 +67,7 @@ export default function ConfirmCodeForm({
.max(settings.emailLoginTokenLength)
.test(
"chars",
- t("routes.LoginRoute.forms.confirmCode.form.code.errors.invalidChars") as string,
+ t("forms.confirmCode.fields.code.errors.invalidChars") as string,
code => {
if (!code) {
return false
@@ -78,7 +78,7 @@ export default function ConfirmCodeForm({
return code.split("").every(char => chars.includes(char))
},
)
- .label(t("routes.LoginRoute.forms.confirmCode.form.code.label")),
+ .label(t("forms.confirmCode.fields.code.label")),
})
const {mutateAsync} = useMutation<
@@ -165,7 +165,7 @@ export default function ConfirmCodeForm({
>
- {t("routes.LoginRoute.forms.confirmCode.title")}
+ {t("forms.confirmCode.title")}
@@ -175,7 +175,7 @@ export default function ConfirmCodeForm({
- {t("routes.LoginRoute.forms.confirmCode.description")}
+ {t("forms.confirmCode.description")}
@@ -196,7 +196,7 @@ export default function ConfirmCodeForm({
}
labelPlacement="end"
label={t(
- "routes.LoginRoute.forms.confirmCode.allowLoginFromDifferentDevices",
+ "forms.confirmCode.allowLoginFromDifferentDevices",
)}
/>
@@ -206,9 +206,7 @@ export default function ConfirmCodeForm({
fullWidth
name="code"
id="code"
- label={t(
- "routes.LoginRoute.forms.confirmCode.form.code.label",
- )}
+ label={t("forms.confirmCode.fields.code.label")}
value={formik.values.code}
onChange={event => {
formik.setFieldValue(
@@ -250,7 +248,7 @@ export default function ConfirmCodeForm({
type="submit"
startIcon={}
>
- {t("routes.LoginRoute.forms.confirmCode.continueAction")}
+ {t("forms.confirmCode.continueActionLabel")}
@@ -260,7 +258,7 @@ export default function ConfirmCodeForm({
- {t("routes.LoginRoute.forms.confirmCode.expiringSoon")}
+ {t("forms.confirmCode.expiringSoonWarning")}
>
diff --git a/src/route-widgets/LoginRoute/ConfirmFromDifferentDevice.tsx b/src/route-widgets/LoginRoute/ConfirmFromDifferentDevice.tsx
index 5f0181e..c05bf8e 100644
--- a/src/route-widgets/LoginRoute/ConfirmFromDifferentDevice.tsx
+++ b/src/route-widgets/LoginRoute/ConfirmFromDifferentDevice.tsx
@@ -22,7 +22,7 @@ export default function ConfirmFromDifferentDevice({
token,
onConfirm,
}: ConfirmFromDifferentDeviceProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation(["login"])
const {mutate, isLoading, isError} = useMutation(
() =>
verifyLoginWithEmail({
@@ -51,14 +51,12 @@ export default function ConfirmFromDifferentDevice({
- {t("routes.LoginRoute.forms.confirmFromDifferentDevice.title")}
+ {t("forms.confirmFromDifferentDevice.title")}
- {t(
- "routes.LoginRoute.forms.confirmFromDifferentDevice.description",
- )}
+ {t("forms.confirmFromDifferentDevice.description")}
diff --git a/src/route-widgets/LoginRoute/EmailForm.tsx b/src/route-widgets/LoginRoute/EmailForm.tsx
index 69f07f6..5d87e7f 100644
--- a/src/route-widgets/LoginRoute/EmailForm.tsx
+++ b/src/route-widgets/LoginRoute/EmailForm.tsx
@@ -24,7 +24,7 @@ interface Form {
}
export default function EmailForm({onLogin, email: preFilledEmail}: EmailFormProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation(["login", "common"])
const $password = useRef(null)
const schema = yup.object().shape({
@@ -32,7 +32,7 @@ export default function EmailForm({onLogin, email: preFilledEmail}: EmailFormPro
.string()
.email()
.required()
- .label(t("routes.LoginRoute.forms.email.form.email.label")),
+ .label(t("fields.email.label", {ns: "common"})),
})
const {mutateAsync} = useMutation(loginWithEmail, {
@@ -63,9 +63,9 @@ export default function EmailForm({onLogin, email: preFilledEmail}: EmailFormPro
))}
-
- {t("routes.SettingsRoute.2fa.setup.recoveryCodes.description")}
-
+ {t("setup.recoveryCodes.description")}
diff --git a/src/routes/Settings2FARoute.tsx b/src/routes/Settings2FARoute.tsx
index 068dc3c..4c71a7b 100644
--- a/src/routes/Settings2FARoute.tsx
+++ b/src/routes/Settings2FARoute.tsx
@@ -11,20 +11,18 @@ import Setup2FA from "~/route-widgets/Settings2FARoute/Setup2FA"
import getHas2FAEnabled from "~/apis/get-has-2fa-enabled"
export default function Settings2FARoute(): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("settings-2fa")
const queryKey = ["get_2fa_enabled"]
const query = useQuery(queryKey, getHas2FAEnabled)
return (
-
+ query={query}>
{has2FAEnabled =>
has2FAEnabled ? (
-
- {t("routes.SettingsRoute.2fa.alreadyEnabled")}
-
+ {t("alreadyEnabled")}
From 67ceddc3f7ca14e1d07fdc1b85bc7b2d05e1f3bd Mon Sep 17 00:00:00 2001
From: Myzel394 <50424412+Myzel394@users.noreply.github.com>
Date: Sun, 5 Mar 2023 10:08:41 +0100
Subject: [PATCH 12/22] refactor: Improve i18n for settings 2fa
---
public/locales/en-US/settings-2fa.json | 4 +-
public/locales/en-US/translation.json | 38 -------------------
.../Settings2FARoute/Delete2FA.tsx | 16 ++++----
3 files changed, 10 insertions(+), 48 deletions(-)
diff --git a/public/locales/en-US/settings-2fa.json b/public/locales/en-US/settings-2fa.json
index 1c2333e..fb4e637 100644
--- a/public/locales/en-US/settings-2fa.json
+++ b/public/locales/en-US/settings-2fa.json
@@ -14,7 +14,7 @@
"success": "You have successfully enabled 2FA!"
},
"delete": {
- "label": "Disable 2FA",
+ "title": "Disable 2FA",
"steps": {
"askType": {
"code": "I have my 2FA code",
@@ -27,7 +27,7 @@
"label": "Recovery Code"
}
},
- "submit": "Disable 2FA",
+ "continueActionLabel": "Disable 2FA",
"success": "You have successfully disabled 2FA!"
}
}
diff --git a/public/locales/en-US/translation.json b/public/locales/en-US/translation.json
index 2b285be..5610130 100644
--- a/public/locales/en-US/translation.json
+++ b/public/locales/en-US/translation.json
@@ -89,44 +89,6 @@
}
}
},
- "SettingsRoute": {
- "2fa": {
- "title": "Two-Factor-Authentication",
- "alreadyEnabled": "You have successfully enabled 2FA!",
- "setup": {
- "description": "Enable 2FA to add an extra layer of security to your account. Each time you log in, you will need to enter a code generated from your authenticator app. This makes it harder for an attacker to hack into your account as they would need to have access to your phone.",
- "setupLabel": "Enable 2FA",
- "code": {
- "label": "Code",
- "description": "Enter the code generated by your authenticator app.",
- "onlyDigits": "The code can only contain digits."
- },
- "submit": "Enable 2FA",
- "expired": "The verification time for your current Two-Factor-Authentication code has expired. A new code has been generated.",
- "recoveryCodes": {
- "title": "Note down your recovery codes",
- "description": "These codes are used to recover your account if you lose access to your authenticator app. Note them down and store them in a safe place. You will not be able to view them again. Do not store them in your password manager. IF YOU LOSE YOUR RECOVERY CODES, YOU WILL LOSE ACCESS TO YOUR ACCOUNT. WE WILL NOT BE ABLE TO HELP YOU.",
- "submit": "I have noted down my recovery codes"
- },
- "success": "You have successfully enabled 2FA!"
- },
- "delete": {
- "showAction": "Disable 2FA",
- "askType": {
- "code": "I have my 2FA code",
- "recoveryCode": "I have a recovery code"
- },
- "askCode": {
- "label": "Code"
- },
- "askRecoveryCode": {
- "label": "Recovery Code"
- },
- "submit": "Disable 2FA",
- "success": "You have successfully disabled 2FA!"
- }
- }
- },
"ReservedAliasesRoute": {
"title": "Reserved Aliases",
"pageActions": {
diff --git a/src/route-widgets/Settings2FARoute/Delete2FA.tsx b/src/route-widgets/Settings2FARoute/Delete2FA.tsx
index eb0c2a0..146554d 100644
--- a/src/route-widgets/Settings2FARoute/Delete2FA.tsx
+++ b/src/route-widgets/Settings2FARoute/Delete2FA.tsx
@@ -17,7 +17,7 @@ export interface Delete2FAProps {
}
export default function Delete2FA({onSuccess}: Delete2FAProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("settings-2fa")
const {showSuccess, showError} = useErrorSuccessSnacks()
const {mutate} = useMutation(delete2FA, {
onSuccess: () => {
@@ -36,7 +36,7 @@ export default function Delete2FA({onSuccess}: Delete2FAProps): ReactElement {
case "showAction":
return (
)
@@ -45,7 +45,7 @@ export default function Delete2FA({onSuccess}: Delete2FAProps): ReactElement {
@@ -53,7 +53,7 @@ export default function Delete2FA({onSuccess}: Delete2FAProps): ReactElement {
onClick={() => setView("askRecoveryCode")}
startIcon={}
>
- {t("routes.SettingsRoute.2fa.delete.askType.recoveryCode")}
+ {t("delete.steps.askType.recoveryCode")}
@@ -65,7 +65,7 @@ export default function Delete2FA({onSuccess}: Delete2FAProps): ReactElement {
setValue(e.target.value)}
/>
@@ -76,7 +76,7 @@ export default function Delete2FA({onSuccess}: Delete2FAProps): ReactElement {
variant="contained"
startIcon={}
>
- {t("routes.SettingsRoute.2fa.delete.submit")}
+ {t("delete.continueActionLabel")}
@@ -88,7 +88,7 @@ export default function Delete2FA({onSuccess}: Delete2FAProps): ReactElement {
setValue(e.target.value)}
/>
@@ -99,7 +99,7 @@ export default function Delete2FA({onSuccess}: Delete2FAProps): ReactElement {
variant="contained"
startIcon={}
>
- {t("routes.SettingsRoute.2fa.delete.submit")}
+ {t("delete.continueActionLabel")}
From 908d1b81a46a3c274bb9cc18fb1a18ac6917b687 Mon Sep 17 00:00:00 2001
From: Myzel394 <50424412+Myzel394@users.noreply.github.com>
Date: Sun, 5 Mar 2023 10:19:41 +0100
Subject: [PATCH 13/22] refactor: Improve i18n for admin global settings
---
.../locales/en-US/admin-global-settings.json | 71 ++++++++
public/locales/en-US/admin.json | 7 +
public/locales/en-US/common.json | 4 +-
public/locales/en-US/translation.json | 92 ----------
.../GlobalSettingsRoute/SettingsDisabled.tsx | 9 +-
.../GlobalSettingsRoute/SettingsForm.tsx | 172 +++++-------------
src/routes/AdminRoute.tsx | 8 +-
7 files changed, 138 insertions(+), 225 deletions(-)
create mode 100644 public/locales/en-US/admin-global-settings.json
create mode 100644 public/locales/en-US/admin.json
diff --git a/public/locales/en-US/admin-global-settings.json b/public/locales/en-US/admin-global-settings.json
new file mode 100644
index 0000000..155606c
--- /dev/null
+++ b/public/locales/en-US/admin-global-settings.json
@@ -0,0 +1,71 @@
+{
+ "title": "Global Settings",
+ "description": "Configure global settings for your instance.",
+ "updatedSuccessfullyMessage": "Settings have been saved successfully!",
+ "randomAliasesPreview": {
+ "title": "Random aliases will look like this",
+ "helperText": "This is just a preview. Those are not real aliases."
+ },
+ "randomAliasesIncreaseExplanation": "Random aliases' length will be increased from {{originalLength}} to {{increasedLength}} characters after {{amount}} aliases have been created.",
+ "resetLabel": "Reset to defaults",
+ "disabled": {
+ "title": "Global settings are disabled",
+ "description": "Global settings have been disabled. You can enable them in the configuration file."
+ },
+ "fields": {
+ "randomEmailIdMinLength": {
+ "label": "Minimum random alias ID length",
+ "description": "The minimum length for randomly generated emails. The server will automatically increase the length if required so."
+ },
+ "randomEmailIdChars": {
+ "label": "Random alias character pool",
+ "description": "Characters that are used to generate random emails."
+ },
+ "randomEmailLengthIncreaseOnPercentage": {
+ "label": "Percentage of used aliases",
+ "description": "If the percentage of used random email IDs is higher than this value, the length of the random email ID will be increased. This is used to prevent spammers from guessing the email ID."
+ },
+ "customEmailSuffixLength": {
+ "label": "Custom email suffix length",
+ "description": "The length of the custom email suffix."
+ },
+ "customEmailSuffixChars": {
+ "label": "Custom email suffix character pool",
+ "description": "Characters that are used to generate custom email suffixes."
+ },
+ "imageProxyStorageLifeTimeInHours": {
+ "label": "Image proxy storage lifetime",
+ "description": "The lifetime of images that are stored on the server in hours. After this time, the image will be deleted.",
+ "unit_one": "hour",
+ "unit_other": "hours"
+ },
+ "enableImageProxy": {
+ "label": "Enable image proxy",
+ "description": "If enabled, images will be proxied through the server. This enhances your user's privacy as their ip address will not be leaked."
+ },
+ "enableImageProxyStorage": {
+ "label": "Enable image proxy storage",
+ "description": "If enabled, images will be stored on the server and forwarded to the user. This makes email tracking nearly impossible as every message will be marked as read instantly, which is obviously not true as a user is typically not able to view an email in just a few seconds after it has been sent. This will only affect new images."
+ },
+ "userEmailEnableDisposableEmails": {
+ "label": "Enable disposable emails for new accounts",
+ "description": "If enabled, users will be able to use disposable emails when creating a new account. This will only affect new accounts."
+ },
+ "userEmailEnableOtherRelays": {
+ "label": "Enable other relays for new accounts",
+ "description": "If enabled, users will be able to use other relays (such as SimpleLogin or DuckDuckGo's Email Tracking Protection) when creating a new account. This will only affect new accounts."
+ },
+ "allowStatistics": {
+ "label": "Allow statistics",
+ "description": "If enabled, your instance will collect anonymous statistics and share them. They will only be stored locally on this instance but made public."
+ },
+ "allowAliasDeletion": {
+ "label": "Allow alias deletion",
+ "description": "If enabled, users will be able to delete their aliases."
+ },
+ "maxAliasesPerUser": {
+ "label": "Maximum aliases per user",
+ "description": "The maximum number of aliases a user can create. 0 means unlimited. Existing aliases will not be affected."
+ }
+ }
+}
diff --git a/public/locales/en-US/admin.json b/public/locales/en-US/admin.json
new file mode 100644
index 0000000..7eb0c5d
--- /dev/null
+++ b/public/locales/en-US/admin.json
@@ -0,0 +1,7 @@
+{
+ "title": "Site configuration",
+ "routes": {
+ "reservedAliases": "Reserved Aliases",
+ "settings": "Global Settings"
+ }
+}
diff --git a/public/locales/en-US/common.json b/public/locales/en-US/common.json
index 2aa8ffc..ebc82d5 100644
--- a/public/locales/en-US/common.json
+++ b/public/locales/en-US/common.json
@@ -56,7 +56,9 @@
"noLabel": "No",
"continueLabel": "Continue",
"unavailableValue": "Unavailable",
- "experimentalFeatureExplanation": "This is an experimental feature."
+ "experimentalFeatureExplanation": "This is an experimental feature.",
+ "saveLabel": "Save",
+ "resetLabel": "Reset"
},
"noSearchResults": {
"title": "Nothing found",
diff --git a/public/locales/en-US/translation.json b/public/locales/en-US/translation.json
index 5610130..bcfb7d6 100644
--- a/public/locales/en-US/translation.json
+++ b/public/locales/en-US/translation.json
@@ -129,98 +129,6 @@
"reservedAliases": "Reserved Aliases",
"settings": "Global Settings"
},
- "forms": {
- "reservedAliases": {
- "title": "Reserved Aliases",
- "description": "Define what alias should forward to whom.",
- "saveAction": "Create Alias",
- "fields": {
- "local": {
- "label": "Local"
- },
- "users": {
- "label": "Users",
- "me": "{{email}} (Me)"
- }
- },
- "explanation": {
- "step1": "User from outside",
- "step2": "Sends mail to",
- "step4": "KleckRelay forwards to"
- }
- },
- "settings": {
- "randomEmailIdMinLength": {
- "label": "Minimum random alias ID length",
- "description": "The minimum length for randomly generated emails. The server will automatically increase the length if required so."
- },
- "randomEmailIdChars": {
- "label": "Random alias character pool",
- "description": "Characters that are used to generate random emails."
- },
- "randomEmailLengthIncreaseOnPercentage": {
- "label": "Percentage of used aliases",
- "description": "If the percentage of used random email IDs is higher than this value, the length of the random email ID will be increased. This is used to prevent spammers from guessing the email ID."
- },
- "customEmailSuffixLength": {
- "label": "Custom email suffix length",
- "description": "The length of the custom email suffix."
- },
- "customEmailSuffixChars": {
- "label": "Custom email suffix character pool",
- "description": "Characters that are used to generate custom email suffixes."
- },
- "imageProxyStorageLifeTimeInHours": {
- "label": "Image proxy storage lifetime",
- "description": "The lifetime of images that are stored on the server in hours. After this time, the image will be deleted.",
- "unit_one": "hour",
- "unit_other": "hours"
- },
- "enableImageProxy": {
- "label": "Enable image proxy",
- "description": "If enabled, images will be proxied through the server. This enhances your user's privacy as their ip address will not be leaked."
- },
- "enableImageProxyStorage": {
- "label": "Enable image proxy storage",
- "description": "If enabled, images will be stored on the server and forwarded to the user. This makes email tracking nearly impossible as every message will be marked as read instantly, which is obviously not true as a user is typically not able to view an email in just a few seconds after it has been sent. This will only affect new images."
- },
- "userEmailEnableDisposableEmails": {
- "label": "Enable disposable emails for new accounts",
- "description": "If enabled, users will be able to use disposable emails when creating a new account. This will only affect new accounts."
- },
- "userEmailEnableOtherRelays": {
- "label": "Enable other relays for new accounts",
- "description": "If enabled, users will be able to use other relays (such as SimpleLogin or DuckDuckGo's Email Tracking Protection) when creating a new account. This will only affect new accounts."
- },
- "allowStatistics": {
- "label": "Allow statistics",
- "description": "If enabled, your instance will collect anonymous statistics and share them. They will only be stored locally on this instance but made public."
- },
- "allowAliasDeletion": {
- "label": "Allow alias deletion",
- "description": "If enabled, users will be able to delete their aliases."
- },
- "maxAliasesPerUser": {
- "label": "Maximum aliases per user",
- "description": "The maximum number of aliases a user can create. 0 means unlimited. Existing aliases will not be affected."
- }
- }
- },
- "settings": {
- "title": "Global Settings",
- "description": "Configure global settings for your instance.",
- "successMessage": "Settings have been saved successfully!",
- "randomAliasesPreview": {
- "title": "Random aliases will look like this",
- "helperText": "This is just a preview. Those are not real aliases."
- },
- "randomAliasesIncreaseExplanation": "Random aliases' length will be increased from {{originalLength}} to {{increasedLength}} characters after {{amount}} aliases have been created.",
- "resetLabel": "Reset to defaults",
- "disabled": {
- "title": "Global settings are disabled",
- "description": "Global settings have been disabled. You can enable them in the configuration file."
- }
- },
"reservedAlias": {
"actions": {
"delete": {
diff --git a/src/route-widgets/GlobalSettingsRoute/SettingsDisabled.tsx b/src/route-widgets/GlobalSettingsRoute/SettingsDisabled.tsx
index 79a15e3..692f9f6 100644
--- a/src/route-widgets/GlobalSettingsRoute/SettingsDisabled.tsx
+++ b/src/route-widgets/GlobalSettingsRoute/SettingsDisabled.tsx
@@ -5,8 +5,7 @@ import {useTranslation} from "react-i18next"
import {Container, Grid, Typography} from "@mui/material"
export default function SettingsDisabled(): ReactElement {
- console.log("asdas")
- const {t} = useTranslation()
+ const {t} = useTranslation("admin-global-settings")
return (
@@ -21,16 +20,14 @@ export default function SettingsDisabled(): ReactElement {
>
- {t("routes.AdminRoute.settings.disabled.title")}
+ {t("disabled.title")}
-
- {t("routes.AdminRoute.settings.disabled.description")}
-
+ {t("disabled.description")}
diff --git a/src/route-widgets/GlobalSettingsRoute/SettingsForm.tsx b/src/route-widgets/GlobalSettingsRoute/SettingsForm.tsx
index 81f91d7..948867a 100644
--- a/src/route-widgets/GlobalSettingsRoute/SettingsForm.tsx
+++ b/src/route-widgets/GlobalSettingsRoute/SettingsForm.tsx
@@ -44,7 +44,7 @@ const DEFAULT_POOLS = createPool({
})
export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
- const {t} = useTranslation()
+ const {t} = useTranslation(["admin-global-settings", "common"])
const {showSuccess, showError} = useErrorSuccessSnacks()
const validationSchema = yup.object().shape({
@@ -52,50 +52,33 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
.number()
.min(1)
.max(1_023)
- .label(t("routes.AdminRoute.forms.settings.randomEmailIdMinLength.label")),
- randomEmailIdChars: yup
- .string()
- .label(t("routes.AdminRoute.forms.settings.randomEmailIdChars.label")),
+ .label(t("fields.randomEmailIdMinLength.label")),
+ randomEmailIdChars: yup.string().label(t("fields.randomEmailIdChars.label")),
randomEmailLengthIncreaseOnPercentage: yup
.number()
.min(0)
.max(1)
- .label(
- t("routes.AdminRoute.forms.settings.randomEmailLengthIncreaseOnPercentage.label"),
- ),
+ .label(t("fields.randomEmailLengthIncreaseOnPercentage.label")),
imageProxyStorageLifeTimeInHours: yup
.number()
- .label(t("routes.AdminRoute.forms.settings.imageProxyStorageLifeTimeInHours.label")),
+ .label(t("fields.imageProxyStorageLifeTimeInHours.label")),
customEmailSuffixLength: yup
.number()
.min(1)
.max(1_023)
- .label(t("routes.AdminRoute.forms.settings.customEmailSuffixLength-label")),
- customEmailSuffixChars: yup
- .string()
- .label(t("routes.AdminRoute.forms.settings.customEmailSuffixChars.label")),
+ .label(t("fields.customEmailSuffixLength.label")),
+ customEmailSuffixChars: yup.string().label(t("fields.customEmailSuffixChars.label")),
userEmailEnableDisposableEmails: yup
.boolean()
- .label(t("routes.AdminRoute.forms.settings.userEmailEnableDisposableEmails.label")),
+ .label(t("fields.userEmailEnableDisposableEmails.label")),
userEmailEnableOtherRelays: yup
.boolean()
- .label(t("routes.AdminRoute.forms.settings.userEmailEnableOtherRelays.label")),
- enableImageProxy: yup
- .boolean()
- .label(t("routes.AdminRoute.forms.settings.enableImageProxy.label")),
- enableImageProxyStorage: yup
- .boolean()
- .label(t("routes.AdminRoute.forms.settings.enableImageProxyStorage.label")),
- allowStatistics: yup
- .boolean()
- .label(t("routes.AdminRoute.forms.settings.allowStatistics.label")),
- allowAliasDeletion: yup
- .boolean()
- .label(t("routes.AdminRoute.forms.settings.allowAliasDeletion.label")),
- maxAliasesPerUser: yup
- .number()
- .label(t("routes.AdminRoute.forms.settings.maxAliasesPerUser.label"))
- .min(0),
+ .label(t("fields.userEmailEnableOtherRelays.label")),
+ enableImageProxy: yup.boolean().label(t("fields.enableImageProxy.label")),
+ enableImageProxyStorage: yup.boolean().label(t("fields.enableImageProxyStorage.label")),
+ allowStatistics: yup.boolean().label(t("fields.allowStatistics.label")),
+ allowAliasDeletion: yup.boolean().label(t("fields.allowAliasDeletion.label")),
+ maxAliasesPerUser: yup.number().label(t("fields.maxAliasesPerUser.label")).min(0),
} as Record)
const {mutateAsync} = useMutation<
@@ -109,7 +92,7 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
return
}
- showSuccess(t("routes.AdminRoute.settings.successMessage"))
+ showSuccess(t("updatedSuccessfullyMessage"))
queryClient.setQueryData>(queryKey, newSettings)
},
@@ -144,12 +127,12 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
- {t("routes.AdminRoute.settings.title")}
+ {t("title")}
- {t("routes.AdminRoute.settings.description")}
+ {t("description")}
@@ -160,9 +143,7 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
- {t(
- "routes.AdminRoute.forms.settings.imageProxyStorageLifeTimeInHours.unit",
- {
- count:
- formik.values
- .imageProxyStorageLifeTimeInHours || 0,
- },
- )}
+ {t("fields.imageProxyStorageLifeTimeInHours.unit", {
+ count:
+ formik.values
+ .imageProxyStorageLifeTimeInHours || 0,
+ })}
),
}}
@@ -421,9 +373,7 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
/>
}
disabled={formik.isSubmitting}
- label={t(
- "routes.AdminRoute.forms.settings.userEmailEnableDisposableEmails.label",
- )}
+ label={t("fields.userEmailEnableDisposableEmails.label")}
/>
{(formik.touched.userEmailEnableDisposableEmails &&
formik.errors.userEmailEnableDisposableEmails) ||
- t(
- "routes.AdminRoute.forms.settings.userEmailEnableDisposableEmails.description",
- )}
+ t("fields.userEmailEnableDisposableEmails.description")}
@@ -450,9 +398,7 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
/>
}
disabled={formik.isSubmitting}
- label={t(
- "routes.AdminRoute.forms.settings.userEmailEnableOtherRelays.label",
- )}
+ label={t("fields.userEmailEnableOtherRelays.label")}
/>
{(formik.touched.userEmailEnableOtherRelays &&
formik.errors.userEmailEnableOtherRelays) ||
- t(
- "routes.AdminRoute.forms.settings.userEmailEnableOtherRelays.description",
- )}
+ t("fields.userEmailEnableOtherRelays.description")}
@@ -481,9 +425,7 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
/>
}
disabled={formik.isSubmitting}
- label={t(
- "routes.AdminRoute.forms.settings.enableImageProxy.label",
- )}
+ label={t("fields.enableImageProxy.label")}
/>
{(formik.touched.enableImageProxy &&
formik.errors.enableImageProxy) ||
- t(
- "routes.AdminRoute.forms.settings.enableImageProxy.description",
- )}
+ t("fields.enableImageProxy.description")}
@@ -513,9 +453,7 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
/>
}
disabled={formik.isSubmitting}
- label={t(
- "routes.AdminRoute.forms.settings.enableImageProxyStorage.label",
- )}
+ label={t("fields.enableImageProxyStorage.label")}
/>
{(formik.touched.enableImageProxyStorage &&
formik.errors.enableImageProxyStorage) ||
- t(
- "routes.AdminRoute.forms.settings.enableImageProxyStorage.description",
- )}
+ t("fields.enableImageProxyStorage.description")}
@@ -545,9 +481,7 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
/>
}
disabled={formik.isSubmitting}
- label={t(
- "routes.AdminRoute.forms.settings.allowStatistics.label",
- )}
+ label={t("fields.allowStatistics.label")}
/>
{(formik.touched.allowStatistics &&
formik.errors.allowStatistics) ||
- t(
- "routes.AdminRoute.forms.settings.allowStatistics.description",
- )}
+ t("fields.allowStatistics.description")}
@@ -574,9 +506,7 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
/>
}
disabled={formik.isSubmitting}
- label={t(
- "routes.AdminRoute.forms.settings.allowAliasDeletion.label",
- )}
+ label={t("fields.allowAliasDeletion.label")}
/>
{(formik.touched.allowAliasDeletion &&
formik.errors.allowAliasDeletion) ||
- t(
- "routes.AdminRoute.forms.settings.allowAliasDeletion.description",
- )}
+ t("fields.allowAliasDeletion.description")}
@@ -608,7 +536,7 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
formik.submitForm()
}}
>
- {t("routes.AdminRoute.settings.resetLabel")}
+ {t("general.resetLabel", {ns: "common"})}
@@ -618,7 +546,7 @@ export default function SettingsForm({settings, queryKey}: SettingsFormProps) {
type="submit"
startIcon={}
>
- {t("general.saveLabel")}
+ {t("general.saveLabel", {ns: "common"})}
diff --git a/src/routes/AdminRoute.tsx b/src/routes/AdminRoute.tsx
index 994dc15..e1eab67 100644
--- a/src/routes/AdminRoute.tsx
+++ b/src/routes/AdminRoute.tsx
@@ -11,7 +11,7 @@ import {useNavigateToNext, useUser} from "~/hooks"
import ServerStatus from "~/route-widgets/AdminRoute/ServerStatus"
export default function AdminRoute(): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("title")
const navigateToNext = useNavigateToNext()
const user = useUser()
@@ -22,20 +22,20 @@ export default function AdminRoute(): ReactElement {
}, [user.isAdmin, navigateToNext])
return (
-
+
-
+
-
+
From b600d56e9591d5ee7af2381e3d990ae5ba8a0df9 Mon Sep 17 00:00:00 2001
From: Myzel394 <50424412+Myzel394@users.noreply.github.com>
Date: Sun, 5 Mar 2023 10:33:44 +0100
Subject: [PATCH 14/22] refactor: Improve i18n for admin create reserved
aliases
---
.../locales/en-US/admin-reserved-aliases.json | 38 ++++++++
public/locales/en-US/common.json | 3 +
public/locales/en-US/translation.json | 92 +++++++++++++++++++
.../AliasExplanation.tsx | 8 +-
.../UsersSelectField.tsx | 15 ++-
.../ReservedAliasesRoute/EmptyStateScreen.tsx | 12 +--
src/routes/AdminRoute.tsx | 2 +-
src/routes/CreateReservedAliasRoute.tsx | 24 ++---
src/routes/ReservedAliasesRoute.tsx | 14 ++-
9 files changed, 164 insertions(+), 44 deletions(-)
create mode 100644 public/locales/en-US/admin-reserved-aliases.json
diff --git a/public/locales/en-US/admin-reserved-aliases.json b/public/locales/en-US/admin-reserved-aliases.json
new file mode 100644
index 0000000..f8cf123
--- /dev/null
+++ b/public/locales/en-US/admin-reserved-aliases.json
@@ -0,0 +1,38 @@
+{
+ "title": "Reserved Aliases",
+ "pageActions": {
+ "search": {
+ "placeholder": "Search for aliases"
+ }
+ },
+ "actions": {
+ "create": {
+ "label": "Create new Reserved Alias"
+ }
+ },
+ "userAmount_one": "Forwards to one user",
+ "userAmount_other": "Forwards to {{count}} users",
+ "emptyState": {
+ "title": "Create your first reserved alias",
+ "description": "Reserved aliases are aliases that will be forwarded to selected admin users. This is useful if you want to create aliases that are meant to be public, like contact@example.com or hello@example.com."
+ },
+ "createNew": {
+ "title": "Reserved Aliases",
+ "description": "Define what alias should forward to whom.",
+ "continueActionLabel": "Create Reserved Alias",
+ "fields": {
+ "active": {
+ "label": "Active"
+ },
+ "users": {
+ "label": "Users",
+ "me": "{{email}} (Me)"
+ }
+ },
+ "explanation": {
+ "step1": "User from outside",
+ "step2": "Sends mail to",
+ "step4": "KleckRelay forwards to"
+ }
+ }
+}
diff --git a/public/locales/en-US/common.json b/public/locales/en-US/common.json
index ebc82d5..d93c5be 100644
--- a/public/locales/en-US/common.json
+++ b/public/locales/en-US/common.json
@@ -32,6 +32,9 @@
"label": "Address",
"placeholder": "awesome-fish"
},
+ "local": {
+ "label": "Address"
+ },
"search": {
"label": "Search"
}
diff --git a/public/locales/en-US/translation.json b/public/locales/en-US/translation.json
index bcfb7d6..5610130 100644
--- a/public/locales/en-US/translation.json
+++ b/public/locales/en-US/translation.json
@@ -129,6 +129,98 @@
"reservedAliases": "Reserved Aliases",
"settings": "Global Settings"
},
+ "forms": {
+ "reservedAliases": {
+ "title": "Reserved Aliases",
+ "description": "Define what alias should forward to whom.",
+ "saveAction": "Create Alias",
+ "fields": {
+ "local": {
+ "label": "Local"
+ },
+ "users": {
+ "label": "Users",
+ "me": "{{email}} (Me)"
+ }
+ },
+ "explanation": {
+ "step1": "User from outside",
+ "step2": "Sends mail to",
+ "step4": "KleckRelay forwards to"
+ }
+ },
+ "settings": {
+ "randomEmailIdMinLength": {
+ "label": "Minimum random alias ID length",
+ "description": "The minimum length for randomly generated emails. The server will automatically increase the length if required so."
+ },
+ "randomEmailIdChars": {
+ "label": "Random alias character pool",
+ "description": "Characters that are used to generate random emails."
+ },
+ "randomEmailLengthIncreaseOnPercentage": {
+ "label": "Percentage of used aliases",
+ "description": "If the percentage of used random email IDs is higher than this value, the length of the random email ID will be increased. This is used to prevent spammers from guessing the email ID."
+ },
+ "customEmailSuffixLength": {
+ "label": "Custom email suffix length",
+ "description": "The length of the custom email suffix."
+ },
+ "customEmailSuffixChars": {
+ "label": "Custom email suffix character pool",
+ "description": "Characters that are used to generate custom email suffixes."
+ },
+ "imageProxyStorageLifeTimeInHours": {
+ "label": "Image proxy storage lifetime",
+ "description": "The lifetime of images that are stored on the server in hours. After this time, the image will be deleted.",
+ "unit_one": "hour",
+ "unit_other": "hours"
+ },
+ "enableImageProxy": {
+ "label": "Enable image proxy",
+ "description": "If enabled, images will be proxied through the server. This enhances your user's privacy as their ip address will not be leaked."
+ },
+ "enableImageProxyStorage": {
+ "label": "Enable image proxy storage",
+ "description": "If enabled, images will be stored on the server and forwarded to the user. This makes email tracking nearly impossible as every message will be marked as read instantly, which is obviously not true as a user is typically not able to view an email in just a few seconds after it has been sent. This will only affect new images."
+ },
+ "userEmailEnableDisposableEmails": {
+ "label": "Enable disposable emails for new accounts",
+ "description": "If enabled, users will be able to use disposable emails when creating a new account. This will only affect new accounts."
+ },
+ "userEmailEnableOtherRelays": {
+ "label": "Enable other relays for new accounts",
+ "description": "If enabled, users will be able to use other relays (such as SimpleLogin or DuckDuckGo's Email Tracking Protection) when creating a new account. This will only affect new accounts."
+ },
+ "allowStatistics": {
+ "label": "Allow statistics",
+ "description": "If enabled, your instance will collect anonymous statistics and share them. They will only be stored locally on this instance but made public."
+ },
+ "allowAliasDeletion": {
+ "label": "Allow alias deletion",
+ "description": "If enabled, users will be able to delete their aliases."
+ },
+ "maxAliasesPerUser": {
+ "label": "Maximum aliases per user",
+ "description": "The maximum number of aliases a user can create. 0 means unlimited. Existing aliases will not be affected."
+ }
+ }
+ },
+ "settings": {
+ "title": "Global Settings",
+ "description": "Configure global settings for your instance.",
+ "successMessage": "Settings have been saved successfully!",
+ "randomAliasesPreview": {
+ "title": "Random aliases will look like this",
+ "helperText": "This is just a preview. Those are not real aliases."
+ },
+ "randomAliasesIncreaseExplanation": "Random aliases' length will be increased from {{originalLength}} to {{increasedLength}} characters after {{amount}} aliases have been created.",
+ "resetLabel": "Reset to defaults",
+ "disabled": {
+ "title": "Global settings are disabled",
+ "description": "Global settings have been disabled. You can enable them in the configuration file."
+ }
+ },
"reservedAlias": {
"actions": {
"delete": {
diff --git a/src/route-widgets/CreateReservedAliasRoute/AliasExplanation.tsx b/src/route-widgets/CreateReservedAliasRoute/AliasExplanation.tsx
index 6e538ab..1d5f199 100644
--- a/src/route-widgets/CreateReservedAliasRoute/AliasExplanation.tsx
+++ b/src/route-widgets/CreateReservedAliasRoute/AliasExplanation.tsx
@@ -14,7 +14,7 @@ export interface AliasExplanationProps {
}
export default function AliasExplanation({local, emails}: AliasExplanationProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("admin-reserved-aliases")
const theme = useTheme()
const serverSettings = useLoaderData() as ServerSettings
@@ -37,7 +37,7 @@ export default function AliasExplanation({local, emails}: AliasExplanationProps)
- {t("routes.AdminRoute.forms.reservedAliases.explanation.step1")}
+ {t("createNew.explanation.step1")}
@@ -49,7 +49,7 @@ export default function AliasExplanation({local, emails}: AliasExplanationProps)
- {t("routes.AdminRoute.forms.reservedAliases.explanation.step2")}
+ {t("createNew.explanation.step2")}
@@ -76,7 +76,7 @@ export default function AliasExplanation({local, emails}: AliasExplanationProps)
- {t("routes.AdminRoute.forms.reservedAliases.explanation.step4")}
+ {t("createNew.explanation.step4")}
diff --git a/src/route-widgets/CreateReservedAliasRoute/UsersSelectField.tsx b/src/route-widgets/CreateReservedAliasRoute/UsersSelectField.tsx
index 9fb60f9..e7657b7 100644
--- a/src/route-widgets/CreateReservedAliasRoute/UsersSelectField.tsx
+++ b/src/route-widgets/CreateReservedAliasRoute/UsersSelectField.tsx
@@ -37,7 +37,7 @@ export default function UsersSelectField({
error,
...props
}: UsersSelectFieldProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("admin-reserved-aliases")
const meUser = useUser()
const {data: {users} = {}} = useQuery(
["getAdminUsers"],
@@ -49,7 +49,7 @@ export default function UsersSelectField({
return (
- {t("routes.AdminRoute.forms.reservedAliases.fields.users.label")}
+ {t("createNew.fields.users.label")}
diff --git a/src/components/widgets/TimedButton.tsx b/src/components/widgets/TimedButton.tsx
index bdcd711..0579de8 100644
--- a/src/components/widgets/TimedButton.tsx
+++ b/src/components/widgets/TimedButton.tsx
@@ -18,7 +18,7 @@ export default function TimedButton({
disabled: parentDisabled = false,
...props
}: TimedButtonProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("components")
const [startDate, resetInterval] = useIntervalUpdate(1000)
@@ -35,9 +35,7 @@ export default function TimedButton({
}}
>
{children}
- {secondsLeft > 0 && (
- {t("components.TimedButton.remainingTime", {count: secondsLeft})}
- )}
+ {secondsLeft > 0 && {t("TimedButton.remainingTime", {count: secondsLeft})}}
)
}
diff --git a/src/route-widgets/LoginRoute/ConfirmCodeForm/ResendMailButton.tsx b/src/route-widgets/LoginRoute/ConfirmCodeForm/ResendMailButton.tsx
index 3d52a46..152a1ae 100644
--- a/src/route-widgets/LoginRoute/ConfirmCodeForm/ResendMailButton.tsx
+++ b/src/route-widgets/LoginRoute/ConfirmCodeForm/ResendMailButton.tsx
@@ -19,8 +19,8 @@ export default function ResendMailButton({
email,
sameRequestToken,
}: ResendMailButtonProps): ReactElement {
+ const {t} = useTranslation("components")
const settings = useLoaderData() as ServerSettings
- const {t} = useTranslation()
const mutation = useMutation(() =>
resendEmailLoginCode({
@@ -37,7 +37,7 @@ export default function ResendMailButton({
startIcon={}
onClick={() => mutate()}
>
- {t("components.ResendMailButton.label")}
+ {t("ResendMailButton.label")}
>
diff --git a/src/route-widgets/SignupRoute/YouGotMail/ResendMailButton.tsx b/src/route-widgets/SignupRoute/YouGotMail/ResendMailButton.tsx
index a6426dc..81f1451 100644
--- a/src/route-widgets/SignupRoute/YouGotMail/ResendMailButton.tsx
+++ b/src/route-widgets/SignupRoute/YouGotMail/ResendMailButton.tsx
@@ -19,7 +19,7 @@ export default function ResendMailButton({
email,
onEmailAlreadyVerified,
}: ResendMailButtonProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("components")
const settings = useLoaderData() as ServerSettings
const mutation = useMutation(
@@ -41,7 +41,7 @@ export default function ResendMailButton({
startIcon={}
onClick={() => mutate()}
>
- {t("components.ResendMailButton.label")}
+ {t("ResendMailButton.label")}
>
From 126eb58c9683727d96e476b3dabbd2e6a88fef4b Mon Sep 17 00:00:00 2001
From: Myzel394 <50424412+Myzel394@users.noreply.github.com>
Date: Sun, 5 Mar 2023 11:33:09 +0100
Subject: [PATCH 20/22] refactor: Improve i18n for extension
---
public/locales/en-US/extension.json | 12 ++++++++++++
.../PasswordShareConfirmationDialog.tsx | 18 +++++++-----------
2 files changed, 19 insertions(+), 11 deletions(-)
create mode 100644 public/locales/en-US/extension.json
diff --git a/public/locales/en-US/extension.json b/public/locales/en-US/extension.json
new file mode 100644
index 0000000..c8f1efe
--- /dev/null
+++ b/public/locales/en-US/extension.json
@@ -0,0 +1,12 @@
+{
+ "sharePassword": {
+ "title": "Share Password?",
+ "description": "An extension is asking for your password. Do you want to share it? Only continue if you initiated this action.",
+ "warning": "THIS WILL SHARE YOUR PASSWORD WITH THE EXTENSION. ALL YOUR DATA CAN BE DECRYPTED USING IT. ONLY CONTINUE IF YOU TRUST THE EXTENSION AND IF YOU INITIATED THIS REQUEST.",
+
+ "sharePassword": "Share Password",
+ "doNotShare": "Do not share",
+ "decideLater": "Decide later",
+ "doNotAskAgain": "Do not ask again"
+ }
+}
diff --git a/src/components/AuthContext/PasswordShareConfirmationDialog.tsx b/src/components/AuthContext/PasswordShareConfirmationDialog.tsx
index b1a92f2..bd43330 100644
--- a/src/components/AuthContext/PasswordShareConfirmationDialog.tsx
+++ b/src/components/AuthContext/PasswordShareConfirmationDialog.tsx
@@ -25,32 +25,28 @@ export default function PasswordShareConfirmationDialog({
onShare,
onClose,
}: PasswordShareConfirmationDialogProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("extension")
return (
From f289a2340dcffad8c019854600f08d9496c7164f Mon Sep 17 00:00:00 2001
From: Myzel394 <50424412+Myzel394@users.noreply.github.com>
Date: Sun, 5 Mar 2023 11:38:04 +0100
Subject: [PATCH 21/22] refactor: Fix i18n
---
public/locales/en-US/alias-notes.json | 5 ++++-
.../AliasDetailRoute/AddWebsiteField.tsx | 20 +++++++++----------
.../AliasPercentageAmount.tsx | 4 ++--
.../RandomAliasGenerator.tsx | 8 +++-----
.../AdminUserPicker.tsx | 4 ++--
.../Settings2FARoute/Delete2FA.tsx | 2 +-
6 files changed, 21 insertions(+), 22 deletions(-)
diff --git a/public/locales/en-US/alias-notes.json b/public/locales/en-US/alias-notes.json
index 70a2bd5..8dca49e 100644
--- a/public/locales/en-US/alias-notes.json
+++ b/public/locales/en-US/alias-notes.json
@@ -24,7 +24,10 @@
"label": "Websites",
"emptyText": "You haven't used this alias on any site yet.",
"placeholder": "https://example.com",
- "helperText": "Add a website to this alias. Used to autofill."
+ "helperText": "Add a website to this alias. Used to autofill.",
+ "errors": {
+ "invalid": "This URL is invalid."
+ }
}
}
}
diff --git a/src/route-widgets/AliasDetailRoute/AddWebsiteField.tsx b/src/route-widgets/AliasDetailRoute/AddWebsiteField.tsx
index 52d08e4..42d2fc4 100644
--- a/src/route-widgets/AliasDetailRoute/AddWebsiteField.tsx
+++ b/src/route-widgets/AliasDetailRoute/AddWebsiteField.tsx
@@ -18,14 +18,14 @@ interface WebsiteForm {
url: string
}
-const WEBSITE_SCHEMA = yup.object().shape({
- url: yup.string().matches(URL_REGEX, "This URL is invalid."),
-})
-
export default function AddWebsiteField({onAdd, isLoading}: AddWebsiteFieldProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("alias-notes")
+
+ const schema = yup.object().shape({
+ url: yup.string().matches(URL_REGEX, t("form.websites.error.invalid") as string),
+ })
const websiteFormik = useFormik({
- validationSchema: WEBSITE_SCHEMA,
+ validationSchema: schema,
initialValues: {
url: "",
},
@@ -58,10 +58,8 @@ export default function AddWebsiteField({onAdd, isLoading}: AddWebsiteFieldProps
{(websiteFormik.touched.url && websiteFormik.errors.url) ||
- t("routes.AliasDetailRoute.sections.notes.form.websites.helperText")}
+ t("form.websites.helperText")}
diff --git a/src/route-widgets/GlobalSettingsRoute/AliasPercentageAmount.tsx b/src/route-widgets/GlobalSettingsRoute/AliasPercentageAmount.tsx
index 117a1da..6780bc1 100644
--- a/src/route-widgets/GlobalSettingsRoute/AliasPercentageAmount.tsx
+++ b/src/route-widgets/GlobalSettingsRoute/AliasPercentageAmount.tsx
@@ -14,14 +14,14 @@ export default function AliasesPercentageAmount({
length,
percentage,
}: AliasPercentageAmountProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("admin-global-settings")
const amount = Math.floor(Math.pow(characters.length, length) * percentage)
return (
- {t("routes.AdminRoute.settings.randomAliasesIncreaseExplanation", {
+ {t("randomAliasesIncreaseExplanation", {
originalLength: length,
increasedLength: length + 1,
amount,
diff --git a/src/route-widgets/GlobalSettingsRoute/RandomAliasGenerator.tsx b/src/route-widgets/GlobalSettingsRoute/RandomAliasGenerator.tsx
index 37cb4b6..d2be605 100644
--- a/src/route-widgets/GlobalSettingsRoute/RandomAliasGenerator.tsx
+++ b/src/route-widgets/GlobalSettingsRoute/RandomAliasGenerator.tsx
@@ -18,7 +18,7 @@ export default function RandomAliasGenerator({
length,
}: RandomAliasGeneratorProps): ReactElement {
const serverSettings = useLoaderData() as ServerSettings
- const {t} = useTranslation()
+ const {t} = useTranslation("admin-global-settings")
const theme = useTheme()
const generateLocal = useCallback(
@@ -39,7 +39,7 @@ export default function RandomAliasGenerator({
return (
- {t("routes.AdminRoute.settings.randomAliasesPreview.title")}
+ {t("randomAliasesPreview.title")}
@@ -51,9 +51,7 @@ export default function RandomAliasGenerator({
-
- {t("routes.AdminRoute.settings.randomAliasesPreview.helperText")}
-
+ {t("randomAliasesPreview.helperText")}
)
}
diff --git a/src/route-widgets/ReservedAliasDetailRoute/AdminUserPicker.tsx b/src/route-widgets/ReservedAliasDetailRoute/AdminUserPicker.tsx
index a33e68f..b857356 100644
--- a/src/route-widgets/ReservedAliasDetailRoute/AdminUserPicker.tsx
+++ b/src/route-widgets/ReservedAliasDetailRoute/AdminUserPicker.tsx
@@ -17,7 +17,7 @@ export default function AdminUserPicker({
onPick,
alreadyPicked,
}: AdminUserPickerProps): ReactElement {
- const {t} = useTranslation()
+ const {t} = useTranslation("admin-reserved-aliases")
const meUser = useUser()
const {data: {users: availableUsers} = {}} = useQuery(
["getAdminUsers"],
@@ -54,7 +54,7 @@ export default function AdminUserPicker({
{users.map(user => (