Firefox 3ではじめる拡張機能開発

第5回localeパッケージによるローカライズ

前回まででタグヘルパー拡張機能の実装は完了しましたが、新しく追加したメニュー項目やダイアログの文言はすべて英語のままとなっています。今回はlocaleパッケージを追加することで、これらの文言をローカライズ可能にし、日本語での表示ができるようにします。なお、第5回完成時点でのソースファイルは、下記URLから入手可能です。

ソースファイルのフォルダ構成

前回までは、第2回で説明した「クロムと3種類のパッケージ」のうち、contentパッケージのみ使用しました。今回は、localeパッケージを追加します。localeパッケージのソースファイルは「locale」フォルダ内に作成した言語別のサブフォルダ内に格納します。したがって、第5回完成時点での各種ソースファイルのフォルダ構成は図1のようになります。また、第5回で新たに作成するソースファイルの概要を表1に示します。

図1 第5回完成時点でのフォルダ構成
図1 第5回完成時点でのフォルダ構成
表1 第5回で新たに作成するソースファイルの概要
ファイル名概要
overlay.dtd overlay.xulにて使用する実体参照を定義したDTDファイル。
overlay.properties overlay.jsにて使用するローカライズ可能文字列を定義したpropertiesファイル。

localeパッケージの追加

localeパッケージを追加するために、クロムマニフェストへリスト1の内容を追加してください。

リスト1 クロムマニフェストへの記述内容1(localeパッケージの追加)
content  taghelper  content/
locale  taghelper  en-US  locale/en-US/ 
locale  taghelper  ja-JP  locale/ja-JP/ 
overlay  chrome://browser/content/browser.xul  chrome://taghelper/content/overlay.xul 

リスト1の2行目が英語版(en-US)のlocaleパッケージを登録するための宣言です。パッケージ名が「taghelper⁠⁠、localeパッケージ内のソースファイルを格納したフォルダへの相対パスが「locale/en-us/」となります[1]⁠。同様に、リスト1の3行目が日本語版(ja-JP)のlocaleパッケージを登録するための宣言です。もし、フランス語や中国語といった他言語版のlocaleパッケージを追加するのであれば、リスト1のような宣言を追加し、⁠locale」フォルダ内に言語別のサブフォルダを作成して、その中に各言語へローカライズしたソースファイルを格納します。

DTDファイルによるローカライズ

XULドキュメント内にハードコーディングされた英語の文字列を各言語へローカライズ可能にするには、英語の文字列を実体参照へと置き換え、その実体参照の定義を各言語のlocaleパッケージ内に格納したDTDファイルへ記述します。まず、⁠overlay.xul」リスト2の内容を追加してください。

リスト2 ⁠overlay.xul」への記述内容(実体参照への置き換え)
<?xml version="1.0"?>

<!DOCTYPE overlay SYSTEM "chrome://taghelper/locale/overlay.dtd"> 

<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> 
  <script type="application/x-javascript" src="chrome://taghelper/content/overlay.js" /> 
  <popup id="contentAreaContextMenu">
    <menuitem id="taghelper-menu" 
              label="&taghelperMenu.label;"
              oncommand="TagHelper.generateTags();" />
  </popup>
</overlay>

リスト2では、menuitem要素のlabel属性「Generate Tags from Selection」を実体参照「&taghelperMenu.label;」に置き換えています。その実体参照の定義は「overlay.dtd」に記述しますので、⁠overlay.xul」の冒頭部分へDOCTYPE宣言を追加し、⁠overlay.dtd」を呼び出すようにします。

各言語の「overlay.dtd」には、リスト3リスト4のような内容を記述してください。なお、DTDファイルに日本語などのマルチバイト文字列を記述する場合、文字コードUTF-8、BOM(Byte Order Mark)無しの形式でファイルを保存する必要があります。

リスト3 ⁠en-US」フォルダ内の「taghelper.dtd」への記述内容
<!ENTITY taghelperMenu.label "Generate Tags from Selection"> 
リスト4 ⁠ja-JP」フォルダ内の「taghelper.dtd」への記述内容
<!ENTITY taghelperMenu.label "選択範囲からタグを生成"> 

動作確認

ここまでできたら、いったん動作確認を行います。今回はクロムマニフェストを修正して新たにlocaleパッケージを追加しました。クロムマニフェストはFirefox起動時に読み込まれますので、今回変更した内容を反映させるためには、Firefoxを一度再起動する必要があります。

Firefox再起動後、適当なWebページ上で範囲を選択し、右クリックメニューを表示すると、図2のようにタグヘルパーのメニュー項目が日本語で表示されることを確認してください。ただし、英語版のFirefoxを使用している場合、英語で表示されます。

図2 ローカライズされたタグヘルパーのメニュー項目
図2 ローカライズされたタグヘルパーのメニュー項目

なお、日本語版のFirefoxにて英語での表示を確認したい場合、⁠about:config」で設定値「general.useragent.locale」の値を「ja」から「en-US」に変更し、Firefoxの新しいウィンドウを開いてください。

propertiesファイルによるローカライズ

