Эта вторая часть рассказа про локализацию 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_USERControl PanelInput MethodEnableHexNumpad со значением 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, так чтобы он стал выглядеть прилично.
Автор: muxaeji