https://kotlinlang.org logo
#compose
Title
# compose
d

Dmitriy Gaiduk

10/07/2021, 2:34 PM
Hello, What’s the preferred way to implement a custom string resource system in Compose? Problem: We are adding the Lokalise SDK https://docs.lokalise.com/en/articles/1400668-lokalise-android-sdk. And working with strings looks like this:
Copy code
val resources = new LokaliseResources(context)
val text = resources.getString(R.string.screen_title)
What’s the best way to store and create the
LokaliseResources
object in Compose? We want to use the
LokaliseResources.getString ()
function as a replacement for
androidx.compose.ui.res.stringResource ()
. We now have an implementation like this:
Copy code
@Composable
fun CustomTheme(
  useDarkTheme: Boolean = false,
  content: @Composable () -> Unit,
) {
  val colors = if (useDarkTheme) DarkColorPalette else LightColorPalette
  val colorPalette = remember { colors }
  colorPalette.update(colors)
  
  MaterialTheme(
    colors = debugColors(),
    typography = MaterialTypography,
  ) {
    CompositionLocalProvider(
      CustomColors provides colorPalette,
      content = content,
    )
  }
}

class Screen : com.bluelinelabs.conductor.Controller {
  private val lokaliseResources: LokaliseResources by lazy { LokaliseResources(activity) }
  private fun getString(@StringRes resId: Int): String {
    return lokaliseResources.getString(resId)
  }

 @Composable
 fun Content() {
    CustomTheme(useDarkTheme = false) {
      Text(value = getString(R.string.screen_title))
    }
  }
}
But the problem is that you cannot get a string resource outside of the
Screen
class in any Compose method. Is it possible to create LokaliseResources in a singleton? Or can this be added to
CustomTheme
somehow?
🧵 3
a

annsofi

10/07/2021, 2:51 PM
What’s the reason for not using Compose’s
stringResourse
? We’re also using Lokalise and that seems to work, when you override the base context just as you do with “regular” fragments and activities.
c

Csaba Kozák

10/07/2021, 2:52 PM
The built-in in
stringResource()
function calls
LocalConfiguration.current
under the hood, to get the
Resources
object, and read the strings from it. You could provide
LocalConfiguration
and wrap the original one with yours, like in a
ProvideLocaliseConfiguration
function.
Copy code
@Composable
fun ProvideLocaliseConfiguration(
  content: @Composable () -> Unit
) {

  val orig = LocalConfiguration.current

   CompositionLocalProvider(LocalConfiguration provides LocaliseConfiguration(orig) {
    content()
  }
}
Edit: checking the sources again, actually you have to provide
LocalContext
instead, or both. But you get the idea. 🙂
Yeah, overriding the base context should also work, but in a pure compose app, i would rather go with the
CompositionLocal
.
d

Dmitriy Gaiduk

10/07/2021, 3:10 PM
What’s the reason for not using Compose’s stringResourse?
For some reason Compose’s
stringResourse
does not work. Override the base context:
Copy code
MainActivity {
 override fun attachBaseContext(context: Context) {
   super.attachBaseContext(LokaliseContextWrapper.wrap(context))
 }
}
d

dimsuz

10/11/2021, 9:32 AM
Maybe you also need to wrap application context:
Copy code
MyApplication : Application {
 override fun attachBaseContext(context: Context) {
   super.attachBaseContext(LokaliseContextWrapper.wrap(context))
 }   
}
41 Views