Localization and Plurals

あなたは恐らく .properties ファイルをローカライズしようとして、そこにあったリンクからこのページにたどり着いたことと思います。このページでは、.properties ファイルに含まれる文字列をローカライズする際に、"1 page" や "2 pages" のように正しい複数形がユーザーに表示されるようにする方法を説明します。

もしあなたが拡張機能などのコードを複数形を考慮してローカライズ可能にしたいなら、PluralForm を使った開発の節に飛んでも結構です。ただコードの初期文字列をローカライズする必要があるでしょうから、少なくとも「使用方法」の節は読んでおくと良いでしょう。

使用方法

このページでは、説明をわかりやすくするために 2 つの用語を使用しています。

  • 複数規則 (plural rule): 言語には、単語を修飾する数字に応じて単語を変更する文法規則があります。言語が違えば規則も異なることがあります。
  • 複数形 (plural form): それぞれの複数規則には、"page" と "pages" のように複数の単語の形式があり得ます。この場合は 2 つの形式がありますが、他の言語では 1 つだったり、もっと多くの形式がある場合もあります。

もしあなたが <tt>chrome/global/intl.properties</tt> ファイルの <tt>pluralRule</tt> を見てこのページに来たなら、あなたのローカライゼーションでどの複数規則を選ぶべきなのかを知る必要があるでしょう。複数規則は、複数形を考慮する必要がある単語をローカライズするときに、複数形がいくつ必要なのかを知るために使用します。

その他の properties ファイルに書かれていたリンクからこのページに来たのなら、ローカライズする単語に対して、必要な分の複数形をセミコロン (;) 区切りで与える必要があるでしょう。複数形がいくつ必要なのかわからなければ、<tt>chrome/global/intl.properties</tt> の <tt>pluralRule</tt> の数値を調べ、以下の複数規則の一覧でその数値に対応するエントリを探してください。

複数規則の一覧

この節では、複数規則をその番号順にリストアップします。各エントリには、単語をローカライズする際に必要な複数形の数が示されています。また、<tt>pluralRule</tt> にどの番号を入力すればいいのかがわかりやすいように、語族およびそれに属する言語の一覧も載せています。さらに、それぞれの複数形の簡単な説明と、その形式に分類される数の例も掲載しています。

それぞれの複数規則において、複数形がリストされている順番は単語をローカライズする際にセミコロン区切りで入力する順番と同じです。例えば、英語では複数規則 1 を使用します。したがって、<tt>plurals</tt> という単語をローカライズするときには、"plural;plurals" のようにして、一つめの単語に単数形を、二つめには汎用の複数形を入力する必要があるでしょう。

複数規則 #0 (1 形式)

語族: アジア (中国語, 日本語, 韓国語, ベトナム語), チュルク/アルタイ諸語 (トルコ語)
すべて: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, …

複数規則 #1 (2 形式)

語族: ゲルマン語派 (デンマーク語, オランダ語, 英語, フェロー語, フリジア語, ドイツ語, ノルウェー語, スウェーデン語), フィン・ウゴル語派 (エストニア語, フィンランド語, ハンガリー語), 孤独語 (バスク語), ラテン/ギリシャ (ギリシャ語), セム語派 (ヘブライ語), ロマンス諸語 (イタリア語, ポルトガル語, スペイン語, カタルーニャ語)
1 である: 1
それ以外: 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, …

複数規則 #2 (2 形式)

語族: ロマンス諸語 (フランス語, ブラジルポルトガル語)
0 か 1 である: 0, 1
それ以外: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, …

複数規則 #3 (3 形式)

語族: バルト語派 (ラトビア語)
0 である: 0
1 で終わり、11 で終わらない: 1, 21, 31, 41, 51, 61, 71, 81, 91, 101, 121, 131, 141, 151, 161, 171, 181, 191, 201, 221, 231, 241, 251, 261, 271, 281, 291, …
それ以外: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 52, 53, 54, 55, …

複数規則 #4 (3 形式)

語族: ケルト語派 (スコットランド・ゲール語)
1 である: 1
2 である: 2
それ以外: 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, …

複数規則 #5 (3 形式)

語族: ロマンス諸語 (ルーマニア語)
1 である: 1
0 であるか、01-19 で終わる: 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, …
それ以外: 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, …

複数規則 #6 (3 形式)

語族: バルト語派 (リトアニア語)
1 で終わり、11 で終わらない: 1, 21, 31, 41, 51, 61, 71, 81, 91, 101, 121, 131, 141, 151, 161, 171, 181, 191, 201, 221, 231, 241, 251, 261, 271, 281, 291, …
0 で終わるか、10-20 で終わる: 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, …
それ以外: 2, 3, 4, 5, 6, 7, 8, 9, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 49, 52, 53, 54, 55, 56, 57, 58, 59, 62, 63, 64, 65, 66, 67, 68, 69, 72, 73, …

