Размещение символа валюты в строках .NET

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

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

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

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

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

123,45 (символ риала) Риалы

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

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


person DMG    schedule 24.11.2010    source источник


Ответы (1)


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

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

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

В алгоритме каждая последовательность конкатенированных строгих символов называется запуском. Слабый персонаж, расположенный между двумя сильными персонажами с одинаковой ориентацией, унаследует их ориентацию. Слабый символ, расположенный между двумя сильными символами с разным направлением письма, унаследует направление написания основного контекста (в документе LTR символ станет LTR, в документе RTL он станет RTL). Если за слабым символом следует другой слабый символ, алгоритм будет рассматривать первый соседний сильный символ. Иногда это приводит к непреднамеренным ошибкам отображения. Эти ошибки исправляются или предотвращаются с помощью псевдо-строгих символов. Такие управляющие символы Unicode называются метками. Знак 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);
person dtb    schedule 24.11.2010
comment
Большое тебе спасибо! Именно то, что мне нужно. - person DMG; 25.11.2010
comment
Подробности алгоритма BiDi я нашел здесь: unicode.org/reports/tr9 - person DMG; 29.11.2010