A Web é uma plataforma ideal para desenvolver aplicativos e serviços com alcance mundial. Para criar um aplicativo que tenha verdadeiro apelo global, é necessário adaptá-lo ao processo e exibir dados em diversos idiomas e sistemas de escrita.
Um aplicativo é adaptado para outro idioma em diversas fases, a primeira das quais é a chamada internacionalização, frequentemente abreviada como i18n. O objetivo da internacionalização é garantir que os usuários possam utilizar seu idioma e notações no aplicativo, incluindo caracteres especiais para entrada e exibição de dados, exibindo números e datas no formato adequado e classificando listas de acordo com as regras específicas do idioma.
A abordagem mais avançada também inclui localização (abreviada como l10n). Durante a localização, o aplicativo é adaptado para dar suporte a hábitos culturais, linguísticos e locais específicos. Esse processo envolve tradução para o idioma local; a configuração adequada de formatos de datas, números e moedas; regras de classificação; etc.
Este artigo apresenta os novos recursos do PHP V5.3 que aperfeiçoam sua habilidade de criar aplicativos internacionalizados em PHP. O artigo não lida com o problema da localização em geral — especialmente com tradução; essa tarefa é mais bem abordada por bibliotecas PHP adicionais, como gettext do GNU (consulte Recursos).
Um aplicativo adequadamente internacionalizado deve ser capaz de processar dados escritos em diferentes sistemas de escrita. Inglês e outros idiomas usados na Europa Ocidental são baseados no sistema de script latino e usam somente caracteres latinos — algumas vezes com acentos adicionados (sinais diacríticos). Conforme avançamos para o oriente, encontramos os alfabetos cirílicos, os sistemas hebraico e árabe no Oriente Médio e diversos alfabetos indianos. Então há o chinês, o japonês e uma dúzia de outros sistemas de script orientais. A maioria dos sistemas de caracteres usados mais ou menos comumente estão inclusos no conjunto de caracteres Unicode (consulte Recursos para obter mais informações).
Entretanto, os caracteres Unicode são apenas abstrações. Sistemas de computador precisam codificar caracteres Unicode quando armazenados na memória ou em disco ou quando transferidos pela rede. Diversas codificações são usadas para Unicode: as duas mais populares são UTF-8 e UTF-16. Ambientes de desenvolvimento modernos como a tecnologia Java™ e o Microsoft® .NET Framework usam Unicode e possuem tipos de dados para caracteres e sequências de caracteres Unicode. Trabalhar com texto que usa caracteres Unicode é, então, completamente transparente para os desenvolvedores. É responsabilidade das funções da biblioteca lidar corretamente com todas as entradas e saídas (UI, formulários HTML, o banco de dados, XML) e, se necessário, transformá-las para codificação interna usada para a representação de sequências de caracteres Unicode.
Infelizmente, a linguagem PHP ainda carece de suporte Unicode adequado. Embora desenvolvedores de PHP central estejam pensando sobre adicionar suporte Unicode ao PHP desde 2001, nem sequer PHP V5.3 o inclui. Entretanto, esse suporte está planejado para o próximo importante release — PHP V6.
Superando o suporte Unicode ausente em PHP
A falta de suporte Unicode em PHP é desagradável, mas há soluções alternativas que permitem desenvolver aplicativos internacionalizados adequados mesmo em PHP. O primeiro problema que precisa ser solucionado é a representação adequada de dados Unicode. PHP usa as chamadas cadeias binárias de caracteres — em PHP, uma cadeia de caracteres não é uma sequência de caracteres Unicode, mas uma sequência de bytes. É possível armazenar internamente todas as sequências de caracteres em codificação UTF-8 e certificar-se de que todas as entradas e saídas do script sejam adequadamente codificadas e decodificadas.
Em teoria, é possível usar outras codificações além de UTF-8, mas UTF-8 cria menos problema que os outros sistemas. Muitas bibliotecas PHP já esperam que sequências de caracteres sejam codificadas em UTF-8, incluindo todas as funções que funcionam com XML e a recentemente adicionada biblioteca intl. Para trabalhar de maneira mais tranquila com sequências de caracteres codificadas em UTF-8, é melhor codificar caracteres em UTF-8 e enviar saída de scripts em UTF-8.
Ainda assim, transformar tudo em UTF-8 não resolve nada. Se você codificar um caractere latino com um acento ou caractere não latino em UTF-8, obterá dois, três ou quatro bytes, o que confunde as funções de cadeia de caracteres do PHP que calculam o comprimento da sequência de caracteres ou trabalham com subsequências de caracteres. A Listagem 1 demonstra esse problema.
Listagem 1. Problemas relacionados a suporte inadequado a Unicode em PHP
<?php
Header("Content-type: text/plain;charset=utf-8");
$text["en"] = "The Hitchhiker's Guide to the Galaxy";
$text["es"] = "Guía del autoestopista galáctico";
$text["cs"] = "Stopařův průvodce po Galaxii";
$text["ru"] = "Путеводитель хитч-хайкера по Галактике";
$text["ja"] = "銀河ヒッチハイク・ガイド";
foreach($text as $lang => $t)
{
echo $lang, ": ", $t, " (", strlen($t), " vs. ", mb_strlen($t, "utf-8"), ")\n";
}
?>
|
A saída dessa listagem é mostrada na Figura 1.
Figura 1. Funções de cadeia de caracteres PHP simples retornam resultados inadequados para texto codificado em UTF-8

