My favorites | English | Sign in

More personalization in Google Friend Connect New!

Legacy Gadgets API (Deprecated)

Gadgets and Internationalization (i18n)

This document describes how to create gadgets that can be easily localized for an international audience.

Contents

  1. Introduction
  2. Basic Concepts
  3. Encoding for Internationalization
  4. Example
  5. Creating a Localized Gadget
  6. Message Bundles
    1. Naming Conventions
    2. Best Practices
  7. Using Message Bundles in a Gadget
    1. Message Fallback
    2. Accessing Messages from Message Bundles
    3. Displaying Messages in Gadget HTML
  8. Hello World Gadget Spec
  9. Creating Bi-directional Gadgets
    1. Changing Direction for Part of a Gadget
  10. Testing
  11. Caching
  12. Troubleshooting
  13. Supported Languages and Countries

Introduction

The gadgets API gives you an easy way to make your gadget available to an international audience. It’s simple: all you have to do is structure your gadget to so that user-visible text (any text that should be translated) is in message bundles that are separate from your gadget. Then 3rd party translators translate your strings and create new locale-specific message bundles, which you add to your gadget spec. Thus your gadget becomes available to a new group of users.

I18n gadgets work unmodified on all other Google properties, such as Google Desktop.

For a list of the languages and countries supported by iGoogle, see Supported Languages and Countries.

For a discussion on working with non-English gadgets, see Non-English Gadgets.

Basic Concepts

This document refers to internationalization (i18n) and localization (l10n):

  • I18n means structuring applications in a way that makes it possible for them to be localized.
  • L10n means making an application work for a particular market, such as French-speaking Canadians.

For the purposes of this document, a user’s “localization profile” consists of two components: a country (based on the user’s domain), and a preferred user interface language (see Testing for details).

Encoding for Internationalization

The gadgets API supports UTF-8 encodings for XML attribute values and in the <Content> section. When your content type is set to html, UTF-8 is explicitly set as the default encoding. You should not try to set this yourself.

Example

The example gadget used in this document displays the message “Hello World,” shown here in Chinese:

Hello World-Chinese

In this example, the user preferences drop-down menu lets users specify a font color for the “Hello World” message. The color names that appear in the menu are defined in external files (message bundles). The language in which the menu is displayed depends on the user’s country/language profile. If a user with an English profile runs this gadget, the text appears in English. Here is what the English version of the example looks like with the drop-down userprefs menu displayed:

Hello World-English

You can see the gadget spec for Hello World here.

Creating a Localized Gadget

To create a localized gadget, the basic steps are as follows:

  1. Write the gadget.
  2. Extract any text that needs to be translated into message bundles.
  3. Find someone who can help you translate the gadget.
  4. The translator creates a new message bundle for a particular locale. This could be per language (French), or per language/country (French/Canada, French/France). Note that non-English message bundles must be saved in UTF-8 format.
  5. The translator sends you a URL to the new bundle.
  6. Modify your gadget spec to use the message bundle.
  7. If your gadget is in the Content Directory, wait 1-2 weeks for the crawler and pipeline to find your updated gadget and make it available in the new market.

Message Bundles

The gadgets i18n strategy centers around message bundles. Message bundles are XML files that contain the translated strings for a given locale. Each string is identified by a unique name that is the same across bundles.

Message bundles can be hosted at any URL, and can be shared between applications. Message bundles contain only one locale.

Message bundles have the following format:

<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> 

The possible fields you can include in a message bundle file are as follows:

  • messagebundle: A group of messages for translation.
  • msg: A single piece of translatable content, usually a label, sentence, or even paragraph.
  • msg name: A human-readable ID for each message.

Naming Conventions

By convention, message bundles are named as follows:

<language>_<country>.xml 

Where there is no language- or country-specific value, the convention is to use “ALL.” For example, the file de_ALL.xml applies to all German speakers, regardless of their country. The message bundle ALL_ALL.xml is the file that is used by default.

Best Practices

