от Rumen_Yotov(5-11-2004)

рейтинг (17)   [ добре ]  [ зле ]

Printer Friendly Вариант за отпечатване

Използване на уникод с Линукс (превод)
http://software.newsforge.com/article.pl?sid=04/10/27/1631244

Последният път ставаше дума за уникод и неговите предимства (бел.пр. има предишна обзорна статия за уникод, но мисля че тази е по-практичната). Ако сте решили, че искате да ползвате тези предимства, ето как да настройте една Линукс система от не-уникод кодиране към уникод такова.

Преди всичко проверете дали вече използвате уникод локал. Командата 'locale' извежда стойностите на променливите на средата, които имат отношение към настройката на локала. Пълно описание на техните стойности е налично в помощните (man) страници на локала. Обикновенно, наименованията на локала се състоят от код на език с малки букви, следван от долна черта (underscore) и кода на държава с големи букви (напр. en_US за американски английски). Имената на локали, които използват уникод кодиране допълнително завършват с ".UTF-8." Ако подобни имена присъстват в резултата след стартиране на 'locale' то Вие вече използвате уникод локал.

Ако все пак трябва да пренастройвате системата си, първо направете резервно копие на важните си файлове, тъй като ще трансформирате вашите дискови файлови системи. Забележете, че резервните копия направени преди трансформацията на файловата система и след нея са до известна степен несъвместими. Както отбелязахме преди това (в друга статия), операционната система и много програми не вземат предвид с какви символи е представено името на файла. Измежду програмите имащи този проблем е и 'tar' -програмата, която е един често използван инструмент за създаване на резервни копия. Ако в момента Вие използвате 'en_US' локал и някои имена на файлове съдържат символа "ä" (германско A umlaut), то той се представя от единичен байт: hex 0xE4. След като преминете към уникод (UTF-8), същата буква ще се представя от два байта: 0xC3 0xA4. Обаче нито файловата система нито 'tar' "знаят", че тези две различни последователности от байтове могат да представляват един и същ символ. Ако възстановите старото име на файл от резервно копие (бакъп) след преминаване към уникод локал, еднобайтова кодировка ще бъде използвана в името на възстановен файл, правейки името различно от това при новата (уникод) версия. При ползване на UTF-8 локал, този единичен байт няма да представлява "ä" а по-скоро невалидна UTF-8 последователност, и ще бъде представен чрез заместител или чрез осмично представяне само на 'грешния' байт. Така че, ако Вие възстановявате данни от стари копия или архиви след като преминете към UTF-8, може да се наложи да използвате програма за конвертиране, подобна на тази за която ще споменем по-долу върху имената на възстановените файлове за да може те да се изобразяват правилно.

Възможността да се ползва UTF-8 локал без да трябва да се инвестира прекалено много труд за постигането му, изисква glibc (GNU C library) версия 2.2 или по-нова (всяка относително съвременна дистрибуция би трябвало да я има). Можете да проверите Вашата версия стартирайки /lib/libc.so.6.

Следващият параграф представя стъпка по стъпка описание на начина по който да извършите трансформацията. Повечето операции, описани тук трябва да се извършат като администратор (root).

Задаване на локала

Определени променливи на средата казват на приложенията кой локал да се използва. По-често използваните променливи са:

* LC_ALL -- Когато е зададена, стойността на тази променлива припокрива (замества) стойностите на всички други LC_* променливи.
* LC_* -- Тези променливи контролират различни аспекти на локала. Например, LC_CTYPE контролира начина за трансформация от големи-към-малки букви, докато LC_TIME контролира формата за дата и време. LC_MESSAGES определя езика, използван в съобщенията от приложенията. Подробности могат да се видят в помощната страница на locale(7).
* LANG -- Ако LC_ALL не е зададено, тогава параметри на локала, чиито съответни LC_* променливи не са зададени получават стойността по подразбиране на LANG.

Преди да промените своя локал, не забравяйте да запазите във файл изходната информация от 'locale', която показва Вашият текущ локал. Също така, запишете някъде изходящата информация от 'locale -k LC_CTYPE | fgrep charmap' (Вашето текущо кодиране на символите), тъй като ще се нуждаете от тази информация по-късно.

За да посочите на приложенията да използват UTF-8 кодиране, и предполагайки, че U.S. английски е Вашият предпочитан език (за нас BG), може да използвате следната команда:

export LC_ALL=en_US.UTF-8