複数規則 #7 (3 形式)

語族: スラヴ語派 (クロアチア語, セルビア語, ロシア語, ウクライナ語)
1 で終わり、11 で終わらない: 1, 21, 31, 41, 51, 61, 71, 81, 91, 101, 121, 131, 141, 151, 161, 171, 181, 191, 201, 221, 231, 241, 251, 261, 271, 281, 291, …
2-4 で終わり、12-14 で終わらない: 2, 3, 4, 22, 23, 24, 32, 33, 34, 42, 43, 44, 52, 53, 54, 62, 63, 64, 72, 73, 74, 82, 83, 84, 92, 93, 94, 102, 103, 104, 122, 123, 124, 132, 133, 134, 142, 143, 144, 152, 153, 154, 162, 163, 164, 172, 173, 174, 182, 183, …
それ以外: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, 27, 28, 29, 30, 35, 36, 37, 38, 39, 40, 45, 46, 47, 48, 49, 50, 55, 56, 57, 58, 59, 60, 65, 66, 67, 68, 69, 70, 75, 76, 77, …

複数規則 #8 (3 形式)

語族: スラヴ語派 (スロバキア語, チェコ語)
1 である: 1
2-4 である: 2, 3, 4
それ以外: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, …

複数規則 #9 (3 形式)

語族: スラヴ語派 (ポーランド語)
1 である: 1
2-4 で終わり、12-14 で終わらない: 2, 3, 4, 22, 23, 24, 32, 33, 34, 42, 43, 44, 52, 53, 54, 62, 63, 64, 72, 73, 74, 82, 83, 84, 92, 93, 94, 102, 103, 104, 122, 123, 124, 132, 133, 134, 142, 143, 144, 152, 153, 154, 162, 163, 164, 172, 173, 174, 182, 183, …
それ以外: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 25, 26, 27, 28, 29, 30, 31, 35, 36, 37, 38, 39, 40, 41, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59, 60, 61, 65, 66, 67, 68, …

複数規則 #10 (4 形式)

語族: スラヴ語派 (スロベニア語, ソルブ語)
01 で終わる: 1, 101, 201, …
02 で終わる: 2, 102, 202, …
03-04 で終わる: 3, 4, 103, 104, 203, 204, …
それ以外: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, …

複数規則 #11 (5 形式)

語族: ケルト語派 (アイルランド・ゲール語)
1 である: 1
2 である: 2
3-6 である: 3, 4, 5, 6
7-10 である: 7, 8, 9, 10
それ以外: 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, …

複数規則 #12 (4 形式)

語族: セム語派 (アラビア語)
1 である: 1
2 である: 2
0 もしくは 3-10 である: 0, 3, 4, 5, 6, 7, 8, 9, 10
それ以外: 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, …

複数規則 #13 (4 形式)

語族: セム語派 (マルタ語)
1 である: 1
0 であるか、01-10 で終わる: 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, …
11-19 で終わる: 11, 12, 13, 14, 15, 16, 17, 18, 19, 111, 112, 113, 114, 115, 116, 117, 118, 119, 211, 212, 213, 214, 215, 216, 217, 218, 219, …
それ以外: 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, …

複数規則 #14 (3 形式)

語族: スラヴ語派 (マケドニア語)
1 で終わる: 1, 11, 21, 31, 41, 51, 61, 71, 81, 91, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 201, 211, 221, 231, 241, 251, 261, 271, 281, 291, …
2 で終わる: 2, 12, 22, 32, 42, 52, 62, 72, 82, 92, 102, 112, 122, 132, 142, 152, 162, 172, 182, 192, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, …
それ以外: 0, 3, 4, 5, 6, 7, 8, 9, 10, 13, 14, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 46, 47, 48, 49, 50, 53, 54, 55, 56, 57, 58, 59, 60, 63, …

以下ではいくつかの言語を例に取り、大まかな思考プロセスを解説します。

フランス語

フランス語では通常 0 を単数として扱いますが、フランス語圏の中には複数として扱う地域もあります。その他の単数は 1 だけで、残りはすべて複数です。したがって、複数規則 #1 または #2 を選択します。

pluralRule=2
seconds=seconde;secondes
minutes=minute;minutes
hours=heure;heures
days=jour;jours

他の単語をローカライズする時と同様に、常に性が一致するように単語を調整する必要があるかもしれません。(secode と jour のように)

中国語

前にどんな数字があっても単語は変化せず、すべての数字に対して同じ複数形が使用されます。複数形が 1 つだけの言語では、複数規則 #0 を適用します。各単語をローカライズする際にはセミコロンは必要なく、単一の単語と同様にローカライズします。

pluralRule=0
seconds=秒
minutes=分
hours=時
days=日

ポーランド語

