XUL と XML には、地域化 (localization) を可能にする便利な方法であるエンティティーがあります。
多くのアプリケーションは、インターフェースを別の言語に翻訳するのをできるだけ簡単にするように作られています。通常、個々の言語のため、文字列テーブルが作られます。テキストを直接アプリケーションに埋め込むのではなく、個々のテキスト部分は、文字列テーブルを参照するだけです。XML には、似た目的で使えるエンティティーがあります。
HTML を書いたことがあるなら、エンティティーは既にお馴染みのはずです。コード < や > は、テキストに小なり記号や大なり記号を置くのに使われるエンティティーの例です。XML には、カスタムエンティティーを宣言できるシンタックスがあります。これを使えば、その値でエンティティーを置き換えることができます。その値はテキスト文字列でも構いません。エンティティーは、属性の値を含めて、テキストが置ける場所ならどこでも使えます。下の例は、ボタンにエンティティーを使った例を示しています。
<button label="&findLabel;"/> |
ラベルに表示されるテキストは、エンティティー &findLabel; の値になります。サポートする個々の言語のエンティティー宣言をもつファイルを作ります。英語では、&findLabel; エンティティーは、'Find' というテキストになるように宣言されるでしょう。
エンティティーは、DTD (文書型宣言 - Document Type Declaration) ファイルで宣言されます。この種のファイルは、通常、特定の XML ファイルのシンタックスやセマンティクスを宣言するのに使われます。これを使って、エンティティーの宣言ができます。Mozilla のクロムシステムでは、locales サブディレクトリーに DTD ファイルが置かれているのが分かるでしょう。通常は、XUL ファイルごとに、(dtd という拡張子をもつ) DTD ファイルが一つあります。
chrome/locales ディレクトリーを見れば、インストールした個々のロケールのためのディレクトリーがあるのが分かるはずです。その構造は、スキンで使われるディレクトリー構造に非常によく似ています。
例えば、アメリカ英語 (en-us) と フランス語 (fr) という 2 つの言語のためのロケールファイルがあるかもしれません。その他のサブディレクトリーを、インストールする個々の言語のため、追加できます。
言語ディレクトリー内には、エンティティーを宣言した DTD ファイルを置きます。多くの場合、XUL ファイルそれぞれに DTD ファイルが一つ対応します。これは拡張子が .dtd であることを除けば、同じファイル名です。そのため、「ファイル検索」ダイアログの場合、findfile.dtd という名前のファイルが必要です。
インストールしていないクロムファイルの場合、XUL ファイルと同じディレクトリーに DTD ファイルを置くだけで済みます。
自分の XUL に DTD ファイルを作ったら、XUL ファイルに、DTD ファイルを使いたいことを指示する行を追加する必要があります。そうしなければ、エンティティーを見付けることができないので、エラーが発生します。このためには、XUL ファイルの先頭辺りに次のような内容の行を追加します。
<!DOCTYPE window SYSTEM "chrome://findfile/locale/findfile.dtd"> |
この行は、指定された URL をファイルの DTD として使用することを指定するものです。この場合は、findfile.dtd という DTD ファイルを使いたいと宣言しています。この行は、多くの場合、window 要素の直前に置かれます。
エンティティーは、以下に示すような簡単なシンタックスを使って宣言します。
<!ENTITY findLabel "Find"> |
この例は、findLabel という名前と Find という値をもつエンティティーを作ります。これは、XUL ファイルに &findLabel; というテキストがあると、Find というテキストを使うことを意味します。別の言語のための DTD ファイルには、その言語のためのテキストを使います。エンティティー宣言には、その末尾に終わりを表わすスラッシュがない点に注意して下さい。
例えば、次のテキストは以下のように翻訳されます。
<description value="&findLabel;"/> これは次のように翻訳される。 <description value="Find"/> |
自分のインターフェースで使用する個々のラベルやテキスト文字列のためのエンティティーを宣言することになるでしょう。XUL ファイル中には、決して、直接表示されるテキストを入れるべきではありません。
テキストラベルにエンティティーを使う以外に、言語によって異なる値にもそれを使うとよいでしょう。次の例は、アクセスキーとキーボードショートカットです。
<menuitem label="&undo.label;" accesskey="&undo.key;"/> <!ENTITY undo.label "Undo"> <!ENTITY undo.key "u"> |
上の例は、エンティティーを 2 つ使っています。一つは、Undo メニュー項目のラベルで、もう一つは、アクセスキーです。
テキスト文字列すべてのために DTD を使うように「ファイル検索」ダイアログを変更することによって、どうやってこれらすべてをひとまとめにするか見ることにしましょう。XUL ファイル全体を以下に示します。変更は赤で表示しました。
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="findfile.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://findfile/locale/findfile.dtd">
<window
id="findfile-window"
title="&findWindow.title;"
persist="screenX screenY width height"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="initSearchList();">
<script src="findfile.js"/>
<popupset>
<popup id="editpopup">
<menuitem label="Cut" accesskey="&cutCmd.accesskey;"/>
<menuitem label="Copy" accesskey="©Cmd.accesskey;"/>
<menuitem label="Paste" accesskey="&pasteCmd.accesskey;" disabled="true"/>
</popup>
</popupset>
<keyset>
<key id="cut_cmd" modifiers="accel" key="&cutCmd.commandkey;"/>
<key id="copy_cmd" modifiers="accel" key="©Cmd.commandkey;"/>
<key id="paste_cmd" modifiers="accel" key="&pasteCmd.commandkey;"/>
<key id="close_cmd" keycode="VK_ESCAPE"/>
</keyset>
<box orient="vertical" flex="1">
<toolbox>
<menubar id="findfiles-menubar">
<menu id="file-menu" label="&fileMenu.label;"
accesskey="&fileMenu.accesskey;">
<menupopup id="file-popup">
<menuitem label="&openCmd.label;"
accesskey="&openCmd.accesskey;"/>
<menuitem label="&saveCmd.label;"
accesskey="&saveCmd.accesskey;"/>
<menuseparator/>
<menuitem label="&closeCmd.label;"
accesskey="&closeCmd.accesskey;" key="close_cmd" oncommand="window.close();"/>
</menupopup>
</menu>
<menu id="edit-menu" label="&editMenu.label;"
accesskey="&editMenu.accesskey;">
<menupopup id="edit-popup">
<menuitem label="&cutCmd.label;"
accesskey="&cutCmd.accesskey;" key="cut_cmd" oncommand="doCut()"/>
<menuitem label="©Cmd.label;"
accesskey="©Cmd.accesskey;" key="copy_cmd" oncommand="doCopy()"/>
<menuitem label="&pasteCmd.label;"
accesskey="&pasteCmd.accesskey;" key="paste_cmd" oncommand="doPaste()"/>
</menupopup>
</menu>
</menubar>
<toolbar id="findfiles-toolbar">
<button id="opensearch" label="&openCmdToolbar.label;"/>
<button id="savesearch" label="&saveCmdToolbar.label;"/>
</toolbar>
</toolbox>
<tabbox orient="vertical">
<tabs orient="horizontal">
<tab label="&searchTab;" selected="true"/>
<tab label="&optionsTab;"/>
</tabs>
<tabpanels>
<tabpanel id="searchpanel" orient="vertical">
<html>
&findDescription;
</html>
<spacer class="titlespace"/>
<groupbox orient="horizontal">
<label control="searchtype" value="&findCriteria;"/>
<menulist id="searchtype">
<menupopup>
<menuitem label="&type.name;"/>
<menuitem label="&type.size;"/>
<menuitem label="&type.date;"/>
</menupopup>
</menulist>
<spacer class="springspace"/>
<menulist id="searchmode">
<menupopup>
<menuitem label="&mode.is;"/>
<menuitem label="&mode.isnot;"/>
</menupopup>
</menulist>
<spacer class="springspace"/>
<textbox id="find-text" flex="1" style="min-width: 15em;" context="editpopup"/>
</groupbox>
</tabpanel>
<tabpanel id="optionspanel" orient="vertical">
<checkbox id="casecheck" label="&casesensitive;"/>
<checkbox id="wordscheck" label="&matchfilename;"/>
</tabpanel>
</tabpanels>
</tabbox>
<tree id="results" style="display: none;">
<treecolgroup>
<treecol flex="1"/>
<treecol flex="2"/>
<treecol flex="1"/>
</treecolgroup>
<treehead>
<treerow>
<treecell label="&results.filename;"/>
<treecell label="&results.location;"/>
<treecell label="&results.size;"/>
</treerow>
</treehead>
<treechildren flex="1">
<treeitem>
<treerow>
<treecell label="mozilla"/>
<treecell label="/usr/local"/>
<treecell label="&bytes.before;2520&bytes.after;"/>
</treerow>
</treeitem>
</treechildren>
</tree>
<splitter id="splitbar" collapse="before" resizeafter="grow" style="display: none;"/>
<box orient="horizontal">
<progressmeter id="progmeter" value="50%" style="display: none;"/>
<spacer flex="1"/>
<button id="find-button" label="&button.find;" default="true"
onclick="doFind()"/>
<button id="cancel-button" label="&button.cancel;"
onclick="window.close();"/>
</box>
</box>
</window>
|
個々のテキスト文字列は、エンティティーの参照で置き換えられています。DTD ファイルは、XUL ファイルの先頭近くにインクルードされています。追加した個々のエンティティーは、DTD ファイルで宣言すべきです。宣言されていないエンティティーが XUL ファイルにあると、ウィンドウは表示されません。
エンティティーの名前は重要ではない点に注意して下さい。上の例では、エンティティー内の語はピリオドで区切られています。別にこの通りにする必要はありません。ここでは、エンティティー名は Mozilla のコードの他の部分と同様の慣習に従っています。
'2520 bytes' というテキストが 2 つのエンティティーによって置き換えられていることに気が付いたかもしれません。これは、語句の構造がロケールによって異なるかもしれないからです。例えば、数値は、'bytes' に対応する語の後ではなく前に表示する必要があるかもしれません。もちろん、これは、必要な場合、KB や MB を表示する場合、もっと込み入ったものになる場合もあります。
アクセスキーとキーボードショートカットもエンティティーに翻訳されています。これは、ロケールによって違ったものになるかもしれないからです。
次は、DTD ファイル (findfile.dtd) です。
<!ENTITY findWindow.title "Find Files"> <!ENTITY fileMenu.label "File"> <!ENTITY editMenu.label "Edit"> <!ENTITY fileMenu.accesskey "f"> <!ENTITY editMenu.accesskey "e"> <!ENTITY openCmd.label "Open Search..."> <!ENTITY saveCmd.label "Save Search..."> <!ENTITY closeCmd.label "Close"> <!ENTITY openCmd.accesskey "o"> <!ENTITY saveCmd.accesskey "s"> <!ENTITY closeCmd.accesskey "c"> <!ENTITY cutCmd.label "Cut"> <!ENTITY copyCmd.label "Copy"> <!ENTITY pasteCmd.label "Paste"> <!ENTITY cutCmd.accesskey "t"> <!ENTITY copyCmd.accesskey "c"> <!ENTITY pasteCmd.accesskey "p"> <!ENTITY cutCmd.commandkey "X"> <!ENTITY copyCmd.commandkey "C"> <!ENTITY pasteCmd.commandkey "V"> <!ENTITY openCmdToolbar.label "Open"> <!ENTITY saveCmdToolbar.label "Save"> <!ENTITY searchTab "Search"> <!ENTITY optionsTab "Options"> <!ENTITY findDescription "Enter your search criteria below and select the Find button to begin the search."> <!ENTITY findCriteria "Search Criteria"> <!ENTITY type.name "Name"> <!ENTITY type.size "Size"> <!ENTITY type.date "Date Modified"> <!ENTITY mode.is "Is"> <!ENTITY mode.isnot "Is Not"> <!ENTITY casesensitive "Case Sensitive Search"> <!ENTITY matchfilename "Match Entire Filename"> <!ENTITY results.filename "Filename"> <!ENTITY results.location "Location"> <!ENTITY results.size "Size"> <!ENTITY bytes.before ""> <!ENTITY bytes.after "bytes"> <!ENTITY button.find "Find"> <!ENTITY button.cancel "Cancel"> |
これで、言語を変更する場合に必要なのは、別の DTD ファイルを作るだけです。異なったロケールのため DTD ファイルを追加するクロムシステムを使うことにより、同じ XUL ファイルをどの言語でも使うことができるのです。
(進む) 次は、プロパティーファイルを見ることにしましょう。