A internacionalização de software é difícil na melhor das circunstânciasmas sempre me surpreendeu a frequência com que um particular surgiu em discussões sobre problemas de internacionalização: Turquia.
Por exemplo, esta postagem de Rick Strahl de meados de 2005 é um dos muitos exemplos que encontrei:
Tenho monitorado um bug muito estranho em meu aplicativo West Wind Web Store que parece aparecer com pouca frequência em meus registros de erros. Em um post anterior, mencionei que havia instituído alguns recursos adicionais de registro, especificamente certificando-me de que também registraria a localidade do usuário que acessava o aplicativo.
Bem, três relatórios de bugs depois, notei que todos os erros ocorriam com um navegador turco (tr). Então, alterei o idioma padrão do meu navegador para turco e, com certeza, pude ver o erro ocorrer.
Ou, digamos, esta publicação de 2005 de Scott Hanselman:
Eu havia publicado anteriormente no blog sobre um bug no dasBlog que afetava os usuários turcos. Quando um navegador turco informava que um cabeçalho HTTP Accept-Language indicava o turco como idioma preferencial, não apareciam posts no blog. Como correção, sugeri que os usuários alterassem os modelos de seus blogs, mas sabia que essa não era uma correção adequada.
Entendo que o As prisões turcas não são para se brincar com o senhorMas a pergunta permanece: por que os turcos têm um prazer tão cruel e perverso em quebrar nosso belo software? O que há de errado com a Turquia?
Como acontece com tantos outros problemas no desenvolvimento de software, a pergunta não deveria ser o que há de errado com a Turquia, mas sim, o que diabos há de errado com a desenvolvedores de software? Algumas dessas coisas são meio óbvias se o senhor tiver algum tipo de consciência cultural.
- Nos Estados Unidos, normalmente formatamos a data de hoje como 3/14/2008. Na Turquia, o formato é o seguinte 14.3.2008.
- Nos Estados Unidos, usamos vírgulas para agrupar dígitos, assim: 32,768. Na Turquia, eles agrupam os dígitos usando um ponto, de modo que o mesmo número seria digitado como 32.768.
Essas pequenas diferenças de formatação geralmente não são um grande problema para fins de saída e exibição, mas o jogo é totalmente diferente quando o senhor está analisando a entrada. Naturalmente, o senhor espera que as pessoas insiram datas e números no formato com o qual estão acostumadas. Se o seu código presumir que a entrada será no formato típico do inglês americano, haverá… problemas.
A maioria das linguagens tem isso coberto; há funções que permitem que o senhor leia ou escreva datas e números de forma apropriada para várias culturas. No .NET, por exemplo, é a diferença entre essas duas chamadas:
int.Parse("32.768"); int.Parse("32,768", System.Globalization.NumberFormatInfo.InvariantInfo);
Como nenhuma cultura é especificada, a primeira chamada analisará o número de acordo com as regras da cultura padrão em que o código está sendo executado. Esperamos que ele esteja sendo executado em uma versão turca do Windows, para que possa analisar o número corretamente. A segunda chamada, entretanto, especifica explicitamente uma cultura. A cultura “invariante” é o sonho secreto de todo programador americano realizado: nós simplesmente fechamos os olhos e desejamos que todas essas linguagens e culturas confusas e seus esquemas de formatação de datas e números loucos e indutores de bugs sejam substituídos pelos nossos. Um sonho agradável enquanto dura, mas em vez de pedir rudemente aos seus usuários que “falem americano” por meio da cultura invariante, o senhor poderia pedir educadamente que eles inserissem dados no formato padrão internacional ISO.
De qualquer forma, a questão é que esse tipo de suporte à cultura está embutido na maioria das linguagens de programação modernas, portanto, tudo o que o senhor precisa fazer é garantir que seus desenvolvedores estejam cientes disso e, o que é mais importante, que eles estejam pensando em situações em que possam precisar para usá-lo.
Mas toda essa coisa de formatação de data e hora é fácil. Ou, pelo menos, o mais fácil que a i18n consegue. As cadeias de caracteres são onde o realmente começa a ficar complicado. Adivinhe onde esse código falha?
switch (myType.ToLower()) { case "integer" : ; }
Se o senhor adivinhou a Turquia, está errado! Estava brincando. É claro que ele falha na Turquia. Quando convertemos a string “integer” para maiúsculas e minúsculas na localidade turca, recebemos alguns caracteres estranhos de volta:
"INTEGER".ToLower() = "ınteger" "integer".ToUpper() = "İNTEGER"
É um pouco difícil ver as diferenças sutis aqui, a menos que aumentemos o tamanho da fonte:
I → minúsculas → ı |
i → maiúsculas → İ |
Obviamente, não há como essas cadeias de caracteres corresponderem a “integer” ou “INTEGER”, respectivamente. Isso é conhecido como o problema do I turcoe a solução já deve lhe parecer bastante familiar:
"INTEGER".ToLower(System.Globalization.CultureInfo.InvariantCulture)
Isso produzirá o resultado esperado ou, pelo menos, o resultado que corresponde à comparação no trecho de código original.
É claro que isso é apenas a ponta do iceberg quando se trata de internacionalização. Nem sequer tocamos nas localidades realmente difíceis, como hebraico e árabe. Mas concordo com Jeff Moser – se o seu código puder passar no teste do Turkey, o senhor está se saindo muito bem. Certamente melhor do que a maioria.
Se o senhor se importa um pouco com localização ou internacionalização, force seu código a ser executado na localidade turca assim que for razoavelmente possível. Esse é um forte indicador de que seu código será executado na maioria das culturas e localidades, mas não em todas.