Como se pode ver, o comprimento das sequências de caracteres escritas em diversos sistemas de escrita é calculado incorretamente. Somente para texto contendo letras do alfabeto latino um resultado correto é retornado. Nesse caso, é possível solucionar o problema usando funções da biblioteca mbstring (consulte Recursos). Assim, para obter o comprimento correto da cadeia de caracteres codificada em UTF-8, é necessário usar mb_strlen(string, "utf-8"), em vez de somente strlen(string).
Quando seus scripts estão processando dados em UTF-8, você está pronto para adicionar mais recursos de internacionalização com a biblioteca intl.
A biblioteca intl é um wrapper de PHP da famosa biblioteca International Components for Unicode (ICU) (consulte Recursos). Muitos aplicativos usam ICU para implementar suporte Unicode e de localização adequado.
A biblioteca intl é uma parte padrão do PHP desde a V5.3. Se você possui o PHP V5.3 ou posterior, a biblioteca deve estar disponível para uso. Para versões mais antigas do PHP, ainda é possível usar a biblioteca através de uma extensão PECL.
Trabalhando com códigos do idioma
A combinação de idioma, região, sistema de escrita e outros parâmetros que controlam a localização é conhecida como código do idioma. O código do idioma normalmente é identificado por um tag de idioma como definido em IETF Best Current Practices (BCP) 47 (consulte Resources para obter mais informações). Por exemplo, inglês será identificado pela tag simples en. Alguns idiomas historicamente evoluíram em diferentes regiões e hoje possuem diferenças significativas. Para lidar com essa situação, é possível anexar um identificador de país após o identificador de idioma. Por exemplo, pt_PT identifica português como usado em Portugal, enquanto pt_BR denota o português como usado no Brasil. O BCP 47 oferece um controle muito mais refinado, mas para fins de brevidade, este artigo não fornece mais detalhes sobre identificadores de códigos do idioma.
Todas as funções e métodos intl que reconhecem o código do idioma aceitam um tag de idioma como o identificar do código do idioma. Ainda, a biblioteca intl fornece uma interface dupla — funcional e orientada a objeto. É possível escolher a interface adequada dependendo do seu estilo de codificação PHP. Por exemplo, há uma função/um método que retorna o nome do idioma para um código do idioma no idioma escolhido. Usando a notação funcional, é possível chamar o código usando o seguinte:
// return name of language used for "en" locale in French (fr)
echo locale_get_display_language("en", "fr"); // Anglais
|
Se você prefere a abordagem orientada a objeto, é possível usar o método estático correspondente:
// return name of language used for "en" locale in French (fr)
echo Locale::getDisplayLanguage("en", "fr"); // Anglais
|
A classe Locale fornecida na biblioteca intl define métodos de utilitário úteis. Alguns exemplos são fornecidos na Listagem 2.
Listagem 2. Uso dos métodos na classe Locale
<?php
Header("Content-type: text/plain; charset=utf-8");
// display name of Portuguese as used in Brazil in different languages
echo Locale::getDisplayName("pt_BR", "en"), "\n";
echo Locale::getDisplayName("pt_BR", "de"), "\n";
echo Locale::getDisplayName("pt_BR", "ru"), "\n";
echo Locale::getDisplayName("pt_BR", "ja"), "\n";
// return preferred locale set in user's browser
echo "Preferred locale from browser: ",
Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
?>
|
O script produz o nome do idioma (Português) e o nome do país (Brasil) em diversos códigos do idioma diferentes. Ainda, o método acceptFromHttp(), que pode ser usado para ler o código do idioma preferido que um usuário definiu, é mostrado. A Figura 2 mostra a saída dessa listagem.
Figura 2. Saída do código da Listagem 2

