Gadgets e internacionalização (i18n)

Este documento descreve como criar gadgets que possam ser facilmente localizados para um público internacional.

Sumário

  1. Introdução
  2. Conceitos básicos
  3. Codificação para a internacionalização
  4. Exemplo
  5. Criação de um gadget localizado
  6. Pacotes de mensagens
    1. Convenções de nomenclatura
    2. Melhores práticas
  7. Uso de pacotes de mensagens em um gadget
    1. Consulta às mensagens
    2. Acesso a mensagens de pacotes de mensagens
    3. Exibição de mensagens no HTML do gadget
  8. Especificação do gadget Hello World
  9. Criação de gadgets bidirecionais
    1. Alteração da direção de parte do gadget
  10. Teste
  11. Cache
  12. Solução de problemas

Introdução

A API de gadgets oferece uma maneira fácil de você disponibilizar seu gadget para um público internacional. É simples: basta estruturar o gadget de forma que o texto visível para o usuário (qualquer texto que será traduzido) esteja em pacotes de mensagens separados do gadget. Assim, qualquer tradutor de terceiros pode traduzir suas strings e criar novos pacotes de mensagens específicos ao local, os quais você pode adicionar à especificação do seu gadget. Dessa forma, seu gadget fica disponível para um novo grupo de usuários.

Para ler mais sobre como criar gadgets em idiomas diferentes do inglês, consulte Gadgets em idiomas diferentes do inglês.

Conceitos básicos

Este documento refere-se à internacionalização (i18n) e à localização (l10n):

  • Internacionalizar significa estruturar aplicativos de forma a possibilitar sua localização.
  • Localizar significa fazer um aplicativo funcionar para um mercado específico, como canadenses francófonos.

Para a finalidade deste documento, o “perfil de localização” de um usuário consiste em dois componentes: um país (com base no domínio do usuário) e um idioma de interface preferido pelo usuário (consulte a seção Teste para obter mais detalhes).

Codificação para a internacionalização

A API de gadgets suporta codificação UTF-8 para valores de atributos XML e também na seção <Content>. Quando o tipo de conteúdo é definido como html, a codificação padrão é definida expressamente como UTF-8. Você não deve tentar defini-la sozinho.

Exemplo

O exemplo de gadget usado neste documento exibe a mensagem “Hello World,” mostrada aqui em chinês:

Hello World-Chinese

Neste exemplo, o menu suspenso de preferências do usuário permite que o usuário especifique uma cor de fonte para a mensagem “Hello World”. Os nomes das cores que aparecem no menu são arquivos externos definidos (pacotes de mensagens). O idioma no qual o menu será exibido depende do perfil de país/idioma do usuário. Se um usuário com perfil inglês executar este gadget, o texto aparecerá em inglês. Veja aqui a aparência da versão em inglês do exemplo, com o menu suspenso userprefs sendo exibido:

Hello World-English

Você pode ver a especificação do gadget Hello World aqui.

Criação de um gadget localizado

As etapas básicas para a criação de um gadget localizado são:

  1. Criar o gadget.
  2. Extrair todo o texto que precisa de tradução e colocá-lo em pacotes de mensagens.
  3. Encontrar alguém que possa ajudá-lo a traduzir o gadget.
  4. O tradutor cria um novo pacote de mensagens para um local específico. Esse local pode ser definido por idioma (francês) ou por idioma/país (francês/Canadá, francês/França). Os pacotes de mensagens em idiomas diferentes do inglês devem ser salvos no formato UTF-8.
  5. O tradutor envia um URL do novo pacote a você.
  6. Modifique a especificação do gadget para usar o pacote de mensagens.
  7. Se o gadget estiver no diretório de conteúdo, aguarde de 1 a 2 semanas para que o indexador e as informações possam encontrar seu gadget atualizado e você possa então disponibilizá-lo no novo mercado.

Pacotes de mensagens

O elemento principal da estratégia de internacionalização de gadgets são os pacotes de mensagens. Os pacotes de mensagens são arquivos XML que contêm as strings traduzidas para um dado local. Cada string é identificada por um nome exclusivo e esse mesmo nome é usado em todos os pacotes.

