• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!--
2[NOTEs for editors:
3 * Try to be consistent about string vs. message (it's probably not yet).
4-->
5
6<p>
7You need to put all of its user-visible strings into a file
8named <a href="i18n-messages.html"><code>messages.json</code></a>.
9Each time you add a new locale,
10you add a messages file
11under a directory
12named <code>_locales/<em>localeCode</em></code>,
13where <em>localeCode</em> is a code such as
14<code>en</code> for English.
15</p>
16
17<p>
18Here's the file hierarchy
19for an internationalized extension that supports
20English (<code>en</code>),
21Spanish (<code>es</code>), and
22Korean (<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>
33Say you have an extension
34with 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>
42To internationalize this extension,
43you name each user-visible string
44and put it into a messages file.
45The extension's manifest,
46CSS files,
47and JavaScript code
48use each string's name to get its localized version.
49</p>
50
51<p>
52Here'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>
62If an extension has a <code>_locales</code> directory,
63the <a href="manifest.html">manifest</a>
64<b>must</b> define "default_locale".
65</p>
66
67<p>
68Some 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>
131For more information, see
132<a href="i18n-messages.html">Formats: Locale-Specific Messages</a>.
133</p>
134  </li>
135</ul>
136
137<p>
138Once an extension or app is internationalized,
139translating it is simple.
140You copy <code>messages.json</code>,
141translate it,
142and put the copy into a new directory under <code>_locales</code>.
143For example, to support Spanish,
144just put a translated copy of <code>messages.json</code>
145under <code>_locales/es</code>.
146The following figure shows the previous extension
147with 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>
158The internationalization system provides a few predefined
159messages to help you localize.
160These include <code>@@ui_locale</code>,
161so you can detect the current UI locale,
162and a few <code>@@bidi_...</code> messages
163that let you detect the text direction.
164The latter messages have similar names to constants in the
165<a href="http://code.google.com/apis/gadgets/docs/i18n.html#BIDI">
166gadgets BIDI (bi-directional) API</a>.
167</p>
168
169<p>
170The special message <code>@@extension_id</code>
171can be used in the CSS and JavaScript files,
172whether or not the extension or app is localized.
173This message doesn't work in manifest files.
174</p>
175
176<p>
177The 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>
223Here's an example of using <code>@@extension_id</code> in a CSS file
224to construct a URL:
225</p>
226
227<pre>
228body {
229  <b>background-image:url('chrome-extension://__MSG_@@extension_id__/background.png');</b>
230}
231</pre>
232
233<p>
234If the extension ID is abcdefghijklmnopqrstuvwxyzabcdef,
235then the bold line in the previous code snippet becomes:
236</p>
237
238<pre>
239background-image:url('chrome-extension://abcdefghijklmnopqrstuvwxyzabcdef/background.png');
240</pre>
241
242<p>
243Here's an example of using <code>@@bidi_*</code> messages in a CSS file:
244</p>
245
246<pre>
247body {
248  <b>direction: __MSG_@@bidi_dir__;</b>
249}
250
251div#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>
262For left-to-right languages such as English,
263the bold lines become:
264</p>
265
266<pre>
267dir: ltr;
268padding-left: 0;
269padding-right: 1.5em;
270</pre>
271
272
273<h2 id="overview-locales">Locales</h2>
274
275<p>
276You can choose from many locales,
277including some (such as <code>en</code>)
278that 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>
286You 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>
294You don't have to define every string for every supported locale.
295As long as the default locale's <code>messages.json</code> file
296has a value for every string,
297your extension or app will run no matter how sparse a translation is.
298Here'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>
333In the following figure,
334the message named "colores" is in all three locales
335that the extension supports,
336but "extName" is in only two of the locales.
337Wherever a user running Google Chrome in US English sees the label "Colors",
338a user of British English sees "Colours".
339Both US English and British English users
340see the extension name "Hello World".
341Because the default language is Spanish,
342users running Google Chrome in any non-English language
343see 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>
353To test translations, you might want to set your browser's locale.
354This 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>
363You can change the locale using either
364a locale-specific shortcut
365or the Google Chrome UI.
366The shortcut approach is quicker, once you've set it up,
367and 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>
373To create and use a shortcut that launches Google Chrome
374with 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>
401For example, to create a shortcut
402that launches Google Chrome in Spanish (<code>es</code>),
403you might create a shortcut named <code>chrome-es</code>
404that 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>
410You can create as many shortcuts as you like,
411making it easy to test in multiple languages.
412For 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>
421Specifying <code>--user-data-dir</code> is optional but handy.
422Having one data directory per locale
423lets you run the browser
424in several languages at the same time.
425A disadvantage is that because the locales' data isn't shared,
426you have to install your extension multiple times &mdash; once per locale,
427which can be challenging when you don't speak the language.
428For 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>
436Here'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>
453To change the locale on Mac,
454you 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>
468To change the locale on Linux,
469first quit Google Chrome.
470Then, all in one line,
471set the LANGUAGE environment variable
472and launch Google Chrome.
473For example:
474</p>
475
476<pre>
477LANGUAGE=es ./chrome
478</pre>
479
480
481<h2 id="overview-examples">Examples</h2>
482
483<p>
484You 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>
486directory.
487For 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>.
489For other examples and for help in viewing the source code, see
490<a href="samples.html">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
498one-variable example that includes the messages.json code.]
499-->
500
501<p>
502The following code gets a localized message from the browser
503and displays it as a string.
504It replaces two placeholders within the message with the strings
505"string1" and "string2".
506</p>
507
508<pre>
509function getMessage() {
510  var message = chrome.i18n.getMessage("click_here", ["string1", "string2"]);
511  document.getElementById("languageSpan").innerHTML = message;
512}
513</pre>
514
515<p>
516Here's how you'd supply and use a single string:
517</p>
518
519<pre>
520<em>// In JavaScript code</em>
521status.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>
537For more information about placeholders, see the
538<a href="i18n-messages.html">Locale-Specific Messages</a> page.
539For 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>
545The following code gets accept-languages from the browser and displays them as a
546string by separating each accept-language with ','.
547</p>
548
549<pre>
550function 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>
559For details on calling <code>getAcceptLanguages()</code>, see the
560$ref:[i18n.getAcceptLanguages API reference].
561</p>
562