Better I18NBetter I18N
Vite

TypeScript

Type-safe translation keys and autocomplete for Vite + React

Enable autocomplete and type safety for your translation keys in Vite + React applications.

Setup

Step 1: Create Type Declaration

Create a type declaration file that references your translation messages:

src/types/i18n.d.ts
import messages from '../locales/en.json'

type Messages = typeof messages 

declare global { 
  interface IntlMessages extends Messages {} 
} 

The IntlMessages interface is used by use-intl to provide type safety for translation keys.

Step 2: Add Local Translation File

For TypeScript to infer types, you need a local copy of your translations:

src/locales/en.json
{
  "home": {
    "title": "Welcome to our app",
    "description": "Get started by editing src/App.tsx"
  },
  "greeting": {
    "hello": "Hello, {name}!"
  }
}

This file is only for type inference. At runtime, translations are still fetched from the Better i18n CDN.

Usage

Once configured, you'll get autocomplete for translation keys:

import { useTranslations } from '@better-i18n/use-intl'

export function HomePage() {
  const t = useTranslations('home')

  return (
    <div>
      {/* ✅ TypeScript knows 'title' exists */}
      <h1>{t('title')}</h1>

      {/* ❌ TypeScript error: 'invalid' doesn't exist */}
      <p>{t('invalid')}</p>
    </div>
  )
}

Namespaced Types

For namespaced translations, your type file should reflect the structure:

src/types/i18n.d.ts
import home from '../locales/en/home.json'
import common from '../locales/en/common.json'

type Messages = {
  home: typeof home
  common: typeof common
}

declare global {
  interface IntlMessages extends Messages {}
}

Syncing Types

Manual Sync

Download your translations from the Better i18n dashboard or CDN:

curl -o src/locales/en.json https://cdn.better-i18n.com/your-org/your-project/en.json

Use the Better i18n CLI to keep types in sync:

# Install CLI
npm install -D @better-i18n/cli

# Pull translations
npx better-i18n pull --locale en --output src/locales

Add to your package.json scripts:

package.json
{
  "scripts": {
    "i18n:pull": "better-i18n pull --locale en --output src/locales"
  }
}

Type Checking in CI

Add type checking to your CI pipeline to catch missing translations:

.github/workflows/ci.yml
- name: Pull translations
  run: npm run i18n:pull

- name: Type check
  run: npx tsc --noEmit

Next Steps

On this page