Эта вторая часть рассказа про локализацию ABBYY FineReader Sprint на арабский. В отличие от первой части, где собственно про язык было мало, а про окна много, здесь речь пойдет уже про письменность и ее особенности.

Арабские арабские цифры


Точнее индо-арабские. В то время как европейцы и примкнувшие к ним полмира используют арабские цифры, сами арабы (в большинстве стран) предпочитают использовать другие, хоть и (отдаленно) похожие цифры: ??????????. Слегка подробнее, например, в википедии. Но в википедии не описан удивительный факт: в современном арабском языке число, скорее всего, будет записываться слева направо – вне зависимости от того, какие цифры используются. Сколько-нибудь подробных правил, где в интерфейсах какие цифры применять, я не нашел. Те закономерности, что использовали мы, были выведены эмпирически, в процессе разглядывания Windows 8 с арабским языком интерфейса. И не так уж и много их нашлось:

• Если цифра – часть английского текста, то она остается «английской». Например, F1 или A4.
• Если в контроле текстового ввода вводятся цифры, то они «арабские». Да, и в IP address контроле тоже.
• Да и вообще, почти всегда используются «арабские» цифры.

Кстати, хорошие новости. Судя по нашему опыту, для того чтобы выполнить эти правила, не нужно делать ничего специально. Вот что пишет msdn по этому поводу: «… мы чаще всего оставляем цифры в ANSI, оставляя операционной системе вывод правильных цифр в зависимости от системных настроек».

Про клавиатурные ускорители


Речь идет о тех подчеркнутых буквах, которые можно увидеть в диалогах и меню (если не видно – нужно нажать Alt). В терминах Микрософт – Access Keys. На всякий случай опишу, как это работает (с точки зрения пользователя) на примере Notepad:



Если открыть меню, как на картинке, и нажать ‘X’, то приложение закроется, если ‘P’ – откроется диалог печати, и т.д. Кстати, чтобы получить меню такого вида, нужно нажать “Alt, F” (можно не одновременно). Поддержка этой фичи «встроена» в WinAPI: все, что нужно сделать при разработке, — указать в соответствующем ресурсе меню или диалога, какая буква будет ускорителем для того или иного пункта. Это делается с помощью символа ‘&’, проставленного перед нужной буквой. Т.е. в ресурсах меню Notepad просто написано: “E&xit”.

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



Решение, как видно на этом скриншоте, не самое красивое, но рабочее: к японскому названию пункта меню в скобках дописывается латинская буква, которая и будет ускорителем.

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

• лигатуры (письменный арабский очень любит лигатуры, но, к счастью, обязательной является только лям-алиф, остальные при вводе с клавиатуры практически не встречаются),
• символы, которые вводятся с зажатым Shift,
• символы, которые на письме объединяются в конструкцию, по которой сложно понять, какой символ подчеркнут (например, алиф с хамзой: ??),
• латинские символы — если есть возможность этого избежать (так, если частью названия пункта меню является английское слово, не нужно ставить на него ускоритель).

Подробнее можно посмотреть в микрософтовском Arabic Style Guide, в разделе Software Consideration, Keys.

Кстати, по какой-то причине техписатели решили, что арабский язык в контексте таких ускорителей похож на японский: ?????(X). И эта ошибка имела шанс прожить довольно долго незамеченной, если бы не более бросающаяся в глаз проблема со скобками, описанная в следующем разделе.

Смешение языков


Иногда (а в случае локализации программ весьма часто) в арабский текст нужно встраивать английские слова: названия компаний (хоть у ABBYY и есть перевод названия на китайский, но в арабском продукт все еще называется ABBYY FineReader Sprint), технологий (например, TCP/IP) и многое другое. При этом основной арабский текст будет читаться, как и положено, справа налево, а английскии слова в нём – слева направо. Например, «Домашняя страница ABBYY» будет писаться как «????? ???? ABBYY ??? ?????». Кстати, попробуйте скопировать эту фразу в текстовый редактор, и «погулять» по ней курсором, чтобы понять всю логичность порядка чтения в смешанных текстах.

Но это еще была не проблема: сам по себе смешанный текст беды не приносит. Но стоит рядом с английскими словами в арабском тексте оказаться знакам препинания или цифрам… Например, в нашем приложении (поскольку оно поддерживает сканирование) есть строка, описывающая популярный размер бумаги: “A4 (210 x 297 mm)”. Название размера не переводится, а вот единица измерения – да. В итоге, в арабском эта строка выглядит вот так (скриншот сделан на английской системе, поэтому на «не арабские» цифры обращать внимание не нужно):



