Home | History | Annotate | Download | only in intros
      1 <!--
      2 [NOTEs for editors:
      3  * Try to be consistent about string vs. message (it's probably not yet).
      4 -->
      5 
      6 <p>
      7 You need to put all of its user-visible strings into a file
      8 named <a href="i18n-messages"><code>messages.json</code></a>.
      9 Each time you add a new locale,
     10 you add a messages file
     11 under a directory
     12 named <code>_locales/<em>localeCode</em></code>,
     13 where <em>localeCode</em> is a code such as
     14 <code>en</code> for English.
     15 </p>
     16 
     17 <p>
     18 Here's the file hierarchy
     19 for an internationalized extension that supports
     20 English (<code>en</code>),
     21 Spanish (<code>es</code>), and
     22 Korean (<code>ko</code>):
     23 </p>
     24 
     25 <img src="{{static}}/images/i18n-hierarchy.gif"
     26  alt='In the extension directory: manifest.json, *.html, *.js, _locales directory. In the _locales directory: en, es, and ko directories, each with a messages.json file.'
     27  width="385" height="77" />
     28 
     29 
     30 <h2 id="l10">How to support multiple languages</h2>
     31 
     32 <p>
     33 Say you have an extension
     34 with the files shown in the following figure:
     35 </p>
     36 
     37 <img src="{{static}}/images/i18n-before.gif"
     38  alt='A manifest.json file and a file with JavaScript. The .json file has "name": "Hello World". The JavaScript file has title = "Hello World";'
     39  width="323" height="148">
     40 
     41 <p>
     42 To internationalize this extension,
     43 you name each user-visible string
     44 and put it into a messages file.
     45 The extension's manifest,
     46 CSS files,
     47 and JavaScript code
     48 use each string's name to get its localized version.
     49 </p>
     50 
     51 <p>
     52 Here's what the extension looks like when it's internationalized
     53 (note that it still has only English strings):
     54 </p>
     55 
     56 <img src="{{static}}/images/i18n-after-1.gif"
     57  alt='In the manifest.json file, "Hello World" has been changed to "__MSG_extName__", and a new "default_locale" item has the value "en". In the JavaScript file, "Hello World" has been changed to chrome.i18n.getMessage("extName"). A new file named _locales/en/messages.json defines "extName".'
     58  width="782" height="228">
     59 
     60 <p class="note">
     61 <b>Important:</b>
     62 If an extension has a <code>_locales</code> directory,
     63 the <a href="manifest">manifest</a>
     64 <b>must</b> define "default_locale".
     65 </p>
     66 
     67 <p>
     68 Some notes about internationalizing:
     69 </p>
     70 
     71 <ul>
     72   <li><p>
     73     You can use any of the <a href="#overview-locales">supported locales</a>.
     74     If you use an unsupported locale,
     75     Google Chrome ignores it.
     76   </p></li>
     77 
     78   <li>
     79     In <code>manifest.json</code>
     80     and CSS files,
     81     refer to a string named <em>messagename</em> like this:
     82     <pre>__MSG_<em>messagename</em>__</pre>
     83   </li>
     84 
     85   <li>
     86     In your extension or app's JavaScript code,
     87     refer to a string named <em>messagename</em>
     88     like this:
     89     <pre>chrome.i18n.getMessage("<em>messagename</em>")</pre>
     90 
     91   <li> <p>
     92     In each call to <code>getMessage()</code>,
     93     you can supply up to 9 strings
     94     to be included in the message.
     95     See <a href="#examples-getMessage">Examples: getMessage</a>
     96     for details.
     97     </p>
     98   </li>
     99 
    100   <li><p>
    101     Some messages, such as <code>@@bidi_dir</code> and <code>@@ui_locale</code>,
    102     are provided by the internationalization system.
    103     See the <a href="#overview-predefined">Predefined messages</a> section
    104     for a full list of predefined message names.
    105     </p>
    106   </li>
    107 
    108   <li>
    109     In <code>messages.json</code>,
    110     each user-visible string has a name, a "message" item,
    111     and an optional "description" item.
    112     The name is a key
    113     such as "extName" or "search_string"
    114     that identifies the string.
    115     The "message" specifies
    116     the value of the string in this locale.
    117     The optional "description"
    118     provides help to translators,
    119     who might not be able to see how the string is used in your extension.
    120     For example:
    121 <pre data-filename="messages.json">
    122 {
    123   "search_string": {
    124     "message": "hello%20world",
    125     "description": "The string we search for. Put %20 between words that go together."
    126   },
    127   ...
    128 }</pre>
    129 
    130 <p>
    131 For more information, see
    132 <a href="i18n-messages">Formats: Locale-Specific Messages</a>.
    133 </p>
    134   </li>
    135 </ul>
    136 
    137 <p>
    138 Once an extension or app is internationalized,
    139 translating it is simple.
    140 You copy <code>messages.json</code>,
    141 translate it,
    142 and put the copy into a new directory under <code>_locales</code>.
    143 For example, to support Spanish,
    144 just put a translated copy of <code>messages.json</code>
    145 under <code>_locales/es</code>.
    146 The following figure shows the previous extension
    147 with a new Spanish translation.
    148 </p>
    149 
    150 <img src="{{static}}/images/i18n-after-2.gif"
    151  alt='This looks the same as the previous figure, but with a new file at _locales/es/messages.json that contains a Spanish translation of the messages.'
    152  width="782" height="358">
    153 
    154 
    155 <h2 id="overview-predefined">Predefined messages</h2>
    156 
    157 <p>
    158 The internationalization system provides a few predefined
    159 messages to help you localize.
    160 These include <code>@@ui_locale</code>,
    161 so you can detect the current UI locale,
    162 and a few <code>@@bidi_...</code> messages
    163 that let you detect the text direction.
    164 The latter messages have similar names to constants in the
    165 <a href="http://code.google.com/apis/gadgets/docs/i18n.html#BIDI">
    166 gadgets BIDI (bi-directional) API</a>.
    167 </p>
    168 
    169 <p>
    170 The special message <code>@@extension_id</code>
    171 can be used in the CSS and JavaScript files,
    172 whether or not the extension or app is localized.
    173 This message doesn't work in manifest files.
    174 </p>
    175 
    176 <p>
    177 The following table describes each predefined message.
    178 </p>
    179 
    180 <table>
    181 <tr>
    182   <th>Message name</th> <th>Description</th>
    183 </tr>
    184 <tr>
    185   <td> <code>@@extension_id</code> </td>
    186   <td>The extension or app ID;
    187     you might use this string to construct URLs
    188     for resources inside the extension.
    189     Even unlocalized extensions can use this message.
    190     <br>
    191     <b>Note:</b> You can't use this message in a manifest file.
    192     </td>
    193 </tr>
    194 <tr>
    195   <td> <code>@@ui_locale</code> </td>
    196   <td>The current locale;
    197     you might use this string to construct locale-specific URLs. </td>
    198 </tr>
    199 <tr>
    200   <td> <code>@@bidi_dir</code> </td>
    201   <td> The text direction for the current locale,
    202        either "ltr" for left-to-right languages such as English
    203        or "rtl" for right-to-left languages such as Japanese. </td>
    204 </tr>
    205 <tr>
    206   <td> <code>@@bidi_reversed_dir</code> </td>
    207   <td> If the <code>@@bidi_dir</code> is "ltr", then this is "rtl";
    208        otherwise, it's "ltr". </td>
    209 </tr>
    210 <tr>
    211   <td> <code>@@bidi_start_edge</code> </td>
    212   <td> If the <code>@@bidi_dir</code> is "ltr", then this is "left";
    213        otherwise, it's "right". </td>
    214 </tr>
    215 <tr>
    216   <td> <code>@@bidi_end_edge</code> </td>
    217   <td> If the <code>@@bidi_dir</code> is "ltr", then this is "right";
    218        otherwise, it's "left". </td>
    219 </tr>
    220 </table>
    221 
    222 <p>
    223 Here's an example of using <code>@@extension_id</code> in a CSS file
    224 to construct a URL:
    225 </p>
    226 
    227 <pre>
    228 body {
    229   <b>background-image:url('chrome-extension://__MSG_@@extension_id__/background.png');</b>
    230 }
    231 </pre>
    232 
    233 <p>
    234 If the extension ID is abcdefghijklmnopqrstuvwxyzabcdef,
    235 then the bold line in the previous code snippet becomes:
    236 </p>
    237 
    238 <pre>
    239 background-image:url('chrome-extension://abcdefghijklmnopqrstuvwxyzabcdef/background.png');
    240 </pre>
    241 
    242 <p>
    243 Here's an example of using <code>@@bidi_*</code> messages in a CSS file:
    244 </p>
    245 
    246 <pre>
    247 body {
    248   <b>direction: __MSG_@@bidi_dir__;</b>
    249 }
    250 
    251 div#header {
    252   margin-bottom: 1.05em;
    253   overflow: hidden;
    254   padding-bottom: 1.5em;
    255   <b>padding-__MSG_@@bidi_start_edge__: 0;</b>
    256   <b>padding-__MSG_@@bidi_end_edge__: 1.5em;</b>
    257   position: relative;
    258 }
    259 </pre>
    260 
    261 <p>
    262 For left-to-right languages such as English,
    263 the bold lines become:
    264 </p>
    265 
    266 <pre>
    267 dir: ltr;
    268 padding-left: 0;
    269 padding-right: 1.5em;
    270 </pre>
    271 
    272 
    273 <h2 id="overview-locales">Locales</h2>
    274 
    275 <p>
    276 You can choose from many locales,
    277 including some (such as <code>en</code>)
    278 that let a single translation support multiple variations of a language
    279 (such as <code>en_GB</code> and <code>en_US</code>).
    280 </p>
    281 
    282 
    283 <h3 id="locales-supported">Supported locales</h3>
    284 
    285 <p>
    286 You can use any of the
    287 <a href="http://code.google.com/chrome/webstore/docs/i18n.html#localeTable">locales that the Chrome Web Store supports</a>.
    288 </p>
    289 
    290 
    291 <h3 id="locales-usage">Searching for messages</h3>
    292 
    293 <p>
    294 You don't have to define every string for every supported locale.
    295 As long as the default locale's <code>messages.json</code> file
    296 has a value for every string,
    297 your extension or app will run no matter how sparse a translation is.
    298 Here's how the extension system searches for a message:
    299 </p>
    300 
    301 <ol>
    302   <li>
    303      Search the messages file (if any)
    304      for the user's preferred locale.
    305      For example, when Google Chrome's locale is set to
    306      British English (<code>en_GB</code>),
    307      the system first looks for the message in
    308      <code>_locales/en_GB/messages.json</code>.
    309      If that file exists and the message is there,
    310      the system looks no further.
    311   </li>
    312   <li>
    313      If the user's preferred locale has a region
    314      (that is, the locale has an underscore: _),
    315      search the locale without that region.
    316      For example, if the <code>en_GB</code> messages file
    317      doesn't exist or doesn't contain the message,
    318      the system looks in the <code>en</code> messages file.
    319      If that file exists and the message is there,
    320      the system looks no further.
    321   </li>
    322   <li>
    323      Search the messages file for the default locale.
    324      For example, if the extension's "default_locale" is set to "es",
    325      and neither <code>_locales/en_GB/messages.json</code>
    326      nor <code>_locales/en/messages.json</code> contains the message,
    327      the extension uses the message from
    328      <code>_locales/es/messages.json</code>.
    329   </li>
    330 </ol>
    331 
    332 <p>
    333 In the following figure,
    334 the message named "colores" is in all three locales
    335 that the extension supports,
    336 but "extName" is in only two of the locales.
    337 Wherever a user running Google Chrome in US English sees the label "Colors",
    338 a user of British English sees "Colours".
    339 Both US English and British English users
    340 see the extension name "Hello World".
    341 Because the default language is Spanish,
    342 users running Google Chrome in any non-English language
    343 see the label "Colores" and the extension name "Hola mundo".
    344 </p>
    345 
    346 <img src="{{static}}/images/i18n-strings.gif"
    347  alt='Four files: manifest.json and three messages.json files (for es, en, and en_GB).  The es and en files show entries for messages named "extName" and "colores"; the en_GB file has just one entry (for "colores").'
    348  width="493" height="488" />
    349 
    350 <h3 id="locales-testing">How to set your browser's locale</h3>
    351 
    352 <p>
    353 To test translations, you might want to set your browser's locale.
    354 This section tells you how to set the locale in
    355 <a href="#testing-win">Windows</a>,
    356 <a href="#testing-mac">Mac OS X</a>, and
    357 <a href="#testing-linux">Linux</a>.
    358 </p>
    359 
    360 <h4 id="testing-win">Windows</h4>
    361 
    362 <p>
    363 You can change the locale using either
    364 a locale-specific shortcut
    365 or the Google Chrome UI.
    366 The shortcut approach is quicker, once you've set it up,
    367 and it lets you use several languages at once.
    368 </p>
    369 
    370 <h5 id="win-shortcut">Using a locale-specific shortcut</h5>
    371 
    372 <p>
    373 To create and use a shortcut that launches Google Chrome
    374 with a particular locale:
    375 </p>
    376 
    377 <ol>
    378   <li>
    379     Make a copy of the Google Chrome shortcut
    380     that's already on your desktop.
    381   </li>
    382   <li>
    383     Rename the new shortcut to match the new locale.
    384   </li>
    385   <li>
    386     Change the shortcut's properties
    387     so that the Target field specifies the
    388     <code>--lang</code> and
    389     <code>--user-data-dir</code> flags.
    390     The target should look something like this:
    391 
    392 <pre><em>path_to_chrome.exe</em> --lang=<em>locale</em> --user-data-dir=c:\<em>locale_profile_dir</em></pre>
    393   </li>
    394 
    395   <li>
    396     Launch Google Chrome by double-clicking the shortcut.
    397   </li>
    398 </ol>
    399 
    400 <p>
    401 For example, to create a shortcut
    402 that launches Google Chrome in Spanish (<code>es</code>),
    403 you might create a shortcut named <code>chrome-es</code>
    404 that has the following target:
    405 </p>
    406 
    407 <pre><em>path_to_chrome.exe</em> --lang=es --user-data-dir=c:\chrome-profile-es</pre>
    408 
    409 <p>
    410 You can create as many shortcuts as you like,
    411 making it easy to test in multiple languages.
    412 For example:
    413 </p>
    414 
    415 <pre><em>path_to_chrome.exe</em> --lang=en --user-data-dir=c:\chrome-profile-en
    416 <em>path_to_chrome.exe</em> --lang=en_GB --user-data-dir=c:\chrome-profile-en_GB
    417 <em>path_to_chrome.exe</em> --lang=ko --user-data-dir=c:\chrome-profile-ko</pre>
    418 
    419 <p class="note">
    420 <b>Note:</b>
    421 Specifying <code>--user-data-dir</code> is optional but handy.
    422 Having one data directory per locale
    423 lets you run the browser
    424 in several languages at the same time.
    425 A disadvantage is that because the locales' data isn't shared,
    426 you have to install your extension multiple times &mdash; once per locale,
    427 which can be challenging when you don't speak the language.
    428 For more information, see
    429 <a href="http://www.chromium.org/developers/creating-and-using-profiles">Creating and Using Profiles</a>.
    430 </p>
    431 
    432 
    433 <h5 id="win-ui">Using the UI</h5>
    434 
    435 <p>
    436 Here's how to change the locale using the UI on Google Chrome for Windows:
    437 </p>
    438 
    439 <ol>
    440   <li> Wrench icon > <b>Options</b> </li>
    441   <li> Choose the <b>Under the Hood</b> tab </li>
    442   <li> Scroll down to <b>Web Content</b> </li>
    443   <li> Click <b>Change font and language settings</b> </li>
    444   <li> Choose the <b>Languages</b> tab </li>
    445   <li> Use the drop down to set the <b>Google Chrome language</b> </li>
    446   <li> Restart Chrome </li>
    447 </ol>
    448 
    449 
    450 <h4 id="testing-mac">Mac OS X</h4>
    451 
    452 <p>
    453 To change the locale on Mac,
    454 you use the system preferences.
    455 </p>
    456 
    457 <ol>
    458   <li> From the Apple menu, choose <b>System Preferences</b> </li>
    459   <li> Under the <b>Personal</b> section, choose <b>International</b> </li>
    460   <li> Choose your language and location </li>
    461   <li> Restart Chrome </li>
    462 </ol>
    463 
    464 
    465 <h4 id="testing-linux">Linux</h4>
    466 
    467 <p>
    468 To change the locale on Linux,
    469 first quit Google Chrome.
    470 Then, all in one line,
    471 set the LANGUAGE environment variable
    472 and launch Google Chrome.
    473 For example:
    474 </p>
    475 
    476 <pre>
    477 LANGUAGE=es ./chrome
    478 </pre>
    479 
    480 
    481 <h2 id="overview-examples">Examples</h2>
    482 
    483 <p>
    484 You can find simple examples of internationalization in the
    485 <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/">examples/api/i18n</a>
    486 directory.
    487 For a complete example, see
    488 <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/">examples/extensions/news</a>.
    489 For other examples and for help in viewing the source code, see
    490 <a href="samples">Samples</a>.
    491 </p>
    492 
    493 
    494 <h3 id="examples-getMessage">Examples: getMessage</h3>
    495 
    496 <!--
    497 [PENDING: improve this section. it should probably start with a
    498 one-variable example that includes the messages.json code.]
    499 -->
    500 
    501 <p>
    502 The following code gets a localized message from the browser
    503 and displays it as a string.
    504 It replaces two placeholders within the message with the strings
    505 "string1" and "string2".
    506 </p>
    507 
    508 <pre>
    509 function getMessage() {
    510   var message = chrome.i18n.getMessage("click_here", ["string1", "string2"]);
    511   document.getElementById("languageSpan").innerHTML = message;
    512 }
    513 </pre>
    514 
    515 <p>
    516 Here's how you'd supply and use a single string:
    517 </p>
    518 
    519 <pre>
    520 <em>// In JavaScript code</em>
    521 status.innerText = chrome.i18n.getMessage("error", errorDetails);
    522 </pre>
    523 <pre data-filename="messages.json">
    524 "error": {
    525   "message": "Error: $details$",
    526   "description": "Generic error template. Expects error parameter to be passed in.",
    527   "placeholders": {
    528     "details": {
    529       "content": "$1",
    530       "example": "Failed to fetch RSS feed."
    531     }
    532   }
    533 }
    534 </pre>
    535 
    536 <p>
    537 For more information about placeholders, see the
    538 <a href="i18n-messages">Locale-Specific Messages</a> page.
    539 For details on calling <code>getMessage()</code>, see the
    540 $(ref:i18n.getMessage API reference).
    541 </p>
    542 
    543 <h3 id="example-accept-languages">Example: getAcceptLanguages</h3>
    544 <p>
    545 The following code gets accept-languages from the browser and displays them as a
    546 string by separating each accept-language with ','.
    547 </p>
    548 
    549 <pre>
    550 function getAcceptLanguages() {
    551   chrome.i18n.getAcceptLanguages(function(languageList) {
    552     var languages = languageList.join(",");
    553     document.getElementById("languageSpan").innerHTML = languages;
    554   })
    555 }
    556 </pre>
    557 
    558 <p>
    559 For details on calling <code>getAcceptLanguages()</code>, see the
    560 $(ref:i18n.getAcceptLanguages API reference).
    561 </p>
    562