Skip to content

Commit

Permalink
Merge pull request #39 from okisdev/i18n
Browse files Browse the repository at this point in the history
  • Loading branch information
okisdev authored May 5, 2023
2 parents 4a815dd + 3453fd3 commit f924b3f
Show file tree
Hide file tree
Showing 53 changed files with 753 additions and 201 deletions.
8 changes: 3 additions & 5 deletions README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ https://user-images.githubusercontent.com/66008528/235539163-35f7ee91-e357-453a-
## Features

- [x] TTS
- [x] Dark Mode
- [x] Chat with files
- [x] Markdown formatting
- [x] Multi-language support
- [x] Support for System Prompt
- [x] Shortcut menu (command + k)
- [x] Wrapped API (no more proxies)
Expand All @@ -53,11 +55,7 @@ https://user-images.githubusercontent.com/66008528/235539163-35f7ee91-e357-453a-

## Roadmap

- [ ] Dark Mode
- [ ] Voice input
- [ ] More API support
- [x] Personal Dashboard
- [ ] Multi-language support
Please refer to https://github.com/users/okisdev/projects/7

## Usage

Expand Down
8 changes: 3 additions & 5 deletions README.zh_CN.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ https://user-images.githubusercontent.com/66008528/235539163-35f7ee91-e357-453a-
## 功能

- [x] TTS
- [x] 黑暗模式
- [x] 与文件聊天
- [x] 支持多种语言
- [x] 支持分享对话
- [x] 支持流信息(SSE)
- [x] Markdown 格式化
Expand All @@ -54,11 +56,7 @@ https://user-images.githubusercontent.com/66008528/235539163-35f7ee91-e357-453a-

## Roadmap

- [ ] 语音输入
- [ ] 黑暗模式
- [x] 个人仪表板
- [ ] 多语言支持
- [ ] 支持更多 API
请参考 https://github.com/users/okisdev/projects/7

## 使用

Expand Down
8 changes: 3 additions & 5 deletions README.zh_HK.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ https://user-images.githubusercontent.com/66008528/235539163-35f7ee91-e357-453a-
## 功能

- [x] TTS
- [x] 暗色模式
- [x] 與文件聊天
- [x] 多語言支持
- [x] 支持分享對話
- [x] 支持流信息(SSE)
- [x] Markdown 格式化
Expand All @@ -53,11 +55,7 @@ https://user-images.githubusercontent.com/66008528/235539163-35f7ee91-e357-453a-

## Roadmap

- [ ] 語音輸入
- [ ] 黑暗模式
- [x] 個人儀表板
- [ ] 多語言支持
- [ ] 支持更多 API
請查看 https://github.com/users/okisdev/projects/7

## 使用

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import LandingSide from '@/components/landing/side';
import LandingSide from '@/components/landing/side/side';

import { getCurrentUserProfile } from '@/lib/auth/session';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import store from '@/hooks/store';
import { useAtomValue } from 'jotai';

import LandingHeader from '@/components/landing/header';
import ChatMain from '@/components/landing/mode/chat-main';
import LandingHeader from '@/components/landing/main/header';
import ChatMain from '@/components/landing/main/chat-main';

