Mozilla 言語パック内部構造

ニュースグループでの議論 / メーリングリスト
Mozilla 地域化プロジェクトスタッフ

MLP [地域化プロジェクトホーム] | [地域化資料] | [言語パック技術]

はじめに

Mozilla は XPI パッケージを使って自動的に追加コンポーネントをインストールすることができます。

典型的な例では、Mozilla の言語パックは一つの XPI アーカイブで構成されています。 これは、PKZip 互換のアーカイブで、新しい言語のためのリソースを含み、Mozilla の特定のリリースのユーザインタフェースを対象としていて、インストール・スクリプトを含んでいます。 このようにして、ユーザはクリック一つで言語を追加することができます。

それぞれのユーザおよびユーザ・プロファイルごとに、Mozilla のアプリケーションのユーザ・インタフェースの言語は、インストールされている中から好きな物を動的に選択することができます。

目次

Mozilla の地域化可能なリソース

Mozilla ユーザ・インタフェースはレイアウトエンジンが実行時に描画するのに使ういくつかの XML ページで成り立っています。 このことはユーザ・インタフェース・リソースがただのテキストファイルと一般的な Web フォーマットで保存された画像で構成されていることを意味します。 ユーザ・インタフェースの一部である地域化可能リソースはこの規則の例外ではありません。

忘れてはならないこととして、すべてのテキストエディタがいかなるテキストファイルを編集するのにも十分適しているというわけではないことがあります。 ここでのキーワードはテキストのエンコーディングです。 エンコーディングはアプリケーションが文字や記号を電子的文書に変換する方法です。 すべてのプレーン・テキストが同じエンコーディングであるわけではありません。 同じプログラム(例えば Windows のメモ帳)であっても、別の言語を使うマシン(例えばスロバキア語や中国語など)であれば、同じ記号を異なった方法で保存する場合があり、また種類によってスクリプトや記号を読み込み/受け入れできない場合もあります。 操作する文字列テキストを Mozilla が理解できるエンコーディングに"エンコード"できるツールが必要でしょう。

ユーザ・インタフェースのファイルは Web 文書として解析される場合が非常に多いでしょう。 Web 文書がアクセス拒否されなくてはならないというセキュリティのための機能へのアクセスを持つという点において異なっています。そのため、ユーザ・インタフェースのリソースはインストールされ、登録される必要があります。 すべてのユーザ・インタフェース素材は、Web ページが HTTP プロトコルを使って他のドキュメントを指すのと似た方法で、"chrome" プロトコルを通してお互いのファイルを参照するよう動作します。

便宜上、Mozilla アプリケーション・スィートを構成するたくさんのユーザ・インタフェースファイルは、バイナリの chrome/ フォルダ以下の(Java アーカイブの .jar ファイルとの共通点は少ないのですが).jar 拡張子をもつ少数の zip 圧縮ファイルの中に含まれています。 これらの集約ファイルはたいてい、多少は地域化可能素材を整えてあります。地域化可能素材は存在するならば locale/ フォルダの下に集められています。

chrome/ フォルダの外に置かれている追加の地域化可能なリソースはデフォルトのユーザ・プロファイルとその他の任意リソース(検索プラグインスペルチェッカー辞書など)を含んでいます。 この素材は登録の必要はありません。

典型的な場面を考えてみます。 英語 - Mozilla に同梱された合衆国(en-US)ロケールリソース。 これらは、たいてい地域化作業者が作業者の言語のバージョンの Mozilla を得るために作業すべきファイルです。

