Создание собственных переводов

В библиотеке Ant Design механизм локализации построен вокруг конфигурационного компонента ConfigProvider. Через него в приложение передается объект локали, содержащий переводы интерфейса для всех компонентов библиотеки: календарей, таблиц, форм, модальных окон, уведомлений и других элементов.

Каждый компонент Ant Design использует ключи локализации из общего объекта locale. Внутри этого объекта определены вложенные структуры для различных компонентов:

  • Pagination
  • DatePicker
  • TimePicker
  • Calendar
  • Table
  • Modal
  • Popconfirm
  • Transfer
  • Upload
  • Empty
  • и другие

Стандартные переводы распространяются вместе с библиотекой и находятся в пакете:

antd/es/locale

Каждый файл в этой директории представляет локаль для определённого языка.

Пример доступных локалей:

en_US
ru_RU
fr_FR
de_DE
zh_CN
es_ES

Каждая локаль представляет собой JavaScript-объект со структурой переводов.


Подключение стандартной локали

Базовый механизм подключения перевода выглядит следующим образом.

import { ConfigProvider } from 'antd';
import ruRU from 'antd/es/locale/ru_RU';

function App() {
  return (
    <ConfigProvider locale={ruRU}>
      <Application />
    </ConfigProvider>
  );
}

После передачи локали через ConfigProvider все компоненты Ant Design автоматически начинают использовать соответствующие переводы.


Структура файла локали

Файл локали представляет собой объект со множеством вложенных разделов. Ниже приведена упрощённая структура:

const locale = {
  locale: 'ru',

  Pagination: {
    items_per_page: 'элементов / стр',
    jump_to: 'Перейти',
    jump_to_confirm: 'подтвердить',
    page: '',
  },

  DatePicker: {
    lang: {
      placeholder: 'Выберите дату',
      rangePlaceholder: ['Начальная дата', 'Конечная дата']
    }
  },

  Table: {
    filterTitle: 'Фильтр',
    filterConfirm: 'Ок',
    filterReset: 'Сбросить',
    emptyText: 'Нет данных'
  },

  Modal: {
    okText: 'Ок',
    cancelText: 'Отмена'
  }
}

Каждый раздел содержит строки, используемые соответствующим компонентом.


Причины создания собственных переводов

Стандартные локали подходят не всегда. Необходимость создания пользовательских переводов возникает в нескольких ситуациях:

1. Корпоративная терминология

В интерфейсе могут использоваться специфические формулировки:

  • «Клиенты» вместо «Пользователи»
  • «Сделки» вместо «Транзакции»

2. Исправление стандартных переводов

Некоторые локали могут содержать неудачные формулировки.

3. Частичная локализация

В приложении может использоваться собственный перевод только части компонентов.

4. Поддержка редких языков

Если нужный язык отсутствует в стандартной библиотеке.


Создание собственной локали

Наиболее распространённый способ — создать новый файл локализации на основе существующего.

Пример структуры проекта:

src/
  locales/
    ruCustom.js

Файл пользовательской локали:

import ruRU from 'antd/es/locale/ru_RU';

const ruCustom = {
  ...ruRU,

  Table: {
    ...ruRU.Table,
    emptyText: 'Данные отсутствуют'
  },

  Modal: {
    ...ruRU.Modal,
    okText: 'Подтвердить',
    cancelText: 'Закрыть'
  }
};

export default ruCustom;

Использование:

import { ConfigProvider } from 'antd';
import ruCustom from './locales/ruCustom';

function App() {
  return (
    <ConfigProvider locale={ruCustom}>
      <Application />
    </ConfigProvider>
  );
}

Такой подход позволяет переопределять только нужные строки.


Полностью кастомная локаль

Если требуется создать перевод с нуля, можно сформировать собственный объект локализации.

Пример:

const customLocale = {
  locale: 'custom',

  Pagination: {
    items_per_page: 'на странице',
    jump_to: 'Страница',
    jump_to_confirm: 'перейти',
    page: '',
  },

  Modal: {
    okText: 'Подтвердить',
    cancelText: 'Отмена'
  },

  Table: {
    emptyText: 'Список пуст'
  }
};

Использование остаётся тем же:

<ConfigProvider locale={customLocale}>

Важно учитывать, что отсутствующие ключи будут использовать значения по умолчанию.


Расширение существующих переводов

На практике чаще всего используется расширение стандартной локали.

