I have to put in one xml string in android two plurals for age of user. And I have to handle sutch cases:
"You are 3 months old" (for parents which use child's profile)
"You are 1 year old"
"You are 1 year and 1 month old"
"You are 1 year and 3 months old"
"You are 2 years old"
"You are 3 years and 1 month old"
"You are 5 years and 3 months old"
And as you see only for english I need 6 diffrent cases. For another languages are more. Also I don't want to break string to two plurals beacuse in same languages order of world in sentence is diffrent.
Till now I alwas use plurals for only one quantity. In docs I don't see any hint how to correct solve sutch issue?
Actual solution:
in xml:
<string name="age_1">You are %1$s old</string>
<string name="age_2">You are %1$s and %2$s old</string>
<plurals name="age_months">
<item quantity="one">%d month</item>
<item quantity="other">%d months</item>
</plurals>
<plurals name="age_years">
<item quantity="one">%d year</item>
<item quantity="other">%d years</item>
</plurals>
And in code:
if(years == 0) {
String m = res.getQuantityString(R.plurals.age_months, months, months);
ageTextView.setText(String.format(res.getString(R.age_1), m);
} else if (months == 0){
String y = res.getQuantityString(R.plurals.age_years, years, years);
ageTextView.setText(String.format(res.getString(R.age_1), y);
} else {
String m = res.getQuantityString(R.plurals.age_months, months, months);
String y = res.getQuantityString(R.plurals.age_years, years, years);
ageTextView.setText(String.format(res.getString(R.age_2), y, m);
}
But I'm looking for something which use one plural contant in xml:
<plurals name="age_months">
<item quantityA="one" quantityB="one">You are %1$d year %2$d month</item>
<item quantityA="other"quantityB="one">You are %1$d years %2d month</item>
...
</plurals>
So it seems that there is no bether solution than I used:
In xml:
<string name="age_1">You are %1$s old</string>
<string name="age_2">You are %1$s and %2$s old</string>
<plurals name="age_months">
<item quantity="one">%d month</item>
<item quantity="other">%d months</item>
</plurals>
<plurals name="age_years">
<item quantity="one">%d year</item>
<item quantity="other">%d years</item>
</plurals>
And some logic in code:
if(years == 0) {
String m = res.getQuantityString(R.plurals.age_months, months, months);
ageTextView.setText(String.format(res.getString(R.age_1), m);
} else if (months == 0){
String y = res.getQuantityString(R.plurals.age_years, years, years);
ageTextView.setText(String.format(res.getString(R.age_1), y);
} else {
String m = res.getQuantityString(R.plurals.age_months, months, months);
String y = res.getQuantityString(R.plurals.age_years, years, years);
ageTextView.setText(String.format(res.getString(R.age_2), y, m);
}
Check this.
Quantity Strings (Plurals) :
https://developer.android.com/guide/topics/resources/string-resource.html#Plurals
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals
name="plural_name">
<item
quantity=["zero" | "one" | "two" | "few" | "many" | "other"]
>text_string</item>
</plurals>
</resources>
Related
I would to display text like this sample : "0/2 documents"
I'm trying to do this with :
<plurals name="documents_get">
<item quantity="one">%1d/%2d doucment</item>
<item quantity="other">%1d/%2d documents</item>
</plurals>
resources.getQuantityString(
R.plurals.documents_get,
docCount,
documents.filter {
it.retrieved_at != null
}.count(),
docCount)
My problem is the result is : 0/ 2 documents instead "0/2 documents". Space after the '/' is the problem.
Do you know a solution for this ?
Thanks in Advance
The problem is the format you are using (%2d). So change your plurals to this:
<plurals name="documents_get">
<item quantity="one">%d/%d doucment</item>
<item quantity="other">%d/%d documents</item>
</plurals>
Example with using String.format
String s1 = String.format("%d/%d document", 0, 1); // s1: "0/1 document"
String s2 = String.format("%d/%2d document", 0, 1); // s2: "0/ 1 document"
Edit
As #Kingfisher Phuoc noted, it should be %1$d/%2$d instead of %d. The $ sign allows you to specify the index of the string (the position where the string should be printed, called "explicit argument indices" or "positional arguments". You can read more here).
For example:
String s1 = String.format("%1$d/%2$d", 1, 2); // s1: "1/2"
String s2 = String.format("%2$d/%1$d", 1, 2); // s2: "2/1"
Remove (%2d) and replace it with (%d) or you can use string format
String resource = String.format("%d/%d document", 0, 1); // s1: "0/1 document"
You can define your string inside string.xml like this
<resources>
<string name="string">0"/"2 documents</string>
</resources>
and fetch it via getResources.getString method.
Note : Special Characters are enclosed inside double quotes.
So I have many strings in strings.xml, they are recorded in a format of:
<string name="list_1">xxxxxxxxxxx</string>
<string name="list_2">xxxxxxxxxxx</string>
<string name="list_3">xxxxxxxxxxx</string>
......
Now I want to load them one by one without having to type all the string IDs. I want to load them in a fashion like:
for (int i = 1; i <= num; i++) {
// Just showing what I mean.
String xxx = getString(R.string.("list_" + i));
}
Is there a method to do so?
Try this:
int resourceID = getResources().getIdentifier("list_" + i, "string", getPackageName());
String xxx = getString(resourceID);
It would be worth to use resource arrays. For example
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="planets_array">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
<item>Mars</item>
</string-array>
</resources>
and you can access, iterate as follows:
Resources res = getResources();
String[] planets = res.getStringArray(R.array.planets_array);
My target is to show text like "1 star" "2.5 stars" "3 stars".
which is remove .0 for float value like 1.0, 2.0 etc. But for the value with .5 show the float value 2.5 3.5 etc.
Is this possible to use android plurals ?
I used this way but doesn't work.
plurals.xml
<plurals name="hotel_card_rating_text">
<item quantity="zero">#string/text_zero</item>
<item quantity="one">#string/text_one</item>
<item quantity="two">#string/text_two</item>
<item quantity="few">#string/text_few</item>
<item quantity="many">#string/text_many</item>
<item quantity="other">#string/text_other</item>
</plurals>
strings.xml
<resources>
<string name="text_zero">%.1f stars</string>
<string name="text_one">1 star</string>
<string name="text_two">%.1f stars</string>
<string name="text_few">%.1f stars</string>
<string name="text_many">%.1f stars</string>
<string name="text_other">%.1f stars</string>
</resources>
test code
DecimalFormat format = new DecimalFormat();
float rating = getRating();
getStarText().setText(getContext().getResources().getQuantityString(R.plurals.hotel_card_rating_text, (int) rating, format.format(rating)));
}
strings.xml use %s instead of %.1f
<resources>
<string name="text_zero">%s stars</string>
<string name="text_one">1 star</string>
<string name="text_two">%s stars</string>
<string name="text_few">%s stars</string>
<string name="text_many">%s stars</string>
<string name="text_other">%s stars</string>
</resources>
test code
DecimalFormat format = new DecimalFormat("#.#"); // format the number
float rating = getRating();
getContext().getResources()
.getQuantityString(R.plurals.hotel_card_rating_text, (int) rating, format.format(rating)));
Be careful when you use plurals. It has its own issues, see below:
Plural definition is ignored for zero quantity
Issue 8287: PluralRules does not handle quantity "zero"
you can give it a try to below snippet which is very typical
String somePostFixText = "star";
String output;
double starCount;
if (starCount > (double)1)
somePostFixText = somePostFixText+"s";
if(starCount == (long) starCount){
output = String.format("%d",(long)starCount)+" "+somePostFixText;
} else {
output = String.format("%s",starCount)+" "+somePostFixText;
}
//do whatever you want to do with output variable
Happy Coding!
I start to meet with android plurals and i'm stack in usability of this feature. I declare plurals.xml and try to read them from my code, but i getting incorrect results.
Plurals :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="numbers">
<item quantity="zero">No comments</item>
<item quantity="one">%1$d comment.</item>
<item quantity="two">%1$d comments.</item>
<item quantity="few">%1$d comments.</item>
<item quantity="many">%1$d comments.</item>
<item quantity="other">%1$d comments.</item>
</plurals>
<plurals name="numberOfSongsAvailable">
<item quantity="zero">No song found.</item>
<item quantity="one">One song found.</item>
<item quantity="two">Two song found.</item>
<item quantity="other">Other songs found.</item>
</plurals>
</resources>
Activity :
public class AndroidPlurals extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.plurals);
((ListView) findViewById(R.id.listView)).setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getPluralsList(10)));
Toast.makeText(this, getClass().getSimpleName(), Toast.LENGTH_LONG).show();
}
private String[] getPluralsList(int k) {
String[] array = new String[k];
for (int i = 0; i < array.length; i++) {
String quantityString = (String) this.getResources().getQuantityText(R.plurals.numberOfSongsAvailable, i);
array[i] = quantityString;
android.util.Log.i("Plurals", "i = " + i + ", quantityString = " + quantityString);
}
return array;
}
}
OutPut :
I/Plurals (17689): i = 0, quantityString = Other songs found.
I/Plurals (17689): i = 1, quantityString = One song found.
I/Plurals (17689): i = 2, quantityString = Other songs found.
I/Plurals (17689): i = 3, quantityString = Other songs found.
I/Plurals (17689): i = 4, quantityString = Other songs found.
I/Plurals (17689): i = 5, quantityString = Other songs found.
I/Plurals (17689): i = 6, quantityString = Other songs found.
I/Plurals (17689): i = 7, quantityString = Other songs found.
I/Plurals (17689): i = 8, quantityString = Other songs found.
I/Plurals (17689): i = 9, quantityString = Other songs found.
Why i have not correct result for 0 quantity like a No song found. text???
Note : tested on Android 5.0 Lolipop
The short answer is that on Android, plurals are meant for grammatical distinctions.
Quote from the docs (my highlight):
The selection of which string to use is made solely based on grammatical necessity. In English, a string for zero 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", and so on). Conversely, in Korean only the other string will ever be used.
And:
Don't be misled either by the fact that, say, two sounds like it could only apply to the quantity 2: a language may require that 2, 12, 102 (and so on) are all treated like one another but differently to other quantities. Rely on your translator to know what distinctions their language actually insists upon.
More details and alternatives here: Android plurals treatment of "zero"
On the android device where input language is English the case with 0 or 2 will be handled the same. So in russian language (and very possible in others) if you app use russian language and you use it on the device with English input, you always will get the value for zero case from many case. For example
2 Билетов а не 2 Билета
Why i have not correct result for 0 quantity like a No song found. text?
Because English has only a special case for quantity one. The quantity other is picked up for all other cases.
Please read the documentation.
From developer.android.com:
Don't be misled either by the fact that, say, two sounds like it could only apply to the quantity 2: a language may require that 2, 12, 102 (and so on) are all treated like one another but differently to other quantities. Rely on your translator to know what distinctions their language actually insists upon.
You'd only need to specify one and other here ("song" vs. "songs").
I would like to support multiple languages using plurals:
<string-array name="quantityTypes">
<item>#plurals/Package</item>
<item>#plurals/Piece</item>
</string-array>
<plurals name="Package">
<item quantity="one">"Package"</item>
<item quantity="other">"Packages"</item>
</plurals>
<plurals name="Piece">
<item quantity="one">"Piece"</item>
<item quantity="other">"Pieces"</item>
</plurals>
I am trying to get the string array, but this call returns a string array with 2 elements, both of which are null.
getResources().getStringArray(R.array.quantityTypes)
Is there something I am missing? Do string-arrays even support plurals?
For me also getResources().getStringArray(R.array.quantityTypes) returns an array of nulls. Seems that Android still doesn't support it.
But I found a workaround which looks even better (no need to check array bounds):
// strings.xml
<plurals name="Season">
<item quantity="one">"Season"</item>
<item quantity="other">"Seasons"</item>
</plurals>
<plurals name="Volume">
<item quantity="one">"Volume"</item>
<item quantity="other">"Volumes"</item>
</plurals>
<plurals name="Collection">
<item quantity="one">"Collection"</item>
<item quantity="other">"Collections"</item>
</plurals>
<plurals name="Special">
<item quantity="one">"Special"</item>
<item quantity="other">"Specials"</item>
</plurals>
<plurals name="Set">
<item quantity="one">"Set"</item>
<item quantity="other">"Sets"</item>
</plurals>
// ShowTypes.java
public enum ShowTypes {
SEASON("Season", R.plurals.Season),
VOLUME("Volume", R.plurals.Volume),
COLLECTION("Collection", R.plurals.Collection),
SPECIAL("Special", R.plurals.Special),
SET("Set", R.plurals.Set)
private String typeValue;
private int resId;
private ShowTypes(String typeValue, int resId) {
this.typeValue = typeValue;
this.resId = resId;
}
public static ShowTypes getType(String typeValue) {
ShowTypes result = SEASON;
for (ShowTypes type : ShowTypes.values()) {
if (type.typeValue.equals(typeValue)) {
return type;
}
}
return result;
}
public String getResourceString(Resources res, int quantity) {
return res.getQuantityString(resId, quantity);
}
}
This is certainly possible. You first need to define your resource array as an integer array and not a string array, since plurals are resource IDs, not strings.
<integer-array name="quantities">
<item>#plurals/quantity_1</item>
<item>#plurals/quantity_2</item>
<item>#plurals/quantity_3</item>
</integer-array>
You can then resolve the quantities like this:
val quantity = 1 // This is the quantity plurals are resolved for.
val ta = resources.obtainTypedArray(R.array.quantities)
val quantitiesArray = Array(ta.length()) {
resources.getQuantityString(ta.getResourceId(it, 0), quantity)
}
ta.recycle()
You can actually do that with most resources types: drawables, ids, layouts. You could even have arrays of arrays.