BowlerKitBowlerKit
Features

Internationalization (i18n)

10/11/2026

Add and switch translations in the Expo template.

Current setup

The template uses i18next and react-i18next. services/i18n.ts registers the bundled locale files:

  • locales/en.json
  • locales/id.json

The device language is used during initialization, with English as the fallback. The preferences store then applies the persisted language after local storage hydration.

import { useTranslation } from 'react-i18next';

export function WelcomeTitle() {
  const { t } = useTranslation();
  return <Text>{t('welcome.title')}</Text>;
}

Changing language

Use usePreferencesStore().setLanguage(...) or the existing language settings screen. The setter persists the value locally and, in Account mode, schedules a debounced PUT /api/v1/app/preferences update. Guest mode never sends this request.

Add a locale

  1. Copy locales/en.json to a new JSON file such as locales/es.json.
  2. Add the resource to services/i18n.ts.
  3. Add the language to the settings picker and type any supported language list used by the UI.
  4. Keep the same key structure across all locale files.
  5. Test both the first render (device locale) and the post-hydration render (saved preference).

Translation guidance

  • Use semantic, nested keys such as auth.login.title.
  • Keep interpolation values separate from translated text.
  • Do not hardcode user-facing strings in new screens.
  • Add keys to every bundled locale or provide an intentional English fallback.

Relevant files

  • services/i18n.ts
  • locales/en.json and locales/id.json
  • store/preferences-store.ts
  • app/settings/general.tsx