Files
cunningham/packages/react/src/components/Provider/index.tsx
Nathan Vasse d4a574c30f 🔧(react) fix types file broken imports
Generated types for the react package were broken because they were
still using absolute imports which cannot work in standalone .d.ts
files because they cannot rely on the local baseUrl compiler option.
Thus, we introduced an alias that we are able to reliably replace
during type generation.
2023-05-04 16:53:29 +02:00

93 lines
2.3 KiB
TypeScript

import React, {
createContext,
PropsWithChildren,
useContext,
useMemo,
} from "react";
import * as enUS from ":/locales/en-US.json";
import * as frFR from ":/locales/fr-FR.json";
import { PartialNested } from ":/types";
import { Locales } from ":/components/Provider/Locales";
type TranslationSet = PartialNested<typeof enUS>;
const CunninghamContext = createContext<
| undefined
| {
t: (key: string, vars?: Record<string, string | number>) => string;
}
>(undefined);
export const useCunningham = () => {
const context = useContext(CunninghamContext);
if (context === undefined) {
throw new Error("useCunningham must be used within a CunninghamProvider.");
}
return context;
};
interface Props extends PropsWithChildren {
customLocales?: Record<string, TranslationSet>;
currentLocale?: string;
}
export const DEFAULT_LOCALE = Locales.enUS;
export const SUPPORTED_LOCALES = Object.values(Locales);
const findTranslation = (
key: string,
locale: TranslationSet
): string | undefined => {
const [namespace, ...keys] = key.split(".");
return keys.reduce((acc, subKey) => acc[subKey], (locale as any)[namespace]);
};
export const CunninghamProvider = ({
currentLocale = DEFAULT_LOCALE,
customLocales,
children,
}: Props) => {
const locales: Record<string, TranslationSet> = useMemo(
() => ({
[DEFAULT_LOCALE]: enUS,
"fr-FR": frFR,
...customLocales,
}),
[customLocales]
);
const locale = useMemo(() => {
if (!locales[currentLocale]) {
return locales[DEFAULT_LOCALE];
}
return locales[currentLocale];
}, [currentLocale, locales]);
const context = useMemo(
() => ({
t: (key: string, vars?: Record<string, string | number>) => {
let message: string =
findTranslation(key, locale) ??
findTranslation(key, locales[DEFAULT_LOCALE]) ??
key;
// Replace vars in message from vars in form of {varName}.
if (vars) {
Object.keys(vars).forEach((varName) => {
message = message?.replace(`{${varName}}`, "" + vars[varName]);
});
}
return message;
},
}),
[currentLocale, locales]
);
return (
<CunninghamContext.Provider value={context}>
{children}
</CunninghamContext.Provider>
);
};