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

Локализация в Spotify — важное дело. Наша миссия состоит в том, чтобы «раскрыть потенциал человеческого творчества, предоставляя миллионам музыкантов возможность зарабатывать своим искусством на жизнь, а миллиардам поклонников — наслаждаться и вдохновляться им». Для достижения этой миссии важно, чтобы пользователи из разных стран могли эффективно общаться на своих языках. Недавно мы запустили Spotify в регионах Северной Африки и Западной Азии. Одним из языков в этих регионах является арабский. В отличие от английского, арабский читается справа налево. Это сказывается на веб-сайтах, которые хотят поддерживать арабский язык.

Оглавление



В статье будем использовать следующие аббревиатуры:

LTR (Left To Right): текст, который читается слева направо, например, английский или испанский.
RTL (Right To Left): текст, который читается справа налево, например, арабский.

Макет зеркального отображения


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

Как работает атрибут dir


Направление текста в элементе браузеру сообщает атрибут dir. Чтобы задать глобальное направление страницы, необходимо задать атрибут dir для всей страницы.

Значения атрибута:

  • ltr — используется для письма слева направо (например, английский, шведский). Это значение по умолчанию.
  • rtl — используется для письма справа налево (например, арабский, иврит, персидский).
  • auto — используется для динамического содержимого. Браузер сам выбирает направление. Для обработки элементов и определения направления используется алгоритм Unicode Bidirectional Algorithm. Подробнее см. в разделе «Английский язык в формате RTL».

CSS


И CSS Flexbox, и CSS Grid смотрят на атрибут dir, чтобы определить направление элемента. Например, flex-start автоматически переключается на RTL, когда атрибут dir установлен в "rtl".

Но атрибута dir с использованием flexbox или grid может быть недостаточно для отражения всего пользовательского интерфейса на RTL. Слишком много асимметричных свойств CSS, за которыми нужно следить при разработке веб-сайта, поддерживающего как LTR, так и RTL. Например margin-left: 20px и text-align: right в RTL поменяются и станут margin-right: 20px и text-align: left.

Есть много инструментов для автоматизации этой работы. Мы выбрали PostCSS-RTL, который на этапе сборки генерирует правила RTL с «перевёрнутыми» свойствами.

.foo {
  margin-left: 15px;
  text-align: right;
  color: rebeccapurple;
}

Вход CSS

[dir] .foo {
  color: rebeccapurple;
}

[dir="ltr"] .foo {
  margin-left: 15px;
  text-align: right;
}

[dir="rtl"] .foo {
  margin-right: 15px;
  text-align: left;
}

Вывод CSS

Иконки


Иконки и элементы, имеющие направление или связанные с прогрессом, следует перевести в RTL. Например, кнопки навигации назад и вперёд нужно поменять местами.


Кнопка «Назад» в LTR


Кнопка «Назад» в RTL (вместо арабского используется английский текст)

Все анимации с направлением движения тоже надо перевернуть. Например, карусели должны скользить в другую сторону.



Исключения


Изначально мы предполагали, что всё будет зеркально. Но довольно быстро увидели некоторые исключения. Например, кнопки воспроизведения мультимедиа и индикатор выполнения не требуют зеркального отображения, поскольку они относятся к направлению проигрываемой ленты. Арабоязычные пользователи ожидают, что элементы управления воспроизведением и индикатор выполнения будут выглядеть так же, как и на языке LTR.


Индикатор воспроизведения в LTR

Английский язык в формате RTL


Нередко на одной странице смешиваются тексты LTR и RTL. На Spotify более 40 миллионов песен музыкантов со всего мира и более 3 миллиардов плейлистов. Контент представлен на многих языках для пользователей со всего мира. Поэтому в клиентах Spotify контент LTR и RTL часто смешивается.

