Доступность для скрин-ридеров

Локализация интерфейса не ограничивается переводом текстовых строк. Полноценная интернационализация должна учитывать потребности пользователей, работающих со скрин-ридерами, экранными увеличителями, голосовым управлением и другими ассистивными технологиями. При использовании I18next особое внимание уделяется переводу не только видимого контента, но и атрибутов доступности, динамических сообщений, уведомлений и описаний элементов интерфейса.

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


Перевод атрибутов доступности

Многие элементы содержат текст, который не отображается визуально, но активно используется программами чтения экрана.

К таким атрибутам относятся:

  • aria-label
  • aria-description
  • aria-placeholder
  • aria-valuetext
  • title
  • alt

Структура переводов

{
  "accessibility": {
    "searchButton": "Поиск",
    "closeDialog": "Закрыть окно",
    "userAvatar": "Аватар пользователя"
  }
}

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

button.setAttribute(
  "aria-label",
  i18next.t("accessibility.searchButton")
);

closeBtn.setAttribute(
  "aria-label",
  i18next.t("accessibility.closeDialog")
);

avatar.setAttribute(
  "alt",
  i18next.t("accessibility.userAvatar")
);

В результате скрин-ридер озвучивает элементы на языке локали пользователя.


Локализация альтернативного текста изображений

Атрибут alt играет важнейшую роль для незрячих пользователей. Его отсутствие приводит к потере части информации интерфейса.

Переводы

{
  "images": {
    "productPhoto": "Фотография товара",
    "companyLogo": "Логотип компании",
    "profilePicture": "Фотография профиля"
  }
}

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

img.alt = i18next.t("images.productPhoto");

Если изображение декоративное и не несёт смысловой нагрузки, используется пустой атрибут:

<img src="background.png" alt="" />

Такой элемент будет проигнорирован скрин-ридером.


Перевод ARIA-меток

ARIA-метки позволяют уточнять назначение элементов управления.

Пример кнопки удаления

{
  "actions": {
    "delete": "Удалить запись"
  }
}
deleteButton.setAttribute(
  "aria-label",
  i18next.t("actions.delete")
);

Пример панели навигации

{
  "navigation": {
    "main": "Основная навигация"
  }
}
<nav aria-label="Основная навигация">
</nav>

При использовании I18next:

nav.setAttribute(
  "aria-label",
  i18next.t("navigation.main")
);

Локализация скрытого текста

Нередко в интерфейсе присутствует текст, скрытый визуально, но доступный для скрин-ридеров.

Пример

<button>
  <span class="icon"></span>
  <span class="sr-only">
    Удалить документ
  </span>
</button>

Переводы

{
  "buttons": {
    "deleteDocument": "Удалить документ"
  }
}

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

screenReaderText.textContent =
  i18next.t("buttons.deleteDocument");

Подход особенно полезен для иконок без текстовых подписей.


Доступность форм

Формы содержат большое количество элементов, требующих перевода.

Локализуются:

  • подписи полей;
  • подсказки;
  • сообщения об ошибках;
  • инструкции по заполнению;
  • ARIA-описания.

Переводы

{
  "form": {
    "email": "Электронная почта",
    "emailHint": "Введите адрес электронной почты",
    "emailError": "Некорректный адрес электронной почты"
  }
}

Разметка

<label for="email">
  Электронная почта
</label>

<input
  id="email"
  aria-describedby="emailHint"
/>

<div id="emailHint">
  Введите адрес электронной почты
</div>

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

label.textContent =
  i18next.t("form.email");

hint.textContent =
  i18next.t("form.emailHint");

Перевод сообщений об ошибках

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

Переводы

{
  "errors": {
    "required": "Поле обязательно для заполнения",
    "email": "Укажите корректный адрес электронной почты"
  }
}

Отображение

errorElement.textContent =
  i18next.t("errors.required");

Добавление ARIA-атрибутов

input.setAttribute(
  "aria-invalid",
  "true"
);

input.setAttribute(
  "aria-describedby",
  "error-message"
);

Скрин-ридер сможет автоматически связать поле с текстом ошибки.


Использование live-регионов

Динамические уведомления должны озвучиваться автоматически.

Для этого применяются ARIA live-регионы.

Разметка

<div
  id="notifications"
  aria-live="polite"
></div>

Переводы

{
  "notifications": {
    "saved": "Изменения успешно сохранены",
    "deleted": "Запись удалена"
  }
}

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

notifications.textContent =
  i18next.t("notifications.saved");

После обновления содержимого скрин-ридер озвучит сообщение пользователю.


Режимы aria-live

polite

Сообщение озвучивается после завершения текущего чтения.

<div aria-live="polite"></div>

Подходит для:

  • уведомлений;
  • информационных сообщений;
  • статусов операций.

