FireVoxにもどる

目次

目的

FireVoxを日本語化したときの工程や、資料をまとめます。 日本語ロケールファイルを付け加える作業だけではなく、 ローカリゼーション機構のない拡張にlocalフォルダを作り多言語対応にする方法です。 一からローカリゼーション対応の拡張を作るときにも役に立つでしょう。 なお、この文書はWindows上での作業をまとめたものです。

これは私がこのようにやったという報告であって、正攻法ではないかもしれません。 自分でスクリプトを書いて自動化したり、いろいろやってみてください。

参考ページ

主に以下のサイトを参考にしました。他にも記録していないページを参考にしています。

ここにあるページの情報を見れば、自分がまとめる必要もないかもしれない。

ここにあるサイトは古い情報が含まれている可能性があります。事実そのために手こずったところもあります。

準備するソフト

UTF8N形式で読み書き可能なエディタ

いろいろありますが、フリーで使えておすすめなのは、

両者ともちゃんと検索には正規表現が使えます。

ユニコードエスケープシーケンスに変換するソフト

JDK付属のnative2asciiを使う方法もありますが、読み書き可能なテキストエディタがあります。

jarファイルなので、J2REやJ2SDKが必要です。詳しくは上記のリンク。

ZIP形式対応の解凍圧縮ソフト

いろいろありますが、

この文書の中にある圧縮解凍のバッチファイルは、この7-ZIPを前提に書かれています。

パッケージの展開

拡張機能のファイルはxpiという拡張子の付いたファイルですが、実はこれはいくつかのファイルをZIP形式で圧縮したものです。展開することで内容を見ることができます。

ZIPが解凍できるソフトならば何でもいいのですが、Windowsで7-ZIPをインストールしてあり、パスの通っているところに7z.exeがあることを前提ですすめます。

マイドキュメント内などに作業フォルダを決め、そこに拡張名のフォルダを作ります。そこに展開したい拡張機能を置き、右クリックメニューのExtract Hereコマンドを実行します。するとinstall.rdfファイルとchromeフォルダなどが解凍されます。

chromeフォルダの中を見ると、拡張機能名に拡張子jarがついたファイルが見つかります。 このJARファイルも、複数のファイルを集めてZIPでまとめたファイルです。 同じように右クリックでメニューを出し、Extract Hereコマンドで展開します。このJARファイルは解凍が終われば削除してもかまいません。

解凍後content フォルダなどが現れるはずです。このときlocaleフォルダも見つかれば、この拡張機能にはローカリゼーションの機能があります。日本語で表示されないならば、日本語化ができていないだけなので、ローカライズを参考にして、日本語化してください。この文書の大部分で説明しようとしているのは、localeフォルダそのものが存在しない場合です。

上記の作業をバッチファイル(extract.bat)で書くと、

7z x "*.xpi"
cd chrome
7z x "*.jar"
del *.jar
cd ..

ローカリゼーションへの対応

結局これから何をするのかというと、翻訳対象となる文字列をXULファイルとJSファイルから切り出し、その文字列に約束事に従った名前をつけ、その名前と文字列との対応表を作ります。簡単にいうとそういうことです。

この対応表を別の言語用を用意することで、ローカリゼーションができるようになるわけです。

パッケージのローカリゼーション対応

ローカリゼーションを実現するために、拡張機能のパッケージにいくつかの新しいファイルやフォルダを追加し、既にあるファイルにいくつかの記述を追加していく必要があります。

フォルダの構成

XULファイルとJSファイルから切り離した文字列を格納するためのフォルダを作ります。

localフォルダはchromeフォルダ内に作ります。そしてその中にその言語のロケール名のフォルダを作ります。ここにその言語の文字列ファイルを置きます。ここに置かずにさらにこの中に拡張名のフォルダを作りその中に置く流儀もあるようです。

例えば、英語ロケールを作る場合

chrome/locale/en-US/

というフォルダを作り、その中に文字列ファイルを置きます。 別な流儀だと、拡張機能hogeとすると、

chrome/locale/en-US/hoge

となります。

install.rdfの記述

これはパッケージの構成を記述してあるファイルです。firefoxの拡張機能マネージャーは、このファイルの記述を利用して、自動的に拡張機能を組み込んでいきます。なおこのファイルはXMLで書かれています。

