Контрольный список для перехода в Unicode с помощью Perl
Я помогаю клиенту преобразовать свой сайт доски объявлений с плоским файлом Perl из ISO-8859-1 в Unicode.
Поскольку это мой первый раз, я хотел бы узнать, завершен ли следующий "контрольный список". Все хорошо работает в тестировании, но мне может не хватать чего-то, что происходило бы только в редких случаях.
Это то, что я сделал до сих пор (простите меня за включение только "сводных" примеров кода):
-
Убедитесь, что файлы всегда читаются и записываются в UTF-8:
use open ':utf8';
-
Убедитесь, что вход CGI получен как UTF-8 (сайт не использует CGI.pm):
s{%([a-fA-F0-9]{2})}{ pack ("C", hex ($1)) }eg; # Kept from existing code
s{%u([0-9A-F]{4})}{ pack ('U*', hex ($1)) }eg; # Added
utf8::decode $_;
-
Убедитесь, что текст напечатан как UTF-8:
binmode STDOUT, ':utf8';
-
Убедитесь, что браузеры интерпретируют мой контент как UTF-8:
Content-Type: text/html; charset=UTF-8
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
-
Убедитесь, что формы отправляют UTF-8 (возможно, не обязательно, если установлена кодировка страницы):
accept-charset="UTF-8"
-
Не думаю, что мне нужно следующее, поскольку встроенный текст (меню, заголовки и т.д.) находится только в ASCII:
use utf8;
Это выглядит разумно или я что-то не хватает?
EDIT: Я должен, вероятно, также упомянуть, что мы будем запускать одноразовый пакет для чтения всех существующих файлов текстовых данных и сохранения их в кодировке UTF-8.
Ответы
Ответ 1
-
Уровень :utf8
PerlIO
not достаточно строгий. Он допускает ввод, который удовлетворяет структурным требованиям последовательностей байтов UTF-8, но для хорошей защиты вы хотите отклонить материал, который на самом деле не является действительным Unicode. Замените его повсюду слоем PerlIO::encoding
, таким образом: :encoding(UTF-8)
.
-
По той же причине всегда Encode::decode('UTF-8', …)
, а не Encode::decode_utf8(…)
.
-
Сделать декодирование неудачным с исключением, сравните:
perl -E'use Encode qw(decode); say decode(q(UTF-8), qq(\x{c0})); say q(survived)'
perl -E'use Encode qw(decode); say decode(q(UTF-8), qq(\x{c0}), Encode::FB_CROAK); say q(survived)'
-
Вы не заботитесь о суррогатных парах в обозначениях %u
. Это единственная серьезная ошибка, которую я вижу в вашем списке. 2.
написано правильно:
use Encode qw(decode);
use URI::Escape::XS qw(decodeURIComponent);
$_ = decode('UTF-8', decodeURIComponent($_), Encode::FB_CROAK);
-
Не вмешивайтесь в функции из модуля utf8
. В его документации так говорится. Он предназначен как прагма для указания Perl, что исходный код находится в UTF-8. Если вы хотите сделать кодирование/декодирование, используйте модуль Encode
.
-
В любом случае добавьте прагму utf8
в каждом модуле. Это не может повредить, но вы будете поддерживать будущий код в случае, если кто-то добавит эти строковые литералы. См. Также CodeLayout::RequireUseUTF8
.
-
Используйте encoding::warnings
, чтобы выкурить оставшиеся неявные обновления. Подтвердите для каждого случая, нужно ли это/необходимо. Если да, преобразуйте его в явное обновление с помощью Unicode::Semantics
. Если нет, это намек на то, что раньше вы должны были выполнить шаг декодирования. Документы из http://p3rl.org/UNI дают совет немедленно декодировать после получения данных из источника. Перейдите по местам, где код считывает/записывает данные и проверяет, что у вас есть шаг декодирования/кодирования, либо явно (decode('UTF-8', …)
), либо неявно через слой (use open
pragma, binmode
, 3 аргумента формы open
).
-
Для отладки: если вы не знаете, какая строка находится в переменной, в которой представление в определенное время, вы не можете просто print
, используйте инструменты Devel::StringInfo
и Devel::Peek
.
Ответ 2
Ты всегда чего-то пропускаешь. Проблема, как правило, неизвестные неизвестные.:)
Эффективное программирование на Perl содержит раздел Unicode, который охватывает многие основы Perl. Один элемент, который мы не рассматривали, - это все, что вам нужно сделать, чтобы ваш сервер базы данных и веб-сервер поступали правильно.
Некоторые другие вещи, которые вам нужно сделать:
-
Обновите свой последний Perl. Unicode стало намного проще в 5.8, а еще проще в 5.10.
-
Убедитесь, что содержимое сайта преобразовано в UTF-8. Вы можете написать сканер для попадания страниц и поиска символа замещения Юникода (эта вещь, которая выглядит как алмаз с вопросительным знаком в нем). Посмотрим, смогу ли я сделать это в StackOverflow: & # xfffd;
-
Убедитесь, что ваш сервер базы данных поддерживает UTF-8, что вы настроили таблицы с столбцами, поддерживающими UTF-8, и что вы сообщаете DBI использовать поддержку UTF-8 в своем драйвере (некоторые из этих находится в книге).
-
Убедитесь, что все, что смотрит на @ARGV, переводит элементы из локали командной строки в UTF-8 (это в книге).
Если вы найдете что-нибудь еще, сообщите нам, ответив на свой вопрос тем, что мы оставили.;)