Пособие по практике программирования

       

Интернационализация


Если вы живете в Соединенных Штатах, то вы, может быть, забыли, что английский — не единственный язык на свете, ASCII — не единственный набор символов, $ — не единственный символ валюты, что даты могут записываться с указанием сначала дня, а потом уже месяца, что время может записываться в формате с 24-мя часами и т. п. Так вот, еще один аспект переносимости в общем виде связан с созданием программ, переносимых между разными языками и культурными границами. Это на самом деле весьма обширная тема для разговора, и мы будем вынуждены ограничиться освещением лишь нескольких основных концепций.

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

Не рассчитывайте на ASCII. В большинстве стран мира наборы символов богаче, чем ASCII. Стандартная функция проверки символов из ctype. h, в общем, успешно справляется с этими различиями:

if (isalpha(c)) ...

Такое выражение не зависит от конкретной кодировки символов, а главное — если программу скомпилировать в локальной среде, то она будет работать корректно и в тех случаях, когда букв больше или меньше, чем от а до г. Правда, имя isalpha ("это буква?") говорит само за себя, а ведь существуют языки, в которых алфавита нет вообще.

В большинстве европейских стран кодировка ASCII, определяющая только значения до 0x7F (7 битов), расширяется дополнительными символами, которые представляют собой буквы национальных языков.

Кодировка Latin-1, широко распространенная в Западной Европе, является расширением ASCII, определяющим значения байтов от 80 до FF я небуквенных символов и акцентированных букв — так, значение Е7 представляет букву д. Английское слово boy представляется в ASCII ли Latin-1) тремя байтами с шестнадцатеричными значениями 62 6F 79, эранцузское слово да гсоп представляется в Latin-1 байтами 67 61 72 Е7 6Е. В других языках определяются, соответственно, другие символы, но они не могут уложиться в 128 значений, не используемых в ASCII, к что существует множество конфликтующих стандартов для символов, привязанных к байтам от 80 до FF.

Некоторым языкам вообще не хватает 8 битов: в большинстве азиат-их языков существуют тысячи символов. В кодировках, используе-,гх в Китае, Японии и Корее, на символ отводится 16 битов. В результа- i возникает глобальная проблема переносимости: как прочитать кумент на некотором языке на компьютере, настроенном на другой ык. Даже если все символы передадутся без ошибок, для прочтения на [ериканском компьютере документа на китайском языке должны как шимум стоять специальные шрифты и соответствующее программное обеспечение. Если же мы захотим на одной машине использовать анг-| [йский, китайский и русский языки, проблем у нас возникнет море.

Набор символов Unicode — попытка улучшить описанную ситуацию, юдоставив единую кодировку для всех языков мира. Unicode совмес-' :ма с 16-битовым подмножеством стандарта ISO 10646; в ней исполь-ется 16 битов на символ. Значения от OOFF и ниже относятся к Latin-1,то есть слово gargon будет представлено 16-битовыми значениями 0067 61 0072 ООЕ7 006F 006Е. Кириллица занимает значения от 0401 до 04FF,а идеографическим языкам отведен большой блок, начинающийся ЮОО. Все известные и некоторые почти неизвестные языки мира пред-авлены в Unicode, так что именно этой кодировкой и стоит пользовать для передачи документов между странами или для хранения текста, .писанного на разных языках. Unicode стала весьма популярна в Интер-;те, и некоторые языки программирования даже поддерживают ее как стандартный формат: например, Java использует Unicode как родной на-ip символов для строк. Операционные системы Plan 9 и Inferno испольч ют Unicode более широко — даже для имен файлов и пользователей, icrosoft Windows поддерживает набор символов Unicode, но не считает о стандартом; большинство приложений Windows до сих пор лучше; .ботает с ASCII, хотя соотношение стремительно меняется в пользу: nicode.

Надо сказать, что и у Unicode есть недостатки: символы в ней уже не гещаются в один байт, поэтому текст в Unicode страдает от проблемы >рядка байтов. Для преодоления этой напасти документы в Unicod перед передачей между программами или по сети обычно преобразуются в кодировку потока байтов, называемую UTF-8. В ней каждый 16-битовый символ кодируется для передачи как последовательность из 1, 2 или 3 байтов. Набор символов ASCII использует значения от 00 до 7F, все они умещаются в один байт при использовании UTF-8. Таким образом, получается, что UTF-8 односторонне совместима с ASCII. Значения между 80 и 7FF представляются двумя байтами, а значения от 800 и выше — тремя.1 В UTF-8 слово gargon представляется байтами 67 61 72 СЗ А7 6F 6Е; значение Unicode E7 — символ g — представляется в UTF-8 двумя байтами — СЗ А7.

Совместимость UTF-8 с ASCII весьма полезн-а, поскольку благодаря ей программы, рассматривающие текст как непрерывный поток байтов, могут работать с текстом Unicode на любом языке. Мы опробовали программу markov из третьей главы с текстом в UTF-8 на русском, греческом, японском и китайском языках, и она работала без каких-либо проблем. Для европейских языков, слова в которых разделяются ASCII-символами пробелов, табуляции или перевода строки, программа выдавала вполне сносный текст. При использовании других языков для того, чтобы получить что-то приемлемое на выходе, пришлось бы изменять правила разбиения текста на слова.

С и C++ поддерживают "широкие символы" (wide characters), которые представляются 16-битовыми или еще большими целыми. Суще-CTByiw и соответствующие функции, которые могут быть использованы для обработки символов в Unicode или в другом расширенном наборе символов. Строковые константы из широких символов записываются как L". . ,". Однако и здесь возникает большая проблема с переносимостью: программа с константами из широких символов может быть воспроизведена только на дисплее, использующем тот же набор символов. Поскольку символы должны быть конвертированы в поток байтов вроде UTF-8 для передачи между машинами, язык С предоставляет функции для преобразования широких символов в байты и обратно. Однако какое преобразование использовать? Интерпретация набора символов и описания кодировки потока байтов таятся в недрах библиотек, и вытащить их оттуда достаточно сложно; ситуация складывается не в нашу пользу. Может статься, в отдаленном светлом будущем все наконец придут к согласию об использовании единого набора символов, но пока что от фоблемы порядка байтов никуда нам не деться.

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

Как же быть с сообщениями об ошибках? По крайней мере, в них не должно использоваться жаргона или сленга; лучше всего писать на самом простом языке. Полезно еще собрать тексты всех сообщений в каком-то одном месте программы — тогда можно будет быстро перевести их все.

Существует множество местных культурных особенностей, например формат дат mm/dd/yy используется только в Северной Америке. Если существует вероятность того, что ваша программа будет использоваться в другой стране, от таких особенностей надо по возможности избавиться. Иконки в графическом интерфейсе очень часто зависят от традиций; если понятия, на которых базируется зрительный образ, пользователю незнакомы, такая иконка его только дезориентирует.

<



Содержание раздела