54

Let's I have the following strings.xml resource file:

<resources>
    <!-- basic string -->
    <string name="app_name">My Playground</string>

    <!-- basic string with an argument -->
    <string name="greeting">Hello %!</string>

    <!-- plural string -->
    <plurals name="likes">
        <item quantity="one">%1d like</item>
        <item quantity="other">%1d likes</item>
    </plurals>

    <!-- string array -->
    <string-array name="planets">
        <item>Earth</item>
        <item>Mars</item>
    </string-array>
</resources>

How can I use these resources in Jetpack Compose?

Valeriy Katkov
  • 33,616
  • 20
  • 100
  • 123

4 Answers4

87

There's androidx.compose.ui.res package containing functions for loading string resources as well as other resource types.

string

You can get a string using stringResource() function, for example:

...
import androidx.compose.ui.res.stringResource

@Composable
fun StringResourceExample() {
  Text(
    // a string without arguments
    text = stringResource(R.string.app_name)
  )

  Text(
    // a string with arguments
    text = stringResource(R.string.greeting, "World")
  )
}

string array

Can be obtained using stringArrayResource() function:

val planets = stringArrayResource(R.array.planets_array)

plural (quantity string)

As of compose 1.0.0-alpha10 there's no build-in function for obtaining a plural resource, but you can get the android context via LocalContext and use it the same way as you do it in a view-based app. Even better if you create your own function similar to other resource functions (like Jetcaster compose sample does for example):

// PluralResources.kt

package com.myapp.util

import androidx.annotation.PluralsRes
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext

@Composable
fun quantityStringResource(@PluralsRes id: Int, quantity: Int, vararg formatArgs: Any): String {
    return LocalContext.current.resources.getQuantityString(id, quantity, *formatArgs)
}

so you can use it the same way:

val likes = quantityStringResource(R.plurals.likes, 10, 10)

a note about recomposition

As you know, in compose a composable function might be re-executed up to hundreds of times per second during recomposition. If the string you build isn't trivial and requires some calculation, it's better to remember the calculation result, so it won't be re-executed on each recomposition. For example:

...

import androidx.compose.runtime.remember

@Composable
fun BirthdayDateComposable(username: String, dateMillis: Long) {
  // formatDate() function will be executed only if dateMillis value 
  // is changed, otherwise the remembered value will be used
  val dateStr = remember(dateMillis) {
    formatDate(dateMillis)
  }

  Text(
    text = stringResource(R.string.birthday_date, dateStr)
  )
}
Valeriy Katkov
  • 33,616
  • 20
  • 100
  • 123
  • 3
    Regarding recomposition, are you sure `remember` would be needed in this example? The [official documentation](https://developer.android.com/jetpack/compose/mental-model#recomposition) suggests that a composable function is not recomposed if its parameters stay the same: "By skipping all functions or lambdas that don't have changed parameters, Compose can recompose efficiently." – Jonik Sep 15 '21 at 08:42
4

Here is an example:

Text(text = stringResource(id = R.string.myString)
JustSightseeing
  • 1,460
  • 3
  • 17
  • 37
  • I'm still getting issues with the strings even after importing. I'm using a multimodule project. Text( text = stringResource(id = R.strings.welcome_text) ) – Josphat Mwania Jun 26 '23 at 02:39
3

This is now supported as of compose 1.2.0-alpha06:

val likes = pluralStringResource(R.plurals.likes, 10, 10)
lt0
  • 33
  • 1
  • 4
0

Use this in composable:

LocalContext.current.getResources().getIdentifier()
Soufiane Sabiri
  • 749
  • 1
  • 5
  • 20