Skip to main content
ProComponents provides comprehensive internationalization (i18n) support out of the box, with built-in translations for 35+ languages and easy customization options.

Overview

The i18n system in ProComponents:
  • Supports 35+ languages out of the box
  • Automatically syncs with Ant Design locale settings
  • Provides a simple API for accessing translations
  • Allows custom translation overrides
  • Uses a fallback mechanism (defaults to Chinese)
ProComponents automatically detects and uses the locale from Ant Design’s ConfigProvider, so in most cases, you don’t need to configure it separately.

Built-in Locales

ProComponents includes translations for:
  • English: en_US, en_GB
  • Spanish: es_ES
  • French: fr_FR
  • German: de_DE
  • Italian: it_IT
  • Portuguese: pt_BR
  • Dutch: nl_NL
  • Polish: pl_PL
  • Romanian: ro_RO
  • Swedish: sv_SE
  • Czech: cs_CZ
  • Slovak: sk_SK
  • Catalan: ca_ES

Basic Usage

Automatic Locale Detection

The simplest way to use i18n is to let ProComponents detect the locale from Ant Design:
import { ConfigProvider } from 'antd';
import { ProLayout } from '@ant-design/pro-components';
import enUS from 'antd/locale/en_US';
import zhCN from 'antd/locale/zh_CN';

function App() {
  return (
    <ConfigProvider locale={enUS}>
      {/* ProComponents automatically uses English translations */}
      <ProLayout />
    </ConfigProvider>
  );
}

Explicit Locale Setting

You can explicitly set the ProComponents locale:
import { ProConfigProvider, enUSIntl } from '@ant-design/pro-components';

function App() {
  return (
    <ProConfigProvider intl={enUSIntl}>
      <YourApp />
    </ProConfigProvider>
  );
}

Using the useIntl Hook

Access translations in your components with the useIntl hook:
import { useIntl } from '@ant-design/pro-components';

function MyComponent() {
  const intl = useIntl();

  return (
    <div>
      <button>
        {intl.getMessage('tableForm.search', 'Search')}
      </button>
      <button>
        {intl.getMessage('tableForm.reset', 'Reset')}
      </button>
    </div>
  );
}

getMessage API

The getMessage function accepts two parameters:
getMessage(
  id: string,           // Translation key path
  defaultMessage: string // Fallback text if translation not found
): string
The defaultMessage is required and will be used if:
  1. The translation key doesn’t exist
  2. The current locale doesn’t have a translation for that key
  3. The locale falls back to Chinese but the key still isn’t found

Translation Keys

Here are the available translation keys in ProComponents:

Common Keys

// Money symbol
intl.getMessage('moneySymbol', '$')  // '$' or '¥' depending on locale

// Table actions
intl.getMessage('deleteThisLine', 'Delete this line')
intl.getMessage('copyThisLine', 'Copy this line')

Form Keys

// src/provider/locale/en_US.tsx
intl.getMessage('form.lightFilter.more', 'More')
intl.getMessage('form.lightFilter.clear', 'Clear')
intl.getMessage('form.lightFilter.confirm', 'Confirm')
intl.getMessage('form.lightFilter.itemUnit', 'Items')

Table Keys

intl.getMessage('alert.clear', 'Clear')
intl.getMessage('alert.selected', 'Selected')
intl.getMessage('alert.item', 'Item')

Editable Table Keys

intl.getMessage('editableTable.onlyOneLineEditor', 'Only one line can be edited')
intl.getMessage('editableTable.onlyAddOneLine', 'Only one line can be added')
intl.getMessage('editableTable.action.save', 'Save')
intl.getMessage('editableTable.action.cancel', 'Cancel')
intl.getMessage('editableTable.action.delete', 'Delete')
intl.getMessage('editableTable.action.add', 'add a row of data')

Layout Keys (SettingDrawer)

ProLayout includes a SettingDrawer with extensive i18n support:
// From src/layout/locales/en-US/settingDrawer.ts
intl.getMessage('app.setting.pagestyle', 'Page style setting')
intl.getMessage('app.setting.pagestyle.dark', 'Dark Menu style')
intl.getMessage('app.setting.pagestyle.light', 'Light Menu style')
intl.getMessage('app.setting.themecolor', 'Theme Color')

Locale File Structure

Here’s the complete structure of a locale file:
// src/provider/locale/en_US.tsx
export default {
  moneySymbol: '$',
  deleteThisLine: 'Delete this line',
  copyThisLine: 'Copy this line',
  form: {
    lightFilter: {
      more: 'More',
      clear: 'Clear',
      confirm: 'Confirm',
      itemUnit: 'Items',
    },
  },
  tableForm: {
    search: 'Query',
    reset: 'Reset',
    submit: 'Submit',
    collapsed: 'Expand',
    expand: 'Collapse',
    inputPlaceholder: 'Please enter',
    selectPlaceholder: 'Please select',
  },
  alert: {
    clear: 'Clear',
    selected: 'Selected',
    item: 'Item',
  },
  pagination: {
    total: {
      range: ' ',
      total: 'of',
      item: 'items',
    },
  },
  // ... more keys
};

Custom Translations

