Автоматическая вставка меток LTR - PullRequest
1 голос
/ 08 марта 2011

Я работаю с двунаправленным текстом (смешанный английский и иврит) для проекта. Текст отображается в HTML, поэтому иногда для правильного отображения «слабых символов», таких как знаки пунктуации, требуется знак LTR или RTL (‎ или ‏). Эти метки отсутствуют в исходном тексте из-за технических ограничений, поэтому нам необходимо добавить их, чтобы окончательно отображаемый текст выглядел правильно.

Например, следующий текст: (example: מדגם) sample отображается как sample (מדגם :example) в режиме справа налево. Исправленная строка будет выглядеть как ‎(example:‎ מדגם) sample и будет выглядеть как sample (מדגם (example:.

Мы бы хотели оперативно вставлять эти метки, а не переписывать весь текст. Сначала это кажется простым: просто добавьте ‎ к каждому пункту. Однако часть текста, который необходимо изменить на лету, содержит HTML и CSS. Причины этого неудачны и неизбежны.

Если не считать парсинга HTML / CSS, существует ли известный алгоритм для оперативной вставки меток направления Unicode (псевдосильные символы)?

1 Ответ

1 голос
/ 08 марта 2011

Я не знаю алгоритма, позволяющего безопасно вставлять метки направления в строку HTML без ее анализа. Разбор HTML в DOM и манипулирование текстовыми узлами - самый безопасный способ избежать случайного добавления меток направления в текст внутри тегов <script> и <style>.

Вот короткий скрипт на Python, который может помочь вам автоматически преобразовать ваши файлы. Логика должна быть легко переведена на другие языки, если это необходимо. Я недостаточно знаком с правилами RTL, которые вы пытаетесь кодировать, но вы можете настроить регулярное выражение '(\W([^\W]+)(\W)' и шаблон подстановки ur"\u200e\1\2\3\u200e", чтобы получить ожидаемый результат:

import re
import lxml.html

_RE_REPLACE = re.compile('(\W)([^\W]+)(\W)', re.M)

def _replace(text):
    if not text:
        return text
    return _RE_REPLACE.sub(ur'\u200e\1\2\3\u200e', text)

text = u'''
<html><body>
    <div>sample (\u05de\u05d3\u05d2\u05dd :example)</div>
    <script type="text/javascript">var foo = "ignore this";</script>
    <style type="text/css">div { font-size: 18px; }</style>
</body></html>
'''

# convert the text into an html dom
tree = lxml.html.fromstring(text)
body = tree.find('body')
# iterate over all children of <body> tag
for node in body.iterdescendants():
    # transform text with trails after the current html tag
    node.tail = _replace(node.tail)
    # ignore text inside script and style tags
    if node.tag in ('script','style'):
        continue
    # transform text inside the current html tag
    node.text = _replace(node.text)

# render the modified tree back to html
print lxml.html.tostring(tree)

Выход:

python convert.py

<html><body>
    <div>sample (&#1502;&#1491;&#1490;&#1501; &#8206;:example)&#8206;</div>
    <script type="text/javascript">var foo = "ignore this";</script>
    <style type="text/css">div { font-size: 18px; }</style>
</body></html>
...