summaryrefslogtreecommitdiffstats
path: root/chrome/common/extensions/docs/static/i18n.html
blob: abe5c9e2c3d424e423266d53de72067fa786cf6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
<div id="pageData-name" class="pageData">Internationalization (i18n)</div>

<!--
[NOTEs for editors:
 * Try to be consistent about string vs. message (it's probably not yet).
-->

<!-- BEGIN AUTHORED CONTENT -->
<p id="classSummary">
An <em>internationalized</em> extension
can be easily
<em>localized</em> &mdash;
adapted to languages and regions
that it didn't originally support.
</p>

<p>
To internationalize your extension,
you need to put all of its user-visible strings into a file
named <a href="i18n-messages.html"><code>messages.json</code></a>.
Each time you localize your extension
you add a messages file
under a directory
named <code>_locales/<em>localeCode</em></code>,
where <em>localeCode</em> is a code such as
<code>en</code> for English.
</p>

<p>
Here's the file hierarchy
for an internationalized extension that supports
English (<code>en</code>),
Spanish (<code>es</code>), and
Korean (<code>ko</code>):
</p>

<img src="images/i18n-hierarchy.gif"
 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.'
 width="385" height="77" />


<h2 id="l10">How to support multiple languages</h2>

<p>
Say you have an extension
with the files shown in the following figure:
</p>

<img src="images/i18n-before.gif"
 alt='A manifest.json file and a file with JavaScript. The .json file has "name": "Hello World". The JavaScript file has title = "Hello World";'
 width="323" height="148">

<p>
To internationalize this extension,
you name each user-visible string
and put it into a messages file.
The extension's manifest,
CSS files,
and JavaScript code
use each string's name to get its localized version.
</p>

<p>
Here's what the extension looks like when it's internationalized
(note that it still has only English strings):
</p>

<img src="images/i18n-after-1.gif"
 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".'
 width="782" height="228">

<p class="note">
<b>Important:</b>
If an extension has a <code>_locales</code> directory,
the <a href="manifest.html">manifest</a>
<b>must</b> define "default_locale".
</p>

<p>
Some notes about internationalizing extensions:
</p>

<ul>
  <li><p>
    You can use any of the <a href="#overview-locales">supported locales</a>.
    If you use an unsupported locale,
    Google Chrome ignores it.
  </p></li>

  <li>
    In <code>manifest.json</code>
    and CSS files,
    refer to a string named <em>messagename</em> like this:
    <pre>__MSG_<em>messagename</em>__</pre>
  </li>

  <li>
    In your extension's JavaScript code,
    refer to a string named <em>messagename</em>
    like this:
    <pre>chrome.i18n.getMessage("<em>messagename</em>")</pre>

  <li> <p>
    In each call to <code>getMessage()</code>,
    you can supply up to 9 strings
    to be included in the message.
    See <a href="#examples-getMessage">Examples: getMessage</a>
    for details.
    </p>
  </li>

  <li><p>
    Some messages, such as <code>@@bidi_dir</code> and <code>@@ui_locale</code>,
    are provided by the internationalization system.
    See the <a href="#overview-predefined">Predefined messages</a> section
    for a full list of predefined message names.
    </p>
  </li>

  <li>
    In <code>messages.json</code>,
    each user-visible string has a name, a "message" item,
    and an optional "description" item.
    The name is a key
    such as "extName" or "search_string"
    that identifies the string.
    The "message" specifies
    the value of the string in this locale.
    The optional "description"
    provides help to translators,
    who might not be able to see how the string is used in your extension.
    For example:
<pre>
{
  "search_string": {
    "message": "hello%20world",
    "description": "The string we search for. Put %20 between words that go together."
  },
  ...
}</pre>

<p>
For more information, see
<a href="i18n-messages.html">Formats: Locale-Specific Messages</a>.
</p>
  </li>
</ul>

<p>
Once an extension is internationalized,
translating it is simple.
You copy <code>messages.json</code>,
translate it,
and put the copy into a new directory under <code>_locales</code>.
For example, to support Spanish,
just put a translated copy of <code>messages.json</code>
under <code>_locales/es</code>.
The following figure shows the previous extension
with a new Spanish translation.
</p>

<img src="images/i18n-after-2.gif"
 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.'
 width="782" height="358">


<h2 id="overview-predefined">Predefined messages</h2>

<p>
The internationalization system provides a few predefined
messages to help you localize your extension.
These include <code>@@ui_locale</code>,
so you can detect the current UI locale,
and a few <code>@@bidi_...</code> messages
that let you detect the text direction.
The latter messages have similar names to constants in the
<a href="http://code.google.com/apis/gadgets/docs/i18n.html#BIDI">
gadgets BIDI (bi-directional) API</a>.
</p>

<p>
The special message <code>@@extension_id</code>
can be used in the CSS and JavaScript files of any extension,
whether or not the extension is localized.
This message doesn't work in manifest files.
</p>

<p class="note">
<b>Note:</b>
Content script CSS files can't use
predefined messages such as <code>@@extension_id</code>.
For details, see
<a href="http://crbug.com/39899">bug 39899</a>.
</p>

<p>
The following table describes each predefined message.
</p>

<table>
<tr>
  <th>Message name</th> <th>Description</th>
</tr>
<tr>
  <td> <code>@@extension_id</code> </td>
  <td>The extension ID;
    you might use this string to construct URLs
    for resources inside the extension.
    Even unlocalized extensions can use this message.
    <br>
    <b>Note:</b> You can't use this message in a manifest file.
    </td>
</tr>
<tr>
  <td> <code>@@ui_locale</code> </td>
  <td>The current locale;
    you might use this string to construct locale-specific URLs. </td>
</tr>
<tr>
  <td> <code>@@bidi_dir</code> </td>
  <td> The text direction for the current locale,
       either "ltr" for left-to-right languages such as English
       or "rtl" for right-to-left languages such as Japanese. </td>
</tr>
<tr>
  <td> <code>@@bidi_reversed_dir</code> </td>
  <td> If the <code>@@bidi_dir</code> is "ltr", then this is "rtl";
       otherwise, it's "ltr". </td>
</tr>
<tr>
  <td> <code>@@bidi_start_edge</code> </td>
  <td> If the <code>@@bidi_dir</code> is "ltr", then this is "left";
       otherwise, it's "right". </td>
</tr>
<tr>
  <td> <code>@@bidi_end_edge</code> </td>
  <td> If the <code>@@bidi_dir</code> is "ltr", then this is "right";
       otherwise, it's "left". </td>
</tr>
</table>

<p>
Here's an example of using <code>@@extension_id</code> in a CSS file
to construct a URL:
</p>

<pre>
body {
  <b>background-image:url('chrome-extension://__MSG_@@extension_id__/background.png');</b>
}
</pre>

<p>
If the extension ID is abcdefghijklmnopqrstuvwxyzabcdef,
then the bold line in the previous code snippet becomes:
</p>

<pre>
background-image:url('chrome-extension://abcdefghijklmnopqrstuvwxyzabcdef/background.png');
</pre>

<p>
Here's an example of using <code>@@bidi_*</code> messages in a CSS file:
</p>

<pre>
body {
  <b>direction: __MSG_@@bidi_dir__;</b>
}

div#header {
  margin-bottom: 1.05em;
  overflow: hidden;
  padding-bottom: 1.5em;
  <b>padding-__MSG_@@bidi_start_edge__: 0;</b>
  <b>padding-__MSG_@@bidi_end_edge__: 1.5em;</b>
  position: relative;
}
</pre>

<p>
For left-to-right languages such as English,
the bold lines become:
</p>

<pre>
dir: ltr;
padding-left: 0;
padding-right: 1.5em;
</pre>


<h2 id="overview-locales">Locales</h2>

<p>
Extensions can use all the locales that Google Chrome supports,
plus a few (such as <code>en</code>)
that let a single translation support multiple variations of a language
(such as <code>en_GB</code> and <code>en_US</code>).
</p>


<h3 id="locales-supported">Supported locales</h3>

<p>
Your extension can use any of the following locales:
</p>

<p>
<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
lv  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>
</p>


<h3 id="locales-usage">How extensions find strings</h3>

<p>
You don't have to define every string for every locale
that your internationalized extension supports.
As long as the default locale's <code>messages.json</code> file
has a value for every string,
your extension will run no matter how sparse a translation is.
Here's how the extension system searches for a message:
</p>

<ol>
  <li>
     Search the messages file (if any)
     for the user's preferred locale.
     For example, when Google Chrome's locale is set to
     British English (<code>en_GB</code>),
     the system first looks for the message in
     <code>_locales/en_GB/messages.json</code>.
     If that file exists and the message is there,
     the system looks no further.
  </li>
  <li>
     If the user's preferred locale has a region
     (that is, the locale has an underscore: _),
     search the locale without that region.
     For example, if the <code>en_GB</code> messages file
     doesn't exist or doesn't contain the message,
     the system looks in the <code>en</code> messages file.
     If that file exists and the message is there,
     the system looks no further.
  </li>
  <li>
     Search the messages file for the extension's default locale.
     For example, if the extension's "default_locale" is set to "es",
     and neither <code>_locales/en_GB/messages.json</code>
     nor <code>_locales/en/messages.json</code> contains the message,
     the extension uses the message from
     <code>_locales/es/messages.json</code>.
  </li>
</ol>

<p>
In the following figure,
the message named "colores" is in all three locales
that the extension supports,
but "extName" is in only two of the locales.
Wherever a user running Google Chrome in US English sees the label "Colors",
a user of British English sees "Colours".
Both US English and British English users
see the extension name "Hello World".
Because the default language is Spanish,
users running Google Chrome in any non-English language
see the label "Colores" and the extension name "Hola mundo".
</p>

<img src="images/i18n-strings.gif"
 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").'
 width="493" height="488" />

<h3 id="locales-testing">How to set your browser's locale</h3>

<p>
To test translations, you might want to set your browser's locale.
This section tells you how to set the locale in
<a href="#testing-win">Windows</a>,
<a href="#testing-mac">Mac OS X</a>, and
<a href="#testing-linux">Linux</a>.
</p>

<h4 id="testing-win">Windows</h4>

<p>
You can change the locale using either
a locale-specific shortcut
or the Google Chrome UI.
The shortcut approach is quicker, once you've set it up,
and it lets you use several languages at once.
</p>

<h5 id="win-shortcut">Using a locale-specific shortcut</h5>

<p>
To create and use a shortcut that launches Google Chrome
with a particular locale:
</p>

<ol>
  <li>
    Make a copy of the Google Chrome shortcut
    that's already on your desktop.
  </li>
  <li>
    Rename the new shortcut to match the new locale.
  </li>
  <li>
    Change the shortcut's properties
    so that the Target field specifies the
    <code>--lang</code> and
    <code>--user-data-dir</code> flags.
    The target should look something like this:

<pre><em>path_to_chrome.exe</em> --lang=<em>locale</em> --user-data-dir=c:\<em>locale_profile_dir</em></pre>
  </li>

  <li>
    Launch Google Chrome by double-clicking the shortcut.
  </li>
</ol>

<p>
For example, to create a shortcut
that launches Google Chrome in Spanish (<code>es</code>),
you might create a shortcut named <code>chrome-es</code>
that has the following target:
</p>

<pre><em>path_to_chrome.exe</em> --lang=es --user-data-dir=c:\chrome-profile-es</pre>

<p>
You can create as many shortcuts as you like,
making it easy to test your extension in multiple languages.
For example:
</p>

<pre><em>path_to_chrome.exe</em> --lang=en --user-data-dir=c:\chrome-profile-en
<em>path_to_chrome.exe</em> --lang=en_GB --user-data-dir=c:\chrome-profile-en_GB
<em>path_to_chrome.exe</em> --lang=ko --user-data-dir=c:\chrome-profile-ko</pre>

<p class="note">
<b>Note:</b>
Specifying <code>--user-data-dir</code> is optional but handy.
Having one data directory per locale
lets you run the browser
in several languages at the same time.
A disadvantage is that because the locales' data isn't shared,
you have to install your extension multiple times &mdash; once per locale,
which can be challenging when you don't speak the language.
For more information, see
<a href="http://www.chromium.org/developers/creating-and-using-profiles">Creating and Using Profiles</a>.
</p>


<h5 id="win-ui">Using the UI</h5>

<p>
Here's how to change the locale using the UI on Google Chrome for Windows:
</p>

<ol>
  <li> Wrench icon > <b>Options</b> </li>
  <li> Choose the <b>Under the Hood</b> tab </li>
  <li> Scroll down to <b>Web Content</b> </li>
  <li> Click <b>Change font and language settings</b> </li>
  <li> Choose the <b>Languages</b> tab </li>
  <li> Use the drop down to set the <b>Google Chrome language</b> </li>
  <li> Restart Chrome </li>
</ol>


<h4 id="testing-mac">Mac OS X</h4>

<p>
To change the locale on Mac,
you use the system preferences.
</p>

<ol>
  <li> From the Apple menu, choose <b>System Preferences</b> </li>
  <li> Under the <b>Personal</b> section, choose <b>International</b> </li>
  <li> Choose your language and location </li>
  <li> Restart Chrome </li>
</ol>


<h4 id="testing-linux">Linux</h4>

<p>
To change the locale on Linux,
first quit Google Chrome.
Then, all in one line,
set the LANGUAGE environment variable
and launch Google Chrome.
For example:
</p>

<pre>
LANGUAGE=es ./chrome
</pre>


<h2 id="overview-examples">Examples</h2>

<p>
You can find simple examples of internationalization in the
<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/">examples/api/i18n</a>
directory.
For a complete example, see
<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/">examples/extensions/news</a>.
For other examples and for help in viewing the source code, see
<a href="samples.html">Samples</a>.
</p>


<h3 id="examples-getMessage">Examples: getMessage</h3>

<!--
[PENDING: improve this section. it should probably start with a
one-variable example that includes the messages.json code.]
-->

<p>
The following code gets a localized message from the browser
and displays it as a string.
It replaces two placeholders within the message with the strings
"string1" and "string2".
</p>

<pre>
function getMessage() {
  var message = chrome.i18n.getMessage("click_here", ["string1", "string2"]);
  document.getElementById("languageSpan").innerHTML = message;
}
</pre>

<p>
Here's how you'd supply and use a single string:
</p>

<pre>
<em>// In JavaScript code</em>
status.innerText = chrome.i18n.getMessage("error", errorDetails);

<em>// In messages.json</em>
"error": {
  "message": "Error: $details$",
  "description": "Generic error template. Expects error parameter to be passed in.",
  "placeholders": {
    "details": {
      "content": "$1",
      "example": "Failed to fetch RSS feed."
    }
  }
}
</pre>

<p>
For more information about placeholders, see the
<a href="i18n-messages.html">Locale-Specific Messages</a> page.
For details on calling <code>getMessage()</code>, see the
<a href="#method-getMessage">API reference</a>.
</p>

<h3 id="example-accept-languages">Example: getAcceptLanguages</h3>
<p>
The following code gets accept-languages from the browser and displays them as a
string by separating each accept-language with ','.
</p>

<pre>
function getAcceptLanguages() {
  chrome.i18n.getAcceptLanguages(function(languageList) {
    var languages = languageList.join(",");
    document.getElementById("languageSpan").innerHTML = languages;
  })
}
</pre>

<p>
For details on calling <code>getAcceptLanguages()</code>, see the
<a href="#method-getAcceptLanguages">API reference</a>.
</p>

<!-- END AUTHORED CONTENT -->