Неверное направление стрелки в контекстах RTL

Это не имеет никакого отношения к настройкам bidi в Discourse.

Когда я ввожу ->, он преобразуется в символ стрелки , поэтому A -> B отображается как «A → B». Довольно круто.

Однако в тексте с направлением справа налево (RTL) стрелка указывает не в ту сторону: א -> ב отображается как «א → ב», причём стрелка направлена неверно. (Если вы читаете это в будущем, после исправления этой ошибки, здесь должно было быть отображено «א → ב»)

Обратите внимание, что последовательность входных символов здесь следующая:

Символ Название
א БУКВА ЕВРЕЙСКАЯ АЛЕФ
ПРОБЕЛ
- ДЕФИС-МИНУС
> ЗНАК БОЛЬШЕ
ПРОБЕЛ
ב БУКВА ЕВРЕЙСКАЯ БЕТ

Это можно проверить, скопировав строку א -> ב в этот инструмент: https://unicodedecode.com/

Это связано с тем, что в Unicode символы стрелок не поддерживают зеркальное отражение для bidi. Соответствующий документ: https://www.unicode.org/L2/L2022/22026r-non-bidi-mirroring.pdf

В частности, у каждого символа стрелки или похожего на стрелку часто есть зеркальный аналог. Можно было бы утверждать, что им следовало бы иметь свойство Bidi_Mirrored=Yes, но у них его нет, и сейчас его уже нельзя добавить.

К сожалению, не существует символа стрелки с зеркальным отражением для bidi, что означает: если вы хотите корректно выполнить эту замену, вам необходимо определить направление bidi окружающего текста, чтобы правильно выбрать между стрелками <- и ->. Это непростая задача.

1 лайк

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

Учитывая, что

Это означает, что нам придется реализовать новую функцию, так как в настоящее время мы следуем спецификации Unicode. Именно поэтому я перевел эту задачу в категорию #feature request (запрос на новую функцию).

Переходя к решению вашей проблемы, я думаю, что это можно легко реализовать в виде #theme-component, используя наш существующий API api.decorateCooked.

2 лайка

Спасибо. Я не спешу, чтобы это исправлено в каком-то конкретном форуме, я просто считаю, что это должно быть исправлено в Discourse.

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

Спасибо за ваше внимание и быстрый ответ :slight_smile:

1 лайк

Что ж… человек может сопротивляться лишь до определённого предела. Я скажу ещё одно последнее слово (обещаю). Насколько мне известно, спецификация Unicode не поощряет замену -> на (и эта проблема — одна из причин), поэтому существующая функция Discourse не соответствует никакой спецификации Unicode. Она делает ложное предположение о тексте и тем самым вносит эту ошибку. Так я это вижу. (Хотя сама функция всё равно интересная)

Теперь я всё сказал!

3 лайка

Если я печатаю на языке с правосторонним направлением текста, я мог бы надеяться, что после ввода «тире» и «меньше» оно преобразуется в стрелку влево, как здесь: ←. Это кажется мне разумным ожиданием. Однако при вводе символа «меньше» редактор вставляет символ «больше». Это совершенно неожиданно. Не является ли это ошибкой?

Я заметил, что текстовое поле с правосторонним направлением (например, поле поиска на aljazeera.net) вставляет числа и математические символы в порядке слева направо внутри текста с правосторонним направлением. Это кажется вполне естественным. (То же самое происходит и с латинскими буквами).

Ниже я введу фразу «меньше — это <, а больше — это >» в контексте с правосторонним направлением (не знаю, как именно это будет работать в локале с правосторонним направлением):

‮меньше — это <, а больше — это >

3 лайка

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

Это работает именно так, как и должно. Подумайте об этом так:

Символ > буквально означает «больше». Строка «A > B» означает «A больше B».

Аналогично, чтобы сказать «א больше ב», я заменю «больше» на тот же самый символ «больше» с тем же кодом U+003E. Однако, поскольку строка полностью направлена справа налево, «א» появляется справа от «ב». Если бы символ «больше» отображался так же, как и в направлении слева направо, это выглядело бы так: א<B, что читается как «א меньше ב» или «ב больше א» — то есть ровно обратное отношение тому, которое описывается.

Вот почему при отображении символа «больше» он визуально переворачивается в контексте справа налево. Но базовый символ и данные Unicode, стоящие за ним, по-прежнему являются символом «больше». Строка по-прежнему означает «א больше ב».

Теперь вернёмся к вашему первому вопросу:

Если вы измените раскладку клавиатуры на язык с направлением справа налево (например, иврит или арабский), то комбинация клавиш Shift+, (клавиша с напечатанным на ней символом <) на самом деле введёт символ «больше» >. В контексте справа налево, например в поле поиска, которое вы нашли, это отобразится как ‏>‏.