assertive

Сообщение озвучивается немедленно.

<div aria-live="assertive"></div>

Подходит для:

  • критических ошибок;
  • предупреждений безопасности;
  • сообщений о сбоях.

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


Интерполяция в сообщениях доступности

Скрин-ридеру часто требуется озвучивать динамические значения.

Переводы

{
  "cart": {
    "itemsCount": "В корзине {{count}} товаров"
  }
}

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

const message = i18next.t(
  "cart.itemsCount",
  {
    count: 5
  }
);

Результат:

В корзине 5 товаров

Скрин-ридер получит актуальную информацию.


Плюрализация для скрин-ридеров

Неправильные формы слов ухудшают восприятие озвучиваемого текста.

Переводы

{
  "messages_zero": "Нет сообщений",
  "messages_one": "{{count}} сообщение",
  "messages_few": "{{count}} сообщения",
  "messages_many": "{{count}} сообщений"
}

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

i18next.t("messages", {
  count: unreadCount
});

Для русского языка I18next автоматически выберет корректную форму.

Примеры:

1 сообщение
2 сообщения
5 сообщений
21 сообщение

Перевод состояния элементов интерфейса

Пользователь скрин-ридера должен получать информацию о текущем состоянии интерфейса.

Переводы

{
  "state": {
    "expanded": "Развернуто",
    "collapsed": "Свернуто"
  }
}

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

const stateText = isOpen
  ? i18next.t("state.expanded")
  : i18next.t("state.collapsed");

ARIA

button.setAttribute(
  "aria-label",
  stateText
);

Локализация описаний сложных элементов

Сложные виджеты часто требуют дополнительных пояснений.

Пример таблицы

{
  "table": {
    "description":
      "Таблица содержит информацию о заказах пользователей"
  }
}
<table aria-describedby="orders-desc">
</table>

<div id="orders-desc">
</div>
description.textContent =
  i18next.t("table.description");

Скрин-ридер сможет озвучить контекст до чтения содержимого таблицы.


Доступность модальных окон

При открытии модального окна важно передать его назначение пользователю.

Переводы

{
  "dialogs": {
    "settingsTitle": "Настройки профиля",
    "settingsDescription":
      "Окно изменения параметров профиля"
  }
}

Разметка

<div
  role="dialog"
  aria-labelledby="dialog-title"
  aria-describedby="dialog-description"
>
</div>

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

title.textContent =
  i18next.t("dialogs.settingsTitle");

description.textContent =
  i18next.t("dialogs.settingsDescription");

Использование контекстов перевода

Одно и то же слово может иметь разные значения для скрин-ридера.

Переводы

{
  "open_male": "Открыт",
  "open_female": "Открыта"
}

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

i18next.t("open", {
  context: "female"
});

Результат:

Открыта

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


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

Во время длительных операций необходимо информировать пользователя.

Переводы

{
  "loading": {
    "start": "Загрузка данных",
    "complete": "Загрузка завершена"
  }
}

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

statusRegion.textContent =
  i18next.t("loading.start");

После завершения:

statusRegion.textContent =
  i18next.t("loading.complete");

В сочетании с aria-live такие уведомления становятся доступными для программ чтения экрана.


Проверка качества локализованной доступности

После перевода интерфейса необходимо контролировать качество доступности.

Основные направления проверки:

  1. Корректность перевода ARIA-атрибутов.
  2. Наличие переводов для скрытых текстов.
  3. Проверка всех сообщений live-регионов.
  4. Тестирование форм и ошибок в разных локалях.
  5. Проверка плюрализации.
  6. Контроль длины озвучиваемых фраз.
  7. Проверка переключения языка во время работы приложения.
  8. Тестирование с несколькими скрин-ридерами.

Наиболее распространённые средства проверки:

  • NVDA
  • JAWS
  • VoiceOver
  • TalkBack

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

Организация пространства переводов для доступности

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

Структура

{
  "a11y": {
    "close": "Закрыть",
    "openMenu": "Открыть меню",
    "loading": "Выполняется загрузка",
    "error": "Произошла ошибка"
  }
}

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

i18next.t("a11y.close");

Такой подход обеспечивает:

  • централизованное хранение ARIA-переводов;
  • удобство сопровождения;
  • упрощение аудита доступности;
  • снижение риска пропуска важных строк при локализации.

Интеграция I18next с механизмами доступности позволяет создавать многоязычные интерфейсы, одинаково удобные как для зрячих пользователей, так и для людей, использующих скрин-ридеры и другие ассистивные технологии. Полноценная локализация должна охватывать весь информационный слой приложения: видимый текст, скрытые описания, ARIA-атрибуты, уведомления, ошибки, состояния элементов и динамические сообщения.