Теги в социальных сетях и синтетические (флективные) языки

  • Tutorial

I. В чём проблема


Многие компьютерные технологии, разработанные изначально в мире аналитического языка , при переносе в сообщество с синтетическим языком натыкаются на дополнительные трудности.

Например, поиск с учётом морфологии в английских и русских текстах требует разного уровня сложности. Разветвлённость русского словоизменения уже давно стала предметом расхожих шуток о мучениях иностранцев, изучающих русскую грамматику со всеми нормами и исключениями.

Один из примеров того, как технология натыкается на разницу языков, являют теги в английских и русских блогах и социальных сетях. Пока теги выделяются в отдельный блок (как это реализовано на Хабрахабре или в ЖЖ), проблем нет: в обоих языках используются начальные формы слов, иногда множественное число (и тут даже английский язык являет остатки былого синтетизма). Но как только теги попадают в текст, разница обостряется. И порой кажется, что, например, хештеги Твиттера становятся мощным фактором усиливающегося аналитизма в русском языке. То и дело натыкаешься на фразы вроде:

Мы с #муж в ресторане.

С завтрашнего дня в #Москва.

Вернулись с #море.

Возникает очень странное чувство, некоторое языковое головокружение и раздвоение.

Люди, которые не хотят мириться с такое выпирающей неестественностью, решают проблему по-разному.

Кто-то выносит теги в конец твита, как бы в отдельный блок.

Вернулись. #море #отпуск

Кто-то выносит теги вперёд, как бы дополнительно вычленяя тему следующего предложения.

#Москва. С завтрашнего дня.

Кто-то превращает в теги все словоформы. Хотя это существенно уменьшает потенциал поиска по тегам — ведь морфологию к ним ещё не прикрутили.

Мы с #мужем в ресторане.

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

Мы с #муж-ем в ресторане.

Мы с #муж'ем в ресторане.

Мы с #муж ем в ресторане.

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

Улицы #Киев-а. Вечерним #Киев-ом. Мы в #Киев-е.

Улицы #Москв-ы. Вечерней #Москв-ой. Мы в #Москв-е.

Но всё же слов с совпадающей основой и начальной формой достаточно много, чтобы найти для их тегирования читабельную реализацию.

II. Два возможных решения и их особенности


На самом деле в наборах символов есть два подходящих знака, которые одновременно и прерывают тегирование, и не оставляют никакого видимого промежутка между тегом-основой и окончанием: это мягкий перенос (сокращённо «shy») и пробел нулевой ширины (сокращённо «zwsp»).

Их применение позволяет создавать, например, вот такие хештеги в Твиттере:



Или такие в Фейсбуке (предыдущий вариант не получится, потому что Фейсбук фильтрует одинаковые хештеги, оставляя тегом только первый встретившийся):



У двух символов есть ряд общих черт.

1. В большинстве случаев они невидимы внутри слова.

2. Они становятся местом переноса части слова на другую строку, когда слово уже не помещается целиком.

3. Они не дают разрываться частям слова при выравнивании текста по ширине (по крайней мере, в основных браузерах последних версий).

4. Обнаружить оба знака в слове можно следующими способами: а. при перемещении каретки от символа к символу стрелками с клавиатуры каретка на месте невидимого символа один раз «пробуксовывает», как бы не реагирует на нажатие клавиши; б. при добавлении пробелов перед словом оно рано или поздно, походя к концу строки, «разламывается» на две части в месте вставленного знака; в. некоторые текстовые редакторы (чаще программистские) отображают невидимые символы (например, нулевой пробел можно увидеть в известном сервисе jsfiddle.net, а вот мягкий перенос там не отображается; кстати, можно понаблюдать за поведением текста с такими скрытыми символами, если поперемещать рамки блоков: jsfiddle.net/k37ssezj (в первом отрезке после каждого «слова» вставлен нулевой пробел, во втором — мягкий перенос)).