[Редактирование: следующий абзац был написан, когда я немного неправильно понял то, что вы сказали о проведённых вами тестах. Я думал, что вы вводите текст в поле справа налево с клавиатурой слева направо, а на самом деле вы делали наоборот. Надеюсь, я всё же ответил на ваш вопрос и развеял сомнения.]

Но вы всё ещё используете латинскую раскладку клавиатуры, поэтому при нажатии этой комбинации вставляется символ «меньше» <. Однако он отображается как ‏<‏, потому что в направлении справа налево это означает, что то, что справа, меньше того, что слева.

Итог: символ тот же самый, но его отображение зеркально отражается.

Если вы поняли всё, что я сказал до этого момента, то вы поймёте, что это привело бы к -< или, в контексте справа налево, ‏-<‏, что, я думаю, не то, что вы имели в виду.

Удалось ли мне всё объяснить, или я лишь ещё больше запутал вас?

1 лайк

Если вы считаете, что с официальными документами Unicode справитесь лучше, попробуйте этот: UAX #9: Unicode Bidirectional Algorithm Нажмите Ctrl+F, введите «mirror» (зеркальное отображение), и вы найдёте хорошие описания и примеры.

1 лайк

Вы абсолютно правы, я вмешиваюсь без опыта, да ещё и с латинской клавиатурой!

Так что мне, наверное, следовало бы молчать… но я заметил, что если я ввожу (на своей латинской клавиатуре) 3<6 в поле поиска Al Jazeera, то вижу вот это:

Что, вероятно, подтверждает вашу правоту и мою ошибку, и это не должно удивлять!

2 лайка

Ничего подобного! Если бы обсуждать и исправлять ошибки, связанные с написанием справа налево (RTL), могли только пользователи RTL, нам было бы гораздо хуже! Я просто воспользовался этим случаем, чтобы познакомить вас с этой темой. Чтобы во всём разобраться, нужно некоторое время. Я с радостью отвечу на любые ваши дополнительные вопросы или уточнения по этому поводу.

1 лайк

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

(От меня:) Проблема в том, что эта замена выполняется (насколько мне известно) вне какого-либо контекста рендеринга, когда текст представляет собой просто последовательность кодов символов. Невозможно разумно определить направление текста. Иногда это совершенно невозможно, если направление текста зависит от контекста, который недоступен во время замены.

Вышеизложенное строго говоря неточно. Любая серьёзная система рендеринга текста в наши дни требует движка формирования (shaping engine), такого как HarfBuzz, и связывание «->» в «→» выполняется именно таким движком в сотрудничестве со шрифтом, поддерживающим лигатуры. Движок формирования осведомлён о контексте bidi и скрипте текста, который он формирует, поэтому он мог бы в принципе отразить стрелку.

Они говорят о чём-то вроде этого: GitHub - tonsky/FiraCode: Free monospaced font with programming ligatures · GitHub

Рассмотрите возможность переключения на подход с лигатурами вместо слепой замены символов. Ещё одним спорным преимуществом было бы то, что при копировании и вставке текст оставался бы «->», а не превращался бы в стрелку.

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

Редактирование: ну, как и следовало ожидать, Fira Code, в частности, не предназначена для работы с RTL, поэтому рендеринг не идеален — но хотя бы она указывает в правильном направлении! https://fonts.google.com/specimen/Fira+Code?preview.text=A%20->%20B,%20א%20->%20ב
Firefox:

Не уверен, существует ли сегодня шрифт, который делает это правильно и явно поддерживает RTL/bidi.

1 лайк

Интересно, в Chromium я получаю другой результат:
Редактирование: сейчас я не могу воспроизвести это, так что, вероятно, я ошибся при вводе, когда делал этот скриншот.
Редактирование: и теперь я снова могу воспроизвести это. Ситуация серьёзная.

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

Редактирование: ограничения форума заставили меня удалить это из моего предыдущего ответа:
Для справки, вот код, отвечающий за эту замену:

1 лайк

Как я уже упоминал, я работаю над предложением решения этой проблемы с использованием Unicode. В нём я подробно и, надеюсь, более ясно, чем здесь, объясняю суть вопроса. Работа ещё не завершена, но, пожалуйста, ознакомьтесь с ней: Create [<message>] git stash create. (постоянная ссылка)

В частности, обратите внимание на раздел о Discourse.

Конечно, даже если Unicode примет это предложение (когда я в конечном итоге его представлю), на его широкое и надёжное внедрение уйдут годы, поэтому ждать этого — не лучшее решение.