Fürstentum L10n #3

l10n のだいたいの形が決まったので、その通りに組んでみた。

おさらいする。3 種のブラウザで同様に動く l10n の仕組みを wasavi に組み込むのが目的。3 種のブラウザがそれぞれ l10n の仕組みを備えているが、wasavi 上では Chrome のそれを基本にし、他のブラウザでは Chrome の仕組みをエミュレートする形。Chrome の l10n の仕組みとは、エクステンションのアーカイブ内に _locales/[localeCode]/messages.json といったファイルを配置し、その json ファイルにメッセージ ID とそれに対応する各言語のテキストを格納し、変換は、wasavi 実行中に動的に行うというもの。

それに加えて、wasavi 独自の仕組みがある。

  • メッセージへのパラメータの埋め込み。平たく言うと sprintf() だ。これは Chrome が提供する i18n にも用意されているが、wasavi 側で行う。メッセージ中の {0} といった部分は、パラメータで置き換えられる(数値はパラメータのインデックス)。
  • メッセージ中、複数形になりうる名詞の変換。1 行削除したときは
    deleted 1 line.
    それ以上の行を削除したときは
    deleted 10 lines.
    のように自然な形のメッセージを生成する。ソース上は、メッセージは “deleted {0} {line:0}.” と記述する。{word:number} の形式だ。ここでも number はパラメータのインデックス。パラメータの値によって word を自然な形に変化させ、波かっことその中身全体を、生成した word で置き換える。

    これには、以下のものが必要になる:

    1. パラメータを引数にとって、変化パターンを返す関数
    2. 各変化パターンに対応する word の変化形

    これらの情報もまた、messages.json に格納する。まず 1. は、Language Plural Rules を参考に生成する。例えば英語の場合は

    Language Name Code Category Examples Rules
    English en one 1 one → n is 1;
    other → everything else
    other 0, 2-999;
    1.2, 2.07…

    ということである。変換関数は Rules を、変化パターンは Category を見ればいい。まず変換関数は、Rules に対応する javascript の式を書く。n が 1 の場合は ‘one’、それ以外は ‘other’(実際は、空文字で代用)を返すようにする。

    {
    "_plural_rule@function": {
    "message": "n==1?'one':''"
    }
    }

    そして、全メッセージ中で使用している複数形になりうる単語について、one パターンと other パターンのそれぞれを定義する。

    {
    "_plural_substitution": {
    "message": "substitutions"
    },
    "_plural_substitution@one": {
    "message": "substitution"
    },
    "_plural_line": {
    "message": "lines"
    },
    "_plural_line@one": {
    "message": "line"
    },
    "_plural_character": {
    "message": "characters"
    },
    "_plural_character@one": {
    "message": "character"
    },
    "_plural_operation": {
    "message": "operations"
    },
    "_plural_operation@one": {
    "message": "operation"
    }
    }

    メッセージ ID は “_plural_” + word の基本形 + @ + 変化パターンとなる。この後ろに、通常のメッセージ群についてメッセージ ID と変換結果を全て記述する。

    {
    "invalid_boolean_value": {
    "message": "Invalid boolean value",
    "description": "Invalid boolean value"
    },
    :
    :
    :
    "top_of_history": {
    "message": "Top of history.",
    "description": "Top of history."
    }
    }

    messages.json 側でやることは以上。

で、Chrome ではメッセージ ID を変換するには chrome.i18n.getMessage() を呼ぶだけでよいのだが、他のブラウザではそうは行かない。

  • Opera
    フォルダベースの l10n 機能を利用する。background の起動時に XHR でエクステンションアーカイブ内の /messages.json を読み込む。実際は、メッセージカタログは locales/[localeCode]/messages.json に配置してあり、自動的にロケールに応じたファイルが参照される。wasavi 起動時にメッセージカタログの内容を wasavi.js へ送信する。wasavi.js 側でメッセージが必要になった際は、自分でカタログの中から探し出す。
  • Firefox
    メッセージカタログは data/xlocale/[localeCode]/messages.json へ配置する。現在のロケールを得るために api-utils/l10n/locale モジュールの getPreferedLocales() を使う。また、有効なロケール群から現在のロケールに最もふさわしいロケールを抜き出すためにも、上記のモジュールが提供する findClosestLocale() メソッドを使う。これ以外に、標準的な l10n の機能は使わない。
    その他の仕組みは、Opera と共通。

というわけで、とりあえず日本語ロケールのメッセージを作ってみた。

Leave a Reply

Your email address will not be published. Required fields are marked *