JavaScriptのソースファイル内にハードコーディングされた英語の文字列は、Java言語で使われるようなpropertiesファイルへと分離させることで、ローカライズ可能となります。propertiesファイルに定義した文字列をJavaScriptから取り出すには、XULのstringbundle要素を使用する方式と、XPCOMサービスであるnsIStringBundleServiceを使用する方式があります。今回は、前者の方式を使用した手順を解説します。

まず、⁠overlay.xul」リスト5のように記述を追加してください。

リスト5 ⁠overlay.xul」への記述内容(stringbundle要素の追加)
<?xml version="1.0"?>

<!DOCTYPE overlay SYSTEM "chrome://taghelper/locale/overlay.dtd">

<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script type="application/x-javascript" src="chrome://taghelper/content/overlay.js" /> 
  <stringbundleset id="stringbundleset"> 
    <stringbundle id="taghelper-bundle" src="chrome://taghelper/locale/overlay.properties" /> 
  </stringbundleset> 
  <popup id="contentAreaContextMenu"> 
    <menuitem id="taghelper-menu" 
              label="&taghelperMenu.label;" 
              oncommand="TagHelper.generateTags();" /> 
  </popup> 
</overlay> 

リスト5では、stringbundle要素を追加することで、localeパッケージ内のpropertiesファイル「overlay.properties」を読み込みます。stringbundle要素は単独では使用せずに、stringbundleset要素を使用してグループ化して配置します。今回の場合「overlay.xul」のオーバーレイ先である「browser.xul」に、idが「stringbundleset」のstringbundleset要素が存在するため[2]⁠、この要素をマージポイントとしてstringbundle要素を追加します。

次に、⁠overlay.js」「generateTags」プロパティへリスト6のように記述を追加・修正してください。

リスト6 ⁠overlay.js」「generateTags」プロパティへの記述内容(stringbundle要素の使用)
generateTags: function() {
  var bundle = document.getElementById("taghelper-bundle"); 
  var url = window.content.location.href;
  url = PlacesUtils._uri(url);
  if (!PlacesUtils.bookmarks.isBookmarked(url)) {
    alert(bundle.getFormattedString("NOT_BOOKMARKED", [window.content.document.title])); 
    return;
  }
  var keywords = [];
  var sel = window.content.getSelection();
  for (var i = 0; i < sel.rangeCount; i++) {
    var keyword = sel.getRangeAt(i).toString();
    keyword = keyword.replace(/^\s+|\s+$/g, "");
    keywords.push(keyword);
  }
  Application.console.log(bundle.getString("KEYWORDS") + " = " + keywords); 
  if (keywords.length > 0) {
    PlacesUtils.tagging.tagURI(url, keywords);
  }
  sel.removeAllRanges();
},

引き続き、各言語のpropertiesファイル「overlay.properties」を作成します。propertiesファイルには、各文字列を「キー=値」の形式で記述します。今回は「overlay.js」にて追加した2つのキー「NOT_BOOKMARKED」⁠KEYWORDS」に対応するローカライズされた文字列をリスト7リスト8のように記述します。なお、propertiesファイルに日本語などのマルチバイト文字列を記述する場合、DTDファイルと同様に、文字コードUTF-8、BOM(Byte Order Mark)無しの形式でファイルを保存する必要があります。

リスト7 ⁠en-US」フォルダ内の「overlay.properties」への記述内容
NOT_BOOKMARKED="%S" is not bookmarked. 
KEYWORDS=Keywords
リスト8 ⁠ja-JP」フォルダ内の「overlay.properties」への記述内容
NOT_BOOKMARKED=「%S」はブックマークされていません。 
KEYWORDS=キーワード

リスト6では、まずリスト5で追加したstringbundle要素を変数「bundle」として取得します。stringbundle要素を介してpropertiesファイルからローカライズ文字列を取得するには、通常stringbundle要素のgetStringメソッドを使用します。リスト6では「bundle.getString("KEYWORDS")」とすることで、⁠overlay.properties」に記述したキー「KEYWORDS」に対応するローカライズされた文字列を取得します。

一方、ローカライズされた文字列内の一部を置き換える必要がある場合、stringbundle要素のgetFormattedStringメソッドを使用します。リスト6では「bundle.getFormattedString("NOT_BOOKMARKED", [window.content.document.title])」とすることで、⁠overlay.properties」に記述したキー「NOT_BOOKMARKED」に対応するローカライズされた文字列を取得し、さらに文字列内の「%S」を引数「window.content.document.title」の内容へ置換します。

動作確認

「DTDファイルによるローカライズ」の動作確認でFirefoxを一度再起動しているのであれば、すでにlocaleパッケージが読み込まれていますが、propertiesファイルを追加・修正した際には、そのたびにFirefoxを再起動する必要があります。Firefoxを再起動し、以下の2点を確認してください。

  • ブックマークされていないWebページ上で範囲を選択し、右クリックから「選択範囲からタグを生成」メニュー項目を選択すると、図3のように日本語で警告メッセージが表示される。
  • ブックマーク済みのWebページ上で範囲を選択し、右クリックから「選択範囲からタグを生成」メニュー項目を選択すると、図4のようにエラーコンソールのメッセージパネルへ日本語のデバッグメッセージが出力される。
