Dictionaries

How to use traditional dictionary-based translation patterns

Dictionaries provide a traditional approach to organizing translations in nested objects with key-value pairs. While <T> components are the recommended approach, dictionaries can be useful for migration from other i18n libraries or when you prefer centralized translation storage.

Recommendation: Use <T> components for new projects. Dictionaries are supported primarily for migration and compatibility with existing translation workflows.

Dictionary vs Component Translation

Dictionary Pattern

// dictionary.ts
export default {
  greetings: {
    hello: 'Hello, world!',
    welcome: 'Welcome, {name}!'
  }
};

// Component usage
function MyComponent() {
  const d = useTranslations();
  return <div>{d('greetings.hello')}</div>;
}

Component Pattern

// Direct component usage - recommended
function MyComponent() {
  return <T><div>Hello, world!</div></T>;
}

Trade-offs

Dictionary Advantages

  • Centralized storage - All translations in one place
  • Industry standard - Familiar pattern from other i18n libraries
  • Migration friendly - Easy to port existing translations

Dictionary Disadvantages

  • Complexity - More setup and configuration required
  • Maintainability - Content separated from usage makes updates harder
  • Debuggability - Harder to trace translations back to components
  • Readability - Keys don't show actual content

Quick Start

Step 1: Create Dictionary

Create a dictionary file in your project root or src directory:

dictionary.ts
const dictionary = {
  greetings: {
    hello: 'Hello, world!',
    welcome: 'Welcome to our app!'
  },
  navigation: {
    home: 'Home',
    about: 'About',
    contact: 'Contact'
  }
};

export default dictionary;

Or use JSON format:

dictionary.json
{
  "greetings": {
    "hello": "Hello, world!",
    "welcome": "Welcome to our app!"
  },
  "navigation": {
    "home": "Home", 
    "about": "About",
    "contact": "Contact"
  }
}

Then you pass it to your <GTProvider> component:

index.js
import dictionary from "./dictionary.js";
import config from "./gt.config.json";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <GTProvider {...config} dictionary={dictionary}>
      <App />
    </GTProvider>
  </StrictMode>
);

Step 2: Use in Components

The useTranslations hook lets you access dictionary entries:

import { useTranslations } from 'gt-react';

function MyComponent() {
  const d = useTranslations();
  
  return (
    <div>
      <h1>{d('greetings.hello')}</h1>
      <p>{d('greetings.welcome')}</p>
    </div>
  );
}

Using Variables

Add variables to dictionary entries using {variable} syntax:

dictionary.ts
const dictionary = {
  user: {
    greeting: 'Hello, {name}!',
    itemCount: 'You have {count} items',
    orderTotal: 'Total: ${amount}'
  }
};
function UserDashboard() {
  const d = useTranslations();
  
  return (
    <div>
      <h1>{d('user.greeting', { name: 'Alice' })}</h1>
      <p>{d('user.itemCount', { count: 5 })}</p>
      <p>{d('user.orderTotal', { amount: 99.99 })}</p>
    </div>
  );
}

Using Prefixes

Scope dictionary access to specific sections using prefixes:

dictionary.ts
const dictionary = {
  dashboard: {
    header: {
      welcome: 'Welcome back!',
      lastLogin: 'Last login: {date}'
    },
    stats: {
      totalUsers: 'Total Users: {count}',
      activeUsers: 'Active Users: {count}'
    }
  }
};
function DashboardHeader() {
  // Prefix limits access to 'dashboard.header'
  const d = useTranslations('dashboard.header');
  
  return (
    <header>
      <h1>{d('welcome')}</h1> {/* -> dashboard.header.welcome */}
      <p>{d('lastLogin', { date: 'Today' })}</p> {/* -> dashboard.header.lastLogin */}
    </header>
  );
}

function DashboardStats() {
  // Different prefix for stats section
  const d = useTranslations('dashboard.stats');
  
  return (
    <div>
      <p>{d('totalUsers', { count: 1000 })}</p> {/* -> dashboard.stats.totalUsers */}
      <p>{d('activeUsers', { count: 150 })}</p> {/* -> dashboard.stats.activeUsers */}
    </div>
  );
}

Multiple Language Support

Most users should use loadTranslations to automatically generate translations from your base dictionary:

dictionary.ts
const dictionary = {
  common: {
    save: 'Save',
    cancel: 'Cancel',
    delete: 'Delete'
  },
  forms: {
    required: 'This field is required',
    email: 'Please enter a valid email'
  }
};

export default dictionary;

Then create a loadTranslations function to load generated translation files:

src/loadTranslations.ts
export default async function loadTranslations(locale: string) {
  const translations = await import(`./_gt/${locale}.json`);
  return translations.default;
}

Pass it to your <GTProvider>:

src/index.tsx
import loadTranslations from './loadTranslations';
import dictionary from './dictionary';

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <GTProvider 
      {...config} 
      dictionary={dictionary}
      loadTranslations={loadTranslations}
    >
      <App />
    </GTProvider>
  </StrictMode>
);

GT automatically generates translations for other languages based on your base dictionary. Run npx gtx-cli translate to generate translations for all configured languages.

Manual Translation Files (Migration)

For migration from other i18n libraries or manual translation management, use loadDictionary:

src/loadDictionary.ts
export default async function loadDictionary(locale: string) {
  const translations = await import(`../public/locales/${locale}.json`);
  return translations.default;
}

This loads JSON translation files from your public/locales/ directory:

es.json
fr.json
de.json

Choose the right approach: Use loadTranslations for new projects with automatic translation generation, or loadDictionary when migrating existing translation files.

Production Setup

Build Process

Add translation to your build pipeline:

package.json
{
  "scripts": {
    "build": "npx gtx-cli translate && <...YOUR_BUILD_COMMAND...>"
  }
}

Development vs Production Behavior

  • Development: Dictionary entries translated on-demand with dev API key
  • Production: All dictionary translations pre-built during build step

Combining with Components

Dictionaries and <T> components can work together:

function MixedApproach() {
  const d = useTranslations();
  
  return (
    <div>
      {/* Dictionary for simple strings */}
      <h1>{d('page.title')}</h1>
      
      {/* T component for complex JSX */}
      <T>
        <p>This is a <strong>complex message</strong> with <a href="/link">links</a>.</p>
      </T>
      
      {/* Dictionary for form labels */}
      <label>{d('forms.email')}</label>
    </div>
  );
}

Next Steps

How is this guide?

Dictionaries