Но есть и различия между двумя знаками, и все они в пользу мягкого переноса:

1. Мягкий перенос — более традиционный и древний для компьютерного мира знак, он находится в начальной части Юникода, присутствует в большем количестве шрифтов и его легче вводить с клавиатуры. Пробел нулевой ширины расположен значительно позже в таблице Юникода, может быть в меньшем количестве шрифтов и вводить его с клавиатуры сложнее.

2. При переносе части слова на новую строку знак переноса более логичен и более явно обозначает единство слова.

Некоторые различия зависят от приложений.

1. Знаки могут по-разному влиять на поиск по странице (перенос не мешает поиску в Chrome и Firefox, но мешает в IE; пробел не мешает поиску в Chrome, но мешает в Firefox и IE).

2. При двойном щелчке на слове, содержащем невидимый знак, иногда выделяется только часть слова под курсором, иногда всё слово (при вставке переноса выделение делится только в гибридных тегах Твиттера в Chrome; при вставке пробела — делится во всех словах в Chrome и IE).

3. Нужно помнить про баг IE11: при работе с продвинутыми полями ввода (так называемыми Rich Editor, позволяющими видеть оформление в реальном времени в стиле редакторов WYSIWYG; их порождают свойства element.contentEditable и document.designMode) иногда не работает вставка из буфера обмена — в таком случае в консоли разработчика нужно переключаться из режима Edge в режим совместимости с более низкой версией браузера (начиная с IE10). Например, такая проблема проявляется при попытке что-то вставить в текст заметки (Note) в Фейсбуке.

Наконец, на вставку знаков могут по-разному влиять сайты.

1. Фейсбук более враждебен к невидимому пробелу. Он удаляет его почти сразу во время ввода, и уж точно не сохраняет его при публикации поста (судя по всему, это мало кому доставляет трудности). Невидимый перенос сохраняется, в том числе в малопопулярных пока фейсбучных хештегах, но иногда почему-то приходится поводить по слову кареткой ввода при помощи клавиатуры взад-вперёд, чтобы сайт этот знак в слове «увидел», иначе тоже может не сохранить (при ручном вводе эта проблема проявляется реже, чем при попытках вставить символ в текст программно при помощи скрипта (об этом чуть позже)).

2. При попытках вставить знак в Twitter скриптом, нужно помнить про этот досадно застаревший баг в Firefox. Придётся или пользоваться другими способами вставки, или устанавливать ключ security.csp.enable из about:config в false, что, наверное, будет слишком радикальным способом решения типографических проблем.

III. Способы реализации


1. Ввод вручную.

Если вы нечасто вводите редкие символы с клавиатуры, возможно, вам будет полезно ознакомиться с этой небольшой статьёй. В ней описывается два метода ввода символов: в десятеричном счислении (надёжно работает только с начальным блоком Юникода и некоторыми символами распространённых кодировок) и в шестнадцатеричном. Для удобства упомянутого в статье редактирования реестра можно сохранить этот текст в файл с расширением .reg и кодировкой Юникод, щёлкнуть на нём и согласиться на внесение данных в реестр.

EnableHexNumpad.reg
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Control Panel\Input Method]
"EnableHexNumpad"="1"



Итак, при вводе вручную мы должны знать порядковый номер наших символов в двух счислениях:

Мягкий перенос: 0173 и 00ad (соответственно Alt + '0173' и Alt + '+00ad').

Нулевой пробел: 8203 и 200b (соответственно Alt + '8203' и Alt + '+200b').

(Кстати, интересно, что нулевой пробел не входит в класс пробельных символов JavaScript '\s': перечисление одной из групп пробелов прерывается как раз перед ним).

Что нужно учесть:

а. Десятеричный ввод символов с большим порядковым номером работает очень редко. Иногда ничего не вставляется, иногда вставляется что-то совсем неожиданное.