このファイルにはロケール要素を追加します。追加する場所は、em:file要素のjarファイルを指定しているDescription要素内です。追加する行は、その言語の文字列を納めたファイルが置かれるフォルダをem:localeタグで挟んだものになります。

拡張機能hogeに、chromeフォルダからの相対位置locale/en-USのフォルダに英語の文字列情報を置くときは、

<em:file>
 <Description about="urn:mozilla:extension:file:hoge.jar">
  <em:locale>locale/en-US/</em:locale>
 </Description>
</em:file>

となります。

いろいろ拡張機能の内部を見てみましたが、どういう理由か分かりませんが、中にはinstall.rdf内の構造が違うものもありました。その場合はその構造に合わせてください。

contents.rdf

パッケージ内のファイルがあるフォルダには、contens.rdfファイルを用意する必要があります。新しくlocaleフォルダを作ったので、この中にもcontents.rdfファイルを作らないといけません。なおlocaleフォルダに直に置くのではなく、各ロケールのファイルの置いてあるフォルダに置きます。

ロケールフォルダに入れる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#">

  <RDF:Seq about="urn:mozilla:locale:root">
    <RDF:li resource="urn:mozilla:locale:en-US"/>
  </RDF:Seq>

  <RDF:Description about="urn:mozilla:locale:en-US"
        chrome:displayName="My Application"
        chrome:author="name"
        chrome:name="en-US">
    <chrome:packages>
      <RDF:Seq about="urn:mozilla:locale:en-US:packages">
        <RDF:li resource="urn:mozilla:locale:en-US:myapplication"/>
      </RDF:Seq>
    </chrome:packages>
  </RDF:Description>
</RDF:RDF>

上記の、My Application、name、myapplicationと書かれている部分を、拡張に合わせて書き換えます。 また違う言語を対象とする場合は上記のen-USの部分を置き換えます。

なお、このファイルに非ASCII文字が含まれる場合はUTF8形式で保存します。chrome:displayNameの値が非ASCII文字列になる可能性があります。

XULのローカリゼーション対応

拡張機能のユーザーインターフェイス部分、つまりメニューの項目やウィンドウ上のボタンの配置、そして処理の指定など、そういうものを記述してあるのが、XULファイルです。

このXULファイルには、ウィンドウのラベルやメニューの項目など、翻訳の対象となる文字列があります。

XULファイル中の翻訳箇所

このファイルはXMLで書かれています。 ウィンドウ上の言葉や、メニューの項目名がどのような形でXULファイル上に記載されているかは、XML言語の文法、XUL言語の要素や属性についての知識が必要になってきます。

翻訳の可能性があるのは、次の箇所です。

  • 要素の label 属性
  • 要素の accesskey 属性
  • window 要素の title 属性
  • label 要素の value 属性
  • textbox 要素の value 属性
  • description 要素の内容
  • html 要素が使用できるなら適宜その内容もしくは属性

accesskey 属性は、日本語においては英語のものを訳に関係なくそのまま利用していますが、ヨーロッパの言語などでは、訳に伴い置き換えられる可能性がありますので、置き換え可能な対象にしておく必要があります。

上記の属性を眺めてみて、翻訳の必要なものを探していきます。 そしてその文字列をDTDファイルに記述していきます。

DTDファイルの作成

DTDは日本語で文書型定義と呼ばれるもので、XMLでの要素や属性を定義しているファイルです。詳しくはXMLの入門書などを参考にしてもらうとして、ここではXULファイルで使われる文字列を定義するファイルとして使われています。

DTDファイルはlocaleフォルダ内に作成します。install.rdfで記述されているその言語のロケール指定の階層にファイルを作ります。

次の記述がinstall.rdfファイル内にあるならば、

<em:locale>locale/en-US/</em:locale>

この場合は、localeフォルダ内のen-USフォルダに作ります。 次の場合ならば、

<em:locale>locale/en-US/hoge/</em:locale>

localeフォルダ内のen-USフォルダのhogeフォルダに作ります。

DTDファイルの名前はその拡張の名前に、".dtd"を付けたものが分かりやすいでしょう。 XULファイルが複数あるときはXULファイルに合わせ分割する方法もわかりやすいでしょう。