Em um primeiro relance, formatar números pode parecer uma tarefa fácil. Mas quando é preciso lidar com todos os detalhes entediantes — os diferentes separadores e agrupadores de decimais usados em diferentes idiomas, por exemplo— você gostará de poder usar o intl para fazer isso por você. Além de formatação de números e moedas, o intl lida com tarefas mais sofisticadas, como escrever números corretamente —novamente, não apenas para o inglês, mas para muitos códigos do idioma suportados.
Formatação está disponível como funções, iniciando com o prefixo numfmt_, ou como métodos, como na classe NumberFormatter. Os exemplos neste artigo usam o estilo orientado a objeto, mas é possível obter os mesmos resultados usando uma abordagem funcional.
Antes de formatar, é preciso criar uma nova instância do NumberFormatter. É preciso fornecer um identificador de código do idioma e um estilo de formatador como parâmetros para o método de construção. É possível especificar o estilo usando diversas constantes predefinidas, como NumberFormatter::DECIMAL (formato decimal), NumberFormatter::CURRENCY (formato de moeda), NumberFormatter::SCIENTIFIC (formato científico) e NumberFormatter::SPELLOUT (o número será escrito corretamente). Por exemplo:
$fmt = new NumberFormatter("en", NumberFormatter::SPELLOUT);
|
Em um formatador recentemente criado, é possível salvar diversos métodos. Os mais úteis provavelmente são format() para formatar números e formatCurrency() para formatar quantias. O último método aceita um código de moeda como um segundo parâmetro. O uso dos métodos é mostrado na Listagem 3.
Listagem 3. Uso dos métodos na classe
FormatNumber
<?php
Header("Content-type: text/plain; charset=utf-8");
// Locale-aware number formatting
$fmt = new NumberFormatter("en", NumberFormatter::DECIMAL);
echo $fmt->format(19841984.123456), "\n";
// Spelling out numbers in English
$fmt = new NumberFormatter("en", NumberFormatter::SPELLOUT);
echo $fmt->format(1984), "\n";
// Spelling out numbers in Russian
$fmt = new NumberFormatter("ru", NumberFormatter::SPELLOUT);
echo $fmt->format(1984), "\n";
// Formatting Euro and Czech crowns in German
$fmt = new NumberFormatter("de", NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(123456.789, "EUR"), "\n";
echo $fmt->formatCurrency(123456.789, "CZK"), "\n";
// Formatting Euro and Czech crowns in Czech
$fmt = new NumberFormatter("cs", NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(123456.789, "EUR"), "\n";
echo $fmt->formatCurrency(123456.789, "CZK"), "\n";
?>
|
Como a saída na Figura 3 mostra, separadores decimais e agrupamento adequado são usados ao formatar o número decimal. Se você conhece os idiomas inglês e russo, é possível verificar se o número está escrito corretamente. E, por fim, é possível ver que alguns códigos de moedas como EUR estão formatados como €, enquanto outros estão presentes em formas localizadas — por exemplo, a Coroa Tcheca (CZK) está escrita em tcheco como Kč.
Figura 3. Saída do script da Listagem 3

Em muitos aplicativos, os dados podem ser classificados antes de serem exibidos. Mas regras de ordenação para idiomas que não o inglês podem ser complexas. Caracteres com acentos normalmente são tratados de uma maneira especial; alguns idiomas tratam sequências selecionadas de dois caracteres como uma letra para classificar (por exemplo, ch em tcheco e espanhol tradicional). Felizmente, a biblioteca intl fornece a classe Collator (e funções de sombra com nomes iniciando com collator_), que você pode usar para comparar e classificar sequências de caracteres com relação ao seu código do idioma selecionado.
Antes de comparar ou classificar, é preciso criar o novo intercalador e especificar um código do idioma para ele: $coll = new Collator("en_US");.
Agora á possível chamar diversos métodos no objeto criado. Por exemplo, o método compare() compara duas sequências de caracteres; os métodos sort() e asort() classificam arrays ou arrays associativas de maneira semelhante às funções de array do PHP correspondentes. O código na Listagem 4 mostra como é possível classificar uma array de palavras em tcheco baseadas de maneira diferente no código do idioma usado para o intercalador.
Listagem 4. Ordenando com diferentes códigos do idioma
<?php
Header("Content-type: text/plain; charset=utf-8");
// words to sort
$words = array("čočka", "čekanka", "cena", "chalupa",
"ťululum", "dálnopis", "tyfus", "traktor");
// sort using built-in PHP sort function
sort($words);
echo "Words sorted using built-in sort function:\n";
var_export($words);
// sort according to English rules
$coll = new Collator("en_US");
$coll->sort($words);
echo "\n\nWords sorted according to English rules:\n";
var_export($words);
// sort according to Czech rules
$coll = new Collator("cs");
$coll->sort($words);
echo "\n\nWords sorted according to Czech rules:\n";
var_export($words);
?>
|
Se você classificar palavras usando a função integrada sort() do PHP, as palavras iniciando com letras acentuadas estão no final, porque o PHP compara sequências de caracteres como valores binários e não trata letras acentuadas de uma maneira especial. Entretanto, se você classificar as mesmas palavras usando um intercalador criado para inglês, as palavras são classificadas como se os acentos fossem ignorados — comportamento desejado se você possui algumas poucas palavras estrangeiras em um texto em inglês. No final, um intercalador tcheco é usado. Como se pode ver, regras estranhas agora são aplicadas: alguns caracteres acentuados são tratados como não acentuados (por exemplo, ť), alguns são tratados como caracteres separados (por exemplo, c e č) e ch é tratado como um caractere especial. A Figura 4 mostra o resultado do código na Listagem 4.
Figura 4. Saída do script da Listagem 4

Unicode e internacionalização é um amplo tópico, mas você deve conhecer pelo menos mais um elemento importante. Por motivos históricos, Unicode permite representações alternativas dos mesmos caracteres. Por exemplo, á pode ser escrito tanto como um caractere pré-composto á com o ponto de código Unicode U+00E1 quanto como uma sequência decomposta da letra a (U+0061) combinada com o acento ´ (U+0301). Para fins de comparação e classificação, essas duas representações devem ser consideradas iguais.
Para solucionar isso, a biblioteca intl fornece a classe Normalizer. Essa classe, por sua vez, fornece o método normalize(), que pode ser usado para converter uma cadeia de caracteres em uma forma normalizada composta ou decomposta. Seu aplicativo deve transformar de maneira consistente todas as sequências de caracteres em uma ou outra forma antes de realizar comparações.
echo Normalizer::normalize("a´, Normalizer::FORM_C); // á
echo Normalizer::normalize("á", Normalizer::FORM_D); // a´
|
Este breve artigo apresentou a funcionalidade mais importante e útil que a biblioteca intl fornece. Essa biblioteca tornou-se uma parte padrão do PHP V5.3. A biblioteca oferece muito mais funcionalidade que este artigo poderia abordar—por exemplo, formatação de data e análise de valores armazenados em formatos localizados. Para mais informações, consulte o manual do PHP em PHP.
| Descrição | Nome | Tamanho | Método de download |
|---|---|---|---|
| Source code for this article | php-unicode_source.zip | 4KB | HTTP |
Informações sobre métodos de download
Aprender
-
A seção de Funções de Internacionalização do manual do PHP inclui referências para todas as funções e classes
intl. -
O Unicode Consortium é o recurso mais autorizado sobre Unicode.
-
Leia o padrão BCP 47 para combinar tags de idioma.
-
Leia "The future of PHP" para saber mais sobre as alterações planejadas para o PHP V6.
-
Consulte "What's new in PHP V5.3" para saber mais sobre alterações no PHP V5.3.
-
PHP.net é o recurso central dos desenvolvedores de PHP.
-
Consulte a "Lista de leituras recomendadas em PHP."
-
Navegue por todo o conteúdo PHP do developerWorks.
-
Siga o developerWorks no Twitter.
-
Expanda suas habilidades em PHP consultando os recursos de projetos em PHP do IBM developerWorks.
-
Para ouvir entrevistas e discussões interessantes para desenvolvedores de software, consulte os podcasts do developerWorks.
-
Usando um banco de dados com PHP? Consulte Zend Core para IBM, um ambiente de desenvolvimento e produção PHP perfeito, inovador e fácil de instalar que suporta IBM DB2 V9.
-
A comunidade My developerWorks é um exemplo de comunidade geral de sucesso que abrange uma ampla gama de tópicos.
-
Mantenha-se atualizado com os eventos e webcasts técnicos do developerWorks.
-
Consulte as próximas conferências, feiras, webcasts e outros Eventos em todo o mundo que sejam de interesse dos desenvolvedores IBM de software livre.
-
Visite a Zona de software livre do developerWorks para obter informações abrangentes sobre procedimentos, ferramentas e atualizações de projetos que simplificam o desenvolvimento de tecnologias de software livre e a utilização destas com produtos IBM; e não deixe de passar pelos nossos artigos e tutoriais mais populares.
-
Assista e aprenda sobre a IBM e as tecnologias e funções de produtos de software livre com as demos on demand do developerWorks grátis.
Obter produtos e tecnologias
-
GNU
gettext: Consulte essa biblioteca de tradução do PHP. -
Biblioteca
mbstring. Faça download e saiba mais sobre essa biblioteca de internacionalização. -
Faça download e saiba mais sobre a biblioteca ICU.
-
Inove em seu próximo projeto de desenvolvimento de software livre com o software de avaliação da IBM, disponível para download ou em DVD.
- Faça download das versões de avaliação de produtos IBM ou explore as avaliações on-line no IBM SOA Sandbox e utilize as ferramentas de desenvolvimento de aplicativos e produtos de middleware do DB2®, Lotus®, Rational®, Tivoli® e WebSphere®.
Discutir
-
Consulte o archive Internationalization archives de Unicode do PHP e a lista i18N.
-
Participe dos blogs developerWorks e envolva-se na comunidade do developerWorks.
-
Participe do Fórum PHP developerWorks: Desenvolvendo aplicativos PHP com produtos IBM Information Management (DB2, IDS).

Jirka Kosek é consultor autônomo de XML e professor na University of Economics em Praga. Ele tem mais de 10 anos de experiência em fornecer consultoria e treinamento em XML e é um integrante ativo em diversos órgãos de padronização, incluindo OASIS (DocBook TC e RELAX NG TC), W3C (XSL WG e ITS WG) e ISO/IEC JTC1/SC34. Jirka é autor de diversos livros e artigos sobre tecnologias da Web. Em seu tempo livre, ele contribui com código no projeto de software livre de folhas de estilo do DocBook XSL. Confira seu mais recente trabalho e ideias no seu blog.