б. При вводе шестнадцатеричных кодов, содержащих буквы, часто срабатывают заданные в приложениях клавиатурные сокращения (shortcuts), и ввод символа срывается. Иногда это зависит от текущей клавиатурной раскладки, иногда нет.

2. Вставка из буфера обмена.

Можно где-то сохранить эти два символа, чтобы копировать их оттуда и вставлять через Ctrl+C/Ctrl+V. Хотя хранить и копировать невидимые символы немного труднее, чем видимые: придётся или сохранить каждый в отдельном файле, или знать их место и выделять при помощи клавиатуры (Shift+стрелки).

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





3. Ввод при помощи скрипта (букмарклета).

Чуть дальше будут представлены две программки, идентичные во всём, кроме кода символа и его переменной. Они последовательно перебирают три варианта обстоятельств:

а. Фокус ввода находится в простом однострочном или многострочном текстовом поле. Используются обычные для таких случаев свойства и методы.

б. Фокус ввода находится в поле с расширенными возможностями типа Rich Editor (учитываются варианты как с элементом текущего окна/документа, так и с полностью выделенной под редактор iframe со своим окном/документом). Используется document.execCommand().

в. Фокус не в текстовом поле или нужный метод работы с Rich Editor не реализован в браузере (в IE11 команда insertText не поддерживается, но будет реализована в Edge). В этом случае перед пользователем всплывает окошко с текстовым полем, в котором необходимый символ уже выделен (хоть он при этом и невидим). Остаётся лишь нажать Ctrl+C, закрыть окно (можно нажатием Enter или Esc), потом вставить курсор в нужное место текста и нажать Ctrl+V. Можно считать этот вариант удобной реализацией предыдущего способа копирования и вставки из файла или утилиты.

Мягкий перенос
javascript: (function(d, e, shy, s1, s2, v, sy, sx) {
    if (e.type == 'textarea' || e.type == 'text') {
        s1 = e.selectionStart;
        s2 = e.selectionEnd;
        sy = e.scrollTop;
        sx = e.scrollLeft;
        v = e.value;
        e.value = v.substring(0, s1) + shy + v.substring(s2);
        e.selectionStart = e.selectionEnd = ++s1;
        e.scrollTop = sy;
        e.scrollLeft = sx;
        e.focus();
    } else if ((e.isContentEditable || d.designMode == 'on') && d.queryCommandSupported('insertText') || (d = e.contentDocument) && (d.activeElement.isContentEditable || d.designMode == 'on') && d.queryCommandSupported('insertText')) {
        d.execCommand('insertText', false, shy);
    } else {
        prompt('Copy and paste in the text:', shy);
    }
})(document, document.activeElement, '\u00ad')


Нулевой пробел
javascript: (function(d, e, zwsp, s1, s2, v, sy, sx) {
    if (e.type == 'textarea' || e.type == 'text') {
        s1 = e.selectionStart;
        s2 = e.selectionEnd;
        sy = e.scrollTop;
        sx = e.scrollLeft;
        v = e.value;
        e.value = v.substring(0, s1) + zwsp + v.substring(s2);
        e.selectionStart = e.selectionEnd = ++s1;
        e.scrollTop = sy;
        e.scrollLeft = sx;
        e.focus();
    } else if ((e.isContentEditable || d.designMode == 'on') && d.queryCommandSupported('insertText') || (d = e.contentDocument) && (d.activeElement.isContentEditable || d.designMode == 'on') && d.queryCommandSupported('insertText')) {
        d.execCommand('insertText', false, zwsp);
    } else {
        prompt('Copy and paste in the text:', zwsp);
    }
})(document, document.activeElement, '​\u200b')


В Chrome или Firefox можно создать новую закладку на произвольную страницу, а затем вставить код (от самой первой буквы javascript: до последней скобки после '\u00ad' или '​\u200b' включительно) в поле адреса, изменив по необходимости название закладки.

В Chrome можно просто выделить код и перетащить выделенный текст сразу в закладки, потом изменив название на более читаемое.

