複数形リソースを使う場合の注意(otherについて)

冷静に考えれば、そりゃそうなるわな、という話なんですが、ハマったので整理しつつメモ。

# 結論

* 複数形リソース（[Quantity Strings (Plurals)](https://developer.android.com/guide/topics/resources/string-resource.html#Plurals)）を使う場合は、必ず`other`は定義すること。
    * 端末が日本語設定の場合は常に`other`しか使用されない。
    * `other`以外を使う言語の場合でも、数詞に対応する文字列リソースがなければ`other`を使うようfallbackしてくれる。
    * `other`すら無ければ、[Resources.NotFoundException](http://developer.android.com/reference/android/content/res/Resources.NotFoundException.html)で落ちる。
* Lintでも怒ってくれない様子。

# 例

複数形に対応しようとして、 `res/values/string.xml` に以下のように書いている。

```xml:res/values/string.xml
<plurals name="plural_book">
    <item quantity="one">Buy one book</item>
    <item quantity="other">Buy %1$d books</item>
</plurals>
```

非日本語ユーザーに対して、とりあえず英語で表示されるように、デフォルトの文字列リソースは英語にしてある。
日本語リソースはまだ作っていない状態。

この時、本体の言語設定を「日本語」にして実際に実行してみると、指定する数量に関係なく常に`other`の方が使われる。

```java
getResources().getQuantityString(R.plurals.plural_book, 1);    // → Buy %1$d books
getResources().getQuantityString(R.plurals.plural_book, 4, 4); // → Buy 4 books
```

なぜかというと日本語設定だから。
日本語には複数形がないので、常に`other`が使われる。

端末の言語設定を英語にして動かしてみると、ちゃんと切り替わる。

実際にアプリを作っている最中に、とりあえず`one`だけ定義してコードの方も数量が常に1になる状態で動かしたら、`other`が無くて落ちてしまった事があった。

# 仕様

## APIリファレンス

APIリファレンスにも、第2引数に渡された数に応じて、現在の言語に応じて適切なものを選択すると書いてある。

> *quantity* The number used to get the correct string for the current language's plural rules.
> [https://developer.android.com/reference/android/content/res/Resources.html#getQuantityString(int, int)](https://developer.android.com/reference/android/content/res/Resources.html#getQuantityString(int, int))

## Common Locale Data Repository

どの数詞を使うかは、UnicodeのCommon Locale Data Repositoryのルールに基づいて選択される。
この表では、Japaneseは常に`other`が使われる事になっている事が解る。

> http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html

実際のリソースの選択には、[International Components for Unicode](http://site.icu-project.org/)の[PluralRules](http://icu-project.org/apiref/icu4c/classicu_1_1PluralRules.html)クラスが使用されている(Resourcesクラスの実装参照)。

## Resources#getQuantityText

ドキュメントに明記されている箇所を見つけることは出来なかったが、実装上は`zero`や`one`などに対応するリソースを見つけられない場合は`other`を使用するようになっている。
`other`すら見つけられない場合は[Resources.NotFoundException](http://developer.android.com/reference/android/content/res/Resources.NotFoundException.html)になる。

> https://android.googlesource.com/platform/frameworks/base/+/android-4.4.4_r1/core/java/android/content/res/Resources.java#248

# 実用例

拙作の絵文字入力アプリでは、入力しようとしている文字数に応じてメッセージを切り替えるために複数形リソースを使用している。

先の例と同様に、デフォルトの言語リソースは英語で作成している。
`one`の数詞が無い言語(中国語とか)では、文字数に関係なく常に「Use Emojis」と複数形で表示されてしまうが、キリがないので気にしていない。

```xml:res/values/strings.xml
<plurals name="message_use_emojis">
    <item quantity="one">Use Emoji</item>
    <item quantity="other">Use Emojis</item>
</plurals>
```

日本語用のリソースでは`other`だけ定義してある。

```xml:res/values-ja/strings.xml
<plurals name="message_use_emojis">
    <item quantity="other">絵文字を使う</item>
</plurals>
```

# 参考

* Resources | Android Developers  
  https://developer.android.com/reference/android/content/res/Resources.html
* String Resources | Android Developers  
  https://developer.android.com/guide/topics/resources/string-resource.html
* Common Locale Data Repository - Wikipedia  
  http://ja.wikipedia.org/wiki/Common_Locale_Data_Repository