将非英文文本左对齐

Align Non-English Text To Left

我正在将类似收据格式的订单打印到 RichtextBox,当我的商品名称是英文时,一切正常,一旦我的商品名称是非英语语言,如希伯来语或阿拉伯语,其中这两种语言都是从右往左写的,整体格式变得凌乱。

所有文本均为英文的示例

1...5...10...15...20...25...30...35...40...45.48
ITM                          Price   QTY   Value
------------------------------------------------
Test                         6,000   x1    6,000
test02                       0       x1        0
test03                       0       x1        0

如您所见,一切都井井有条且格式正确,但是当我有一个名称为希伯来语或阿拉伯语的项目时,就会发生这种情况

1...5...10...15...20...25...30...35...40...45.48
ITM                          Price   QTY   Value
------------------------------------------------
Test                         6,000   x1    6,000
1,500                        تيست    x1    1,500

如您所见,非英语文本在价格栏下移动。正如我提到的,这只发生在从右到左编写的语言中。

我的格式化代码

int Item_Length = -29;
int Price_Length = -8;
int Qty_Length = -3;
int Value_Length = 8;

string Seperator = "------------------------------------------------"+"\n";

string ruler = "1...5...10...15...20...25...30...35...40...45.48"+"\n";
rTxtReceipt.Text = ruler;

string Headers = string.Format("{0,"+Item_Length+"}{1,"+Price_Length+"}{2,"+Qty_Length+"}{3,"+Value_Length+"}", "ITM", "Price", "QTY", "Value")+"\n";
rTxtReceipt.AppendText(Headers);
rTxtReceipt.AppendText(Seperator);

string Rows = null;
foreach (var item in Items_List)
{
    Rows += string.Format("{0,"+Item_Length+"}{1," + Price_Length + ":N0}{2," + Qty_Length + "}{3," + Value_Length + ":N0}", item.ItemName, item.ItemSellPrice, ("x" + item.SellsQty), item.SellsValue) + "\n";
}

rTxtReceipt.AppendText(Rows);

其中 rTxtReceipt 是 RichTextBox 控件。 任何人都可以建议如何使所有文本不管语言从左到右对齐吗?

我有一个功能可以检测文本是否为英文,但如果文本不是英文,我不知道在哪里更改。

public bool IsEnglish(string inputstring)
{
    Regex regex = new Regex(@"[A-Za-z0-9 .,-=+(){}\[\]\]");
    MatchCollection matches = regex.Matches(inputstring);

    if (matches.Count.Equals(inputstring.Length))
        return true;
    else
        return false;
    }
}

问题与 RTL 字符在双向文本中被数字包围时的行为有关。更多信息,您可以阅读这篇文章: Right-to-left language support and bidirectional text

如果不是紧跟在商品名称后面的价格,而是一个拉丁字母:تيست x1,500.

,您就不会遇到这个问题

很明显,这不是您想要的。因此,要强制文本方向保持 LTR 并防止数字弄乱,您只需在项目名称后立即添加一个 "hidden character"。幸运的是,有一个特定的字符可用于此目的。它被称为 Left-to-Right Mark.

  • 首先,在适当的地方添加以下常量:

    const string LtrMark = "\u200E";
    
  • 然后你可以简单地做这样的事情:*

    Rows += string.Format(format, item.ItemName + LtrMark, item.ItemSellPrice, ...
    //                                            ^^^^^^^
    

现在,您不必担心检查项目名称是否为英文。只需插入该字符即可同时适用于 LTR 和 RTL 语言。但是请注意,您需要使用适用于英语和阿拉伯语的 fixed-width 字体(例如 Courier New)。这就是最终结果的样子:


* 因为LTR标记是一个zero-width字符,所以会让后面的值出现在一个字符的后面。为避免这种情况,您可以对项目使用 Item_Length - 1 或对 headers 使用 Item_Length + 1 以确保它们对齐。