Os pacotes de mensagens podem ser hospedados por qualquer URL e compartilhados entre aplicativos. Cada pacote de mensagens contém somente um local.

Os pacotes de mensagens têm o seguinte formato:

<messagebundle>
  <msg name="hello_world"> 
    Hello World. 
  </msg> 
  <msg name="color">Color</msg> 
  <msg name="red">Red</msg> 
  <msg name="green">Green</msg> 
  <msg name="blue">Blue</msg> 
  <msg name="gray">Gray</msg> 
  <msg name="purple">Purple</msg> 
  <msg name="black">Black</msg> 
</messagebundle> 

Veja abaixo os campos que você pode incluir em um arquivo de pacote de mensagens:

  • messagebundle: Um grupo de mensagens para tradução.
  • msg: Um único item de conteúdo traduzível, normalmente um marcador, frase ou parágrafo.
  • msg name: Um ID legível para cada mensagem.

Convenções de nomenclatura

A convenção é nomear os pacotes de mensagens como descrito abaixo:

<language>_<country>.xml 

Onde não houver um valor específico ao idioma ou ao país, a convenção é usar "ALL". Por exemplo, o arquivo de_ALL.xml aplica-se a todas as pessoas que falam alemão, independentemente de seu país. O pacote de mensagens ALL_ALL.xml é o arquivo usado como padrão.

Melhores práticas

Não há requisitos rígidos a serem seguidos nas convenções de nomenclatura dos pacotes de mensagem. O gadget usa os atributos lang e country de <Locale> para identificar o arquivo de pacote de mensagens correto para o perfil do usuário. Ele não usa o nome do pacote de mensagens em si.

Entretanto, embora a API de gadgets ofereça muita flexibilidade, recomendamos que você siga estas orientações:

  • Sempre forneça um pacote de mensagens ALL_ALL.xml ao lidar com mensagens padrão.
  • Especifique um local por idioma. Ou seja, use fr_ALL, de_ALL e assim por diante.
  • Se precisar ignorar locais específicos, use pacotes de mensagens idioma-país. Por exemplo, se quiser fornecer um pacote de mensagens em inglês canadense para ignorar en_ALL, use en_CA e não ALL_CA.

Uso de pacotes de mensagens em um gadget

Use a tag <Locale> (aninhada dentro da seção <ModulePrefs>) para listar os pacotes de mensagens usados pelo seu gadget. Por exemplo:

<ModulePrefs title="i18n Example"> 
  <Locale messages="http://doc.examples.googlepages.com/ALL_ALL.xml"/> 
  <Locale lang="de" messages="http://doc.examples.googlepages.com/de_ALL.xml"/> 
  <Locale lang="zh-cn" messages="http://doc.examples.googlepages.com/zh_cn_ALL.xml"/> 
  <Locale lang="fr" messages="http://doc.examples.googlepages.com/fr_ALL.xml"/> 
  <Locale lang="ja" messages="http://doc.examples.googlepages.com/ja_ALL.xml"/> 
  <Locale lang="es" messages="http://doc.examples.googlepages.com/es_ALL.xml"/> 
  <Locale lang="it" messages="http://doc.examples.googlepages.com/it_ALL.xml"/> 
  <Locale lang="ru" messages="http://doc.examples.googlepages.com/ru_ALL.xml"/> 
</ModulePrefs>

<Locale> pode ter os seguintes atributos:

  • messages: Um pacote de mensagens acessado através de um URL.
  • lang: O idioma para o qual as strings do pacote de mensagens foram traduzidas.
  • country: Não há exemplos desse atributo na especificação do gadget “Hello World”, mas você também pode especificar um atributo de país. Por exemplo, este pacote de mensagens é configurado para usuários canadenses francófonos:
<Locale lang="fr" country="CA" messages="http://example.com/fr_CA.xml"/> 

Durante a execução, o gadget usa o pacote de mensagens que melhor corresponda ao perfil do usuário.

Os valores válidos para o idioma são códigos de idioma ISO639-1 com dois dígitos e os valores válidos para o país são códigos ISO 3166-1 alfa-2.

Consulta às mensagens

