Implement big text view and preliminary i18n

This commit is contained in:
aet
2021-11-06 21:49:54 -04:00
parent 92e0fddbfc
commit 7dcb2fc7a5
22 changed files with 624 additions and 263 deletions

View 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>
})