File:  [mozdev] / books / www / chapters / ch11.html
Revision 1.15: download - view: text, annotated - select for diffs - revision graph
Fri Apr 4 16:27:40 2003 UTC (16 years, 7 months ago) by cdn
Branches: MAIN
CVS tags: HEAD
ahem

    1:     <link rel="prev" href="http://books.mozdev.org/chapters/ch10.html" />
    2:     <link rel="next" href="http://books.mozdev.org/chapters/ch12.html" />
    3: 
    4:     <style type="text/css">
    5:       div.c24 {font-weight: bold; text-align: center}
    6:       div.c23 {text-align: center}
    7:     </style>
    8: 
    9:     <h2>Chapter 11</h2>
   10:     <h1><a name="77028"></a> Localization</h1>
   11:     <p>This chapter describes how to use Mozilla's
   12:     internationalization (I18N) and localization (L10N)
   13:     technologies to make applications usable by people around the
   14:     world. Because the Mozilla community (and the Internet
   15:     community in general), is global, it is vital to be able to
   16:     cross language barriers by localizing your application and
   17:     making it available to a wider audience.</p>
   18:     <p>In this chapter, you are given step-by-step instructions on
   19:     how to change the visible text for your application in the XUL
   20:     interface and how to handle nonstatic strings that arise from
   21:     dynamic string handling in other areas of your application
   22:     code.</p>
   23:     <p>While the basic technologies that are used are not new,
   24:     Mozilla is innovating in areas such as Unicode support and
   25:     quick access language pack installs. The information in this
   26:     chapter about the internationalization (<i><a href=
   27:     "http://www.mozilla.org/projects/intl/index.html">http://www.mozilla.org/projects/intl/index.html</a></i>)
   28:     and localization (<i><a href=
   29:     "http://www.mozilla.org/projects/l10n/mlp.html">http://www.mozilla.org/projects/l10n/mlp.html</a></i>)
   30:     projects will give you a solid foundation for what is possible
   31:     in your own application.</p>
   32:     <h2><a name="77029"></a> Localization Basics</h2>
   33:     <p>Before learning how to 
   34:     <!--INDEX internationalization:(see also localization)[internationalization:zz(see also localization)] -->
   35:     <!--INDEX localization:(see also internationalization)[localization:zz(see also internationalization)] -->
   36:     <!--INDEX localization:overview --> 
   37:     <!--INDEX internationalization:overview --> localize your
   38:     Mozilla application, it's useful to run through some of the
   39:     high-level goals and features of the Mozilla
   40:     internationalization and localization projects. First, here are
   41:     some definitions:</p>
   42:     <dl>
   43:       <dt>Internationalization (I18N)</dt>
   44:       <dd>The design <!--INDEX I18N (see internationalization) -->
   45:       and development of software to function in a particular
   46:       locale. The shorthand term, I18N, refers to the 18 letters
   47:       between the initial "i" and final "n."</dd>
   48:       <dt>Localization (L10N)</dt>
   49:       <dd>The <!--INDEX L10N (see localization) --> modification of
   50:       software to meet the language of a location and the
   51:       adaptation of resources, such as the user interface (UI) and
   52:       documentation, for that region. L10N is an acronym for
   53:       localization and refers to the 10 letters between the initial
   54:       "l" and final "n."</dd>
   55:       <dt>Locale</dt>
   56:       <dd>"A set of conventions <!--INDEX locales --> affected or
   57:       determined by human language and customs, as defined within a
   58:       particular geo-political region. These conventions include
   59:       (but are not necessarily limited to) the written language,
   60:       formats for dates, numbers and currency, sorting orders,
   61:       etc.," according to the official Mozilla document found at
   62:       <i><a href=
   63:       "http://www.mozilla.org/docs/refList/i18n/">http://www.mozilla.org/docs/refList/i18n/</a></i>.</dd>
   64:     </dl>
   65:     <p>Locale in the context of this chapter is related
   66:     specifically to the display of text in the user interface. The
   67:     focus will be on UI localization of XUL files and strings
   68:     contained in JavaScript and C++ files, as well as the methods
   69:     employed for localization.</p>
   70:     <p>Here are some main features of the Mozilla
   71:     internationalization capabilities, which are relevant to the
   72:     user front end application level:</p>
   73:     <ul>
   74:       <li>Mozilla is Unicode-enabled for Latin-based languages,
   75:       Cyrillic, Greek, Chinese, Japanese, and Korean. Mozilla
   76:       widgets and HTML rendering can support the input and display
   77:       of these languages. Unicode-enabling for other languages and
   78:       character sets is an ongoing process.</li>
   79:       <li>Mozilla can be easily localized into different languages,
   80:       even if not supported by the underlying operating
   81:       system.</li>
   82:       <li>Most Mozilla localization work involves translating
   83:       strings as entities in Document Type Definition (DTD) format
   84:       and properties file format (an idea taken from Java), which
   85:       are based on open standards.</li>
   86:       <li>Localization can be done once and run on Windows,
   87:       Macintosh, Unix, and other platforms-something we have come
   88:       to expect from the Mozilla framework. This is a great time
   89:       saver, and indeed a cost saver if you come at it from that
   90:       perspective.</li>
   91:       <li>Mozilla supports BIDI, the display and input of text in a
   92:       bidirectional format for such languages as Arabic and Hebrew,
   93:       yet the capabilities for this in the UI were not mature when
   94:       we were writing this book.</li>
   95:       <li>The UI locale DTD files use UTF-8 as the default encoding
   96:       for translated items. Mozilla then maps to Unicode or
   97:       non-Unicode fonts, depending on which platform you're running
   98:       on or what fonts you installed in your system. You are
   99:       encouraged to encode your DTD files as UTF-8 when
  100:       possible.</li>
  101:     </ul>
  102:     <p>Recalling the architecture of the XPFE toolkit described in
  103:     <a href="ch02.html#77048">Chapter 2</a>, the locale component
  104:     can be easily plugged in and out of the application that you
  105:     are working on without impacting any other components. This
  106:     functionality is ideal, for instance, for people with
  107:     linguistic skills and less experience with technical issues to
  108:     become involved in a Mozilla-related project.</p>
  109:     <h3><a name="77030"></a> For the Developer</h3>
  110:     <p>Many available <!--INDEX localization:resources --> 
  111:     <!--INDEX resources:localization --> resources show you how to
  112:     help localize an existing application into a specific language
  113:     or to find out how to add localization support to your own
  114:     application. <!--INDEX newsgroups, localization --> 
  115:     <!--INDEX development:localization resources -->
  116:     </p>
  117:     <p>The Mozilla Localization Project hosts various localization
  118:     teams and provides help whenever possible. The Mozilla
  119:     community includes a discussion group that uses many languages
  120:     to discuss Mozilla development issues. The
  121:     <i>netscape.public.mozilla.l10n</i> and
  122:     <i>netscape.public.mozilla.i18n</i> newsgroups are a great
  123:     place to discuss these issues with other developers.</p>
  124:     <p>When developing an application, some words and phrases that
  125:     developers like to hear (according to the Mozilla organization,
  126:     at <i><a href=
  127:     "http://www.mozilla.org/projects/l10n/xul-l10n.html">http://www.mozilla.org/projects/l10n/xul-l10n.html</a></i>)
  128:     are: standards compliant, simple, leveragable, portable,
  129:     extensible, separable, consistent, dynamic, valid, parser
  130:     friendly, invisible (part of the XUL authoring process), and
  131:     efficient. The following sections will help you understand how
  132:     these terms and goals impact the chosen technologies and how to
  133:     use those technologies. The ultimate aim is to help you
  134:     localize your application easily.</p>
  135:     <h3><a name="77031"></a> Files and File Formats</h3>
  136:     <p>Here are the <!--INDEX localization:file types --> 
  137:     <!--INDEX files:localization file types --> main file types
  138:     you'll see when learning about locale and that you will use
  139:     when localizing your Mozilla application. A good home for all
  140:     of these resources is in the <i>locale</i> area of the
  141:     application <i>chrome</i>.</p>
  142:     <dl>
  143:       <dt>DTD (<i>.dtd</i>)</dt>
  144:       <dd>Files containing entities that host the strings from XUL
  145:       content files.</dd>
  146:       <dt>Property (<i>.properties</i>) or string bundles</dt>
  147:       <dd>Files containing strings that are accessed by JavaScript,
  148:       C++, and possibly other scripting or component files.</dd>
  149:       <dt>RDF</dt>
  150:       <dd>RDF files are described in XML syntax, so use
  151:       entities.</dd>
  152:       <dt>HTML and text</dt>
  153:       <dd>Suitable for long text, HTML and XML documents and other
  154:       content that needs to be localized.</dd>
  155:     </dl>
  156:     <p>The next two sections will help you start localizing your
  157:     application. The sections focus on DTD files and string
  158:     bundles, which are the core formats for XUL-localizable
  159:     content. Before getting started, here is a review of some
  160:     general principles that might help you design and implement the
  161:     locale component.</p>
  162:     <h3><a name="77032"></a> UI Aesthetics and Principles</h3>
  163:     <p>To put locale in context, this section looks at some issues
  164:     you may encounter when localizing your Mozilla application.
  165:     Some are universal principles and others are unique to the
  166:     environment. This reference is by no means exhaustive, but it
  167:     contains some scenarios and tips the authors came across in
  168:     their experience with locale in Mozilla.</p>
  169:     <h4><a name="77033"></a> Space management</h4>
  170:     <p>One of the 
  171:     <!--INDEX localization:UI aesthetics, space management --> 
  172:     <!--INDEX user interface:localization:space management --> 
  173:     <!--INDEX design issues, user interfaces:localization and space management -->
  174:     guiding principles in UI design is for your interface to not
  175:     get too crowded. Although estimates are not specific, it is
  176:     wise to leave about 30 percent expansion space in your window
  177:     and dialogs. To achieve this flexibility, you have to ensure
  178:     that the XUL window has ample space in the first place for all
  179:     the widgets to fit.</p>
  180:     <p>More specifically, the application needs to have space for
  181:     widgets to expand or contract without detracting from the
  182:     overall look and feel. Intuitive use of the XUL box model
  183:     (refer to <a href="ch03.html#77084">Chapter 3</a> for more
  184:     information) and correct choice of widgets goes a long way in
  185:     achieving this goal.</p>
  186:     <p>The factors that can cause this space to be filled include
  187:     using languages/character sets that are more verbose than the
  188:     one that was there originally, and the users changing their
  189:     font size settings. Some safeguards that have been built into
  190:     Mozilla already handle this problem. Much of it is done in CSS,
  191:     but other methods are available. The section "Language Quirks,"
  192:     later in this chapter, outlines one of these methods.</p>
  193:     <h4><a name="77034"></a> Help system</h4>
  194:     <p>If you <!--INDEX help system, localization and --> 
  195:     <!--INDEX localization:help system --> 
  196:     <!--INDEX user interface:localization:help system --> choose to
  197:     integrate a Help system into your application, a localizable
  198:     resource will be most content. Opinions differ within technical
  199:     writing circles, but having screenshots in your documents is
  200:     generally not considered advantageous. For example, they can
  201:     get out of date easily in the constantly evolving world of
  202:     software, or they need to be retaken frequently when new
  203:     features are added to the UI.</p>
  204:     <h4><a name="77035"></a> Tooltips</h4>
  205:     <p>Tooltips <!--INDEX tooltips:localization and --> 
  206:     <!--INDEX localization:tooltips --> 
  207:     <!--INDEX user interface:localization:tooltips --> are a
  208:     sometimes overlooked yet valuable way of relaying information
  209:     to the user. They can be used as an alternative to a help
  210:     system if you are looking for something simpler. They can also
  211:     expand an explanation of something that was annotated in the UI
  212:     text. Sometimes text can have multiple meanings in context, and
  213:     expanding it with a tooltip can clear up any confusion. In an
  214:     editor or multifile browser, for example, you might have a find
  215:     button. A tooltip can clear up the confusion about whether the
  216:     results of the action searches in the current file or in all
  217:     files.</p>
  218:     <p>Most XUL widgets support tooltips. Implementation is as
  219:     straightforward as adding a <tt>tooltip</tt> attribute to the
  220:     widget with an associated value. For it to be localizable, it
  221:     must be in the form of a DTD entity.</p>
  222: <pre>
  223: &lt;tab id="config" label="&amp;config.label;" tooltip="&amp;config.tooltip;" /&gt;
  224: </pre>
  225:     <p>The <a href="#77040">"Inserting Entities</a>" section, later
  226:     in this chapter, provides more information on the rationale for
  227:     using entities and how to insert them into XUL content.</p>
  228:     <h4><a name="77036"></a> Grammar</h4>
  229:     <p>In any user <!--INDEX grammar, localization and --> 
  230:     <!--INDEX localization:user interface:grammar considerations -->
  231:     <!--INDEX user interface:localization:grammar considerations -->
  232:     interface, there is limited screen space. When possible,
  233:     however, provide complete or near-complete sentences. These
  234:     sentences are better than using text based on phrases or
  235:     acronyms. They provide meaning to the translator and clearer
  236:     instructions to the user.</p>
  237:     <h4><a name="77037"></a> Commenting</h4>
  238:     <p>Commenting <!--INDEX comments:localization and --> 
  239:     <!--INDEX localization:user interface:commenting --> 
  240:     <!--INDEX user interface:localization:commenting --> was
  241:     mentioned before, but is worth stressing again. The translators
  242:     may have not even seen the software that you are working on,
  243:     but you hope that is not the case! Commenting is very useful
  244:     for giving context and flagging strings that should not be
  245:     commented. You can comment your HTML, XML, or DTD files by
  246:     wrapping it in a <tt>&lt;!-- comment --&gt;</tt> block.</p>
  247: <pre>
  248: &lt;!--NOTE to Translators: Do NOT change the next string --&gt;
  249: &lt;!ENTITY appName.label "My Application"&gt;
  250: </pre>
  251:     <p>Note that a bundle file uses the <tt>#</tt> notation at the
  252:     beginning of each line to signify a comment.</p>
  253: <pre>
  254: # This text is used in the view menu for launching the page choices dialog
  255: pageChoices=Go To...
  256: </pre>
  257:     <h4><a name="77038"></a> Web resources</h4>
  258:     <p>Localizable <!--INDEX web resources, localization and --> 
  259:     <!--INDEX localization:user interface:web resources --> 
  260:     <!--INDEX user interface:localization:web resources -->
  261:     resources are not only strings of text that need to be
  262:     translated into different languages; they are any variable
  263:     information that is liable to change over the lifetime of your
  264:     application. The handling of URLs is a case in point. You may
  265:     have references interspersed throughout your UI that point to
  266:     web resources. These references can be explicit listings or
  267:     widgets that, once activated, launch a client to bring you to a
  268:     certain location.</p>
  269:     <p>Images are another resource commonly used in documentation.
  270:     A tutorial on your application may have screenshots of the UI
  271:     in action. If you do use images, keep an eye out for
  272:     localizable content in them.</p>
  273:     <h2><a name="77039"></a> DTD Entities</h2>
  274:     <p>Entities in XUL <!--INDEX DTD entities --> work the same way
  275:     as they do in any other XML application. They are used to
  276:     reference data that was abstracted from the content. This
  277:     process encourages reuse of data, but in the context of
  278:     Mozilla's XPFE, it is used to extract visible text in interface
  279:     widgets. This extraction ensures that the content can remain
  280:     untouched during the localization process.</p>
  281:     <h3><a name="77040"></a> Inserting Entities</h3>
  282:     <p><a href="#77008">Example 11-1</a> shows 
  283:     <!--INDEX DTD entities:inserting into XUL code --> 
  284:     <!--INDEX XUL (XML-based User-interface Language):DTD entities, inserting into code -->
  285:     how to put DTD entities into your XUL code by using attribute
  286:     values for the text of a menu item (<tt>label</tt>) and the
  287:     keyboard access shortcuts (<tt>accesskey</tt>). The syntax
  288:     requires that an entity be placed in quotes as the value of the
  289:     attribute. This is a useful example because it highlights the
  290:     localization of a widget label, which is common to many
  291:     widgets, and a supplementary attribute, which, in this case, is
  292:     an <tt>accesskey</tt>.</p>
  293:     <p><i>Example 11-1: <a name="77008"></a></i> <i>XUL menu with
  294:     entity references for text and accesskeys</i></p>
  295: <pre>
  296:  &lt;menu label="&amp;menuFile.label;&lt;/td&gt;" accesskey="&amp;menuFile.accesskey;"&gt;
  297:    &lt;menupopup&gt;
  298:      &lt;menuitem accesskey="&amp;menuNew.accesskey;&lt;/td&gt;" label="&amp;menuNew.label;"         oncommand="doNew( );"/&gt;
  299:      &lt;menuitem accesskey="&amp;menuOpen.accesskey;" label="&amp;menuOpen.label;"        oncommand="doOpen( );"/&gt;
  300:      &lt;menuseparator /&gt;
  301:      &lt;menuitem accesskey="&amp;menuClose.accesskey;" label="&amp;menuClose.label;"        oncommand="doClose( );"/&gt;
  302:      &lt;menuitem accesskey="&amp;menuSave.accesskey;" label="&amp;menuSave.label;"        oncommand="doSave( )"/&gt;
  303:      &lt;menuitem accesskey="&amp;menuSaveAs.accesskey;" label="&amp;menuSaveAs.label;"        oncommand="doSaveAs"/&gt;
  304:      &lt;menuseparator /&gt;
  305:      &lt;menuitem accesskey="&amp;menuPrint.accesskey;" label="&amp;menuPrint.label;"        oncommand="doPrint( );"/&gt;
  306:      &lt;menuseparator /&gt;
  307:      &lt;menuitem accesskey="&amp;menuExit.accesskey;" label="&amp;menuExit.label;"
  308:          oncommand="doExit( );"/&gt;
  309:    &lt;/menupopup&gt;
  310:  &lt;/menu&gt;
  311: </pre>
  312:     <p>Note that each entity in <a href="#77008">Example 11-1</a>
  313:     has a text value associated with it in the DTD entities
  314:     declarations. The entity that appears on the menu is
  315:     <tt>&amp;menuFile.label;</tt>. Note that this entity mirrors
  316:     the correct syntax for referencing a value, which is:
  317:     <tt>&amp;get.text;</tt>.</p>
  318:     <p>The entity reference (or name, in this context) must be
  319:     preceded by an ampersand (<tt>&amp;</tt>) and end with a
  320:     semicolon (<tt>;</tt>). The period is optional, but
  321:     conventional. Typically, the period separates the entity's
  322:     element or target (<tt>menuFile</tt>) from the type of entity
  323:     (<tt>label</tt>). Refer to the<a href="#77052">"Programming and
  324:     Localization</a>" section later in this chapter for more
  325:     information on naming conventions.</p>
  326:     <p>For some widgets, including <tt>&lt;description&gt;</tt> and
  327:     <tt>&lt;label&gt;</tt>, the entity can be placed inside the
  328:     element tags, as opposed to being values of attributes.</p>
  329: <pre>
  330: &lt;description&gt;&amp;explanation.text;&lt;/description&gt;
  331: </pre>
  332:     <p><a href="#77006">Table 11-1</a> represents the DTD files
  333:     that accompany the XUL content in <a href="#77008">Example
  334:     11-1</a>. Two languages, English and Spanish, are separated
  335:     into different files. These files have the same name as the DTD
  336:     file referenced in the XUL file that contains the entities.
  337:     However, each file for every different language exists in a
  338:     separate locale folder. Each entry, or entity, in the DTD file
  339:     has a name that matches the name referenced in the XUL and a
  340:     value to be filled in for that entity. The value is enclosed in
  341:     quotes. When generating these files, you will need to create
  342:     the file only once and copy it to a different directory where
  343:     you can replace the values in the entities. A good tool would
  344:     carry out this process for you. Refer to the <a href=
  345:     "#92113">"Localization Tools</a>" sidebar later in the chapter
  346:     for more information.</p>
  347:     <p><i>Table 11-1: <a name="77006"></a></i> <i>Entity
  348:     definitions for the XUL menu</i></p>
  349:     <table width="100%" border="1">
  350:       <tr>
  351:         <td><b>English DTD</b></td>
  352:         <td><b>Spanish DTD</b></td>
  353:       </tr>
  354:       <tr>
  355:         <td>&lt;!ENTITY menuFile.label "File"&gt;</td>
  356:       </tr>
  357:       <tr>
  358:         <td>&lt;!ENTITY menuNew.label "New"&gt;</td>
  359:       </tr>
  360:       <tr>
  361:         <td>&lt;!ENTITY menuOpen.label "Open..."&gt;</td>
  362:       </tr>
  363:       <tr>
  364:         <td>&lt;!ENTITY menuClose.label "Close"&gt;</td>
  365:       </tr>
  366:       <tr>
  367:         <td>&lt;!ENTITY menuSave.label "Save"&gt;</td>
  368:       </tr>
  369:       <tr>
  370:         <td>&lt;!ENTITY menuSaveAs.label "Save As..."&gt;</td>
  371:       </tr>
  372:       <tr>
  373:         <td>&lt;!ENTITY menuPrint.label "Print..."&gt;</td>
  374:       </tr>
  375:       <tr>
  376:         <td>&lt;!ENTITY menuExit.label "Exit"&gt;</td>
  377:       </tr>
  378:       <tr>
  379:         <td>&lt;!ENTITY menuFile.accesskey "f"&gt;</td>
  380:       </tr>
  381:       <tr>
  382:         <td>&lt;!ENTITY menuNew.accesskey "n"&gt;</td>
  383:       </tr>
  384:       <tr>
  385:         <td>&lt;!ENTITY menuOpen.accesskey "o"&gt;</td>
  386:       </tr>
  387:       <tr>
  388:         <td>&lt;!ENTITY menuClose.accesskey "c"&gt;</td>
  389:       </tr>
  390:       <tr>
  391:         <td>&lt;!ENTITY menuSave.accesskey "s"&gt;</td>
  392:       </tr>
  393:       <tr>
  394:         <td>&lt;!ENTITY menuSaveAs.accesskey "a"&gt;</td>
  395:       </tr>
  396:       <tr>
  397:         <td>&lt;!ENTITY menuPrint.accesskey "p"&gt;</td>
  398:       </tr>
  399:       <tr>
  400:         <td>&lt;!ENTITY menuExit.accesskey "x"&gt;</td>
  401:         <td>&lt;!ENTITY menuFile.label "Archivo"&gt;</td>
  402:       </tr>
  403:       <tr>
  404:         <td>&lt;!ENTITY menuNew.label "Nuevo"&gt;</td>
  405:       </tr>
  406:       <tr>
  407:         <td>&lt;!ENTITY menuOpen.label "Abrir Archivo..."&gt;</td>
  408:       </tr>
  409:       <tr>
  410:         <td>&lt;!ENTITY menuClose.label "Cerrar"&gt;</td>
  411:       </tr>
  412:       <tr>
  413:         <td>&lt;!ENTITY menuSave.label "Salvar"&gt;</td>
  414:       </tr>
  415:       <tr>
  416:         <td>&lt;!ENTITY menuSaveAs.label "Salvar Como..."&gt;</td>
  417:       </tr>
  418:       <tr>
  419:         <td>&lt;!ENTITY menuPrint.label "Imprimir..."&gt;</td>
  420:       </tr>
  421:       <tr>
  422:         <td>&lt;!ENTITY menuExit.label "Salir"&gt;</td>
  423:       </tr>
  424:       <tr>
  425:         <td>&lt;!ENTITY menuFile.accesskey "a"&gt;</td>
  426:       </tr>
  427:       <tr>
  428:         <td>&lt;!ENTITY menuNew.accesskey "n"&gt;</td>
  429:       </tr>
  430:       <tr>
  431:         <td>&lt;!ENTITY menuOpen.accesskey "o"&gt;</td>
  432:       </tr>
  433:       <tr>
  434:         <td>&lt;!ENTITY menuClose.accesskey "c"&gt;</td>
  435:       </tr>
  436:       <tr>
  437:         <td>&lt;!ENTITY menuSave.accesskey "s"&gt;</td>
  438:       </tr>
  439:       <tr>
  440:         <td>&lt;!ENTITY menuSaveAs.accesskey "a"&gt;</td>
  441:       </tr>
  442:       <tr>
  443:         <td>&lt;!ENTITY menuPrint.accesskey "i"&gt;</td>
  444:       </tr>
  445:       <tr>
  446:         <td>&lt;!ENTITY menuExit.accesskey "r"&gt;</td>
  447:       </tr>
  448:     </table>
  449:     <p><a href="#77002">Figure 11-1</a> shows the resulting XUL
  450:     menus. There can only be one value for each entity and only one
  451:     language taking precedence, or appearing in the UI, at a
  452:     time.</p>
  453:     <div class="c23">
  454:       <img src="foo.gif">
  455:     </div>
  456:     <p><i>Figure 11-1: <a name="77002"></a></i> <i>Localized menus
  457:     in English and Spanish</i></p>
  458:     <p>This example presents only two languages, but theoretically,
  459:     you can have as many languages as you require. The
  460:     locale-switching mechanism and the chrome registry must
  461:     determine which one should be used, which is explained later in
  462:     the section "The Chrome Registry and Locale."</p>
  463:     <h3><a name="77041"></a> External and Inline Entities</h3>
  464:     <p>You may ask, <!--INDEX DTD entities:types --> 
  465:     <!--INDEX external DTD entities --> 
  466:     <!--INDEX internal DTD entities --> how are the entities
  467:     accessed? You can associate the DTD with your XUL file in two
  468:     ways. The first is internally, which involves wrapping the
  469:     strings in a DTD data type enclosure by using the
  470:     <tt>DOCTYPE</tt> declaration.</p>
  471: <pre>
  472: &lt;!DOCTYPE window [
  473: &lt;!ENTITY windowTitle.label "Greetings"&gt;
  474: &lt;!ENTITY fileMenu.label "File"&gt;
  475: ]&gt;
  476: </pre>
  477:     <p>The second is an external DTD file, which is associated with
  478:     your XUL that also uses the <tt>DOCTYPE</tt> declaration, and a
  479:     reference pointing to the file:</p>
  480: <pre>
  481: &lt;!DOCTYPE window SYSTEM "chrome://xfly/locale/xfly.dtd"&gt;
  482: </pre>
  483:     <p>The node referenced in the <tt>DOCTYPE</tt> declaration is
  484:     usually followed by the XUL document's root node. In this case,
  485:     it is <tt>window</tt>, but can be other elements like
  486:     <tt>page</tt> or <tt>dialog</tt> (however, it is not actually
  487:     validated so it can be any value).</p>
  488:     <p>If you have a small application, the DTD files can reside in
  489:     the same folder as your XUL files, but putting them into their
  490:     own locale directory within your chrome structure is good
  491:     practice.</p>
  492:     <p>Consider the main Editor window in Mozilla. Its declaration
  493:     in <a href="#77010">Example 11-2</a> is flexible enough to
  494:     associate multiple DTD files with your content.</p>
  495:     <p><i>Example 11-2: <a name="77010"></a></i> <i>The Editor's
  496:     Doctype definitions</i></p>
  497: <pre>
  498:  &lt;!DOCTYPE window &lt;/td&gt;[
  499:    &lt;!ENTITY % editorDTD SYSTEM "chrome://editor/locale/editor.dtd" &gt;
  500:    %editorDTD;
  501:    &lt;!ENTITY % editorOverlayDTD SYSTEM "chrome://editor/locale/editorOverlay.dtd" &gt;
  502:    %editorOverlayDTD;
  503:    &lt;!ENTITY % brandDTD SYSTEM "chrome://global/locale/brand.dtd" &gt;
  504:    %brandDTD;
  505:  ]&gt;
  506: </pre>
  507:     <p>The declaration first stores the document associated with
  508:     the chrome URL in an associated parameter entity. It then
  509:     simply uses it. XML does not have a one-step way of storing and
  510:     using the entity as in other languages. In other words, the
  511:     declaration is the equivalent of the <tt>import foo</tt> in
  512:     Python, or <tt>#include "foo.h"</tt> in C.</p>
  513:     <p>Certain localizable resources lend themselves to reuse. It
  514:     makes sense to use the same strings across different content,
  515:     which explains the inclusion of a DTD file in more than one XUL
  516:     document. In Mozilla, this includes brand information, build ID
  517:     numbers, and help resources.</p>
  518:     <p>Which is more appropriate to use: internal or external
  519:     entities? Using the external approach is preferable because the
  520:     content (XUL) does not have to be touched during the
  521:     translation process. If someone opts to create a tool to
  522:     extract and/or insert strings, their job would be much easier
  523:     if they had to parse one less file type. This may remove
  524:     context somewhat, but it can be overcome by actively commenting
  525:     the DTD file.</p>
  526:     <h2><a name="77042"></a> String Bundles</h2>
  527:     <p>String bundles <!--INDEX localization:string bundles --> 
  528:     <!--INDEX string bundles:localization --> 
  529:     <!--INDEX user interface:localization:string bundles --> are
  530:     flat text files that contain text for the UI that is accessed
  531:     in JavaScript, C++, and theoretically any language that fits
  532:     within the Mozilla framework. These bundles are strings that
  533:     can be presented visually to the user via some functionality in
  534:     the application at any time. This may be anything from a
  535:     dynamically changing menu item to an alert box, or from a URL
  536:     to a placeholder that is filled depending on the context in
  537:     which it is accessed. The bundle files are given an extension
  538:     of <i>.properties</i> and they commonly reside in the locale
  539:     directory with the DTD files.</p>
  540:     <p>A user interface can use one or more string bundles, each of
  541:     which is defined in a <tt>&lt;stringbundle&gt;</tt> element and
  542:     surrounded by a <tt>&lt;stringbundleset&gt;</tt> element. <a
  543:     href="#77012">Example 11-3</a> contains the bundles used by the
  544:     Mozilla browser.</p>
  545:     <p><i>Example 11-3: <a name="77012"></a></i> <i>String bundles
  546:     used by the Mozilla browser</i></p>
  547: <pre>
  548:  &lt;stringbundleset id="stringbundleset"&gt;
  549:      &lt;stringbundle id="bundle_navigator"
  550:          src="chrome://navigator/locale/navigator.properties"/&gt;
  551:      &lt;stringbundle id="bundle_brand"
  552:          src="chrome://global/locale/brand.properties"/&gt;
  553:      &lt;stringbundle id="bundle_navigator_region"
  554:          src="chrome://navigator-region/locale/region.properties"/&gt;
  555:      &lt;stringbundle id="bundle_brand_region"
  556:          src="chrome://global-region/locale/region.properties"/&gt;
  557:      &lt;stringbundle id="findBundle"
  558:          src="chrome://global/locale/finddialog.properties"/&gt;
  559:  &lt;/stringbundleset&gt;
  560: </pre>
  561:     <p>As you can see from their names and their locations in the
  562:     chrome, each bundle serves a different purpose. They include a
  563:     file that contains the bulk of the strings for the browser
  564:     (<i>navigator.properties</i>), a file that includes branding
  565:     strings, and a couple of files for regional information. This
  566:     model is useful if you need to output many strings to the UI
  567:     from your source code and would like to organize them into
  568:     meaningful groups.</p>
  569:     <h3><a name="77043"></a> Inside a Bundle</h3>
  570:     <p>A string 
  571:     <!--INDEX localization:string bundles:file format --> 
  572:     <!--INDEX string bundles:localization:file format --> 
  573:     <!--INDEX user interface:localization:string bundle file format -->
  574:     bundle (<i>.properties</i>) file has a very simple format. It
  575:     contains one or more lines that have the identifier associated
  576:     with the localizable string. The format of a string bundle
  577:     string with an identifier is:</p>
  578: <pre>
  579: Identifier=String
  580: </pre>
  581:     <p>The format for comments in a bundle file requires the hash
  582:     notation (<tt>#</tt>). Comments are useful for notifying
  583:     translators of the context of strings, or flagging a string
  584:     that should be left as is and not localized. Comments in
  585:     properties files are formatted in the following manner.</p>
  586: <pre>
  587: # DO NOT TRANSLATE
  588: applicationTitle=xFly
  589: </pre>
  590:     <p>Spaces in bundles are treated literally-spaces between words
  591:     are observed, with the exception of the start and the end of
  592:     the string.</p>
  593:     <p>The next section shows the methods and properties specific
  594:     to the <tt>&lt;stringbundle&gt;</tt> element that are available
  595:     to you when you use it. The implementations are contained in
  596:     the binding for the element.</p>
  597:     <h3><a name="77044"></a> String Bundle Methods and
  598:     Properties</h3>
  599:     <p>Defining your bundle in XUL and then creating the file with
  600:     the values is only half the story. This section shows how to
  601:     extract the values from the bundle and place them in UI. The
  602:     language of choice in these examples is JavaScript. This
  603:     process is necessary when you have to change values in the UI
  604:     because DTD entities can not be updated dynamically.</p>
  605:     <h4><a name="77045"></a> Methods</h4>
  606:     <p>Our bundle <!--INDEX methods:string bundles --> 
  607:     <!--INDEX localization:string bundles:methods --> 
  608:     <!--INDEX string bundles:localization:methods --> 
  609:     <!--INDEX user interface:localization:string bundle methods -->
  610:     is defined in XUL like this:</p>
  611: <pre>
  612: &lt;stringbundle id="bundle_xfly"
  613: src="chrome://xfly/locale/xfly.properties"/&gt;
  614: </pre>
  615:     <p>To access the methods of the bundle object in your script,
  616:     you have to get a handle on the XUL element by using its
  617:     <tt>id</tt>. First declare the variable globally that will be
  618:     holding the bundle:</p>
  619: <pre>
  620: var xFlyBundle;
  621: </pre>
  622:     <p>Then assign the variable to the bundle. A good place to do
  623:     this is in the load handler function of your XUL window, or in
  624:     the constructor for your binding if you are using it from
  625:     there:</p>
  626: <pre>
  627: xFlyBundle = document.getElementById("bundle_xfly");
  628: </pre>
  629:     <p>Now that you have access to the bundle, you can use the
  630:     available methods to retrieve the strings. The two main
  631:     functions are <tt>getString</tt> and
  632:     <tt>getFormattedString</tt>.</p>
  633:     <h5><a name="77046"></a> getString</h5>
  634:     <p>The most <!--INDEX getString method --> straightforward
  635:     string access method, <tt>getString</tt>, takes one parameter
  636:     (namely the identifier of the string) and returns the
  637:     localizable string value for use in the UI:</p>
  638: <pre>
  639: var readonly = xFlyBundle.getString(`readonlyFile');
  640: alert(readonly);
  641: </pre>
  642:     <p>The string bundle entry looks like this:</p>
  643: <pre>
  644: readonlyfile=This file is read only
  645: </pre>
  646:     <h5><a name="77047"></a> getFormattedString</h5>
  647:     <p>This <!--INDEX getFormattedString method --> function takes
  648:     an extra parameter-an array of string values, which are
  649:     substituted into the string in the bundle. Then the full string
  650:     with the substituted values is returned:</p>
  651: <pre>
  652: var numFiles = numberInEditor
  653: numFilesMsg = xflyBundle.getFormattedString("numFilesMessage", [numFiles]);
  654: </pre>
  655:     <p>You can have more than one value replaced in the string,
  656:     each one delimited within the square brackets by using a
  657:     comma:</p>
  658: <pre>
  659: fileInfo = xflyBundle.getFormattedString("fileInformation",
  660: [fileName, fileSize]);
  661: </pre>
  662:     <p>The string bundle entry looks like this:</p>
  663: <pre>
  664: flyFileInformation=The file is called %1$s and its size is %2$s
  665: </pre>
  666:     <p>The <tt>%x</tt> numerical value refers to the ordering of
  667:     the values to be substituted in the string. The type of the
  668:     value is determined by the dollar ($) symbol. In this case,
  669:     there are two possibilities-<tt>$s</tt> is a string value and
  670:     <tt>$d</tt> is an integer value.</p>
  671:     <h4><a name="77048"></a> Properties</h4>
  672:     <p>Some <!--INDEX properties:string bundles --> 
  673:     <!--INDEX localization:string bundles:properties --> 
  674:     <!--INDEX string bundles:localization:properties --> 
  675:     <!--INDEX user interface:localization:string bundle properties -->
  676:     binding properties that are exposed to your script accompany
  677:     the methods. These properties are not often needed for routine
  678:     retrieval of string values, but are useful to know nonetheless
  679:     if you ever need to discover or share the meta information
  680:     related to your bundle and locale.</p>
  681:     <h5><a name="77049"></a> stringBundle</h5>
  682:     <p>This <!--INDEX StringBundle property --> property is the
  683:     string bundle object that queries the
  684:     <i>nsIStringBundleService</i> interfaces and initializes the
  685:     XPCOM interface, making methods available to it. It is the
  686:     direct way of getting a string from a bundle:</p>
  687: <pre>
  688: var appBundle = document.getElementById("bundle_app");
  689: return appBundle.stringBundle.GetStringFromName("chapter11");
  690: </pre>
  691:     <h5><a name="77050"></a> src</h5>
  692:     <p>This property <!--INDEX src property --> is the attribute
  693:     used to get and set the properties file that will be used as a
  694:     string bundle:</p>
  695: <pre>
  696: var appBundle = document.getElementById("bundle_app");
  697: dump("You are using the properties file " + appBundle.src);
  698: </pre>
  699:     <h3><a name="77051"></a> Creating Your Own Bundle</h3>
  700:     <p>The implementation <!--INDEX string bundles:creating --> 
  701:     <!--INDEX localization:string bundles:creating --> for setting
  702:     up your string bundle just described is hidden from the XUL
  703:     author. You only need to point at the bundle you want to use by
  704:     using the source attribute. There is however, an alternative
  705:     way to do this if you do not favor using
  706:     <tt>&lt;stringbundle&gt;</tt> or would like to extend that
  707:     binding.</p>
  708:     <p>The alternative is to use utility routines that come bundled
  709:     with Mozilla and are contained in a string resources JavaScript
  710:     file: <i>strres.js</i>. With this file, creating a bundle is a
  711:     three-step process.</p>
  712:     <ol>
  713:       <li>Include the JavaScript file:</li>
  714:     </ol>
  715: <pre>
  716: &lt;script type="application/x-javascript"
  717: src="chrome://global/content/strres.js"/&gt;
  718: </pre>
  719:     <ol>
  720:       <li>Set up your bundle:</li>
  721:     </ol>
  722: <pre>
  723: var bundle =
  724: srGetStrBundle("chrome://mypackage/locale/mypackage.properties");
  725: </pre>
  726:     <ol>
  727:       <li>Access the strings:</li>
  728:     </ol>
  729: <pre>
  730: var greeting = bundle.GetStringFromName( "hello" );
  731: </pre>
  732:     <p>The result retrieves the string corresponding to "hello" in
  733:     your bundle file and is the equivalent of the
  734:     <tt>getString</tt> call when using the XUL bundle method.</p>
  735:     <p>If your chrome is independent of Mozilla's chrome and you do
  736:     not want to use their UI files, you can create the bundle
  737:     directly by using the <i>nsIStringBundleService</i> XPCOM
  738:     interface, as seen in <a href="#77014">Example 11-4</a>.</p>
  739:     <p><i>Example 11-4: <a name="77014"></a></i> <i>Creating the
  740:     bundle via XPConnect</i></p>
  741: <pre>
  742:  var src = 'chrome://packagexfly/content/packagebundle.properties';
  743:  var localeService =
  744:      Components.classes&lt;/td&gt;["@mozilla.org/intl/nslocaleservice;1"]
  745:      .getService(Components.interfaces.nsILocaleService&lt;/td&gt;);
  746:  var appLocale =  localeService.GetApplicationLocale( );
  747:  var stringBundleService =
  748:      Components.classes&lt;/td&gt;["@mozilla.org/intl/stringbundle;1"]
  749:      .getService(Components.interfaces.nsIStringBundleService&lt;/td&gt;);
  750:  bundle = stringBundleService.CreateBundle(src, appLocale);
  751: </pre>
  752:     <p>The first step is to get the application locale-the language
  753:     that is currently registered with the chrome service. This is
  754:     done via the <tt>nsILocalService</tt> component. The
  755:     <i>nsIStringBundleService</i> is then initialized and the
  756:     <tt>CreateBundle</tt> method is called, returning an instance
  757:     of <i>nsIStringBundle</i> that provides access to the methods
  758:     for querying strings.</p>
  759:     <h2><a name="77052"></a> Programming and Localization</h2>
  760:     <p>This section provides little nuggets of information, not
  761:     necessarily related, that show how to work around common
  762:     problems when programming locale-related information in your
  763:     application. It strays a little from the main path of string
  764:     replacement and translation, and the topics vary from
  765:     recommended naming conventions for your string identifiers to
  766:     locale in XBL bindings and what tools you can use to be more
  767:     productive.</p>
  768:     <h3><a name="77053"></a> Naming Conventions</h3>
  769:     <p>The decision 
  770:     <!--INDEX programming localization:naming conventions --> 
  771:     <!--INDEX localization:programming:naming conventions --> 
  772:     <!--INDEX 
  773:     naming conventions, localization --> of what to call your code
  774:     internals emerged more than once in this book. In <a href=
  775:     "ch08.html#77048">Chapter 8</a>, you decided the name of the
  776:     component IDL interface IDL file and its associated
  777:     implementation. In locale, it is the entity names and string
  778:     identifiers contained in bundles.</p>
  779:     <p>Naming conventions in localization are useful because they
  780:     provide some context to the translator. In this spirit, it is
  781:     good for the reference to be as descriptive as possible. You
  782:     can choose your route for naming or stick with the way that
  783:     Mozilla does it. Examining the files in the Mozilla source
  784:     base, common naming conventions for entities include the
  785:     following:</p>
  786:     <blockquote>
  787:       id.label id.tooltip id.text id.accesskey id.commandkey
  788:     </blockquote>
  789:     <p>Certain XUL widgets can contain multiple localizable
  790:     resources, including a text <tt>label</tt> or
  791:     <tt>description</tt>, a <tt>tooltip</tt>, and an
  792:     <tt>accesskey</tt>. A button is a prime example:</p>
  793: <pre>
  794: &lt;button id="flyBtn" label="&amp;flyBtn.label;" accesskey="&amp;flyBtn.accesskey;"
  795: tooltip="&amp;flyBtn.tooltip;" /&gt;
  796: </pre>
  797:     <p>The naming convention is consistent, using the value of the
  798:     <tt>id</tt> attribute appended by the name of the UI feature.
  799:     The attribute and name are delimited by a period. Not only does
  800:     using this value flag the resource as being associated with a
  801:     certain widget, but it also permits logical grouping in the
  802:     DTD:</p>
  803: <pre>
  804: &lt;!ENTITY flyBtn.label "Fly Away"&gt;
  805: &lt;!ENTITY flyBtn.accesskey "f"&gt;
  806: &lt;!ENTITY flyBtn.tooltip "Click here to take to the air"&gt;
  807: </pre>
  808:     <p>Naming string identifiers in bundle files fits less into a
  809:     pattern like that in DTDs, and in the Mozilla, source files may
  810:     appear random. If a pattern must be found, you could look at
  811:     two things: filenames and identifier descriptions.</p>
  812:     <p>In a filename, the association of a single
  813:     <i>.properties</i> file is with a logical part of the
  814:     application. If a string appears in a certain dialog or window,
  815:     you know where to go to translate the strings or add more
  816:     strings. Example files in the Mozilla tree worth examining
  817:     include <i>editor.properties</i>,
  818:     <i>commonDialogs.properties</i>, and
  819:     <i>wizardManager.properties</i>.</p>
  820:     <p>With identifier descriptions, the text used on the
  821:     identifier describes what the text actually refers to. The goal
  822:     is to be as descriptive as possible by using as brief text as
  823:     possible:</p>
  824: <pre>
  825: dontDeleteFiles=Don't Delete Files
  826: </pre>
  827:     <p>The descriptor is the same as the value, although in a
  828:     different format. The opportunity was taken here to be as
  829:     descriptive as possible.</p>
  830:     <h3><a name="77054"></a> Breaking Up the Text</h3>
  831:     <p>Under certain 
  832:     <!--INDEX programming localization:line breaks in messages --> 
  833:     <!--INDEX localization:programming:line breaks in messages --> 
  834:     <!--INDEX message localization, line breaks --> circumstances,
  835:     you may need to pop up your own alert messages as XUL dialogs.
  836:     Some messages may involve multiple lines of text that need to
  837:     be put on new lines. There is no natural delimiter that breaks
  838:     up the text contained within <tt>&lt;description&gt;</tt> or
  839:     <tt>&lt;label&gt;</tt> elements in XUL, so following are a
  840:     couple of tricks to get around this problem.</p>
  841:     <h4><a name="77055"></a> Method 1: Multiple &lt;description&gt;
  842:     elements</h4>
  843:     <p>First, create 
  844:     <!--INDEX description element, localization programming considerations -->
  845:     the placeholder in your XUL where the generated elements will
  846:     be inserted:</p>
  847: <pre>
  848: &lt;vbox id="main-message" flex="1" style="max-width: 40em;"/&gt;
  849: &lt;!-- insert elements here --&gt;
  850: &lt;/vbox&gt;
  851: </pre>
  852:     <p>The script in <a href="#77016">Example 11-5</a> generates
  853:     the needed text elements, fills in the text, and appends all
  854:     the items to the containing box.</p>
  855:     <p><i>Example 11-5: <a name="77016"></a></i> <i>Using multiple
  856:     &lt;description&gt; elements</i></p>
  857: <pre>
  858:  var text = window.arguments[0];
  859:  var holder = document.getElementById("main-message");
  860:  var lines = text.split("\n");
  861:  for (var i = 0; i &lt; lines.length; i++) {
  862:    var descriptionNode = document.createElement("description");
  863:    var linetext = document.createTextNode(lines[i]);
  864:    descriptionNode.appendChild(linetext);
  865:    holder.appendChild(descriptionNode);
  866:  }
  867: </pre>
  868:     <p>The text is passed into the window that is used for the
  869:     message. It presumes that the <tt>\n</tt> delimiter is used to
  870:     signify a new line in the text and is split thus. Then it loops
  871:     through each line, creating a description element for each line
  872:     and populating it with a text node with the message inside.
  873:     Then each element is appended to the main container that lives
  874:     in the XUL file.</p>
  875:     <h4><a name="77056"></a> Method 2: HTML &lt;br&gt; tag</h4>
  876:     <p>For this example, 
  877:     <!--INDEX br element, localization programming considerations -->
  878:     create the XUL placeholder similar to the example in Method 1,
  879:     and then slot the script in <a href="#77018">Example 11-6</a>
  880:     into your load handler.</p>
  881:     <p><i>Example 11-6: <a name="77018"></a></i> <i>Using the HTML
  882:     break tag</i></p>
  883: <pre>
  884:  var text = window.arguments[0];
  885:  var holder = document.getElementById("main-message");
  886:  var lines = text.split("\n");
  887:  var descriptionNode = document.createElement("description");
  888:  for (var i = 0; i &lt; lines.length; i++) {
  889:    var linetext = document.createTextNode(lines[i]);
  890:    var breakNode = document.createElement("html:br");
  891:    descriptionNode.appendChild(linetext);
  892:    descriptionNode.appendChild(breakNode);
  893:  }
  894:  holder.appendChild(descriptionNode);
  895: </pre>
  896:     <p>This way is similar to the code in <a href="#77016">Example
  897:     11-5</a>, with some notable differences. First, there is only
  898:     one <tt>&lt;description&gt;</tt> element created outside the
  899:     loop for each new line. In that loop, the break occurs when an
  900:     HTML <tt>&lt;br&gt;</tt> element is inserted after a piece of
  901:     text.</p>
  902:     <p>With both methods, you need to put some sort of width
  903:     constraint on the window at the level where you want the text
  904:     to wrap. Method 1 is recommended because it is a true XUL
  905:     solution, but the second method is also a good example of mixed
  906:     markup in a XUL document (HTML).</p>
  907:     <h3><a name="77057"></a> Anonymous Content and Locale</h3>
  908:     <p>Entities are everywhere. Well, not quite everywhere.
  909:     However, as entity references and DTD constructs are part of
  910:     the XML language, they can be used for localization purposes in
  911:     other files in your package, such as RDF and XBL files.</p>
  912:     <p>In the case of XBL, it is common for 
  913:     <!--INDEX binding content, localization --> 
  914:     <!--INDEX localization:binding content --> binding content to
  915:     inherit its locale information from the base widget. Take the
  916:     <a href="#77020">Example 11-7</a> as a case in point. Here is
  917:     the bound element in the XUL document; the binding for the
  918:     bound element is shown:</p>
  919: <pre>
  920: &lt;article id="artheader" class="articleheader" title="Common Garden Flies" author="Brad Buzzworth"/&gt;
  921: </pre>
  922:     <p>The attributes of note here are <tt>title</tt> and
  923:     <tt>author</tt>, both user-defined, because they contain the
  924:     localizable values that will be used in the binding.</p>
  925:     <p><i>Example 11-7: <a name="77020"></a></i> <i>Binding with
  926:     attribute inheritance</i></p>
  927: <pre>
  928:  &lt;binding id="articleheader"&gt;
  929:    &lt;content&gt;
  930:      &lt;xul:hbox flex="1"&gt;
  931:        &lt;xul:label class="flybox-homeheader-text" xbl:inherits="value=title"&lt;/td&gt;/&gt;
  932:        &lt;xul:spacer flex="1"/&gt;
  933:        &lt;xul:label class="flybox-homeheader-text" xbl:inherits="value=author"&lt;/td&gt;/&gt;
  934:      &lt;/xul:hbox&gt;
  935:    &lt;/content&gt;
  936:    &lt;implementation&gt;
  937:      &lt;property name="title"&gt;
  938:        &lt;setter&gt;
  939:          &lt;!&lt;/td&gt;[CDATA[
  940:            this.setAttribute('title',val); return val;
  941:          ]]&gt;
  942:        &lt;/setter&gt;
  943:        &lt;getter&gt;
  944:          &lt;!&lt;/td&gt;[CDATA[
  945:            return this.getAttribute('title');
  946:          ]]&gt;
  947:        &lt;/getter&gt;
  948:      &lt;/property&gt;
  949:      &lt;property name="author"&gt;
  950:        &lt;setter&gt;
  951:          &lt;!&lt;/td&gt;[CDATA[
  952:            this.setAttribute('author',val); return val;
  953:          ]]&gt;
  954:        &lt;/setter&gt;
  955:        &lt;getter&gt;
  956:          &lt;!&lt;/td&gt;[CDATA[
  957:            return this.getAttribute('author');
  958:          ]]&gt;
  959:        &lt;/getter&gt;
  960:      &lt;/property&gt;
  961:    &lt;/implementation&gt;
  962:  &lt;/binding&gt;
  963: </pre>
  964:     <p>The binding in <a href="#77020">Example 11-7</a> illustrates
  965:     a binding whose content inherits its locale from the bound
  966:     element. The attributes used on the bound element, namely
  967:     <tt>title</tt> and <tt>author</tt>, are descriptive, enabling
  968:     the author to be specific about what they are setting a value
  969:     to. The rest is taken care of in the binding, where the
  970:     <tt>inherits</tt> attribute sets the value on the anonymous
  971:     content to the value of the more descriptive attributes on the
  972:     bound element. You can retrieve the values or set them by using
  973:     the getter and setter.</p>
  974:     <blockquote>
  975:       <hr>
  976:       <a name="92113"></a> Localization 
  977:       <!--INDEX localization:tools --> Tools 
  978:       <p>To translate your XUL interface strings, just change the
  979:       text that corresponds to your entity reference or string
  980:       bundle value. For a small application, this step should be
  981:       simple, but for large applications, it can be a big task.</p>
  982:       <p>The good news is that tools are available to help localize
  983:       your applications. The most popular tool is
  984:       MozillaTranslator, which is discussed in more detail in <a
  985:       href="appb.html#77021">Appendix B</a>.</p>
  986:       <p>There is also a handy command line utility for Unicode
  987:       conversion called nsconv, bundled in the Mozilla <i>bin</i>
  988:       folder in any distribution. (If you are unfamiliar with
  989:       Unicode, the section <a href="#77067">"XPFE and Unicode</a>"
  990:       later in this chapter provides more information.) Although it
  991:       is broken at the time of this writing, it is worth
  992:       mentioning. Let's look at a simple conversion of ASCII text
  993:       to UTF-8:</p>
  994: <pre>
  995: &lt;!ENTITY PrintPreviewCmd.label    "Print Preview"&gt;
  996: </pre>
  997:       Replace the string in the entity with the Spanish version: 
  998: <pre>
  999: &lt;!ENTITY PrintPreviewCmd.label    "Presentaci&oacute;n preliminar..."&gt;
 1000: </pre>
 1001:       Then run the conversion. 
 1002: <pre>
 1003: &gt; nsconv -f ascii -t utf-8 foo.dtd bar.dtd
 1004: </pre>
 1005:       The accented characters are converted into the Unicode for
 1006:       you: 
 1007: <pre>
 1008: &lt;!ENTITY PrintPreviewCmd.label   "Presentaci&amp;#243;n preliminar..."&gt;
 1009: </pre>
 1010:       Using the NCR or CER value as well is also acceptable, if
 1011:       appropriate. A NCR is an entity that contains a hex
 1012:       (<tt>&amp;#x61;</tt>) or decimal (<tt>&amp;#97;</tt>) value,
 1013:       while a CER is also an entity containing an abbreviation
 1014:       (<tt>&amp;eacute;</tt>). This assumes, though, that you know
 1015:       what the code is! String bundles accept only one form of
 1016:       encoding, which is known as <tt>escape-unicode</tt>. If using
 1017:       nsconv, the name for this encoding is <tt>x-u-escaped</tt>. 
 1018:       <p>Various third-party conversion tools that do the same
 1019:       thing are available. A freeware editor called Unipad that
 1020:       lets you import multiple types of native encoding documents
 1021:       and then save as Unicode. Unipad is available from <i><a
 1022:       href=
 1023:       "http://www.unipad.org/">http://www.unipad.org/</a></i>.</p>
 1024:       <hr>
 1025:     </blockquote>
 1026:     <h3><a name="77058"></a> Localizable Resources in HTML</h3>
 1027:     <p>As a web <!--INDEX localization:HTML and --> 
 1028:     <!--INDEX HTML (Hypertext Markup Language):localization and -->
 1029:     application, Mozilla permits seamless integration of web
 1030:     content, both local and remote, in many formats. If you have
 1031:     verbose text that just needs to be displayed somewhere in the
 1032:     framework of your application, HTML or XML content may be ideal
 1033:     for this purpose. Through the use of XUL content widgets, such
 1034:     as <tt>&lt;iframe&gt;</tt> and <tt>&lt;browser&gt;</tt>, you
 1035:     have ready-made frames to slot your content into:</p>
 1036: <pre>
 1037: &lt;iframe src="xFly.html" flex="1"/&gt;
 1038: </pre>
 1039:     <p>Therefore, a simple modification of <i>xFly.html</i> with a
 1040:     local language leaves the main application untouched. Some
 1041:     other uses of HTML or XML content include an "About"
 1042:     dialog/page, Help pages, a wizard interface, or a getting
 1043:     started/introduction page.</p>
 1044:     <h3><a name="77059"></a> Localizable Resources in RDF</h3>
 1045:     <p>Strings to be 
 1046:     <!--INDEX RDF (Resource Description Framework):localization and -->
 1047:     <!--INDEX localization:RDF and --> converted in RDF content can
 1048:     take more than one form. You can use entities directly in your
 1049:     RDF file or have the text inline in your node descriptions.
 1050:     Whichever method you choose, you must ensure that the file is
 1051:     installed in the right place in the tree and registered
 1052:     correctly for the application to pick up on it.</p>
 1053:     <p>As an XML markup, RDF can handle inline entity definitions.
 1054:     These entity definitions have been covered thoroughly in the
 1055:     chapter so far. <a href="#77022">Example 11-8</a> looks at
 1056:     localizable strings contained directly in RDF node
 1057:     descriptions. This example is taken from the Help table of
 1058:     contents in the Mozilla tree.</p>
 1059:     <p><i>Example 11-8: <a name="77022"></a></i> <i>RDF Description
 1060:     node with localizable text</i></p>
 1061: <pre>
 1062:  &lt;rdf:Description about="#nav-doc"&gt;
 1063:    &lt;nc:subheadings&gt;
 1064:      &lt;rdf:Seq&gt;
 1065:        &lt;rdf:li&gt;
 1066:          &lt;rdf:Description ID="nav-doc-language"
 1067:                 &lt;/td&gt;nc:name="Language and Translation Services"
 1068:                 nc:link="chrome://help/locale/nav_help.html#nav_language"/&gt;
 1069:        &lt;/rdf:li&gt;
 1070:      &lt;/rdf:Seq&gt;
 1071:    &lt;/nc:subheadings&gt;
 1072:  &lt;/rdf:Description&gt;
 1073: </pre>
 1074:     <p>The text in the <tt>nc:name</tt> attribute is the text that
 1075:     will be changed. Note that this issue of text in RDF is
 1076:     separate from the topic of using RDF as the mechanism in the
 1077:     chrome registry to register your locale and set up a switching
 1078:     mechanism. This difference is addressed in the next
 1079:     section.</p>
 1080:     <h2><a name="77060"></a> The Chrome Registry and Locale</h2>
 1081:     <p>Your application is built and you're ready to upload your
 1082:     shiny new Mozilla program to your server for download. The last
 1083:     piece of the puzzle, locale versions, has been put in place.
 1084:     With the structures that Mozilla has in place, it no longer has
 1085:     to be an afterthought. Once you have the translated files, you
 1086:     need to make the decision about how you want to distribute your
 1087:     language versions, the languages you want to make available to
 1088:     the users, and the level of customization that you want to give
 1089:     to them.</p>
 1090:     <p>In this section, we look at how the Mozilla application
 1091:     suite handles the chrome's locale component. Then you see how
 1092:     to apply these chrome registry structures and utilities on a
 1093:     more generic level for your application.</p>
 1094:     <h3><a name="77061"></a> The Directory Structure</h3>
 1095:     <p>A typical 
 1096:     <!--INDEX localization:chrome directory structure --> 
 1097:     <!--INDEX chrome:localization:directory structure -->
 1098:     application chrome structure looks like the directory structure
 1099:     in <a href="#77004">Figure 11-2</a>. A folder for each language
 1100:     is under the <i>locale</i> directory. The general format is
 1101:     that each language has a unique identifier based on country
 1102:     code and the region. This conforms to the ISO-639 two-letter
 1103:     code with ISO-3166 two-letter country code standards.</p>
 1104:     <blockquote>
 1105:       <div class="c24">
 1106:         NOTE
 1107:       </div>
 1108:       <p>The W3C site has good resources that provide information
 1109:       about the ISO-639 and ISO-3166 standards at <i><a href=
 1110:       "http://www.w3.org/International/O-HTML-tags.html">http://www.w3.org/International/O-HTML-tags.html</a></i>.</p>
 1111:     </blockquote>
 1112:     <p>For example, the unique identifier for Scots, Great Britain,
 1113:     is <i>Sc-GB</i>. The first code, <i>Sc</i>, is for the Scots
 1114:     (Scottish) dialect, and the second code, <i>GB</i>, is for the
 1115:     country code for Great Britain. This is the standard that
 1116:     Mozilla follows.</p>
 1117:     <div class="c23">
 1118:       <img src="foo.gif">
 1119:     </div>
 1120:     <p><i>Figure 11-2: <a name="77004"></a></i> <i>Locale's
 1121:     placement in typical chrome layout</i></p>
 1122:     <p>The folder that is registered is the language folder, which
 1123:     is what has to be changed on an install. Thus, the URL
 1124:     <i>chrome://package/locale</i> actually points to
 1125:     <i>package/locale/en-US</i> or whichever language is turned on
 1126:     at the time. The language folder may in turn include subfolders
 1127:     that contain logical units for your application.</p>
 1128:     <h3><a name="77062"></a> Interaction with the Chrome
 1129:     Registry</h3>
 1130:     <p>As pointed <!--INDEX localization:chrome registry --> 
 1131:     <!--INDEX chrome:localization:registry --> out in <a href=
 1132:     "ch06.html#77063">Chapter 6</a>, your packages directories need
 1133:     to be registered as chrome with the chrome registry. The first
 1134:     step is to ensure that the entry for your package component is
 1135:     in the file <i>chrome.rdf</i> in the root chrome directory.</p>
 1136:     <p>A <i>resource:/</i> URL points to the folder for your files
 1137:     to be picked up and recognized by the chrome mechanism and
 1138:     accessed via <i>chrome://</i> URLs in your application code.
 1139:     The locale is no exception.</p>
 1140: <pre>
 1141: &lt;RDF:Description about="urn:mozilla:locale:en-US:xfly"
 1142: c:baseURL="resource:/chrome/xfly/locale/en-US/"&gt;
 1143: c:localeVersion="0.1.0.0"
 1144: &lt;c:package resource="urn:mozilla:package:xfly"/&gt;
 1145: &lt;/RDF:Description&gt;
 1146: </pre>
 1147:     <p>A built-in versioning system in the chrome registry uses
 1148:     <i>c:localeVersion</i> descriptor, if you plan on distributing
 1149:     multiple language packs for your application. Other descriptors
 1150:     are available if you choose to use them: display name
 1151:     (<i>c:displayName</i>), internal name (<i>c:name</i>), location
 1152:     type (<i>c:locType</i>), and author (<i>c:author</i>).</p>
 1153:     <h3><a name="77063"></a> Distribution</h3>
 1154:     <p>Language d <!--INDEX localization:distrubution issues --> 
 1155:     <!--INDEX distribution:localization issues --> istribution may
 1156:     not be an issue for you. If, for example, your application were
 1157:     only going to be localized into a finite number of languages,
 1158:     bundling each of them up with the main installer would be most
 1159:     convenient. If, however, the need for new language versions
 1160:     arises at various intervals in the release process, you need to
 1161:     find a way to make them available and install them on top of an
 1162:     existing installation.</p>
 1163:     <p>For example, as more people from various locations in the
 1164:     world are becoming aware of the Mozilla project, they want to
 1165:     customize it into their own language. Here are the steps that
 1166:     you need to take to set up your version.</p>
 1167:     <ol>
 1168:       <li>Register as a contributor and set up the resources that
 1169:       you need, if any (web page, mailing list). This will ensure
 1170:       that you are added to the project page on the mozilla.org
 1171:       site.</li>
 1172:       <li>Get a copy of Mozilla to test either via a binary
 1173:       distribution or by downloading and building your own source
 1174:       (see <a href="appa.html#90096">Appendix A</a> for more
 1175:       information).</li>
 1176:       <li>Translate the files.</li>
 1177:       <li>Package your new files for distribution.</li>
 1178:       <li>Test and submit your work.</li>
 1179:     </ol>
 1180:     <p>Step 4, the packaging of the new language pack, is discussed
 1181:     next. Mozilla's Cross-Platform Install (XPI) is the ideal
 1182:     candidate for achieving this packaging. This method is
 1183:     discussed extensively in <a href="ch06.html#77063">Chapter
 1184:     6</a>. This distribution method provides great flexibility and
 1185:     has the benefit of being native to Mozilla, thus bypassing the
 1186:     search for external install technologies for your
 1187:     application.</p>
 1188:     <h4><a name="77064"></a> The anatomy of an install script</h4>
 1189:     <p><a href="#77024">Example 11-9</a> presents 
 1190:     <!--INDEX localization:install scripts --> 
 1191:     <!--INDEX installation:localization and install scripts --> 
 1192:     <!--INDEX scripts:install, localization and --> a script that
 1193:     is based on the Mozilla process that distributes localized
 1194:     language packs. It presumes that there is a single JAR file for
 1195:     the language that is installed and registered in the Mozilla
 1196:     binary's chrome root.</p>
 1197:     <p>The XPI archive consists of the JAR file in a
 1198:     <i>bin/chrome</i> directory and the <i>install.js</i> file,
 1199:     together in a compressed archive with an <i>.xpi</i> extension.
 1200:     Simply clicking on a web page link to this file invokes the
 1201:     Mozilla software installation service and installs your
 1202:     language. For convenience, inline comments in <a href=
 1203:     "#77024">Example 11-9</a> explain what is happening.</p>
 1204:     <p><i>Example 11-9: <a name="77024"></a></i> <i>The locale XPI
 1205:     install script, install.js</i></p>
 1206: <pre>
 1207:  function verifyDiskSpace(dirPath, spaceRequired)
 1208:  {
 1209:    var spaceAvailable;
 1210:    spaceAvailable = fileGetDiskSpaceAvailable(dirPath);
 1211:    spaceAvailable = parseInt(spaceAvailable / 1024);
 1212:    if(spaceAvailable &lt; spaceRequired)
 1213:    {
 1214:      logComment("Insufficient disk space: " + dirPath);
 1215:      logComment("  required : " + spaceRequired + " K");
 1216:      logComment("  available: " + spaceAvailable + " K");
 1217:      return(false);
 1218:    }
 1219:    return(true);
 1220:  }
 1221:  // platform detection
 1222:  function getPlatform( ) {
 1223:    var platformStr;
 1224:    var platformNode;
 1225:    if('platform' in Install) {
 1226:      platformStr = new String(Install.platform);
 1227:      if (!platformStr.search(/^Macintosh/))
 1228:        platformNode = 'mac';
 1229:      else if (!platformStr.search(/^Win/))
 1230:        platformNode = 'win';
 1231:      else
 1232:        platformNode = 'unix';
 1233:    }
 1234:    else {
 1235:      var fOSMac  = getFolder("Mac System");
 1236:      var fOSWin  = getFolder("Win System");
 1237:      logComment("fOSMac: "  + fOSMac);
 1238:      logComment("fOSWin: "  + fOSWin);
 1239:      if(fOSMac != null)
 1240:        platformNode = 'mac';
 1241:      else if(fOSWin != null)
 1242:        platformNode = 'win';
 1243:      else
 1244:        platformNode = 'unix';
 1245:    }
 1246:    return platformNode;
 1247:  }
 1248:  // Size in KB of JAR file
 1249:  var srDest = 500;
 1250:  var err;
 1251:  var fProgram;
 1252:  var platformNode;
 1253:  platformNode = getPlatform( );
 1254:  // --- LOCALIZATION NOTE: translate only these ---
 1255:  // These fields are changeable in this generic script
 1256:  var prettyName = "Irish";
 1257:  var langcode = "ie";
 1258:  var regioncode = "GA";
 1259:  var chromeNode = langcode + "-" + regioncode;
 1260:  // --- END LOCALIZABLE RESOURCES ---
 1261:  // build the paths and file names for registry and chrome:// url access
 1262:  var regName    = "locales/mozilla/" + chromeNode;
 1263:  var chromeName = chromeNode + ".jar";
 1264:  var regionFile = regioncode + ".jar";
 1265:  var platformName = langcode + "-" + platformNode + ".jar";
 1266:  var localeName = "locale/" + chromeNode + "/";
 1267:  // Start the installation
 1268:  err = initInstall(prettyName, regName, "0.1.0.0");
 1269:  logComment("initInstall: " + err);
 1270:  fProgram = getFolder("Program");
 1271:  logComment("fProgram: " + fProgram);
 1272:  // Check disk space using utility function at the start of the script
 1273:  if (verifyDiskSpace(fProgram, srDest))
 1274:  {
 1275:    err = addDirectory("",
 1276:    "bin",
 1277:    fProgram,
 1278:    "");
 1279:    logComment("addDirectory( ) returned: " + err);
 1280:    &lt;/td&gt;// register chrome
 1281:    var cf = getFolder(fProgram, "chrome/"+chromeName);
 1282:    var pf = getFolder(fProgram, "chrome/"+platformName);
 1283:    var rf = getFolder(fProgram, "chrome/"+regionFile);
 1284:    var chromeType = LOCALE | DELAYED_CHROME;
 1285:    registerChrome(chromeType, cf, localeName + "global/");
 1286:    registerChrome(chromeType, cf, localeName + "communicator/");
 1287:    registerChrome(chromeType, cf, localeName + "content-packs/");
 1288:    registerChrome(chromeType, cf, localeName + "cookie/");
 1289:    registerChrome(chromeType, cf, localeName + "editor/");
 1290:    registerChrome(chromeType, cf, localeName + "forms/");
 1291:    registerChrome(chromeType, cf, localeName + "help/");
 1292:    registerChrome(chromeType, cf, localeName + "messenger/");
 1293:    registerChrome(chromeType, cf, localeName + "messenger-smime/");
 1294:    registerChrome(chromeType, cf, localeName + "mozldap/");
 1295:    registerChrome(chromeType, cf, localeName + "navigator/");
 1296:    registerChrome(chromeType, cf, localeName + "necko/");
 1297:    registerChrome(chromeType, cf, localeName + "pipnss/");
 1298:    registerChrome(chromeType, cf, localeName + "pippki/");
 1299:    registerChrome(chromeType, cf, localeName + "wallet/");
 1300:    registerChrome(chromeType, pf, localeName + "global-platform/");
 1301:    registerChrome(chromeType, pf, localeName + "communicator-platform/");
 1302:    registerChrome(chromeType, pf, localeName + "navigator-platform/");
 1303:    if (platformNode == "win") {
 1304:      registerChrome(chromeType, pf, localeName + "messenger-mapi/");
 1305:    }
 1306:    registerChrome(chromeType, rf, regionName + "global-region/");
 1307:    registerChrome(chromeType, rf, regionName + "communicator-region/");
 1308:    registerChrome(chromeType, rf, regionName + "editor-region/");
 1309:    registerChrome(chromeType, rf, regionName + "messenger-region/");
 1310:    registerChrome(chromeType, rf, regionName + "navigator-region/");
 1311:    if (err == SUCCESS)
 1312:    {
 1313:      &lt;/td&gt;// complete the installation
 1314:      err = performInstall( );
 1315:      logComment("performInstall( ) returned: " + err);
 1316:    }
 1317:    else
 1318:    {
 1319:      &lt;/td&gt;// cancel the installation
 1320:      cancelInstall(err);
 1321:      logComment("cancelInstall due to error: " + err);
 1322:    }
 1323:  }
 1324:  else
 1325:  {
 1326:    &lt;/td&gt;// if we enter this section,
 1327:    // there is not enough disk space for installation
 1328:    cancelInstall(INSUFFICIENT_DISK_SPACE);
 1329:  }
 1330: </pre>
 1331:     <p>By changing some values of the changeable fields, you can
 1332:     tailor this script to handle the install in any directory in
 1333:     the chrome (<i>cf</i>) that you want and register the chrome
 1334:     URL (<i>localeName</i>) for use. The rest is handled by the
 1335:     built-in functionality in XPI provided by such functions as
 1336:     <tt>initInstall</tt> and <tt>performInstall</tt>.</p>
 1337:     <h4><a name="77065"></a> Switching languages</h4>
 1338:     <p>The mechanism <!--INDEX localization:switching languages -->
 1339:     for switching languages can take many forms. Mozilla switches
 1340:     languages by updating an RDF datasource when a language pack is
 1341:     installed. The UI for switching languages in Mozilla is in the
 1342:     main Preferences (Edit &gt; Preferences). Within the
 1343:     preferences area, the language/content panel (Appearance &gt;
 1344:     Languages/Content) interacts with the chrome registry when
 1345:     loaded, reading in the installed language packs and populating
 1346:     a selectable list with the available language identifier.
 1347:     Selecting one language and restarting Mozilla changes the
 1348:     interface for the user. <a href="#77026">Example 11-10</a> is a
 1349:     simple script for switching locales. Example 11-10<a name=
 1350:     "77026"></a> <i>Locale-switching script</i></p>
 1351: <pre>
 1352:  function switchLocale(langcode)
 1353:  {
 1354:    try {
 1355:      var chromeRegistry = Components.classes&lt;/td&gt;["@mozilla.org/chrome/chrome-registry;1"].getService(Components.interfaces.nsIChromeRegistry);
 1356:      chromeRegistry.selectLocale(langcode, true);
 1357:      var observerService = Components.classes&lt;/td&gt;["
 1358:          @mozilla.org/observer-service;1"].
 1359:          getService(Components.interfaces.nsIObserverService);
 1360:      observerService.notifyObservers(null, "locale-selected", null);
 1361:      var prefUtilBundle = srGetStrBundle
 1362:          ("chrome://communicator/locale/pref/prefutilities.properties");
 1363:      var brandBundle = srGetStrBundle
 1364:          ("chrome://global/locale/brand.properties");
 1365:      var alertText = prefUtilBundle.GetStringFromName("languageAlert");
 1366:      var titleText = prefUtilBundle.GetStringFromName("languageTitle");
 1367:      alertText = alertText.replace(/%brand%/g,
 1368:          brandBundle.GetStringFromName("brandShortName"));
 1369:      var promptService = Components.classes&lt;/td&gt;["
 1370:          @mozilla.org/embedcomp/prompt-service;1"].getService( );
 1371:      promptService = promptService.QueryInterface
 1372:          (Components.interfaces.nsIPromptService)
 1373:      promptService.alert(window, titleText, alertText);
 1374:    }
 1375:    catch(e) {
 1376:      return false;
 1377:    }
 1378:    return true;
 1379:  }
 1380: </pre>
 1381:     <p>The language code is passed in as a parameter to the
 1382:     <tt>switchLocale</tt> JavaScript method in <a href=
 1383:     "#77026">Example 11-10</a>. The locale is set via the
 1384:     <tt>nsIChromeRegistry</tt> component, which uses a method named
 1385:     <tt>selectLocale</tt>. This locale selection is located in the
 1386:     first few lines, and the rest of the code prepares and shows a
 1387:     prompt to the user. This prompt reminds you to restart Mozilla
 1388:     to ensure that the new locale takes effect.</p>
 1389:     <h2><a name="77066"></a> Localization Issues</h2>
 1390:     <p>This section aims to dig a little deeper into the issues of
 1391:     UI aesthetics and principles, in order to provide some
 1392:     background into the underlying encoding of documents in the
 1393:     XPFE framework. The main portion is taken up by a discussion of
 1394:     Unicode. There is some background to what Unicode is, how
 1395:     Mozilla uses it, and some practical conversion utilities to
 1396:     ensure that your files are in the correct encoding.</p>
 1397:     <h3><a name="77067"></a> XPFE and Unicode</h3>
 1398:     <p>Unicode is <!--INDEX localization:Unicode --> 
 1399:     <!--INDEX Unicode:overview --> a broad topic and we cannot hope
 1400:     to give you anywhere near a full understanding of what it is.
 1401:     However, a brief introduction will highlight its importance in
 1402:     the software world and show how it is used as one of the
 1403:     internationalization cornerstones in the Mozilla project.</p>
 1404:     <blockquote>
 1405:       <div class="c24">
 1406:         NOTE
 1407:       </div>
 1408:       <p>For more in-depth information, refer to the book <i>The
 1409:       Unicode Standard, Version 3.0</i> by the Unicode Consortium,
 1410:       published by Addison Wesley Longman. Another useful reference
 1411:       is <i>Unicode: A Primer</i> by Tony Graham, published by
 1412:       M&amp;T Books.</p>
 1413:     </blockquote>
 1414:     <p>Unicode is an encoding system used to represent every
 1415:     character with a unique number. It is a standard that came
 1416:     about when multiple encoding systems were merged. It became
 1417:     clear that keeping separate systems was hindering global
 1418:     communication, and applications were not able to exchange
 1419:     information with one another successfully. Now all major
 1420:     systems and applications are standardizing on Unicode. Most
 1421:     major operating systems, such as Windows, AIX, Solaris, and Mac
 1422:     OS, have already adopted it. The latest browsers, including
 1423:     Mozilla, support it. This quote from the Unicode Consortium
 1424:     (<i><a href=
 1425:     "http://www.unicode.org/unicode/standard/WhatIsUnicode.html">http://www.unicode.org/unicode/standard/WhatIsUnicode.html</a></i>)
 1426:     sums it up the best:</p>
 1427:     <blockquote>
 1428:       Unicode enables a single software significant cost savings
 1429:       over the use of legacy character sets. Unicode enables a
 1430:       single software product or a single web site to be targeted
 1431:       across multiple platforms, languages and countries without
 1432:       re-engineering. It allows data to be transported through many
 1433:       different systems without corruption.
 1434:     </blockquote>
 1435:     <p>There are seven character-encoding schemes in Unicode:
 1436:     UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and
 1437:     UTF-32LE. UTF is an abbreviation for Unicode Transformation
 1438:     Format. The size of the character's internal representation can
 1439:     range from 8 bits (UTF-8) to 32 bits (UTF-32).</p>
 1440:     <p>One of Unicode's core principles is that it be able to
 1441:     handle any character set and that clients supporting it provide
 1442:     the tools necessary to convert. This conversation can be from
 1443:     Unicode to native character sets and vice versa. The number of
 1444:     native character sets is extensive and ranges from Central
 1445:     European (ISO-8859-2) to Thai (TIS-620).</p>
 1446:     <p>The default encoding of XUL, XML, and RDF documents in
 1447:     Mozilla is UTF-8. If no encoding is specified in the text
 1448:     declaration, this is the encoding that is used. In the Mozilla
 1449:     tree, you will usually see no encoding specified in this
 1450:     instance and UTF-8 is the default. To use a different encoding,
 1451:     you need to change the XML text declaration at the top of your
 1452:     file. To change your encoding to Central European, include:</p>
 1453: <pre>
 1454: &lt;?xml version="1.0" encoding="ISO-8859-2" ?&gt;
 1455: </pre>
 1456:     <h3><a name="77068"></a> Language Quirks</h3>
 1457:     <p>The size and 
 1458:     <!--INDEX localization:language display issues --> proportion
 1459:     of your windows can come into play when you know your
 1460:     application will be localized into more than one language. In
 1461:     some languages, it takes more words or characters, hence more
 1462:     physical space, to bring meaning to some text. This is
 1463:     especially the case in widgets that contain more text, such as
 1464:     when you want to provide usage guidelines in a panel.</p>
 1465:     <p>One solution that Mozilla uses in at least one place is to
 1466:     make the actual size of the window or make the widget into a
 1467:     localizable entity.</p>
 1468: <pre>
 1469: &lt;window style="&amp;window.size;" ...&gt;
 1470: &lt;!ENTITY  window.size             "width: 40em; height: 40em;"&gt;
 1471: </pre>
 1472:     <p>The translator or developer can anticipate the size based on
 1473:     the number of words or preview their changes in the displayed
 1474:     UI. If there is an overflow, they can overflow or do the
 1475:     reverse in the case of empty space.</p>
 1476:     <p>As you begin to localize your application, especially if it
 1477:     is a web-related application, you will encounter words and
 1478:     phrases that have universal meaning and may not require
 1479:     translation. If you translate the whole Mozilla application,
 1480:     for example, you'll find that some words or phrases remain
 1481:     untouched. These items include terms that are used for
 1482:     branding, or universal web browsing terms, such as Bookmarks,
 1483:     Tasks, and Tools. In some instances, the choice to translate
 1484:     some of these terms is purely subjective.</p>
 1485:     <hr>
 1486:     <br>
 1487:     <br>
 1488:     File a <a href=
 1489:     "http://mozdev.org/bugs/enter_bug.cgi?product=books">Bug</a>
 1490:     for chapter 11. 
 1491:     <?php $hide_text_control=1; $post_to_list=NO; $author='reviewers@mozdev.org'; // require(NOTES); ?>

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>