diff options
-rw-r--r-- | core/java/android/content/res/PluralRules.java | 111 | ||||
-rw-r--r-- | core/java/android/content/res/Resources.java | 58 | ||||
-rw-r--r-- | docs/html/guide/topics/resources/string-resource.jd | 67 |
3 files changed, 102 insertions, 134 deletions
diff --git a/core/java/android/content/res/PluralRules.java b/core/java/android/content/res/PluralRules.java deleted file mode 100644 index 2dce3c1..0000000 --- a/core/java/android/content/res/PluralRules.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.res; - -import java.util.Locale; - -/* - * Yuck-o. This is not the right way to implement this. When the ICU PluralRules - * object has been integrated to android, we should switch to that. For now, yuck-o. - */ - -abstract class PluralRules { - - static final int QUANTITY_OTHER = 0x0000; - static final int QUANTITY_ZERO = 0x0001; - static final int QUANTITY_ONE = 0x0002; - static final int QUANTITY_TWO = 0x0004; - static final int QUANTITY_FEW = 0x0008; - static final int QUANTITY_MANY = 0x0010; - - static final int ID_OTHER = 0x01000004; - - abstract int quantityForNumber(int n); - - final int attrForNumber(int n) { - return PluralRules.attrForQuantity(quantityForNumber(n)); - } - - static final int attrForQuantity(int quantity) { - // see include/utils/ResourceTypes.h - switch (quantity) { - case QUANTITY_ZERO: return 0x01000005; - case QUANTITY_ONE: return 0x01000006; - case QUANTITY_TWO: return 0x01000007; - case QUANTITY_FEW: return 0x01000008; - case QUANTITY_MANY: return 0x01000009; - default: return ID_OTHER; - } - } - - static final String stringForQuantity(int quantity) { - switch (quantity) { - case QUANTITY_ZERO: - return "zero"; - case QUANTITY_ONE: - return "one"; - case QUANTITY_TWO: - return "two"; - case QUANTITY_FEW: - return "few"; - case QUANTITY_MANY: - return "many"; - default: - return "other"; - } - } - - static final PluralRules ruleForLocale(Locale locale) { - String lang = locale.getLanguage(); - if ("cs".equals(lang)) { - if (cs == null) cs = new cs(); - return cs; - } - else { - if (en == null) en = new en(); - return en; - } - } - - private static PluralRules cs; - private static class cs extends PluralRules { - int quantityForNumber(int n) { - if (n == 1) { - return QUANTITY_ONE; - } - else if (n >= 2 && n <= 4) { - return QUANTITY_FEW; - } - else { - return QUANTITY_OTHER; - } - } - } - - private static PluralRules en; - private static class en extends PluralRules { - int quantityForNumber(int n) { - if (n == 1) { - return QUANTITY_ONE; - } - else { - return QUANTITY_OTHER; - } - } - } -} - diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 0608cc0..5ac55c4 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -16,7 +16,6 @@ package android.content.res; - import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; @@ -41,6 +40,8 @@ import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.Locale; +import libcore.icu.NativePluralRules; + /** * Class for accessing an application's resources. This sits on top of the * asset manager of the application (accessible through getAssets()) and @@ -52,6 +53,8 @@ public class Resources { private static final boolean DEBUG_CONFIG = false; private static final boolean TRACE_FOR_PRELOAD = false; + private static final int ID_OTHER = 0x01000004; + // Use the current SDK version code. If we are a development build, // also allow the previous SDK version + 1. private static final int sSdkVersion = Build.VERSION.SDK_INT @@ -86,7 +89,7 @@ public class Resources { /*package*/ final AssetManager mAssets; private final Configuration mConfiguration = new Configuration(); /*package*/ final DisplayMetrics mMetrics = new DisplayMetrics(); - PluralRules mPluralRule; + private NativePluralRules mPluralRule; private CompatibilityInfo mCompatibilityInfo; private Display mDefaultDisplay; @@ -203,9 +206,17 @@ public class Resources { } /** + * Return the character sequence associated with a particular resource ID for a particular + * numerical quantity. + * + * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String + * Resources</a> for more on quantity strings. + * * @param id The desired resource identifier, as generated by the aapt * tool. This integer encodes the package, type, and resource * entry. The value 0 is an invalid identifier. + * @param quantity The number used to get the correct string for the current language's + * plural rules. * * @throws NotFoundException Throws NotFoundException if the given ID does not exist. * @@ -213,29 +224,52 @@ public class Resources { * possibly styled text information. */ public CharSequence getQuantityText(int id, int quantity) throws NotFoundException { - PluralRules rule = getPluralRule(); - CharSequence res = mAssets.getResourceBagText(id, rule.attrForNumber(quantity)); + NativePluralRules rule = getPluralRule(); + CharSequence res = mAssets.getResourceBagText(id, + attrForQuantityCode(rule.quantityForInt(quantity))); if (res != null) { return res; } - res = mAssets.getResourceBagText(id, PluralRules.ID_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=" + PluralRules.stringForQuantity(rule.quantityForNumber(quantity))); + + " item=" + stringForQuantityCode(rule.quantityForInt(quantity))); } - private PluralRules getPluralRule() { + private NativePluralRules getPluralRule() { synchronized (mSync) { if (mPluralRule == null) { - mPluralRule = PluralRules.ruleForLocale(mConfiguration.locale); + mPluralRule = NativePluralRules.forLocale(mConfiguration.locale); } return mPluralRule; } } + private static int attrForQuantityCode(int quantityCode) { + switch (quantityCode) { + case NativePluralRules.ZERO: return 0x01000005; + case NativePluralRules.ONE: return 0x01000006; + case NativePluralRules.TWO: return 0x01000007; + case NativePluralRules.FEW: return 0x01000008; + case NativePluralRules.MANY: return 0x01000009; + default: return ID_OTHER; + } + } + + private static String stringForQuantityCode(int quantityCode) { + switch (quantityCode) { + case NativePluralRules.ZERO: return "zero"; + case NativePluralRules.ONE: return "one"; + case NativePluralRules.TWO: return "two"; + case NativePluralRules.FEW: return "few"; + case NativePluralRules.MANY: return "many"; + default: return "other"; + } + } + /** * Return the string value associated with a particular resource ID. It * will be stripped of any styled text information. @@ -290,6 +324,9 @@ public class Resources { * stripped of any styled text information. * {@more} * + * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String + * Resources</a> for more on quantity strings. + * * @param id The desired resource identifier, as generated by the aapt * tool. This integer encodes the package, type, and resource * entry. The value 0 is an invalid identifier. @@ -312,6 +349,9 @@ public class Resources { * Return the string value associated with a particular resource ID for a particular * numerical quantity. * + * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String + * Resources</a> for more on quantity strings. + * * @param id The desired resource identifier, as generated by the aapt * tool. This integer encodes the package, type, and resource * entry. The value 0 is an invalid identifier. @@ -1334,7 +1374,7 @@ public class Resources { } synchronized (mSync) { if (mPluralRule != null) { - mPluralRule = PluralRules.ruleForLocale(config.locale); + mPluralRule = NativePluralRules.forLocale(config.locale); } } } diff --git a/docs/html/guide/topics/resources/string-resource.jd b/docs/html/guide/topics/resources/string-resource.jd index 81c5d55..2db38f1 100644 --- a/docs/html/guide/topics/resources/string-resource.jd +++ b/docs/html/guide/topics/resources/string-resource.jd @@ -12,8 +12,8 @@ your application with strings:</p> <dd>XML resource that provides a single string.</dd> <dt><a href="#StringArray">String Array</a></dt> <dd>XML resource that provides an array of strings.</dd> - <dt><a href="#Plurals">Plurals</a></dt> - <dd>XML resource that carries different strings for different pluralizations + <dt><a href="#Plurals">Quantity Strings (Plurals)</a></dt> + <dd>XML resource that carries different strings for different quantities of the same word or phrase.</dd> </dl> @@ -218,13 +218,30 @@ getStringArray}(R.array.planets_array); -<h2 id="Plurals">Plurals</h2> +<h2 id="Plurals">Quantity Strings (Plurals)</h2> -<p>A pair of strings that each provide a different plural form of the same word or phrase, -which you can collectively reference from the application. When you request the plurals -resource using a method such as {@link android.content.res.Resources#getQuantityString(int,int) -getQuantityString()}, you must pass a "count", which will determine the plural form you -require and return that string to you.</p> +<p>Different languages have different rules for grammatical agreement with quantity. In English, +for example, the quantity 1 is a special case. We write "1 book", but for any other quantity we'd +write "<i>n</i> books". This distinction between singular and plural is very common, but other +languages make finer distinctions. The full set supported by Android is <code>zero</code>, +<code>one</code>, <code>two</code>, <code>few</code>, <code>many</code>, and <code>other</code>. + +<p>The rules for deciding which case to use for a given language and quantity can be very complex, +so Android provides you with methods such as +{@link android.content.res.Resources#getQuantityString(int,int) getQuantityString()} to select +the appropriate resource for you. + +<p>Note that the selection is made based on grammatical necessity. A string for <code>zero</code> +in English will be ignored even if the quantity is 0, because 0 isn't grammatically different +from 2, or any other number except 1 ("zero books", "one book", "two books", et cetera). +Don't be misled either by the fact that, say, <code>two</code> sounds like it could only apply to +the quantity 2: a language may require that 2, 12, 102 (et cetera) are all treated like one +another but differently to other quantities. Rely on your translator to know what distinctions +their language actually insists upon. + +<p>It's often possible to avoid quantity strings by using quantity-neutral formulations such as +"Books: 1". This will make your life and your translators' lives easier, if it's a style that's +in keeping with your application. <p class="note"><strong>Note:</strong> A plurals collection is a simple resource that is referenced using the value provided in the {@code name} attribute (not the name of the XML @@ -251,7 +268,7 @@ In Java: <code>R.plurals.<em>plural_name</em></code> <<a href="#plurals-element">plurals</a> name="<em>plural_name</em>"> <<a href="#plurals-item-element">item</a> - quantity=["one" | "other"] + quantity=["zero" | "one" | "two" | "few" | "many" | "other"] ><em>text_string</em></item> </plurals> </resources> @@ -285,16 +302,27 @@ Styling</a>, below, for information about to properly style and format your stri <p class="caps">attributes:</p> <dl class="atn-list"> <dt><code>quantity</code></dt> - <dd><em>Keyword</em>. A value indicating the case in which this string should be used. Valid -values: + <dd><em>Keyword</em>. A value indicating when this string should be used. Valid +values, with non-exhaustive examples in parentheses: <table> <tr><th>Value</th><th>Description</th></tr> <tr> - <td>{@code one}</td><td>When there is one (a singular string).</td> + <td>{@code zero}</td><td>When the language requires special treatment of the number 0 (as in Arabic).</td> + </tr> + <tr> + <td>{@code one}</td><td>When the language requires special treatment of numbers like one (as with the number 1 in English and most other languages; in Russian, any number ending in 1 but not ending in 11 is in this class).</td> + </tr> + <tr> + <td>{@code two}</td><td>When the language requires special treatment of numbers like two (as in Welsh).</td> + </tr> + <tr> + <td>{@code few}</td><td>When the language requires special treatment of "small" numbers (as with 2, 3, and 4 in Czech; or numbers ending 2, 3, or 4 but not 12, 13, or 14 in Polish).</td> </tr> <tr> - <td>{@code other}</td><td>When the quantity is anything other than one (a plural -string, but also used when the count is zero).</td> + <td>{@code many}</td><td>When the language requires special treatment of "large" numbers (as with numbers ending 11-99 in Maltese).</td> + </tr> + <tr> + <td>{@code other}</td><td>When the language does not require special treatment of the given quantity.</td> </tr> </table> </dd> @@ -315,6 +343,17 @@ string, but also used when the count is zero).</td> </plurals> </resources> </pre> + <p>XML file saved at {@code res/values-pl/strings.xml}:</p> +<pre> +<?xml version="1.0" encoding="utf-8"?> +<resources> + <plurals name="numberOfSongsAvailable"> + <item quantity="one">Znaleziono jedną piosenkę.</item> + <item quantity="few">Znaleziono %d piosenki.</item> + <item quantity="other">Znaleziono %d piosenek.</item> + </plurals> +</resources> +</pre> <p>Java code:</p> <pre> int count = getNumberOfsongsAvailable(); |