Уведомления и алерты

Локализация уведомлений и алертов в FormatJS опирается на идею того, что любые пользовательские сообщения в интерфейсе представляют собой форматируемые строки с параметрами, зависящие от языка, контекста и грамматических правил конкретной локали. Уведомления (notifications), всплывающие алерты (alerts), toast-сообщения и системные сообщения становятся частью единого механизма интернационализации, где текст не «вшивается» в логику приложения, а описывается через структурированные сообщения ICU MessageFormat.

Ключевая особенность подхода заключается в разделении логики и представления текста. Сообщение описывается через defineMessages, MessageDescriptor или аналогичные структуры, а затем динамически форматируется через formatMessage. Это позволяет унифицировать уведомления вне зависимости от источника события: ошибки, успех операции, предупреждения или информационные сообщения.


Уведомление в контексте FormatJS представляет собой объект с метаданными:

  • уникальный идентификатор сообщения (id)
  • значение по умолчанию (defaultMessage)
  • описание (description)
  • параметры форматирования (values)

Пример базового описания:

import { defineMessages } from 'react-intl';

const messages = defineMessages({
  saveSuccess: {
    id: 'notifications.save.success',
    defaultMessage: 'Данные успешно сохранены',
    description: 'Уведомление об успешном сохранении'
  }
});

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


Формирование уведомлений через formatMessage

Формирование текста уведомления выполняется через formatMessage, который принимает описание сообщения и значения для подстановки:

import { useIntl } from 'react-intl';

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

  const handleSave = async () => {
    await saveData();

    const text = intl.formatMessage(messages.saveSuccess);

    showToast(text);
  };

  return <button onCl ick={handleSave}>Сохранить</button>;
}

Функция formatMessage гарантирует корректную подстановку текста в зависимости от текущей локали, включая правила склонения, чисел и дат, если они используются.


Динамические уведомления с параметрами

Уведомления редко бывают статичными. Чаще они содержат переменные значения: количество элементов, имена пользователей, суммы, статусы.

ICU MessageFormat позволяет встроить параметры прямо в шаблон:

const messages = defineMessages({
  itemsDeleted: {
    id: 'notifications.items.deleted',
    defaultMessage: 'Удалено {count} элементов'
  }
});

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

intl.formatMessage(messages.itemsDeleted, { count: 5 });

Плюрализация в уведомлениях

Одна из наиболее сложных задач локализации — корректное отображение множественных форм. FormatJS использует ICU plural rules, адаптированные под каждую локаль.

const messages = defineMessages({
  inbox: {
    id: 'notifications.inbox',
    defaultMessage: 'У вас {count, plural, one {# новое сообщение} few {# новых сообщения} many {# новых сообщений} other {# сообщения}}'
  }
});

Форматирование:

intl.formatMessage(messages.inbox, { count: 3 });

Система автоматически выбирает правильную форму в зависимости от языка, например для русского учитываются категории one, few, many, other.


Уведомления с условиями и вложенной логикой

ICU MessageFormat поддерживает не только числа, но и условия (select), что особенно полезно для алертов с разными типами статусов.

const messages = defineMessages({
  taskStatus: {
    id: 'notifications.task.status',
    defaultMessage: 'Задача: {status, select, success {успешно завершена} error {завершена с ошибкой} pending {в процессе} other {неизвестный статус}}'
  }
});

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

intl.formatMessage(messages.taskStatus, { status: 'success' });

Интеграция уведомлений с toast-системами

В реальных приложениях FormatJS редко используется изолированно — чаще он является слоем генерации текста для UI-компонентов уведомлений.

Пример интеграции с toast-менеджером:

function notifySuccess(intl) {
  toast.success(
    intl.formatMessage({
      id: 'notifications.save.success',
      defaultMessage: 'Сохранение завершено успешно'
    })
  );
}

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


Ошибки и алерты с параметризацией

Ошибки часто требуют передачи контекста: кода ошибки, имени поля, причины.

const messages = defineMessages({
  fieldError: {
    id: 'notifications.error.field',
    defaultMessage: 'Ошибка в поле {field}: {reason}'
  }
});

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

intl.formatMessage(messages.fieldError, {
  field: 'Email',
  reason: 'неверный формат'
});