К нашему удивлению, когда ресурсы пришли с перевода, текст в приложении выглядел совсем не так:



Причем, для пущего веселья, в Windows 8 (предыдущий скриншот сделан в Windows 7) эти же строки выглядели уже вот так:



Хуже того, в Windows 7 даже текст без единого арабского символа тоже рисовался неправильно (это уже диалог выбора сканера):



Итак, кто виноват и что делать? Отвечает за вывод смешанного текста алгоритм bidi. Описание алгоритма уже было на хабре, правда с упором на применение в html. Я же кратенько перескажу википедию, и перейду к тому, как это работает в Windows.

В этом алгоритме символы делятся на сильные (те, направление которых заведомо известно, – буквы), слабые (те, направление чтения которых может меняться, – знаки препинания) и нейтральные (те, к которым не применимо понятие направления, – пробельные символы). В памяти символы хранятся в порядке чтения: первая буква, вторая буква и т.д. Ну а алгоритм выводит буквы в визуальном порядке: LTR слова слева направо, RTL – справа налево. Несколько слов одинаковой направленности будут выводиться в порядке этой направленности. Взаимное же расположение частей текста разной направленности определяется общим направлением текста. На следующей картинке это показано наглядно: порядок слов обозначен числами, порядок чтения (т.е. букв в словах) – стрелками, сверху указано общее направление текста.



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

И опять про цифры. Описание алгоритма на wiki говорит, что цифры – это слабые символы. Но это не совсем так. Как я уже упоминал, вне зависимости от того, арабские или индо-арабские цифры используются, числа будут писаться слева направо. А направление слабых символов должно зависеть от окружения. Но при расчете направления других слабых символов цифры не учитываются, так что, по сути, они выделены в отдельную категорию направленных слабых символов. Эксперименты также показали, что если «граничное» число следует за LTR текстом (в порядке хранения в памяти), то и выводится оно как часть LTR текста даже в RTL окружении.

Экспериментально было выяснено, что Windows XP/Vista/7/7.1 используют одну версию алгоритма, а Windows 8/8.1 другую. Начиная с Windows 8, судя по всему, алгоритм был усовершенствован: если в строке присутствуют два парных слабых символа (например, открывающая и закрывающая скобки), один из которых расположен на границе, а второй между сильных символов одной направленности, то оба парных символа будут нарисованы в той направленности, которая определена сильными символами.

Что же делать, если определенное правилами положение символа при рисовании не соответствует ожидаемому? Стандарт Unicode предлагает для этого несколько способов. Из них, на мой взгляд, самым простым (для понимания) и вполне достаточным для любых ситуаций является использование символов “Left-to-right mark” (LRM, U+200E) и “Right-to-left mark” (RLM, U+200F). Это невидимые сильные символы, имеющие соответствующую названию направленность. Их нужно просто вставлять в те места, где направленность граничного слабого символа определяется неверно. Эти символы MS Visual Studio показывает, впрочем, как и Notepad, если включить соответствующую настройку в контекстном меню. В том же меню есть и команда вставки LRM и RLM:



Альтернативным способом ввода этих символов (помимо очевидного: копирование нужного символа из другого места :-), является ввод через Alt код. Для этого нужно добавить в реестр строковый ключ HKEY_CURRENT_USER\Control Panel\Input Method\EnableHexNumpad со значением 1 и перезагрузить компьютер. После этого символs LRM и RLM можно будет вводить с помощью последовательностей “Alt + Num+, 200e” и “Alt + Num+, 200f” соответственно. Подробнее: нужно нажать одновременно Alt и + на дополнительной клавиатуре, отпустить, потом набрать шестнадцатеричный код символа, для цифр используя дополнительный блок.

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



В этом примере крайняя скобка неправильно определялась как RTL и поэтому «уезжала» влево и разворачивалась. Достаточно добавить LRM после скобки, и все образуется.



В этих трех проблемах с размерами бумаги (внизу представлен размер Tabloid 11x17 inches) работает совокупность двух факторов. Во-первых, вместо символа умножения ‘?’ (U+00D7) используется строчная латинская «икс». Это не вызывало никаких проблем раньше, но здесь вызвало. По крайней мере для решения проблем с Win8 и Tabloid оказалось достаточным заменить ‘x’ на знак умножения. Столь странное «уезжание» ‘x’ от окружающих его цифр связано же с тем, что ширина (210) была определена как RTL (по скобке в случае с Win8 и по названию размера бумаги в случае с Tabloid), высота же в обоих случаях была признана одним LTR куском с ‘x’.

