Dir html что это
Справа налево. Что такое dir=rtl и как приручить арабский язык
Привет, Хабр. Мы недавно перевели на арабский язык 2ГИС Онлайн, и хотим поделиться своим опытом адаптации интерфейса под RTL (right-to-left). Это будет актуально и для иврита, и для персидского языка.
Я разделю этот опыт на две статьи — теоретическую и практическую. Сегодня — больше про теорию. Я расскажу, зачем нам понадобилось переворачивать весь интерфейс, что для разработчика интерфейсов значит фраза «сделать арабскую версию» и как справиться с арабским языком, смешанным с английским. Особое внимание уделю алгоритму, по которому строится отображение текста смешанной направленности — unicode bidirectional algorithm.
Зачем это всё?
Кажется, ценность в адаптации интерфейса под «справа налево» такая же, как у адаптации на любой другой популярный язык, но это не совсем так.
Различие между английской и русской версией небольшое — чаще всего, это просто переведёный текст. Пользовательский опыт, за исключением редких мелочей, в целом не отличается. Различие же между арабской и английской версией огромное.
Всего 0.6% интернет-ресурсов в мире содержат арабский контент. Однако, на арабском говорит больше 5% пользователей интернета, и эта доля стремительно растёт. Привычное направление чтения для них — справа налево. Какие ощущения у них от современного веба? Точно такие же, как у носителя русского языка при пользовании RTL–интерфейсом. Выбери себе метафору сам — может, это как садиться за руль праворульной машины, когда постоянно водишь леворульную. Или как зайти однажды в 2ГИС и увидеть, что карточки и поиск — справа:
Если мы хотим, чтобы наш сервис был максимально удобным для всех пользователей, адаптировать его под RTL нужно обязательно.
В чём состоит задача?
С первого взгляда она мне показалась необъятной — нужно переделать весь интерфейс под требования, которые никто не сможет нормально объяснить.
Посмотрев несколько примеров арабских сайтов, я понимаю, что сделать арабскую версию — это:
С переводами вроде всё понятно. С переворачиванием интерфейса — ничего не понятно. Остановимся на этом подробнее.
Первым делом я добавил тегу html атрибут dir=»rtl»:
Всё изменилось, но не совсем так, как я ожидал. Я осознал, что совсем не понимаю, что происходит. По какому принципу выстраиваются элементы друг за другом?
Базовое направление (base direction)
Рассмотрим один и тот же простой кусок вёрстки в LTR и RTL. Он не очень осмысленный, но наглядный:
Как видно на скриншоте, атрибут dir (как и css-свойство direction ) задаёт:
Элементы поменяли порядок, но символы в словах всё равно расположены как обычно. Потому что порядок символов в строке определяется другим алгоритмом.
Последовательность символов внутри строки
Физически в строке символы расположены последовательно, но за итоговое отображение этой последовательности на экране отвечает unicode bidirectional algorithm.
На направленность каждого символа влияет его тип и направленность соседних символов.
Три типа символов
1) Сильно направленные (или строго типизированные, strongly typed) — например, буквы. Их направленность заранее определена — для большинства символов это LTR, для арабских и иврита — RTL.
Слова на картинке целиком строго типизированы:
2) Нейтральные — например, знаки пунктуации или пробелы. Их направленность не задана явно, они направлены так же, как соседние сильно направленные символы.
Запятая между направленными слева направо «o» и «w» в строке «Hello, world» принимает их направленность и при базовом LTR, и при RTL:
Но что, если нейтрально направленный символ попадает между двумя сильно направленными символами разной направленности? Такой символ принимает базовую направленность.
Вот тут расположение «++» в одном случае между однонаправленными «C» и «a», а в другом — между разнонаправленными «C» и арабским «و», приводит к разному результату:
То же самое случается с нейтральными символами в конце строки:
3) Слабо направленные (или слабо типизированные, weakly typed) — например, числа. Они имеют свою направленность, но никак не влияют на окружающие символы.
Непрерывные слова из цифр выстраиваются слева направо, но два числа подряд, разделённые нейтральным символом, будут идти друг за другом справа налево, если задана базовая RTL–направленность:
Ещё более наглядный случай — число, в котором разряды разделены пробелом:
При этом допускается разделять числа точкой, запятой, двоеточием — эти разделители тоже слабо направлены (подробнее можно посмотреть в спецификации):
Направленные блоки (directional run)
Последовательные символы одинаковой направленности объединяются в блоки (directional run). Эти блоки выстраиваются друг за другом в порядке, определённым базовым направлением:
Слабо направленные числа, несмотря на то, что имеют свою направленность, не влияют на формирование блоков, что может приводить к такому результату — они продолжают предыдущий направленный блок:
Зеркальные символы
Некоторые символы в разных контекстах имеют разную форму — например, открывающая скобка в RTL будет выглядеть как закрывающая в LTR (что логично, ведь контент в скобках будет идти после — то есть, слева от неё).
В большинстве случаев это не создаёт проблем, но если скобки случайно окажутся разной направленности, визуально они будут смотреть в одну сторону. Например, если скобка висит в конце строки:
Берём порядок под контроль
Как мы увидели выше, часто текст по этим правилам форматируется не так, как нам хотелось бы.
В этом случае нам пригодятся инструменты для встраивания желаемого направления в существующий контекст или переопределения направлений конкретных символов.
Изоляция (isolate)
С заданием базового направления мы уже познакомились выше: это делает атрибут dir. Это глобальный атрибут, он применим к любому элементу.
dir создаёт новый уровень встраивания (embedding level) и изолирует содержимое от внешнего контекста. Контент внутри направлен согласно значению атрибута, а внешняя направленность самого контейнера становится нейтральной.
Явная установка атрибута dir позволяет избежать почти всех проблем форматирования смешанного текста:
Если направленность контента неизвестна заранее, можно указать auto в качестве значения атрибута dir. Тогда направление содержимого определится с помощью «некоторой эвристики» — оно просто возьмётся у первого попавшегося строго типизированного символа.
Аналогично работает тег и css-правило unicode-bidi: isolate :
Встраивание (embed)
Можно открыть новый уровень встраивания без изоляции — правило unicode-bidi: embed в комбинации с нужным значением правила direction определяют и направление внутри элемента, и его направленность снаружи. Но это на практике не нужно почти никогда.
Переопределение (override)
Управляющие символы (marks)
Вставка управляющих символов — неприятный способ, но он полезен, когда у нас нет доступа к разметке, но есть доступ к контенту. Например, это могут быть просто невидимые сильно направленные символы, и ( / или \u200e / \u200f ). Они помогают задать нужное направление нейтральному символу.
Например, в этом случае, чтобы восклицательный знак в конце строки принял направление LTR, нужно, чтобы он находился между двумя LTR символами:
Также любая описанная выше логика реализуется через управляющие символы. Для изоляции — LRI/RLI, для переопределения — LRO/RLO, и т.д. — смотри подробное руководство по управляющим символам.
Поддержка браузерами
HTML или CSS?
Перед заключением: немного боли
Мы познакомились с теорией. Но знание теории не освобождает от необходимости страдать.
Главная проблема, с которой я столкнулся на первых же минутах разработки под RTL–язык, это его чужеродность. Мы пишем код слева направо. Моя система, браузер и редактор работают слева направо, все наши внутренние продукты — слева направо. Поэтому, как только в это пространство попадает арабский язык, всё плохо и больно:
Манипуляции с текстом
Если символы на экране расположены не в том порядке, в каком они на самом деле располагаются в строке, что будет, если попытаться редактировать двунаправленный текст? Или хотя бы выделить и скопировать его часть?
Ничего хорошего. Попробуйте сами:
Landmarks: دبي مارينا مول — 600 m, داماك العقارية — 1.2 km
azbycxdwevfugthsirjqkplomn
Манипуляции с кодом
И то же самое при правке кода в редакторе и код-ревью — боль.
Даже в порядке элементов в массиве нельзя быть уверенным:
Или того хуже, код вообще не выглядит валидным:
Снова берём всё под контроль
В любой ситуации есть только один источник правды — логическое расположение символов в строке. Символы могут быть расположены визуально правильно в редакторе или в почтовом клиенте, но на итоговой странице правильно их расположить не получится, потому что логический порядок нарушен.
Посмотреть, как изначально расположены символы в строке и почему они визуально расположились именно так, позволяет инструмент на сайте Юникода: http://unicode.org/cldr/utility/bidi.jsp
Итого
Мы познакомились с правилами, по которым определяется порядок элементов и порядок символов в строке, и узнали, как можно на него влиять.
Что нужно обязательно помнить:
На практике вся эта теория выливается в одно простое правило:
Также нужно готовиться к тому, что в редакторе текст может выглядеть не совсем так, как будет выглядеть в браузере. И это обязательно причинит тебе боль.
Что дальше?
В следующей статье я расскажу о нашем практическом опыте. Как быстро сделать прототип RTL-версии и какие выбрать решения для продакшна. Как быть заранее готовым, но какие моменты невозможно предусмотреть.
Атрибут dir
Атрибут dir используется для указания направления движения текста (слева направо или справа налево), язык которого является основным для данного элемента. Это бывает нужно в тех случаях, когда в тексте присутствуют фразы из разных языков, у которых направление письма различается, например арабский или персидский языки имеют письменность справа налево.
Атрибут dir появился в HTML довольно давно, но раньше он поддерживался ограниченным количеством тегов, а теперь он есть у всех. Поэтому, если на страницах описания каких-то тегов вы увидите логотип HTML 5 () напротив атрибута, то знайте, что этот тег начал поддерживать атрибут dir именно с версии HTML 5. Впрочем, таких тегов очень мало. C другой стороны, хоть в HTML 5 теперь все теги могут иметь этот атрибут — не факт, что браузеры его будут также понимать во всех случаях. Более того, в описаниях W3C также нет конкретики по данному вопросу, например о том, для чего использовать dir в тегах
.
Итак, атрибут dir сообщает браузеру о том, какое направление письма имеет язык, для которого, в сущности, предназначен текст внутри данного HTML-элемента. Основываясь на этих данных браузер, применив двунаправленный алгоритм, решит, в каком направлении будет правильней вывести основной текст на странице, а какие слова в коде текста перевернуть, если они написаны на языке с направлением письменности отличным от основного языка.
Кстати, программы с двунаправленным алгоритмом «вшиты» не только в браузеры, но и, допустим, в почтовые клиенты (Outlook, Bat и т.д.), а также во многие другие приложения работающие с текстом.
Допустим в коде страницы есть параграф содержащий текст на русском и арабском языках, обозначим слова на русском, как «русский1», «русский2», «русский3», а слова на арабском, как «арабский1», «арабский2», «арабский3». Я использовал именно такое обозначение арабских слов из-за того, что настоящие слова на этом языке довольно сложны для восприятия русскоговорящего населения.
Пример части кода HTML:
Пример со значением dir=»ltr» (слева направо):
Результат в браузере
русский1 1йиксбара русский2 2йиксбара русский3 3йиксбара
В этом примере атрибут dir сообщил браузеру то, что основной язык имеет направление слева направо, поэтому он и сохранил такой стиль письма, а арабские слова просто перевернул так, как этого требует данный язык.
Теперь рассмотрим другой пример.
Пример со значением dir=»rtl» (справа налево):
Результат в браузере
3йиксбара русский3 2йиксбара русский2 1йиксбара русский1
В данном примере атрибут dir указал браузеру то, что основной язык элемента имеет направление справа налево, поэтому он полностью перевернул всю строку. Но так как браузер нашел в тексте русские слова, то, используя свой двунаправленный алгоритм, он вычислил, что они пишутся слева направо, поэтому он так их и вывел.
Еще раз обращаю ваше внимание на то, что указанные выше примеры были всего лишь имитацией действия двунаправленного алгоритма, чтобы увидеть его реальную работу необходимо использовать настоящие слова из языков имеющих разное направление письма.
Значения
Значением атрибута dir является одно из ключевых слов, задающих направление текста.
Значение по умолчанию: ltr.
Синтаксис
Обязательный атрибут: нет.
Пример HTML: применение атрибута dir
Результат: Применение атрибута dir.
, то вся вторая строка примера сместилась бы вправо.
Спецификация HTML 4.01
Содержание
В этом разделе обсуждаются два важных вопроса, которые влияют на интернационализацию HTML: спецификация языка (атрибут lang ) и направление (атрибут dir ) текста в документе.
8.1 Спецификация языка содержимого: атрибут lang
Атрибут lang определяет язык содержимого элемента и значений атрибутов. Относится ли это к соответствующему атрибуту, зависит от синтаксиса и семантики атрибута и выполняемой операции.
Например, если символы греческого алфавита появляются в окружении английского текста:
ПА должен
(1) попытаться представить английское содержимое соответствующим образом (например, при обработке знаков кавычек) и
(2) обязан попытаться представить символ γ наилучшим образом, несмотря на то, что этот символ не является английской буквой.
См. дополнительную информацию в разделе неотображаемые символы.
8.1.1 Коды языка
Значением атрибута lang является код языка, идентифицирующий язык, используемый людьми для разговора, письма и других видов общения. Компьютерные языки исключены из кодов языка.
[RFC1766] определяет и разъясняет коды языка, которые должны использоваться в документах HTML.
Если говорить кратко, коды языка состоят из первичного кода и, возможно пустых, серий субкодов:
Вот примеры кодов некоторых языков:
Двухсимвольные первичные коды зарезервированы для аббревиатур [ISO639].
Двухсимвольные коды включают fr (французский), de (немецкий), it (итальянский), nl (фламандский), el (греческий), es (испанский), pt (португальский), ar (арабский), he (еврейский), ru (русский), zh (китайский), ja (японский), hi (хинди), ur (урду) и sa (санскрит).
Любые двухбуквенный субкод понимается как код страны в [ISO3166].
8.1.2 Наследование кодов языка
Элемент наследует информацию кода языка в следующем порядке (приоритет от высшего к низшему):
8.1.3 Интерпретация кодов языка
Примечание. Иерархии кодов языка не гарантируют, что все языки с обычным префиксом будут свободно пониматься, но они (иерархии) позволяют пользователю запрашивать эту сообщность, если для пользователя это является верным.
8.2 Спецификация направления в тексте и в таблицах: атрибут dir
Спецификация [UNICODE] назначает направление символам и определяет (сложный) алгоритм для определения соответствующего направления текста. Если документ не содержит отображаемых справа-налево символов, то от соответствующего ПА не требуется применять двунаправленный алгоритм [UNICODE]. Если документ содержит отображаемые справа-налево символы и если ПА отображает эти символы, ПА обязан использовать двунаправленный алгоритм.
чем то же самое в мнемониках Unicode:
ПА не должны использовать атрибут lang для определения направления текста.
Атрибут dir наследуется и может быть переопределён. См. детали в разделе информация о наследовании направления текста.
8.2.1 Двунаправленный алгоритм. Введение.
Следующий пример иллюстрирует ожидаемое поведение двунаправленного алгоритма. Он включает английский, скрипт слева-направо, и еврейский языки, скрипт справа-налево:
В этом случае, всё предложение представлено как текст справа-налево, и внедрённая последовательность символов на английском соответствующим образом повёрнута с помощью двунаправленного алгоритма.
8.2.2 Наследование информации о направлении текста
Если атрибут dir установлен для элементов уровня блока, он действует на период существования самого элемента и всех вложенных элементов уровня блока. Установка атрибута dir во вложенном элементе переопределяет наследованное значение.
8.2.3 Установка направления внедрённого текста
Двунаправленный алгоритм [UNICODE] автоматически поворачивает внедрённые последовательности символов в соответствии с их унаследованным направлением (как показано в предыдущих примерах). Однако в целом только один уровень внедрения может быть просчитан. Чтобы установить дополнительные уровни внедрённых изменений направления, придётся использовать атрибут dir в инлайн-элементах.
Рассмотрим тот же текст, что и ранее:
Предположим, преобладающим языком документа, содержащего этот параграф, является английский. С другой стороны, это предложение на английском содержит раздел на еврейском от HEBREW2 до HEBREW4, и раздел на еврейском содержит в себе английский (english3). Нужное представление предложения таково:
Чтобы выполнить два изменения направления, мы должны предоставить дополнительную информацию путём явного разграничения. В этом примере мы используем элемент SPAN и атрибут dir для разметки текста:
Авторы могут также использовать специальные символы Unicode для выполнения множественных внедрённых изменений направления текста. Для получения внедрения «слева-направо», окружите внедряемый текст символами LEFT-TO-RIGHT EMBEDDING («LRE», 16-ричная 202A) и POP DIRECTIONAL FORMATTING («PDF», 16-ричная 202C). Для получения внедрения «справа-налево», окружите внедряемый текст символами RIGHT-TO-LEFT EMBEDDING («RTE», 16-ричная l 202B) и PDF.
Использование разметки направления HTML с символами Unicode. Авторы и разработчики авторских программных продуктов должны знать, что конфликты могут увеличиться, если атрибут dir в инлайн-элементах (включая BDO ) соседствует с символами форматирования [UNICODE]. Лучше использовать то или другое. Метод разметки даёт больше гарантии структурной целостности документа и облегчает решение некоторых проблем при редактировании двунаправленного текста HTML в простом текстовом редакторе, но некоторые программы могут быть более адаптированы к использованию символов [UNICODE]. Если используются оба метода, нужно быть очень внимательным, устанавливая вложенную разметку и внедрённые изменения направления, иначе результаты отображения могут быть непредсказуемыми.
8.2.4 Переопределение двунаправленного алгоритма: элемент BDO
Начальный тег: необходим, Конечный тег: необходим
Атрибут, определённый в другом месте
Двунаправленного алгоритма и атрибута dir обычно достаточно для обслуживания внедрённых изменений направления. Однако, в некоторых ситуациях двунаправленный алгоритм может быть причиной некорректного представления. Элемент BDO позволяет авторам отключить двунаправленный алгоритм в определённом фрагменте текста.
Рассмотрим документ, содержащий текст:
и представим, что этот текст уже выведен в таком визуальном порядке. Причиной этого может быть то, что стандарт MIME ([RFC2045], [RFC1556]) отдаёт преимущество визуальному расположению, т.e. что последовательности текста «справа-налево» вставляются справа-налево в потоке байтов.
В email этот пример может быть сформатирован с включением символов новой строки:
Это конфликтует с двунаправленным алгоритмом [UNICODE], поскольку этот алгоритм повернёт 2WERBEH, 4WERBEH и 6WERBEH вторично, отображая еврейские слова слева-направо вместо справа-налево.
Это говорит двунаправленному алгоритму «Оставь меня слева-направо!» и должно создать желаемое представление:
Элемент BDO должен использоваться в конструкциях, где нужен полный контроль за порядком расположения (напр., несколько многоязычных частей). Наличие атрибута dir для этого элемента обязательно.
Примечание. Напоминаем, что может увеличиться количество конфликтов, если атрибут dir в инлайн-элементах (включая BDO ) соседствует с символами форматирования [UNICODE].
Поскольку HTML использует двунаправленный алгоритм Unicode, соответствующие документы, кодированные с использованием ISO 8859-8, должны быть помечены как «ISO-8859-8-i». Явный контроль направления также возможен в HTML, но он не может быть выражен в ISO 8859-8, так что «ISO-8859-8-e» не должен использоваться.
Значение «ISO-8859-8» подразумевает, что документ сформатирован визуально, с потерей некоторой разметки (такой как TABLE с правым выравниванием и запретом переноса слов), чтобы обеспечить верное отображение в более старых ПА, не обрабатывающих двунаправленность. Такие документы не соответствуют настоящей спецификации. При необходимости они могут быть оформлены в соответствии с настоящей спецификацией (и одновременно будут корректно отображаться в более старых ПА) путём добавления разметки BDO там, где это необходимо. В противоположность уже сказанному в [RFC1555] и [RFC1556], ISO-8859-6 (арабский язык) визуально не упорядочивается.
8.2.5 Символьные мнемоники для указания направления и управление сращиванием
Поскольку иногда возникают двусмысленные ситуации при установке направления определённых символов (напр., знаки препинания), спецификация [UNICODE] содержит символы для соответствующего разрешения таких ситуаций. Также Unicode включает некоторые символы управления поведением сращивания там, где это необходимо (напр., некоторые ситуации с арабскими буквами). HTML 4 включает символьные ссылки-мнемоники для таких символов.
Следующий отрывок ОТД представляет некоторые мнемоники направления:
Мнемоника zwnj используется для блокировки сращивания в контексте, когда сращивание есть, но нежелательно.
Мнемоника zwj действует наоборот: она форсирует сращивание, когда его не должно быть, но оно необходимо. Например, арабская буква «HEH» используется как сокращение от «Hijri», названия исламской календарной системы. Поскольку изолированно форма «HEH» похожа на цифру пять, как принято в арабском письме (на базе индийской нумерации), для предотвращения конфликтов «HEH» с конечной цифрой пять в обозначении года используется начальная форма «HEH». В то же время, отсутствует контекст (т.е. сращивание букв), к которому «HEH» можно присоединить. Символ zwj обеспечивает такой контекст.
Также в персидских текстах встречаются случаи, когда буквы, которые обычно могут сращиваться с последующими, в курсивном соединении не делают этого. Символ zwnj используется для блокировки сращивания в таких случаях.
«Зеркальные» глифы символов. Вообще двунаправленный алгоритм не отражает «зеркально» глифы символов, а оставляет их без воздействия. исключение составляют символы, такие как скобки (см. [UNICODE], таблица 4-7). В тех случаях, когда зеркальное отражение необходимо, например, для египетских иероглифов или греческих Bustrophedon, или для достижения специальных дизайнерских эффектов, этим можно управлять с помощью стилей.
8.2.6 Действие таблиц стилей на двунаправленность
В целом, использование таблиц стилей для изменения визуального представления элементов с уровня блока на инлайн и наоборот является более прямым путём. Однако, поскольку двунаправленный алгоритм основывается на различении уровней блок/инлайн, необходимо особое внимание при обеспечении трансформации.