Ir para o conteúdo
ou

Software livre Brasil

 Voltar a Porão do Tri...
Tela cheia

Convertendo softwares PHP de encoding ISO-8859-1 para UTF-8

2 de Fevereiro de 2012, 0:00 , por Software Livre Brasil - 0sem comentários ainda | Ninguém está seguindo este artigo ainda.
Visualizado 573 vezes

Hoje vamos falar de um assunto delicado, conversão de softwares ISO-8859-1 para UTF-8. A uma primeira olhada parece uma tarefa bem simples, mas não é. Passamos recentemente por um caso real : a conversão do conhecido Gnuteca – software de gerenciamento de acervos e bibliotecas. Apos tudo ficar 100% funciona, vamos dividir um pouco de nossas experiências. A quem possa interessar o Gnuteca passou para UTF-8 a partir da versão 3.3 que será disponibilizada a público ainda em Fevereiro.

Codificação dos arquivos fonte

Para que tudo funcione corretamente primeiramente precisamos converter a codificação de todos arquivos de fonte, para isso utilizamos a ferramenta iconv, atraveś de um script.

O script shell/bash detectará arquivos em ISO e tentará a conversão para UTF. Sim, alguns arquivos podem gerar erro na conversão devido posuírem caracteres estranhos em seu fonte, nesses casos a conversão precisa ser manual.

for FILE in $(find -type f -regex "^.*\.\(php\)$");
    do if [ $(file --mime "$FILE" | grep "iso-8859-1" | wc -l) -ne 1 ];
        then echo "Arquivo não iso: $FILE";
        else echo -n "Convertendo $FILE ... "; iconv -f iso-8859-1 -t utf-8 "$FILE" -o /tmp/1; if [ $? -ne 0 ];
        then echo " Erro na conversão";
        else echo " Pronto."; mv /tmp/1 $FILE; fi; fi;
    done

Apache (virtualhost/php.ini)

MBString no PHP significa Multybite String, isto que adiciona suporte a caracteres UTF-8.

http://br2.php.net/mbstring

Para ativar necessitamos adicionar alguns itens ao php.ini/virtualhost.

O exemplo abaixo exemplifica o caso do virtualhost.

    php_admin_value mbstring.func_overload 7
    php_value mbstring.internal_encoding UTF-8

Mbstring.func_overload determinada a quantidade de funções padrão que devem ser substituídas pelas versões mb (multybite), no caso serão as definidas pelas codificações UTF;

Mbstring.internal_encoding determina a codificação interna utilizada pelo php, no caso UTF.

str_pad

Infelizmente mesmo ativando o func_overload a contagem de caracteres através do strpad não funciona corretamente, pois não existe função mb_strpad. Então precisamos criar nossa própria versão do str_pad, com os mesmos parâmetros do original, para compatibilidade.

   /**
     * StrPad compatível com UTF8.
     *
     * @param string $input texto original
     * @param integer $pad_length quantidade de caracteres que ficará o pad
     * @param string $pad_string string para efetuar o pad
     * @param integer $pad_type tipo do pad
     * @return string
     */
    public static function strPad($input, $pad_length, $pad_string=' ', $pad_type=STR_PAD_RIGHT)
    {
        $diff = mb_strlen($input, 'ISO-8859-1') - mb_strlen($input, 'UTF-8');
        return str_pad($input, $pad_length+$diff, $pad_string, $pad_type);
    }

O código acima torna possível a utilização do str_pad em UTF-8.

Pode ser necessário fazer uma replace de str_pad por strPad em todo o sistema.

rpl 'str_pad(' 'strPad' * -R

Aplicar isso em todo o sistema pode ser desastroso, pois existem partes onde realmente é necessário manter o pad em ISO, como no caso do FPDF citado abaixo.

FFDF

A classe FPDF é um dos problemas específicos de classes que não suportam UTF-8,  nesse caso temos que criar uma classe nova que extende a FPDF modificando o comportamento no __construct e __destruct.