Приложения стартирани след това от същият терминален прозорец ще бъдат настроени за UTF-8. За да проверите дали това е така, можете например да използвате командата 'wc'. 'wc -c' ще Ви покаже броят на байтовете а 'wc -m' броят на символите в файл или данни, четени от стандартния вход (край на текста е Enter или Ctrl-D). При UTF-8 локал, ако текста съдържа не-ASCII символи, броя на байтовете ще бъде по-голям от броя на символите. Например:

user@host:~$ wc -c
Bär
5
user@host:~$ wc -m
Bär
4

Тази три-буквена дума е кодирана чрез 4-байта при UTF-8 (допълнителният символ или байт е маркера за край на ред).

Ако Вашият тест се провали (т.е. wc изведе един и същ брой при двата случая), то вероятно Вашата система не притежава UTF-8 - дефиниции на локал, и Вие ще трябва да използвате 'localedef' за да ги генерирате. Например, ако en_US.UTF-8 липсва, то може да го генерирате от 'en_US' използвайки:

localedef -i en_US -f UTF-8 en_US.UTF-8

Тъй като стойностите на променливите от обкръжението са валидни само в рамките на сесията, то трябва Вие да поставите Вашите команди за експорт в /etc/profile така че, те да бъдат стартирани за всеки потребител, когато следващият път той/тя се включва в системата. Ако работите в KDE, ще трябва да излезете и отново да влезете, така че променливите от обкръжението да бъдат прочетени отново и да бъдат активирани. GNOME изглежда винаги използва UTF-8 вътрешно, дори ако локала не е UTF-8-базиран. Без значение какъв десктоп-среда използвате, може да се наложи да излезете ако ползвате менажер за вход (т.е. KDM или GDM), рестартирайте X Window системата чрез натискане на 'Ctrl-Alt-Backspace' така че, /etc/profile да бъде прочетен наново и всички приложения да знаят за новия локал.

Конвертиране на файловите системи

Следващата стъпка е да се конвертират (трансформират) Вашите файлови системи. Това е единствената рискова част от преминаването (към UTF-8), така че, направете копие (бакъп) на всички важни данни от дисковете си ако все още не сте го направили.

Както бе отбелязано по-горе, ядрото на Linux не се интересува от кодирането на символите. За често използваните файлови системи (ext2, ext3, ReiserFS, и други файлови системи, типични за Юникс-ите), информацията че дадена файлова система използва едно или друго кодиране не се съхранява като част от файловата система. Само контролиращите локала променливи от обкръжението "казват" на софтуера че дадени байтове трябва да се изобразят като един или друг символ. Файловите системи работещи на Microsoft Windows машини (NTFS и FAT) са различни по това, че те съхраняват на диска имената на файловете използвайки дадено кодиране. Ядрото трябва да преведе това кодиране към системното кодиране, което ще бъде UTF-8 в нашият случай.

Ако във Вашата система имате Windows дялове, трябва да внимавате те да бъдат монтирани, използвайки правилните опции. За FAT и ISO9660 (използвано при CD-ROM-мите) дяловете, опцията 'utf8' кара системата да "преведе" кодирането на файловата система към UTF-8. За NTFS, nls=utf8 е препоръчаната опция (utf8 също би трябвало да работи). Добавете тези опции при монтиране на файлови системи от тези типове в Вашия /etc/fstab за да ги монтирате с правилните настройки. Фрагмент от /etc/fstab вероятно ще изглежда така (други опции могат да присъстват съобразно Вашите настройки):

/dev/hda2 /mnt/c ntfs defaults,ro,nls=utf8 1 0
/dev/hda3 /mnt/d vfat defaults,quiet,utf8 1 0
/dev/cdrom /mnt/cdrom iso9660 defaults,noauto,users,ro,utf8 0 0
# If using supermount, add "utf8" to the options _after_ two dashes, e.g.
#none /mnt/cdrom supermount fs=iso9660,dev=/dev/cdrom,--,auto,ro,utf8 0 0
/dev/fd0 /mnt/floppy auto defaults,noauto,users,rw,quiet,utf8 0 0