chrome/ en-US.jar !locale/en-US/component/*
各々のコンポーネントは、chrome://component/locale/* 配下に登録されています。
en-US.jar アーカイブには、地域化対象部分として登録されていて Mozilla アプリケーション(コンポーネント別)のユーザ・インタフェース全体で使われるものがまとめて収められています。

chrome/ en-mac.jar !locale/en-US/component/* (プラットフォームによっては en-win.jaren-unix.jar)
各々のコンポーネントは、chrome://component/locale/* 配下に登録されています。
Mozilla のユーザ・インタフェースのうちプラットフォーム依存のものだけが含まれています。 これらのファイルすべてには、完全に同じコンポーネントが含まれています。 したがって、この3ファイルのうち1つのコンポーネントだけが有効なものとして登録されます。

chrome/ US.jar !locale/US/component/*
各々のコンポーネントは、chrome://component/locale/* 配下に登録されています。
いわゆる地域別コンテンツが収められています。 これらは、ユーザ・インタフェースをあちこちで使われる外部リソースへの地域特定のポインタです。 この素材はその他の地域化対象リソースとは異なったロケールコードを使います。 そのため、このコンテンツだけ独立して選択できるようになっています。

defaults/profile/US/*
プロファイルのテンプレートです。 これらのファイルは次のようないくつかのファイルについてのユーザプロフィルのテンプレートを含んでいます。
  • ブックマーク、デフォルトのウィンドウの形・位置、MIME タイプの結びつけ、デフォルトのサイドバーパネル、デフォルトの検索プラグイン
これらのファイルは地域コンテンツの一部ですが、新しいユーザプロファイルを作成する時にだけ使われます。 フォルダ名は地域素材のために使われているロケールコードと一致しなくてはなりません。

searchplugins/*, components/myspell/*, ...
追加の要素です。 これらの任意ファイルは、Mycroft 検索プラグインから、スペルチェッカー辞書、アプリケーションを全面的にユーザの習慣に順応させるための適切な配布がされるかもしれないその他の地域化可能・ロケール依存コンポーネントに分類されます。

地域化可能テキストファイル

上述の通り、すべてのテキストエディタが Mozilla のテキストリソースを編集するのに適しているわけではありません。 このアプリケーションは最初から万国の利用者・開発者を考慮して設計されたため、多くの有名なテキストエディタで今も使われている旧来の 8 ビットエンコーディングは、すぐに Mozilla のためには不十分であることが明らかになりました。

中心となる地域化可能なリソースは以下のものから構成されています:

  • DTD files = XML 定義テーブル。エンコーディング: UTF-8
  • properties files = Java/JS properties 定義。エンコーディング: Escaped Unicode (\uXXXX)

正しくこれらのファイルを手動編集するためには、これらのエンコーディングを処理可能なテキストエディタが必要となるでしょう。 このようにして、Mozilla はUnicode コンソーシアムで定義された文字・記号の全体を使うことができます。

Mozilla Translator のようなツールは、ユーザに意識させることなくこれらの込み入った部分を扱うことができます。

dtdproperties 両方のテキストファイルには名前づけられた文字列の集合が入っています。 前者は XML 文書の規則を、後者は JavaScript の慣習を遵守しなくてはなりません。 この規則・慣習はコメント、引用、使うことができる文字を決定づけます。

これらのファイルを直接編集しようとするとき、心にとめておく必要のある一般的なルールを以下のテーブルに一覧します:

   dtd
文字列形式:
<!ENTITY string_name "Text Text">
許されない文字:
&
<
"
%
代替文字:
&amp;
&lt;
&quot;
&#037;
その他の有用な事前に定義された実体:
>&gt;
'&apos;
&十進数; 形式でその他すべての Unicode 文字
一行/複数行コメント:  <!-- テキストをこの部分に -->
   properties
文字列形式:
string_name = Text Text
許されない文字:
改行 (文字列の終わり)
バックスラッシュ "\"
ダブルクォートとシングルクォート " '
代替文字:
改行文字としての \n
バックスラッシュとしての \\
\"\'
その他の有用なエスケープされた文字:
\bバックスペース
\f改ページ
\rキャリッジリターン(CR)
\tタブ

\uXXXX 形式でその他のすべての Unicode 文字: XXXX は 4桁の 16進数の Unicode 番号

行の最後の文字としての「継続のバックスラッシュ "\"」は次の行に文字列が続くことを示します。

行全体コメント(行の最初の文字から):# テキスト テキスト
行の最後のコメント: // テキスト テキスト
複数行コメント: /* テキストが続く */

Mozilla Chrome の紹介

ここでの最終目標は、自分にあった Mozilla に登録された新しい言語リソースを作ることです。 ひとたび登録すれば、ユーザはアプリケーション全体で、新しい言語リソースを選択し、現在使用するものとして有効化することができます。 これは設定で言語を選択し( (Edit | Preferences | Appearance | Language/Contents)訳注:編集 | 設定 | 表示 | 言語/コンテンツ)、再起動するということです。

