Skip to content

Commit 9d0f467

Browse files
committed
fix missing translation keys and raw error strings across auth and dashboard flows
1 parent 27de4eb commit 9d0f467

10 files changed

Lines changed: 71 additions & 22 deletions

File tree

frontend/components/auth/LoginForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export function LoginForm({ locale, returnTo }: LoginFormProps) {
8585

8686
if (!res.ok) {
8787
setErrorCode(data?.code ?? 'RESEND_FAILED');
88-
setErrorMessage(data?.error ?? t('errors.resendFailed'));
88+
setErrorMessage(t('errors.resendFailed'));
8989
return;
9090
}
9191

frontend/components/auth/ResetPasswordForm.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,8 @@ export function ResetPasswordForm({ token }: ResetPasswordFormProps) {
7575
}),
7676
});
7777

78-
const data = await res.json().catch(() => null);
79-
8078
if (!res.ok) {
81-
const msg =
82-
typeof data?.error === 'string'
83-
? data.error
84-
: t('errors.resetFailed');
85-
setError(msg);
79+
setError(t('errors.resetFailed'));
8680
return;
8781
}
8882

frontend/components/auth/SignupForm.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,11 @@ export function SignupForm({ locale, returnTo }: SignupFormProps) {
161161
const data = await res.json().catch(() => null);
162162

163163
if (!res.ok) {
164-
const msg =
165-
typeof data?.error === 'string'
166-
? data.error
167-
: t('errors.signupFailed');
168-
setError(msg);
164+
setError(
165+
res.status === 409
166+
? t('errors.emailAlreadyInUse')
167+
: t('errors.signupFailed')
168+
);
169169
return;
170170
}
171171

frontend/components/auth/fields/EmailField.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export function EmailField({
2727

2828
if (input.validity.tooShort && minLength) {
2929
input.setCustomValidity(
30-
`Email must be at least ${minLength} characters.`
30+
t('validation.emailTooShort', { EMAIL_MIN_LEN: minLength })
3131
);
3232
return;
3333
}
@@ -38,7 +38,9 @@ export function EmailField({
3838
}
3939

4040
if (input.validity.tooLong && maxLength) {
41-
input.setCustomValidity(`Email must be at most ${maxLength} characters.`);
41+
input.setCustomValidity(
42+
t('validation.emailTooLong', { EMAIL_MAX_LEN: maxLength })
43+
);
4244
return;
4345
}
4446
};

frontend/components/auth/fields/NameField.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,22 @@ export function NameField({
2828
}
2929

3030
if (input.validity.tooShort && minLength) {
31-
input.setCustomValidity(`Name must be at least ${minLength} characters.`);
31+
input.setCustomValidity(
32+
t('validation.invalidName', {
33+
NAME_MIN_LEN: minLength,
34+
NAME_MAX_LEN: maxLength ?? minLength,
35+
})
36+
);
3237
return;
3338
}
3439

3540
if (input.validity.tooLong && maxLength) {
36-
input.setCustomValidity(`Name must be at most ${maxLength} characters.`);
41+
input.setCustomValidity(
42+
t('validation.invalidName', {
43+
NAME_MIN_LEN: minLength ?? 0,
44+
NAME_MAX_LEN: maxLength,
45+
})
46+
);
3747
return;
3848
}
3949
};

frontend/components/auth/fields/PasswordField.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
import { useTranslations } from 'next-intl';
44
import { useState } from 'react';
55

6+
import {
7+
PASSWORD_MAX_BYTES,
8+
PASSWORD_MIN_LEN,
9+
} from '@/lib/auth/signup-constraints';
10+
611
type PasswordFieldProps = {
712
name?: string;
813
id?: string;
@@ -44,8 +49,12 @@ export function PasswordField({
4449
}
4550

4651
if (input.validity.patternMismatch) {
52+
const reqs = t('validation.passwordRequirements', {
53+
PASSWORD_MIN_LEN: minLength ?? PASSWORD_MIN_LEN,
54+
PASSWORD_MAX_BYTES,
55+
});
4756
input.setCustomValidity(
48-
'Password must include at least one capital letter and one special character.'
57+
t('validation.invalidPassword', { passwordRequirementsText: reqs })
4958
);
5059
return;
5160
}

frontend/components/dashboard/ProfileCard.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export function ProfileCard({
4343
}: ProfileCardProps) {
4444
const t = useTranslations('dashboard.profile');
4545
const tStats = useTranslations('dashboard.stats');
46+
const tFields = useTranslations('auth.fields');
4647
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
4748
const [isSaving, setIsSaving] = useState(false);
4849

@@ -271,6 +272,14 @@ export function ProfileCard({
271272
className="w-full rounded-xl border border-gray-200 bg-white px-4 py-2.5 text-sm transition-all outline-none placeholder:text-gray-400 focus:border-(--accent-primary) focus:ring-1 focus:ring-(--accent-primary) dark:border-neutral-800 dark:bg-neutral-900 dark:text-white"
272273
placeholder={t('defaultName')}
273274
required
275+
onInvalid={e => {
276+
if (e.currentTarget.validity.valueMissing) {
277+
e.currentTarget.setCustomValidity(
278+
tFields('validation.required')
279+
);
280+
}
281+
}}
282+
onInput={e => e.currentTarget.setCustomValidity('')}
274283
/>
275284
</div>
276285
<button
@@ -299,6 +308,14 @@ export function ProfileCard({
299308
placeholder={t('currentPassword')}
300309
className="w-full rounded-xl border border-gray-200 bg-white px-4 py-2.5 text-sm transition-all outline-none placeholder:text-gray-400 focus:border-(--accent-primary) focus:ring-1 focus:ring-(--accent-primary) dark:border-neutral-800 dark:bg-neutral-900 dark:text-white"
301310
required
311+
onInvalid={e => {
312+
if (e.currentTarget.validity.valueMissing) {
313+
e.currentTarget.setCustomValidity(
314+
tFields('validation.required')
315+
);
316+
}
317+
}}
318+
onInput={e => e.currentTarget.setCustomValidity('')}
302319
/>
303320
</div>
304321
<div>
@@ -309,6 +326,14 @@ export function ProfileCard({
309326
minLength={8}
310327
className="w-full rounded-xl border border-gray-200 bg-white px-4 py-2.5 text-sm transition-all outline-none placeholder:text-gray-400 focus:border-(--accent-primary) focus:ring-1 focus:ring-(--accent-primary) dark:border-neutral-800 dark:bg-neutral-900 dark:text-white"
311328
required
329+
onInvalid={e => {
330+
if (e.currentTarget.validity.valueMissing) {
331+
e.currentTarget.setCustomValidity(
332+
tFields('validation.required')
333+
);
334+
}
335+
}}
336+
onInput={e => e.currentTarget.setCustomValidity('')}
312337
/>
313338
</div>
314339
<button

frontend/messages/en.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@
11211121
"loginLink": "Log in",
11221122
"errors": {
11231123
"signupFailed": "Failed to sign up. Please try again.",
1124+
"emailAlreadyInUse": "An account with this email already exists. Try logging in.",
11241125
"networkError": "Network error. Please check your connection and try again."
11251126
},
11261127
"verificationSent": "We've sent a verification email to",
@@ -1159,13 +1160,15 @@
11591160
"show": "Show",
11601161
"hide": "Hide",
11611162
"validation": {
1162-
"emailRequired": "Email is required",
1163+
"required": "This field is required",
11631164
"invalidName": "Name must be at least {NAME_MIN_LEN} characters and at most {NAME_MAX_LEN} characters",
11641165
"emailTooShort": "Email must be at least {EMAIL_MIN_LEN} characters",
11651166
"emailTooLong": "Email must not exceed {EMAIL_MAX_LEN} characters",
11661167
"invalidEmail": "Please enter a valid email address",
11671168
"passwordRequirements": "{PASSWORD_MIN_LEN}-{PASSWORD_MAX_BYTES} characters, at least one capital letter, and at least one special character",
11681169
"invalidPassword": "Password must meet requirements: {passwordRequirementsText}",
1170+
"passwordTooShort": "Password must be at least {minLength} characters",
1171+
"passwordTooLongBytes": "Password must not exceed {PASSWORD_MAX_BYTES} characters",
11691172
"passwordsDontMatch": "Passwords don't match"
11701173
}
11711174
},

frontend/messages/pl.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@
11211121
"loginLink": "Zaloguj się",
11221122
"errors": {
11231123
"signupFailed": "Nie udało się zarejestrować. Spróbuj ponownie.",
1124+
"emailAlreadyInUse": "Konto z tym adresem email już istnieje. Spróbuj się zalogować.",
11241125
"networkError": "Błąd sieci. Sprawdź połączenie i spróbuj ponownie."
11251126
},
11261127
"verificationSent": "Wysłaliśmy email weryfikacyjny na",
@@ -1159,13 +1160,15 @@
11591160
"show": "Pokaż",
11601161
"hide": "Ukryj",
11611162
"validation": {
1162-
"emailRequired": "Proszę wypełnić to pole",
1163+
"required": "To pole jest wymagane",
11631164
"invalidName": "Imię i nazwisko musi mieć co najmniej {NAME_MIN_LEN} znaków i nie więcej niż {NAME_MAX_LEN} znaków",
11641165
"emailTooShort": "Adres e-mail musi mieć co najmniej {EMAIL_MIN_LEN} znaków",
11651166
"emailTooLong": "Adres e-mail nie może mieć więcej niż {EMAIL_MAX_LEN} znaków",
11661167
"invalidEmail": "Proszę podać prawidłowy adres email",
11671168
"passwordRequirements": "{PASSWORD_MIN_LEN}–{PASSWORD_MAX_BYTES} znaków, co najmniej jedną wielką literę i co najmniej jeden znak specjalny",
11681169
"invalidPassword": "Hasło musi spełniać wymagania: {passwordRequirementsText}",
1170+
"passwordTooShort": "Hasło musi mieć co najmniej {minLength} znaków",
1171+
"passwordTooLongBytes": "Hasło nie może przekraczać {PASSWORD_MAX_BYTES} znaków",
11691172
"passwordsDontMatch": "Hasła nie zgadzają się"
11701173
}
11711174
},

frontend/messages/uk.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@
11211121
"loginLink": "Увійти",
11221122
"errors": {
11231123
"signupFailed": "Не вдалося зареєструватися. Спробуйте ще раз.",
1124+
"emailAlreadyInUse": "Акаунт з такою електронною адресою вже існує. Спробуйте увійти.",
11241125
"networkError": "Помилка мережі. Перевірте з'єднання та спробуйте ще раз."
11251126
},
11261127
"verificationSent": "Ми надіслали лист підтвердження на",
@@ -1159,13 +1160,15 @@
11591160
"show": "Показати",
11601161
"hide": "Сховати",
11611162
"validation": {
1162-
"emailRequired": "Будь ласка, введіть email",
1163+
"required": "Це поле є обов'язковим",
11631164
"invalidName": "Ім'я має містити не менше {NAME_MIN_LEN} символів та не більше {NAME_MAX_LEN} символів",
11641165
"emailTooShort": "Електронна адреса має містити щонайменше {EMAIL_MIN_LEN} символів",
11651166
"emailTooLong": "Електронна адреса не повинна перевищувати {EMAIL_MAX_LEN} символів",
11661167
"invalidEmail": "Будь ласка, введіть дійсну адресу електронної пошти",
1167-
"passwordRequirements": "{PASSWORD_MIN_LEN}-{PASSWORD_MAX_BYTES} символи, принаймні одна велика літера та принаймні один спеціальний символ",
1168+
"passwordRequirements": "{PASSWORD_MIN_LEN}-{PASSWORD_MAX_BYTES} символів, принаймні одна велика літера та принаймні один спеціальний символ",
11681169
"invalidPassword": "Пароль має відповідати вимогам: {passwordRequirementsText}",
1170+
"passwordTooShort": "Пароль має містити щонайменше {minLength} символів",
1171+
"passwordTooLongBytes": "Пароль не повинен перевищувати {PASSWORD_MAX_BYTES} символів",
11691172
"passwordsDontMatch": "Паролі не співпадають"
11701173
}
11711174
},

0 commit comments

Comments
 (0)