- Please enter the verification code that was sent to{' '}
+ Please enter the confirmation code that was sent to{' '}
{primaryEmail.email} within 5
minutes.
@@ -118,9 +118,9 @@ export const ModalVerifySession = ({
{
if (errorText) {
@@ -147,14 +147,14 @@ export const ModalVerifySession = ({
Cancel
-
+
diff --git a/packages/fxa-settings/src/components/PageChangePassword/index.tsx b/packages/fxa-settings/src/components/PageChangePassword/index.tsx
index f659bdfd833..e82987b37f9 100644
--- a/packages/fxa-settings/src/components/PageChangePassword/index.tsx
+++ b/packages/fxa-settings/src/components/PageChangePassword/index.tsx
@@ -13,7 +13,7 @@ import {
} from '../../lib/metrics';
import { useAccount, useAlertBar } from '../../models';
import FlowContainer from '../FlowContainer';
-import { AuthUiErrors } from '../../lib/auth-errors/auth-errors';
+import { AuthUiErrors, composeAuthUiErrorTranslationID } from '../../lib/auth-errors/auth-errors';
import { useLocalization, Localized } from '@fluent/react';
import FormPassword from '../FormPassword';
@@ -62,7 +62,7 @@ export const PageChangePassword = ({}: RouteComponentProps) => {
async ({ oldPassword, newPassword }: FormData) => {
if (oldPassword === newPassword) {
const localizedError = l10n.getString(
- `auth-error-${AuthUiErrors.PASSWORDS_MUST_BE_DIFFERENT.errno}`,
+ composeAuthUiErrorTranslationID(AuthUiErrors.PASSWORDS_MUST_BE_DIFFERENT),
null,
AuthUiErrors.PASSWORDS_MUST_BE_DIFFERENT.message
);
@@ -75,7 +75,7 @@ export const PageChangePassword = ({}: RouteComponentProps) => {
alertSuccessAndGoHome();
} catch (e) {
const localizedError = l10n.getString(
- `auth-error-${AuthUiErrors.INCORRECT_PASSWORD.errno}`,
+ composeAuthUiErrorTranslationID(AuthUiErrors.INCORRECT_PASSWORD),
null,
AuthUiErrors.INCORRECT_PASSWORD.message
);
diff --git a/packages/fxa-settings/src/components/PageDeleteAccount/index.tsx b/packages/fxa-settings/src/components/PageDeleteAccount/index.tsx
index eb355e7361c..d5205a009e1 100644
--- a/packages/fxa-settings/src/components/PageDeleteAccount/index.tsx
+++ b/packages/fxa-settings/src/components/PageDeleteAccount/index.tsx
@@ -14,7 +14,7 @@ import { logViewEvent, usePageViewEvent } from '../../lib/metrics';
import { Checkbox } from '../Checkbox';
import { useLocalization } from '@fluent/react';
import { Localized } from '@fluent/react';
-import { AuthUiErrors } from '../../lib/auth-errors/auth-errors';
+import { AuthUiErrors, composeAuthUiErrorTranslationID } from '../../lib/auth-errors/auth-errors';
type FormData = {
password: string;
@@ -76,7 +76,7 @@ export const PageDeleteAccount = (_: RouteComponentProps) => {
window.location.href = `${ROOTPATH}?delete_account_success=true`;
} catch (e) {
const localizedError = l10n.getString(
- `auth-error-${AuthUiErrors.INCORRECT_PASSWORD.errno}`,
+ composeAuthUiErrorTranslationID(AuthUiErrors.INCORRECT_PASSWORD),
null,
AuthUiErrors.INCORRECT_PASSWORD.message
);
diff --git a/packages/fxa-settings/src/components/PageRecoveryKeyAdd/index.test.tsx b/packages/fxa-settings/src/components/PageRecoveryKeyAdd/index.test.tsx
index fc763695223..20dac9a3e88 100644
--- a/packages/fxa-settings/src/components/PageRecoveryKeyAdd/index.test.tsx
+++ b/packages/fxa-settings/src/components/PageRecoveryKeyAdd/index.test.tsx
@@ -131,6 +131,13 @@ describe('PageRecoveryKeyAdd', () => {
account.createRecoveryKey = jest
.fn()
.mockResolvedValue(new Uint8Array(20));
+ } else {
+ account.createRecoveryKey = jest
+ .fn()
+ .mockImplementation(() => {
+ // this is just a random key that does match a real error to keep tests passing.
+ throw { message: 'Example error', errno: 106 }
+ })
}
renderWithRouter(
diff --git a/packages/fxa-settings/src/components/PageRecoveryKeyAdd/index.tsx b/packages/fxa-settings/src/components/PageRecoveryKeyAdd/index.tsx
index 4e3f099550d..00a82fb40f8 100644
--- a/packages/fxa-settings/src/components/PageRecoveryKeyAdd/index.tsx
+++ b/packages/fxa-settings/src/components/PageRecoveryKeyAdd/index.tsx
@@ -13,6 +13,7 @@ import { logViewEvent, usePageViewEvent } from '../../lib/metrics';
import {
AuthUiErrors,
AuthUiErrorNos,
+ composeAuthUiErrorTranslationID,
} from '../../lib/auth-errors/auth-errors';
type FormData = {
@@ -73,13 +74,13 @@ export const PageRecoveryKeyAdd = (_: RouteComponentProps) => {
if (e.errno === AuthUiErrors.THROTTLED.errno) {
localizedError = l10n.getString(
- `auth-error-${e.errno}`,
+ composeAuthUiErrorTranslationID(e),
{ retryAfter: e.retryAfterLocalized },
AuthUiErrorNos[e.errno].message
);
} else {
localizedError = l10n.getString(
- `auth-error-${e.errno}`,
+ composeAuthUiErrorTranslationID(e),
null,
e.message
);
diff --git a/packages/fxa-settings/src/components/PageSecondaryEmailAdd/index.tsx b/packages/fxa-settings/src/components/PageSecondaryEmailAdd/index.tsx
index 5d36cd14af2..e056132dc49 100644
--- a/packages/fxa-settings/src/components/PageSecondaryEmailAdd/index.tsx
+++ b/packages/fxa-settings/src/components/PageSecondaryEmailAdd/index.tsx
@@ -8,7 +8,7 @@ import FlowContainer from '../FlowContainer';
import VerifiedSessionGuard from '../VerifiedSessionGuard';
import { isEmailValid } from 'fxa-shared/email/helpers';
import { useAccount, useAlertBar } from 'fxa-settings/src/models';
-import { AuthUiErrorNos } from 'fxa-settings/src/lib/auth-errors/auth-errors';
+import { AuthUiErrorNos, composeAuthUiErrorTranslationID } from 'fxa-settings/src/lib/auth-errors/auth-errors';
export const PageSecondaryEmailAdd = (_: RouteComponentProps) => {
usePageViewEvent('settings.emails');
@@ -37,7 +37,7 @@ export const PageSecondaryEmailAdd = (_: RouteComponentProps) => {
} catch (e) {
if (e.errno) {
const errorText = l10n.getString(
- `auth-error-${e.errno}`,
+ composeAuthUiErrorTranslationID(e),
{ retryAfter: e.retryAfterLocalized },
AuthUiErrorNos[e.errno].message
);
diff --git a/packages/fxa-settings/src/components/PageSecondaryEmailVerify/en-US.ftl b/packages/fxa-settings/src/components/PageSecondaryEmailVerify/en-US.ftl
index e28485f5c13..ce0e677746b 100644
--- a/packages/fxa-settings/src/components/PageSecondaryEmailVerify/en-US.ftl
+++ b/packages/fxa-settings/src/components/PageSecondaryEmailVerify/en-US.ftl
@@ -1,17 +1,17 @@
## Verify secondary email page
add-secondary-email-step-2 = Step 2 of 2
-verify-secondary-email-error-2 = There was a problem sending the verification code
+verify-secondary-email-error-3 = There was a problem sending the confirmation code
verify-secondary-email-page-title =
.title = Secondary email
-verify-secondary-email-verification-code =
- .label = Enter your verification code
+verify-secondary-email-verification-code-2 =
+ .label = Enter your confirmation code
verify-secondary-email-cancel-button = Cancel
-verify-secondary-email-verify-button = Verify
+verify-secondary-email-verify-button-2 = Confirm
# This string is an instruction in a form.
# Variables:
# $email (String) - the user's email address, which does not need translation.
-verify-secondary-email-please-enter-code = Please enter the verification code that was sent to { $email } within 5 minutes.
+verify-secondary-email-please-enter-code-2 = Please enter the confirmation code that was sent to { $email } within 5 minutes.
# This string is a confirmation message shown after verifying an email.
# Variables:
# $email (String) - the user's email address, which does not need translation.
diff --git a/packages/fxa-settings/src/components/PageSecondaryEmailVerify/index.tsx b/packages/fxa-settings/src/components/PageSecondaryEmailVerify/index.tsx
index 4e36638e1ac..bba049de646 100644
--- a/packages/fxa-settings/src/components/PageSecondaryEmailVerify/index.tsx
+++ b/packages/fxa-settings/src/components/PageSecondaryEmailVerify/index.tsx
@@ -8,7 +8,7 @@ import InputText from '../InputText';
import FlowContainer from '../FlowContainer';
import VerifiedSessionGuard from '../VerifiedSessionGuard';
import { useForm } from 'react-hook-form';
-import { AuthUiErrors } from 'fxa-settings/src/lib/auth-errors/auth-errors';
+import { AuthUiErrors, composeAuthUiErrorTranslationID } from 'fxa-settings/src/lib/auth-errors/auth-errors';
type FormData = {
verificationCode: string;
@@ -60,7 +60,7 @@ export const PageSecondaryEmailVerify = ({ location }: RouteComponentProps) => {
} catch (e) {
if (e.errno) {
const errorText = l10n.getString(
- `auth-error-${e.errno}`,
+ composeAuthUiErrorTranslationID(e),
null,
AuthUiErrors.INVALID_VERIFICATION_CODE.message
);
@@ -68,9 +68,9 @@ export const PageSecondaryEmailVerify = ({ location }: RouteComponentProps) => {
} else {
alertBar.error(
l10n.getString(
- 'verify-secondary-email-error-2',
+ 'verify-secondary-email-error-3',
null,
- 'There was a problem sending the verification code'
+ 'There was a problem sending the confirmation code'
)
);
}
@@ -100,24 +100,24 @@ export const PageSecondaryEmailVerify = ({ location }: RouteComponentProps) => {
})}
>
}}
>
- Please enter the verification code that was sent to{' '}
+ Please enter the confirmation code that was sent to{' '}
{email} within 5 minutes.
diff --git a/packages/fxa-settings/src/components/PageTwoStepAuthentication/en-US.ftl b/packages/fxa-settings/src/components/PageTwoStepAuthentication/en-US.ftl
index 0acb48b2024..2f6cb8ff993 100644
--- a/packages/fxa-settings/src/components/PageTwoStepAuthentication/en-US.ftl
+++ b/packages/fxa-settings/src/components/PageTwoStepAuthentication/en-US.ftl
@@ -12,7 +12,7 @@ tfa-button-finish = Finish
tfa-incorrect-totp = Incorrect two-step authentication code
tfa-cannot-retrieve-code = There was a problem retrieving your code.
-tfa-cannot-verify-code-2 = There was a problem verifying your recovery code
+tfa-cannot-verify-code-3 = There was a problem confirming your recovery code
tfa-incorrect-recovery-code = Incorrect recovery code
tfa-enabled = Two-step authentication enabled
diff --git a/packages/fxa-settings/src/components/PageTwoStepAuthentication/index.tsx b/packages/fxa-settings/src/components/PageTwoStepAuthentication/index.tsx
index e1ca0a6cc41..43181c10673 100644
--- a/packages/fxa-settings/src/components/PageTwoStepAuthentication/index.tsx
+++ b/packages/fxa-settings/src/components/PageTwoStepAuthentication/index.tsx
@@ -15,7 +15,7 @@ import { checkCode, copyRecoveryCodes, getCode } from '../../lib/totp';
import { HomePath } from '../../constants';
import { logViewEvent, useMetrics } from '../../lib/metrics';
import { Localized, useLocalization } from '@fluent/react';
-import { AuthUiErrors } from '../../lib/auth-errors/auth-errors';
+import { AuthUiErrors, composeAuthUiErrorTranslationID } from '../../lib/auth-errors/auth-errors';
import { useAsync } from 'react-async-hook';
export const metricsPreInPostFix = 'settings.two-step-authentication';
@@ -92,7 +92,7 @@ export const PageTwoStepAuthentication = (_: RouteComponentProps) => {
if (e.errno === AuthUiErrors.TOTP_TOKEN_NOT_FOUND.errno) {
setRecoveryCodeError(
l10n.getString(
- `auth-error-${AuthUiErrors.TOTP_TOKEN_NOT_FOUND.errno}`,
+ composeAuthUiErrorTranslationID(e),
null,
AuthUiErrors.TOTP_TOKEN_NOT_FOUND.message
)
@@ -100,9 +100,9 @@ export const PageTwoStepAuthentication = (_: RouteComponentProps) => {
} else {
alertBar.error(
l10n.getString(
- 'tfa-cannot-verify-code-2',
+ 'tfa-cannot-verify-code-3',
null,
- 'There was a problem verifying your recovery code'
+ 'There was a problem confirming your recovery code'
)
);
}
diff --git a/packages/fxa-settings/src/components/UnitRowRecoveryKey/en-US.ftl b/packages/fxa-settings/src/components/UnitRowRecoveryKey/en-US.ftl
index 1c61a051f21..9b933c0fc3f 100644
--- a/packages/fxa-settings/src/components/UnitRowRecoveryKey/en-US.ftl
+++ b/packages/fxa-settings/src/components/UnitRowRecoveryKey/en-US.ftl
@@ -11,7 +11,7 @@ rk-cannot-remove-key = Your account recovery key could not be removed.
rk-refresh-key = Refresh recovery key
rk-content-explain = Restore your information when you forget your password.
rk-content-reset-data = Why does resetting my password reset my data?
-rk-cannot-verify-session-3 = Sorry, there was a problem verifying your session
+rk-cannot-verify-session-4 = Sorry, there was a problem confirming your session
rk-remove-modal-heading = Remove recovery key?
rk-remove-modal-content = In the event you reset your password, you won’t be
able to use your recovery key to access your data. You can’t undo this action.
diff --git a/packages/fxa-settings/src/components/UnitRowRecoveryKey/index.tsx b/packages/fxa-settings/src/components/UnitRowRecoveryKey/index.tsx
index 342f97e35ad..5c54b23cc20 100644
--- a/packages/fxa-settings/src/components/UnitRowRecoveryKey/index.tsx
+++ b/packages/fxa-settings/src/components/UnitRowRecoveryKey/index.tsx
@@ -111,9 +111,9 @@ export const UnitRowRecoveryKey = () => {
hideModal();
alertBar.error(
l10n.getString(
- 'rk-cannot-verify-session-3',
+ 'rk-cannot-verify-session-4',
null,
- 'Sorry, there was a problem verifying your session'
+ 'Sorry, there was a problem confirming your session'
),
error
);
diff --git a/packages/fxa-settings/src/components/UnitRowSecondaryEmail/en-US.ftl b/packages/fxa-settings/src/components/UnitRowSecondaryEmail/en-US.ftl
index c3ef9dd8a61..108e8aa715e 100644
--- a/packages/fxa-settings/src/components/UnitRowSecondaryEmail/en-US.ftl
+++ b/packages/fxa-settings/src/components/UnitRowSecondaryEmail/en-US.ftl
@@ -3,7 +3,7 @@
se-heading = Secondary email
.header = Secondary email
se-cannot-refresh-email = Sorry, there was a problem refreshing that email.
-se-cannot-resend-code-2 = Sorry, there was a problem re-sending the verification code
+se-cannot-resend-code-3 = Sorry, there was a problem re-sending the confirmation code
# This string is used in a notification message near the top of the page.
# Variables:
# $email (String) - the user's email address, which does not need translation.
@@ -14,16 +14,16 @@ se-set-primary-error-2 = Sorry, there was a problem changing your primary email
# $email (String) - the user's email address, which does not need translation.
se-delete-email-successful-2 = { $email } successfully deleted
se-delete-email-error-2 = Sorry, there was a problem deleting this email
-se-verify-session-2 = You’ll need to verify your current session to perform this action
-se-verify-session-error-2 = Sorry, there was a problem verifying your session
+se-verify-session-3 = You’ll need to confirm your current session to perform this action
+se-verify-session-error-3 = Sorry, there was a problem confirming your session
# Button to remove the secondary email
se-remove-email =
.title = Remove email
# Button to refresh secondary email status
se-refresh-email =
.title = Refresh email
-se-unverified = unverified
-se-resend-code = Verification needed.
+se-unverified-2 = unconfirmed
+se-resend-code-2 = Confirmation needed.
if it’s not in your inbox or spam folder.
# Button to make secondary email the primary
se-make-primary = Make primary
diff --git a/packages/fxa-settings/src/components/UnitRowSecondaryEmail/index.tsx b/packages/fxa-settings/src/components/UnitRowSecondaryEmail/index.tsx
index b1a5dcb81d0..efed6f49644 100644
--- a/packages/fxa-settings/src/components/UnitRowSecondaryEmail/index.tsx
+++ b/packages/fxa-settings/src/components/UnitRowSecondaryEmail/index.tsx
@@ -37,9 +37,9 @@ export const UnitRowSecondaryEmail = () => {
} catch (e) {
alertBar.error(
l10n.getString(
- 'se-cannot-resend-code-2',
+ 'se-cannot-resend-code-3',
null,
- 'Sorry, there was a problem re-sending the verification code'
+ 'Sorry, there was a problem re-sending the confirmation code'
)
);
}
@@ -103,9 +103,9 @@ export const UnitRowSecondaryEmail = () => {
setQueuedAction(undefined);
alertBar.info(
l10n.getString(
- 'se-verify-session-2',
+ 'se-verify-session-3',
null,
- "You'll need to verify your current session to perform this action"
+ "You'll need to confirm your current session to perform this action"
)
);
}}
@@ -113,9 +113,9 @@ export const UnitRowSecondaryEmail = () => {
setQueuedAction(undefined);
alertBar.error(
l10n.getString(
- 'se-verify-session-error-2',
+ 'se-verify-session-error-3',
null,
- 'Sorry, there was a problem verifying your session'
+ 'Sorry, there was a problem confirming your session'
),
error
);
@@ -202,19 +202,19 @@ export const UnitRowSecondaryEmail = () => {
{!verified && (
-
+
- unverified
+ unconfirmed
)}
{!verified && (
{
}}
>
- Verification needed.{' '}
+ Confirmation needed.{' '}
{' '}
if it's not in your inbox or spam folder.
diff --git a/packages/fxa-settings/src/components/UnitRowTwoStepAuth/en-US.ftl b/packages/fxa-settings/src/components/UnitRowTwoStepAuth/en-US.ftl
index 28b32ad41b1..852bb64e356 100644
--- a/packages/fxa-settings/src/components/UnitRowTwoStepAuth/en-US.ftl
+++ b/packages/fxa-settings/src/components/UnitRowTwoStepAuth/en-US.ftl
@@ -13,7 +13,7 @@ tfa-row-cannot-refresh = Sorry, there was a problem refreshing two-step
authentication.
tfa-row-content-explain = Prevent someone else from logging in by requiring a
unique code only you have access to.
-tfa-row-cannot-verify-session-3 = Sorry, there was a problem verifying your session
+tfa-row-cannot-verify-session-4 = Sorry, there was a problem confirming your session
tfa-row-disable-modal-heading = Disable two-step authentication?
tfa-row-disable-modal-confirm = Disable
diff --git a/packages/fxa-settings/src/components/UnitRowTwoStepAuth/index.tsx b/packages/fxa-settings/src/components/UnitRowTwoStepAuth/index.tsx
index c6d842e437d..4001c7b2edf 100644
--- a/packages/fxa-settings/src/components/UnitRowTwoStepAuth/index.tsx
+++ b/packages/fxa-settings/src/components/UnitRowTwoStepAuth/index.tsx
@@ -182,9 +182,9 @@ export const UnitRowTwoStepAuth = () => {
hideModal();
alertBar.error(
l10n.getString(
- 'tfa-row-cannot-verify-session-3',
+ 'tfa-row-cannot-verify-session-4',
null,
- 'Sorry, there was a problem verifying your session'
+ 'Sorry, there was a problem confirming your session'
),
error
);
diff --git a/packages/fxa-settings/src/lib/auth-errors/auth-errors.test.ts b/packages/fxa-settings/src/lib/auth-errors/auth-errors.test.ts
new file mode 100644
index 00000000000..bc5b07a2595
--- /dev/null
+++ b/packages/fxa-settings/src/lib/auth-errors/auth-errors.test.ts
@@ -0,0 +1,84 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import {
+ composeAuthUiErrorTranslationID,
+ AuthUiErrorNos,
+ AuthUiError,
+} from './auth-errors';
+import * as Sentry from '@sentry/browser';
+
+const notAnExistingErrorNumber = 100000;
+const errorWithNoErrorNumber = {
+ message: "I'm an error with no error number!",
+} as AuthUiError;
+const errorWithAnInvalidErrorNumber = {
+ errno: notAnExistingErrorNumber,
+ message: 'This is an error with an invalid errno!',
+} as AuthUiError;
+
+jest.mock('@sentry/browser', () => ({
+ captureMessage: jest.fn(),
+}));
+
+describe('composeAuthUIErrorTranslationId', () => {
+ it('logs an informative error to sentry if passed an error with no errno', () => {
+ composeAuthUiErrorTranslationID(errorWithNoErrorNumber);
+ const errorMessage = `composeAuthUiErrorTranslationId: No error number given, unable to create a localization ID for AuthUiError string. error: ${JSON.stringify(
+ errorWithNoErrorNumber
+ )}`;
+ expect(Sentry.captureMessage).toHaveBeenCalledWith(errorMessage);
+ });
+
+ it('logs an informative error to sentry if passed an error which does not match an entry in the AuthUiErrors object', () => {
+ composeAuthUiErrorTranslationID(errorWithAnInvalidErrorNumber);
+ const errorMessage = `composeAuthUiErrorTranslationId: There is no matching error in AuthUiErrors. error: ${JSON.stringify(
+ errorWithAnInvalidErrorNumber
+ )}`;
+ expect(Sentry.captureMessage).toHaveBeenCalledWith(errorMessage);
+ });
+
+ it('returns an empty string if passed no error number', () => {
+ expect(composeAuthUiErrorTranslationID(errorWithNoErrorNumber)).toEqual('');
+ });
+
+ it('returns an empty string when given an error number with no corresponding error in the AuthUiError object', () => {
+ // First we just check that this has not become a valid AuthUiError number, for the sake of future clarity.
+ expect(AuthUiErrorNos[notAnExistingErrorNumber]).toBeUndefined();
+ // Then we actually test the behavior.
+ expect(
+ composeAuthUiErrorTranslationID(errorWithAnInvalidErrorNumber)
+ ).toEqual('');
+ });
+
+ it('correctly forms and returns a translation id for an auth ui error string which has never been updated (has no version number)', () => {
+ const validErrorNo = 106;
+ // First we just make sure that this is still a valid UI error.
+ expect(AuthUiErrorNos[validErrorNo]).toBeDefined();
+ // Then we make sure that it doesn't have a version number. This is a safeguard against the test unknowingly being outdated.
+ expect(AuthUiErrorNos[validErrorNo].version).toBeUndefined();
+ // The we actually test the functionality.
+ const expectedStringId = 'auth-error-106';
+ const stringId = composeAuthUiErrorTranslationID({
+ message: 'I am a valid error with a valid error number',
+ errno: validErrorNo,
+ });
+ expect(stringId).toEqual(expectedStringId);
+ });
+
+ it('correctly forms and returns a translation id for an auth ui error string which HAS been updated (has a version number', () => {
+ const errnoWithVersion = 105;
+ // First we just make sure that this is still a valid UI error.
+ expect(AuthUiErrorNos[errnoWithVersion]).toBeDefined();
+ // Then we make sure that it has a version number. This is a safeguard against the test unknowingly being outdated.
+ expect(AuthUiErrorNos[errnoWithVersion].version).toBeDefined();
+ // The we actually test the functionality.
+ const expectedStringId = `auth-error-105-${AuthUiErrorNos[errnoWithVersion].version}`;
+ const stringId = composeAuthUiErrorTranslationID({
+ message: 'This is a valid error, with a string that has a version number',
+ errno: errnoWithVersion,
+ });
+ expect(stringId).toEqual(expectedStringId);
+ });
+});
diff --git a/packages/fxa-settings/src/lib/auth-errors/auth-errors.ts b/packages/fxa-settings/src/lib/auth-errors/auth-errors.ts
index 1607e36826b..8042bce23e7 100644
--- a/packages/fxa-settings/src/lib/auth-errors/auth-errors.ts
+++ b/packages/fxa-settings/src/lib/auth-errors/auth-errors.ts
@@ -3,13 +3,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { AuthServerError } from 'fxa-auth-client/browser';
+import * as Sentry from '@sentry/browser';
-export type AuthUiError = AuthServerError;
+export type AuthUiError = AuthServerError & { version?: number };
const UNEXPECTED_ERROR_MESSAGE = 'Unexpected error';
const EXPIRED_VERIFICATION_ERROR_MESSAGE =
- 'The link you clicked to verify your email is expired.';
+ 'The link you clicked to confirm your email is expired.';
+const REUSED_SINGLE_USE_CONFIRMATION_CODE_ERROR_MESSAGE =
+ 'That confirmation link was already used, and can only be used once.';
+// We add a `version` value onto the errors for translations. This allows us to signal to translators (via the string ID) that a string has been updated.
const ERRORS = {
UNEXPECTED_ERROR: {
errno: 999,
@@ -45,11 +49,13 @@ const ERRORS = {
},
UNVERIFIED_ACCOUNT: {
errno: 104,
- message: 'Unverified account',
+ message: 'Unconfirmed account',
+ version: 2,
},
INVALID_VERIFICATION_CODE: {
errno: 105,
- message: 'Invalid verification code',
+ message: 'Invalid confirmation code',
+ version: 2,
},
INVALID_JSON: {
errno: 106,
@@ -135,11 +141,13 @@ const ERRORS = {
},
EMAIL_EXISTS: {
errno: 136,
- message: 'This email was already verified by another user',
+ message: 'This email was already confirmed by another user',
+ version: 2,
},
UNVERIFIED_SESSION: {
errno: 138,
- message: 'Unverified session',
+ message: 'Unconfirmed session',
+ version: 2,
},
EMAIL_PRIMARY_EXISTS: {
errno: 139,
@@ -179,7 +187,8 @@ const ERRORS = {
},
CHANGE_EMAIL_TO_UNVERIFIED_EMAIL: {
errno: 147,
- message: 'Can not change primary email to an unverified email',
+ message: 'Can not change primary email to an unconfirmed email',
+ version: 2,
},
CHANGE_EMAIL_TO_UNOWNED_EMAIL: {
errno: 148,
@@ -205,7 +214,8 @@ const ERRORS = {
},
EXPIRED_TOKEN_VERIFICATION_CODE: {
errno: 153,
- message: 'This verification code has expired',
+ message: 'This confirmation code has expired',
+ version: 2,
},
TOTP_TOKEN_EXISTS: {
errno: 154,
@@ -271,7 +281,8 @@ const ERRORS = {
},
INVALID_EXPIRED_SIGNUP_CODE: {
errno: 183,
- message: 'Invalid or expired verification code',
+ message: 'Invalid or expired confirmation code',
+ version: 2,
},
SERVER_BUSY: {
errno: 201,
@@ -373,7 +384,8 @@ const ERRORS = {
},
SIGNUP_EMAIL_BOUNCE: {
errno: 1018,
- message: 'Your verification email was just returned. Mistyped email?',
+ message: 'Your confirmation email was just returned. Mistyped email?',
+ version: 2,
},
DIFFERENT_EMAIL_REQUIRED: {
errno: 1019,
@@ -406,10 +418,12 @@ const ERRORS = {
EXPIRED_VERIFICATION_LINK: {
errno: 1025,
message: EXPIRED_VERIFICATION_ERROR_MESSAGE,
+ version: 2,
},
DAMAGED_VERIFICATION_LINK: {
errno: 1026,
- message: 'Verification link damaged',
+ message: 'Confirmation link damaged',
+ version: 2,
},
UNEXPECTED_POSTMESSAGE_ORIGIN: {
errno: 1027,
@@ -479,11 +493,12 @@ const ERRORS = {
UNKNOWN_ACCOUNT_VERIFICATION: {
errno: 1040,
message: EXPIRED_VERIFICATION_ERROR_MESSAGE,
+ version: 2,
},
REUSED_SIGNIN_VERIFICATION_CODE: {
errno: 1041,
- message:
- 'That confirmation link was already used, and can only be used once.',
+ message: REUSED_SINGLE_USE_CONFIRMATION_CODE_ERROR_MESSAGE,
+ version: 2,
},
INPUT_REQUIRED: {
errno: 1042,
@@ -540,8 +555,8 @@ const ERRORS = {
},
REUSED_PRIMARY_EMAIL_VERIFICATION_CODE: {
errno: 1052,
- message:
- 'That confirmation link was already used, and can only be used once.',
+ message: REUSED_SINGLE_USE_CONFIRMATION_CODE_ERROR_MESSAGE,
+ version: 2,
},
TOTP_CODE_REQUIRED: {
errno: 1053,
@@ -573,7 +588,8 @@ const ERRORS = {
},
OTP_CODE_REQUIRED: {
errno: 1060,
- message: 'Please enter verification code',
+ message: 'Please enter confirmation code',
+ version: 2,
},
/*
Removed in https://github.com/mozilla/fxa/pull/1242
@@ -604,13 +620,41 @@ const ERRORS = {
};
type ErrorKey = keyof typeof ERRORS;
-type ErrorVal = { errno: number; message: string };
+type ErrorVal = { errno: number; message: string; version?: number };
+
+export const composeAuthUiErrorTranslationID = (err: {
+ errno?: number;
+ message: string;
+}) => {
+ /* all of these checks for fields/values being present look a little wonky, but allow us to work with
+ * the AuthUiError type, which has all optional fields. Previously this wasn't an issue bc we didn't use
+ * a utility.
+ */
+ if (err.errno && err.errno in AuthUiErrorNos) {
+ const error = AuthUiErrorNos[err.errno];
+ return `auth-error-${err.errno}${error.version ? '-' + error.version : ''}`;
+ }
+ /*
+ * We opt to return an empty string instead of throwing an error so that this can't break in prod.
+ * Instead, we log to sentry.
+ */
+ const logMessage = err.errno
+ ? `composeAuthUiErrorTranslationID: There is no matching error in AuthUiErrors. error: ${JSON.stringify(
+ err
+ )}`
+ : `composeAuthUiErrorTranslationID: No error number given, unable to create a localization ID for AuthUiError string. error: ${JSON.stringify(
+ err
+ )}`;
+ Sentry.captureMessage(logMessage);
+ return '';
+};
export const AuthUiErrors: { [key in ErrorKey]: AuthUiError } = (
Object.entries(ERRORS) as [[ErrorKey, ErrorVal]]
).reduce((acc: { [key in ErrorKey]: AuthUiError }, [k, v]) => {
const e = new Error(v.message) as AuthUiError;
e.errno = v.errno;
+ e.version = v.version;
acc[k] = e;
return acc;
}, {} as Record);
@@ -621,6 +665,7 @@ export const AuthUiErrorNos: {
(acc: { [key: number]: AuthUiError }, [k, v]) => {
const e = new Error(v.message) as AuthUiError;
e.errno = v.errno;
+ e.version = v.version;
acc[e.errno] = e;
return acc;
},
diff --git a/packages/fxa-settings/src/lib/auth-errors/en-US.ftl b/packages/fxa-settings/src/lib/auth-errors/en-US.ftl
index f632ce49783..c7ac5480658 100644
--- a/packages/fxa-settings/src/lib/auth-errors/en-US.ftl
+++ b/packages/fxa-settings/src/lib/auth-errors/en-US.ftl
@@ -2,7 +2,7 @@
auth-error-102 = Unknown account
auth-error-103 = Incorrect password
-auth-error-105 = Invalid verification code
+auth-error-105-2 = Invalid confirmation code
auth-error-110 = Invalid token
# This string is the amount of time required before a user can attempt another request.
# Variables:
@@ -12,8 +12,8 @@ auth-error-110 = Invalid token
# as part of the string.
# (for example: "in 15 minutes")
auth-error-114 = You’ve tried too many times. Please try again { $retryAfter }.
-auth-error-138 = Unverified session
+auth-error-138-2 = Unconfirmed session
auth-error-139 = Secondary email must be different than your account email
auth-error-155 = TOTP token not found
-auth-error-183 = Invalid or expired verification code
+auth-error-183-2 = Invalid or expired confirmation code
auth-error-1008 = Your new password must be different
diff --git a/packages/fxa-shared/guards/AdminPanelGuard.ts b/packages/fxa-shared/guards/AdminPanelGuard.ts
index 0ee461b6ed6..538a19e7548 100644
--- a/packages/fxa-shared/guards/AdminPanelGuard.ts
+++ b/packages/fxa-shared/guards/AdminPanelGuard.ts
@@ -112,7 +112,7 @@ const defaultAdminPanelPermissions: Permissions = {
level: PermissionLevel.Admin,
},
[AdminPanelFeature.UnverifyEmail]: {
- name: 'Unverify Email Address',
+ name: 'Unconfirm Email Address',
level: PermissionLevel.Admin,
},
[AdminPanelFeature.UnlinkAccount]: {
diff --git a/packages/fxa-support-panel/views/index.hbs b/packages/fxa-support-panel/views/index.hbs
index 26c89567999..d49926536e1 100644
--- a/packages/fxa-support-panel/views/index.hbs
+++ b/packages/fxa-support-panel/views/index.hbs
@@ -12,7 +12,7 @@