Переводы сообщений

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

Локализация через useMessageFormatter

Для организации переводов используется хук useMessageFormatter. Он позволяет централизованно хранить все строки сообщений и форматировать их с учётом выбранной локали.

Пример использования:

import {useMessageFormatter} from '@react-aria/i18n';

const messages = {
  en: {
    greeting: "Hello, {name}!",
    itemsSelected: "{count} items selected"
  },
  ru: {
    greeting: "Привет, {name}!",
    itemsSelected: "Выбрано {count} элементов"
  }
};

function MyComponent({locale, name, count}) {
  let formatMessage = useMessageFormatter(messages[locale]);
  
  return (
    <div>
      <p>{formatMessage('greeting', {name})}</p>
      <p>{formatMessage('itemsSelected', {count})}</p>
    </div>
  );
}

Ключевые моменты:

  • messages содержит набор ключей сообщений для каждой локали.
  • formatMessage автоматически подставляет переменные в строки.
  • Использование хуков React Aria обеспечивает совместимость с другими компонентами и соблюдение стандартов доступности.

Динамическая смена языка

React Aria позволяет менять локаль на лету без перезагрузки приложения. Для этого можно хранить текущую локаль в состоянии и передавать её в useMessageFormatter.

import {useState} from 'react';

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

  return (
    <>
      <button onCl ick={() => setLocale('en')}>English</button>
      <button onCl ick={() => setLocale('ru')}>Русский</button>
      <MyComponent locale={locale} name="Алексей" count={3} />
    </>
  );
}

Особенности:

  • Все компоненты, использующие useMessageFormatter, автоматически обновят отображение при смене локали.
  • Нет необходимости вручную пересоздавать строки сообщений — хук управляет этим автоматически.

Форматирование чисел и дат

Важной частью переводов является корректное форматирование чисел, валют и дат. React Aria предоставляет утилиты через @react-aria/i18n:

import {formatNumber, formatDate} from '@react-aria/i18n';

let formattedNumber = formatNumber(1234567.89, {locale: 'ru'});
let formattedDate = formatDate(new Date(), {locale: 'ru', dateStyle: 'long'});

Принципы работы:

  • Используются стандартные API Intl.NumberFormat и Intl.DateTimeFormat.
  • Форматирование подчиняется локали, включая разделители, порядок дня и месяца, валюту.
  • Это гарантирует корректное отображение информации для пользователей разных регионов.

Сообщения с условными формами (pluralization)

Для языков с различными формами множественного числа важно корректно отображать тексты с переменными числами:

const messages = {
  ru: {
    itemsSelected: "{count, plural, one {# элемент выбран} few {# элемента выбрано} many {# элементов выбрано} other {# элементов выбрано}}"
  }
};

let formatMessage = useMessageFormatter(messages['ru']);
formatMessage('itemsSelected', {count: 5}); // "5 элементов выбрано"

Пояснения:

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

Структурирование сообщений

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

const messages = {
  ru: {
    button: {
      submit: "Отправить",
      cancel: "Отмена"
    },
    form: {
      required: "Поле обязательно для заполнения",
      invalidEmail: "Некорректный адрес электронной почты"
    }
  }
};

Это облегчает поддержку и расширение локалей, а также позволяет использовать динамическое получение сообщений по ключу:

formatMessage('form.required');

Интеграция с компонентами React Aria

Многие компоненты React Aria (например, useButton, useDialog, useTooltip) используют сообщения для доступных атрибутов (aria-label, aria-describedby). С помощью useMessageFormatter можно централизованно управлять этими текстами:

import {useButton} from '@react-aria/button';

function SubmitButton({locale}) {
  let formatMessage = useMessageFormatter(messages[locale]);

  let {buttonProps} = useButton({
    onPress: () => alert('Submitted'),
    'aria-label': formatMessage('button.submit')
  });

  return <button {...buttonProps}>{formatMessage('button.submit')}</button>;
}

Преимущества:

  • Все aria-атрибуты локализованы.
  • Обеспечивается единый источник правды для сообщений.
  • Поддерживается динамическая смена языка без потери доступности.

Рекомендации по организации

  • Централизованное хранилище сообщений: хранить все переводы в одном месте или подключать отдельные JSON-файлы.
  • Использовать переменные: для динамических частей сообщений применять подстановку через {variable}.
  • Проверка plural и gender: учитывать особенности языков при работе с множественным числом и родом.
  • Тестирование локалей: обязательно проверять все языки в интерфейсе, особенно сложные формы чисел и даты.

Эти подходы делают интерфейс React Aria полностью локализуемым, грамматически корректным и доступным для пользователей с различными языковыми настройками.