How to use string-array with plurals? - android

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.

Related

Multiple values String format Android

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.

How to get integer resource array through typed-array?

I have declared following declare-stylables in attr.xml:
<declare-styleable name="SideSpinnerAttrs">
<attr name="stringValues" format="reference" />
<attr name="iconIDs" format="reference"/>
</declare-styleable>
Array of resource icons in array.xml:
<integer-array name="spinnerIcons">
<item>#drawable/ic_attachment_black_24dp</item>
<item>#drawable/ic_audiotrack_black_24dp</item>
<item>#drawable/ic_slideshow_black_24dp</item>
</integer-array>
I would like to call and set those icons from array to an imageView:
private void readSpinnerIcons(Context context, AttributeSet attrs) {
TypedArray icons=context.obtainStyledAttributes(attrs,R.styleable.SideSpinnerAttrs);
int id=icons.getResourceId(R.styleable.SideSpinnerAttrs_iconIDs,0);
int[] i=getResources().getIntArray(id);
spinner_icon.setBackgroundResource(i[0]);
}
But, array "int[] i", is empty. Why?
For example:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer-array name="IntArray">
<item>2</item>
<item>8</item>
<item>10</item>
<item>16</item>
</integer-array>
</resources>
You can use this
Resources r = getResources();
int[] bases = r.getIntArray(R.array.IntArray);
The problem is this line:
int id=icons.getResourceId(R.styleable.SideSpinnerAttrs_iconIDs,0);
The first argument is not the Styleable resource id, but rather the index of the TypedArray containing the resource id. Since you're not providing a valid index, id will always be the default value you're using as the 2nd argument, which means your int[] array i will always be empty.
Also, make sure you always call recycle() once you're done using a TypedArray. Use the following:
private void readSpinnerIcons(Context context) {
TypedArray icons = context.obtainStyledAttributes(new int[] {R.styleable.SideSpinnerAttrs});
int id = icons.getResourceId(0, 0);
int[] i = getResources().getIntArray(id);
spinner_icon.setBackgroundResource(i[0]);
icons.recycle();
}

Two or more plulars in one string in android xml

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>

Get resource id from typedarray

I have this file array.xml and I want to get the item value from an array.
How can I do that? I have tried with getInt but that returns 0. All help is welcome.
<resources>
<array name="firstAd">
<item>border_top_id_1v</item>
<item>R.id.dugme_1v</item>
<item>R.id.rent_or_buy_1v</item>
<item>R.id.currency_1v</item>
<item>R.id.price_1v</item>
<item>R.id.name_1v</item>
<item>R.id.address_1v</item>
</array>
</resources>
First, change each item to #id/object instead of R.id.object, then change the tag from array to integer-array, and move the code to your 'integer.xml' resource file.
integer.xml:
<resources>
<integer-array name="firstAd">
<item>#id/dugme_1v</item>
<item>#id/rent_or_buy_1v</item>
<item>#id/currency_1v</item>
<item>#id/price_1v</item>
<item>#id/name_1v</item>
<item>#id/address_1v</item>
</integer-array>
</resources>
Then, programmatically use a TypedArray, like so:
TypedArray firstAd = getResources().obtainTypedArray(R.array.firstAd);
int resourceId = firstAd.getResourceId(index, defValue);
try #id/yourIDHere
<item>border_top_id_1v</item>
<item>#id/dugme/1v</item>
<item>#id/rent_or_buy_1v</item>
<item>#id/currency_1v</item>

Android show plurals in both integer and float

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!

Categories

Resources