export default function ChatModePage() {
const isHiddenSide = useAtomValue(store.isHiddenSideAtom);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import store from '@/hooks/store';
import { useAtomValue } from 'jotai';

import LandingHeader from '@/components/landing/header';
import CodeMain from '@/components/landing/mode/code-main';
import LandingHeader from '@/components/landing/main/header';
import CodeMain from '@/components/landing/main/code-main';

export default function CodeModePage() {
const isHiddenSide = useAtomValue(store.isHiddenSideAtom);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import store from '@/hooks/store';
import { useAtomValue } from 'jotai';

import LandingHeader from '@/components/landing/header';
import FileMain from '@/components/landing/mode/file-main';
import LandingHeader from '@/components/landing/main/header';
import FileMain from '@/components/landing/main/file-main';

export default function FileModePage() {
const isHiddenSide = useAtomValue(store.isHiddenSideAtom);
Expand Down
2 changes: 1 addition & 1 deletion app/(landing)/page.tsx → app/[locale]/(landing)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import dynamic from 'next/dynamic';

const ChatMode = dynamic(() => import('@/app/(landing)/mode/chat/page'), {});
const ChatMode = dynamic(() => import('@/app/[locale]/(landing)/mode/chat/page'), {});

export default function LandingPage() {
return <ChatMode />;
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
23 changes: 23 additions & 0 deletions app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import '@/styles/globals.css';
import '@/styles/markdown.css';
import 'tippy.js/dist/tippy.css';

import { NextIntlClientProvider } from 'next-intl';

import NotFound from '@/app/not-found';

export default async function LocaleLayout({ children, params: { locale } }: { children: React.ReactNode; params: { locale: string } }) {
let messages;

try {
messages = (await import(`../../locales/${locale}.json`)).default;
} catch (error) {
return <NotFound />;
}

return (
<NextIntlClientProvider locale={locale} messages={messages}>
{children}
</NextIntlClientProvider>
);
}
File renamed without changes.
10 changes: 5 additions & 5 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import '@/styles/globals.css';
import '@/styles/markdown.css';
import 'tippy.js/dist/tippy.css';

import { rubik } from '@/app/fonts';
import { rubik } from '@/app/[locale]/fonts';

import { Providers } from '@/app/providers';
import { Providers } from '@/app/[locale]/providers';

import { Analytics } from '@vercel/analytics/react';

Expand All @@ -13,12 +13,12 @@ import { ClientCommand } from '@/components/client/command';

import { siteConfig } from '@/config/site.config';

export default function RootLayout({ children }: { children: React.ReactNode }) {
export default async function RootLayout({ children, params: { locale } }: { children: React.ReactNode; params: { locale: string } }) {
return (
<html className={`${rubik.className}`} lang='en'>
<html className={`${rubik.className}`} lang={locale}>
<head>
<title>{siteConfig.title}</title>
<meta charSet='utf-8' />

<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0' />
<meta name='description' content={siteConfig.description} />

Expand Down
20 changes: 11 additions & 9 deletions components/auth/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { useState } from 'react';

import Link from 'next/link';

import { useTranslations } from 'next-intl';

import { signIn } from 'next-auth/react';

import { toast } from 'react-hot-toast';
Expand All @@ -15,6 +17,8 @@ import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';

const AuthForm = ({ login }: { login: boolean }) => {
const t = useTranslations('auth');

const [email, setEmail] = useState<string>('');

const handleEmailSubmit = async () => {
Expand All @@ -32,8 +36,6 @@ const AuthForm = ({ login }: { login: boolean }) => {
callbackUrl: '/profile',
});

console.log(emailSignIn);

if (emailSignIn?.error) {
return toast.error('Failed to send email');
}
Expand All @@ -46,21 +48,21 @@ const AuthForm = ({ login }: { login: boolean }) => {
<div className='flex flex-col items-center'>
{login ? (
<>
<p className='text-xl font-bold'>Sign In</p>
<p className='text-xl font-bold'>{t('Sign In')}</p>
<p className='text-sm'>
New User?{' '}
{t('New User?')}{' '}
<Link href={'/register'} className='font-medium text-blue-800 underline dark:text-sky-400'>
Sign up
{t('Sign up')}
</Link>
</p>
</>
) : (
<>
<p className='text-xl font-bold'>Register</p>
<p className='text-xl font-bold'>{t('Register')}</p>
<p className='text-sm'>
Already have an account with us?{' '}
{t('Already have an account with us?')}{' '}
<Link href={'/login'} className='font-medium text-blue-800 underline'>
Log In
{t('Log In')}
</Link>
</p>
</>
Expand All @@ -78,7 +80,7 @@ const AuthForm = ({ login }: { login: boolean }) => {
className='dark:bg-stone-600'
/>
<Button variant='default' onClick={handleEmailSubmit}>
Sign In With Email
{t('Sign In With Email')}
</Button>
</div>
{/* <div className='relative'>
Expand Down
6 changes: 5 additions & 1 deletion components/auth/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Image from 'next/image';

import { useRouter } from 'next/navigation';

import { useTranslations } from 'next-intl';

import { Button } from '@/components/ui/button';

import { IoArrowBackOutline } from 'react-icons/io5';
Expand All @@ -12,11 +14,13 @@ import { siteConfig } from '@/config/site.config';
const AuthHeader = () => {
const router = useRouter();

const t = useTranslations('auth');

return (
<div className='flex h-36 w-full flex-row items-center justify-between'>
<Button variant='secondary' className='inline-flex items-center space-x-2 dark:bg-stone-600' onClick={() => router.push('/')}>
<IoArrowBackOutline />
<span>Home</span>
<span>{t('Home')}</span>
</Button>
<div className='flex flex-row items-center md:hidden'>
<Image src='/hero.png' alt={siteConfig.title} width={60} height={60} priority />
Expand Down
14 changes: 10 additions & 4 deletions components/dashboard/nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import { usePathname } from 'next/navigation';

import { useTranslations } from 'next-intl';

import { signOut } from 'next-auth/react';

import { RxAvatar } from 'react-icons/rx';
Expand All @@ -16,10 +18,14 @@ import { Separator } from '@/components/ui/separator';
const DashboardNav = ({ user }: { user: any }) => {
const pathname = usePathname();

const t = useTranslations('dashboard');

const i18n = /^\/[a-z]{2}-[A-Z]{2}\//.test(pathname ?? '');

const breadcrumbs = pathname
?.split('/')
.filter((path) => path !== '')
.splice(1);
.splice(i18n ? 2 : 1);

const description = DashboardSideItems.find((item) => item.children?.find((child) => child.href === breadcrumbs?.[0]))?.children?.find((child) => child.href === breadcrumbs?.[0])?.description;

Expand All @@ -29,7 +35,7 @@ const DashboardNav = ({ user }: { user: any }) => {
<div className='flex'>
{breadcrumbs?.map((breadcrumb, index) => (
<div key={index} className='inline-flex items-center text-2xl font-medium uppercase text-gray-500 dark:text-stone-200'>
<span className='tracking-wide'>{breadcrumb}</span>
<span className='tracking-wide'>{t(breadcrumb)}</span>
{index !== breadcrumbs.length - 1 && (
<span className='mx-2 inline-block'>
<AiOutlineCaretRight />
Expand Down Expand Up @@ -58,14 +64,14 @@ const DashboardNav = ({ user }: { user: any }) => {
})
}
>
Sign out
{t('Sign out')}
</button>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
<div>
<p className='text-sm text-gray-400'>{description}</p>
<p className='text-sm text-gray-400'>{t(description)}</p>
</div>
<Separator className='my-3' />
</div>
Expand Down
24 changes: 15 additions & 9 deletions components/dashboard/profile-info-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { useState } from 'react';

import { useRouter } from 'next/navigation';

import { useTranslations } from 'next-intl';

import { User } from '@prisma/client';

import { toast } from 'react-hot-toast';
Expand All @@ -22,6 +24,8 @@ import { signOut } from 'next-auth/react';
const ProfileInfoForm = ({ user }: any) => {
const router = useRouter();

const t = useTranslations('dashboard');

const [name, setName] = useState<string>(user.name);
const [email, setEmail] = useState<string>(user.email);
const [image, setImage] = useState<string>(user.image);
Expand Down Expand Up @@ -80,42 +84,44 @@ const ProfileInfoForm = ({ user }: any) => {
<form className='space-y-10 rounded-xl md:p-3'>
<div className='flex w-full justify-between space-x-3'>
<div className='flex w-full flex-col items-start space-y-1'>
<p className='text-sm'>Full Name</p>
<p className='text-sm'>{t('Full Name')}</p>
<Input value={name as string} onChange={(e) => setName(e.target.value)} className='dark:border-stone-400 dark:bg-stone-500' />
</div>
<div className='flex w-full flex-col items-start space-y-1'>
<p className='text-sm'>Email Address</p>
<p className='text-sm'>{t('Email Address')}</p>
<Input value={email as string} onChange={(e) => setEmail(e.target.value)} className='dark:border-stone-400 dark:bg-stone-500' />
</div>
</div>
<div className='flex w-full flex-col items-start space-y-1'>
<p className='text-sm'>Avatar</p>
<p className='text-sm'>{t('Avatar')}</p>
<Input value={image as string} onChange={(e) => setImage(e.target.value)} className='dark:border-stone-400 dark:bg-stone-500' />
</div>
<div className='flex justify-end'>
<Button variant='default' onClick={() => onSave()} disabled={isLoading}>
{isLoading ? <AiOutlineLoading3Quarters className='animate-spin' /> : 'Save'}
{isLoading ? <AiOutlineLoading3Quarters className='animate-spin' /> : t('Save')}
</Button>
</div>
</form>

<Separator />

<div className='space-y-3'>
<p className='text-lg font-medium'>Danger Zoom</p>
<p className='text-sm text-gray-400'>If you want to permanently remove your account from {siteConfig.title}. Please click the button below, please note, This could not be undone.</p>
<p className='text-lg font-medium'>{t('Danger Zoom')}</p>
<p className='text-sm text-gray-400'>
{t('If you want to permanently remove your account')}. {t('Please click the button below, please note, This could not be undone')}
</p>
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
<DialogTrigger asChild>
<button className='text-sm text-red-500'>Delete Account</button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Confirming Deletion</DialogTitle>
<DialogDescription>Please note: This could not be undone.</DialogDescription>
<DialogTitle>{t('Confirming Deletion')}</DialogTitle>
<DialogDescription>{t('Please note: This could not be undone')}</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant='destructive' onClick={onDelete}>
Confirm
{t('Confirm')}
</Button>
</DialogFooter>
</DialogContent>
Expand Down
Loading

1 comment on commit f924b3f

@vercel
Copy link

@vercel vercel bot commented on f924b3f May 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

chat-chat – ./

chat-chat-okisdev.vercel.app
chat-chat-git-main-okisdev.vercel.app
chatchat-main.vercel.app

Please sign in to comment.