Settings

Supaplate comes with a settings feature that allows users to choose their preferred language as well as their preferred theme (light or dark).

In this section we will how they work and how to configure them.

Settings

How they work

Both the language and the theme preferences are stored in cookies.

In the loader function of the app/root.tsx file there is code that reads the cookies and gets the locale and theme values.

export async function loader({ request }: Route.LoaderArgs) {
  // ...
  const [{ getTheme }, locale] = await Promise.all([
    themeSessionResolver(request),
    i18next.getLocale(request),
  ])
  return {
    theme: getTheme(),
    locale,
  }
}

These two values are then put in the lang and className attributes of the <html> tag of the app/root.tsx file.

<html
  lang={data?.locale ?? 'en'}
  className={cn(theme ?? '', 'h-full')}
  dir={i18n.dir()}
>
  // ...
</html>

Locale Setting

The locale setting is powered by i18next.

i18next uses the lang attribute in the <html> tag to know which language to use.

Translation files

Translation files are stored in the ./app/locales directory.

The files are named after the language code.

β”œβ”€β”€ πŸ“„en.ts
β”œβ”€β”€ πŸ“„es.ts
└── πŸ“„ko.ts

Inside of each file you will put the translations for the strings you want to translate.

// en.ts
const en = {
  home: {
    title: 'Supaplate',
    subtitle: "It's time to build!",
  },
  ...
}
// es.ts
const es: Translation = {
  home: {
    title: 'Supaplate',
    subtitle: 'Es hora de construir!',
  },
  ...
}
const ko: Translation = {
  home: {
    title: "μŠˆνŒŒν”Œλ ˆμ΄νŠΈ",
    subtitle: "λΉŒλ“œν•˜λŠ” μ‹œκ°„μ΄μ•Ό!",
  },
  ...
};

Using the translations

To use the translations you can use the useTranslation hook.

import { useTranslation } from 'react-i18next'

import i18next from '~/core/lib/i18next.server'

export const meta: Route.MetaFunction = ({ data }) => {
  return [
    { title: data?.title },
    { name: 'description', content: data?.subtitle },
  ]
}

export async function loader({ request }: Route.LoaderArgs) {
  const t = await i18next.getFixedT(request)
  return {
    title: t('home.title'),
    subtitle: t('home.subtitle'),
  }
}

export default function Home() {
  const { t } = useTranslation()

  return <div>{t('home.title')}</div>
}

Type safety

To ensure type safety, you can use the Translation type exported from the ./app/locales/types.ts file.

export type Translation = {
  home: {
    title: string
    subtitle: string
  }
}

Whenever you want add a new translation, add it first in the Translation type, this way you will get an error if you forget to add it to the translation files.

Theme Setting

To add styles for dark mode you can use Tailwind CSS's dark modifier.

<div className="dark:bg-black"> ... </div>

You can read more about Tailwind CSS's dark mode here.

Modifying the settings

There are two components in the /core/components/ directory called lang-switcher.tsx and theme-switcher.tsx.

You can put them wherever you want in your application, by default they are displayed in the navigation bar.

lang-switcher.tsx is used to change the language of the application by sending a POST request to the /api/settings/locale route with a new locale in the search params.

And theme-switcher.tsx is used to change the theme of the application by sending a POST request to the /api/settings/theme route with a new theme in the search params.

Disabling the settings

If you want to disable a settings feature you can just hide the lang-switcher.tsx or theme-switcher.tsx component and the route that is used to change the settings.