There is no strict requirement to follow the message bundle naming conventions. The gadget uses the lang and country attributes of <Locale> to identify the correct message bundle file for the user’s profile. It does not use the name of the message bundle itself.

However, even though the gadgets API gives you a lot of flexibility, we recommend that you follow these guidelines:

  • Always provide an ALL_ALL.xml message bundle for default message handling.
  • Specify one locale per language. That is, use fr_ALL, de_ALL, and so on.
  • If you need to do locale-specific overrides, use lang-country message bundles. For example, if you want to provide a Canadian English message bundle to override en_ALL, use en_CA, not ALL_CA.

Using Message Bundles in a Gadget

You use the <Locale> tag (nested inside of the <ModulePrefs> section) to list the message bundles used by your gadget. For example:

<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> can have the following attributes:

  • messages: A message bundle that is accessed through a URL.
  • lang: The language the message bundle strings have been translated into.
  • country: There aren’t examples of this in the “Hello World” gadget spec, but you can also specify a country attribute. For example, this message bundle is tailored to French-speaking Canadian users:
<Locale lang="fr" country="CA" messages="http://example.com/fr_CA.xml"/> 

At run-time, the gadget uses the message bundle that most closely matches the user’s profile.

For a list of supported language and country codes, see Supported Languages and Countries.

Message Fallback

Message bundles have a fallback feature. With message fallback, the gadget tries to use the message bundle that most closely matches the user’s country and language UI preference (specified in the URL). If the gadget can’t find an exact match, it “falls back” through the available message bundles to find the closest match.

With message fallback, you can have "default" messages (typically specified in ALL_ALL.xml), in case one isn’t available for a given locale. 

For example, imagine that you have the following specified in your gadget:

<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"/>

How would these files be used? Suppose you have a user whose domain is the US (http://www.google.com), but whose language preference is German. She would see the messages from the de_US.xml file. If a particular message weren’t available from that file, she would see the message from de_ALL.xml, and finally, ALL_ALL.xml.

A user from Germany using the German UI would start with de_DE.xml, a user from Switzerland using the German UI would start with de_ALL.xml, and a user from Switzerland using the French UI would start with ALL_ALL.xml.

Accessing Messages from Message Bundles

How does a gadget access the appropriate message in a message bundle? Consider the de_ALL.xml (German language, country ALL) file in the “Hello World” example:

<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>

Each message has a unique name string that identifies it. For example, in this message:

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

the unique message name is “red” and the translated string that appears in the gadget (in its userprefs drop-down menu) is “Rot”, the German word for “red”. Here is the equivalent English message string in the message bundle ALL_ALL.xml:

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

The “Hello World” gadget spec uses the __MSG_ substitution variable to indicate where the value from the appropriate message bundle should be substituted. For example, this XML statement in the “Hello World” gadget spec is used to add a menu item to the userprefs “Color” drop-down menu:

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

In effect this line says “Go to the message bundle that best matches the user’s country/language profile, get the value for the message named ‘red’, and substitute it in place of __MSG_red__.” This is how the user preferences drop-down menu in the “Hello World” example is populated with color names (here shown in German):

Hello World-German

Displaying Messages in Gadget HTML

To display messages in the XML portion of your gadget, you use substitution variables, as discussed above. Within the CDATA portion of your gadget, you have a few different options.

The simplest technique is to embed the substitution variable in your HTML:

<b>__MSG_hello_world__</b>. 

Alternatively, you can use the userprefs function getMsg(). Note that this function can be used to access all of the messages in message bundles, not just the ones relating to userprefs. However, you must call this function on an _IG_Prefs object. For example:

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

Hello World Gadget Spec

Here is the gadget spec for the "Hello World" example:

<?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[
    <script type="text/javascript"> 
      displayMsg();
      function displayMsg(){
          // Get userprefs
          var prefs = new _IG_Prefs();
          // Set font color to user's color choice
          document.fgColor = prefs.getString("fontcolor");
          // Display message
          document.write("<br><h1>");
          // Use prefs.getMsg to go to the appropriate message bundle
          // and get the string associated with the "hello_world" message.
          document.write(prefs.getMsg("hello_world"));
          document.write("</h1>"); 
      }
    </script>
  ]]>
  </Content>