言語リソースの登録は、Mozilla のレジストリの中の一覧に追加するということです。 Mozilla レジストリはいくつのパッケージがインストールされたかの軌跡を残しています。 どの Mozilla コンポーネント(アプリケーション)もたいてい三つの異なるパッケージにモジュール化されています:

  • コンテント: XML と JavaScript が混在するファイルで、特定のアプリケーション(例:メール、ナビゲータ、コンポーザ、ブックマーク管理、等)のためのユーザ・インタフェースのロジックを含んでいます。 XML ファイルは XUL と呼ばれる特定のタグのセットを使ってそれぞれのアプリケーションのウィンドウを記述します。 それらは実行時に DOM プロパティを通して JavaScript を使って操作できます。
  • スキン: XLSCSS 、Web 用画像ファイルが集まったもので、ユーザインタフェースのある部分の最終的な見栄えを定義しており、アプリケーションの内容によって記述されます。
  • ロケール: 地域化可能ソースで、内容はユーザと対話するのに使われます。

このモジュール化によって、あるアプリケーション内容にとって複数の外観(スキン、テーマという名称で知られている)や言語(ロケール)を持つ機能が得られました。それも、ただアプリケーションの XUL ファイルによって指し示されるファイルを切り替えるというだけでです。

現在選択されているロケールとスキンという考え方により、ロケールとスキンの切り替えが可能となっています。 もちろん前者に焦点を置いていますが、後者にもまったく同じ思想が当てはまります。

どのロケールパッケージも主に二つのプロパティによって識別できます。構成するコンテント(アプリケーション)コンポーネントと所有するロケール(言語-地域 code)です。

ひとたび、Mozilla のユーザインタフェースの言語を選択すると、ロケールコードの対応するロケールパッケージは、chrome:// プロトコルを通じてデフォルトロケールリソースとして配置されます。 アプリケーションファイルは、実際のところ、ユーザのストレージデバイスへの直接のポインタを持っていません。 その代わりに、現在のアプリケーションの chrome:// 空間の locale/ を通してアクセスします。 そして、現在選択されているデフォルトロケールは、アプリケーションの locale/ フォルダの中の対応するロケールリソースと Mozilla によって対応がとられます。

この考え方を例を使ってより明確にしましょう。
コンポーネントが "navigator" という名前のアプリケーションが、navigator.xul という XML ファイルに記述された新しいウィンドウを生成します。そこで Web 検索ボタンの中に文字列を表示させる必要が出てきます。

アプリケーションは、navigator.xul 文書をウィンドウを生成するために Mozilla エンジンに通します。 "navigator" はアプリケーションの中に、対応するコンテント、スキン、ロケールパッケージとともに登録されています。 navigator コンポーネントには複数の異なったロケールパッケージを登録することもできるでしょう。それぞれのリソースは他の言語のリソースのコピーで、ロケールコードで識別されます。その中で、いっときに一つのロケールパッケージだけを選択しなくてはなりません。

アプリケーションは現在どのロケールが選択されているかを知る必要はありません。 すべてのリソースは chrome プロトコルを通してアクセスされるため、選択されたロケールのリソースだけが navigator コンポーネントの locale/ chrome アドレスのもとにマッピングされます。現在選択されているリソースは navigator からアクセスできる当該アプリケーションリソースとなるのです(それが唯一アクセス可能なものとして)。

アプリケーションは新しいウィンドウを記述するファイルのため以下の URI を通ります:

chrome://navigator/content/navigator.xul
その上で、 navigator.xul が内部の文字列を参照します
chrome://navigator/locale/navigator.dtd
ボタンに表示するためのテキストを読み出すために参照します。アプリケーションはそして、どの言語であれ変更することなく表示します。 関連するファイルが選択されたロケールのリソースからアプリケーションまで通過するのを取りはからうのが基底となる chrome です。

地域化可能ソースを登録する方法

Mozilla の地域化可能リソースのうちユーザインタフェース部分は、選択して使用するためには登録される必要があります。

Mozilla にリソースを登録するためには以下のうちのいずれかが必要です:

  • XPI パッケージ内部の JavaScript インストーラでリソース同梱 XPI パッケージの中の JavaScript インストーラスクリプトをリソースの固まりと一緒に配布されたコンテンツに登録しましょう。 そのスクリプトは以下の状況でもうまく処理できなくてはならないでしょう:
    • プラットフォーム依存素材の条件付き登録
    • 複数ユーザ環境で、アプリケーション大と単独ユーザプロファイルのいずれかのインストール
    • エラー状況処理
  • 新しいパッケージを chrome/installed-chrome.txt ファイルを新しいパッケージとしてリストに入れてください。これにより、root(管理者)ユーザが次回に Mozilla を再起動する際にパッケージを登録できるようになります。