No construct incluímos uma definição forçando o PHP a trabalhar como ISO.

  function __construct($filePath = null, $orientation = 'P', $unit = 'mm', $format = 'A4')
    {
        //Necessário para pois a FPDF trabalha com ISO e utiliza funções de strings.
        ini_set('mbstring.internal_encoding', 'ISO-8859-1');

No destruct forçamos o PHP a UTF novamente.

    function __destruct()
    {
        //Habilita novamente o UTF-8 que é o padrão do gnuteca
        ini_set('mbstring.internal_encoding', 'UTF-8');
    }

Ainda necessitamos neste caso converter todo o texto passado para a classe para ISO. Para isso utilizamos a classe Gstring que detecta automaticamente qual a codificação do texto e converte para a codificação necessária.

    public function cell($w, $h, $txt, $border, $ln, $align, $fill, $link)
    {
 
        parent::Cell($w, $h, GString::construct($txt,'ISO-8859-1'), $border, $ln, $align, $fill, $link);
    }
 
    //Sobreescreve a função para alterar a codificação
    public function text($x, $y, $txt)
    {
        parent::Text($x, $y, GString::construct($txt,'ISO-8859-1'));
    }
 
    //Sobreescreve a função para alterar a codificação
    public function write($h, $txt, $link)
    {
        parent::Write($h, GString::construct($txt,'ISO-8859-1'), $link);
    }

Existem outras classes que somente funcionam em ISO no caso do Gnuteca tivemos que executar uma correção similar na classe GISORecord, que são especificamente registros em caracteres ISO.

GString

Montamos uma classe que trabalha automaticamente com string de qualquer codificação convertendo automaticamente para UTF-8 por padrão, ou outras codificações caso necessário, é muito mais segura que o utf8_encode/decode pois dectecta a codificação original, evitando assim um codificar uma string já codificada.

    $string  = new Gstring('meu texto em iso');
    echo $string ;

O resultado será o texto convertido para UTF-8, isso ocorre graças ao método mágico __toString.

Como a classe original ainda não está disponível no repositório oficial, divido-a aqui.  GString.class.php.

Header

Em alguns casos, caso persistam os problemas de codificação, nos casos específicos onde o browser não escolhe a codificação correta.

    header("Content-type: text/html; charset=utf-8");

Base de dados – Postgres

A conversão da base de dados normalmente é bem simples. Um dump e uma restauração normalmente eficientes.

Efetuamos o dump já em UTF8.

    pg_dump -Upostgres -hlocalhost base_em_iso -E utf-8 -f dump_em_utf.sql

Criamos a base de dados e restauramos o dump.

    createdb -Upostgres -hlocalhost base_em_utf -Eutf-8
    psql -Upostgres -hlocalhost base_em_utf -c '\i dump_em_uf.sql'

Mas isso nem sempre é o suficiente. Tivemos problemas com alguns caracteres estranhos, os sqls abaixo resolveram os casos específicos.

    UPDATE gtcmaterial SET content = REPLACE(content, chr(160), '#') WHERE  fieldid = '008' AND subfieldid = 'a';

Outros problemas possíveis

Webservices normalmente aplicam conversão de codificação de forma automática, mas existem casos, onde as strings são serializadas, por exemplo, utiliza-se serialize, ou base64, nem sempre isso funciona de forma limpa então pode ser necessário aplicar algumas das sugestões anteriores.

Banco de dados nem sempre lida corretamente com ligação entre base ISO e UTF8, então em alguns casos precisamos efetuar a conversão manualmente.

http://www.postgresql.org/docs/9.1/static/functions-string.html

Qualquer outro local do sistema que lide/utilize conversão de codificação pode ser um problema em potencial (utf8_encode/utf8_decode).


Fonte: http://trialforce.nostaljia.eng.br/?p=1181

0sem comentários ainda

Enviar um comentário

Os campos são obrigatórios.

Se você é um usuário registrado, pode se identificar e ser reconhecido automaticamente.