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> &mdash;
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 &mdash; 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