Os pacotes de mensagens possuem um recurso de consulta. Com o recurso de consulta às mensagens, o gadget tenta usar o pacote de mensagens que melhor corresponda ao país do usuário e ao idioma de preferência da IU (especificado no URL). Se o gadget não encontrar uma correspondência exata, ele "consulta" todos os pacotes de mensagens para encontrar a correspondência mais próxima.

Com a consulta às mensagens, você pode usar mensagens "padrão" (normalmente especificadas em ALL_ALL.xml), caso não haja um pacote disponível para um determinado local. 

Por exemplo, imagine que o seu gadget contém a seguinte especificação:

<Locale messages="http://x.com/ALL_ALL.xml"/> 
<Locale lang="de" messages="http://x.com/de_ALL.xml"/>
<Locale lang="de" country="DE" messages="http://x.com/de_DE.xml"/> 
<Locale lang="de" country="US" messages="http://x.com/de_US.xml"/>

Como esses arquivos seriam usados? Suponha que o domínio da sua usuária é nos EUA (http://www.google.com), mas o idioma de preferência é o alemão. Ela verá as mensagens do arquivo de_US.xml. Se não houver uma mensagem específica neste arquivo, ela verá a mensagem de de_ALL.xml, e finalmente, de ALL_ALL.xml.

Um usuário da Alemanha usando a IU em alemão começará por de_DE.xml, um usuário da Suíça usando a IU em alemão começará por de_ALL.xml e um usuário da Suíça usando a IU em francês começará por ALL_ALL.xml.

Acesso a mensagens de pacotes de mensagens

Como um gadget acessa a mensagem apropriada no pacote de mensagens? Observe o arquivo de_ALL.xml (idioma alemão, país ALL) no exemplo “Hello World”:

<messagebundle>
  <msg name="hello_world">
    Hallo Welt.
  </msg>
  <msg name="color">Farbe</msg> 
  <msg name="red">Rot</msg> 
  <msg name="green">Grün</msg> 
  <msg name="blue">Blau</msg> 
  <msg name="gray">Grau</msg> 
  <msg name="purple">Purpurrot</msg> 
  <msg name="black">Schwarz</msg>
</messagebundle>

Cada mensagem possui uma string exclusiva de nome para identificá-la. Por exemplo, nesta mensagem:

<msg name="red">Rot</msg> 

o nome exclusivo da mensagem é “red” e a string traduzida que aparece no gadget (no menu suspenso userprefs) é “Rot”, a palavra em alemão para “vermelho”. Aqui está a string da mensagem equivalente em inglês no pacote de mensagens ALL_ALL.xml:

<msg name="red">Red</msg> 

A especificação do gadget “Hello World” usa a variável de substituição __MSG_ para indicar onde o valor do pacote de mensagens apropriado deve ser substituído. Por exemplo, esta sentença XML da especificação do gadget “Hello World” é usada para adicionar um item de menu ao menu suspenso “Color” (Cor) de userprefs:

<EnumValue value="Red" display_value="__MSG_red__" /> 

Esta linha, na verdade, diz “Vá para o pacote de mensagens que melhor corresponda ao perfil de país/idioma do usuário, obtenha o valor da mensagem com nome ‘red’ e use-o no lugar de __MSG_red__”. É assim que as preferências do usuário do menu suspenso do exemplo “Hello World” são preenchidas com nomes de cores (aqui, mostrado em alemão):

Hello World-German

Exibição de mensagens no HTML do gadget

Para exibir as mensagens na parte XML do seu gadget, use as variáveis de substituição conforme discutido acima. Há algumas opções diferentes dentro da parte CDATA do gadget.

A técnica mais simples é incorporar a variável de substituição no HTML:

<b>__MSG_hello_world__</b>. 

Como alternativa, use a função getMsg() de userprefs. Essa função pode ser usada para acessar todas as mensagens dos pacotes de mensagens e não apenas as mensagens relacionadas a userprefs. Entretanto, é necessário chamar esta função para um objeto Prefs. Por exemplo:

var prefs = new gadgets.Prefs();
prefs.getMsg(“red”);

Especificação do gadget Hello World

Aqui está a especificação do gadget do exemplo "Hello World":

<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
  <ModulePrefs title="i18n Example"> 
    <Locale messages="http://doc.examples.googlepages.com/ALL_ALL.xml"/>
    <Locale lang="de" messages="http://doc.examples.googlepages.com/de_ALL.xml"/>
    <Locale lang="zh-cn" messages="http://doc.examples.googlepages.com/zh_cn_ALL.xml"/>
    <Locale lang="fr" messages="http://doc.examples.googlepages.com/fr_ALL.xml"/>
    <Locale lang="ja" messages="http://doc.examples.googlepages.com/ja_ALL.xml"/>
    <Locale lang="es" messages="http://doc.examples.googlepages.com/es_ALL.xml"/>
    <Locale lang="it" messages="http://doc.examples.googlepages.com/it_ALL.xml"/>
    <Locale lang="ru" messages="http://doc.examples.googlepages.com/ru_ALL.xml"/> 
  </ModulePrefs>
  <UserPref name="fontcolor" display_name="__MSG_color__" default_value="Red" datatype="enum">
    <EnumValue value="Red" display_value="__MSG_red__" /> 
    <EnumValue value="Green" display_value="__MSG_green__" /> 
    <EnumValue value="Blue" display_value="__MSG_blue__" /> 
    <EnumValue value="Gray" display_value="__MSG_gray__" /> 
    <EnumValue value="Purple" display_value="__MSG_purple__" /> 
    <EnumValue value="Black" display_value="__MSG_black__" /> 
  </UserPref>
  <Content type="html">
  <![CDATA[
    <div id="content_div"></div>
    <script type="text/javascript"> 
      // Display message in the user's preferred language
      function displayMsg(){
        var div = document.getElementById('content_div');
        // Get userprefs
        var prefs = new gadgets.Prefs();
        // Set font color to user's color choice
        div.style.color = prefs.getString("fontcolor");
        // Display message
        var html = "<br><h1>";
        // Use prefs.getMsg to go to the appropriate message bundle
        // and get the string associated with the "hello_world" message.
        html += prefs.getMsg("hello_world");
        html +=  "</h1>"; 
        div.innerHTML = html;
      }
      gadgets.util.registerOnLoadHandler(displayMsg);
    </script>
  ]]>
  </Content>
</Module>

Criação de gadgets bidirecionais

Use a API BIDI (bidirecional) para alterar dinamicamente a direção de um gadget. "Direção" refere-se à direção na qual o conteúdo é exibido: esquerda para a direita ou direita para a esquerda. Isso é diferente de alinhamento. Por exemplo, você pode criar um gadget com texto em inglês alinhado à direita, mas a direção do texto em si é da esquerda para a direita.

A API BIDI possibilita criar gadgets que suportem idiomas da direita para a esquerda (como hebraico e árabe) e idiomas da esquerda para a direita (como inglês). A API BIDI inclui:

  • Um atributo language_direction dentro da tag <Locale...>. Seu valor pode ser "rtl" (direita para a esquerda) ou "ltr" (esquerda para a direita). Use esse atributo para definir a direção do gadget. Como padrão, a direção dos gadgets é da esquerda para a direita.
  • Um conjunto de variáveis de substituição __BIDI_... cujos valores são alterados dependendo da direção do gadget. Por exemplo, a variável __BIDI_DIR__ tem valor "ltr" quando o gadget está no modo da esquerda para a direita e "rtl" quando o gadget está no modo da direita para a esquerda.

No caso mais simples, use <Locale... language_direction="rtl"> para definir estaticamente a direção de um gadget. Por exemplo, este gadget exibe somente texto em hebraico. Portanto, sua direção é sempre da direita para a esquerda:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="כותרת two-כיוונית"        
    height="100">
    <Locale lang="ALL" language_direction="rtl" />
  </ModulePrefs>
  <Content type="html"><![CDATA[
    אני כותב מימין לשמאל ולא הייתי צריך להגדיר 
    dir=rtl בשביל זה!<br>
  ]]>
  </Content>
</Module>

Entretanto, suponha que você criou um gadget incluindo pacotes de mensagens para idiomas da esquerda para a direita e vice-versa. Como você faria seu gadget suportar ambos os casos? Aqui está um exemplo de gadget que altera a direção dinamicamente, de acordo com o pacote de mensagens que é carregado para o local de um usuário. Este gadget possui pacotes de mensagens para dois idiomas da direita para a esquerda, hebraico (iw) e árabe (ar):

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="BIDI Hello World">
    <Locale messages="http://doc.examples.googlepages.com/ALL_ALL.xml"/>
    <Locale lang="ru" messages="http://doc.examples.googlepages.com/ru_ALL.xml"/>
    <Locale lang="fr" messages="http://doc.examples.googlepages.com/fr_ALL.xml"/>
    <Locale lang="ja" messages="http://doc.examples.googlepages.com/ja_ALL.xml"/>
    <Locale lang="es" messages="http://doc.examples.googlepages.com/es_ALL.xml"/>
    <Locale lang="it" messages="http://doc.examples.googlepages.com/it_ALL.xml"/>
    <Locale lang="iw" messages="http://doc.examples.googlepages.com/iw_ALL.xml" language_direction="rtl"/>
    <Locale lang="ar" messages="http://doc.examples.googlepages.com/ar_ALL.xml" language_direction="rtl"/>
  </ModulePrefs>
  <Content type="html">
  <![CDATA[
    <div style="margin-__BIDI_START_EDGE__:30px;"><h2>__MSG_hello_world__</h2></div>
  ]]>
  </Content>
</Module>

Para este gadget, suponha que o idioma de preferência do usuário seja árabe. A linha <Locale lang="ar" messages="http://.../ar_ALL.xml" language_direction="rtl"/> diz "para árabe, exibir o texto do pacote de mensagens ar_ALL.xml e definir a direção do gadget como rtl." A direção para o hebraico também será da direita para a esquerda. Para outros idiomas, a direção do é implicitamente definida com o padrão ltr (esquerda para a direita).

A linha <div style="margin-__BIDI_START_EDGE__:30px;"><h2>__MSG_hello_world__</h2></div> diz "quando o gadget estiver em modo da esquerda para a direita, deslocar o texto 30 pixels em relação à margem esquerda. Quando o gadget estiver em modo da direita para a esquerda, deslocar o texto 30 pixels em relação à margem direita". Por exemplo, se a configuração do navegador do usuário for árabe (direita para a esquerda), a substituição realizada na execução ficará assim:

<div style="margin-right:30px;"><h2>أهلاً بالعالم</h2></div>

Esta tabela lista as variáveis de substituição BIDI e seus possíveis valores. Seus valores sempre são baseados na direção do próprio gadget. Ou seja, estas variáveis são designadas para serem usadas em conjunto com a configuração de <Locale... language_direction="...">. Você pode usas as variáveis em qualquer parte dentro do corpo do gadget.

Variável Descrição
__BIDI_START_EDGE__ Esta variável representa o lado do gadget que é o ponto inicial da exibição do conteúdo. O valor será "left" (esquerda) quando o gadget estiver em modo LTR e "right" (direita) quando o gadget estiver em modo RTL. O gadget acima é um exemplo de como usar esta variável para a configuração de margens CSS.
__BIDI_END_EDGE__ Esta variável representa a lateral do gadget oposta ao lado de início da exibição do conteúdo. O valor será "right" (direita) quando o gadget estiver em modo LTR e "left" (esquerda) quando o gadget estiver em modo RTL.
__BIDI_DIR__ O valor desta variável será "ltr" quando o gadget estiver em modo LTR e "rtl" quando o gadget estiver em modo RTL.
__BIDI_REVERSE_DIR__ O valor desta variável será "rtl" quando o gadget estiver em modo LTR e "ltr" quando o gadget estiver em modo RTL.

Alteração da direção de parte do gadget

A API BIDI altera a direção de um gadget inteiro e formata o conteúdo do gadget de forma correspondente. Entretanto, pode haver casos em que você deseja mexer na direção de linhas de texto individuais dentro do gadget. Talvez você não queira que a direção do gadget seja associada à configuração de idioma do usuário ou a qualquer idioma específico. Por exemplo, você pode criar um gadget que exibe texto simultaneamente em inglês e hebraico. Ou você pode criar um gadget que lista frases comuns em diversos idiomas. Você pode usar chamadas regulares a funções DOM e CSS para definir a direção do texto dentro do corpo do gadget. Por exemplo:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="DOM Hello World" height="200" />

  <Content type="html"><![CDATA[
  <script type="text/javascript">
  // In this gadget, users choose a language from a drop-down menu, and the gadget displays
  // a "Hello World" message for the selected language. The gadget uses DOM functions to set 
  // the direction and formatting for the message, depending on whether its language is RTL 
  // or LTR.
  // Associative array containing "Hello World" messages for different languages
  var msgs = new Object();
  msgs = {
    "English" : "Hello World",
    "Hebrew"  : "שלום עולם",
    "French"  : "Bonjour Monde",
    "Arabic"  : "أهلاً بالعالم",
    "Russian" : "Здравствуйте Мир!"
    };
  
  function showMsg() {
    var html="<h1>";
    var div = _gel('mydiv');
    div.style.color = "green";
    var index = document.myform.Language.selectedIndex;
    var lang = document.myform.Language.options[index].text;
    var str = msgs[lang];    
    if (!str)
       str="";
    // If language is Hebrew or Arabic, set the div direction to be right-to-left.
    // Offset text 30px from right margin.
    if(lang=="Hebrew" || lang=="Arabic") {
      div.style.direction = "rtl";
      div.style.marginRight = "30px";
      html += str;
    }
    // For other languages, set div direction to left-to-right.
    // Offset text 30px from left margin.
    else {
      div.style.direction = "ltr";
      div.style.marginLeft = "30px";
      html += str;
    }
    html+= "</h1>";
    div.innerHTML = html;
  }
  </script>
  <div style="background-color: #BFCFFF; height: 200px; color:green;">
    <br />
    <div>
      <form name="myform" style="text-align: center;">
        <select name="Language" onchange="showMsg()">
          <option>Pick a Language
          <option>English
          <option>Hebrew
          <option>French
          <option>Arabic
          <option>Russian
        </select>
      </form>
    </div>
    <br />
    <div id="mydiv"><h2 style='text-align: center;'>****Pick a language****</h2></div>
  </div>
  ]]>
  </Content>
</Module>

Teste

Para testar o gadget, altere a configuração de país e idioma de modo que ela corresponda aos pacotes de mensagens incluídos em seu gadget.

A maneira mais simples de alterar a configuração de país e idioma no iGoogle é editar o URL:

http://www.google.com/ig?&gl=<country>&hl=<lang>

Por exemplo, no URL abaixo, o país é Alemanha (DE) e o idioma é inglês (en). Normalmente, o país tem precedência sobre o idioma. Portanto, com este URL, o iGoogle exibe texto em alemão:

http://www.google.com/ig?&gl=DE&hl=en

Neste exemplo, o país é implicitamente EUA e o idioma é espanhol:

http://www.google.com/ig?hl=es

Este link pode ajudá-lo a criar o URL correto para um idioma específico: http://www.google.com/help/customize.html#searchlang. Os valores válidos para o idioma são códigos de idioma ISO639-1 com dois dígitos e os valores válidos para o país são códigos ISO 3166-1 alfa-2.

Cache

Os pacotes de mensagens têm o mesmo comportamento de cache que as especificações de gadget em si: normalmente, atualizamos o cache a cada 1 a 2 horas, os servidores de hospedagem devem ver somente cerca de 100 a 200 solicitações de pacotes de mensagens por dia e, se eles não estiverem disponíveis, continuaremos usando nossa cópia "antiga" pelo tempo que for possível.  No gadget developer.xml, ao desativar o cache do gadget, você também desativa o cache dos pacotes de mensagens do gadget.

Solução de problemas

Durante o desenvolvimento, seu gadget pode ficar em branco ou exibir ??? onde deveria haver uma mensagem. O problema pode ser:

  • Você não salvou o pacote de mensagens em UTF-8. Isso é necessário para qualquer arquivo de idioma diferente do inglês que inclua caracteres especiais.
  • Há um problema na sintaxe do seu pacote de mensagens.
  • Não há um arquivo de pacote de mensagens ALL_ALL.xml para ser usado como padrão pelo gadget.
  • No gadget, o URL do pacote de mensagens está incorreto.
  • Há um erro de correspondência entre o pacote de mensagens e a variável de substituição de mensagens especificada no gadget.

Retornar ao início