Create custom locale objects for your application:
import { createIntl } from '@ant-design/pro-components';

const customLocale = {
  moneySymbol: '€',
  tableForm: {
    search: 'Rechercher',
    reset: 'Réinitialiser',
  },
  // Add your custom keys
  myApp: {
    welcome: 'Bienvenue',
    logout: 'Se déconnecter',
  },
};

const frFRCustom = createIntl('fr_FR', customLocale);

export default frFRCustom;

Locale Mapping

ProComponents automatically maps Ant Design locale keys to ProComponents locales:
// From src/provider/intl.ts
export const findIntlKeyByAntdLocaleKey = (localeKey?: string) => {
  const localeName = (localeKey || 'zh-CN').toLocaleLowerCase();
  return intlMapKeys.find((intlKey) => {
    const LowerCaseKey = intlKey.toLocaleLowerCase();
    return LowerCaseKey.includes(localeName);
  });
};
This means zh_CN, zh-CN, and zhCN all map to the Chinese locale.

Fallback Mechanism

The i18n system uses a graceful fallback:
  1. Try to get translation from current locale
  2. If not found, try Chinese (zh-CN) locale
  3. If still not found, use the provided default message
getMessage: (id: string, defaultMessage: string) => {
  const msg = get(localeMap, id.replace(/\[(\d+)\]/g, '.$1').split('.')) || '';
  if (msg) return msg;
  
  // Fallback to Chinese for non-Chinese locales
  const localKey = locale.replace('_', '-');
  if (localKey === 'zh-CN') {
    return defaultMessage;
  }
  
  const intl = intlMap['zh-CN'];
  return intl ? intl.getMessage(id, defaultMessage) : defaultMessage;
}
Always provide a meaningful defaultMessage. It’s not just a fallback—it also serves as documentation for what the translation should say.

Dynamic Locale Switching

Build a complete locale switcher:
import { ProConfigProvider, enUSIntl, zhCNIntl, jaJPIntl, frFRIntl } from '@ant-design/pro-components';
import { ConfigProvider } from 'antd';
import enUS from 'antd/locale/en_US';
import zhCN from 'antd/locale/zh_CN';
import jaJP from 'antd/locale/ja_JP';
import frFR from 'antd/locale/fr_FR';
import { useState } from 'react';
import { Select } from 'antd';

const locales = {
  'en-US': { antd: enUS, intl: enUSIntl, label: 'English' },
  'zh-CN': { antd: zhCN, intl: zhCNIntl, label: '简体中文' },
  'ja-JP': { antd: jaJP, intl: jaJPIntl, label: '日本語' },
  'fr-FR': { antd: frFR, intl: frFRIntl, label: 'Français' },
};

function App() {
  const [locale, setLocale] = useState('en-US');
  const currentLocale = locales[locale];

  return (
    <ConfigProvider locale={currentLocale.antd}>
      <ProConfigProvider intl={currentLocale.intl}>
        <Select
          value={locale}
          onChange={setLocale}
          style={{ width: 120 }}
        >
          {Object.entries(locales).map(([key, { label }]) => (
            <Select.Option key={key} value={key}>
              {label}
            </Select.Option>
          ))}
        </Select>
        <YourApp />
      </ProConfigProvider>
    </ConfigProvider>
  );
}

TypeScript Support

ProComponents provides full TypeScript support for i18n:
import type { IntlType } from '@ant-design/pro-components';

const myIntl: IntlType = {
  locale: 'en-US',
  getMessage: (id: string, defaultMessage: string) => {
    // Your custom implementation
    return defaultMessage;
  },
};

Real-World Example

Here’s a complete example with locale persistence:
import { ProConfigProvider, enUSIntl, zhCNIntl } from '@ant-design/pro-components';
import { ConfigProvider } from 'antd';
import enUS from 'antd/locale/en_US';
import zhCN from 'antd/locale/zh_CN';
import { useState, useEffect } from 'react';

const locales = {
  'en-US': { antd: enUS, pro: enUSIntl },
  'zh-CN': { antd: zhCN, pro: zhCNIntl },
};

function App() {
  const [locale, setLocale] = useState(() => {
    // Load from localStorage
    return localStorage.getItem('locale') || 'en-US';
  });

  useEffect(() => {
    // Persist to localStorage
    localStorage.setItem('locale', locale);
  }, [locale]);

  const currentLocale = locales[locale];

  return (
    <ConfigProvider locale={currentLocale.antd}>
      <ProConfigProvider intl={currentLocale.pro}>
        <YourApp onLocaleChange={setLocale} currentLocale={locale} />
      </ProConfigProvider>
    </ConfigProvider>
  );
}

Best Practices

  1. Always provide defaultMessage: It serves as both fallback and documentation
  2. Use nested keys: Organize translations by component/feature (e.g., tableForm.search)
  3. Sync with Ant Design: Use the same locale for both ConfigProvider and ProConfigProvider
  4. Test fallbacks: Ensure your app works even if translations are missing
  5. Persist locale choice: Save user’s language preference to localStorage or cookies

Next Steps

Architecture Overview

Learn about ProComponents architecture and design

Theming System

Customize appearance with design tokens

Build docs developers (and LLMs) love