В IE оба этих способа невозможны (зато возможен описанный здесь способ создания файла в папке «Избранного»).

Наконец, во всех браузерах можно перетащить в закладки ссылки с этой страницы (в IE11 нужно будет согласиться с сохранением букмарклета).

IV. Особенности применения в разных браузерах и на разных сайтах.


Вот небольшая таблица с результатами испытаний трёх браузеров последних версий в Windows 7 SP 1. Минус или плюс отображают текущий конечный результат, зависящий от суммы обстоятельств. Он может измениться в процессе развития браузеров или сайтов. Более общие обстоятельства отображены в примечаниях к заголовкам строк и колонок, более частные обстоятельства отмечаются в ячейках. Раздельные варианты с постом и заметкой Фейсбука взяты ради разной реализации Rich Editor в них: в первом случае как элемента страницы, во втором — как целого встроенного фрейма со своим окном/документом.



(картинка без уменьшения)

Примечания в таблице:
1. Хештеги в заметках Фейсбука (пока?) не работают, будь то с невидимыми символами, будь то без них.

2. При вводе десятеричного кода нулевого пробела вместо ожидаемого знака во всех браузерах появляется символ ♂ (порядковый номер — 10: 9794, 16: 2642).

3. В Фейсбуке нулевой пробел удаляется сайтом сразу после вставки или после сохранения поста.

4. Вместо мягкого переноса срабатывают клавиатурные сокращения.

5. Предотвратить срабатывание клавиатурного сокращения в Firefox в данном случае можно добавочным зажатием клавиши Win.

6. Проблема зависит от раскладки клавиатуры: или срабатывает клавиатурное сокращение, или вообще ничего не происходит.

7. В Фейсбуке программно вставленные мягкие переносы не всегда сразу «подхватываются» страницей и тем самым не всегда сохраняются при публикации текста, иногда требуется подвигать курсор внутри слова стрелками клавиатуры. Возможно, есть другие способы «актуализации» вставки. Иногда вставка не распознаётся при первоначальном создании поста, но распознаётся при редактировании уже сохранённого.

8. В IE11 в полях типа Rich Editor будет работать только компромиссный метод букмарклета, с копированием и вставкой символа из буфера.

(P.S. Проверка через виртуальную машину подтверждает реализацию insertText в MS Edge версии 11.00.10240.16397 от 7.22.2015 (по версии файла), она же 20.10240.16384.0 (по информации в настройках): document.queryCommandSupported('insertText') возвращает true).

9. В IE11 поле поста Фейсбука становится обычным полем, без возможностей Rich Editor.


По наглядным итогам испытаний в таблице выделены колонки с самыми универсальными — кроссбраузерными и кроссайтовыми — способами.

Спасибо за внимание.
Поделиться публикацией

