Firefox拡張入門第8回(ローカライズ)
XULのローカライズにはdtdファイルを使い、Javascriptのローカライズにはpropertiesファイルを使います。
今回は、ローカライズした"hello,world."ボタン、つまり、"こんにちは、世界。"ボタンを作ってみましょう。
マッチFOXは"Strings.jsm"ライブラリをご用意していますので、簡単にpropertiesファイルを扱えます。
以下のファイルたちに手を加えてください。
<button oncommand="Sample.hello();" label="&Sample.sidebar.hello;"/>
const EXPORT = ["hello"]; function hello() { var strings = new Strings("chrome://sample/locale/sidebar.properties"); alert(strings.get("hello")); }
<!ENTITY Sample.sidebar.hello "Don't push me! Don't you dare push me!!">
<!ENTITY Sample.sidebar.hello "押すなよ!絶対に押すなよ!!">
- locale/en-US/sidebar.properties
hello = hello,world.
- locale/ja/sidebar.properties
hello = こんにちは、世界。
英語版Firefoxを起動して確認してみましょう。
firefox -UILocale "en-US" -no-remote
すばらしい。
Strings.jsm リファレンスマニュアル
function: Strings aPropertiesFile 新しいインスタンスを作ります。 aPropertiesFile StringBundleに使うpropertiesファイルのURI。文字列。 function: get aName &optional aArgs ローカライズ文字列を取得します。 aName 項目名。文字列。 aArgs printfのような文字列フォーマットに渡す引数。文字列の配列。
参考文献
- Firefox 3ではじめる拡張機能開発:第5回 localeパッケージによるローカライズ
- 作者: 高河ゆん
- 出版社/メーカー: 秋田書店
- 発売日: 1989/08
- メディア: コミック
- クリック: 2回
- この商品を含むブログ (3件) を見る
2chのレスをアンカで並びかえる
アンカで並び替えて、例えばこのように7の次に11を表示するような処理を説明します。
アリの餌集めのシミュレーション
友人と、子どもにコンピュータや数学に興味をもってもらうには、という話をしていて、
アリの餌集めなら、子どもに身近だし、群知能やランダムウォークに繋がるし面白いんじゃないか、となった。
Processingでもいいけど、ブラウザのJavascriptでCanvasを使うほうが簡単かな。
目標
- 子どもに、電子アリのプログラミングを楽しんでもらうこと。
- 子どもの創意工夫を邪魔しないこと。
- 結果を現実のアリでも説明できること。
で、こんなモデルはどうだろう。
電子アリのモデル
出題方法
- processという関数の中身をプログラムしてもらう。
- グローバル変数などで、他の電子アリと直接に値をやりとりするのは禁止。
- (グローバル変数を使うこと自体はOKだけど。とにかく、情報交換にはフェロモン描画を使ってください。)
- process関数は1秒間に1回、各電子アリごとに呼ばれる。
function process(aAntData, aProbedImageData, aFoundSugarsCount) { //この中身を書いてね //描画にはCanvas要素を使ってね。グローバル変数ctxに Canvas.getContext("2d")が入ってるよ。 } //引数aAntDataは以下のようなオブジェクト { id: 2, //ID x: 127, //現在の x 座標 y: 127, //現在の y 座標 carry: false //砂糖を運んでいるか }; //引数aProbedImageDataは以下のような配列 aProbedImageData[-1][-1] == [0,0,0,0] //左上の色。RGBA。これは黒。 aProbedImageData[ 0][-1] == [255,0,0,0] //上の色。これは赤。 ... aProbedImageData[ 1][ 1] == [255,0,0,127] //右下の色。これは半透明の赤。 //引数aFoundSugarsCountは周囲の砂糖の数。 //process関数は以下の値のいずれかを返すこと。 [-1,-1] //左上に動く [ 0,-1] //上 [ 1,-1] //右上 [-1, 0] //左 [ 0, 0] //動かない [ 1, 0] //右 [-1, 1] //左下 [ 0, 1] //下 [ 1, 1] //右下 "carry" //砂糖を拾う
実際に作ってみた
とりあえずランダムウォークする。
砂糖を見つけたら、まるで「あったぞーっ」て大声で叫ぶように、赤いフェロモンを出す。
それが赤のグラデーションになっているので、みんなで濃い赤に向かって進む。
ある程度濃い赤まで来たらランダムウォークで周りを歩いて他の砂糖を探す。
感想
- ちょっと子どもにはプログラムが難しすぎるし、アリの行列をなかなか拝めない。
- 好きに描画していいぞってのは面白いんだけどなー。
- 現実のアリには、こういう大声で叫んで仲間を集めるのはいないのかな?
- あ、天敵に見つかっちゃうか。
Firefox拡張入門第7回(独自プロトコルの定義 - ttp)
2ちゃんねるなどでリンク避けとして"ttp://..."を使うことがあります。
今回の拡張では、ttpプロトコルを定義して、"http://..."と同様に扱えるようにしましょう。
- ttpプロトコルを扱うXPCOMコンポーネントのクラスを登録します。
- そのクラスのnewURI関数で、URIの部品を受け取って、nsIURIのインスタンスを返します。(注)
- そのクラスのnewChannel関数で、↑で作ったnsIURIのインスタンスを受け取って、ttpプロトコルのためのnsIChannelのインスタンスを返します。ここではhttpプロトコルのnewChannel関数に処理を丸投げするので簡単です。
(注)"ここではhttpプロトコルのnewURI関数に処理を丸投げするので簡単です"・・・だと芸がないですもんね。
拡張のcomponentsディレクトリ以下に、jsファイルを置けば自動で認識してくれます。
//XPCOMコンポーネントを作るための便利ライブラリを使います。 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); //プロトコルを扱うクラス function TTProtocol() {} TTProtocol.prototype = { //クラスの説明 classDescription: "TTP Protocol", //XPCOMコンポーネントのID。 末尾の"...=ttp"に注目。 contractID : "@mozilla.org/network/protocol;1?name=ttp", //XPCOMコンポーネントのUUID。UUIDは各自で生成します。 classID : Components.ID("0bc360c0-a913-11de-8a39-0800200c9a66"), QueryInterface : XPCOMUtils.generateQI([Components.interfaces.nsIProtocolHandler]), //プロコトルのスキーム。 scheme: "ttp", //ポート番号は任意。HTTPと同様。 defaultPort: -1, //プロトコルの設定。HTTPと同様。 protocolFlags: Components.interfaces.nsIProtocolHandler.URI_STD | Components.interfaces.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE, //ポート番号は任意。 allowPort: function TTProtocolAllowPort(aPort, aScheme) { return false; }, //URIを処理する関数。 //部品を受け取ってnsIURIのインスタンスを返します。 newURI: function TTProtocolNewURI(aSpec, aCharset, aBaseURI) { var uri = Components.classes["@mozilla.org/network/standard-url;1"] .createInstance(Components.interfaces.nsIStandardURL); uri.init(Components.interfaces.nsIStandardURL.URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI); uri.QueryInterface(Components.interfaces.nsIURI); return uri; }, //通信チャンネルを作る関数。 //↑で作ったnsIURIのインスタンスを受け取ってnsIChannelのインスタンスを返します。 newChannel: function TTProtocolNewChannel(aURI) { var IOService = Components.classes["@mozilla.org/network/io-service;1"]. getService(Components.interfaces.nsIIOService); return IOService.newChannel("h" + aURI.spec, null, null); } }; //コンポーネントの生成。 function NSGetModule(compMgr, fileSpec){ return XPCOMUtils.generateModule([TTProtocol]); }
特にclassIDには、各コンポーネント固有のUUIDが必要なのでUUID (GUID) Generator on the WEBで生成してください。
newURI関数
この関数は、絶対アドレスと相対アドレスの両方を扱う役目があります。
絶対アドレスのときは、aSpecに文字列"http://.../main.html"、aBaseURIにnullが入っています。
相対アドレスのときは、aSpecに文字列"../images/01.jpg", aBaseURIにnsIURIのインスタンスで、specが"http://.../main.html"なものが入っています。
newURI関数は、これらの部品をもとに、nsIURIのインスタンスを作って返します。
newURI関数のnsIStandardURL
この部品をイチから料理するのは面倒です。
特に"http://..."の処理は複雑で、":80"があったり、"user@domain"があったり・・・。
似たり寄ったりの処理を"ftp://..."や"file://..."でも使うので、このnsIStandardURLがあります。
今回の"ttp://..."はhttpと同じなので、コイツに任せればおしまいです。
さらに柔軟にURIを作りたいときは、nsISimpleURIを使うこともあるようです。
独自プロトコルの使いどころ
ブラウザの窓の中に、"CSSとJavascriptを駆使したブラウザ的なページ"を作りはじめたら、
このテクニックが必要なサインです。ブラウザの中にブラウザを作っていませんか?
例えばGMailの画面は、gmailto:があるとスッキリする気がします。
Webブラウザの未来Web-based protocol handlersに期待しましょう。
Firefox拡張入門第6回(Database.jsmライブラリ)
マッチFOXに同梱しているDatabase.jsmライブラリは、SQLite用のORマッパです。tomblooが開発しました。
使用例
// Bookmarkモデルを生成。 var Bookmark = Entity({ name : 'bookmarks', fields : { id : 'INTEGER PRIMARY KEY', url : 'TEXT UNIQUE NOT NULL', title : 'TEXT', date : 'TIMESTAMP NOT NULL', last_visited : 'TIMESTAMP', comment : 'TEXT', } }) // データベースのファイル("ProfD/hogehoge/hogehoge.sqlite")を取得。 function dbFile() { var pd = DirectoryService.get("ProfD", Ci.nsIFile); pd.append("hogehoge"); if (!pd.exists() || !pd.isDirectory()) { pd.create(Ci.nsIFile.DIRECTORY_TYPE, 0755); } pd.append("hogehoge.sqlite"); return pd; } // Databaseインスタンスを生成 var db = new Database(dbFile()); // BookmarkモデルにDatabaseインスタンスをセット Bookmark.db = db; // Bookmarkモデルを初期化 Bookmark.initialize(); ... //Bookmark.insert 作成、 //Bookmark.find 検索、 //Bookmark.update 更新、 //Bookmark.deleteById 削除、などなど ... // データベースを閉じる db.close();
TIMESTAMP型、LIST型
TIMESTAMP型を指定すると、JavascriptのDateオブジェクトを透過的に読み書きできます。
(SQLiteには日付型がないので実際にはINTEGER型で"Date.getTime()の値"をデータベースに保存しています)
同様に、LIST型を指定すると、JavascriptのArrayオブジェクトを透過的に読み書きできます。
(実際にはTEXT型で"Arrayから作ったCSV的な文字列"を保存しています。)
便利。
findByFoo, findByFooAndBar, countByFoo、countByFooAndBar,
モデルのFooやBarの値で、検索やカウントができます。これは__noSuchMethod__をフックして実現してます。
すごい。
リファレンスマニュアル
Firefox拡張入門第5回(Prefs.jsmライブラリ)
マッチFOXが生成するPrefs.jsmは、Firefox拡張でユーザ設定(about:configのアレ)を簡単に読み書きできるライブラリです。
ユーザ設定とは
ユーザ設定の項目の値には型があるので気をつけます。
- boolean (真偽値)
- integer (整数)
- string (文字列)
- など。
項目名が他人様のとカブらないように気をつけます。
"ブランチ"にまとめるように心がけましょう。
例えば拡張で使う項目名には"extensions."ブランチを使いましょう。
例: "javascript.options.strict"オプションを扱う
1. ライブラリを new する。
//ブランチを指定します。ピリオドで終わるのがポイント。 var prefs = new Prefs("javascript.options.");
2. trueにする
prefs.set("strict", true);
3. 取得する
var v = prefs.get("strict");
項目の型はライブラリが自動で判断してくれます(手動で指定もできます)。
リファレンスマニュアル
function: Prefs aBranchName 新しいインスタンスを作ります。 aBranchName ブランチ名。文字列。ブランチ名はピリオドで終わる必要があります。 function: get aPrefName &optional aDefaultValue aType 項目の値を取得します。 aPrefName 項目名。文字列。 aDefaultValue 取得に失敗したとき返す値。 aType 項目の型。文字列。下表1参照。 function: set aPrefName aValue &optional aType aRelFileRelativeToKey 項目の値をセットします。 aPrefName 項目名。文字列。 aValue セットする値。 aType 項目の型。文字列。下表2参照。 aRelFileRelativeToKey 相対ファイルパスの元ディレクトリ。"ProfD"など。文字列。 function: clear aPrefName 項目を削除します。 aPrefName 項目名。文字列。 function: getChildList &optional aStartingAt ブランチ以下の項目名たちを配列で返します。 aStartingAt ブランチ名。文字列。
表1(getのaType)
型 | aType | 動作 |
---|---|---|
真偽値 | "boolean" | getBoolPref(aPrefName) |
整数 | "integer" | getIntPref(aPrefName) |
文字列 | "string" | getComplexValue(aPrefName, Ci.nsISupportsString).data |
地域化文字列 | "localized" | getComplexValue(aPrefName, Ci.nsIPrefLocalizedString).data |
絶対ファイルパス | "file" | getComplexValue(aPrefName, Ci.nsILocalFile) |
相対ファイルパス | "relFile" | getComplexValue(aPrefName, Ci.nsIRelativeFilePref) |
表2(setのaType)
型 | aType | 動作 |
---|---|---|
真偽値 | "boolean" | setBoolPref(aPrefName, !!aValue) |
整数 | "integer" | setIntPref(aPrefName, +aValue) |
文字列 | "string" | setComplexValue(aPrefName, Ci.nsISupportsString, nsISupportsStringのインスタンス) |
地域化文字列 | "localized" | setComplexValue(aPrefName, Ci.nsIPrefLocalizedString, nsIPrefLocalizedStringのインスタンス |
絶対ファイルパス | "file" | setComplexValue(aPrefName, Ci.nsILocalFile, aValue) |
相対ファイルパス | "relFile" | setComplexValue(aPrefName, Ci.nsIRelativeFilePref, nsIRelativeFilePrefのインスタンス) |
相対ファイルパスについてはFile I/O - MDC参照。
XMPPの概略(和訳)
XMPPはインスタントメッセージのプロトコルで、Google Talkが使っています。
今後はGoogle Waveの基盤としてますます重要性が増す要注目のテクノロジです。
そして!ついに!Google App EngineがXMPPをサポートしました!
そこかしこでGAEのXMPPサポートに賞賛の声が。
- 「Google App Engine SDK 1.2.5」リリース メッセージングのオープン標準「XMPP」をサポート:CodeZine
- App Engineと使うXMPPサーバーを探す - スティルハウスの書庫
- XMPP on Google App Engine - hidemonの日記
- civic site : Google App Engine の XMPPをPythonで書いてみる-2
- ぶいてく: 【Google App Engine】 ついにキター! TaskQueueとXMPP
XMPP標準化団体のXMPP Technologies: Overviewの和訳です。どぞー。
XMPPとは、Extensible(拡張性のある) Messaging(メッセージと) and Presence(プレゼンス) Protocol(プロトコル)です。このようなオープン技術の集まりでできています。
- インスタントメッセージ
- プレゼンス
- 多人数チャット
- 音声&ビデオ電話
- 協調作業
- コンテンツ・シンジケーション
- XMLデータの一般化ルーティング
XMPPはもともとJabberというオープンソース・コミュニティで開発されたもので、その目的は、オープンで、セキュアで、スパムが無いこと、そして、当時のクローズドなインスタントメッセージサービスの中央集権を崩すことにありました。XMPPは、そういったサービスへの突破口を用意しています。
- オープン
- XMPPプロトコルは、自由、オープン、公開、簡潔を旨とします。さらに、様々な形で複数の実装があります(クライアント、サーバ、サーバコンポーネント、コードライブラリ)。
- スタンダード
- インターネット技術タスクフォース(IETF)が、インスタントメッセージとプレゼンスの技術として合意を得て策定した、XMLストリームプロトコルです。XMPPの仕様はRFC3920、RFC3921として2004年に公開されました。また、XMPP標準化団体が続けてたくさんのXEPシリーズを公開しています。
- 実績
- Jabber/XMPP技術ははじめ Jeremie Miller が1998年に開発したもので、今では大変安定しています。数百の開発者がこの技術で仕事をし、数千のJabberサーバがインターネット上で動き、数万の人々がXMPPをインスタントメッセージに使っています。Google Talkをはじめ、世界中の組織がXMPPサービスを展開しています。
- 分散
- XMPPネットワークの設計は電子メールと似ています。つまり、誰でも自分のXMPPサーバを立ち上げることができ、個人や組織がコミュニケーションの活用を自己管理できるようになっています。
- セキュア
- XMPPサーバは外のネットワークから切り離せます(例えば企業のイントラネットなどで)。また、頑丈なセキュリティ(SASLとTLSによる)がXMPPのコア仕様に織り込み済みです。そして、XMPPネットワークには事実上スパムはありません。さらに、XMPP開発者は精力的に、エンド・ツー・エンドの暗号化でセキュリティの壁をさらに高くしようと励んでいます。
- 拡張性
- XMLのパワーによって、このプロトコルを土台にしてあなたオリジナルの機能を作ることができます。相互運用性を維持するため、定番の拡張はXEPシリーズとして公開していますが、特に公開が必須というわけでなく、内々でプライベートな拡張を持つことももちろんできます。
- 柔軟性
- XMPPアプリケーションは単なるIMにとどまりません・・・
- ネットワーク管理
- コンテンツ・シンジケーション
- 協調作業ツール
- ファイル共有
- ゲーム
- リモートシステム監視
- Webサービス
- 軽量ミドルウェア
- クラウドコンピューティング
- などなど・・・
- 多様性
- 広範な企業やオープンソース・プロジェクトが、XMPPを使って、リアルタイム・アプリケーションおよびサービスの構築、運用をしています。XMPP技術は決してあなたを"ロック・イン(囲い込み)"しません。
-
-
- -
-
以上です。