19

In Android strings, you can define plurals to handle translations depending on the actual number supplied to the string as described here. Strings also allow for specifying multiple positional parameters similar to what sprintf does in many languages.

However, consider the following string:

<resources>
    <string name="remaining">%1$d hours and %2$d minutes remaining.</string>
</resources>

It contains two numbers, how would I transform this to a plural in Android? All examples always work with a single parameter only. Is this even possible?

Andreas Gohr
  • 4,617
  • 5
  • 28
  • 45

3 Answers3

7

getQuantityString has an overloaded version that takes a String id, the quantity and a varargs of object that you could use to format your string. Even though seems possible to use plural, it sounds strange to me for time. You could use the helper methods contained in DateUtil, which are already localized and take care of singular/plural and then complete your string with the results of these helper methods. E.g. getRelativeTimeSpanString

<plurals name="number_of_emails">
    <item quantity="one">%d email</item>
    <item quantity="other">%d emails</item>
</plurals>

<plurals name="number_of_messages">
    <item quantity="one">%d message</item>
    <item quantity="other">%d messages</item>
</plurals>

and then you can use getQuantityString to retrieve the two pieces and combine it in one.

Howard
  • 53
  • 2
  • 9
Blackbelt
  • 156,034
  • 29
  • 297
  • 305
  • 2
    getRelativeTimeSpanString seems to be a good choice for my problem at hand but wouldn't solve my initial question. Having a text with multiple numbers isn't that rare ("You have 5 mails and 3 messages", "There are 5 Dollars and 83 cents left."). I don't see how I would specify the XML for the getQuantityString version you suggest. – Andreas Gohr Dec 21 '15 at 11:18
  • look at the first link, I posted. The documentations says that quantity will be used to choose the String and the third argument to format it – Blackbelt Dec 21 '15 at 11:22
  • 1
    Sorry, I don't get it. Can you expand your answer with an example of a) the XML to setup a string for the 4 plural forms needed for "You have 5 mails and 3 messages" and b) the call to getQuantityString with mails and messages as input quantities? – Andreas Gohr Dec 21 '15 at 11:27
  • I see what you mean. You need two different plurals in this case I think. It doesn't scale well when you can have a mixture of plurarls and singulars in the same sentence. Do you still want the example? – Blackbelt Dec 21 '15 at 11:35
  • 1
    I know how to do it with a single quantity. Thank you. So I guess the answer is simply "it's not possible doing it in one". – Andreas Gohr Dec 21 '15 at 11:44
7

Previous answer uses string concatenation which is incorrect from an i18n point of view. For the original string "%1$d hours and %2$d minutes remaining." using string concatenation would force the translation of "remaining" to the end which mightn't be appropriate for some languages.

My solution would be:

<resources>
     <string name="remaining">Time remaining: Hours:%1$d Minutes:%2$d.</string>
</resources>

Or perhaps with "Time remaining" as the heading.

This solution is mentioned in http://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling

It's often possible to avoid quantity strings by using quantity-neutral formulations such as "Books: 1"

jj2005
  • 133
  • 2
  • 6
2

strings.xml

<plurals name="lbl_items_selected">
    <item quantity="one">%d item out of %d items Selected</item>
    <item quantity="other">%d items out of %d items Selected</item>
</plurals>

Kotlin File

resources.getQuantityString(
    R.plurals.lbl_items_selected, //plural from strings.xml file
    size, //quantity 
    size, //var arg - first parameter
    allItemCount //var arg - second parameter
)

this will return :

if size = 1 : 1 item out of 10(allItemCount) items selected

if size = 2 (or more) : 2(given size) items out of 10(allItemCount) items selected

akshay bhange
  • 2,320
  • 2
  • 28
  • 46