Это позволяет создавать единый шаблон ошибок без дублирования строк.


Форматирование дат и времени в уведомлениях

Уведомления часто содержат временные метки. FormatJS предоставляет FormattedDate, FormattedTime и intl.formatDate.

intl.formatMessage(
  {
    id: 'notifications.reminder',
    defaultMessage: 'Напоминание: событие состоится {date}'
  },
  {
    date: intl.formatDate(new Date(), {
      year: 'numeric',
      month: 'long',
      day: '2-digit'
    })
  }
);

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


Доступность уведомлений (accessibility)

Уведомления и алерты должны корректно восприниматься скринридерами. При использовании FormatJS текст уведомления уже локализован, но важна его интеграция в ARIA-модель:

  • aria-live="polite" для информационных сообщений
  • aria-live="assertive" для ошибок
  • корректное обновление DOM при смене языка

Пример:

<div aria-live="polite">
  {intl.formatMessage(messages.saveSuccess)}
</div>

FormatJS обеспечивает только текстовый слой, а доступность реализуется на уровне UI-компонентов.


Централизация уведомлений в масштабных приложениях

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

/i18n
  /messages
    notifications.js
    errors.js
    warnings.js

Каждое сообщение становится независимой единицей, что позволяет:

  • переиспользовать тексты в разных модулях
  • избегать дублирования строк
  • централизованно обновлять формулировки
  • синхронизировать переводы

Ошибки архитектуры при локализации уведомлений

Частые проблемы при неправильном использовании FormatJS в алертах:

  • хранение готовых строк вместо message descriptors
  • форматирование строк вне intl-контекста
  • дублирование сообщений с разными id для одного текста
  • игнорирование plural rules и использование ручных if/else конструкций
  • смешивание бизнес-логики с текстовыми шаблонами

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


Динамическая генерация уведомлений на основе событий

В событийных системах уведомления часто генерируются автоматически:

function handleEvent(event, intl) {
  switch (event.type) {
    case 'UPLOAD_COMPLETE':
      return intl.formatMessage(messages.uploadComplete);

    case 'UPLOAD_FAILED':
      return intl.formatMessage(messages.uploadFailed, {
        file: event.payload.fileName
      });

    default:
      return intl.formatMessage(messages.unknownEvent);
  }
}

Такой подход позволяет масштабировать систему уведомлений без усложнения UI-слоя.


Связь уведомлений с контекстом локали

FormatJS реагирует на смену локали через IntlProvider. При смене языка:

  • пересчитываются все formatMessage
  • обновляются активные уведомления (если они реактивны)
  • сохраняется консистентность отображения текста

Это важно для приложений, где пользователь может менять язык «на лету» без перезагрузки интерфейса.


Композиция сложных уведомлений

Сложные алерты могут содержать вложенные значения:

const messages = defineMessages({
  backupStatus: {
    id: 'notifications.backup.status',
    defaultMessage: 'Резервное копирование {status} ({progress}%)'
  }
});
intl.formatMessage(messages.backupStatus, {
  status: 'в процессе',
  progress: 78
});

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


Поведение уведомлений при отсутствующих переводах

Если перевод для текущей локали отсутствует, FormatJS использует defaultMessage. Это делает систему устойчивой:

  • приложение не ломается
  • пользователь видит fallback-текст
  • перевод можно добавить позже без изменения кода

Использование rich-text уведомлений

FormatJS поддерживает rich-text форматирование, позволяя вставлять элементы в сообщения:

const messages = defineMessages({
  terms: {
    id: 'notifications.terms',
    defaultMessage: 'Принятие <b>условий использования</b> обязательно'
  }
});

Рендер:

intl.formatMessage(messages.terms, {
  b: (chunks) => <strong>{chunks}</strong>
});

Это позволяет создавать уведомления с частичным форматированием без нарушения локализационной структуры.


Масштабирование системы алертов

При росте приложения уведомления становятся отдельной подсистемой, где FormatJS выполняет роль слоя генерации текста. В таких архитектурах:

  • UI отвечает за отображение (toast, modal, banner)
  • FormatJS отвечает за текст и локализацию
  • бизнес-логика формирует события
  • слой i18n управляет контентом

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