i18n Key Structure for React Applications

How to structure i18n translation keys for React applications using react-i18next and next-intl. Covers namespace splitting, lazy loading, TypeScript type safety, and component-level translation patterns.

Framework Guide

Detailed Explanation

i18n Key Structure for React

React applications typically use react-i18next or next-intl for internationalization. Both libraries support dot-notation keys with nested JSON translation files, but their patterns for key organization differ.

react-i18next Key Structure

react-i18next uses namespaces that map to separate JSON files:

locales/
  en/
    common.json
    home.json
    dashboard.json
  ja/
    common.json
    home.json
    dashboard.json

In components:

import { useTranslation } from 'react-i18next';

function SubmitButton() {
  const { t } = useTranslation('common');
  return <button>{t('buttons.submit')}</button>;
}

function HomePage() {
  const { t } = useTranslation('home');
  return <h1>{t('hero.title')}</h1>;
}

next-intl Key Structure

next-intl uses a single messages object per locale with namespace-like top-level keys:

{
  "Common": {
    "buttons": {
      "submit": "Submit",
      "cancel": "Cancel"
    }
  },
  "HomePage": {
    "hero": {
      "title": "Welcome",
      "subtitle": "Get started today"
    }
  }
}

TypeScript Type Safety

Both libraries support typed keys. With react-i18next, declare the resource type:

// i18n.d.ts
import 'react-i18next';
import common from './locales/en/common.json';
import home from './locales/en/home.json';

declare module 'react-i18next' {
  interface CustomTypeOptions {
    resources: {
      common: typeof common;
      home: typeof home;
    };
  }
}

This gives you autocomplete and compile-time checking for all translation keys.

Component-Level Patterns

Pattern 1: Shared + Page Namespaces

common.json   -- buttons, labels, errors shared across pages
home.json     -- home page specific
settings.json -- settings page specific

Pattern 2: Feature-Based Namespaces

auth.json       -- login, signup, password reset
checkout.json   -- cart, payment, confirmation
profile.json    -- user profile, preferences

Pattern 3: Component Co-Location

Some teams co-locate translations with components:

components/
  Header/
    Header.tsx
    Header.i18n.json
  Footer/
    Footer.tsx
    Footer.i18n.json

Lazy Loading Namespaces

For large applications, load namespaces on demand:

// Only loads 'settings' namespace when the Settings page is rendered
const { t } = useTranslation('settings', { useSuspense: true });

This reduces initial bundle size by only loading the translations needed for the current page.

Use Case

React developers setting up i18n for the first time need to decide on a key structure that works with their chosen library. The patterns described here prevent common mistakes like loading all translations upfront (performance hit) or using a single flat file (maintenance nightmare). The i18n Key Generator produces keys that follow these React-specific patterns.

Try It — i18n Key Generator

Open full tool