RTL-поддержка
1) Принципы
1. RTL — это не перевод текста, а зеркалирование мышления. Меняются оси, порядок чтения, порядок фокуса, жесты и навигация.
2. Логические CSS-свойства вместо left/right. Переходите на `margin-inline-start`, `inset-inline-end`, `border-start-start-radius` и т. п.
3. Глобально включаем направление, локально изолируем LTR-фрагменты. Числа, URL, коды, e-mail и IBAN всегда читаются слева-направо.
4. Зеркалируйте то, что зависит от направления, а не смысла. «Play», «↗», «↙» и иконки часов/процесса могут не зеркалиться.
5. Тестируйте псевдо-RTL. Включайте `dir="rtl"`/`direction: rtl` и псевдопереводы до выхода.
2) Направление: `dir` и логические свойства
Глобально на документе/корне:html
<html lang="ar" dir="rtl"> … </html>
Логические свойства (замена left/right):
css
.card { padding-inline: 16px; margin-inline: 12px; }
.sidebar { inset-inline-start: 0; }
.button { border-start-start-radius: 12px; border-end-end-radius: 12px; }
Селекторы по направлению:
css
:root:dir(rtl). breadcrumb { flex-direction: row-reverse; }
:root:dir(ltr). breadcrumb { flex-direction: row; }
Локальная авто-направленность пользовательского контента:
html
<p dir="auto">…</p>
3) BiDi и изоляция смешанного текста
Смешение арабского/иврита с латиницей/числами ломает порядок символов. Используйте BiDi-изоляцию:- Теги: `` (изолирует направление), `` (принудительно переопределяет).
- `\u2066` LRI / `\u2067` RLI — начало LTR/RTL-изоляции, `\u2069` PDI — конец,
- `\u200E` LRM / `\u200F` RLM — однобайтные маркеры для коротких вставок.
html
<span dir="rtl">
سحب <bdi dir="ltr">IBAN AE070331234567890123456</bdi> بمبلغ
<bdi dir="ltr">2,000. 00 UAH</bdi>
</span>
4) Навигация, иерархия и макеты
Breadcrumbs: порядок зеркальный: «الصفحة الرئيسية ‹ الرهان ‹ التأكيد».
Панели/меню: основной навбар — справа; «назад» указывает влево (к началу строки RTL).
Карточки/списки: выравнивайте заголовки по inline-start; иконки статуса — к inline-end.
Карусели и свайпы: пролистывание в сторону inline-start (в RTL — вправо). Индикаторы страниц тоже зеркальные.
Пагинация: стрелка «следующая» уходит на inline-start, «предыдущая» — на inline-end.
5) Иконки и изображения
Зеркалируйте направленные пиктограммы: стрелки, «вперед/назад», плей-головка, «разворачивать/сворачивать».
Не зеркалируйте: иконки текста, графиков, часов (если есть реальная стрелка времени), логотипы брендов.
css
.rtl-mirror { transform: scaleX(-1); transform-origin: center; }
html:dir(rtl). icon--arrow { transform: scaleX(-1); }
Для SVG: используйте `transform-box: view-box;` чтобы не «плыло».
Избегайте текста внутри изображений → локализуйте отдельными слоями.
6) Формы и ввод
Выравнивание по контенту: текстовые поля по `text-align: start;`, числовые/суммы/URL/e-mail — LTR.
Атрибуты:html
<input type="email" dir="ltr" inputmode="email" autocomplete="email">
<input type="number" dir="ltr" inputmode="numeric" pattern="[0-9]">
<input type="tel" dir="ltr" inputmode="tel" autocomplete="tel">
Placeholder/label локализованы, но caret в числах/кодах должен идти слева направо.
Маски: не «перехватывайте» caret жестко; поддержите вставку и выделение.
Список/радио/чекбокс: подписи справа от контролов, зоны клика ≥ 44×44 px.
Слайдеры min→max: в RTL минимум на правом краю, максимум — на левом (или показывайте шкалу без инверсии и цифры LTR).
7) Числа, даты, валюты
По умолчанию в арабских локалях применяются арабо-индоцифры (٠١٢٣٤٥٦٧٨٩). Решение — бизнес-политика:- В финансовом UI чаще показывают латинские цифры (0–9) ради интероперабельности, но формат (пробелы/знаки) — по локали.
js new Intl. NumberFormat('ar', { style:'currency', currency:'AED' }). format(2000);
new Intl. DateTimeFormat('he-IL', { dateStyle:'medium', timeStyle:'short' }). format(new Date());
Относительное время (`Intl.RelativeTimeFormat`), направленные разделители и локальные сокращения дней/месяцев.
8) Типографика и читаемость
Шрифты с хорошей арабской/еврейской графемой и лигатурами (Arabic shaping).
Межстрочный интервал 1.4–1.6; избегайте узких трекингов.
Для арабского допустимо kashida (удлинение штрихов) при выравнивании по ширине — включайте осторожно (`text-justify: inter-word;`/поддержка движка).
Запретите курсив латиницы внутри арабской строки (портит вертикальный ритм).
9) Графики, шкалы и таблицы
Оси X идут справа налево; легенда выравнивается по inline-end.
Столбцы таблиц: «первичный» столбец (имя/игра) — справа; номера/суммы могут оставаться LTR и выравниваться по inline-end.
html
<bdi dir="ltr">+12. 5%</bdi>
10) A11y и скринридеры
Убедитесь, что `lang="ar"`/`lang="he"` выставлен: движок TTS выберет правильную озвучку.
Динамические изменения направления озвучивайте аккуратно — не переключайте `dir` на фрагментах без нужды.
Лайв-обновления (`aria-live="polite"`) — текст без смешения направлений.
Иконки не передают смысл без текстовых меток; используйте `aria-label`.
11) Специфика iGaming
11.1 Купон ставки (betslip)
Порядок полей: сумма → коэффициент → потенциальный выигрыш; подписи справа, числа/коэффы LTR.
Обновления коэффициентов подсвечивайте мягко; стрелки «вверх/вниз» зеркалить не нужно (смысл направления цены — универсален).
11.2 Матчи/рынки
Список лиг/событий выравнивайте по inline-start (в RTL — справа).
Таймеры и счет — LTR `dir="ltr"` с табличными цифрами (`font-variant-numeric: tabular-nums;`).
11.3 Платежи/KYC
Поля IBAN/BIC/телефон всегда LTR.
Банковские названия/адрес — RTL.
Ошибки/валидаторы показывают маркеры справа.
11.4 Турниры/лидерборды
Колонки: позиция, ник, очки — позиция справа; очки выравнивайте по inline-end (цифры LTR).
12) Производство и тестирование
Псевдо-RTL в деве:css html. debug-rtl { direction: rtl; }
Автозеркало иконок в RTL (только направленные):
css html:dir(rtl). icon-dir { transform: scaleX(-1); }
Автотесты (пример идей):
- Снапшоты макета при `dir=rtl`.
- Проверка отсутствия `left/right` в CSS (линт).
- E2E: порядок табуляции, свайпы карусели, поведение слайдеров.
- Визуальные тесты с арабским текстом + LTR-вставками (e-mail, сумма).
13) Токены дизайн-системы (пример)
json
{
"direction": {
"supported": ["ltr", "rtl"],
"rtlLocales": ["ar", "he", "fa", "ur"]
},
"layout": {
"gap": { "sm": 8, "md": 12, "lg": 16 },
"useLogicalProps": true
},
"icons": {
"autoMirror": true,
"exclude": ["logo", "chart", "clock", "play"]
},
"forms": {
"numericDir": "ltr",
"minTap": 44
},
"a11y": { "contrastAA": true, "live": "polite" }
}
14) Сниппеты
Переключение направления в приложении (React):tsx import { useEffect } from "react";
export function useDirection(locale: string) {
useEffect(() => {
const lang = locale. split("-")[0];
const isRTL = ["ar", "he", "fa", "ur"].includes(lang);
const html = document. documentElement;
html. setAttribute("dir", isRTL? "rtl": "ltr");
html. setAttribute("lang", locale);
}, [locale]);
}
Гармонизация списков/бредкрамбов:
css
.breadcrumb { display:flex; gap:8px; }
html:dir(rtl). breadcrumb { flex-direction: row-reverse; }
.breadcrumb__sep { transform: scaleX(var(--dir,1)); }
html:dir(rtl). breadcrumb__sep { --dir: -1; }
Числа и суммы как LTR-фрагменты:
html
<span>الربح المحتمل: <bdi dir="ltr">2,000. 00 UAH</bdi></span>
Слайдер min→max для RTL:
css html:dir(rtl) input[type="range"] { direction: rtl; }
15) Антипаттерны
Жесткие `left/right` в стилях → ломается RTL.
Ввод чисел/IBAN/URL без `dir="ltr"` → «ломаный» caret и порядок.
Зеркалирование логотипов/графиков/часов.
Один и тот же набор иконок зеркалится всегда — без исключений по смыслу.
Карусели, листалки и пагинации не перевернуты.
Смешанные строки без BiDi-изоляции → «танцующие» символы.
16) Метрики
RTL coverage: доля экранов, прошедших RTL-ревью.
BiDi-дефекты/релиз: количество багов смешанного текста.
Время выполнения ключевых задач (LTR vs RTL): не должно отличаться >5–10%.
Ошибка ввода в формах чисел: доля событий с неверным caret/маской.
CLS/перф: без скачков макета при `dir`-переключении.
17) QA-чек-лист
Направление и макет
- `` для RTL-локалей; `:dir(rtl)` стили применяются.
- Логические свойства вместо `left/right`.
- Навигация/бредкрамбы/карусели/пагинация зеркалятся корректно.
Текст и BiDi
- Числа/валюты/URL/e-mail — `dir="ltr"` или ``.
- Нет «перевернутых» символов в смешанных строках.
- Локализованы даты/валюты через `Intl.`.
Формы
- Подписи справа; зоны клика ≥ 44×44 px.
- Телефон/IBAN/сумма — LTR caret, корректные маски.
- Слайдеры/минимумы/максимумы ведут себя ожидаемо.
Иконки/Изображения
- Зеркалятся только направленные; исключения соблюдены.
- Нет текста в картинках без локальных версий.
A11y/Перформанс
- `lang` выставлен; SR корректно читает.
- Нет лишних перерисовок при смене `dir`.
- Контраст/фокус-кольца соответствуют AA.
18) Документация в дизайн-системе
Раздел Direction & BiDi: политика зеркалирования, список исключений для иконок.
Набор RTL-токенов и линтер стилей (запрет `left/right`).
Галерея Do/Don’t: карусели, бредкрамбы, формы чисел, слайдеры, графики.
Скрипты псевдо-RTL и чек-листы ревью.
Краткое резюме
Правильная RTL-поддержка — это логические CSS-свойства, осознанное зеркалирование и строгая BiDi-изоляция. Изолируйте числа/URL в LTR, зеркальте навигацию и направленные иконки, держите формы предсказуемыми, а графики — читабельными. Так интерфейс для арабского, иврита, фарси или урду будет естественным и быстрым — от купона ставки и платежных форм до таблиц турниров и live-матчей.