След като промените /etc/fstab, трябва да монтирате отново съответните файлови системи чрез 'mount -o remount /mnt/mount-point' командата за всяка една от тях. Не-ASCII символите в имената на файлове от тези файлови системи би следвало отново да се избразяват правилно. Забележете, че това изисква ядрото да може да конвертира правилно между различните символни набори, така че, поддръжката на UTF-8 трябва да бъде компилирана директно в ядрото или налична като модул. Тази опция се намира в "File systems"->"Native Language Support"->"NLS UTF-8" в програмата за конфигурация на ядрото. В зависимост от кое кодиране използват Вашите Windows дялове, също така може да се наложи да компилирате поддръжка за тяхното кодиране. Проверете тази страница [1] за списък от кодовите страници, използвани от различните езикови версии на FAT. NTFS винаги използва вътрешно Unicode и не се нуждае от никакви NLS опции на ядрото освен тези за UTF-8 поддръжка.

Собствените файлови системи на Линукс не съхраняват информация относно използваното кодиране, така че трябва Вие физически да промените имената на всички файлове към новото кодиране, за разлика от простото повторно монтиране на FAT и NTFS томовете. На теория всичко което трябва да направите е да изпълните:

mv original-filename filename-in-UTF-8-encoding

за всеки файл. На практика, нещата обикновенно са малко по-сложни. Преди всичко, може вече да имате UTF-8-кодирани файлови имена на диска си без да го знаете. Например, някои GNOME приложения създават UTF-8 файлови имена, независимо от използваният локал, и kbd (набор от програми зa работа с конзолните шрифтове) идва с примерен файл наречен ♪♬ (две музикални ноти) в документацията си. По време на конверсията тези файлове трябва да се идентифицират и техните имена да не се променят.

Друга особеност за която да се внимава са директориите. Тъй като и името на директорията и имената на файловете в нея може да се нуждаят от преименуване към техните UTF-8 еквиваленти, не можете просто да си създадете списък с всички файлове и директории и тогава да извършите 'mv old-name new-name' за всеки един/една от тях. Ако го направите и първо преименувате директория, след това пътят използван за достъп до файловете в нея няма повече да бъде валиден. Следователно редът е важен. В дървото на директориите, листата (т.е. файловете) трябва да бъдат преименувани първи, след това директориите от най-ниско ниво, след тях техните родителски директории и така нататък.

По-долу ще намерите скрипт, който опитва да извърши автоматично необходимите преобразувания. Имайте предвид, че неговото използване може да бъде опасно -- първо си съхранете важните данни! Въпреки че работи в повечето случаи, този скрипт не е безгрешен. За да запазим нещата прости, той не обработва някои специални случаи, като интервали вътре в пътища за монтиране (които реално са рядко срещани) и файлови системи, монтирани само за четене (не е очевидно какво трябва да се направи с тях; ако имате намерение да конвертирате дял от твърд диск, монтиран само за четене, ръчно го монтирайте отново за четене/писане чрез: 'mount -o remount,rw /some/mount/path' преди да изпълните скрипта). В зависимост от размера на файловата система и броя файлове които трябва да се конвертират, изпълнението на този скрипт може отнеме доста време, още повече че с оглед простота той е далеч от оптимален (всичко това вероятно може да бъде направено на Perl по много по-стегнат начин).

Не забравяйте да промените 'orgcharset' в скрипта по-долу към името на Вашето старо кодиране, което ще получите като резултат след изпълнение на една от предишните ни стъпки, използвайки: locale -k LC_CTYPE.

#!/bin/sh

fstab=/etc/fstab
orgcharset=INVALID_CHARSET_NAME

export LC_ALL=POSIX

# Find filesystems suitable for conversion
filesystems=`awk '!/vfat|ntfs|iso9960|udf|auto|autofs|swap|subfs|sysfs|proc|devpts|nfs|smbfs|^#/{print $2}' "$fstab"`
# Locate files whose names need to be converted and sort the list
find $filesystems -xdev | {
while read; do
# Check if the filename needs conversion (i.e. is not a correct UTF-8 string)
if ! echo `basename "$REPLY"` | iconv -f UTF-8 -t UTF-8 &>/dev/null; then
echo "$REPLY"
fi
done
} | sort -r | {
# Rename files
while read; do
dirname=`dirname "$REPLY"`
orgfname=`basename "$REPLY"`
newfname=`echo "$orgfname" | iconv -f "$orgcharset" -t UTF-8`
if [ $? -ne 0 ]; then
echo "Error: iconv failed for $REPLY. Skipping." >&2
continue
fi
mv "$REPLY" "$dirname"/"$newfname"
done
}

Конвертиране на текстови файлове

Нормално е за текстовите файлове на потребителя е да се ползва подразбиращото се системно кодиране, така че след преминаване към UTF-8 Вие вероятно искате също така да конвертирате своите текстови файлове. Конвертирането на конфигурационните файлове реално не е необходимо, тъй като програми които могат да обработват не-ASCII данни в своите конфигурации почти винаги вече използват UTF-8 за съхранение. Можете да конвертирате единичен текстови файл с 'iconv':