登録可能パッケージの構造

Mozilla に登録できる最小単位はパッケージです。

パッケージを、そのコンポーネント名称のもとに登録された Mozilla アプリケーションが所有するファイルのグループであると考えることができます。 先に触れたように、パッケージは主に三つの部品、コンテント、スキン、ロケールから成ります。 ではロケールパッケージの作成に注目していきます。

あるコンポーネントがある程度地域化可能に作られていれば、地域化可能リソースは同じコンポーネント名称を持つロケールパッケージの中に外部化されています。 望む限りたくさんのロケールパッケージをロケールコードで識別して同じコンポーネント名で登録できます。

パッケージの基本的コンポーネントは:

  • パッケージそのものによって含まれたファイルで、一つのフォルダか .jar アーカイブの一つのフォルダに集められています(jar について、すべての点において典型的な zip アーカイブと考えることができます)。
  • contents.rdf XML ファイル。このファイルには登録された後にどこが挿入場所になるのか加え、作者名や対象となる Mozilla のバージョンなどパッケージ自身の情報が記述されています。

新しいロケールパッケージを作る

では、"editor" のための簡体字中国語パッケージ(ロケールコードは "zh-CN")を作ると仮定しよう。 対象の Mozilla のバージョン は 1.2とします。 以下の手順に従うことになるでしょう:

  • 一般的な zip 解凍ユーティリティで en-US.jar ファイルの中の locale/en-US/editor/ から英語リソースを抽出する。
  • .dtd.properties その他のファイルを編集して、元となる英語のファイルを中国語に地域化します。
  • パッケージの情報に従って、contents.rdf を編集し、地域化されたリソースファイルと同じフォルダの中に置きます。
  • 圧縮された jar ファイルに、任意にパッケージをアーカイブすることもできます。

これから修正する contents.rdf をそうするべきかみてみましょう:

editor コンポーネントの zh-CN ロケールパッケージのための contents.rdf
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:chrome="http://www.mozilla.org/rdf/chrome#" >

<!-- まずは "locale" のルートに "zh-CN" カテゴリを作成します   -->
  <RDF:Seq about="urn:mozilla:locale:root" >
    <RDF:li resource="urn:mozilla:locale:zh-CN" />
  </RDF:Seq>

<!-- コンテンツのためのグローバルなバージョンを代入して、簡体字中国語に関する情報を追加・更新します -->
  <RDF:Description about="urn:mozilla:locale:zh-CN"
       chrome:displayName="Chinese Simplified (zh-CN)"
       chrome:author="MLP Staff"
       chrome:name="zh-CN"
       chrome:previewURL="http://www.mozilla.org/previewimages/China.png"
       chrome:localeVersion="1.2" >

<!-- zh-CN ロケールの内部に、バージョン情報とともに "editor" パッケージを追加します -->
       <chrome:packages>
         <RDF:Seq about="urn:mozilla:locale:zh-CN:packages">
           <RDF:li resource="urn:mozilla:locale:zh-CN:editor"
                   chrome:localeVersion="1.2" />
         </RDF:Seq>
       </chrome:packages>

  </RDF:Description>

</RDF:RDF>

パッケージを登録する

パッケージ化が完了すれば、以下のセクションで触れる XPI パッケージを作って、成果物を Mozilla のフォルダにコピーしパッケージを登録できるようにする、あるいは chrome/ フォルダの中に置かれた installed-chrome.txt ファイルの中に一行加える事ができます。

上述の中国語 editor パッケージのための地域化されたファイルを、Mozilla chrome/ ディレクトリにある editorpackagetest と呼ばれるフォルダの中に置く場合、行は以下のようになるでしょう。
locale,install,url,resource:/chrome/editorpackagetest/

一度 Mozilla を再起動すると、登録されたパッケージの中に置いておいた情報を探すために、install.log の中(XPI インストールのためのものだけ)と chrome.rdf の中を見るて、登録が成功しているかどうか知ることができます。

Mozilla のレジストリに新しいロケールのノードを追加したばかりであれば(この例ではまだ簡体字中国語をインストールしたことがなければ)、設定 (Edit | Preferences | Appearance | Language/Contents) (訳注:JLP では 編集 | 設定 | 表示 | 言語/コンテンツ))の中に displayName プロパティが追加されているのが見られるでしょう。

