RTL 텍스트 환경에서 화살표 방향이 잘못됨

이 문제는 Discourse의 bidi(양방향 텍스트) 설정과는 전혀 관련이 없습니다.

->를 입력하면 화살표 문자 로 변환되어, A -> B가 "A → B"로 표시됩니다. 꽤 멋진 기능이죠.

하지만 RTL(오른쪽에서 왼쪽으로 읽는) 텍스트에서는 화살표 방향이 잘못 표시됩니다. א -> ב를 입력하면 화살표 방향이 반대인 "א → ב"로 렌더링됩니다. (이 버그가 수정된 후 이 글을 읽는다면, 원래는 "א → ב"로 렌더링되었습니다.)

여기서 입력된 문자열의 문자 시퀀스는 다음과 같습니다:

문자 이름
א HEBREW LETTER ALEF
SPACE
- HYPHEN-MINUS
> GREATER-THAN SIGN
SPACE
ב HEBREW LETTER BET

이 문자열 א -> בhttps://unicodedecode.com/ 도구로 복사하여 붙여넣으면 확인할 수 있습니다.

이는 화살표 문자가 Unicode에서 bidi 미러링(bidi-mirror)을 하지 않기 때문입니다. 관련 문서: https://www.unicode.org/L2/L2022/22026r-non-bidi-mirroring.pdf

특히, 화살표 및 화살표 모양의 문자는 각각 대칭 문자가 있는 경우가 많습니다. Bidi_Mirrored=Yes 속성 값을 가졌어야 한다고 주장할 수도 있지만, 실제로는 그렇지 않으며, 이제 그 값을 부여할 수도 없습니다.

불행히도 bidi 방향에 따라 자동으로 반전되는 화살표 문자가 존재하지 않습니다. 즉, 이 치환을 올바르게 수행하려면 주변 텍스트의 bidi 방향을 결정하여 <-와 → 화살표 중 올바른 것을 선택해야 합니다. 쉬운 작업이 아닙니다.

1개의 좋아요

@falco I would argue that this is indeed a bug, not a feature request. The output is the exact opposite of user intentions and expectations.

다음과 같이

즉, 우리는 현재 유니코드 사양을 따르고 있으므로, 새로운 기능을 구축해야 합니다. 그래서 이를 Contribute > Feature 요청으로 재분류했습니다.

실제로 문제를 해결하는 것에 대해 말씀드리자면, 기존 api.decorateCooked API를 사용하여 #customization:theme-component에서 쉽게 수행할 수 있다고 생각합니다.

2개의 좋아요

Thanks. I’m in no hurry to get it fixed in any particular forum, I just think this should be fixed in Discourse.

I don’t want to get into a pointless argument about semantics, so I’ll leave it at that. I’ve said what I have, I think this should be considered a bug, but what you do with that is up to you now.

Thanks for your attention and quick response :slight_smile:

1개의 좋아요

Well… A man can only resist so much. I will say one last thing (I promise). As far as I’m aware, the Unicode spec does not encourage converting -> to (and this issue would be one reason why), so this existing Discourse feature is not following any Unicode spec. It makes a false assumption about text and introduces this bug in the process. That’s how I see it. (The feature is still neat though)

Now I’ve said what I have!

3개의 좋아요

If I’m typing in a right-to-left language, I could hope to type ‘dash‘ followed by ‘less than’ and expect it to convert to a leftward arrow, like this: ← . That seems a reasonable expectation to me. But, when I type a less-than, the composer inserts a greater-than. This was quite unexpected. Is that the bug??

I notice a RTL text box (such as the search box on aljazeera.net) inserts numbers and maths symbols in LTR order within the RTL text. This seems natural enough. (It does the same for latin alphabetics)

Below I will type “less than is < and greater than is >” in a RTL context (I don’t know if this is how things would work in a RTL locale):

‮less than is < and greater than is >

3개의 좋아요

You don’t use a right-to-left script in everyday life, right? There is no bug in what you described. There is some ambiguity in what you said so to prevent confusion I will address the second part of your comment first.

This is exactly how it’s supposed to work. Think of it this way:

The character > literally means “greater than”. The string “A > B” means “A is greater than B”.

Similarly, to say “א is greater than ב” I would replace “is greater than” with the same greater-than character with the same code U+003E. However, because the string is entirely RTL, “א” appears to the right of “ב”. If the “greater than” character was rendered the same as LTR, it would show: א<ב which reads as “א is less than ב” or “ב is greater than א” - the exact opposite relationship to the one being described.

