Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > utf-8, HTML::Template и warning


Автор: AlexPet 12.8.2008, 12:41
Добрый день!

Пытаюсь разобраться с utf-8 применительно к шаблонизатору HTML::Template
Итак, имеем: файл шаблона содержит символы в кодировке utf-8
1) Если вызывать $htmltmpl->output() без передачи в шаблон параметров (либо с передачей параметров, не содержащих утф8-символы), то отображается все как надо
2) Если же передавать параметры, содержащие символы в кодировке utf-8, то на выходе получаем:
а) кразобляки в тех местах, где в шаблоне юникод
б) нормальные символы там, где были переданы параметры юникодные

Пробовал всяческие комбинации с use open :utf8; binmode STDOUT, ":utf8"; utf8::*. Не получилось.
Нашел в интернете решение ( http://www.mail-archive.com/[email protected]/msg02273.html ), которое сводится к следующему:
Код

use utf8;
my $html = HTML::Template->new(filename => "template.tmpl", filter => \&tmpl2utf8);
sub tmpl2utf8 {
    my $ref = shift;
    utf8::decode(${$ref});
}

(можно конечно открывать файл самому темплейта, и при открытии указывать '<:utf8', а затем передавать его через filehandle => $fh, но это совсем некрасиво)

Вопрос: можно ли как-то изящнее решить данную проблему?

P.S. Сам я только начал работать с UTF-8, могу упустить какое очевидное решение  smile  
P.P.S. А warning в названии - это при использовании Encode::decode_utf8 вместо utf8::decode получался smile

Автор: Bulat 15.8.2008, 09:29
AlexPet, ммм даж не знаю поможет или нет, но просто 
Код

use utf8;


не пробовали ?? smile

Автор: AlexPet 18.8.2008, 08:38
Конечно пробовал smile
без толку. Пока нашел два решения (либо подключать темплейт как файловый дескриптор с указанием utf8 на open, либо через фильтр к темплейту.. об этом я, впрочем, написал выше)

Автор: Bulat 18.8.2008, 12:11
Цитата(AlexPet @  12.8.2008,  12:41 Найти цитируемый пост)
2) Если же передавать параметры, содержащие символы в кодировке utf-8, то на выходе получаем:
а) кразобляки в тех местах, где в шаблоне юникод
б) нормальные символы там, где были переданы параметры юникодные


Не совсем понял, т.е. в теории кодировка одна и та же, что в шаблоне, что у передаваемых параметров - utf8, но отображается по разному??

Автор: ginnie 18.8.2008, 12:54
Уважаемый AlexPet, есть еще пара вариантов:

1. Попробовать 
Код

use open IO  => ":encoding(utf8)";


2. Создать дочерний класс HTML::Template::Unicode, в котором переопределить функцию open():

Код

use subs qw(open);

sub open (*;$@) {
    my $pkg = caller();
    if(defined($_[0])) {
        use Symbol ();
        my $fh = Symbol::qualify($_[0], $pkg);
        no strict 'refs';
        if(@_ == 1) {
            return CORE::open($fh);
        } elsif(@_ == 2) {
            return CORE::open($fh, "<:encoding(UTF-8)", $_[1]);
        } else {
            return CORE::open($fh, $_[1], @_[2..$#_]);
        }
    } else {
        if(@_ == 1) {
            return CORE::open($_[0]);
        } elsif(@_ == 2) {
            return CORE::open($_[0], "<:encoding(UTF-8)", $_[1]);
        } else {
            return CORE::open($_[0], $_[1], @_[2..$#_]);
        }
    }
}

Автор: AlexPet 19.8.2008, 08:02
Bulat, в теории да, но HTML::Template использует хитрый алгоритм (который описан по ссылке выше):
Цитата

If a parameter contains wide characters (katakana, or accented latin
characters for example), then the bytes from the templates are made to
match the wide characters by translating the bytes to Unicode.  This is
done by interpreting the bytes as Latin-1 characters.

If the template file happens to contain Unicode already, this breaks:
the bytes making up an UTF-8 character are fed to the Latin => unicode
transformation, and you end up with characters that are encoded twice.



ginnie, по этой же причине не будет работать и первый предложенный Вами метод (поскольку модуль сам осуществляет перекодировки, и не всегда правильно). За второй метод спасибо, возьму на заметку, если нужно будет использовать в серьезном проекте. Пока что быстро слабал на коленке через фильтр smile

Очень странно, что до сих пор не закоммитили предложенное изменение в этот модуль. Все-таки проблема известная, и патч был предложен для ее решения (опять же по ссылке в моем первом посте)...

Всем спасибо за обсуждение, тему помечаю как решенную (будем ждать новых релизов хтмл::темплейт ;) )

Автор: Ramirez 20.8.2008, 10:04
Я так понимаю, если шаблон берется не из файла (из базы например) то этой проблемы не возникает?

Автор: AlexPet 20.8.2008, 12:22
Не совсем понял, что значит из базы (шаблон можно брать либо из файла, либо из файлового манипулятора), но решение в случае с файловым манипулятором я привел выше (через указание кодировки на поток)

Автор: Ramirez 22.8.2008, 11:37
Ну вот собственно как-то так:

Код

  my $t = HTML::Template->new( scalarref => $ref_to_template_text, 
                               option => 'value' 
                             );

  my $t = HTML::Template->new( arrayref => $ref_to_array_of_lines , 
                               option => 'value' 
                             );


где переменная $ref_to_template_text или $ref_to_array_of_lines содержит текст шаблона. А браться он может откуда угодно. Хоть динамически генерироваться. 

Автор: Vavilen 4.3.2012, 16:49
Цитата(AlexPet @  12.8.2008,  12:41 Найти цитируемый пост)
Нашел в интернете решение ( http://www.mail-archive.com/html-template-...t/msg02273.html ), которое сводится к следующему:

Код

use utf8;
my $html = HTML::Template->new(filename => "template.tmpl", filter => \&tmpl2utf8);
sub tmpl2utf8 {
    my $ref = shift;
    utf8::decode(${$ref});
}

(можно конечно открывать файл самому темплейта, и при открытии указывать '<:utf8', а затем передавать его через filehandle => $fh, но это совсем некрасиво)

Вопрос: можно ли как-то изящнее решить данную проблему?


Мне очень помогло Ваше решение! Спасибо!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)