diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 2ee8573..7c31d16 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -4,6 +4,7 @@ import "./globals.css"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import ReactQueryProvider from "@/providers/react-query"; import clsx from "clsx"; +import { DictionaryProvider } from "@/contexts/dictionary-provider"; const jamjuree = Bai_Jamjuree({ subsets: ["latin"], @@ -27,8 +28,10 @@ export default function RootLayout({ - {children} - + + {children} + + diff --git a/src/contexts/dictionary-provider.tsx b/src/contexts/dictionary-provider.tsx new file mode 100644 index 0000000..57455c5 --- /dev/null +++ b/src/contexts/dictionary-provider.tsx @@ -0,0 +1,91 @@ +"use client"; + +import { createContext, useContext, useEffect, useState } from "react"; +import type { Dictionary, Language } from "@/internationalization/dictionaries"; +import { getDictionary } from "@/internationalization/dictionaries"; +import { api } from "@/lib/api"; +import { useGetUserInfo } from "@/lib/queries/session"; + +export type DictionaryLanguage = Language; + +interface DictionaryContextData { + dictionary: Dictionary; + language: DictionaryLanguage; + setLanguage?: (language: DictionaryLanguage) => void; +} + +const DictionaryContext = createContext( + undefined, +); + +export async function PreferedLanguage(): Promise { + const response = await api.get("/auth/preferences/language"); + console.log(response); + if (!response) { + throw new Error("Failed to fetch preferred language"); + } + const { language } = response.data; + + return language as DictionaryLanguage; +} + +export function getBrowserLanguage(): DictionaryLanguage { + if (typeof navigator !== "undefined" && navigator.language) { + return navigator.language as DictionaryLanguage; + } + return "en-US"; +} + +export function DictionaryProvider({ + children, + language: propLanguage, +}: { + children: React.ReactNode; + language?: DictionaryLanguage; +}) { + const [language, setLanguage] = useState( + propLanguage || "en-US", + ); + + const user = useGetUserInfo(); + + useEffect(() => { + if (!propLanguage) { + (async () => { + try { + if (user) { + const preferredLanguage = await PreferedLanguage(); + setLanguage(preferredLanguage); + } else { + setLanguage(getBrowserLanguage()); + } + } catch { + setLanguage("en-US"); + } + })(); + } + }, [propLanguage, user]); + + const dictionary = getDictionary(language); + return ( + + {children} + + ); +} + +export function useDictionary() { + const context = useContext(DictionaryContext); + if (!context) { + throw new Error("useDictionary must be used within a DictionaryProvider"); + } + return context.dictionary; +} + +export function useLanguage() { + const context = useContext(DictionaryContext); + if (!context) { + throw new Error("useLanguage must be used within a DictionaryProvider"); + } + return context.language; +} diff --git a/src/internationalization/dictionaries.ts b/src/internationalization/dictionaries.ts new file mode 100644 index 0000000..83c10e8 --- /dev/null +++ b/src/internationalization/dictionaries.ts @@ -0,0 +1,17 @@ +import en from "./dictionaries/en.json"; +import pt from "./dictionaries/pt.json"; + +const dictionaries = { + "en-US": en, + "en-GB": en, + "en-CA": en, + "pt-PT": pt, + "pt-BR": pt, +}; + +export type Language = keyof typeof dictionaries; +export type Dictionary = (typeof dictionaries)[Language]; + +export const getDictionary = (lang: Language): Dictionary => { + return dictionaries[lang] || dictionaries["en-US"]; +}; diff --git a/src/internationalization/dictionaries/en.json b/src/internationalization/dictionaries/en.json new file mode 100644 index 0000000..f750bd1 --- /dev/null +++ b/src/internationalization/dictionaries/en.json @@ -0,0 +1,3 @@ +{ + "greeting": "Hello" +} diff --git a/src/internationalization/dictionaries/pt.json b/src/internationalization/dictionaries/pt.json new file mode 100644 index 0000000..1a6f72c --- /dev/null +++ b/src/internationalization/dictionaries/pt.json @@ -0,0 +1,3 @@ +{ + "greeting": "Olá" +}