また、contents.rdf ファイルのバージョン情報を正しく設定することを忘れないでください。でなければ、追加したリソースをユーザが選択しようとしても Mozilla は拒否してしまいます。

簡単な XPI 言語パックを作る

この章では、XPI アーカイブの形で自己インストール可能な言語パックの形で地域化作業結果の成果物を配布可能とする方法について説明しましょう。

自己インストール可能 XPI アーカイブはホストマシンの中の jar 圧縮ファイルの中にグループ化された地域化されたリソースをコピーし、それらを登録します。ここでは jar ファイルと XPI ファイル自体とインストール用スクリプトの準備方法について説明します。

JAR ファイルの中にリソースを梱包する

Mozilla の地域化されたリソースファイルから jar アーカイヴを作るのは簡単です。zip 互換ユーティリティでフォルダごとにまとめられたファイルを集まりを圧縮して、書庫ファイルの拡張子を .zip から .jar に変更すればよいのです。 必ずディレクトリ構造はインストール・スクリプトで使われる情報と一致しなくてはならないことに留意してください。

仮にイタリア語リソースの jar、it-IT.jar のために使うディレクトリ構造があるとします:
it-IT.jar contents.
/locale/it-IT/communicator/contentAreaCommands.dtd
                           contentAreaCommands.properties
                           contents.rdf
                           ...
                           /bookmarks/addBookmark.dtd
                                     /bm-props.dtd
                                     /...
                           /directory/...
                           /dom/...
                           /downloadmanager/...
                           /history/...
                           ...
/locale/it-IT/cookie/contents.rdf
                    /cookie.properties
                    /cookieAcceptDialog.dtd
                    ...
/locale/it-IT/editor/contents.rdf
                    /EdAdvancedEdit.dtd
                    /EdColorPicker.dtd
                    ...
/locale/it-IT/...

同じような方法で it-mac.jarit-unix.jarit-win.jarIT.jar を英語の相当物の内容を翻訳して用意することができます。

IT.jar アーカイヴに同梱された地域コンテンツは言語リソースとは違うロケールコードが必要となるだろうことを覚えておいてください。 この新しいロケールはこれらのパッケージの中で使われる contets.rdf ファイルの中の地域ロケールとして正しく印づけられる必要があります。 手短に言えば、これは localeType プロパティを追加することを意味します。

chrome:localeType="region"
上記は地域ロケールノードの中で、nameauthor などと並列なものです。

メモ: 地域ロケールコードの選び方は?
コードの文字を重複なく保つことが目的となります。 梱包した地域素材が単一の公用語を持つ国家を対象とするのであれば、ISO 国家コードで十分でしょう(例:"IT" はイタリアのために使われます)。 そうでなく、この素材が複数の共用語を持つ国家地域を対象としたり、知名度の低い言語を対象としたりするなら、reg-ll-NN 型のコードを選ぶ方がよいでしょう。 ll が国家の、NN が言語のISO コードです(例:reg-en-CAreg-fr-CA はそれぞれカナダにおける英語とフランス語の地域リソースとしてあり得るロケールコードです)。

インストール・スクリプトを用意する

これは実際に複雑な(といっても難しいというのとは違う)問題です。 とりあえず、実際のスクリプトを通して、どういう風に動作するのかを手短に検討してみましょう。

このインストール・スクリプトは、install.js と名前づけられた通常の JavaScript テキストファイルで、XPI パッケージのルートに置かれています。 このスクリプトに以下の動作を期待しています:

  1. インストール手順を初期化する。
  2. アプリケーションバイナリの設置先フォルダを取得する。
  3. 設置先フォルダに十分な空き容量があるかチェックする(フォルダが変われば違うストレージ単位に割り当てられているかもしれない)。
  4. 利用可能な容量が十分なら、XPI アーカイブの内容を設置先フォルダの中の bin/ フォルダに解凍する。
  5. コピーしようとするフォルダに書き込みアクセス権限がないなどの発生しうるエラー状態をチェックする。 もし、ファイルのコピーが成功しなければ、望むらくはファイルを置くだけの空きスペースのあるだろうユーザ・プロファイル・フォルダを取得して、再度試みることもできます。
  6. ファイルが適切なフォルダに置かれたら、パッケージごとに登録します。
  7. ユーザのホストプラットフォームのみに関係するファイルにも気を配ります。

では、スクリプトのコードを見てみましょう:

install.js XPI インストール・スクリプト。

  // この関数はディスクの空き容量を取得するために後で使います
    function verifyDiskSpace(dirPath, spaceRequired)
    {
      var spaceAvailable;
      // 与えられたパスのディスクの利用可能容量を得る
      spaceAvailable = fileGetDiskSpaceAvailable(dirPath);
      // 得られたディスク容量をキロバイトに変換する
      spaceAvailable = parseInt(spaceAvailable / 1024);
      // チェックを行う
      if(spaceAvailable < spaceRequired)
      {
        logComment("Insufficient disk space: " + dirPath);
        logComment("  required : " + spaceRequired + " kB");
        logComment("  available: " + spaceAvailable + " kB");
        return(false);
      }
      return(true);
    }

  // この関数はホストのプラットフォームを得るために後で使います
    function getPlatform()
    {
      var platformStr, platformNode;

      if('platform' in Install)
      {
        platformStr = new String(Install.platform);

        if (!platformStr.search(/^Macintosh/))
          platformNode = 'mac';
        else if (!platformStr.search(/^Win/))
          platformNode = 'win';
        else if (!platformStr.search(/^OS\/2/))
          platformNode = 'win';
        else
          platformNode = 'unix';
      }
      else
      {
        var fOSMac  = getFolder("Mac System");
        var fOSWin  = getFolder("Win System");
        logComment("fOSMac: "  + fOSMac);
        logComment("fOSWin: "  + fOSWin);
        if(fOSMac != null)
          platformNode = 'mac';
        else if(fOSWin != null)
          platformNode = 'win';
        else
          platformNode = 'unix';
      }
      return platformNode;
    }


  // *********** Main ***********
  var srDest, err, fProgram;
  
  // ----LOCALIZATION NOTE: この部分だけ翻訳します ------
  var prettyName       = "Simplified Chinese Language Pack";
  var regName          = "locales/mozilla/zh-CN";
  var localeName       = "zh-CN";
  var regionLocaleName = "CN";
  var PlatforNeutral   = "zh-CN.jar";
  var Regional         = "CN.jar";
  var macJar           = "zhCN-mac.jar";
  var unixJar          = "zhCN-nix.jar";
  var winJar           = "zhCN-win.jar";
  srDest               = 123; // 必要な容量をキロバイトで
  XPIserial            = "5.0.18.2003010521";
  // --- END CHANGABLE STUFF ---

1 err = initInstall(prettyName, regName, XPIserial); 
  logComment("initInstall: " + err);

2 fProgram = getFolder("Program");
  logComment("fProgram: " + fProgram);
  var chromeType = LOCALE|DELAYED_CHROME;