1 には単数形を使い、2-4 には複数形を、5-21 にはまた別の複数形を使い、22 になると 2 と同じに戻ります。複数規則 #7 には「2-4 で終わり、12-14 で終わらない」複数形がありますが、単数形を使用する数字に 1 で終わり 11 で終わらない数字すべてが含まれます。複数規則 #9 の単数形は 1 のみなので、これを使うのが適切です。

pluralRule=9
seconds=sekunda;sekundy;sekund
minutes=minuta;minuty;minut
hours=godzina;godziny;godzin
days=dzień;dni;dni

"day" の複数形の最後の 2 つは同じものですが、各単語に対して 3 つの複数形を記入する必要があるので、両方を記入しなければなりません。

ソルブ語

主格単数、主格双数、主格複数、属格複数という 4 つの複数形があります。これらは複数規則 #10 に調和します。

pluralRule=10
seconds=sekunda;sekundźe;sekundy;sekundow
minutes=mjeńšina;mjeńšinje;mjeńšiny;mjeńšin
hours=hodźina;hodźinje;hodźiny;hodźin
days=dźeń;dnjej;dny;dnjow

テスト用の拡張機能

正しい複数規則を選び、文字列に対して十分な複数形を与えられるようにするには、拡張機能 pluralForm Checker を使用するのがいいでしょう。拡張機能をインストールしたら、[ツール]メニューから使用できます。

使用するには、プロパティファイルとチェックしたいプロパティを列挙し、ボタンを押します。すると拡張機能が各プロパティを読み込み、表に複数形を表示します。表のエントリを選択すると、下部のボックスにいくつかの数字に対する単語の使用例が表示されます。

Image:pluralForm-checker.0.3.png

拡張機能 pluralForm Checker v0.3 をインストール

拡張機能への入力

拡張機能を使う人たちがコピー&ペーストして入力できるように、複数形が必要な単語をここにリストアップして更新し続けるのが良いでしょう。

chrome://mozapps/locale/downloads/do...tes,hours,days
chrome://mozapps/locale/downloads/do...dsTitlePercent
chrome://browser/locale/browser.prop...ausedDownloads

更新履歴

0.1: 最初のバージョン。pluralRule のチェック、入力されたプロパティの読み込み、表の生成、例を出力して表示
0.2: 将来の規則に対応するため、形式の数を得るのにローカルに計算するのではなく PluralForm.numForms() を使用するように - 2007/01/27 以降のビルドが必要
0.3: どの数字がどの複数形に分類されるかを示すリストを生成する際、例の出力を各形式ごとに最大 3 つに縮小した

PluralForm を使った開発

正しい複数形を得る機能は、JavaScript モジュール <tt>PluralForm.jsm</tt> によって提供されます。このモジュールにはブラウザの現在のロケールに合わせてローカライズするためのメソッドと、指定された複数規則に合わせてローカライズするためのメソッドが用意されています。後者の複数規則を指定する機能は、拡張機能で使用するのが便利です。なぜなら拡張機能は必ずしもブラウザのロケールに合わせてローカライズする必要はないからです。

<tt>PluralForm.jsm</tt> の読み込み

PluralForm モジュールは、Components.utils.import を使って JavaScript から簡単に読み込めます。以下の行を、PluralForm を使用したい部分よりも前に評価される場所に設置するだけです。JavaScript ファイルの先頭が良いでしょう。

Components.utils.import("resource://gre/modules/PluralForm.jsm");

メソッド: <tt>get</tt> と <tt>numForms</tt>

これらのメソッドは、<tt>chrome://global/locale/intl.properties</tt> にある <tt>pluralRule</tt> の値で指定されているブラウザの現在のロケールを使用します。

/**
 * 数値をもとにして単語の正しい複数形を得る
 *
 * @param aNum
 *        どの複数形を使用するかを決定する数値
 * @param aWords
 *        複数形を取り出すための、単語をセミコロン (;) で区切った文字列
 * @return 単語の適切な複数形
 */
string pluralForm
get(int aNum, string aWords)
/**
 * 現在の複数規則の形式の数を得る
 *
 * @return 形式の数
 */
int numForms
numForms()

以下はこれらのメソッドの使用例です。

// PluralForm を読み込む。この例では英語を想定している
Components.utils.import("resource://gre/modules/PluralForm.jsm");

// PluralForm.get はセミコロン区切りの単語のリストを要求する
let forms = "form;forms";
// この数値をもとに正しい複数形を取り出そうとしている
let numForms = PluralForm.numForms();

// "forms" に対しての正しい複数形を表示する
print("This locale has " + numForms + " " + PluralForm.get(numForms, forms) + ".");

上の例は機能しますが、特定の文法構造を想定して文字列を連結しているので、ローカライズが難しくなります。次のようにするのがいいでしょう。

