Skip to content

Instantly share code, notes, and snippets.

@jhannes
Created June 24, 2021 20:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhannes/c0746f32f19d53735a68f558c9f4d74c to your computer and use it in GitHub Desktop.
Save jhannes/c0746f32f19d53735a68f558c9f4d74c to your computer and use it in GitHub Desktop.
TypeScript localization
import React, { useContext, useState } from "react";
import { BrowserRouter, Link } from "react-router-dom";
import { Route, Switch } from "react-router";
import { format, formatDistance, formatRelative } from "date-fns";
import nb from "date-fns/locale/nb";
import enUS from "date-fns/locale/en-US";
type AppLocale = "en" | "nb";
interface ApplicationTexts extends Record<AppLocale, string> {
hello: string;
home: string;
pickLanguage: string;
}
const english: ApplicationTexts = {
en: "English",
hello: "Hello",
home: "Home",
nb: "Norwegian",
pickLanguage: "Pick language",
};
const norwegian: ApplicationTexts = {
en: "Engelsk",
hello: "Hei",
home: "Forside",
nb: "Norsk",
pickLanguage: "Velg språk",
};
const LanguageContext = React.createContext<{
locale: AppLocale;
texts: ApplicationTexts;
setLocale(value: AppLocale): void;
}>({
locale: "nb",
texts: norwegian,
// eslint-disable-next-line @typescript-eslint/no-empty-function
setLocale: () => {},
});
const textLanguages: Record<AppLocale, ApplicationTexts> = {
en: english,
nb: norwegian,
};
const dateLocales: Record<AppLocale, Locale> = {
en: enUS,
nb: nb,
};
function RelativeTime({ date }: { date: Date }) {
const { locale } = useContext(LanguageContext);
return (
<div>
{formatDistance(date, new Date(), {
addSuffix: true,
locale: dateLocales[locale],
})}
</div>
);
}
function Application() {
const { texts, setLocale } = useContext(LanguageContext);
return (
<BrowserRouter>
<header>
<Link to={"/"}>{texts.home}</Link>
<Link to={"/language"}>{texts.pickLanguage}</Link>
</header>
<Switch>
<Route path={"/language"}>
<div>
<h1>{texts.pickLanguage}</h1>
<div>
<button onClick={() => setLocale("en")}>{texts.en}</button>
<button onClick={() => setLocale("nb")}>{texts.nb}</button>
</div>
</div>
</Route>
<Route>
<div>{texts.hello}</div>
</Route>
</Switch>
<footer>
<RelativeTime date={new Date(2021, 1, 1)} />
</footer>
</BrowserRouter>
);
}
export function LocalizationDemo() {
const [language, setLanguage] = useState<AppLocale>("en");
return (
<LanguageContext.Provider
value={{
texts: textLanguages[language],
locale: language,
setLocale: setLanguage,
}}
>
<Application />
</LanguageContext.Provider>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment