Как отмечать контент на разных языках в React Router v7

Отмечайте текст на разных языках для обеспечения доступности

Проблема

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

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

Решение

Оборачивайте текст на иностранном языке в HTML-элементы с атрибутом lang, установленным на соответствующий код языка. Атрибут lang инструктирует браузеры и вспомогательные технологии переключать языковые правила для данного контента, обеспечивая правильное произношение читалками экрана и корректную проверку орфографии и типографики браузерами.

Используйте семантические HTML-элементы, такие как <span> или <i>, чтобы оборачивать встроенный иностранный текст без нарушения макета. Атрибут lang принимает коды языков ISO 639-1 (например, fr для французского или es для испанского) и дополнительные региональные коды для обработки диалектов.

Шаги

1. Создайте компонент для маркировки текста на иностранном языке

Создайте повторно используемый компонент, который оборачивает текст в элемент span с соответствующим атрибутом lang.

type ForeignTextProps = {
  lang: string;
  children: React.ReactNode;
};

export function ForeignText({ lang, children }: ForeignTextProps) {
  return <span lang={lang}>{children}</span>;
}

Этот компонент принимает код языка и оборачивает своих дочерних элементов в span с атрибутом lang, позволяя читалкам экрана переключать правила произношения для заключенного текста.

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

Оборачивайте иностранные слова или фразы в вашем контенте с помощью компонента ForeignText.

export default function ArticlePage() {
  return (
    <article>
      <h1>Международная кухня</h1>
      <p>
        Фирменное блюдо ресторана —{" "}
        <ForeignText lang="fr">coq au vin</ForeignText>, классическое французское
        блюдо, которое идеально сочетается с их домашним вином.
      </p>
      <p>
        В их десертном меню представлены{" "}
        <ForeignText lang="es">tres leches</ForeignText> и{" "}
        <ForeignText lang="it">tiramisu</ForeignText>.
      </p>
    </article>
  );
}

Теперь программы чтения с экрана будут произносить "coq au vin" с французской фонетикой, "tres leches" с испанской фонетикой и "tiramisu" с итальянской фонетикой, в то время как окружающий английский текст будет произноситься с английской фонетикой.

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

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

export default function QuotePage() {
  return (
    <article>
      <h1>Всеобщая декларация прав человека</h1>
      <h2>Статья 1</h2>
      <blockquote lang="fr">
        <p>
          Tous les êtres humains naissent libres et égaux en dignité et en
          droits. Ils sont doués de raison et de conscience et doivent agir les
          uns envers les autres dans un esprit de fraternité.
        </p>
      </blockquote>
    </article>
  );
}

Применение lang к элементу blockquote обозначает всю цитату как французскую, обеспечивая правильное произношение и типографику для всего отрывка.

4. Комбинируйте с переведённым текстом интерфейса

При отображении иностранного контента вместе с переведённым текстом интерфейса используйте react-intl для элементов интерфейса и атрибуты lang для пользовательского или цитируемого контента.

import { FormattedMessage } from "react-intl";
import { ForeignText } from "~/components/ForeignText";

export default function BookReview() {
  return (
    <article>
      <h1>
        <FormattedMessage id="review.title" defaultMessage="Обзор книги" />
      </h1>
      <p>
        <FormattedMessage
          id="review.intro"
          defaultMessage="Роман {title} исследует темы идентичности и принадлежности."
          values={{
            title: <ForeignText lang="de">Der Steppenwolf</ForeignText>,
          }}
        />
      </p>
    </article>
  );
}

Текст интерфейса адаптируется к локали пользователя через react-intl, в то время как название книги сохраняет свой оригинальный немецкий язык с правильной языковой разметкой для доступности.