Пример:

import enUS from 'antd/es/locale/en_US';

const customLocale = {
  ...enUS,

  Table: {
    ...enUS.Table,
    emptyText: 'No records available'
  }
};

Такой подход имеет несколько преимуществ:

  • сохранение полной совместимости с библиотекой
  • обновления Ant Design не ломают локаль
  • минимальный объём собственного кода

Локализация компонентов даты

Компоненты работы с датами используют дополнительную библиотеку:

  • dayjs (начиная с Ant Design v5)

Локализация дат должна настраиваться отдельно.

Пример:

import dayjs from 'dayjs';
import 'dayjs/locale/ru';

dayjs.locale('ru');

Без настройки dayjs календарные компоненты могут отображаться на английском языке.


Создание модульной системы переводов

В крупных проектах переводы обычно разбиваются на отдельные файлы.

Пример структуры:

locales/
  antd/
    ru.js
    en.js
  app/
    ru.js
    en.js

Файл Ant Design:

import ruRU from 'antd/es/locale/ru_RU';

export default {
  ...ruRU,
  Modal: {
    ...ruRU.Modal,
    okText: 'Сохранить'
  }
};

Файл переводов приложения:

export default {
  dashboard: {
    title: 'Панель управления'
  }
};

Главный файл локали:

import antdRu from './antd/ru';
import appRu from './app/ru';

export default {
  antd: antdRu,
  app: appRu
};

Динамическое переключение языков

Для приложений с поддержкой нескольких языков используется состояние языка.

Пример:

const locales = {
  ru: require('./locales/ru'),
  en: require('./locales/en')
};

Переключение:

const [lang, setLang] = useState('ru');

<ConfigProvider locale={locales[lang]}>
  <App />
</ConfigProvider>

Изменение языка автоматически обновляет переводы компонентов.


Lazy-загрузка локалей

В больших приложениях может использоваться динамическая загрузка переводов.

Пример:

const loadLocale = async (lang) => {
  const locale = await import(`antd/es/locale/${lang}`);
  return locale.default;
};

Это позволяет уменьшить размер начального bundle.


Переопределение переводов конкретного компонента

Иногда требуется изменить текст только одного компонента.

Пример для Pagination:

const locale = {
  ...ruRU,

  Pagination: {
    ...ruRU.Pagination,
    items_per_page: 'на странице'
  }
};

Такое изменение затронет все компоненты пагинации.


Локализация уведомлений

Компоненты message и notification не используют стандартный объект локали напрямую. Текст сообщений задаётся вручную.

Пример:

message.success('Данные успешно сохранены');

Поэтому перевод таких сообщений обычно реализуется через систему i18n приложения.


Интеграция с библиотеками i18n

В сложных проектах Ant Design часто используется вместе с:

  • react-i18next
  • formatjs
  • lingui

В этом случае строки интерфейса хранятся в общем словаре приложения, а локаль Ant Design подключается отдельно.

Пример интеграции:

import { useTranslation } from 'react-i18next';

const { t } = useTranslation();

<Button>{t('buttons.save')}</Button>

При этом ConfigProvider продолжает отвечать за переводы встроенных компонентов.


Проверка полноты перевода

При создании собственной локали важно проверять наличие всех ключей.

Один из способов — сравнение со стандартной локалью:

Object.keys(enUS).forEach(key => {
  if (!customLocale[key]) {
    console.warn(`Missing translation: ${key}`);
  }
});

Это позволяет выявить пропущенные переводы.


Организация переводов в больших проектах

В масштабных интерфейсах рекомендуется придерживаться следующих принципов:

1. Разделение переводов

  • библиотечные
  • системные
  • пользовательские

2. Использование единых терминов

Одинаковые элементы интерфейса должны использовать одинаковые переводы.

3. Централизованное управление

Все переводы должны храниться в единой структуре.

4. Поддержка масштабируемости

Новые языки должны добавляться без изменения существующей архитектуры.


Рекомендации по созданию пользовательских локалей

На практике наиболее устойчивой стратегией является следующий подход:

  1. Импорт стандартной локали
  2. Расширение нужных разделов
  3. Переопределение только необходимых строк
  4. Хранение локалей в отдельной директории
  5. Использование динамической загрузки при необходимости

Такая архитектура обеспечивает совместимость с обновлениями Ant Design и упрощает поддержку многоязычных интерфейсов.