This is why when rendering the greater-than character, it gets visually flipped when in RTL. But the underlying character, and the Unicode data backing it, is still the “greater than” symbol. The string still means “א is greater than ב”.

Now back to your first question:

If you change your keyboard layout to a RTL language (like Hebrew or Arabic), then the key combination Shift+, (the key with < printed on it) would actually type the “greater than” character >. This would render as ‏>‏ in a RTL context, like in the search box you found.

[Edit: the next paragraph was written when I slightly misunderstood what you said you had tested. I thought you were typing into a RTL box with a LTR keyboard, when you were actually doing the opposite. Hopefully I still answered your confusion.]

But you are still using a Latin keyboard layout, so when you press that key combination, it inserts a “less than” character <. But it gets rendered as ‏<‏ because in RTL, it means what’s to the right is less than what’s to the left.

Bottom line: the character is the same, but its rendering gets mirrored.

If you’ve understood what I said up to this point, then you’ll understand that that would make -< or in RTL ‏-<‏ which I don’t expect is what you meant.

Did I successfully explain it or did I just make you more confused?

1개의 좋아요

If you think you’d do better with official Unicode documents, try this one: UAX #9: Unicode Bidirectional Algorithm do ctrl+F for “mirror” and you’ll find some good descriptions and examples.

1개의 좋아요

You’re quite right, I’m jumping in without experience, and also with a Latin keyboard!

So I should be quiet… but I do see that if I type (on my Latin keyboard) 3<6 into the aljazeera search box, I see this:

Which probably shows that you’re right, and I’m wrong, and that should be no surprise!

2개의 좋아요

Not at all! If only RTL users were allowed to discuss and fix RTL bugs, we’d be much worse off! I just took this opportunity to introduce you to the subject. It’s supposed to take some time to wrap your head around it. I’m happy to answer any more questions or curiosities you have about this.

1개의 좋아요

I have joined the Unicode mailing list to propose an addition to Unicode that would be a solution in cases like this. One of the responses I got was this:

(Me:) The problem is this replacement is done (as far as I know) outside of any rendering context, when the text is just a sequence of character codes. It’s not reasonable to know which direction the text goes. Sometimes it’s completely impossible, if the text direction depends on context that isn’t available at the time of replacement.

The above is strictly speaking inaccurate. Any serious text rendering
nowadays requires a shaping engine, such as HarfBuzz, and ligation of
“->” into “→” would be done by such a shaper in cooperation with a
font that supports ligatures. The shaping engine is aware of the
bidi context and the script of the text it shapes, so it could in
principle mirror the arrow.

They are talking about something like this: GitHub - tonsky/FiraCode: Free monospaced font with programming ligatures · GitHub

Consider switching to the ligature approach instead of blind character replacement. Another arguable advantage would be that when copy-pasted, the text would still be “->” instead of an arrow.

I haven’t looked into the technical details of how to implement this, I’ll leave that to you if you choose to use this solution.

Edit: well, unsurprisingly, Fira Text in particular isn’t designed with RTL in mind, so the rendering is off - but at least it’s pointing the right way! https://fonts.google.com/specimen/Fira+Code?preview.text=A%20->%20B,%20א%20->%20ב
Firefox:

I’m not sure if there exists a font today that does this correctly and explicitly supports RTL/bidi.

1개의 좋아요

Interestingly, I get a different result in Chromium:
Edit: I can’t reproduce this now so I think I typed it in wrong when I took this screenshot.
Edit: And now I can reproduce it again. The situation is bad.

It’s possible that browser rendering engines/shapers are not up to this task. I’ll need to investigate more, and this is not what I’m supposed to be focusing on right now…

Edit: forum limits forced me to remove this from my previous reply:
For reference, this is the code responsible for this replacement:

1개의 좋아요

앞서 언급했듯이, 저는 이 문제에 대한 Unicode 해결책을 제안하는 작업을 진행 중입니다. 해당 문서에서 문제를 자세히 설명했으며, 여기서 설명한 것보다 더 명확하게 서술했을 것입니다. 아직 작업 중(WIP)이지만, 아래 링크를 확인해 주시면 감사하겠습니다: Create [<message>] git stash create. (영구 링크)

특히 Discourse 섹션을 꼭 살펴보세요.

물론, Unicode에서 이 제안을 수용하더라도(제가 마침내 제출했을 때), 널리 구현되어 신뢰할 수 있을 때까지 수년이 걸릴 것이므로, 그것을 기다리는 것은 좋은 계획이 아닙니다.