Princípios da internacionalização de software Dan Moore Para fazer certo, comece do básico… E antes de qualquer outra coisa! A internacionalização de software cria, em um aplicativo, suporte a várias localidades, onde localidade (locale) significa “[um] subconjunto de ambiente de usuários que define as convenções para uma cultura específica”, geralmente incluindo o idioma (extraído de http://publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixins/insgdrf/glossary.htm). O suporte a várias localidades permite que o usuário escolha a que lhe parecer mais adequada, facilitando o uso do aplicativo em questão. É melhor fazer o processo de internacionalização durante a criação do aplicativo, já que acrescentar depois esse tipo de suporte pode ser caro e complicado. No artigo a seguir, examinaremos os principais componentes internacionalizados de um aplicativo Web e detalharemos alguns princípios comuns a todos os esforços de internacionalização de software. Esse aplicativo, criado em Java com um back-end Oracle, foi desenvolvido inicialmente pela Zia Consulting (http://www.ziaconsulting.com) e fornece cotações de equipamentos para indivíduos em 27 países. As bibliotecas de software citadas neste artigo são do padrão Java; outras linguagens podem ter ou não o mesmo nível de suporte. As três fases principais envolvidas na internacionalização de um aplicativo são: encontrar a localidade preferencial do usuário dentro do conjunto de localidades disponíveis exibir informações adequadas à localidade escolhida questões operacionais Observe que a internacionalização é apenas metade do processo — quando o aplicativo é capaz de lidar com localidades diferentes, devem-se fornecer a ele as informações e os dados específicos a cada uma delas. Esse processo se chama “localização”, e este artigo não abordará esse assunto. Encontrando a localidade apropriada Em primeiro lugar, um usuário deve ser associado a uma localidade. Trata-se de uma configuração como outra qualquer. É essencial permitir que o usuário escolha explicitamente a localidade adequada. Há algumas dicas que o computador do usuário pode fornecer: no Microsoft Windows, existe uma chave “Country” no Registro1, e os navegadores podem fornecer as preferências de uma localidade específica e comunicá-las ao servidor, em um processo chamado “negociação de idioma” (http://www.w3.org/International/questions/qawhen-lang-neg, em inglês). 1 Para obter mais informações, verifique o tópico “How to read, add or modify Windows registry entries with REGEDIT” (Como ler, acrescentar ou modificar entradas do Registro do Windows com o REGEDIT), no site de Rob van der Woude (http://www.robvanderwoude.com/index.html). O artigo pode ser encontrado se você clicar no link “Batch files” da seção “Scripting” da home page. Página 1 de 8 ©2007 Ccaps. Todos os direitos reservados. No entanto, embora isso possa servir como ponto de partida para um item de software, certamente não é a resposta completa. O sistema operacional pode estar configurado incorretamente, ou o usuário pode estar no cibercafé de um país estrangeiro, com as configurações adaptadas para o usuário típico do lugar, mas não para ele. Quando a localidade de um aplicativo não está definida corretamente, o usuário típico culpa o aplicativo e não o sistema operacional ou o navegador. E, ao contrário de outras opções de configuração, é comum inutilizar um aplicativo pela escolha incorreta da localidade. Existem também requisitos comerciais que exigem que o usuário escolha sua localidade, independentemente da configuração da máquina. Por exemplo, no sistema de cotações ao qual se refere este artigo, os usuários podem precisar receber a cotação em dólares norte-americanos. Isso ocorre com freqüência quando empresas multinacionais têm uma entidade de compras que lida apenas com cotações em dólar. Caixa de diálogo de instalação de localidade no GFTPKlient Em resumo, o melhor método para descobrir a localidade mais adequada a um usuário é perguntar. Em aplicativos de desktop, isso geralmente ocorre no momento da instalação, como indicado na ilustração acima. Em um aplicativo Web, é um pouco mais complexo, mas geralmente ele não deve solicitar a localidade de preferência caso reconheça que a solicitação veio de um usuário cuja localidade preferencial já é conhecida. Ao perguntar claramente ao usuário, o aplicativo demonstra estar preparado para lidar com várias localidades e permite que o usuário escolha uma localidade adequada, independentemente das configurações existentes. Naturalmente, temos aqui um problema de inicialização: em que idioma deve ser colocada a consulta inicial sobre localidade? Existem duas opções: use um “mínimo denominador comum” - um idioma que seja amplamente conhecido pelo público-alvo - ou use uma imagem com instruções simples em vários idiomas. O motivo de usar uma imagem em vez de texto é que os usuários talvez não tenham fontes instaladas para todos os idiomas aceitos. Além disso, a aparência de uma imagem é melhor do que uma série de pontos de interrogação, que é como alguns sistemas operacionais exibem os caracteres que não reconhecem. Página 2 de 8 ©2007 Ccaps. Todos os direitos reservados. No entanto, o uso de imagens tem um custo. Quando você precisar atualizar e recolocar a mensagem, sairá mais barato fazer com que alguém modifique um trecho isolado do texto. Trabalhar com imagens é mais caro e mais complicado; alguém precisa fornecer o novo texto, e a imagem existente precisa ser modificada, geralmente por um especialista em artes gráficas. Se a imagem for modificada no tamanho ou na forma, o departamento de controle de qualidade (também conhecido como “QA”, do inglês Quality Assurance), deve se assegurar de que os caracteres inalterados não tenham sofrido modificações. Além das considerações de custo, a opção pela “inicialização de localidade” para um aplicativo depende muito do público-alvo. Para um aplicativo científico na Web, pode até ser seguro usar o inglês nas instruções iniciais; entretanto, um aplicativo de prateleira talvez precise de um texto simples de inicialização, traduzido para vários idiomas. O aplicativo de cotações, como indicado abaixo, optou pelas duas opções – para usuários desconhecidos, usa um padrão de localidade em inglês norte-americano (como demonstrado pelo texto “If your country...”) e, ao mesmo tempo, transporta esses usuários para uma página com mensagens em vários idiomas que pedem que ele “Selecione seu país”. (O motivo de usar “país” em vez de “localidade” nessa mensagem é que os usuários típicos não têm idéia do significado exato de locale.) O selecionador de localidades do aplicativo de cotações. Página 3 de 8 ©2007 Ccaps. Todos os direitos reservados. Para obter a maior compatibilidade possível, seja qual for a escolha do usuário, a localidade deve ser armazenada usando os códigos de país e de idioma ISO (International Organization for Standardization). Java usa o código de idioma com duas letras minúsculas seguidas de um espaço sublinhado e do código do país, também com duas letras, em maiúsculas2. Por exemplo, en_US significa inglês norte-americano, enquanto pt_BR quer dizer português brasileiro. O aplicativo Web de cotações usou vários códigos de localidade, principalmente visando à compatibilidade com produtos mais antigos. Essa decisão causou alguns problemas quando novos produtos de software internacionalizados foram integrados ao site – foi preciso escrever uma camada de tradução. Se for possível, opte por armazenar as informações de localidade no formato padrão. Depois que o usuário já tiver escolhido a localidade, o aplicativo não deverá mais solicitá-la. Em um software de desktop, isso não é problema, uma vez que o desenvolvedor deve armazenar o valor escolhido no Registro ou em um arquivo de configuração. No entanto, em um software para a Web, é inevitável perguntar novamente. Se o usuário apagar seus cookies ou visualizar o aplicativo em outro computador, o servidor não poderá identificá-lo. Isso significa que a escolha da localidade deve ser a mais fácil possível em um aplicativo Web, pois é provável que ocorra com mais freqüência do que em um aplicativo de desktop. Mas o usuário deve ser capaz de reconfigurar o aplicativo e escolher uma nova localidade. Apesar de o Windows permitir que os usuários adotem uma nova localidade sem necessidade de reinstalação, na prática, é comum os aplicativos de desktop típicos não oferecerem essa opção. Por outro lado – e por serem criados para lidar com usuários transitórios – os aplicativos Web devem ter maneiras fáceis de alterar a localidade de preferência. No aplicativo de cotações, por exemplo, cada página tem uma caixa suspensa em que o usuário pode selecionar outra localidade. Apresentando informações específicas à localidade Depois que o usuário tiver feito sua escolha, o aplicativo deve responder mostrando informações pertinentes à localidade. O tipo de informação mais importante é o idioma do texto exibido. Outras informações específicas à localidade são: regras comerciais – se será mostrado ou não um produto que pode ser ilegal ou que não esteja disponível em determinado país –, classificação alfanumérica e formatação de datas e números. Examinaremos cada uma dessas opções no contexto do aplicativo de cotações. A maneira comum de colocar na interface do aplicativo o texto adequado a uma localidade é garantir de que todo o texto da interface foi substituído por tokens. Cada token é uma string de chave usada quando o desenvolvedor está criando a interface do usuário. O aplicativo de cotações a que nos referimos como exemplo usou JSPs (Java Server Pages) e bibliotecas de tags, mas esses conceitos aplicam-se a quase todas as tecnologias de exibição. Em arquivos separados, pelo menos um para cada localidade, a chave recebe um valor localizado. 2 Os códigos de idiomas podem ser encontrados em http://www.loc.gov/standards/iso6392/php/English_list.php, e os códigos de países em http://www.iso.org/iso/en/prodsservices/iso3166ma/02iso-3166-code-lists/list-en1.html. As bibliotecas Java usam os códigos ISO nas classes de localidade: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Locale.html Página 4 de 8 ©2007 Ccaps. Todos os direitos reservados. O valor deve ser armazenado com uma representação UTF (Unicode Transformation Format), que pode usar vários bytes para representar um único caractere. Cada linguagem de programação lida com essa representação de um modo bem específico. No caso de Java, os caracteres UTF são geralmente tratados como caracteres de escape e armazenados no conjunto ISO-8859-1 (para obter mais informações a respeito, visite http://java.sun.com/j2se/1.5.0/docs/api/java/util/Properties.html). Uma seqüência UTF de escape tem o seguinte aspecto: \u65e5. Depois que o usuário identifica a localidade preferencial, o aplicativo (representado pela caixa “Estrutura” na ilustração abaixo) gera a interface correta substituindo todas as chaves pelos valores correspondentes, que são extraídos de um arquivo ou banco de dados (a “Área de armazenamento de dados”, abaixo). Presume-se que o sistema do usuário esteja configurado corretamente, com as fontes etc. para a localidade escolhida. Muitas linguagens modernas de programação têm suporte a bibliotecas para essa separação de valores de chave, inclusive Java e XUL (XML User Interface Language, parte da estrutura dos aplicativos Mozilla). Se você estiver criando um aplicativo internacionalizado e puder escolher uma linguagem de desenvolvimento, é altamente recomendado que você examine os recursos de internacionalização de cada uma das linguagens de programação consideradas, pois algumas contam com melhor suporte do que outras. Um exemplo de um par de valores-chave para localidade inglês norte-americano é: HELLO_KEY=Hello there! Extrair todo o texto presente na interface do usuário é um trabalho tedioso, embora seja possível usar alguma automação. Esse é um motivo importante para internacionalizar o aplicativo desde o início, pois é mais fácil garantir que houve extração de todo o texto quando se faz isso já no começo. O aplicativo tem menos complicadores, e os recursos ou componentes adicionais podem ser internacionalizados um a um. Página 5 de 8 ©2007 Ccaps. Todos os direitos reservados. Nesse ponto, o desenvolvedor deve começar a analisar também o processo de localização: como traduzir, testar e implantar com eficácia todo o texto? No caso de textos armazenados em arquivos, o aplicativo de cotações usou uma combinação de planilhas Excel para entrada de dados, um banco de dados Access para armazenar todas as strings localizadas e vários scripts para extrair e gerar arquivos a serem usados pelo aplicativo Web. Além da mera substituição do valor da chave, talvez convenha colocar conteúdo dinâmico em uma string que será localizada. Geralmente, isso é feito com outro tipo de token para representar o conteúdo dinâmico. Segue-se um exemplo em Java: HELLO_KEY=Olá {0}! Na interface de usuário do aplicativo, não só “HELLO_KEY” será substituído por “Olá {0}!”, mas o token “{0}” poderá ser substituído dinamicamente por qualquer valor que o aplicativo forneça. Essa substituição de token é extremamente útil quando se lida com idiomas que têm uma ordem de sujeito-verbo-objeto diferente. Em Java, existe suporte a bibliotecas para essa funcionalidade. Você pode obter mais informações em http://java.sun.com/j2se/1.5.0/docs/api/java/text/MessageFormat.html. Arquivos específicos a localidades funcionam bem quando o texto é raramente alterado. No entanto, no aplicativo de cotações, havia uma quantidade significativa de texto dinâmico — principalmente dados de produto. Embora a maioria dos bancos de dados modernos aceite armazenar dados UTF, os desenvolvedores precisam ter certeza de que o banco está configurado corretamente e de que todas as outras ferramentas usadas para manipular esses dados também estejam equipadas para isso. O aplicativo de cotações foi criado em Oracle, que aceita o conjunto de caracteres UTF — os desenvolvedores só precisavam se assegurar de que a variável de ambiente NLS_LANG estava definida como “american_america.AL32UTF8”. Também foi preciso que outros aplicativos, como o SQL*Loader, estivessem configurados corretamente para lidar com caracteres de byte múltiplo. Tenha cuidado ao usar strings UTF como chaves em tabelas hash ou em bibliotecas de terceiros. Itens que parecem iguais na tela talvez não sejam a mesma string de caracteres UTF. Por exemplo, a combinação de caracteres de acento pode ou não ser usada para representar acentos. (Para saber mais a respeito, consulte as perguntas freqüentes sobre Unicode em http://unicode.org/faq/char_combmark.html#2) Em geral, a formatação de números e datas é executada pelas bibliotecas de idiomas (http://java.sun.com/j2se/1.5.0/docs/api/java/text/DateFormat.html). No aplicativo de cotações, em vez de usar formatadores de data e número, foram aproveitados os arquivos específicos à localidade. Foram acrescentadas duas chaves, uma para formatação de números e outra para formatação de datas. Cada uma delas seria extraída e transmitida para a classe adequada de formatação sempre que se exibisse para o usuário uma data ou um número. Isso significa que todas as informações específicas à localidade estavam armazenadas em um arquivo. Além disso, as bibliotecas Java não poderiam processar os códigos do aplicativo para localidades fora do padrão, o que, como mencionado acima, seria necessário para fins de compatibilidade. Página 6 de 8 ©2007 Ccaps. Todos os direitos reservados. As regras comerciais são extremamente específicas aos aplicativos e são a segunda parte mais importante da internacionalização de um aplicativo — a primeira é a exibição da interface no idioma preferencial do usuário. Os desenvolvedores devem estar atentos às regras comerciais relativas às localidades e criar suporte a elas desde o início. Por exemplo, no aplicativo de cotações, usuários em países diferentes teriam conjuntos diferentes de produtos disponíveis. Poucas linguagens ou estruturas fornecerão algum suporte, pois essas regras dependem muito do aplicativo. Dessa forma, os desenvolvedores devem planejar a inclusão de conjuntos de regras personalizadas conforme a localidade escolhida. Observe que isso permite alguns tipos de ataques à segurança — se os usuários franceses forem impedidos de comprar determinados itens permitidos aos japoneses, um francês que fale japonês poderá escolher a localidade japonesa e ver os itens proibidos. Como em geral é solicitado que o usuário escolha uma localidade, eles podem driblar algumas regras comerciais que se baseiem nessa escolha. Assim, às vezes é necessário implementar processos comerciais para lidar com questões específicas à localidade. No caso mencionado acima, as centrais de atendimento que perceberem uma cotação indevida poderão escolher ignorá-la ou responder diretamente ao usuário, informando que sua localidade não é permitida. A classificação correta de texto de uma determinada localidade é uma questão complicada. Mais uma vez, parece haver algum suporte a bibliotecas (http://java.sun.com/j2se/1.5.0/docs/api/java/text/Collator.html), mas inicialmente o aplicativo de cotações não aceitava classificações específicas a localidade. No entanto, versões posteriores exigiram que o aplicativo classificasse texto localizado. Em vez de usar o suporte a bibliotecas, foi criada uma interface personalizada para permitir que os usuários comerciais tivessem a opção de definir a ordem de classificação para qualquer coluna em uma tabela. Isso permitiu que os administradores aplicassem à coluna uma classificação alfanumérica padrão, e que os usuários, depois, pudessem alterá-la. Uma vez que todo o texto da interface do usuário tenha sido substituído por tokens, inclusive — se for preciso — a formatação de datas e números, pode-se executar o aplicativo e testar a interface. A geração de fato da interface de usuário do aplicativo é feita quando este sabe a localidade do usuário, de forma que o idioma, a formatação de números e outros recursos específicos à localidade sejam adequados e exibidos corretamente. Em aplicativos de desktop, isso pode ser feito na instalação; em aplicativos Web, a substituição geralmente é feita em tempo de execução. Questões operacionais A internacionalização é mais do que simplesmente extrair strings de arquivos e descobrir a localidade da preferência de um usuário. Em aplicativos Web, a disponibilidade pode ser um desafio. Implantar novas versões do aplicativo de cotações foi um problema, devido aos variados fusos horários dos países incluídos. A implantação do aplicativo afetou severamente sua disponibilidade durante um curto período pois, quase sempre, em algum lugar ainda era de tarde no horário comercial. Embora os desenvolvedores pudessem visualizar os logs de uso e encontrar um horário nos dias úteis em que um mínimo de pessoas estivesse usando o aplicativo, esse período só servia para implantações rápidas ou alterações de configuração. Em qualquer situação que exigisse mais do que alguns minutos de paralisação, a solução era implantar na noite de sexta-feira ou no sábado, que já é fim de semana em todos os fusos horários. Mas isso não era muito aceito pelos desenvolvedores que davam suporte ao aplicativo. Página 7 de 8 ©2007 Ccaps. Todos os direitos reservados. Além disso, do ponto de vista da modelagem de dados, os aplicativos internacionalizados podem dar um pouco de dor de cabeça. Em todas as tabelas que contenham texto a ser exibido para um usuário, existirá uma chave para a tabela de localidades. O aplicativo de cotações ficou com aproximadamente trinta tabelas com chaves externas para a tabela de localidades. Uma alternativa é inserir redundâncias de dados (de-normalize) nas informações de localidade e colocar o código real, em vez de uma chave externa, em todas as tabelas que contiverem texto exibido para o usuário. Quando essa alternativa é escolhida, podem-se usar disparadores para validação e para forçar a exatidão da localidade. Ambas as soluções são perfeitamente razoáveis para atender aos requisitos comerciais e dar suporte ao aplicativo, mas são difíceis de administrar e, o que não é tão importante, um pouco desagradáveis do ponto de vista dos dados. Lições aprendidas O aplicativo de cotações não tinha, de imediato, suporte a todos os 27 países — as localidades foram acrescentadas aos poucos. Essa abordagem gradual permitiu resolver questões específicas ao processo, especialmente o de localização. Ela permitiu também que a manutenção e administração do site amadurecessem. O uso de códigos de localidade padrão sempre que possível maximizará a compatibilidade e pode evitar muita dor de cabeça. No entanto, talvez existam fortes razões comerciais proibitivas, e a incompatibilidade poderá ser contornada. A internacionalização deve ser considerada desde o primeiro momento. Além do tédio de extrair todas as strings presentes na interface do usuário, a complexidade do suporte às regras comerciais recomenda a criação de algum suporte em todos os aplicativos, desde o início. Em resumo, a internacionalização de software, seja ele de desktop ou de Web, não é tão difícil assim. Há um número definido de questões a serem tratadas, sendo que a mais longa e tediosa é a extração, para arquivos separados, de todas as strings exibidas. Quase todas as tarefas de internacionalização ficam mais fáceis se forem levadas em conta desde o começo do projeto, em vez de serem deixadas para o final — e, do ponto de vista da internacionalização, passar de uma localidade para duas geralmente é mais difícil do que passar de duas para N localidades. A maioria das linguagens modernas de programação tem um amplo suporte a bibliotecas para internacionalização, que deve ser aproveitado sempre que possível. Dan Moore é um consultor independente que tem trabalhado com tecnologias de Web desde 1997. Ele colaborou com a Zia Consulting na expansão do aplicativo Web de cotações descrito acima e familiarizou-se com as “pegadinhas” da localização e internacionalização de software. Dan tem escrito artigos e feito apresentações para grupos técnicos locais sobre temas que vão da internacionalização ao uso de Java no celular e à tecnologia de autenticação Java. Formado em Física pelo Whitman College, ele mantém um blog que abrange vários tópicos técnicos (e umas elucubrações ocasionais) em http://www.mooreds.com/weblog. Página 8 de 8 ©2007 Ccaps. Todos os direitos reservados.