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