Skip to content

Commit

Permalink
feat: add translations
Browse files Browse the repository at this point in the history
  • Loading branch information
rharkor committed Aug 10, 2023
1 parent 5af2d73 commit c965470
Show file tree
Hide file tree
Showing 26 changed files with 406 additions and 77 deletions.
6 changes: 6 additions & 0 deletions i18n-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const i18n = {
defaultLocale: "en",
locales: ["en", "fr"],
} as const

export type Locale = (typeof i18n)["locales"][number]
18 changes: 17 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
"dependencies": {
"@auth/prisma-adapter": "^1.0.1",
"@formatjs/intl-localematcher": "^0.4.0",
"@hookform/resolvers": "^3.2.0",
"@next-auth/prisma-adapter": "^1.0.7",
"@next/bundle-analyzer": "^13.4.13",
Expand Down Expand Up @@ -68,6 +69,7 @@
"lodash": "^4.17.21",
"lodash.isequal": "^4.5.0",
"lucide-react": "^0.263.0",
"negotiator": "^0.6.3",
"next": "^13.4.13",
"next-auth": "^4.22.5",
"next-compose-plugins": "^2.2.1",
Expand Down Expand Up @@ -102,6 +104,7 @@
"@types/bcryptjs": "^2.4.2",
"@types/crypto-js": "^4.1.1",
"@types/lodash.isequal": "^4.5.6",
"@types/negotiator": "^0.6.1",
"@types/node": "^20.4.9",
"@types/react": "^18.2.19",
"@types/react-dom": "^18.2.7",
Expand Down
19 changes: 0 additions & 19 deletions src/app/(protected)/profile/see-details-toggle.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,37 @@ import Link from "next/link"
import { ThemeSwitch } from "@/components/theme/theme-switch"
import { buttonVariants } from "@/components/ui/button"
import { authRoutes } from "@/lib/auth/constants"
import { getDictionary } from "@/lib/langs"
import { Locale } from "i18n-config"

export default async function Home({
params: { lang },
}: {
params: {
lang: Locale
}
}) {
const dictionary = await getDictionary(lang)

export default function Home() {
return (
<>
<main className="container flex flex-1 flex-col items-center justify-center gap-3">
<h1 className="text-4xl font-bold">Hello World</h1>
<h1 className="text-4xl font-bold">{dictionary.homePage.title}</h1>
<nav className="flex flex-col items-center justify-center">
<ul className="flex flex-row items-center justify-center gap-2">
<li>
<Link href={authRoutes.signIn[0]} className={buttonVariants({ variant: "ghost" })}>
Sign In
{dictionary.signIn}
</Link>
</li>
<li>
<Link href={authRoutes.signUp[0]} className={buttonVariants({ variant: "ghost" })}>
Sign Up
{dictionary.signUp}
</Link>
</li>
<li>
<Link href="/profile" className={buttonVariants({ variant: "ghost" })}>
Profile
{dictionary.profile}
</Link>
</li>
</ul>
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,38 @@ import { getServerSession } from "next-auth"
import SignoutButton from "@/components/auth/sign-out-button"
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { nextAuthOptions } from "@/lib/auth"
import { getDictionary } from "@/lib/langs"
import { Locale } from "i18n-config"
import SeeDetailsToggle from "./see-details-toggle"

export default async function Profile() {
export default async function Profile({
params: { lang },
}: {
params: {
lang: Locale
}
}) {
const dictionary = await getDictionary(lang)
const session = await getServerSession(nextAuthOptions)

return (
<main className="container flex flex-1 flex-col items-center justify-center p-6">
<div>
<Card className="relative z-10 m-auto max-w-full">
<CardHeader>
<CardTitle>Profile</CardTitle>
<CardTitle>{dictionary.profile}</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground">The following data are retrieve server-side.</p>
<p className="text-muted-foreground">{dictionary.profilePage.serverSideData}</p>
<pre className="mt-2 overflow-auto rounded bg-muted p-2">{JSON.stringify(session, null, 2)}</pre>
</CardContent>
<CardFooter>
<div className="ml-auto">
<SignoutButton />
<SignoutButton>{dictionary.signOut}</SignoutButton>
</div>
</CardFooter>
</Card>
<SeeDetailsToggle />
<SeeDetailsToggle dictionary={dictionary} />
</div>
</main>
)
Expand Down
32 changes: 32 additions & 0 deletions src/app/[lang]/(protected)/profile/see-details-toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import ProfileDetails from "@/components/profile/profile-details"
import UserActiveSessions from "@/components/profile/sessions/user-active-sessions"
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { TDictionary } from "@/lib/langs"

export default function SeeDetailsToggle({ dictionary }: { dictionary: TDictionary }) {
return (
<div className="-mt-4 rounded-b-lg border bg-card p-2 pt-6 text-muted-foreground shadow-sm">
<Accordion type="single" collapsible>
<AccordionItem value="session-toggle" className="border-b-0">
<AccordionTrigger className="flex-none gap-1 p-0">
{dictionary.profilePage.profileDetails.toggle}
</AccordionTrigger>
<AccordionContent>
<UserActiveSessions
dictionary={{
...dictionary.profilePage.profileDetails,
sessionTable: {
areYouAbsolutelySure: dictionary.areYouAbsolutelySure,
cancel: dictionary.cancel,
continue: dictionary.continue,
deleteLoggedDevice: dictionary.profilePage.profileDetails.deleteLoggedDevice,
},
}}
/>
<ProfileDetails dictionary={dictionary.profilePage.profileDetails} />
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
)
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ import GithubSignIn from "@/components/auth/github-sign-in"
import { LoginUserAuthForm } from "@/components/auth/login-user-auth-form"
import { buttonVariants } from "@/components/ui/button"
import { authRoutes } from "@/lib/auth/constants"
import { getDictionary } from "@/lib/langs"
import { cn } from "@/lib/utils"
import { Locale } from "i18n-config"

export default async function SignInPage({
searchParams,
params: { lang },
}: {
searchParams: { [key: string]: string | string[] | undefined }
params: {
lang: Locale
}
}) {
const dictionary = await getDictionary(lang)

const providers = await getProviders()

return (
Expand All @@ -27,8 +35,8 @@ export default async function SignInPage({
<div className="lg:p-8">
<div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
<div className="flex flex-col space-y-2 text-center">
<h1 className="text-2xl font-semibold tracking-tight">Login to your account</h1>
<p className="text-sm text-muted-foreground">Enter your details below.</p>
<h1 className="text-2xl font-semibold tracking-tight">{dictionary.signInPage.loginToYourAccount}</h1>
<p className="text-sm text-muted-foreground">{dictionary.signInPage.enterDetails}</p>
</div>
<div className="grid gap-6">
<LoginUserAuthForm searchParams={searchParams} />
Expand All @@ -37,19 +45,19 @@ export default async function SignInPage({
<span className="w-full border-t" />
</div>
<div className="relative flex justify-center text-xs uppercase">
<span className="bg-background px-2 text-muted-foreground">Or continue with</span>
<span className="bg-background px-2 text-muted-foreground">{dictionary.auth.orContinueWith}</span>
</div>
</div>
{providers?.github && <GithubSignIn provider={providers.github} />}
</div>
<p className="px-8 text-center text-sm text-muted-foreground">
By clicking continue, you agree to our{" "}
{dictionary.auth.clickingAggreement}{" "}
<Link href="/terms" className="underline underline-offset-4 hover:text-primary">
Terms of Service
</Link>{" "}
and{" "}
{dictionary.auth.termsOfService}
</Link>
{dictionary.and}
<Link href="/privacy" className="underline underline-offset-4 hover:text-primary">
Privacy Policy
{dictionary.auth.privacyPolicy}
</Link>
.
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ import { redirect } from "next/navigation"
import { RegisterUserAuthForm } from "@/components/auth/register-user-auth-form"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { authRoutes } from "@/lib/auth/constants"
import { getDictionary } from "@/lib/langs"
import { Locale } from "i18n-config"

export default function SignupByCredentials({
export default async function SignupByCredentials({
searchParams,
params: { lang },
}: {
searchParams: { [key: string]: string | string[] | undefined }
params: {
lang: Locale
}
}) {
const dictionary = await getDictionary(lang)

//? If there is no email in the search params, redirect to the sign-up page
if (!searchParams?.email) {
redirect(authRoutes.signUp[0])
Expand All @@ -17,7 +25,7 @@ export default function SignupByCredentials({
<main className="container relative flex flex-1 flex-col items-center justify-center lg:max-w-none lg:grid-cols-2 lg:px-0">
<Card className="w-[500px]">
<CardHeader>
<CardTitle>Create an account</CardTitle>
<CardTitle>{dictionary.signUpPage.createAnAccount}</CardTitle>
</CardHeader>
<CardContent>
<RegisterUserAuthForm className="gap-3" searchParams={searchParams} />
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ import GithubSignIn from "@/components/auth/github-sign-in"
import { RegisterUserAuthForm } from "@/components/auth/register-user-auth-form"
import { buttonVariants } from "@/components/ui/button"
import { authRoutes } from "@/lib/auth/constants"
import { getDictionary } from "@/lib/langs"
import { cn } from "@/lib/utils"
import { Locale } from "i18n-config"

export default async function SignUpPage({
searchParams,
params: { lang },
}: {
searchParams: { [key: string]: string | string[] | undefined }
params: {
lang: Locale
}
}) {
const dictionary = await getDictionary(lang)
const providers = await getProviders()

return (
Expand All @@ -19,16 +26,16 @@ export default async function SignUpPage({
href={authRoutes.signIn[0]}
className={cn(buttonVariants({ variant: "ghost" }), "absolute right-4 top-4 md:right-8 md:top-8")}
>
Login
{dictionary.login}
</Link>
<div className="relative hidden h-full flex-col bg-muted p-10 text-white dark:border-r lg:flex ">
<div className="absolute inset-0 bg-muted" />
</div>
<div className="lg:p-8">
<div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
<div className="flex flex-col space-y-2 text-center">
<h1 className="text-2xl font-semibold tracking-tight">Create an account</h1>
<p className="text-sm text-muted-foreground">Enter your email below to create your account</p>
<h1 className="text-2xl font-semibold tracking-tight">{dictionary.signUpPage.createAnAccount}</h1>
<p className="text-sm text-muted-foreground">{dictionary.signUpPage.enterEmail}</p>
</div>
<div className="grid gap-6">
<RegisterUserAuthForm isMinimized searchParams={searchParams} />
Expand All @@ -37,19 +44,19 @@ export default async function SignUpPage({
<span className="w-full border-t" />
</div>
<div className="relative flex justify-center text-xs uppercase">
<span className="bg-background px-2 text-muted-foreground">Or continue with</span>
<span className="bg-background px-2 text-muted-foreground">{dictionary.auth.orContinueWith}</span>
</div>
</div>
{providers?.github && <GithubSignIn provider={providers.github} />}
</div>
<p className="px-8 text-center text-sm text-muted-foreground">
By clicking continue, you agree to our{" "}
{dictionary.auth.clickingAggreement}{" "}
<Link href="/terms" className="underline underline-offset-4 hover:text-primary">
Terms of Service
</Link>{" "}
and{" "}
{dictionary.auth.termsOfService}
</Link>
{dictionary.and}
<Link href="/privacy" className="underline underline-offset-4 hover:text-primary">
Privacy Policy
{dictionary.auth.privacyPolicy}
</Link>
.
</p>
Expand Down
Loading

0 comments on commit c965470

Please sign in to comment.