android plurals用法(單複數)

0、相關文章

android plurals用法

Android中的string資源佔位符及Plurals string

1、使用

對一個給定的語言和數字來說,決定使用哪一個case的規則是很複雜的,所以android提供了方法getQuantityString(),它可以用來爲你選擇合適的資源。

一個複數或者單數字符串。它的值可以是對其他字符串資源的一個引用。必須是 的子節點。必須知道不要撇號和引號。可以參考下面的例子。

屬性:

quantity:

關鍵字.這個值反應了什麼時候這個字符該被使用。正確的值,在括號裏面有不詳盡的例子:
Value

zero 當語言需要特別對待0時(就想阿拉伯)
one 當語言需要特別對待1(就像英語裏和其他語言裏的1;在russian,任何以1結尾但是不是以11結尾的也使用這種情況)
two 當語言需要特別對待1(例如Welsh的2,或者Slovenian的102)
few 當語言需要特別對待small(例如Czech的2,3,4;或者以2,3,4結尾但是不是12,13,14的Polisth)
many 當語言需要特別對待large(例如Maltese的11-99)
other 當語言沒有要求對特定資

實例:

    <plurals name="book_number" >
        <item quantity="one">%d book</item>
        <item quantity="other">%d books</item>
    </plurals>

代碼:

 String bookNum = getResources().getQuantityString(R.plurals.book_number, 1, 2);
        tv4.setText(bookNum);

 String bookNum2 = getResources().getQuantityString(R.plurals.book_number, 2, 4);
        tv5.setText(bookNum2);

注意:一定要在English語言環境下才起作用,語言爲中文不起效。

當第二個參數爲1時,會調用 book,爲其他數值時,會調用books。

爲什麼只在英文語言環境下才起作用呢?

2、源碼分析

@NonNull
public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
        throws NotFoundException {
    //容易看出,先根據quantity決定要使用的字符串
    String raw = getQuantityText(id, quantity).toString();

    //再進行佔位符的替換工作
    return String.format(mResourcesImpl.getConfiguration().getLocales().get(0), raw,
            formatArgs);
}

@NonNull
public CharSequence getQuantityText(@PluralsRes int id, int quantity)
        throws NotFoundException {
    //依賴於ResourceImpl的實現
    return mResourcesImpl.getQuantityText(id, quantity);
}

跟進ResourceImpl中的getQuantityText函數:

CharSequence getQuantityText(@PluralsRes int id, int quantity) throws NotFoundException {
    //得到規則
    PluralRules rule = getPluralRule();

    //rule.select根據規則,得到quantity對應的QuanitiyCode,即"zero"、"one"、"other"等
    //之後再根據QuanitiyCode,的到具體的資源文件
    CharSequence res = mAssets.getResourceBagText(id,
            attrForQuantityCode(rule.select(quantity)));
    if (res != null) {
        return res;
    }

    //rule沒能找到對應的QuanitiyCode時,就用"other"字段的定義
    res = mAssets.getResourceBagText(id, ID_OTHER);
    if (res != null) {
        return res;
    }

    //上面尋找資源文件出問題,就拋出異常
    throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
        + " quantity=" + quantity
        + " item=" + rule.select(quantity));
}

這裏我們首先看一下getPluralRule函數:

private PluralRules getPluralRule() {
    synchronized (sSync) {
        if (mPluralRule == null) {
            //單例模式,且和本地化有關,以Locales的第一個配置來初始化規則
            mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
        }
        return mPluralRule;
    }
}

PluralRules的select函數對應的底層實現,在此不作深研究,不同的Locales應該有不同的實現。

在此看看attrForQuantityCode:

private static int attrForQuantityCode(String quantityCode) {
    switch (quantityCode) {
        case PluralRules.KEYWORD_ZERO: return 0x01000005;
        case PluralRules.KEYWORD_ONE:  return 0x01000006;
        case PluralRules.KEYWORD_TWO:  return 0x01000007;
        case PluralRules.KEYWORD_FEW:  return 0x01000008;
        case PluralRules.KEYWORD_MANY: return 0x01000009;
        default:                       return ID_OTHER;
    }
}

從上面的代碼可以看出,PluralRules的select函數的作用,就是將quantity映射成PluralRules定義的Keyword。
然後attrForQuantityCode將Keyword轉化成資源文件能識別的標誌。

現在回到我們之前的問題,爲什麼終端語言爲中文時,Plurals string失效?
原因是attrForQuantityCode的結果一直是ID_OTHER,即中文對應PluralRules無法有效將Quantity轉化爲正確的Keyword。

當然,Google的這種設計並不是Bug,畢竟中文語言環境下,App的顯示就應該是中文,本來就沒有這種需求。
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章