Programação para a Internet II 2.11. PHP i18n Nuno Miguel Gil Fonseca nuno.fonseca@estgoh.ipc.pt
Internacionalização Hoje em dia é cada vez mais usual desenvolver aplicações que suportem várias línguas Convém que se comece desde o início a pensar como se irá proceder para permitir ter o mesmo código a servir para apresentar conteúdos em várias línguas. Internacionalizar um site implica actuar em dois vectores principais: As labels e mensagens (de erro, por exemplo). A base de dados; Geralmente é usado o termo i18n quando se fala de internacionalização (internacionalization). (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 2
A base de dados Existem várias abordagens à internacionalização da base de dados de um site, no entanto a mais simples e eficaz consiste em associar à tabela de base de dados cujo conteúdo se pretende traduzir, uma outra tabela que contenha os campos passíveis de ser traduzidos. Por exemplo, para uma tabela de Produtos não faz sentido traduzir o preço ou a quantidade em stock, por exemplo. Exemplo da modelo físico da base de dados: Produtos Produtos_i18n Língua Id_Produto (PK) Prd_Nome Prd_Descricao Prd_Preco Prd_Quantidade Id_Produto_i18n (PK) Id_Produto (FK) Id_Lingua (FK) Prdi_Nome Prdi_Descricao Id_Lingua(FK) Lin_codigo Lin_Descricao (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 3
A base de dados (cont.) Exemplo dos dados contidos nas tabelas Produtos Id_Produto Prd_Nome Prd_Descricao Prd_Preco Prd_Quantidade 1 PC de Bolso Muito bom! 120 12 2 Disco externo 2000Gb 400 1 Produtos_i18n Id_Produto_i18n Id_Produto Id_Lingua Prdi_nome Prdi_Descricao 10 1 2 Pocket PC Very good 11 1 3 Ordinador de Muy bueno Língua Id_Lingua Lin_codigo Lin_Descricao 2 EN English 3 ES Castelhano (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 4
As labels e mensagens Resolvido o problema da base de dados, é chegada a altura de nos centrarmos no código. Geralmente em XHTML para escrever uma label ou uma mensagem de erro faz-se algo semelhante a: Nome: <input type="text" name="nome" /> <p>por favor insira o nome do utilizador!</p> Ou seja, o valor das labels ou mensagens está hard-coded (ou seja, inserido directamente no código) (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 5
As labels e mensagens modo simples O primeiro passo com vista à internacionalização do site, passa pela criação de ficheiros separados contendo variáveis com os valores de todas as labels e mensagens em cada língua. $label_nome = "Nome:"; $msg_ins_nome = "Por favor insira o nome do utilizador!"; Ficheiro i18n_pt.php $label_nome = "Name:"; $msg_ins_nome = "Please insert type the user name!"; Ficheiro i18n_en.php $label_nome = "Nombre:"; $msg_ins_nome = "Por favor escriba el nombre del usuário!"; Ficheiro i18n_es.php (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 6
As labels e mensagens modo simples (cont.) Em seguida, há que substituir as labels ou mensagens pelas respectivas variáveis print($nome); <input type="text" name="nome" /> <p> print($msg_ins_nome); </p> Para terminar esta parte seria apenas necessário colocar no início do ficheiro onde vão ser utilizadas as mensagens ou labels a inclusão do ficheiro que contem as variáveis include "i18n_pt.php"; No entanto, como vimos anteriormente, criámos diferentes ficheiros (um para cada língua) e não os podemos incluir todos as mesmo tempo. Queremos incluir o ficheiro que contenha as variáveis na língua pretendida. Para tal, temos primeiro que saber qual a língua pretendida (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 7
As labels e mensagens modo simples (cont.) Geralmente a informação sobre a língua pretendida, é obtida em função da língua definida para o browser. Esta informação pode ser obtida através da variável $_SERVER. $lingua = $_SERVER["HTTP_ACCEPT_LANGUAGE"]; print($lingua); pt,en;q=0.7,en-us;q=0.3 No entanto, esta variável contém informação a mais, pelo que temos que fazer algumas modificações $lingua = substr($_server["http_accept_language"],0,2); print($lingua); pt (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 8
As labels e mensagens modo simples(cont.) Sabendo a língua pretendida, poderíamos então fazer a inclusão do ficheiro de variáveis em função da língua. $lingua = substr($_server["http_accept_language"],0,2); if ($lingua == "pt") include "i18n_pt.php"; else if ($lingua == "en") include "i18n_en.php"; else if ($lingua == "es") include "i18n_es.php"; else include "i18n_pt.php"; E poderíamos ter ficado por aqui, não fosse o caso de o utilizador pretender mudar a língua em que está visualizar o site. Imagine por exemplo que a língua do seu browser está definida para inglês. Utilizando o código anteriormente apresentado, seríamos forçados a ver os sites sempre em língua inglesa (se disponível!). (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 9
As labels e mensagens modo simples (cont.) Felizmente, os sites que apresentam conteúdos em várias línguas permitem fazer o overwrite da informação sobre língua proveniente do browser. Disponibilizando ícones representativos da bandeira do país de onde a língua é originária. Neste caso teríamos as imagens das bandeiras com uma hiperligação semelhante a: <a href="index.php?lingua=pt"><img src="bandeira_pt.gif"></a> <a href="index.php?lingua=es"><img src="bandeira_es.gif"></a> <a href="index.php?lingua=en"><img src="bandeira_en.gif"></a> (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 10
As labels e mensagens modo simples (cont.) De modo a que ao clicar-se numa determinada bandeira se mude de língua, mas que se mantenha o item de conteúdo que se estava a ver, é necessário fazer: $file = $_SERVER["SCRIPT_NAME"]; $file_array = explode('/', $file); $filename = $file_array[count($file_array) - 1]; $query=""; if(strlen($_server["query_string"])>0) $query=$_server["query_string"]."&"; <a href=" print($filename. $query. "lingua=pt"); "><img src="bandeira_pt.gif"></a> <a href=" print($filename. $query. "lingua=en"); "><img src="bandeira_en.gif"></a> <a href=" print($filename. $query. "lingua=es"); "><img src="bandeira_es.gif"></a> (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 11
As labels e mensagens modo simples (cont.) Para terminar, apresenta-se o novo script de verificação da língua que irá estar em uso. session_start(); if(isset($_get["lingua"])){ $_SESSION["lingua"] = $_GET["lingua"]; } else if(!isset($_session["lingua"])){ $_SESSION["lingua"] = $_SERVER["HTTP_ACCEPT_LANGUAGE"]{0}.$_SERVER["HTTP_ACCEPT_LANGUAGE"]{1}; } if ($_SESSION["lingua"] == "pt") include "i18n_pt.php"; elseif ($_SESSION["lingua"] == "en") include "i18n_en.php"; elseif ($_SESSION["lingua"] == "es") include "i18n_es.php"; else include "i18n_pt.php"; } Posteriormente, sempre que se pretender saber a língua basta aceder a $_SESSION["lingua"]. (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 12
As labels e mensagens utilizando a livraria gettext Antes de podermos começar a utilizar a livraria gettext temos que garantir que está correctamente instalada no nosso computador Para tal, basta correr de novo o ficheiro de instalação do PHP e adicionar a extensão Gettext. Após reiniciar o Apache, as funcionalidades desta livraria estarão disponíveis. Para exemplificar o funcionamento desta livraria, vamos assumir que temos um ficheiro index.php com o seguinte conteúdo print "eu tenho uma sensação, que esta noite vai ser uma grande noite"; (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 13
As labels e mensagens utilizando a livraria gettext Para começarmos o processo de internacionalização, vamos começar por criar um ficheiro i18n.php onde será determinada a língua a utilizar $locale = 'pt'; // lingua a utilizar por defeito if (isset($_get["locale"])) $locale = $_GET["locale"]; putenv("lc_all=$locale"); setlocale(lc_all, $locale); bindtextdomain("messages", "./locale"); textdomain("messages"); O ficheiro index.php ficará apenas com o seguinte conteúdo include "i18n.php"; print _("feeling"); // é o mesmo que ter gettext("feeling"); A mensagem foi substituída pela variável feeling (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 14
As labels e mensagens utilizando a livraria gettext Experimentando o código agora desenvolvido ainda não iríamos obter o resultado pretendido, uma vez que ainda temos que atribuir valores às variáveis Para atribuir valores às variáveis, vamos utilizar o programa poedit (www.poedit.net/). Vamos utilizar este programa para criar catálogos de pedaços de texto (um catálogo para cada língua). Devemos começar por criar na raiz do nosso projecto uma directoria chamada locale. E dentro desta criar pastas com o nome correspondente ao par língua/cultura (ex. pt, pt_pt, pt_br, etc ) Dentro de cada uma destas pastas vamos criar uma pasta chamada LC_MESSAGES Devemos ficar com uma directoria semelhante a: \locale\pt_pt\lc_messages (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 15
As labels e mensagens utilizando a livraria gettext Depois de criadas as directorias para cada língua, vamos proceder à criação dos catálogos Na aplicação poedit, fazemos: Ficheiro>Novo catálogo Deverá preencher obrigatoriamente o idioma. Já o país, só deverá escrever se pretender ser muito específico (ex.: pt_pt ou pt_br). (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 16
As labels e mensagens utilizando a livraria gettext No diálogo Pastas devemos indicar a localização da pasta raiz do nosso web server, por exemplo: C:\ServidorWeb\htdocs e o nome da pasta onde está o código cujo conteúdo pretendemos internacionalizar (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 17
As labels e mensagens utilizando a livraria gettext Finalmente vamos guardar o ficheiro do catálogo, na directoria correspondente à língua pretendida (ex.: \loclale\pt\lc_messages) com o nome messages.po, por exmplo. (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 18
As labels e mensagens utilizando a livraria gettext Neste momento, o poedit, irá procurar todos os sítios onde foram utilizadas variáveis de internacionalização e irá permitir-nos inserir o conteúdo pretendido. (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 19
As labels e mensagens utilizando a livraria gettext Para finalizar, basta Guardar O processo descrito, terá que ser repetido sempre que pretendamos adicionar uma nova linguagem Se entretanto forem inseridas novas variáveis no código, basta abrir os catálogos e fazer Catálogo>Actualizar a partir do códigofonte. (c) Nuno Miguel Gil Fonseca - Escola Superior de Tecnologia e Gestão de Oliveira do Hospital - Programação para a Internet II 20