Направление письма

Базовые принципы направления текста

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

  • LTR (Left-to-Right) — слева направо: латиница, кириллица, греческий алфавит
  • RTL (Right-to-Left) — справа налево: арабский, иврит, персидский, урду

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

Unicode Bidirectional Algorithm

Основой отображения текста с разными направлениями является Unicode Bidirectional Algorithm (Bidi Algorithm). Он решает, как визуально упорядочить символы, если в одной строке присутствуют разные направления письма.

Ключевые особенности алгоритма:

  • каждому символу назначается bidi-класс (LTR, RTL, нейтральный)
  • последовательности символов группируются в “runs” одного направления
  • нейтральные символы (пробелы, знаки препинания) получают направление от контекста
  • цифры обычно отображаются в LTR-логике даже в RTL-тексте

Пример проблемной строки:

hello 123 שלום

В зависимости от контекста отображение может меняться, особенно если отсутствует явное указание направления контейнера.

Intl API и языковая локализация без прямого управления направлением

Библиотека Intl API в JavaScript не управляет направлением текста напрямую. Её задача — локализация данных:

  • форматирование дат: Intl.DateTimeFormat
  • форматирование чисел: Intl.NumberFormat
  • форматирование списков: Intl.ListFormat
  • сортировка: Intl.Collator

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

Пример:

const ar = new Intl.NumberFormat('ar-EG');
const en = new Intl.NumberFormat('en-US');

console.log(ar.format(1234567.89));
console.log(en.format(1234567.89));

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

Локаль и семантика направления

Локаль в Intl API задаёт не только язык, но и культурные правила отображения данных. Однако направление текста традиционно не было частью стандартного API. Это приводило к тому, что разработчик обязан был отдельно учитывать RTL-локали при построении интерфейса.

Примеры RTL-локалей:

  • ar — арабский
  • he — иврит
  • fa — персидский
  • ur — урду

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

HTML-уровень: связь с Intl через локаль

В веб-разработке направление текста задаётся через атрибут:

<div dir="rtl">مرحبا بالعالم</div>

или:

<div dir="ltr">Hello world</div>

Intl API не управляет этим атрибутом напрямую, но часто используется для определения текущей локали:

const locale = navigator.language;

const rtlLocales = ['ar', 'he', 'fa', 'ur'];

const isRTL = rtlLocales.some(code => locale.startsWith(code));

document.documentElement.dir = isRTL ? 'rtl' : 'ltr';

Таким образом, Intl становится частью системы принятия решений о направлении интерфейса, хотя формально не отвечает за него.

Смешанное направление и визуальные артефакты

Одной из наиболее сложных проблем является смешение LTR и RTL в одной строке.

Пример:

Order № 123 من المتجر

Проблемы, возникающие при рендеринге:

  • перестановка чисел и слов
  • “разрыв” логических блоков
  • неправильное отображение знаков препинания
  • инверсия скобок

Особенно критично это проявляется при отсутствии корректного контейнера с dir.

Intl и локализация интерфейсных данных

Хотя Intl не задаёт направление письма, он влияет на компоненты, которые визуально зависят от него:

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

const dt = new Intl.DateTimeFormat('ar-SA', {
  dateStyle: 'full'
});

console.log(dt.format(new Date()));

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

Форматирование списков

const list = new Intl.ListFormat('he', {
  style: 'long',
  type: 'conjunction'
});

console.log(list.format(['אחד', 'שניים', 'שלושה']));

Порядок элементов и соединители адаптируются к языковой норме, что влияет на восприятие текста в RTL-среде.

Экспериментальная информация о направлении в Intl.Locale

Современные реализации расширяют объект Intl.Locale дополнительными метаданными, включая информацию о тексте:

const locale = new Intl.Locale('ar-EG');

console.log(locale.textInfo?.direction);

В некоторых средах это может возвращать:

  • "rtl"
  • "ltr"

Однако поддержка этого свойства зависит от реализации и может отсутствовать в стандартных окружениях.

Практическая связка: Intl + UI direction pipeline

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

  1. Определение локали

    const locale = navigator.language;
  2. Использование Intl для локализации данных

    • даты
    • числа
    • списки
  3. Определение направления интерфейса

    const isRTL = new Intl.Locale(locale).textInfo?.direction === 'rtl';
  4. Применение к DOM

    document.documentElement.dir = isRTL ? 'rtl' : 'ltr';

Нюансы работы чисел и пунктуации в RTL-среде

В RTL-окружении числовые данные сохраняют LTR-структуру, но визуально могут перестраиваться:

  • число 1234 остаётся логически тем же
  • визуальный порядок может инвертироваться в зависимости от окружения
  • разделители тысяч и десятичные знаки подчиняются локали

Пример:

new Intl.NumberFormat('fa-IR').format(1234567.89);

Влияние на архитектуру интерфейсов

Поддержка направлений письма требует, чтобы интерфейс:

  • не фиксировал горизонтальные координаты без учета dir
  • использовал логические свойства CSS (margin-inline, padding-inline)
  • избегал абсолютного позиционирования для текста
  • учитывал зеркалирование компонентов

Intl API в этом контексте выступает источником культурных правил, а не механизмом управления рендерингом, но его результаты определяют, как данные будут вписаны в RTL или LTR структуру.

Стабильность и предсказуемость отображения

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

  • локаль, используемая в Intl, должна совпадать с локалью интерфейса
  • направление текста должно определяться один раз на уровне приложения
  • смешивание локалей без учета dir приводит к визуальной неоднозначности

Особенно это важно для:

  • финансовых интерфейсов
  • CRM-систем
  • административных панелей
  • мультиязычных редакторов

Итоговая модель взаимодействия Intl и направления письма

В архитектурном смысле роль Intl API сводится к следующему:

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

Направление письма при этом остаётся отдельным уровнем, зависящим от:

  • языка интерфейса
  • HTML-атрибутов
  • CSS-модели отображения
  • Unicode Bidi Algorithm