iconv -f old-encoding -t UTF-8 filename > temp.tmp && mv temp.tmp filename

Напомняне, проверете дали наистина работи преди да го използвате върху важни данни.

Намиране на символни набори (фонтове) с уникод поддръжка

Уникод символи за текстовата конзола обикновено са включени в по-големите Линукс дистрибуции. За да активирате уникод (UTF-8) в конзолата, стартирайте 'unicode_start' ('unicode_stop' за да се върнете към предишният еднобайтов метод на кодиране).

За да имате възможност наистина да виждате уникод символите, изобразявани от X-приложенията, е нужно да си свалите и инсталирате Уникод символни набори (fonts). Bitstream Vera е "TrueType font" който се разпространява под отворен лиценз и към момента се доставя с много Линукс дистрибуции. За съжаление той съдържа малко символи. Разширена версия, в която има поддръжка на повечето латински символи с ударения, се нарича Hunky Font. Фамилия от уникод символни набори, наречена 'FreeFont' също е налична под Общ Публичен Лиценз (GPL). Има също така няколко "free-as-in-beer" символни набори в Интернет, включително "Microsoft Core Fonts" (пакет съдържащ между другото и разпространените шрифтове "Arial" и "Times New Roman"), Bitstream Cyberbit (наличен е само Roman стил, но затова пък има много добра поддръжка на уникод), Gentium, и много други. Разбира се съществуват и много комерсиални символни набори, които могат да се използват в X.

Обобщение

Използването на уникод UTF-8 дава много предимства пред използването на еднобайтов локал. Най-малкото от тях е възможността да се използват всякакви символи в имената на файлове и в командния ред. Основното предимство на уникод, обаче, е в това че много по-лесно става обмена (прехвърлянето) на данни и се подобрява съвместимостта в сравнение с всеки един друг символен набор. UTF-8 е предназначен да замени ASCII в бъдеще, така че в някои момент "текстови файл" ще значи "UTF-8 файл" също както в настоящият момент той значи "ASCII файл".

Непрекъснато обновявана версия на тази статия може да се намери на уеб-сайта на автора.

Michał Kosmulski е студент във Варшавския университет и Варшавския университет за технологии.

Връзки

1. "Last time" - http://software.newsforge.com/article.pl?sid=04/10/27/1628230&tid=130
2. "locale man pages" - http://www.die.net/doc/linux/man/man1/locale.1.html
3. "environment variables" - http://en.wikipedia.org/wiki/Environment_variable
4. "this page" - http://www.microsoft.com/windowsxp/home/using/productdoc/en/default.asp?url=/WINDOWSXP/home/using/productdoc/en/country.asp
5. "Bitstream Vera" - http://www.gnome.org/fonts/
6. "Hunky Font" - http://www.yoper.com/ariszlo/hunky.html
7. "FreeFont" - http://www.nongnu.org/freefont/
8. "Microsoft Core Fonts" - http://corefonts.sourceforge.net/
9. "Bitstream Cyberbit" - http://ftp.netscape.com/pub/communicator/extras/fonts/windows/
10. "Gentium" - http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&item_id=Gentium
11. "Unicode Consortium" - http://unicode.org/
12. "Unicode page in Wikipedia" - http://en.wikipedia.org/wiki/Unicode
13. "UTF-8 page in Wikipedia" - http://en.wikipedia.org/wiki/UTF-8
14. "man page for UTF-8" - http://www.zevils.com/cgi-bin/man/man2html?utf8+7
15. "man page for Unicode" - http://www.zevils.com/cgi-bin/man/man2html?7+unicode
16. "UTF-8 and Unicode FAQ" - http://www.cl.cam.ac.uk/~mgk25/unicode.html
17. "Unicode HOWTO" - http://tldp.org/HOWTO/Unicode-HOWTO.html
18. "updated version of this article" - http://hektor.umcs.lublin.pl/~mikosmul/computing/articles/linux-unicode.html
19. "Michał Kosmulski" - http://hektor.umcs.lublin.pl/~mikosmul/
20. "Warsaw University" - http://www.uw.edu.pl/en/
21. "Warsaw University of Technology" - http://www.pw.edu.pl/english/index.html


<< Въведение в RSBAC, част II | САГА ЗА POSIX или УВОД В POSIX'ИВИЗМА >>