How to access Plural resource in JetpackCompose String

Viewed 1970

I have the below

    <string name="loading_listing">Loading listings %d</string>
    <plurals name="loading_listing">
        <item quantity="one">Found %d listing</item>
        <item quantity="other">Found %d listings</item>
    </plurals>

If I use the string, as below all is okay

Text(text = stringResource(R.string.loading_listing, 1))

But if I use the plurals,

Text(text = stringResource(R.plurals.loading_listing, 1))

it will crash

    android.content.res.Resources$NotFoundException: String resource ID #0x7f0d0003
        at android.content.res.Resources.getText(Resources.java:444)
        at android.content.res.Resources.getString(Resources.java:537)
        at android.content.res.Resources.getString(Resources.java:561)
        at androidx.compose.ui.res.StringResources_androidKt.stringResource(StringResources.android.kt:48)

I think it is not stringResource(...) that I can use. What is it then?

3 Answers

Compose 1.2

From Jetpack Compose 1.2 there's a pluralStringResource function.

pluralStringResource(id = R.plurals.loading_listing, count = 1)

In this version it is an experimental API, so you need to add the annotation @ExperimentalComposeUiApi.

Pre 1.2 Answer

Meanwhile it's not available in Compose lib, you can create a helper function for that...

@Composable
fun pluralResource(
    @PluralsRes resId: Int,
    quantity: Int,
    vararg formatArgs: Any? = emptyArray()
): String {
    return LocalContext.current.resources
        .getQuantityString(resId, quantity, *formatArgs)
}

Starting with Compose 1.2 you can use the pluralStringResource function.

pluralStringResource(R.plurals.plurals_array, 1)

With 1.1.x there isn't a function to get a plural resource.

You can use something like:

val resources = LocalContext.current.resources

Text(
    text = resources.getQuantityString(
        R.plurals.loading_listing, 0, 10
    )
)

more complete solution:

/**
 * Load a plurals resource.
 *
 * @param id the resource identifier
 * @param qty the associated quantity
 * @return the string data associated with the resource
 */
@Composable
@ReadOnlyComposable
fun pluralsResource(@PluralsRes id: Int, qty: Int): String {
    val resources = resources()
    return resources.getQuantityString(id, qty)
}

/**
 * Load a plurals resource with formatting.
 *
 * @param id the resource identifier
 * @param qty the associated quantity
 * @param formatArgs the format arguments
 * @return the string data associated with the resource
 */
@Composable
@ReadOnlyComposable
fun pluralsResource(@PluralsRes id: Int, qty: Int, vararg formatArgs: Any): String {
    val resources = resources()
    return resources.getQuantityString(id, qty, *formatArgs)
}

/**
 * A composable function that returns the [Resources]. It will be recomposed when [Configuration]
 * gets updated.
 */
@Composable
@ReadOnlyComposable
private fun resources(): Resources {
    LocalConfiguration.current
    return LocalContext.current.resources
}
Related