なお、DTDファイルは、非ASCII文字列を含む場合、UTF-8N形式を指定して保存します。

DTDファイルを作成したら、その内容を参照するXULファイル内には DOCUTYPE宣言を追加しておきます。

拡張foo で foo.dtd というDTDファイルを指定する場合、

<!DOCTYPE window SYSTEM "chrome://foo/locale/foo.dtd">

のようになります。上記の文書タイプ名は、その後に記述されるトップレベル要素です。windowの他に、overlay, dialog, wizard となるかもしれません。

DTDファイルの記述と、XULファイルの修正

各翻訳対象の文字列は、次の実体宣言形式で書いていきます。

<!ENTITY 名前 "文字列">

文字列が実際に表示される文字列そのもので、名前がその文字列を参照するための名前です。この文字列の部分を別の言語に翻訳したDTDファイルを用意することで、ウィンドウやメニューに現れる言葉を各言語に対応させていくことができます。

ここで宣言された名前をXULファイル中で参照するには、その名前を &と;で挟んで指定します。

DTDファイルで次のように定義された場合、

<!ENTITY hoge "click me">

XULファイル内のとある部分では、次のように参照できます。

<button label="&hoge;"/>

このENTITY名には、'.'を入れたドット記法が使えるので、拡張名、XUL要素名、要素のidなどを組み合わせて、わかりやすい一意の名前を付けていきます。

このようにして、XULファイルをローカリゼーション対応にします。

Javascriptのローカリゼーション対応

拡張の動作内容を記述しているのがJS拡張子を持つJavascriptファイルです。このJavascriptで出力される文字列もローカリゼーションの対象となります。

作業の対象は、以下の3種類のファイルです。

  • XULファイル
  • JSファイル
  • PROPERTIESファイル

おおまかな手順は次の通りです。

  • localeフォルダに、PROPERTIESファイルを作成する。
  • 対象となるJavascriptを呼び出しているXULファイルにPROPERTIESファイルを登録する。
  • Javascript内の文字列を見渡し、翻訳の対象とすべき文字列がどれかを調べる。
  • 翻訳対象の文字列に英数字で名前をつけ、それをPROPERTIESファイルに後述の書式に従って、その名前と文字列との対応表を作る。
  • JSファイル内の文字列をPROPERTIESファイルの文字列を参照する形式に置き換える。

それでは、細かな手順を示します。

PROPERTIESファイルはどこに作るのか。

PROPERTIESファイルはlocaleフォルダ内に作ります。これはJavascript内で記述されている文字列の言語のロケールフォルダ内です。例えば英語で記述してありメッセージが英語で出力されるプログラムを作業の対象にする場合は英語ロケールとなり、その言語のinstall.rdfで記述しているロケール指定の階層にファイルを作ります。

例えば、以下のような記述がinstall.rdfファイル内にあるとき、

<em:locale>locale/en-US/</em:locale>

この場合は、localeフォルダ内のen-USフォルダに作ります。次の場合は、

<em:locale>locale/en-US/hoge/</em:locale>

localeフォルダ内のen-USフォルダ内のhogeフォルダ内に作ります。

PROPERTIESファイルに名前を付ける。

名前は任意ですが、その拡張機能の名前にしたほうがわかりやすいでしょう。そして拡張子にpropertiesを付けます。

例えば、拡張機能hogeを作っているときは、hoge.properites とします。

またXULファイル毎にPROPERTIESファイルを用意したり、わかりやすいように複数に分類してもかまわないでしょう。

XULファイルへ登録する。

PROPERTIESファイルの登録はそれが使われるXULファイル内で、stringbundleset要素とstringbundle要素を使って登録します。

以下のように登録することで、Javascriptのプログラム内からPROPERTIESファイルの内容を参照することができるようになります。

利用するPROPERTIESファイル毎にわかりやすい任意のidを決めてstringbundle要素を作ります。

例えば、idがhoge-bundle、PROPERTIESファイルがhoge.propertiesのときは、

<stringbundle id="hoge-bundle" src="chrome://hoge/locale/hoge.properties"/>

となります。

