icerockdev / moko-resources

Resources access for mobile (android & ios) Kotlin Multiplatform development
https://moko.icerock.dev/
Apache License 2.0
1.07k stars 120 forks source link

Add common type for resource providers #307

Open y9san9 opened 2 years ago

y9san9 commented 2 years ago

Sometimes it can be useful to get resources from common code. For such situations, a special type can be provided which will have no meaning in the common code, but which needs to be passed from the platform code to the localized() method.

Example:

// common code
expect class ResourceProvider

// android code
actual typealias ResourceProvider = Context

actual class ResourceStringDesc(@StringRes private val id: Int) : StringDesc {
    override fun localized(provider: ResourceProvider): String = provider.getString(id)
}

So then you can use it for common ui:

// android code
class MyActivity : AppCompatActivity() {
    override fun onCreate(savedState: Bundle?) {
        setContent {
            CommonUi(resourceProvider = this)
        }
    }
}

// common ui code, but you still have access to resources
@Composable
fun CommonUi(resourceProvider: ResourceProvider) {
    MR.strings.app_name.desc().localized(resourceProvider)
}

Or something else

plusmobileapps commented 1 month ago

One thing I did in this situation was use the expect/actual for making your own localized().

// commonMain

@Composable 
fun StringResource.localized(): String = StringDesc.Resource(this).localized()

@Composable
expect fun StringDesc.localized(): String

// androidMain
@Composable
actual fun StringDesc.localized(): String  =  this.toString(LocalContext.current)

// iosMain
@Composable
actual fun StringDesc.localized(): String = this.localized()

Then you can use it in common code like so.

@Composable
fun App() {
    val formattedString: StringDesc = StringDesc.ResourceFormatted(
        MR.strings.welcome_greeting,
        args = listOf("Vader")
    )
    Column {
         Text(formattedString.localized())
         Text(MR.strings.my_string.localized())
    }
}
Alex009 commented 1 month ago

@plusmobileapps you can just use resources-compose module that already contains localized for compose

https://github.com/icerockdev/moko-resources/blob/71095fc691d8769b581b1b48c489701f0fd2c344/resources-compose/src/commonMain/kotlin/dev/icerock/moko/resources/compose/StringDescExt.kt#L11

plusmobileapps commented 1 month ago

Lol I didn't see that in the docs but that makes a lot more sense to use that directly. I guess I don't fully understand the use case then for the original issue posted 🤔