図3 ローカライズされた警告メッセージ
図3 ローカライズされた警告メッセージ
図4 ローカライズされたデバッグメッセージ
図4 ローカライズされたデバッグメッセージ

PluralFormモジュールを使用した高度なローカライズ

やや高度な技術となりますが、ここからはFirefox 3の新機能のひとつであるPluralFormモジュールを使用した複数形を含む文字列のローカライズについて簡単に解説します。PluralFormモジュールについての詳細な解説は、下記URLを参照してください。

PluralFormモジュールの使用例として、⁠選択範囲からタグを生成」メニュー項目からタグを追加した後、⁠3個のタグを追加しました。」のようなメッセージを表示する機能を追加します。一見するとリスト9のようにタグの個数を引数としてstringbundle要素のgetFormattedStringメソッドを使用すれば良さそうに思えます。

リスト9 ⁠overlay.js」「generateTags」プロパティへの記述内容(タグの個数表示機能を追加)
generateTags: function() {

  (省略)

  alert(bundle.getFormattedString("ADDED", [keywords.length]));
},

このとき、日本語版の「overlay.properties」ファイルには、⁠ADDED=%S個のタグを追加しました。」という内容を追加すれば問題ありませんが、英語版の「overlay.properties」ファイルへ追加するべき内容は、タグの個数が単数の場合は「ADDED=%S tag was added.」となり、複数の場合は「ADDED=%S tags were added.」と2通りになってしまいます。Firefox 3自体が定義するJavaScriptコードモジュール[2]のひとつであるPluralFormモジュールは、このような複雑な文法に対応したローカライズを可能にします。PluralFormモジュールを使用するには、まずリスト10のようにモジュールをインポートします。

リスト10 ⁠overlay.js」「init」プロパティへの記述内容(PluralFormモジュールのインポート)
init: function() {
  var contextMenu = document.getElementById("contentAreaContextMenu"); 
  contextMenu.addEventListener("popupshowing", this, false);
  Components.utils.import("resource://gre/modules/PluralForm.jsm");
},

次に、⁠overlay.js」「generateTags」プロパティへリスト11のように記述を追加・修正してください。

リスト11 ⁠overlay.js」「generateTags」プロパティへの記述内容(PluralFormモジュールの使用)
generateTags: function() {

  (省略)

  var numTags = keywords.length;
  var msg = PluralForm.get(numTags, bundle.getString("ADDED")); 
  msg = msg.replace("#1", numTags);
  alert(msg + "\n" + keywords.join(", "));
},

引き続き、各言語のpropertiesファイル「overlay.properties」「ADDED」キーの内容を追加します。英語版の「overlay.properties」ファイルには、リスト12のように単数形の場合の文字列と複数形の場合の文字列を「;」で区切って並べて記述します[3]⁠。一方、日本語版の「overlay.properties」ファイルは単数形・複数形による文字列の違いがないため、リスト13のような記述を追加します。

リスト12 ⁠en-US」フォルダ内の「overlay.properties」への記述内容(ADDEDキーの追加)
ADDED=One tag was added.;#1 tags were added.
リスト13 ⁠ja-JP」フォルダ内の「overlay.properties」への記述内容(ADDEDキーの追加)
ADDED=#1個のタグが追加されました。

リスト11ではPluralForm.getメソッドの引数にタグの個数とstringbundle要素のgetStringメソッドで取得したメッセージの文字列を指定し、タグの個数が単数か複数かに応じた適切な文字列を取得します。さらに、取得した文字列中の「#1」をタグの個数に置換し、最後にalert関数でメッセージを表示します。

動作確認

PluralFormモジュールによって、タグの個数が単数か複数かに応じて適切な文字列が選択されることを確かめるには、日本語ではなく英語での動作確認が必要となります。そこで、まず「about:config」で設定値「general.useragent.locale」の値を「ja」から「en-US」に変更し、Firefoxを再起動後に以下の2点を確認してください。

  • ブックマーク済みのWebページ上で範囲をひとつだけ選択し、右クリックから「選択範囲からタグを生成」メニュー項目を選択すると、図5のようなメッセージが表示される。
  • ブックマーク済みのWebページ上でCtrlキーを押下しながら複数の範囲を選択し、右クリックから「選択範囲からタグを生成」メニュー項目を選択すると、図6のようなメッセージが表示される。
図5 ローカライズされたメッセージ(英語・単数形)
図5 ローカライズされたメッセージ(英語・単数形)
図6 ローカライズされたメッセージ(英語・複数形)
図6 ローカライズされたメッセージ(英語・複数形)

まとめと次回の予告

今回はlocaleパッケージを追加することで、拡張機能のUIの文言をローカライズ可能にし、日本語での表示ができるようにしました。DTDファイルによるローカライズ、propertiesファイルによるローカライズともに、拡張機能を開発するでは必須の技術といえるでしょう。

次回は、skinパッケージを追加して拡張機能のUIの装飾を行います。

おすすめ記事

記事・ニュース一覧