Ну и во-вторых, чтобы проблема поправилась и на Windows 7 (и в более ранних версиях), нужно также добавить RLM перед открывающей скобкой.

В результате получилось вот такое:



Rich Edit


Последняя проблема, с которой мы столкнулись, заключалась в том, что редактор ресурсов по умолчанию создает Rich Edit контрол версии 2.1. А в этой версии контрол плохо поддерживает арабский язык. В результате EULA на арабском (а это единственное использование Rich Edit в продукте) выглядело весьма криво. Ручное исправление “RichEdit20W” на “RichEdit50W” ситуацию исправило, но только на Windows 8. На младших версиях поправились некоторые, но далеко не все, косяки. Впрочем, Wordpad этих систем при открытии в нем файла EULA (а файл создавался в какой-то старшей версии Word) показывал столь же грустную картину. Единственное решение, которое мы придумали, – отредактировать этот файл в Wordpad в Windows XP, так чтобы он стал выглядеть прилично.

Комментарии (10)


  1. Muzzy0
    22.04.2015 11:38
    +7

    Даа… Мои соболезнования…

    Перемещения курсора, ввод скобок и чисел, разделённых пробелом или дефисом (телефонные номера) — это адов трэш в RTL :)

    А если взять в расчёт, что некоторые устройства не понимают RTL совсем, то становится ещё веселее. Лично я сталкивался с тем, что приходилось писать слова и целые фразы задом наперёд :)))


    1. muxaeji Автор
      22.04.2015 13:15
      +1

      В описываем продукте такого треша, к счастью, нет. Вот когда добавляли поддержку RTL в редактор FR Pro, вот там наразвлекались. Впрочем, разворачивать слова вручную все же не приходилось. Кмк, малоподдерживаемое решение получается.


      1. Muzzy0
        22.04.2015 23:23

        Мне приходилось работать с одной панелькой на слегка кривой сборке WinCE. Вот в ней поддержки RTL не было и приходилось делать через задницу. Знаки препинания, скобки в этом случае доставляли особо :)


  1. Vapaamies
    22.04.2015 11:41
    +5

    Отличная статья! До этого как-то не попадалось объяснение механизма работы BiDi на русском, да еще с примерами.


  1. IamKarlson
    26.04.2015 22:27
    +3

    Самое интересное это их письмо. В арабском, как я был вынужден выяснить, существует 4 формы символа: форма в начале слова, середине и конце, и отдельно стоящая. Причем эти формы не совпадают. Из 28 символов стандартного алфавита есть еще минимум 3 обязательных, которые являются или модификацией одной из самых частно используемых букв, либо модификацией буквы методом убирания точек. Но это не самое интересное. Самое интересное, что буквы могут писаться как в начале слова если перед ними стоит одна из 6 специальных букв, которые не имеют серединной формы. Но и это еще не все. Буквы могут иметь огласовки. Но они не обязательные. Ну практически, некоторые огласовки все же обязательны. А огласовки вообще нужны чтобы сделать в словах гласные звуки. Но в газетах их не пишут. В газетах зато пишут символ танвин, который ставит слово в определенный падеж. А еще в газетах пишут лигатуру — это такое специальное совмещение символов в один. Но лигатура это не обязательно, ну кроме одной. Ну точнее одной буквы с другой. А с огласовками и модификаторами этих лигатур становится 4( лям-алиф, лям-алиф с хамза сверху, снизу, танвин(не очень обязательный)). А знаю я это потому что некоторые чековые принтеры не умеют печатать арабские буквы, и их надо научить. И единственный способ это нарисовать все эти 100+ символов. Это кромешный ад если честно. Но жутко интерсный)


    1. Muzzy0
      30.04.2015 10:37

      На чековом принтере вполне можно обойтись без огласовок и дагешей (во всяком случае, точка-модификатор в иврите называется дагеш и печатается только в детских книжках, ТаНаХе и учебниках).


      1. IamKarlson
        30.04.2015 12:17

        Есть несколько обязательных, без них сказали нельзя.


        1. Muzzy0
          30.04.2015 12:23

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

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


          1. IamKarlson
            30.04.2015 12:31

            Так мне сказали арабско говорящие специалисты, поэтому вот так.

            А иврит похож на арабский разве?


            1. Muzzy0
              30.04.2015 14:14

              Практически, братья. Не родные, так двоюродные :))))

              В обоих письмо справа налево, нет гласных (вместо них — огласовки), оба происходят, в сущности, от арамейского. Много похожих слов, а некоторые даже общие, только звучат по-разному.