ローカライズの対象となる文字列は実体参照で記述し、それが参照する実体を実体宣言 (.dtdファイル) で記述します。一方でスクリプトからは実体参照を使用できないため、プロパティ (.propertiesファイル) を使用します。
一方でアドオンの説明文をローカライズするには、インストール マニフェストのlocalizedプロパティで記述します。
文字列を記述する位置に、そのまま文字列を記述する代わりに実体参照の形式で値を記述します。
<button label="&label1;" />
実体参照の書式は「&ラベル名;
」の形式で、HTMLのそれと同一です。
実体参照が表す実体となる文字列を宣言することを、実体宣言と呼びます。それはテキストファイルに
<!ENTITY label1 "Foo"> <!ENTITY label2 "Bar"> ...
のように記述して、拡張子を.dtdとして保存します。これがDTD (Document Type Definition) ファイルとなります。
DTDファイルは対象とするロケールごとに、同じファイル名で1つずつ作成します。そして次のように配置します。
\---chrome +---content | \---locale +---en-US | foo.dtd | \---ja foo.dtd
またDTDファイルは、使用されるXULファイルごとに1つずつ作成することが推奨されていますが、1つのDTDファイルを複数のXULファイルから参照しても問題ありません。
対応するロケールには、必ずen-USを含めます。これは対応するロケールがない場合の既定値として使用されるためで、ロケールがない場合にこれがないと、[XML パースエラー]となりXULが正常に表示されません。なお必要なのは「en-US」であり、「en-GB」や「en-AU」では代替となりません。
作成したDTDファイルが読み込まれるように、Chrome Manifestのlocale命令でそのパスを指示します。
locale sample en-US chrome/locale/en-US/ locale sample ja chrome/locale/ja/
XULファイルのwindow要素などの直前で、適用するDTDファイルを外部DTDで指定します。
<!DOCTYPE window SYSTEM "chrome://myPackage/locale/foo.dtd"> <window ...
対象とする文書のルートがdialog要素ならば、
<!DOCTYPE dialog SYSTEM "chrome://myPackage/locale/foo.dtd"> <dialog ...
のように、ルート要素の指定を適宜変更します。なお他のアドオンのソースではDOCTYPEのルート要素を正しく指定していない例を多く見受けますが、特に問題とはならないようです。
たとえば、下表のように実体宣言がされているものとします。
言語 | DTDファイルでの記述 |
---|---|
英語 | <!ENTITY findLabel "Find"> |
日本語 | <!ENTITY findLabel "検索"> |
このときXULファイル内で、
<description value="&findLabel;" />
のように実体参照で記述されていると、その記述はユーザーの環境に応じて次のように変換されて解釈されます。
言語 | 変換後のXULファイル |
---|---|
英語 | <description value="Find" /> |
日本語 | <description value="検索" /> |
実体参照が記述されたXULファイルを開いたとき「XML パースエラー: 定義されていない実体が使用されています。」と表示されるならば、実体参照のラベル名を誤って指定しているか、DTDファイルの読み込みに失敗しています。
スクリプトからは前述の実体参照を利用できないため、代替としてプロパティを使用します。おのおのの値は
名前=値
の書式で、
str1=AAA str2=BBB
のように定義します。そしてそれをテキストファイルとして保存します。そのプロパティ ファイルはロケールごとに、DTDファイルと同様にlocaleフォルダに配置します。
\---chrome +---content | \---locale +---en-US | aaa.dtd | foo.properties | \---ja aaa.dtd foo.properties
対応するロケールには、必ずen-USを含めます。その理由や注意点はDTDと同様ですが、対応するロケールがない場合にはパースエラーではなく、NS_ERROR_UNEXPECTED例外が発生します。
たとえばプロパティ ファイルがfoo.propertiesというファイル名だとすると、それをスクリプトから参照するには、XULファイル内で
<stringbundleset>
<stringbundle id="bar" src="chrome://myPackage/locale/foo.properties" />
<stringbundle ... <!-- 複数のファイルがある場合 -->
</stringbundleset>
のように、stringbundle要素でChrome URIを指定して読み込みます※1。このときその要素には、スクリプトから参照しやすいようにid属性を設定しておきます。そしてスクリプトではそのidから要素を取得して、
var stringbundle = document.getElementById( 'bar' );
var str = stringbundle.getString( 'str1' );
alert( str ); // 「AAA」と表示
のように、プロパティを取得できます。
※1 stringbundle要素でプロパティ ファイルを指定するときは、必ずChrome URIを使用します。さもなくばgetString()でプロパティを取得するときに「NS_ERROR_UNEXPECTED: Component returned failure code: 0x8000ffff (NS_ERROR_UNEXPECTED) [nsIStringBundle.GetStringFromName]」として例外が発生します。
.propertiesファイルへの修正を反映させるには、Firefoxを再起動させる必要があります。再起動せず新しく追加した項目を読み込もうとすると、それを認識できないため「NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIStringBundle.GetStringFromName]」として例外が発生します。
ロケールの設定による表示の変化を確認するには、言語パックをインストールして表示言語を変更します。