【问题标题】:Weird behaviour on joining mixed right-to-left and left-to-right language strings加入混合的从右到左和从左到右的语言字符串时的奇怪行为
【发布时间】:2021-04-20 11:41:51
【问题描述】:

输入:

临时文本数组: ▿ 3 个元素

- 0 : "זה מבחן"
- 1 : "7 x 5 abc"
- 2 : "other text"

当做一个简单的tempText = tempTextArray.joined(" | ") 时,结果并没有将所有元素放在我期望它们的位置...结果:

Printing description of tempText:
"זזה מבחן | 7 x 5 abc | other text"

这是我第一次将从右到左的文本与从左到右的文本结合起来,以前有没有人处理过类似的情况?

我的应用正在接收来自后端的翻译,所以我不知道哪些元素被翻译成(在这种情况下)希伯来语,以及我会以我的默认语言(英语)接收哪些元素

【问题讨论】:

    标签: ios arrays swift right-to-left left-to-right


    【解决方案1】:

    这是由Unicode BIDI (Bidirectional Text) algorithm 引起的。首先,我将解释如何解决它,因为它相当简单,然后我会解释发生了什么,以防您需要更多信息。

    您需要在要将文本方向重置为 LTR 的每个位置添加 LTR(从左到右标记)字符。在您的情况下,它位于字符串的开头和每个 | 块的开头:

    let ltr = "\u{200e}"
    let tempText = ltr + tempTextArray.joined(separator: "\(ltr) | ")
    // => ‎זה מבחן‎ | 7 x 5 abc‎ | other text
    

    如果您打算使用希伯来语,您绝对想阅读 Cal Henderson 对算法的精彩解释:Understanding Bidirectional (BIDI) Text in Unicode

    现在解释发生了什么。您正在打印一个字符串,其第一个字符是“זה מבחן”中的 ז,最后一个字符是“文本”中的最后一个 t。它不是由| 分隔的三个字符串,它只是一个长字符串。当您显示该字符串时,BIDI 算法必须决定所有字符的去向。

    第一个字符 (ז) 是 RTL 字符,因此它决定这是一个嵌入了一些 LTR 文本的 RTL 字符串。这与你想要的相反。您希望这是一个嵌入了一些 RTL 文本的 LTR 字符串。因此,您需要以 LTR 字符开头,例如 Left-To-Right Mark。

    BIDI 算法的工作是告诉系统下一个字符应该朝哪个方向移动。 זה 中的每个字符都是 RTL,所以这很容易,继续向左走。但是 זה 和 מבחן 之间的空间呢?空格在方向上是中性的,最后一个字符是 RTL,所以空格向左。但随后我们来到了 מבחן 和 | 之间的空间。空间是中性的,|是中性的,所以 BIDI 算法会将空格和 |再次向左。你想要的空间和|是 LTR,所以你需要在那里添加另一个 LTR 字符。

    7 也是中性的,但x 是 LATIN SMALL LETTER X,它是 LTR(不是 MULTIPLICATION X,它是中性的)。

    最终结果是 BIDI 算法确定这是一个以 7 | זה מבחן 开头的 RTL 字符串,然后(向左)是一个嵌入的 LTR 字符串 x 5 abc | other text。 (换句话说,这是一个恰好包含一些英语的希伯来语字符串,而不是一个恰好包含一些希伯来语的英语字符串。)

    我希望您在上面的问题中实际显示的不是您所看到的(因为 BIDI 算法如何应用于 Stack Overflow)。我希望它实际上看起来像这样:

    如果你从右到左阅读,现在发生的事情应该更有意义。

    【讨论】:

    • 虽然我接受了您的回答,但我从未回复过 - 但迟来的感谢您的详细回复! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 2014-10-05
    • 2012-09-11
    • 2011-09-19
    • 1970-01-01
    相关资源
    最近更新 更多