POWERMAN
"In each of us sleeps a genius...
and his sleep gets deeper everyday."

Abstract

Пора перевести систему с koi8-r на utf-8: появляется всё больше софта, который заточен под utf-8 и глючит с koi8-r с одной стороны, и, думаю, практически в весь софт уже успели добавить поддержку utf-8 с другой стороны (октябрь 2008).

Исходная документация

В этих howto информация довольно сильно устарела, кроме того на моей системе хватает софта не описанного в этих howto. Но, тем не менее, они мне очень помогли:

Сам процесс

Разумеется, начать рекомендуется с полного обновления системы (включая софт из моего оверлея).

Шрифт

Устанавливаем terminus, просто на всякий случай, чтобы был хоть один точно нормальный шрифт.

echo '=media-fonts/terminus-font-4.28' >> /etc/portage/package.keywords
echo 'media-fonts/terminus-font ru-dv ru-g ru-i' >> /etc/portage/package.use
emerge -av terminus-font

Теперь мой шрифт (я его перевёл в unicode).

echo 'media-fonts/developer-font' >> /etc/portage/package.keywords
emerge -av developer-font

Для подключения к X нужно в /etc/X11/xorg.conf прописать путь к нему:

FontPath    "/usr/share/fonts/developer/"

Если был установлен предыдущий вариант этого шрифта, то его можно удалить из /etc/X11/xorg.conf (/usr/share/fonts/russify/). Впрочем, конфликтовать они не будут, у них немного отличаются имена:

# старый, только koi8-r, из media-fonts/russify:
-powerman-developer-bold-r-*-*-24-*-*-*-*-*-koi8-r
# новый, iso10646-1/koi8-r/microsoft-cp1251, из media-fonts/developer:
-powerman-developer-medium-r-*-*-24-*-*-*-*-*-koi8-r
-powerman-developer-medium-r-*-*-24-*-*-*-*-*-iso10646-1

Локаль

Проверка наличия локали ru_RU.utf8 (если её нет - надо будет её установить, как это сделать описано везде):

locale -a | grep ru

Установка локали. В файле /etc/env.d/99local должно быть:

LANG="ru_RU.UTF-8"
LC_NUMERIC="C"