これを、PROPERTIESファイルの数だけ用意して(通常は一つでOK)、全体をstringbundleset要素で囲みます。このstringbundleset要素にも任意のid属性を指定しておきます。

<stringbundleset id="hoge-bundle-set">
   <stringbundle id="hoge-bundle" src="chrome://hoge/locale/hoge.properties"/>
</stringbundleset>

どの文字列を翻訳対象にするか。

Javascriptの書かれているjsファイル内から、文字列の部分を探し出します。これにはJavascriptの文法が分かっていなくてはいけません。また文字列をすべて抜き出してしまえばいいというものでもありません。表示もしくは音声による出力に関連するものや、外部からの入力に対するものなど、プログラムの動作を詳しく分析しながら、判断していきます。

このとき便利なのは、Javascriptの構文を認識し着色してくれるエディタですね。文字列部分を容易に見つけ出せます。もしくは検索で該当箇所を着色してくれる機能があるエディタです。検索には次のような正規表現を使えばいいでしょう。

("[^"]*"|'[^']*')

PROPERTIESファイルの書き方

XULファイル内で呼び出されているJavascriptファイルに対して、一つずつ翻訳対象の文字列がないか調べていきます。見つかったら、その情報を先ほどXULファイルに登録したPROPERTIESファイルに、記述していきます。

記述の仕方ですが、文字列を見つけたらそれを指し示す名前を決めます。万人のために英語的な名前にします。この名前の後に'='記号を置いて、さらにその文字列そのものを置きます。文字列を囲む引用符はいりません。

例えば、"Hello,World!"という文字列が見つかったら、PROPERTIESファイルに、

HelloWorld=Hello,World!

という行を追加します。

既に同じ文字列を示しているものがある場合は追加する必要はありません。ただし、同じ文字列だからといって、同じ意味で使われていないこともあります。

文字列の名前はそのXULファイルに登録してある複数のPROPERTIESファイル間で重複がないように決めていきます。

さて、このときの各行の細かな記法ですが(mozillaのコードを読んだわけでなく経験則です)、

左辺=右辺

とおくと、

左辺は

  • 行頭以降で空白以外の文字から始まり、=の左側で空白以外の文字で終わる文字列です。
  • この文字列の内部(文字列の最初、最後以外)に空白を含むことができます。
  • この文字列に=を含むことはできません。
  • この文字列にエスケープコードを含むことはできません。
  • 左辺がない場合(=が行頭、もしくは左側に空白文字以外無いとき)は、左辺は""と見なされます。

右辺は、

  • =以降で空白以外の文字から始まり、空白を含んでもよく、空白以外の文字で終わる文字列です。
  • この文字列の内部(文字列の最初、最後以外)に空白を含むことができます。
  • この文字列には=を含むことができます。
  • 行末に\がこない場合は、行末が終端になります。
  • 行末に\がくる場合は次の行へ継続します。継続されるのは先頭の空白以外の文字からとなります。
  • この文字列にはエスケープコードを含むことができます。
  • 右辺が無い場合、右辺は""と見なされます。

コメント行も作ることができます。

コメント行

  • 継続されていない行の、行頭(もしくは行頭のいくつかの空白文字のあと)に#のある行はコメント行になります。
  • それ以外の場所の#は文字と見なされます。
  • コメント行の行末に\を置いても、次の行に継続はされません。

右辺の文字列には変換指定を含むことができます。オリジナルのJSファイルで文字列の足し算を使って処理している部分などをこれを使って表現します。

PROPERTIESファイル内の変換指定について

文字列中に含むことができる変換指定は、%S です。%dや%xなども用意されているようですが、思い通りの値は出力されないようです。

%S は、文字列の式の値も、数値の式の値も表示してくれますので、実用上問題ないでしょう。なお小文字sを使った %s は最初の一文字だけを表示しました。

翻訳をする上で問題となるのは、語順の問題です。 原文と同じパラメータの順序で文章を作ることはできなくもありませんが、素直な翻訳文を作るためにはパラメータの順序を変えたいなという場面も多々あります。 そんなときは、%とSとの間に「数値$」を入れ、何番目のパラメータを対象にするのかを指定します。

%S, %S

%1$S, %2$S

と同じです。 これの逆に並べたものは、

%2$S,  %1$S

となります。