3 if(verifyDiskSpace(fProgram, srDest))
  {
    setPackageFolder(fProgram);
4   err = addDirectory("",
                       XPIserial, // インストールするバージョンの文字列
                       "bin",     // XPI を解凍するディレクトリ名
                       fProgram,  // 設置先フォルダ
                       "",        // fProgram に関連するサブディレクトリ
                       true);     // 上書きフラグ?Force Flag
    logComment("addDirectory() returned: " + err);

5   if (err!=SUCCESS)
    { // アプリケーション格納場所にユーザ横断的にインストールできなければ、プロファイルへのインストールを試みる
      resetError();
      fProgram = getFolder("Profile");
      logComment("fProgram: " + fProgram);
      chromeType = LOCALE|PROFILE_CHROME;
      if(verifyDiskSpace(fProgram, srDest))
      {
        setPackageFolder(fProgram);
        err = addDirectory("", XPIserial, "bin", fProgram, "", true);
        logComment("addDirectory() returned: " + err);
      }
      else err = INSUFFICIENT_DISK_SPACE;
    }

    if (err==SUCCESS)   // 何も問題なければ先に進む
    {
6     // 解凍したパッケージの登録

                           // zh-CN.jar
      lpath   = "locale/"+localeName+"/";
      jarPath = getFolder (fProgram, "chrome/"+PlatforNeutral);
      registerChrome(chromeType, jarPath, lpath+"autoconfig/" );
      registerChrome(chromeType, jarPath, lpath+"communicator/" );
      registerChrome(chromeType, jarPath, lpath+"contents-pack/" );
      registerChrome(chromeType, jarPath, lpath+"cookie/" );
      registerChrome(chromeType, jarPath, lpath+"editor/" );
          ...

7     switch (getPlatform()) {
       case "mac":         // zhCN-mac.jar
        logComment("Registering Mac packages");
        lpath   = "locale/"+localeName+"/";
        jarPath = getFolder (fProgram, "chrome/"+macJar);
        registerChrome(chromeType, jarPath, lpath+"communicator-platform/" );
        registerChrome(chromeType, jarPath, lpath+"global-platform/" );
        registerChrome(chromeType, jarPath, lpath+"navigator-platform/" );
          ...
        break;

       case "unix":         // zhCN-nix.jar
        logComment("Registering Unix packages");
        lpath   = "locale/"+localeName+"/";
        jarPath = getFolder (fProgram, "chrome/"+unixJar);
        registerChrome(chromeType, jarPath, lpath+"communicator-platform/" );
        registerChrome(chromeType, jarPath, lpath+"global-platform/" );
        registerChrome(chromeType, jarPath, lpath+"navigator-platform/" );
          ...
        break;

       case "win":         // zhCN-win.jar
        logComment("Registering Windows packages");
        lpath   = "locale/"+localeName+"/";
        jarPath = getFolder (fProgram, "chrome/"+winJar);
        registerChrome(chromeType, jarPath, lpath+"communicator-platform/" );
        registerChrome(chromeType, jarPath, lpath+"global-platform/" );
        registerChrome(chromeType, jarPath, lpath+"messenger-mapi/" );
        registerChrome(chromeType, jarPath, lpath+"navigator-platform/" );
          ...
      }

                           // CN.jar
      lpath   = "locale/"+regionLocaleName+"/";
      jarPath = getFolder (fProgram, "chrome/"+Regional);
      registerChrome(chromeType, jarPath, lpath+"communicator-region/" );
      registerChrome(chromeType, jarPath, lpath+"editor-region/" );
      registerChrome(chromeType, jarPath, lpath+"messenger-region/" );
          ...

      err = performInstall(); 
      logComment("performInstall() returned: " + err);
    }
    else cancelInstall(err);
  }
  else cancelInstall(INSUFFICIENT_DISK_SPACE);
  
  // ******** End Main **********

logComment() の呼び出しが、インストール進捗についての有用な情報を install.log に書き込めるということを覚えておいてください。

従来の JavaScript コードであることで、このインストーラ・スクリプトは、考えられるほとんどすべての場合に対応して操作や修正ができます。 アクセス可能な必須のインストール呼び出しは XPInstall プロジェクトページにより詳細に記述されています。

全部 XPI パッケージの中に置く

必要なものがすべて揃ったならば、配布の準備のために一つのファイルに詰め込むことができます。

今まで示してきた例では、以下に示すようなディレクトリ構造を持つ空のフォルダの中に成果物を置きます。 chrome/ フォルダの中は登録可能なもので、defaults/ フォルダの中のものは登録の必要がないことに注意してください。

そこで、最終的な zip アーカイブの中にすべてを圧縮します。 このファイルを正しく Mozilla に認識させるためには 一度 Navigator でローカルにこのファイルを開くだけで、(ユーザへのインストールプロンプトを Navigator に表示させ)Mozilla に正しく認識させるためには、ファイルの拡張子を .zip から .xpi に変更しなければなりません。
ChineseLanguagePack.xpi アーカイヴのディレクトリ構造
/install.js
/bin/chrome/zh-CN.jar
           /zhCN-mac.jar
           /zhCN-nix.jar
           /zhCN-win.jar
           /CN.jar
    /defaults/profile/CN/bookmarks.html
                        /localstore.rdf
                        /mimeTypes.rdf
                        /panels.rdf
                        /search.rdf
                        /chrome/userChrome-example.css
                               /userContent-example.css

最後の注意として、XPI パッケージはオンラインでのインストールにきわめて便利だということを付け加えておこう。 いくらかの JavaScript コード一つの伴った HTML ドキュメントは、一つの呼び出しでユーザに対してインストールに必要とされるコンポーネントを尋ねること、また複数の XPI パッケージの段階のダウンロードやインストールを始めることができます。

必要な JavaScript コードはこれだけです:

  xpi = {'Chinese Language Pack': 'http://www.invented.cn/ChineseLanguagePack.xpi',
         'Beautiful skin installation': 'http://foo.bar.com/beautifulSkin.xpi',
         ...    };
  InstallTrigger.install(xpi);

XPI ファイルに対するサーバの MIME Type は次の通りです:

application/x-xpinstall