Комментарии 32

    +2
    Не очень понятно, вы хотите, чтобы пользователи озаботились правописанием хеш-тегов? Думаю, мало кто этим будет заниматься: читающий может в уме сам достроить/поправить кривую грамматику. Ну а для обработки текста — да, точность упадет, но систему можно обучить на кривизну текста.
      0
      Обучение «кривому» тексту практически равняется полнотекстовому поиску (в чуть меньшем масштабе, потому что #), так что тэги вообще не нужны будут.
        +2
        Нет, я не пытаюсь к чему-то обязать пользователей. Просто делюсь уловками с теми, кто тоже захочет сделать теги более читабельными и естественными. Мне всегда казалось, что автору лучше самому заботиться о ясности письма: потраченное им время с лихвой окупиться временем, которое многие читатели не будут тратить на достраивание чего-то в уме. Там ведь из секунд образуются годы, если помножить на количество читающих во всём времени существования текста.
        +2
        #читаю #хабр, #яумный.

        А если серьёзно, разве нынче можно что-то найти по тэгам, когда все в каждый пост по куче тэгов пихают и такая мешанина получается, что всё равно ничего не найдёшь?
          0
          В общем, в тегах сейчас и правда избыточность и путаница. А тут ещё и экономические и политические технологии примешиваются (рекламный спам при помощи тегов, деятельность ботов). Но, с другой стороны, возрастают и способы увеличения релевантности результатов поиска.

          Для многих Твиттер сейчас становится чуть ли не основным источником оперативной информации. Многие читают в соцсетях очень много по профессии (взять хотя бы репортёров и редакторов СМИ). А экономия места, обычная для Твиттера, иногда приводит к тому, что тексты вообще становятся какими-то нечеловеческими — сплошные сокращения, отмена окончаний, хештеги через каждое слово. Даже с этой стороны предложенный способ поможет экономить место не за счёт ясности и естественности.
          +1
          Думаю, что-то типа «Вот свежая фотка с #Москвы{Москва}» (при этом показывать только первый вариант, а в самой ссылке сделать поиск по вариант в скобках) могло бы решить проблему очень быстро и удобно, но зачем твиттеру этим заморачиваться? В англоязычных все работает, и хорошо.
            0
            Да, это могло бы стать хорошим стандартом вообще для всякого использования хештегов. А количество вспомогательных символов можно не учитывать, как не учитывается размер ссылок в твитах.

            Англоязычным бы тоже пригодилось, хотя бы для унификации единственного и множественного числа существительных, а то и для приведения однокоренных существительных/прилагательных/наречий/глаголов к единому гнезду. А можно даже ещё шире: для поисковой унификации синонимических цепочек (как, например, это делается в Лурке: ссылки на одну и ту же статью даются под видом разных синонимов в зависимости от контекста).
              0
              Как будем присекать эксплутацию такого подхода? Например: «Вот я со своим #мужем{ParisHilton}»
                0
                Так она и сейчас возможна.

                Вот я со своим мужем. #ParisHilton

                Тысячи их.
                  +1
                  Вот негодяи :) Но в Вашем примере тег виден явно.
                  Ну тут, как минимум, чтобы полной подмены не было, можно прийти к конструкции наподобие "#муж{ем}". Было бы желание.
                  С Москвой не так просто, конечно. Допустим, "Я в #Москв{а|е}" или "Я в #Москв[а]{е}".

                  С другой стороны, для среднестатистиечкого пользователя Твиттера это может быть слишком мудрено. Но кто знает? :)
                    0
                    Ну, так ими же спамят для поиска, потом уже поздно, когда видно. Вы можете задать поиск по хештегу #сын или #кот и попасть на десятки твитов типа:



                    Да, такой код, наверное, только программистам будет в удовольствие)

              +3
              Вот, кстати, ещё повод пожалеть о разделении Хабра. Было бы интересно послушать читателей разделов Facebook, Twitter, Социальные сети и сообщества — но не будешь же делать туда кросспост, заругают за умножение сущностей.
                +3
                Пора склеивать обратно! Только минусы одни от этого!
                +2
                Современные твиты настолько мало удобочитаемы, что напоминают высказывания какого-то футуристического(прологоподобного) языка программирования: @me #friend @­someuser. Осталось только добавить переменные: $somevariable. Назвал его bundle(связка), так как порядок тегов не влияет на значение высказывания.
                  +2
                  А что…
                  Прописать у себя в конфиге аккаунта:
                  [aliases]
                  i, I = @me
                  wife = @superbaby1997
                  <3 = love
                  

                  И пишешь потом
                  I <3 wife в #Москв{а|е}
                    +1
                    а может быть даже и так:
                    #alias i I @me

                    ну еще можно добавить какой-нибудь служебный тег, типа:
                    #alias #config wife @superbaby1997

                    тогда ретвитом можно будет распространять списки синонимов:
                    #config #alias #Москва #Москвы #Москве #Москву #Москвой #Moskov
                  +1
                  У вас очень скудное знание английского судя по картинке. Вот навскидку слова происходящие от «Running»
                  Baserunning
                  Forerunning
                  Gunrunning
                  Outrunning
                  Overrunning
                  Rerunning
                  + каждое из этих слов может быть как минимум в трех формах.
                    +1
                    Картинка не моя, этот распространённый мем.

                    И вы путаете словоизменение и словообразование. Перечисленное вами — это не формы слова run, это однокоренные ему слова. А так-то правда, английский один из самых богатых языков, в том числе по количеству синонимов и однокоренных слов.
                      0
                      На картинке тоже приведены однокоренные. Замена префикса и суффикса — это не изменение, а словообразование. В основу слова не входит только окончание.
                        +1
                        Да, на картинке есть несколько форм с префиксами, но тут дело осложняется тем, что в русском языке виды глагола, а иногда и времена можно образовывать только при помощи префиксов (вы не сможете образовать совершенный вид или синтетическое будущее время от глагола «бежать» без префикса). Суффиксы же тоже принимают участие в образовании форм — есть суффиксы причастий как форм глагола, например.

                          +2
                          Тем не менее, табличка предвзятая, почему-то нет runs (бежит) и runnings (бега).

                            0
                            Тут не поспоришь. Но это ведь не столько научная табличка, сколько художественный образ, а в них важно донести основную идею.
                              +3
                              Хех, ну там на самом деле такое разноообразие получается за счёт русской орфографии, мы записываем древнерусские местоимения и, я, е (он, она, оно) и русские на конце слова как часть этого слова:

                              бежавши + и = бежавший
                              бежавши + я = бежавшая
                              бежавши + е = бежавшее

                              бежавши + его = бежавшего
                              бежавши + ему = бежавшему
                              бежавши + ей = бежавшей

                              бежавши + им = бежавшим

                              и т.д.

                              Поэтому получается, что до черта вариантов. А на самом деле вариант один, просто прибавляем местоимения, которые в английском пишутся отдельно.

                                –1
                                Ну, языки ведь типологически сравнивают в синхронии, в современном состоянии, а не в диахронии, не в форме их исторических этапов. С точки зрения сегодняшнего дня и сегодняшних носителей это уже просто окончания.
                                  –1
                                  Эм, это структурная типология рассматривается вне диахронии, а типологическое сравнение в общем учитывает и то и другое.
                                  В любом случае производя разрозненное сравнение можно прийти к прямо противоположному выводу.
                                  Сравните:
                                  to be быть
                                  was был
                                  were был
                                  am есть
                                  is есть
                                  are есть

                                    –1
                                    Ну, это ведь сравнение исключения с нормой.
                                      +1
                                      «быть» это тоже глагол-исключение в русском: был, есть, буду)))
                                        0
                                        Ну, пусть будет так. Я уже не понимаю, о чём мы спорим, честно говоря. Зря я вообще эту картинку прилепил. Она вообще сбоку припёка, но привлекла к себе почти всё внимание и вызвала какое-то особенное возмущение. Я вообще не об этом писал…

                                        Уберу её, пожалуй, вообще.
                                          +1
                                          Вы как-то болезненно реагируете)

                                          Это просто стёб, которым тут весь хабр занимается. Понятное дело что русский более замороченный язык чем английский, так что картинка была в тему.

                                          Честно говоря если бы не картинка, я бы даже и в тему не зашёл бы)
                                            +1
                                            Получилось, что картинка «для привлечения внимания» скушала всё внимание)
                            +1
                            Формы глагола — это опять-таки новые слова, а не изменение слова. Глагол в настоящем времени спрягается, а в прошедшем — изменяется по родам.
                      0
                      (P.S. Проверка через виртуальную машину подтверждает реализацию insertText в MS Edge версии 11.00.10240.16397 от 7.22.2015 (по версии файла), она же 20.10240.16384.0 (по информации в настройках): document.queryCommandSupported('insertText') возвращает true).

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                      Самое читаемое