変換指定ではありませんが、mozillaのソース内で見つけたgetStringメソッドを用いた手法があります。それは、PROPERTIESファイルの右辺文字列中に%title%というふうな部分を作っておき、Javascriptのソースの方でそれをgetStringで取り込んだ後、文字列のreplaceメソッドを使って置き換えて使用する方法です。

例えば、プロパティ定義ファイルで

title=新規ファイル
message=%title%を作りました。

と定義して、Javascriptファイルで次のように使います。

var ttl = document.getElementById("foo").getString("title");
var mes = document.getElementById("foo").getString("message").replace(/%title%/,ttl);

プロパティ定義ファイルで何度も出てくる文字列に名前を付け定数化したり、いろんな応用が考えられます。

PROPERTIESファイルでの漢字等非ASCII文字の保存形式

現在、この手順は英語のプログラムの改造を書いているので問題はないのですが、 日本語のプログラムなど非ASCII文字の言語をローカリゼーション対応にしているときは、PROPERTIESファイルの保存形式が問題になってきます。

PROPERTIESファイル内の文字には非ASCII文字は使えません。 では、どうやってASCII文字列だけを使いながら、非ASCII文字列を表示するのかというと、 ユニコードエスケープシーケンスという表記法を使います。各文字に割り当てられた文字コードを直接表記していく方法です。 例えば

文書

\u6587\u66F8

となります。

ではこの変換はどうするのか、対応表を手に入れて手作業で置き換えるのは大変です。これには、RsoureceEditor?というJavaで書かれたエディタを使うと便利です。保存するときにASCII(UNICODE\uxxxx)を選べば、この形式で保存できます。 再び編集するときも、ちゃんとした文字の形に自動的に変換して見せてくれるので、人間はまったくこの変換に気をつかう必要はありません。

JSファイルの文字列を置き換える。

PROPERTIESファイルに文字列の対応リストができたら、この文字列を参照するようにJSファイルの内容を書き換えていきます。

注意:この作業はJavascriptの内容を直接書き換えていくので、より慎重におこなってください。引用符を消し間違えただけで、この拡張機能は使い物にならなくなってしまいます。一度に多くの文字列を書き換えずに、少しずつ動作を確認しながら、おこなった方が賢明です。

単純な文字列の場合と、文字列や数値のパラメータを実行時に組み込む文字列の場合があります。

まず、単純な文字列の場合

getStringメソッドを使います。このメソッドは文字列を引数としてとり、stringbundle内から名前としてさがし、対応する値を文字列で返します。

stringbundleを特定するためにgetElementById?メソッドを利用して、次のような式になります。

document.getElementById("foo").getString("bar")

stringbundleのidがfooで、PROPERTIESリスト内の要素名がbarであるときの例です。 これを対象の文字列と置き換えていきます。

PROPERTIESリスト内で次のように名前と文字列が対応しているとき、

bar=Hello,World!

そしてオリジナルのコードが次のとき、

shout("Hello,World!")

書き換え後はこのようになります。

shout( document.getElementById("foo").getString("bar") );

同じ文字列が繰り返し現れるときなどは、エディタについている確認付きの置換コマンドを利用したりしながら、丁寧にやっていきます。しかし一文字違っただけでプログラムは動かなくなったり望んでいる動作ができなくなりますので、とにかく慎重にします。

また、行が長くなるので、document.getElementById?("foo")を大域変数に代入しておき、それを活用するなど適宜自分のスタイルに書き換えてください。

変換指定付き文字列の場合

変換指定付きの文字列の場合、メソッドgetFormattedString?利用します。配置の仕方はgetStringと同じで、対象の文字列と置き換えるのですが、引数が一つ多くなります。第二引数に文字列に対するパラメータの配列がきます。パラメータは文字列もしくは数値をとることができます。

PROPERTIESファイルにおいて

message = %S means %S.

JSファイルにおいて次のように用います。

var number = 3;
var word   = "three";
shout( document.getElementById("foo").getFormattedString("message",[number,word]) );

プログラムの変更

プログラムによっては文字列の置き換えだけでは対応しきれない場合もあるかもしれません。その場合はロケールで条件分岐できるようにプログラムを作りかえて対処します。しかしこの方法だと新たにロケールを追加する毎に、プログラムを書き換えていかなくてはいけないので、あまりおすすめはできません。

