From d79a13dc8a77b01bfb472fd0dbf2f0e593a14319 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 5 Mar 2022 13:24:39 -0800 Subject: [PATCH] Localized signup and login --- components/LoginModal/index.tsx | 26 +++++++++++-------- components/SignupModal/index.tsx | 37 +++++++++++++++------------ public/locales/en/common.json | 42 +++++++++++++++++++++++++++++++ public/locales/ja/common.json | 43 ++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 27 deletions(-) diff --git a/components/LoginModal/index.tsx b/components/LoginModal/index.tsx index 2b79c49e..eb11dc41 100644 --- a/components/LoginModal/index.tsx +++ b/components/LoginModal/index.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react' import { useCookies } from 'react-cookie' +import { useTranslation } from 'react-i18next' import { AxiosResponse } from 'axios' import * as Dialog from '@radix-ui/react-dialog' @@ -24,6 +25,8 @@ interface ErrorMap { const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ const LoginModal = (props: Props) => { + const { t } = useTranslation('common') + // Set up form states and error handling const [formValid, setFormValid] = useState(false) const [errors, setErrors] = useState({ @@ -49,16 +52,16 @@ const LoginModal = (props: Props) => { switch(name) { case 'email': if (value.length == 0) - newErrors.email = 'Please enter your email' + newErrors.email = t('modals.login.errors.empty_email') else if (!emailRegex.test(value)) - newErrors.email = 'That email address is not valid' + newErrors.email = t('modals.login.errors.invalid_email') else newErrors.email = '' break case 'password': newErrors.password = value.length == 0 - ? 'Please enter your password' + ? t('modals.login.errors.empty_password') : '' break @@ -117,21 +120,22 @@ const LoginModal = (props: Props) => { access_token: response.data.access_token } - setCookies('account', cookieObj, { path: '/'}) + setCookies('account', cookieObj, { path: '/' }) } function storeUserInfo(response: AxiosResponse) { const user = response.data.user + setCookies('NEXT_LOCALE', user.language, { path: '/' }) + const cookieObj = { picture: user.picture.picture, element: user.picture.element, language: user.language, } - setCookies('user', cookieObj, { path: '/'}) + setCookies('user', cookieObj, { path: '/' }) - accountState.account.language = user.language accountState.account.user = { id: user.id, username: user.username, @@ -155,13 +159,13 @@ const LoginModal = (props: Props) => {
  • - Log in + {t('menu.login')}
  • event.preventDefault() }>
    - Log in + {t('modals.login.title')} @@ -172,7 +176,7 @@ const LoginModal = (props: Props) => {
    {
    - + diff --git a/components/SignupModal/index.tsx b/components/SignupModal/index.tsx index 2c637753..7f3dadf7 100644 --- a/components/SignupModal/index.tsx +++ b/components/SignupModal/index.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react' import { useCookies } from 'react-cookie' +import { Trans, useTranslation } from 'next-i18next' import { AxiosResponse } from 'axios' import * as Dialog from '@radix-ui/react-dialog' @@ -26,6 +27,8 @@ interface ErrorMap { const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ const SignupModal = (props: Props) => { + const { t } = useTranslation('common') + // Set up form states and error handling const [formValid, setFormValid] = useState(false) const [errors, setErrors] = useState({ @@ -95,9 +98,9 @@ const SignupModal = (props: Props) => { language: user.language, } + // TODO: Set language setCookies('user', cookieObj, { path: '/'}) - accountState.account.language = user.language accountState.account.user = { id: user.id, username: user.username, @@ -138,7 +141,7 @@ const SignupModal = (props: Props) => { validateName(fieldName, value) } else { - newErrors[fieldName] = `This ${fieldName} is already in use` + newErrors[fieldName] = t('modals.signup.errors.field_in_use', { field: fieldName}) setErrors(newErrors) setFormValid(false) } @@ -150,9 +153,9 @@ const SignupModal = (props: Props) => { switch(fieldName) { case 'username': if (value.length < 3) - newErrors.username = 'Username must be at least 3 characters' + newErrors.username = t('modals.signup.errors.username_too_short') else if (value.length > 20) - newErrors.username = 'Username must be less than 20 characters' + newErrors.username = t('modals.signup.errors.username_too_long') else newErrors.username = '' @@ -161,7 +164,7 @@ const SignupModal = (props: Props) => { case 'email': newErrors.email = emailRegex.test(value) ? '' - : 'That email address is not valid' + : t('modals.signup.errors.invalid_email') break default: @@ -180,20 +183,20 @@ const SignupModal = (props: Props) => { switch(name) { case 'password': newErrors.password = passwordInput.current?.value.includes(usernameInput.current?.value!) - ? 'Your password should not contain your username' + ? t('modals.signup.errors.password_contains_username') : '' break case 'password': newErrors.password = value.length < 8 - ? 'Password must be at least 8 characters' + ? t('modals.signup.errors.password_too_short') : '' break case 'confirm_password': newErrors.passwordConfirmation = passwordInput.current?.value === passwordConfirmationInput.current?.value ? '' - : 'Your passwords don\'t match' + : t('modals.signup.errors.passwords_dont_match') break default: @@ -231,13 +234,13 @@ const SignupModal = (props: Props) => {
  • - Sign up + {t('menu.signup')}
  • event.preventDefault() }>
    - Sign up + {t('modals.signup.title')} @@ -248,7 +251,7 @@ const SignupModal = (props: Props) => {
    {
    {
    {
    - + - By signing up, I agree to the
    Terms and Conditions and Usage Guidelines. + + By signing up, I agree to the Privacy PolicyUsage Guidelines. +
    diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 1cba56d4..8620f84a 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -54,6 +54,22 @@ "cancel": "Nevermind" } }, + "login": { + "title": "Log in", + "buttons": { + "confirm": "Log in" + }, + "errors": { + "empty_email": "Please enter your email", + "empty_password": "Please enter your password", + "invalid_email": "That email address is not valid", + "invalid_credentials": "Your email address or password is incorrect" + }, + "placeholders": { + "email": "Email address", + "password": "Password" + } + }, "settings": { "title": "Account Settings", "labels": { @@ -71,14 +87,40 @@ "buttons": { "confirm": "Save settings" } + }, + "signup": { + "title": "Create an account", + "buttons": { + "confirm": "Sign up" + }, + "agreement": "By signing up, I agree to the
    <2>Privacy Policy and <1>Usage Guidelines.", + "errors": { + "field_in_use": "This {{field}} is already in use", + "empty_email": "Please enter your email", + "invalid_email": "That email address is not valid", + "username_too_short": "Username must be at least 3 characters", + "username_too_long": "Username must be less than 20 characters", + "empty_password": "Please enter your password", + "password_contains_username": "Your password should not contain your username", + "password_too_short": "Password must be at least 8 characters", + "mismatched_passwords": "Your passwords don't match" + }, + "placeholders": { + "username": "Username", + "email": "Email address", + "password": "Password", + "password_confirm": "Password (again)" + } } }, "menu": { "about": "About", "guides": "Guides", "language": "Language", + "login": "Log in", "saved": "Saved", "settings": "Settings", + "signup": "Sign up", "teams": "Teams", "logout": "Logout" }, diff --git a/public/locales/ja/common.json b/public/locales/ja/common.json index e76b09ca..e77619e9 100644 --- a/public/locales/ja/common.json +++ b/public/locales/ja/common.json @@ -54,6 +54,22 @@ "cancel": "キャンセル" } }, + "login": { + "title": "ログイン", + "buttons": { + "confirm": "ログイン" + }, + "errors": { + "empty_email": "メールアドレスを入力して下さい", + "empty_password": "パスワードを入力して下さい", + "invalid_email": "メールアドレスは有効ではありません", + "invalid_credentials": "パスワードまたはメールアドレスが違います" + }, + "placeholders": { + "email": "メールアドレス", + "password": "パスワード" + } + }, "settings": { "title": "アカウント設定", "labels": { @@ -71,14 +87,41 @@ "buttons": { "confirm": "設定を保存する" } + }, + "signup": { + "title": "アカウント登録", + "buttons": { + "confirm": "登録する" + }, + "agreement": "続行することで<1>利用規約に同意し、
    <1>プライバシーポリシーを読んだものとみなされます。", + "errors": { + "field_in_use": "入力された{{field}}は既に登録済みです", + "empty_email": "メールアドレスを入力して下さい", + "invalid_email": "メールアドレスは有効ではありません", + "username_too_short": "ユーザーネームは3文字以上で入力してください", + "username_too_long": "ユーザーネームは20文字以内で入力してください", + "empty_password": "パスワードを入力して下さい", + "password_contains_username": "パスワードにはユーザー名を含めないでください", + "password_too_short": "パスワードは8文字以上で入力してください", + "mismatched_passwords": "パスワードとパスワード確認を確かめてください", + "invalid_credentials": "パスワードまたはメールアドレスが違います" + }, + "placeholders": { + "username": "ユーザー名", + "email": "メールアドレス", + "password": "パスワード", + "password_confirm": "パスワード確認" + } } }, "menu": { "about": "このサイトについて", "guides": "攻略", "language": "言語", + "login": "ログイン", "saved": "保存した編成", "settings": "アカウント設定", + "signup": "登録", "teams": "編成一覧", "logout": "ログアウト" },