Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support localization for Nav components #688

Merged
merged 31 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1deba34
init localization
NoahDragon Jun 27, 2023
1870606
Merge https://github.com/danny-avila/LibreChat
NoahDragon Jun 27, 2023
c0c5b2a
Update defaul to en
NoahDragon Jun 27, 2023
00c612c
Merge branch 'main' of https://github.com/danny-avila/LibreChat into …
NoahDragon Jun 27, 2023
773418a
Fix merge issue and import path.
NoahDragon Jun 27, 2023
b313db7
Set default to en
NoahDragon Jun 27, 2023
6c8f47c
Merge branch 'main' of https://github.com/NoahDragon/LibreChat into main
NoahDragon Jun 27, 2023
b2b4a2d
Change jsx to tsx
NoahDragon Jun 27, 2023
cc619b8
Merge branch 'main' of https://github.com/danny-avila/LibreChat into …
NoahDragon Jun 27, 2023
78cb0b3
Merge main http://github.com/danny-avila/LibreChat
NoahDragon Jul 7, 2023
67da8a2
Update the password max length string.
NoahDragon Jul 7, 2023
98df1cd
Merge branch 'main' into main
NoahDragon Jul 7, 2023
fe7199e
Remove languageContext as using the recoil instead.
NoahDragon Jul 11, 2023
4f68b55
Merge branch 'main' of https://github.com/danny-avila/LibreChat into …
NoahDragon Jul 11, 2023
f73e592
Merge branch 'main' of https://github.com/NoahDragon/LibreChat into main
NoahDragon Jul 11, 2023
ad5aba4
Merge branch 'main' of https://github.com/danny-avila/LibreChat into …
NoahDragon Jul 12, 2023
62ad300
Add localization to component endpoints pages
NoahDragon Jul 19, 2023
69035c5
Revert default to en after testing.
NoahDragon Jul 19, 2023
c5f9da2
Merge branch 'main' of https://github.com/danny-avila/LibreChat into …
NoahDragon Jul 19, 2023
b7a413d
Update LoginForm.tsx
NoahDragon Jul 19, 2023
02eb6a7
Fix translation.
NoahDragon Jul 19, 2023
d72c1d5
Merge branch 'main' of https://github.com/NoahDragon/LibreChat into main
NoahDragon Jul 19, 2023
b048a17
Merge branch 'main' into main
NoahDragon Jul 22, 2023
abcfb76
Merge branch 'main' into main
NoahDragon Jul 22, 2023
28d86ad
Make lint happy
NoahDragon Jul 22, 2023
babc542
Merge branch 'main' of https://github.com/danny-avila/LibreChat into …
NoahDragon Jul 23, 2023
44cdb0e
Merge (#1)
NoahDragon Jul 23, 2023
861f849
Translate Nav pages
NoahDragon Jul 23, 2023
695c35b
Merge branch 'main' of https://github.com/NoahDragon/LibreChat into main
NoahDragon Jul 23, 2023
10aa6f2
Fix npm test
NoahDragon Jul 23, 2023
dd2264a
Merge branch 'main' into main
NoahDragon Jul 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
init localization
  • Loading branch information
NoahDragon committed Jun 27, 2023
commit 1deba34c82eb49cd08de0b2027df2855370318df
28,757 changes: 28,757 additions & 0 deletions client/package-lock.json

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions client/src/components/Auth/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ import LoginForm from './LoginForm';
import { useAuthContext } from '~/hooks/AuthContext';
import { useNavigate } from 'react-router-dom';
import { SHOW_GOOGLE_LOGIN_OPTION, ALLOW_REGISTRATION, DOMAIN_SERVER } from "~/utils/envConstants";
import { useRecoilValue } from 'recoil';
import store from '~/store';
import { localize } from '../../localization/Translation';

function Login() {
const { login, error, isAuthenticated } = useAuthContext();

const lang = useRecoilValue(store.lang);

const navigate = useNavigate();

useEffect(() => {
Expand All @@ -18,23 +23,22 @@ function Login() {
return (
<div className="flex min-h-screen flex-col items-center justify-center bg-white pt-6 sm:pt-0">
<div className="mt-6 w-96 overflow-hidden bg-white px-6 py-4 sm:max-w-md sm:rounded-lg">
<h1 className="mb-4 text-center text-3xl font-semibold">Welcome back</h1>
<h1 className="mb-4 text-center text-3xl font-semibold">{localize(lang, 'com_auth_welcome_back')}</h1>
{error && (
<div
className="relative mt-4 rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700"
role="alert"
>
Unable to login with the information provided. Please check your credentials and try
again.
{localize(lang, 'com_auth_error_login')}
</div>
)}
<LoginForm onSubmit={login} />
{ALLOW_REGISTRATION && (
<p className="my-4 text-center text-sm font-light text-gray-700">
{' '}
Don&apos;t have an account?{' '}
{localize(lang, 'com_auth_no_account')}{' '}
<a href="/register" className="p-1 text-green-500 hover:underline">
Sign up
{localize(lang, 'com_auth_sign_up')}
</a>
</p>
)}
Expand Down Expand Up @@ -72,7 +76,7 @@ function Login() {
d="m419.404 58.936-82.933 67.896C313.136 112.246 285.552 103.82 256 103.82c-66.729 0-123.429 42.957-143.965 102.724l-83.397-68.276h-.014C71.23 56.123 157.06 0 256 0c62.115 0 119.068 22.126 163.404 58.936z"
></path>
</svg>
<p>Login with Google</p>
<p>{localize(lang, 'com_auth_google_login')}</p>
</a>
</div>
</>
Expand Down
31 changes: 18 additions & 13 deletions client/src/components/Auth/LoginForm.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { useForm } from 'react-hook-form';
import { TLoginUser } from '~/data-provider';
import { useRecoilValue } from 'recoil';
import store from '~/store';
import { localize } from '../../localization/Translation';

type TLoginFormProps = {
onSubmit: (data: TLoginUser) => void;
};

function LoginForm({ onSubmit }: TLoginFormProps) {
const lang = useRecoilValue(store.lang);

const {
register,
handleSubmit,
Expand All @@ -25,20 +30,20 @@ function LoginForm({ onSubmit }: TLoginFormProps) {
type="text"
id="email"
autoComplete="email"
aria-label="Email"
aria-label={localize(lang, 'com_auth_email')}
{...register('email', {
required: 'Email is required',
required: localize(lang, 'com_auth_email_required'),
minLength: {
value: 3,
message: 'Email must be at least 6 characters'
message: localize(lang, 'com_auth_email_min_length')
},
maxLength: {
value: 120,
message: 'Email should not be longer than 120 characters'
message: localize(lang, 'com_auth_email_max_length')
},
pattern: {
value: /\S+@\S+\.\S+/,
message: 'You must enter a valid email address'
message: localize(lang, 'com_auth_email_pattern')
}
})}
aria-invalid={!!errors.email}
Expand All @@ -49,7 +54,7 @@ function LoginForm({ onSubmit }: TLoginFormProps) {
htmlFor="email"
className="absolute left-2.5 top-4 z-10 origin-[0] -translate-y-4 scale-75 transform text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:text-green-500"
>
Email address
{localize(lang, 'com_auth_email_address')}
</label>
</div>
{errors.email && (
Expand All @@ -65,16 +70,16 @@ function LoginForm({ onSubmit }: TLoginFormProps) {
type="password"
id="password"
autoComplete="current-password"
aria-label="Password"
aria-label={localize(lang, 'com_auth_password')}
{...register('password', {
required: 'Password is required',
required: localize(lang, 'com_auth_password_required'),
minLength: {
value: 8,
message: 'Password must be at least 8 characters'
message: localize(lang, 'com_auth_password_min_length')
},
maxLength: {
value: 40,
message: 'Password must be less than 40 characters'
message: localize(lang, 'com_auth_password_max_length')
}
})}
aria-invalid={!!errors.password}
Expand All @@ -85,7 +90,7 @@ function LoginForm({ onSubmit }: TLoginFormProps) {
htmlFor="password"
className="absolute left-2.5 top-4 z-10 origin-[0] -translate-y-4 scale-75 transform text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:text-green-500"
>
Password
{localize(lang, 'com_auth_password')}
</label>
</div>

Expand All @@ -97,15 +102,15 @@ function LoginForm({ onSubmit }: TLoginFormProps) {
)}
</div>
<a href="/forgot-password" className="text-sm text-green-500 hover:underline">
Forgot Password?
{localize(lang, 'com_auth_password_forgot')}
</a>
<div className="mt-6">
<button
aria-label="Sign in"
type="submit"
className="w-full transform rounded-sm bg-green-500 px-4 py-3 tracking-wide text-white transition-colors duration-200 hover:bg-green-600 focus:bg-green-600 focus:outline-none"
>
Continue
{localize(lang, 'com_auth_continue')}
</button>
</div>
</form>
Expand Down
61 changes: 33 additions & 28 deletions client/src/components/Auth/Registration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ import { useNavigate } from 'react-router-dom';
import { useForm } from 'react-hook-form';
import { useRegisterUserMutation, TRegisterUser } from '~/data-provider';
import { SHOW_GOOGLE_LOGIN_OPTION, DOMAIN_SERVER } from '~/utils/envConstants';
import { useRecoilValue } from 'recoil';
import store from '~/store';
import { localize } from '../../localization/Translation';

function Registration() {
const navigate = useNavigate();

const lang = useRecoilValue(store.lang);

const {
register,
watch,
Expand Down Expand Up @@ -58,16 +63,16 @@ function Registration() {
id="name"
type="text"
autoComplete="name"
aria-label="Full name"
aria-label={localize(lang, 'com_auth_full_name')}
{...register('name', {
required: 'Name is required',
required: localize(lang, 'com_auth_name_required'),
minLength: {
value: 3,
message: 'Name must be at least 3 characters'
message: localize(lang, 'com_auth_name_min_length')
},
maxLength: {
value: 80,
message: 'Name must be less than 80 characters'
message: localize(lang, 'com_auth_name_max_length')
}
})}
aria-invalid={!!errors.name}
Expand All @@ -78,7 +83,7 @@ function Registration() {
htmlFor="name"
className="absolute left-2.5 top-4 z-10 origin-[0] -translate-y-4 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:text-green-500"
>
Full name
{localize(lang, 'com_auth_full_name')}
</label>
</div>

Expand All @@ -94,16 +99,16 @@ function Registration() {
<input
type="text"
id="username"
aria-label="Username"
aria-label={localize(lang, 'com_auth_username')}
{...register('username', {
required: 'Username is required',
required: localize(lang, 'com_auth_username_required'),
minLength: {
value: 3,
message: 'Username must be at least 3 characters'
message: localize(lang, 'com_auth_username_min_length')
},
maxLength: {
value: 20,
message: 'Username must be less than 20 characters'
message: localize(lang, 'com_auth_username_max_length')
}
})}
aria-invalid={!!errors.username}
Expand All @@ -115,7 +120,7 @@ function Registration() {
htmlFor="username"
className="absolute left-2.5 top-4 z-10 origin-[0] -translate-y-4 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:text-green-500"
>
Username
{localize(lang, 'com_auth_username')}
</label>
</div>

Expand All @@ -132,20 +137,20 @@ function Registration() {
type="email"
id="email"
autoComplete="email"
aria-label="Email"
aria-label={localize(lang, 'com_auth_email')}
{...register('email', {
required: 'Email is required',
required: localize(lang, 'com_auth_email_required'),
minLength: {
value: 3,
message: 'Email must be at least 6 characters'
message: localize(lang, 'com_auth_email_min_length')
},
maxLength: {
value: 120,
message: 'Email should not be longer than 120 characters'
message: localize(lang, 'com_auth_email_max_length')
},
pattern: {
value: /\S+@\S+\.\S+/,
message: 'You must enter a valid email address'
message: localize(lang, 'com_auth_email_pattern')
}
})}
aria-invalid={!!errors.email}
Expand All @@ -156,7 +161,7 @@ function Registration() {
htmlFor="email"
className="absolute left-2.5 top-4 z-10 origin-[0] -translate-y-4 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:text-green-500"
>
Email
{localize(lang, 'com_auth_email')}
</label>
</div>
{errors.email && (
Expand All @@ -173,16 +178,16 @@ function Registration() {
id="password"
data-testid="password"
autoComplete="current-password"
aria-label="Password"
aria-label={localize(lang, 'com_auth_password')}
{...register('password', {
required: 'Password is required',
required: localize(lang, 'com_auth_password_required'),
minLength: {
value: 8,
message: 'Password must be at least 8 characters'
message: localize(lang, 'com_auth_password_min_length')
},
maxLength: {
value: 40,
message: 'Password must be less than 40 characters'
message: localize(lang, 'com_auth_password_max_length')
}
})}
aria-invalid={!!errors.password}
Expand All @@ -193,7 +198,7 @@ function Registration() {
htmlFor="password"
className="absolute left-2.5 top-4 z-10 origin-[0] -translate-y-4 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:text-green-500"
>
Password
{localize(lang, 'com_auth_password')}
</label>
</div>

Expand All @@ -210,14 +215,14 @@ function Registration() {
type="password"
id="confirm_password"
data-testid="confirm_password"
aria-label="Confirm password"
aria-label={localize(lang, 'com_auth_password_confirm')}
// uncomment to prevent pasting in confirm field
onPaste={(e) => {
e.preventDefault();
return false;
}}
{...register('confirm_password', {
validate: (value) => value === password || 'Passwords do not match'
validate: (value) => value === password || localize(lang, 'com_auth_password_not_match')
})}
aria-invalid={!!errors.confirm_password}
className="peer block w-full appearance-none rounded-t-md border-0 border-b-2 border-gray-300 bg-gray-50 px-2.5 pb-2.5 pt-5 text-sm text-gray-900 focus:border-green-500 focus:outline-none focus:ring-0"
Expand All @@ -227,7 +232,7 @@ function Registration() {
htmlFor="confirm_password"
className="absolute left-2.5 top-4 z-10 origin-[0] -translate-y-4 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:text-green-500"
>
Confirm password
{localize(lang, 'com_auth_password_confirm')}
</label>
</div>

Expand All @@ -251,19 +256,19 @@ function Registration() {
aria-label="Submit registration"
className="w-full transform rounded-sm bg-green-500 px-4 py-3 tracking-wide text-white transition-colors duration-200 hover:bg-green-600 focus:bg-green-600 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-green-500"
>
Continue
{localize(lang, 'com_auth_continue')}
</button>
</div>
</form>
<p className="my-4 text-center text-sm font-light text-gray-700">
{' '}
Already have an account?{' '}
{localize(lang, 'com_auth_already_have_account')}{' '}
<a
href="/login"
aria-label="Login"
className="p-1 font-medium text-green-500 hover:underline"
>
Login
{localize(lang, 'com_auth_login')}
</a>
</p>
{SHOW_GOOGLE_LOGIN_OPTION && (
Expand Down Expand Up @@ -301,7 +306,7 @@ function Registration() {
d="m419.404 58.936-82.933 67.896C313.136 112.246 285.552 103.82 256 103.82c-66.729 0-123.429 42.957-143.965 102.724l-83.397-68.276h-.014C71.23 56.123 157.06 0 256 0c62.115 0 119.068 22.126 163.404 58.936z"
></path>
</svg>
<p>Login with Google</p>
<p>{localize(lang, 'com_auth_google_login')}</p>
</a>
</div>
</>
Expand Down
Loading