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