gettext .po Files in Vite — Without a Translation SaaS

Internationalization (i18n) is one of the quickest ways for a web project's complexity to spiral out of control. Most React tutorials advocate either storing fragmented JSON files across component directories or signing up for paid translation management SaaS platforms like Crowdin or Lokalise. For a solo engineer or small development team supporting multiple languages, these approaches introduce substantial overhead, API dependencies, and subscription costs.

For this portfolio, which supports four languages (English, Spanish, German, and Italian), I chose a time-tested, open standard: GNU gettext `.po` catalogs. Paired with a lightweight custom Vite plugin and lazy code splitting, this architecture delivers offline-first, bundle-time compiled localization with zero runtime overhead.

Standard JSON localization formats require developers to invent arbitrary nested keys (such as `home.hero.buttons.learnMore`), which quickly decouple code from actual text. When reading JSX, seeing `{t('home.hero.buttons.learnMore')}` forces developers to constantly jump between source code and locale files to verify what text is actually displayed.

← Rafael González Albes