Implement big text view and preliminary i18n
This commit is contained in:
73
packages/web/src/i18n/index.tsx
Normal file
73
packages/web/src/i18n/index.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
import { createContext, memo, useContext, useEffect, useMemo, useState } from "react"
|
||||
import texts from "./texts.yml"
|
||||
|
||||
type Keys = keyof typeof texts
|
||||
|
||||
const ALLOWED = new Set(["en", "fr"])
|
||||
const LOCALSTORAGE_KEY = "preferred-locale"
|
||||
|
||||
function getLocaleFromStorage() {
|
||||
try {
|
||||
const key = localStorage.getItem(LOCALSTORAGE_KEY)
|
||||
if (key && ALLOWED.has(key)) {
|
||||
return key
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function getNavigatorLocale() {
|
||||
if (typeof navigator !== "undefined") {
|
||||
for (const lang of navigator.languages) {
|
||||
if (ALLOWED.has(lang)) {
|
||||
return lang
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getEnvLocale() {
|
||||
return getLocaleFromStorage() ?? getNavigatorLocale() ?? "en"
|
||||
}
|
||||
|
||||
const LocaleContext = createContext<{
|
||||
locale: string
|
||||
setLocale(locale: string): void
|
||||
}>(undefined!)
|
||||
|
||||
export const useLocaleContext = () => useContext(LocaleContext)
|
||||
|
||||
export function useTranslate() {
|
||||
const { locale } = useContext(LocaleContext)
|
||||
const t = useMemo(
|
||||
() =>
|
||||
new Proxy(
|
||||
{},
|
||||
{
|
||||
get(_, p: string) {
|
||||
if (
|
||||
process.env.NODE_ENV === "development" &&
|
||||
!Object.prototype.hasOwnProperty.call(texts, p)
|
||||
) {
|
||||
throw new Error(`t.${p} does not exist.`)
|
||||
}
|
||||
return (texts as any)[p][locale]
|
||||
},
|
||||
}
|
||||
) as {
|
||||
[key in Keys]: string
|
||||
},
|
||||
[locale]
|
||||
)
|
||||
return t
|
||||
}
|
||||
|
||||
export const LocaleContextProvider = memo(({ children }) => {
|
||||
const [locale, setLocale] = useState(getEnvLocale)
|
||||
useEffect(() => {
|
||||
try {
|
||||
localStorage.setItem(LOCALSTORAGE_KEY, locale)
|
||||
} catch {}
|
||||
}, [locale])
|
||||
const value = useMemo(() => ({ locale, setLocale }), [locale])
|
||||
return <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>
|
||||
})
|
Reference in New Issue
Block a user