fFireVoxにもどる
このコンテンツは現在執筆中です。
FireVoxを日本語化したときの工程や、資料をまとめます。 日本語ロケールファイルを付け加える作業だけではなく、 ローカリゼーション機構のない拡張にlocalフォルダを作り多言語対応にする方法です。 一からローカリゼーション対応の拡張を作るときにも役に立つでしょう。
これは私がこのようにやったという報告であって、正攻法ではないかもしれません。 実際にやるときは、概略だけを参考にして、自分でスクリプトを書いて自動化したり、いろいろやってみてください。
主に以下のサイトを参考にしました。他にも記録していないページを参考。
ここにあるページの情報を見れば、自分がまとめる必要もないかもしれない。
ここにあるサイトは古い情報が含まれている可能性があります。事実そのために手こずったところもあります。
ローカリゼーションを実現するために、拡張機能のパッケージにいくつかの新しいファイルやフォルダを追加し、既にあるファイルにいくつかの記述を追加していく必要があります。
パッケージの構成を記述してあるファイルです。拡張機能マネージャーというプログラムは、このファイルにある記述を利用して、自動的に拡張機能をfirefoxの機能として組み込んでいきます。なおこのファイルはXMLで書かれています。
拡張機能のユーザーインターフェイス部分、つまりメニューの項目やウィンドウ上のボタンの配置、そして処理の指定など、そういうものを記述してあるのが、XULファイルです。
このXULファイルには、ウィンドウのラベルやメニューの項目など、翻訳の対象となる文字列があります。
このファイルはXMLで書かれています。 ウィンドウ上の言葉や、メニューの項目名がどのような形でXULファイル上に記載されているかは、XML言語の文法、XUL言語の要素や属性についての知識が必要になってきます。
翻訳の可能性があるのは、次の箇所です。
accesskey 属性は、日本語においては英語のものを訳に関係なくそのまま利用していますが、ヨーロッパの言語などでは、訳に伴い置き換えられる可能性がありますので、置き換え可能な対象にしておく必要があります。
上記の属性を眺めてみて、翻訳の必要なものを探していきます。 そしてその文字列を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-8形式を指定して保存します。
DTDファイルを作成したら、その内容を参照するXULファイル内には DOCUTYPE宣言を追加しておきます。
拡張foo で foo.dtd というDTDファイルを指定する場合、
<!DOCTYPE window SYSTEM "chrome://foo/locale/foo.dtd">
のようになります。上記の文書タイプ名windowの他に、このあと記述されるトップレベル要素overlay, dialog, wizard が記入されます。
各翻訳対象の文字列は、次の実体宣言形式で書いていきます。
<!ENTITY 名前 "文字列">
文字列が実際に表示される文字列そのもので、名前がその文字列を参照するための名前です。この文字列の部分を別の言語に翻訳したDTDファイルを用意することで、ウィンドウやメニューに現れる言葉を各言語に対応させていくことができます。
ここで宣言された名前をXULファイル中で参照するには、その名前を &と;で挟んで指定します。
DTDファイルで次のように定義された場合、
<!ENTITY hoge "click me">
XULファイル内のとある部分では、次のように参照できます。
<button label="&hoge;"/>
このENTITY名には、'.'を入れたドット記法が使えるので、拡張名、XUL要素名、要素のidなどを組み合わせて、わかりやすい一意の名前を付けていきます。
このようにして、XULファイルをローカリゼーション対応にします。
拡張の動作内容を記述しているのがJS拡張子を持つJavascriptファイルです。このJavascriptで出力される文字列もローカリゼーションの対象となります。
作業の対象は、以下の3種類のファイルです。
おおまかな手順は次の通りです。
それでは、細かな手順を示します。
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を付けます。
例えば、拡張機能hogeを作っているときは、hoge.properites とします。
またXULファイル毎にPROPERTIESファイルを用意したり、わかりやすいように複数に分類してもかまわないでしょう。
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の構文を認識し着色してくれるエディタですね。文字列部分を容易に見つけ出せます。もしくは検索で該当箇所を着色してくれる機能があるエディタです。検索には次のような正規表現を使えばいいでしょう。
("[^"]*"|'[^']*')
XULファイル内で呼び出されているJavascriptファイルに対して、一つずつ翻訳対象の文字列がないか調べていきます。見つかったら、その情報を先ほどXULファイルに登録したPROPERTIESファイルに、記述していきます。
記述の仕方ですが、文字列を見つけたらそれを指し示す名前を決めます。万人のために英語的な名前にします。この名前の後に'='記号を置いて、さらにその文字列そのものを置きます。文字列を囲む引用符はいりません。
例えば、"Hello,World!"という文字列が見つかったら、PROPERTIESファイルに、
HelloWorld=Hello,World!
という行を追加します。
既に同じ文字列を示しているものがある場合は追加する必要はありません。ただし、同じ文字列だからといって、同じ意味で使われていないこともあります。
文字列の名前はそのXULファイルに登録してある複数のPROPERTIESファイル間で重複がないように決めていきます。
さて、このときの各行の細かな記法ですが(mozillaのコードを読んだわけでなく経験則です)、
左辺=右辺
とおくと、
左辺は
右辺は、
コメント行も作ることができます。
コメント行
右辺の文字列には変換指定を含むことができます。オリジナルのJSファイルで文字列の足し算を使って処理している部分などをこれを使って表現します。
文字列中に含むことができる変換指定は、%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);
プロパティ定義ファイルで何度も出てくる文字列に名前を付け定数化したり、いろんな応用法が考えられます。
現在、この手順は英語のプログラムの改造を書いているので問題はないのですが、 日本語のプログラムなど非ASCII文字の言語をローカリゼーション対応にしているときは、PROPERTIESファイルの保存形式が問題になってきます。
PROPERTIESファイル内の文字には非ASCII文字は使えません。 では、どうやってASCII文字列だけを使いながら、非ASCII文字列を表示するのかというと、 ユニコードエスケープシーケンスという表記法を使います。各文字に割り当てられた文字コードを直接表記していく方法です。 例えば
文書
は
\u6587\u66F8
となります。
ではこの変換はどうするのか、対応表を手に入れて手作業で置き換えるのは大変です。これには、RsoureceEditor?というJavaで書かれたエディタを使うと便利です。保存するときにASCII(UNICODE\uxxxx)を選べば、この形式で保存できます。 再び編集するときも、ちゃんとした文字の形に自動的に変換して見せてくれるので、人間はまったくこの変換に気をつかう必要はありません。
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ファイルの項目に、ロケールを表す文字列をフラグとして定義することで、簡易的に現在のロケールを獲得できます。
以上の手順でローカリゼーション対応の機能拡張パッケージを作成できたら、翻訳したい言語(今回は当然日本語)で、ローカライズをしていきます。
何をなすべきかが分かっていれば、上記のローカリゼーション対応作業の中で同時並行で、以下の作業をおこなってもかまいません。