Больше в файлах /etc/env.d/* не должно быть ни одного упоминания LANG или LC_.

Консоль

/etc/runit/1, в LOADKEYS():

/usr/bin/kbd_mode -u
/bin/loadkeys koi2
dumpkeys -c koi8-r | loadkeys --unicode

/etc/setfont (или ter-k16n для Terminus):

setfont dev-k16n -C /dev/$1
echo -n $'\033%G' >/dev/$1

Портаж

В /etc/make.conf:

  • добавить USE-флаг "unicode"

  • убрать USE-флаг "slang" (он нужен только mc, остальным он всё портит)

Пересобрать что нужно и поставить полезные утилитки:

emerge -uDNa world
emerge -a enca xsel convmv

Пересобрать все пакеты использующие ncurses (чтобы они увидели поддержку юникода в ncurses и могли, при желании, слинковаться с /lib/libncursesw.so.5 вместо /lib/libncurses.so.5):

revdep-rebuild -i --library /lib/libncurses.so.*
revdep-rebuild -i --library /usr/lib/libslang.so.*

XTerm

В ~/.Xdefaults прописать юникодный шрифт:

XTerm*font:      -powerman-developer-medium-r-normal-*-24-*-*-*-*-*-iso10646-1
XTerm*boldFont:  -powerman-developer-medium-r-normal-*-24-*-*-*-*-*-iso10646-1

Less

В /etc/env.d/99local удалить:

LESSCHARSET="latin1"

Man pages

В /etc/man.conf добавить per rectum поддержку русского:

NROFF      /usr/bin/enconv -L ru -x KOI8-R | /usr/bin/nroff -Tlatin1 -c -mandoc | /usr/bin/enconv -L ru -x UTF-8

Файлы: имена

Файлы с русскими именами на линуховых разделах нужно переименовать из koi8-r в utf-8.

Перекодировать имена файлов в текущем каталоге, рекурсивно, с помощью convmv:

convmv -f koi8-r -t utf8 -r ./                      # dry run
convmv -f koi8-r -t utf8 -r --notest ./             # СТРАШНО?!
Warning Если будет желание запустить в корне, то файлы на подмонтированных виндовых разделах будут испорчены (в смысле, тоже переименованы).
Warning В момент запуска convmv локаль должна быть koi8-r (т.е. чтобы ls корректно показывал имена файлов).

Я запускал:

convmv -f koi8-r -t utf8 -r --notest /home/ /tmp/ /var/www/

Файлы: содержимое

Подумать, какие файлы конвертировать:

  • часть файлов уже в UTF-8

  • часть файлов бинарные

  • нужно ли конвертировать проекты

Содержимое файлов в текущем каталоге, рекурсивно, можно перекодировать через enconv. Он достаточно умный, а кроме того можно параметрами find уточнить для каких файлов его запускать, а для каких нет.

find -type f -exec enca   -L ru -x UTF-8 {} +       # dry run
find -type f -exec enconv -L ru -x UTF-8 {} +       # СТРАШНО?!

Может потребоваться дополнительно изменить при конвертации некоторых файлов:

  • в html поменять <meta…charset…>

  • в cgi поменять charset в HTTP-заголовках ($HEADER{-Charset})

Монтирование виндовых разделов

Для FAT и ISO9660: iocharset=utf8 (или в ядре как default, или в /etc/fstab).

Для NTFS: nls=utf8 (или в ядре как default, или в /etc/fstab).

Vim

Изменить в ~/.vimrc:

#set fileencodings=koi8-r
set fileencodings=ucs-bom,utf-8,koi8-r,default
#set langmap=....................
map ё `
map й q
map ц w
map у e
map к r
map е t
map н y
map г u
map ш i
map щ o
map з p
map х [
map ъ ]
map ф a
map ы s
map в d
map а f
map п g
map р h
map о j
map л k
map д l
map ж ;
map э '
map я z
map ч x
map с c
map м v
map и b
map т n
map ь m
map б ,
map ю .
map Ё ~
map Й Q
map Ц W
map У E
map К R
map Е T
map Н Y
map Г U
map Ш I
map Щ O
map З P
map Х {
map Ъ }
map Ф A
map Ы S
map В D
map А F
map П G
map Р H
map О J
map Л K
map Д L
map Ж :
map Э "
map Я Z
map Ч X
map С C
map М V
map И B
map Т N
map Ь M
map Б <
map Ю >
Warning Если не удалить langmap, то можно будет вспомнить детство и попытаться выйти из vi - мне это не удалось. :-)

Так же нужно удалить все упоминания утилит xcb и xclip (использовались для перехвата Ctrl-Insert и Shift-Del), а вместо них добавить использование xsel:

""" Запоминание выделенного текста (в буфер VIM и в X Clipboad): Ctrl-Insert
""" Вырезание   выделенного текста (в буфер VIM и в X Clipboad): Shift-Del
vmap <silent> <Esc>[2;5~ y:call system("echo -n \"".escape(getreg(""),"\\\"$`")."\" \| xsel -i &")<CR>gvv
vmap <silent> <Esc>[3;2~ d:call system("echo -n \"".escape(getreg(""),"\\\"$`")."\" \| xsel -i &")<CR>

Чтобы снова заработало автодополнение русских слов по <Tab> нужно в ~/.vimrc в моей функции InsertTabWrapper заменить строку (ибо, как выяснилось, в Vi строковые функции с многобайтовыми кодировками не работают, а регулярные выражения - работают):

#if !col || getline('.')[col - 1] !~ '\k'
if !col || eval('getline(".") !~ ''\k\%'.col(".").'c''')

Samba

В /etc/samba/smb.conf в [global]:

dos charset = 866
unix charset = UTF-8
display charset = UTF-8

Conky

В ~/.conkyrc:

use_xft yes
xftfont Terminus:size=5
override_utf8_locale yes

Lynx

Либо в настройках выставить, либо в ~/.lynxrc:

character_set=UNICODE (UTF-8)

Mutt

В ~/.muttrc заменить везде koi8-r на utf-8.

xine-ui

Вероятно, это не имеет отношения к переходу на utf-8, но я разобрался как в нём настроить поддержку русского шрифта и увеличить его размер. Добавить в ~/.fonts.conf:

<!-- fix xine-ui russian font -->
<match target="pattern" >
    <test name="family" qual="any"> <string>Helvetica</string> </test>
    <test name="pixelsize" compare="eq"> <double>12</double> </test>
    <edit name="family">    <string>Verdana</string>  </edit>
    <edit name="pixelsize"> <double>14</double>         </edit>
</match>
<match target="pattern" >
    <test name="family" qual="any"> <string>Helvetica</string> </test>
    <test name="pixelsize" compare="less"> <double>12</double> </test>
    <edit name="family">    <string>Verdana</string>  </edit>
    <edit name="pixelsize"> <double>14</double>         </edit>
    <edit name="weight">    <const>medium</const>       </edit>
</match>

Эти настройки, к сожалению, не ограничены одним xine-ui, и будут влиять на другие приложения… но у меня других приложений использующих такие шрифты нет. В общем, криво, но это работает.

k3b

В настройках удалить пользовательские параметры для mkisofs (сейчас выставлено в -jcharset koi8-r).

MySQL

Приводим, наконец-то, MySQL в корректное состояние, когда информация о кодировках в таблицах соответствует действительности, а сам MySQL сервер готов работать с любыми кодировками. В /etc/mysql/my.cnf все упоминания latin1 заменяем на utf8, и удаляем строку:

init-connect='SET NAMES latin1'

Перезапускаем MySQL сервер (и ранее запущенные консольные mysql-клиенты).

Находим все таблицы/колонки, в которых некорректная информация о кодировке (например, стоит latin1 вместо koi8r) и исправляем их.

Пример конвертации таблицы asdfDict из базы DICT. Для начала меняем charset по умолчанию для всей базы, чтобы новые таблицы не создавались с latin1:

ALTER DATABASE DICT CHARACTER SET utf8;

Теперь выставляем корректный charset (koi8r) для нужных колонок таблицы asdfDict (enum поля оставим в latin1 - в них всё-равно только английский):

ALTER TABLE asdfDict DISABLE KEYS;
ALTER TABLE asdfDict CHARSET koi8r;
ALTER TABLE asdfDict MODIFY word VARBINARY(255) NOT NULL;
ALTER TABLE asdfDict MODIFY word VARCHAR(255) CHARACTER SET koi8r NOT NULL;
ALTER TABLE asdfDict DROP INDEX art_txt;
ALTER TABLE asdfDict MODIFY art_txt BLOB NOT NULL;
ALTER TABLE asdfDict MODIFY art_txt TEXT CHARACTER SET koi8r NOT NULL;
ALTER TABLE asdfDict ADD FULLTEXT KEY (art_txt);
ALTER TABLE asdfDict ENABLE KEYS;

Теперь эта таблица работает корректно. Но можно пойти дальше, и отконвертировать её в utf8. Это не обязательно, приведёт к увеличению занимаемого таблицей места (раза в полтора! но индекс практически не увеличится), и даст возможность хранить в ней не только англо-русские словари. :)

ALTER TABLE asdfDict DISABLE KEYS;
ALTER TABLE asdfDict CHARSET utf8;
ALTER TABLE asdfDict MODIFY word VARCHAR(255) CHARACTER SET utf8 NOT NULL;
ALTER TABLE asdfDict MODIFY art_txt TEXT CHARACTER SET utf8 NOT NULL;
ALTER TABLE asdfDict ENABLE KEYS;

xfontsel (и другие старые x-приложения)

Медленно запускается. Эта проблема решается установкой (и подключением в /etc/X11/xorg.conf) пакета media-fonts/intlfonts.

perldoc/man

Чтобы появился шанс на корректное отображение русской POD-документации, необходимо в POD прописать кодировку (и поставить свежий Pod::Man со CPAN):

=encoding koi8-r
=encoding utf-8

Дальше нужно или ждать, пока выйдут версии perldoc/pod2man/etc. которые умеют с этим корректно работать (их сейчас активно фиксят для этого), или заменить perldoc на вот такой скрипт (положить в ~/bin/perldoc):

#!/bin/bash
/usr/bin/perldoc -u "$@" |
   pod2man --utf8 |
   sed 's/IO::HANDLE=IO(0X........) 1/"" ""/' |
   enconv -L ru -x KOI8-R |
   nroff -Tlatin1 -c -mandoc |
   enconv -L ru -x UTF-8 |
   less -is

man работать от этого не начнёт, но он особо и не нужен, при работающем (через этот скрипт) perldoc.

Отличия в работе

  1. Имена файлов на FAT стали case-sensitive! %-)

  2. Чтобы заходить через ssh на машины с koi8:

    luit -encoding "KOI8-R" ssh ...
    
  3. Т.к. кодировка asciidoc указывается глобально в /etc/asciidoc/asciidoc.conf, то нужно или все .txt оставить в koi8-r, или ВСЕ отконвертировать в utf-8. IMHO лучше отконвертировать.

  4. Хотя существующие файлы Vim будет прозрачно редактировать и в koi8-r и в utf-8, но новые файлы он будет создавать в utf-8 - это может мешать при работе с проектами, которые ещё не отконвертированы в utf-8.

  5. Есть много способов copy&paste в X, и далеко не все корректно работают! Практически везде работают: выделение мышкой (xterm, vi, pidgin, opera) или режимом VISUAL в vi (если нужно выделить строки длиннее экрана), и вставка третьей кнопкой мышки.

    ИСКЛЮЧЕНИЕ 1

    из pidgin нельзя вставить мышкой в vi (вставляется \u0000), но можно через Shift+Insert.

    ИСКЛЮЧЕНИЕ 2

    из режима VISUAL в vi нельзя вставить в pidgin (ничего не вставляется), но можно вместо VISUAL использовать echo | xsel (я настроил vi делать это при нажатии Ctrl+Insert).

  6. Perl. Отличий море. Но старый код должен работать (за редкими исключениями, например: раньше этот код на вход получал koi8-r, а теперь будет получать utf8). Особенно это чувствуется по онлайнерам:

    $ echo "Привет" | perl -ne 'print if /Привет/'
    Привет
    $ echo "Привет" | perl -ne 'print if /привет/i'
    $ echo "Привет" | perl -C -ne 'use utf8; print if /привет/i'
    Привет
    

    здесь -C указывает что на STDIN идёт utf8 (и на STDOUT тоже пойдёт utf8), а use utf8 указывает, что в тексте скрипта используются не странные байты, а utf8.

Нерешённые проблемы

mc

Не знаю, как юникод поддерживается в mc-mp (если он вообще им хоть как-то поддерживается), но у mc мелкие проблемы есть:

  • F1 (помощь) нет русских букв (вроде лечится патчем при компиляции) это исправлено в app-misc/mc-4.7.0_pre1

  • в командной строке под таблицами, если в пути есть каталог с русскими буквами, позиция с которой начинается набор команды отодвигается (mc считает что русские буквы занимают по две позиции на экране) это исправлено в app-misc/mc-4.6.2_pre1

  • вверху, над панелью, если текущий путь выводится не полностью, причём он начинается с русской буквы, вместо этой буквы может быть её код (точнее, второй байт её кода) это исправлено в app-misc/mc-4.7.0_pre1

  • диалоги по F5/F6 слишком широкие и вылезают за границы экрана это исправлено в app-misc/mc-4.6.2_pre1

fluxbox

В заголовках окон нет русского. В меню, наверное, тоже нет.

gsview

В меню нет русского (лечится запуском с LANG=ru_RU.KOI8-R или LANG=). В именах файлов нет русского (пока не лечится). Русский в PDF работает.

У меня это единственное приложение использующее gtk+-1. IMHO проще заменить другим и окончательно избавиться от gtk+-1.

man

Если /usr/bin/man не находит запрошенную man-страницу, то он выдаёт сообщение об ошибке в некорректной кодировке.