This site utilizes a simple custom hook to provide i18n support. The hook is called useI18n
and is located in hooks/useI18n.ts. The hook relies on a translation file provided by the top-level ancestor based on language code. Each transaltion file is a JSON with keys such as "audio.open_transcript_modal"
which correspond to the translation of that particular word or phrase. The hook itself relies on a LanguageContext
(see hooks/useLanguageContext.ts), which is a simple Context
that is used at the top level of each translated route:
// app/val/en/page.tsx
import ValHomeEn from './val-home-en';
import en from '@/i18n/en.json' assert { type: 'json' }; // translations file
export default async function ValPageEn() {
return <ValHomeEn translations={en} />;
}
// app/val/en/val-home-en.tsx
import ValHome from '@/components/val/home/val-home';
import { LanguageContext } from '@/hooks/useLanguageContext';
import { SupportedLanguages } from '@/types/i18n-types';
export default function ValHomeEn({ translations }: { translations: Record<string, string> }) {
return (
<LanguageContext.Provider value={{ language: SupportedLanguages.english, translations }}>
<ValHome />
</LanguageContext.Provider>
);
}
The LanguageContext
is then used by the useI18n
hook to provide the correct translations to the components. The hook is used as follows:
export default functgion SomeComponent() {
const { t } = useI18n();
return <div>{t('global.some_slug')}</div>;
}
In the translation files such as i18n/en.json
, slugs are arranged alphabetically and the keys are namespaced, e.g. global.normal
or val.hero.author_text
. Keys which have markdown values are suffixed with _md
to indicate that they should be parsed as markdown.