PROPERTIESファイルの項目に、ロケールを表す文字列をフラグとして定義することで、簡易的に現在のロケールを獲得できます。

以上のようにローカリゼーション対応が済んだら、パッケージをまとめて一つのXPIファイルを作ります。

すでに一つのオリジナル言語ではローカライズが済んでいますが、必要に応じて下の方法によりローカライズしてください。

ローカライズ

以上の手順でローカリゼーション対応の機能拡張パッケージを作成できたら、翻訳したい言語で、ローカライズをしていきます。

何をなすべきかが分かっていれば、上記のローカリゼーション対応作業の中で同時並行で、以下の作業をおこなってもかまいません。

既にen-USロケールが用意されており、新たにja-JPロケールを追加していく例を示します。

install.rdfの修正

既に英語のロケールが用意されているはずなので、その行をコピーして次の行に貼り付けます。そしてen-USのところをja-JPで置き換えます。

このようになっているとき、

<em:file>
 <Description about="urn:mozilla:extension:file:hoge.jar">
  <em:locale>locale/en-US/</em:locale>
 </Description>
</em:file>

次のように行を追加します。

<em:file>
 <Description about="urn:mozilla:extension:file:hoge.jar">
  <em:locale>locale/en-US/</em:locale>
  <em:locale>locale/ja-JP/</em:locale>
 </Description>
</em:file>

そのほか、完全に日本語専用にするならば、em:description要素の内容を日本語に翻訳します。同様な翻訳は、contents.rdfファイル内のchrome:displayName、chrome:description属性の値に対してもおこないます。

ロケールフォルダの作成

localeフォルダを開き、その中にあるen-USというフォルダをコピーし、それにja-JPという名前を付けます。

DTDファイルの翻訳

ja-JPフォルダの中には英語で書かれたDTDという拡張子を持つファイルがあるはずです。このファイルを日本語化します。

このファイルの各行は、

<!ENTITY 名前 "文字列">

という形式をしています。 この文字列の部分を翻訳していきます。 そしてこのファイルをUTF8N形式で保存します。

PROPERTIESファイルの翻訳

ja-JPフォルダの中にはproperties拡張子を持ったファイルもあるでしょう。 これはJavascript内で使用する翻訳対象の文字列のリストです。 各行は次のような形式で書かれています。

「文字列名」=「文字列」

この文字列の部分を翻訳していきます。

文字列中に%Sがあるときは、プログラム側でパラメータを渡しそれをその場所に文字列として表示するものです。このとき、2つ以上の%Sがあって、日本語に翻訳するとどうしてもパラメータの順序を変えないといけないときは、%2$S、%1$Sのようなパラメータの番号を指定して使います。

このファイルは保存の時に注意があります。非ASCII文字列はユニコードエスケープシーケンス(\uxxxx)で表現しなくてはいけません。そのため、普通にファイルを作り変換するフィルタを通すか、最初からRsoureceEditor?など記録形式にユニコードエスケープシーケンスが選べるエディタを使って編集します。

XPIファイルの作り方

以上の作業が終わったら、それを一つのXPIファイルにします。 これには、How to create Firefox extensionsで紹介されているバッチファイルを利用します。 ただし、このバッチファイルを利用するには7-zipがインストールされ、パスが通っている必要があります。

set v=「バージョンなどの記述」
set x=%cd%
md build\chrome
cd chrome
7z a -tzip "%x%.jar" * -r -mx=0
move "%x%.jar" ..\build\chrome
cd ..
if not exist components\*.* goto skip
md build\components
copy components\*.* build\components
:skip
copy install.* build
cd build
7z a -tzip "%x%%v%.xpi" * -r -mx=9
move "%x%%v%.xpi" ..\
cd ..
rd build /s/q

このスクリプトにはバージョン情報が付け加えられるようにちょっと変更してあります。

この内容で新しいファイルを作り、build.batという名前を付けて保存します。 保存先は、install.rdfがある場所にします。 このbuild.batをダブルクリックするとXPIファイルが自動的に作られます。

これで新しいロケールに対応した拡張機能の完成です。


トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2014-10-29 (水) 02:23:35 (1871d)