Components.utils.import("resource://gre/modules/PluralForm.jsm");

let forms = "This locale has one form.;This locale has #1 forms.";
let numForms = PluralForm.numForms();

// 英語の場合、"This locale has 2 forms." と表示される
print(PluralForm.get(numForms, forms).replace("#1", numForms);

この例ではプレースホルダに対応したコードを書け、また文字列の形式によってはプレースホルダを使用しないこともできるということに注目してください。それに加え、ローカライザーがテキストのほかの部分に合わせてプレースホルダの位置を調整できるようになります。

もちろん、ローカライズする文字列は JavaScript ファイルにハードコードするのではなく、 yourextension.properties のような別のファイルに置かれることのほうが多いでしょう。

以下の 3 つのファイル片は、<tt>.xul</tt>、 <tt>.properties</tt>、 <tt>.js</tt> で PluralForm を使用する方法を示しています。

<tt>downloads.xul</tt>:

<stringbundleset>
  <stringbundle id="strings" src="chrome://downloads.properties"/>
</stringbundleset>

<tt>downloads.properties</tt>:

# LOCALIZATION NOTE (downloadsTitleFiles): セミコロン区切りの複数形のリスト
# 参照: http://developer.mozilla.org/en/docs/Localization_and_Plurals
# #1 ファイルの数
# 例: 111 files - Downloads
downloadsTitleFiles=#1 file - Downloads;#1 files - Downloads

# LOCALIZATION NOTE (timePair): #1 時間の数値; #2 時間の単位
# 例: 1 second; 11 seconds
timePair=#1 #2
seconds=second;seconds

<tt>downloads.js</tt>:

Components.utils.import("resource://gre/modules/PluralForm.jsm");
let getStr = function(string) document.getElementById("strings").getString(string);

// タイトル用に正しい複数形を得る
let numDownloads = 3;
let title = PluralForm.get(numDownloads, getStr("downloadsTitleFiles"));
// 正しいダウンロード数を挿入する
print(title.replace("#1", numDownloads));

// 秒数の正しい複数形を得る
let timeLeft = 55;
let seconds = PluralForm.get(timeLeft, getStr("seconds"));
// ローカライズされた文字列 "55 seconds" を出力する
print(getStr("timePair").replace("#1", timeLeft).replace("#2", seconds));

メソッド: <tt>makeGetter</tt>

拡張機能を書いているのなら、<tt>PluralForm.get()</tt> または <tt>PluralForm.numForms()</tt> ではなく <tt>makeGetter</tt> を使うのがいいでしょう。なぜなら、異なるロケールに拡張機能をインストールする人は、拡張機能のデフォルトのロケールが提供する文字列を使用することになるからです。例えば、拡張機能が複数規則 #1 (2 つの複数形を要求する) に属する英語にローカライズされており、それが複数規則 #4 (3 つの複数形を要求する) に属する言語にローカライズされたバージョンの Firefox にインストールされた場合などです。

/**
 * 与えられた複数規則番号に対応する複数形関数のペアを生成する
 *
 * @param aRuleNum
 *        関数を生成するための複数規則番号
 * @return ペア: [正しい複数形を得るための関数,
 *                複数形の数を返す関数]
 */ 
[string pluralForm get(int aNum, string aWords), int numForms numForms()]
makeGetter(int aRuleNum)

以下は <tt>makeGetter</tt> の使用例です。

Components.utils.import("resource://gre/modules/PluralForm.jsm");

// アイルランド語 (複数規則 #11) を取得しよう
let [get, numForms] = PluralForm.makeGetter(11);

// "get" に使用する値を作成する
let dummyText = "form 1;form 2;form 3;form 4;form 5";
let dummyNum = 10;

// アイルランド語の場合 10 という数値は複数形 #4 を使用するので、"form 4" が出力される
print(get(dummyNum, dummyText));

この例ではアイルランド語の複数規則をハードコードしていますが、これには .properties ファイルに指定された値を使用できます。よって拡張機能では、.properties 内の pluralRule の値を指定し、<tt>PluralForm.makeGetter(pluralRuleFromProperties)</tt> を呼び出して、返される 2 つの関数が保存されるようにしてください (JavaScript 1.7 の 分割代入を使うときれいに書けます。)。 返される関数は <tt>PluralForm.get()</tt> および <tt>PluralForm.numForms()</tt> と同じ働きをしますが、デフォルトの複数規則ではなく指定された複数規則を使用する点が異なります。

クレジット

Plural Form のコードは最初に バグ 394516 - 残り時間を分から時間/日に丸める仕組みを考案する のために実装されました。
複数規則と語族の一覧は GNU <tt>gettext</tt> のドキュメントから引用しました。




Document Tags and Contributors

Contributors to this page: Shoot, Mgjbot
最終更新者: Mgjbot,