Размещение символа валюты в строках .NET - PullRequest
5 голосов
/ 25 ноября 2010

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

(символ валюты) (десятичная строка) (описание валюты)

Этот подход прекрасно работает для большинства символов, однако я заметил, что некоторыесимволов автоматически сдвигаются вправо от десятичного значения, даже если явно размещены слева.Используя отладчик, я вижу это поведение даже на самом фундаментальном уровне в самих строках, так что это не случай каких-либо манипуляций на более высоких уровнях при рендеринге на уровне представления.Следующий код представляет простой случай, демонстрирующий проблему:

string rialSymbol = "\ufdfc";
string amount = "123.45";
string description = "Rials";
string plainConcat = rialSymbol + " " + amount + " " + description;
Debug.WriteLine(plainConcat);

Вывод отладки (который также соответствует тому, что видно в пользовательском интерфейсе приложения) выглядит следующим образом:

123.45 (символ риала) Rials

(Примечание: символ находится справа от десятичного знака, а не слева, как указано)

Я пробовал много подходов и вариантов форматирования строк, культурного форматирования и т. Д., Но, похоже, ничего не происходитрешить эту проблему.Как я могу принудительно установить расположение символа Юникод, не заставляя каркас определять размещение символа относительно десятичного значения?Это работает с большинством других символов, почему Rial (и некоторые другие) вызывают этот тип фундаментального поведения строки?

1 Ответ

9 голосов
/ 25 ноября 2010

U + FDFC - это символ Юникода справа налево.Он предназначен для встраивания в текст справа налево.Вы смешиваете текст слева направо и справа налево.

Из Википедия :

В кодировке Юникод все символы без знаков препинанияхранятся в порядке записи.Это означает, что направление письма символов хранится внутри символов.Если это так, персонаж называется «сильный».Однако знаки пунктуации могут появляться как в сценариях LTR, так и в сценариях RTL.Их называют «слабыми» персонажами, потому что они не содержат никакой информации о направлении.Поэтому именно программное обеспечение решает, в каком направлении будут размещены эти «слабые» символы.Иногда (в тексте со смешанными направлениями) это приводит к ошибкам отображения, вызванным двунаправленным алгоритмом, который проходит по тексту и идентифицирует сильные символы LTR и RTL и назначает направление слабым символам в соответствии с правилами алгоритма.

В алгоритме каждая последовательность объединенных сильных символов называется «выполнением».Слабый персонаж, расположенный между двумя сильными персонажами с одинаковой ориентацией, унаследует их ориентацию.Слабый символ, расположенный между двумя сильными символами с различным направлением письма, унаследует направление письма основного контекста (в документе LTR символ станет LTR, в документе RTL он станет RTL).Если за «слабым» символом следует другой «слабый» символ, алгоритм будет искать первый соседний «сильный» символ. Иногда это приводит к непреднамеренным ошибкам отображения.Эти ошибки исправляются или предотвращаются с помощью «псевдо-сильных» символов. Такие управляющие символы Unicode называются mark .Метка U + 200E (метка слева направо) или U + 200F (метка справа налево) должна быть вставлена ​​в локацию, чтобы вложенный слабый символ унаследовал направление письма.

ДляНапример, для правильного отображения знака торговой марки U + 2122 ™ для английской торговой марки (LTR) в отрывке на арабском языке (RTL) после символа торговой марки вставляется знак LRM, если за символом не следует текст LTR.Если метка LRM не добавлена, слабый символ ™ будет соседствовать с сильным символом LTR и сильным символом RTL.Следовательно, в контексте RTL он будет считаться RTL и отображаться в неправильном порядке.

Таким образом, решение заключается в добавлении метки слева направо U + 200E после правой -налево символы валюты:

string rialSymbol = "\ufdfc\u200e";
string amount = "123.45";
string description = "Rials";
string plainConcat = rialSymbol + " " + amount + " " + description;
Debug.WriteLine(plainConcat);
...