Всего на сайте:
166 тыс. 848 статей

Главная | Информатика

Интернационализация  Просмотрен 178

 

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

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

 

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

 

if (isalpha(c)) ...

 

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

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

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

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

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

Надо сказать, что и у Unicode есть недостатки: символы в ней уже не умещаются в один байт, поэтому текст в Unicode страдает от проблемы порядка байтов. Для преодоления этой напасти документы в Unicode перед передачей между программами или по сети обычно преобразуют­ся в кодировку потока байтов, называемую UTF-8.

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

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

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

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

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

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

Заключение

 

Переносимый код — это идеал, к которому надо стремиться, посколь­ку только он способен сэкономить вам время при переносе программы из системы в систему или при изменении текущего окружения. Однако переносимость достается не бесплатно — вам придется быть особенно внимательными при написании кода, а также представлять себе детали всех потенциально пригодных систем.

Мы рассмотрели два подхода к обеспечению переносимости — объединение и пересечение. Объединение предусматривает создание версий, которые работают в каждой конкретной среде; акцент при этом делается на механизмы вроде условной компиляции. Недостат­ков у этого подхода много: требуется писать больше кода, и нередко этот код получается весьма сложным; трудно изменять версии, очень трудно тестировать.

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

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

Дополнительная литература

Есть много описаний языков программирования, но немногие из них достаточно точны, чтобы служить полноценным справочным ру­ководством по языку. Авторы данной книги имеют личные причины, чтобы предпочитать книгу "Язык программирования С" Брайана Кернигана и Денниса Ритчи (Brian Kernighan, Dennis Ritchie. The С Programming Language. Prentice Hall, 1988), но она не заменяет стан­дарт. В книге "С: Справочное руководство" Сэма Харбисона и Гая Стила (Sam Harbison, Guy Steele. C: A Reference Manual. Prentice Hall, 1994), которая дожила уже до четвертого издания, даны хорошие со­веты по переносимости. Официальные стандарты языков С и C + + доступны в ISO (The International Organization for Standardization). Книга, наиболее близкая к официальному стандарту языка Java, — "Спецификация языка Java" Джеймса Гослинга, Билла Джоя и Гая Стила (James Gosling, Bill Joy and Guy Steele. The Java Language. Specification. Addison-Wesley, 1996).

Книга Ричарда Стивенса "Программирование в системе Unix" (Ri­chard Stevens. Advanced Programming in the Unix Environment. Addison-Wesley, 1992) является отличным пособием для программистов под Unix; в частности, там дан подробный обзор вопросов переносимости между различными Unix-системами.

POSIX (the Portable Operating System Interface) — международный стандарт команд и библиотек, основанный на Unix-системах. Он опи­сывает стандартную среду, переносимость исходного кода, а также уни­фицированный интерфейс для ввода-вывода, файловых систем и про­цессов. Этот стандарт описан в нескольких книгах, опубликованных IEEE.

Термин "big-endian" был введен Джонатаном Свифтом в 1726 г.[15] Ста­тья Денни Коэна "О святых войнах и мольбе о мире" (Danny Cohen. On holy wars and a plea for peace. IEEE Computer, October 1981) является замечательной басней о порядке байтов, в которой термин "endian" был впервые применен в компьютерной области.

В операционной системе Plan 9, разработанной в Bell Labs, перено­симость является главным приоритетом. Система компилируется из од­ного и того же исходного кода (без директив условной компиляции!) на множестве разных процессоров и повсеместно использует символы Unicode. Последние версии редактора Sam, впервые описанного в "The Text Editor sam"(Software — Practice and Experience, 17, 11, p. 813-845, 1987), используют Unicode, но тем не менее работают на большом коли­честве систем. Проблемы работы с 16-битовыми наборами символов вроде Unicode описаны в статье Роба Пайка и Кена Томпсона "Hello, World or (написано на языке арабского происхождения :-) ) (Документы зимней конфе­ренции USENIXT993.

Сан-Диего, 1993. С. 43-50). Впервые кодировка UTF-8 была представлена именно в этой статье. Данный документ, как и последняя версия редактора Sam, также доступен на Web-сайте, по­священном системе Plan 9 в Bell Labs.

Система Inferno основывается на опыте Plan 9 и в чем-то похожа на Java, поскольку она определяет виртуальную машину, которая может быть реализована на любой реальной машине, предоставляет язык (Limbo), который может быть скомпилирован в инструкции для этой виртуальной машины, и использует Unicode в качестве основного набо­ра символов. Она также включает виртуальную операционную систему, которая предоставляет переносимый интерфейс ко множеству коммер­ческих систем. Она описана в статье "Операционная система Inferno" Шона Дорварда, Роба Пайка, Дэвида Л. Презотто, Денниса Ритчи, Го­варда Трики и Филиппа Винтерботтома (Sean Dorward, Rob Pike, David Leo Presotto, Dennis M. Ritchie, Howard W. Trickey и Philip Winter-bottom. The Inferno Operating System. Bell Labs Technical Journal, 2, 1, Winter, 1997).


9. Нотация

 

 

Из всех творений человека

самым удивительным является язык.

 

Джайлс Литтон Страчи. Слова и поэзия

 

 

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

Преимущества хорошей нотации — способа записи — появляются при переходе от традиционного программирования к узкоспециальным про­блемным областям. Регулярные выражения позволяют использовать компактные (из-за этого подчас превращающиеся в тайнопись) описания классов строк. Язык HTML позволяет определять внешний вид интерак­тивных документов, нередко используя встроенные программы на других языках, вроде JavaScript. PostScript рассматривает целый документ — на­пример эту книгу — как стилизованную программу. Электронные табли­цы и текстовые процессоры часто содержат в себе языки программирова­ния типа Visual Basic, они используются для вычисления выражений, доступа к информации, управления размещением данных в документе.

Если вы ловите себя на том, что приходится писать слишком много кода для выполнения рутинных операций, или если у вас возникают проблемы с тем, чтобы в удобной форме описать весь процесс, знайте — скорее всего, вы выбрали неправильный язык. Отсутствие правильного языка можно считать хорошим поводом написать его самостоятельно. Придумать свой язык вовсе не означает создать преемника Java: просто нередко самые за­путанные проблемы проясняются при выборе должной нотации. В связи с этим вспомните форматные строки семейства printf, которые дают нам компактный и выразительный способ для управления выводом.

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

Предыдущая статья:Переносимость и внесение усовершенствований Следующая статья:Форматирование данных
page speed (0.0116 sec, direct)