</Module> 

Creating Bi-directional Gadgets

You can use the gadgets BIDI (bi-directional) API to dynamically change the direction of a gadget. "Direction" refers to the direction in which content is displayed: left-to-right, or right-to-left. Note that this is different from alignment. For example, you could have a gadget with right-aligned English text, but the direction of the text itself would still be left-to-right.

The BIDI API makes it possible to write gadgets that support both right-to-left languages (such as Hebrew and Arabic), as well as left-to-right languages (such as English). The BIDI API includes the following:

  • A language_direction attribute under the <Locale...> tag. Its value can either be "rtl" (right-to-left) or "ltr" (left-to-right). You use this attribute to set the direction of the gadget. By default, gadgets have the direction left-to-right.
  • A set of __BIDI_... substitution variables whose values change depending on the direction of the gadget. For example, the variable __BIDI_DIR__ has the value "ltr" when the gadget is in left-to-right mode, and "rtl" when the gadget is in right-to-left mode.

In the simplest case, you can use <Locale... language_direction="rtl"> to statically set the direction for a gadget. For example, this gadget only displays Hebrew text, so its direction is set to always be right-to-left:

<?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>

However, suppose you have a gadget that includes message bundles for both left-to-right and right-to-left languages. How would you design your gadget to support both cases? Here is an example of a gadget that dynamically changes direction according to which message bundle gets loaded for a user's locale. This gadget has message bundles for two right-to-left languages, Hebrew (iw) and Arabic (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>

For this gadget, suppose the user's language preference is Arabic. The line <Locale lang="ar" messages="http://.../ar_ALL.xml" language_direction="rtl"/> says "for Arabic, display the text in the message bundle ar_ALL.xml, and set the gadget direction to rtl." The direction would also be right-to-left for Hebrew. For the other languages, the gadget direction is implicitly set to the default ltr (left-to-right).

The line <div style="margin-__BIDI_START_EDGE__:30px;"><h2>__MSG_hello_world__</h2></div> says "when the gadget is in left-to-right mode, offset the text from the left margin by 30 pixels. When the gadget is in right-to-left mode, offset the text from the right margin by 30 pixels." For example, if the user's browser setting is Arabic (right-to-left), this is how the substitution is done at run-time:

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

This table lists the BIDI substitution variables and their possible values. Note that their values are always relative to the direction of the gadget itself. In other words, these variables are designed to be used in conjunction with the <Locale... language_direction="..."> setting. You can use these variables anywhere within the body of the gadget.

Variable Description
__BIDI_START_EDGE__ This variable represents the side of the gadget that is the starting point for content display. The value is "left" when the gadget is in LTR-mode and "right" when the gadget is in RTL-mode. The above gadget gives an example of using this variable for CSS margin settings.
__BIDI_END_EDGE__ This variable represents the edge of the gadget that is opposite to where content display starts. The value is "right" when the gadget is in LTR-mode and "left" when the gadget is in RTL-mode.
__BIDI_DIR__ The value of this variable is "ltr" when the gadget is in LTR-mode and "rtl" when the gadget is in RTL-mode.
__BIDI_REVERSE_DIR__ The value of this variable is "rtl" when the gadget is in LTR-mode and "ltr" when the gadget is in RTL-mode.

Changing Direction for Part of a Gadget

The BIDI API is designed to change the direction of an entire gadget, and to format the gadget's content accordingly. However, there may be cases where you want to tweak the direction of individual lines of text within a gadget. You may not want the gadget direction to be tied to the user's language setting, or to any particular language. For example, you might create a gadget that simultaneously displays English and Hebrew text. Or, you might create a gadget that lists common phrases for a variety of languages. You can use regular DOM function calls and CSS to set text direction within the body of a gadget. For example:

<?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>

Testing

To test your gadget, you can change your country and language settings to correspond to the message bundles your gadget includes.

The simplest way to change your country and language settings in iGoogle is to edit the URL:

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

For example, in the following URL, the country is Germany (DE) and the language is English (en). Typically, country takes precedence over language, so with this URL, iGoogle displays text in German:

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

In this example the country is implicitly the US, and the language is Spanish:

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

For a list of supported language and country codes, see Supported Languages and Countries. You can use this link to help construct the correct URL for a particular language: http://www.google.com/help/customize.html#searchlang.

Caching

Message bundles have the same caching behavior as for gadget specs themselves: we typically refresh the cache every 1-2 hours, hosting servers should see only ~100-200 requests per day for message bundles, and if they're unavailable, we'll continue using our "stale" copy for as long as we can.  In the developer.xml gadget, if you disable caching for a gadget, it also disables caching for the gadget’s message bundles.

Troubleshooting

During development, you might find that your gadget either comes up blank or displays ??? where a message should be. The problem could be any of the following:

  • You didn’t save the message bundle as UTF-8. This is necessary for any non-English language files that include special characters.
  • There is a problem with your message bundle syntax.
  • You don’t have an ALL_ALL.xml message file for your gadget to use by default.
  • In your gadget, the URL for the message bundle is incorrect.
  • There is a mismatch between the message bundle and the message substitution variable you specified in your gadget.

Supported Languages and Countries

This section lists the language and country codes supported by iGoogle. By convention language codes are lowercase and country codes are uppercase in the tables below, but this is not a requirement.

iGoogle supports the following languages:

Language Code Language
ar Arabic
bg Bulgarian
ca Catalan
cs Czech
da
Danish
de German
el Greek
en-gb English (United Kingdom)
en-us English (United States)
es Spanish
fi Finnish
fr French
hi Hindi
hr Croatian
hu Hungarian
id Indonesian
iw or he Hebrew
is Icelandic
it Italian
ja Japanese
ko Korean
lt Lithuanian
lv Latvian
ms Malay
nl Dutch
no Norwegian
pl Polish
pt-BR Portuguese (Brazil)
pt-PT Portuguese (Portugal)
ro Romanian
sk Slovak
sl Slovenian
sr Serbian
sv Swedish
ru Russian
th Thai
tl Filipino / Tagalog
tr Turkish
uk Ukrainian
vi Vietnamese
zh-CN Simplified Chinese
zh-TW Traditional Chinese

iGoogle supports the following countries/regions:

Country Code Country
AE United Arab Emirates
AT Austria
AU Australia
AR Argentina
BE Belgium
BG Bulgaria
BO Bolivia
BR Brazil
CA Canada
CH Switzerland
CL Chile
CO Colombia
CR Costa Rica
CS Yugoslavia
CZ Czech Republic
DE Germany
DK Denmark
DO Dominican Republic
EC Ecuador
EG Eygpt
ES Spain
FI Finland
FR France
GR Greece
GT Guatemala
HK Hong Kong
HN Honduras
HR Croatia
HU Hungary
ID Indonesia
IE Ireland
IL Israel
IN India
IS Iceland
IT Italy
JO Jordan
JP Japan
KR Korea
LT Lithuania
LV Latvia
MA Morocco
MX Mexico
MY Malaysia
NL Netherlands
NO Norway
NZ New Zealand
OM Oman
PA Panama
PE Peru
PH Philippines
PK Pakistan
PL Poland
PR Puerto Rico
PT Portugal
PY Paraguay
RO Romania
RU Russia
SA Saudi Arabia
SE Sweden
SG Singapore
SK Slovakia
SI Slovenia
SV El Salvador
TH Thailand
TR Turkey
TW Taiwan
UA Ukraine
UK United Kingdom
US United States
UY Uraguay
VE Venezuela
VN Vietnam
ZA South Africa

Back to top