(Hello (World: проблема пунктуации и скобок


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


Проблема скобок

Такое происходит, потому что браузер задаёт базовое направление текста исходя из значения атрибута dir нашего элемента. Знаки препинания, такие как ( ) . ! и остальные, не описываются направлением в Unicode. Они наследуют базовое направление текста.

Двунаправленный алгоритм Unicode Bidirectional Algorithm рассматривает каждый символ в строке справа налево. В качестве примера возьмём на странице строку "Hello (World)".

  • Алгоритм начинает разбор строки справа. Он видит ненаправленный символ ), поэтому смотрит на базовое направление текста и видит, что текст идёт справа налево. Алгоритм решает перенести ) в начало строки.

        “Hello (World)” -> “(Hello (World”
  • Алгоритм видит d с направлением LTR. Его не нужно перемещать. То же самое касается других английских символов вплоть до (.
  • Алгоритм видит ( без направления. Он помнит преобладающее базовое направление (заданное предыдущим символом W) слева направо. Алгоритм решает не перемещать (. То же самое касается пробела и всех символов в "Hello”

Подробнее о том, как работает Unicode Bidirectional Algorithm, см. здесь.

В итоге мы получаем строку "(Hello (World". Мы решили эту проблему, указав значение auto для атрибута dir во всём динамическом контенте, например, в именах исполнителей, названиях альбомов и песен. Это изолирует содержимое и задаёт базовое направление в соответствии с первым строго типизированным символом направления. В этом случае ненаправленные символы всегда будут наследовать направление от окружающих символов, а не страницы. Поэтому получится строка "Hello (World)". Для соблюдения корректного выравнивания используйте атрибут только для встроенных элементов inline, иначе придётся добавлять в элементы свойство text-align.

...ello World: проблема с усечением


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


LTR UI: арабский текст, усечённый с неправильной стороны


RTL UI: английский текст, усечённый с неправильной стороны

Усечение происходит с неправильной стороны, потому что браузер задаёт направление текста из атрибута dir. Проблему решает установка атрибута "auto" для элемента с усечённым текстом.


LTR UI: арабский текст, усечённый с правильной стороны


RTL UI: английский текст, усечённый с правильной стороны

Арабское письмо


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

Межсимвольный интервал


Арабское письмо — это вязь. Большинство, если не все символы в слове связаны друг с другом. По этой причине в арабском не следует использовать межсимвольный интервал. Он разрывает символы, нарушая естественную вязь.

Размер шрифта


Как правило, у арабских символов более сложные глифы, чем у английских. Там больше линий и нюансов, которые должны вписаться в такое же пространство. Из-за этого арабское письмо с тем же размером шрифта менее разборчивое, чем английский язык. Символы слишком маленькие. Мы решили увеличить минимальный размер шрифта на арабском языке с 11 до 12px. Мы также убедились, что шрифт не усложняет арабские глифы. Хорошим выбором будет Google Noto, который более разборчив, чем Arial — резервный шрифт по умолчанию для арабского языка в браузере.

Вертикальная обрезка


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


Вертикальная обрезка

Заглавные буквы


В арабском нет заглавных букв, поэтому нет смысла что-то выделять прописными буквами на странице.

Арабские запятые


Во многих языках в качестве запятой используется ,. В арабском языке другой разделитель: ?.

У нас в коде часто встречалась команда array.join(‘, ‘). Для поддержки разных разделителей в зависимости от языковых настроек пользователя мы добавили метод getSeparator().

Цифры на арабском


На арабском языке две системы цифр

  • Западные арабские цифры: 0 1 2 3 4 5 6 7 8 9
  • Восточные арабские цифры: ? ? ? ? ? ? ? ? ? ?

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

Прозрачный цвет текста


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


Проблема прозрачности

Стандарты качества


Вот некоторые вещи, которые мы сделали, чтобы качественно внедрить арабский язык:

  • Тестовые сессии в команде
  • Бета-тест с арабоязычными сотрудниками
  • Тест UI и переводов внешними агентствами.

Чтобы обеспечить качество арабского UI, понадобились некоторые инструменты.

Мы решили создать бота GitHub. Он публикует комментарии на пул-реквесты, которые соответствуют потенциальным проблемам. Комментарий ничего не навязывает: это просто напоминание проверить, как изменение повлияет на арабский язык, со ссылкой на инструкции по тестированию. Бот комментирует изменённые строки, соответствующие заполнению, межсимвольному интервалу, преобразованиям и т. д. Код CSS конвертируется PostCSS-RTL, поэтому обычно достаточно взглянуть на изменение на арабском языке и убедиться, что оно выглядит хорошо. Свойства CSS можно устанавливать через JS, а PostCSS-RTL не преобразует JS. Бот же проверяет JS-файлы и комментирует их тоже, если там встречаются соответствующие свойства.


Комментарий tob-bot

Полезные источники


  1. Material Design – двунаправленность
  2. Методы интернационализации: авторинг HTML & CSS
  3. Авторинг HTML: письменность справа налево
  4. Сравнительный анализ арабского и персидского языков
  5. ECMAScript Internationalization API

Комментарии (3)


  1. defint
    29.04.2019 21:56

    Еще интересный кейс с форматированием чисел.
    Допустим вам надо вывести миллион в виде: 1 000 000. При dir=«rtl» получите — 000 000 1, хотя все числа на арабском не должны никак трансформироваться.
    Особенно сложно отлавливать, когда изначально разделитель был ",".


  1. tyomitch
    30.04.2019 13:45

    На арабском языке две системы счисления

    Это не «системы счисления». Система счисления одна и та же, десятичная; различаются обозначения цифр. И всё это не имеет отношения к арабскому языку — это чисто типографские традиции.
    (В оригинале статьи та же некорректная формулировка.)


  1. tyomitch
    30.04.2019 18:14

    И ещё одно дополнение.
    В статье всё время речь идёт об арабском языке, когда на самом деле имеется в виду арабское письмо.
    Арабское письмо используется, кроме арабоязычных, ещё примерно четвертью миллиарда человек — в Иране, Афганистане, Пакистане и Синьцзяне. Как-то некрасиво ими всеми пренебрегать.
    И вот у этих неарабоязычных пользователей арабского письма есть свои собственные варианты арабских цифр.