Languages
The web app ships in seventeen languages: English, Arabic, Chinese, French, German, Hindi, Hungarian, Italian, Korean, Polish, Portuguese (Portugal and Brazil), Russian, Spanish, Thai, Turkish and Ukrainian. Exercise instructions from the catalog are available in ten of them; the others show English instructions.
Arabic is written right to left: the page gets dir="rtl", layouts use logical utilities (ms-, ps-, start-, text-start) so they mirror, and back and forward arrows flip. A regional variant wins over its base language when the browser asks for it (pt-BR → Brazilian Portuguese, pt-PT → Portuguese). Plural forms follow Intl.PluralRules; a language may spell the number out in its one and two forms (Arabic does).
English strings live in apps/web/src/i18n/en.ts and define the key set. Each other language is a file in apps/web/src/i18n/locales/ typed against it, so a missing key fails type checking. Plurals use Intl.PluralRules, which covers the Polish and Russian forms. Dates, numbers and units format through Intl in the user’s locale.
The language follows the browser until the user picks one in Settings; the choice is saved to their profile, so it follows them across devices.
To add a language, copy en.ts to locales/<code>.ts, translate the values, register it in apps/web/src/i18n/index.ts, and run pnpm --filter @gymgym/web test.