Как отмечать текст на разных языках в Next.js (Pages Router) v16

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

Проблема

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

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

Решение

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

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

Шаги

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

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

interface ForeignTextProps {
  lang: string;
  children: React.ReactNode;
}

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

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

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

Оборачивайте текст на иностранном языке в вашем контенте с помощью компонента, указывая соответствующий код языка ISO 639-1.

export default function ArticlePage() {
  return (
    <article>
      <h1>Понимание французской кухни</h1>
      <p>
        Концепция <ForeignText lang="fr">mise en place</ForeignText> является
        основополагающей для профессиональной кулинарии. Это означает, что все ингредиенты
        должны быть подготовлены и организованы перед началом.
      </p>
      <p>
        Ресторан <ForeignText lang="fr">Le Bernardin</ForeignText> в Нью-Йорке
        сохраняет три звезды Мишлен на протяжении десятилетий.
      </p>
    </article>
  );
}

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

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

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

export default function QuotePage() {
  return (
    <article>
      <h1>Всеобщая декларация прав человека</h1>
      <h2>Статья 1</h2>
      <blockquote lang="es">
        <p>
          Todos los seres humanos nacen libres e iguales en dignidad y derechos
          y, dotados como están de razón y conciencia, deben comportarse
          fraternalmente los unos con los otros.
        </p>
      </blockquote>
    </article>
  );
}

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

4. Выделение иностранного текста в форматированных сообщениях

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

import { FormattedMessage } from "react-intl";

export default function RecipePage() {
  return (
    <div>
      <FormattedMessage
        id="recipe.description"
        defaultMessage="Это блюдо называется {dishName} во французской кухне."
        values={{
          dishName: <ForeignText lang="fr">coq au vin</ForeignText>,
        }}
      />
    </div>
  );
}

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

5. Создание вариантов для семантического выделения

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

interface ForeignEmphasisProps {
  lang: string;
  children: React.ReactNode;
}

export function ForeignEmphasis({ lang, children }: ForeignEmphasisProps) {
  return <i lang={lang}>{children}</i>;
}

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

6. Документирование поддерживаемых языковых кодов

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

export const SUPPORTED_LANGUAGES = {
  FRENCH: "fr",
  SPANISH: "es",
  GERMAN: "de",
  ITALIAN: "it",
  JAPANESE: "ja",
  CHINESE: "zh",
} as const;

type LanguageCode =
  (typeof SUPPORTED_LANGUAGES)[keyof typeof SUPPORTED_LANGUAGES];

interface ForeignTextProps {
  lang: LanguageCode | string;
  children: React.ReactNode;
}

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

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