diff --git a/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt b/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt index 800e2bc7..4b53d538 100644 --- a/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt +++ b/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt @@ -4,8 +4,11 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview -import co.nimblehq.kmm.template.Greeting +import co.nimblehq.kmm.template.Strings +import co.nimblehq.kmm.template.getPlatform +import co.nimblehq.kmm.template.sharedres.SharedRes import co.nimblehq.kmm.template.ui.theme.ComposeTheme @Composable @@ -14,7 +17,12 @@ fun HomeScreen() { modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background ) { - Text(text = Greeting().greet()) + Text( + text = Strings(LocalContext.current).get( + id = SharedRes.strings.greeting, + args = listOf(getPlatform().name) + ) + ) } } diff --git a/build.gradle.kts b/build.gradle.kts index 09329006..7fa6d01a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,6 +11,12 @@ plugins { kotlin(Plugins.KOTLIN_SERIALIZATION) version Versions.KOTLIN } +buildscript { + dependencies { + classpath(Dependencies.Moko.RESOURCES_GENERATOR) + } +} + detekt { toolVersion = Versions.DETEKT config.setFrom("detekt.yml") diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index f7ae174a..b2c9fae8 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -45,6 +45,13 @@ object Dependencies { const val TIMBER = "com.jakewharton.timber:timber:${Versions.TIMBER}" } + object Moko { + const val RESOURCES_GENERATOR = "dev.icerock.moko:resources-generator:${Versions.MOKO_RESOURCES}" + const val RESOURCES = "dev.icerock.moko:resources:${Versions.MOKO_RESOURCES}" + const val RESOURCES_COMPOSE = "dev.icerock.moko:resources-compose:${Versions.MOKO_RESOURCES}" + const val GRAPHICS = "dev.icerock.moko:graphics:${Versions.MOKO_GRAPHICS}" + } + object Test { const val COMPOSE_UI_TEST_JUNIT = "androidx.compose.ui:ui-test-junit4:${Versions.COMPOSE}" const val COMPOSE_UI_TEST_MANIFEST = "androidx.compose.ui:ui-test-manifest:${Versions.COMPOSE}" @@ -60,6 +67,8 @@ object Dependencies { const val MOCKK = "io.mockk:mockk:${Versions.MOCKK}" const val MOCKK_ANDROID = "io.mockk:mockk-android:${Versions.MOCKK}" + const val MOKO_RESOURCES_TEST = "dev.icerock.moko:resources-test:${Versions.MOKO_RESOURCES}" + const val ROBOLECTRIC = "org.robolectric:robolectric:${Versions.ROBOLECTRIC}" const val TURBINE = "app.cash.turbine:turbine:${Versions.TURBINE}" diff --git a/buildSrc/src/main/java/Plugins.kt b/buildSrc/src/main/java/Plugins.kt index 671a93ab..ab2a1e6c 100644 --- a/buildSrc/src/main/java/Plugins.kt +++ b/buildSrc/src/main/java/Plugins.kt @@ -14,5 +14,7 @@ object Plugins { const val KOVER = "org.jetbrains.kotlinx.kover" const val KSP = "com.google.devtools.ksp" + const val MOKO = "dev.icerock.mobile.multiplatform-resources" + const val MULTIPLATFORM = "multiplatform" } diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt index 2bfae497..ba0f3739 100644 --- a/buildSrc/src/main/java/Versions.kt +++ b/buildSrc/src/main/java/Versions.kt @@ -33,6 +33,9 @@ object Versions { const val MOCKATIVE = "1.3.0" const val MOCKK = "1.13.3" + const val MOKO_RESOURCES = "0.23.0" + const val MOKO_GRAPHICS = "0.9.0" + const val NAPIER = "2.6.1" const val ROBOLECTRIC = "4.9.1" diff --git a/sample/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt b/sample/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt index 800e2bc7..4b53d538 100644 --- a/sample/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt +++ b/sample/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt @@ -4,8 +4,11 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview -import co.nimblehq.kmm.template.Greeting +import co.nimblehq.kmm.template.Strings +import co.nimblehq.kmm.template.getPlatform +import co.nimblehq.kmm.template.sharedres.SharedRes import co.nimblehq.kmm.template.ui.theme.ComposeTheme @Composable @@ -14,7 +17,12 @@ fun HomeScreen() { modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background ) { - Text(text = Greeting().greet()) + Text( + text = Strings(LocalContext.current).get( + id = SharedRes.strings.greeting, + args = listOf(getPlatform().name) + ) + ) } } diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts index 09329006..7fa6d01a 100644 --- a/sample/build.gradle.kts +++ b/sample/build.gradle.kts @@ -11,6 +11,12 @@ plugins { kotlin(Plugins.KOTLIN_SERIALIZATION) version Versions.KOTLIN } +buildscript { + dependencies { + classpath(Dependencies.Moko.RESOURCES_GENERATOR) + } +} + detekt { toolVersion = Versions.DETEKT config.setFrom("detekt.yml") diff --git a/sample/buildSrc/src/main/java/Dependencies.kt b/sample/buildSrc/src/main/java/Dependencies.kt index f7ae174a..b2c9fae8 100644 --- a/sample/buildSrc/src/main/java/Dependencies.kt +++ b/sample/buildSrc/src/main/java/Dependencies.kt @@ -45,6 +45,13 @@ object Dependencies { const val TIMBER = "com.jakewharton.timber:timber:${Versions.TIMBER}" } + object Moko { + const val RESOURCES_GENERATOR = "dev.icerock.moko:resources-generator:${Versions.MOKO_RESOURCES}" + const val RESOURCES = "dev.icerock.moko:resources:${Versions.MOKO_RESOURCES}" + const val RESOURCES_COMPOSE = "dev.icerock.moko:resources-compose:${Versions.MOKO_RESOURCES}" + const val GRAPHICS = "dev.icerock.moko:graphics:${Versions.MOKO_GRAPHICS}" + } + object Test { const val COMPOSE_UI_TEST_JUNIT = "androidx.compose.ui:ui-test-junit4:${Versions.COMPOSE}" const val COMPOSE_UI_TEST_MANIFEST = "androidx.compose.ui:ui-test-manifest:${Versions.COMPOSE}" @@ -60,6 +67,8 @@ object Dependencies { const val MOCKK = "io.mockk:mockk:${Versions.MOCKK}" const val MOCKK_ANDROID = "io.mockk:mockk-android:${Versions.MOCKK}" + const val MOKO_RESOURCES_TEST = "dev.icerock.moko:resources-test:${Versions.MOKO_RESOURCES}" + const val ROBOLECTRIC = "org.robolectric:robolectric:${Versions.ROBOLECTRIC}" const val TURBINE = "app.cash.turbine:turbine:${Versions.TURBINE}" diff --git a/sample/buildSrc/src/main/java/Plugins.kt b/sample/buildSrc/src/main/java/Plugins.kt index 671a93ab..ab2a1e6c 100644 --- a/sample/buildSrc/src/main/java/Plugins.kt +++ b/sample/buildSrc/src/main/java/Plugins.kt @@ -14,5 +14,7 @@ object Plugins { const val KOVER = "org.jetbrains.kotlinx.kover" const val KSP = "com.google.devtools.ksp" + const val MOKO = "dev.icerock.mobile.multiplatform-resources" + const val MULTIPLATFORM = "multiplatform" } diff --git a/sample/buildSrc/src/main/java/Versions.kt b/sample/buildSrc/src/main/java/Versions.kt index 2bfae497..ba0f3739 100644 --- a/sample/buildSrc/src/main/java/Versions.kt +++ b/sample/buildSrc/src/main/java/Versions.kt @@ -33,6 +33,9 @@ object Versions { const val MOCKATIVE = "1.3.0" const val MOCKK = "1.13.3" + const val MOKO_RESOURCES = "0.23.0" + const val MOKO_GRAPHICS = "0.9.0" + const val NAPIER = "2.6.1" const val ROBOLECTRIC = "4.9.1" diff --git a/sample/ios/sample/Configurations/Plists/Info.plist b/sample/ios/sample/Configurations/Plists/Info.plist index b18749da..79ad0959 100644 --- a/sample/ios/sample/Configurations/Plists/Info.plist +++ b/sample/ios/sample/Configurations/Plists/Info.plist @@ -24,8 +24,12 @@ armv7 - UILaunchStoryboardName - LaunchScreen + CFBundleLocalizations + + en + + UILaunchStoryboardName + LaunchScreen UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/sample/shared/build.gradle.kts b/sample/shared/build.gradle.kts index b9cca8ba..c2d6dae4 100644 --- a/sample/shared/build.gradle.kts +++ b/sample/shared/build.gradle.kts @@ -11,6 +11,7 @@ plugins { id(Plugins.KOVER) id(Plugins.KSP) id(Plugins.BUILD_KONFIG) + id(Plugins.MOKO) } @OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class) @@ -36,6 +37,8 @@ kotlin { podfile = project.file("../ios/Podfile") framework { baseName = "shared" + export(Dependencies.Moko.RESOURCES) + export(Dependencies.Moko.GRAPHICS) } xcodeConfigurationToNativeBuildType["Debug Staging"] = NativeBuildType.DEBUG @@ -59,6 +62,11 @@ kotlin { implementation(AUTH) } + with(Dependencies.Moko) { + api(RESOURCES) + // api(RESOURCES_COMPOSE) FIXME: Cannot build the shared module with this dependency + } + implementation(Dependencies.Log.NAPIER) } } @@ -71,6 +79,7 @@ kotlin { implementation(KOTLINX_RESOURCES) implementation(MOCKATIVE) implementation(TURBINE) + implementation(MOKO_RESOURCES_TEST) } } } @@ -145,3 +154,8 @@ buildkonfig { ) } } + +multiplatformResources { + multiplatformResourcesPackage = "co.nimblehq.kmm.template.sharedres" + multiplatformResourcesClassName = "SharedRes" +} diff --git a/sample/shared/src/androidMain/kotlin/co/nimblehq/kmm/template/Strings.kt b/sample/shared/src/androidMain/kotlin/co/nimblehq/kmm/template/Strings.kt new file mode 100644 index 00000000..12095024 --- /dev/null +++ b/sample/shared/src/androidMain/kotlin/co/nimblehq/kmm/template/Strings.kt @@ -0,0 +1,20 @@ +package co.nimblehq.kmm.template + +import android.content.Context +import dev.icerock.moko.resources.StringResource +import dev.icerock.moko.resources.desc.Resource +import dev.icerock.moko.resources.desc.StringDesc +import dev.icerock.moko.resources.format + +actual class Strings(private val context: Context) { + actual fun get( + id: StringResource, + args: List, + ): String { + return if (args.isEmpty()) { + StringDesc.Resource(id).toString(context = context) + } else { + id.format(*args.toTypedArray()).toString(context) + } + } +} diff --git a/sample/shared/src/commonMain/kotlin/co/nimblehq/kmm/template/Strings.kt b/sample/shared/src/commonMain/kotlin/co/nimblehq/kmm/template/Strings.kt new file mode 100644 index 00000000..2348968a --- /dev/null +++ b/sample/shared/src/commonMain/kotlin/co/nimblehq/kmm/template/Strings.kt @@ -0,0 +1,7 @@ +package co.nimblehq.kmm.template + +import dev.icerock.moko.resources.StringResource + +expect class Strings { + fun get(id: StringResource, args: List = emptyList()): String +} diff --git a/sample/shared/src/commonMain/resources/MR/base/strings.xml b/sample/shared/src/commonMain/resources/MR/base/strings.xml new file mode 100644 index 00000000..7b75c648 --- /dev/null +++ b/sample/shared/src/commonMain/resources/MR/base/strings.xml @@ -0,0 +1,3 @@ + + Hello, %s! + diff --git a/sample/shared/src/iosMain/kotlin/co/nimblehq/kmm/template/Strings.kt b/sample/shared/src/iosMain/kotlin/co/nimblehq/kmm/template/Strings.kt new file mode 100644 index 00000000..4c9d3a8d --- /dev/null +++ b/sample/shared/src/iosMain/kotlin/co/nimblehq/kmm/template/Strings.kt @@ -0,0 +1,19 @@ +package co.nimblehq.kmm.template + +import dev.icerock.moko.resources.StringResource +import dev.icerock.moko.resources.desc.Resource +import dev.icerock.moko.resources.desc.StringDesc +import dev.icerock.moko.resources.format + +actual class Strings { + actual fun get( + id: StringResource, + args: List, + ): String { + return if (args.isEmpty()) { + StringDesc.Resource(id).localized() + } else { + id.format(*args.toTypedArray()).localized() + } + } +} diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index b9cca8ba..c2d6dae4 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -11,6 +11,7 @@ plugins { id(Plugins.KOVER) id(Plugins.KSP) id(Plugins.BUILD_KONFIG) + id(Plugins.MOKO) } @OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class) @@ -36,6 +37,8 @@ kotlin { podfile = project.file("../ios/Podfile") framework { baseName = "shared" + export(Dependencies.Moko.RESOURCES) + export(Dependencies.Moko.GRAPHICS) } xcodeConfigurationToNativeBuildType["Debug Staging"] = NativeBuildType.DEBUG @@ -59,6 +62,11 @@ kotlin { implementation(AUTH) } + with(Dependencies.Moko) { + api(RESOURCES) + // api(RESOURCES_COMPOSE) FIXME: Cannot build the shared module with this dependency + } + implementation(Dependencies.Log.NAPIER) } } @@ -71,6 +79,7 @@ kotlin { implementation(KOTLINX_RESOURCES) implementation(MOCKATIVE) implementation(TURBINE) + implementation(MOKO_RESOURCES_TEST) } } } @@ -145,3 +154,8 @@ buildkonfig { ) } } + +multiplatformResources { + multiplatformResourcesPackage = "co.nimblehq.kmm.template.sharedres" + multiplatformResourcesClassName = "SharedRes" +} diff --git a/shared/src/androidMain/kotlin/co/nimblehq/kmm/template/Strings.kt b/shared/src/androidMain/kotlin/co/nimblehq/kmm/template/Strings.kt new file mode 100644 index 00000000..12095024 --- /dev/null +++ b/shared/src/androidMain/kotlin/co/nimblehq/kmm/template/Strings.kt @@ -0,0 +1,20 @@ +package co.nimblehq.kmm.template + +import android.content.Context +import dev.icerock.moko.resources.StringResource +import dev.icerock.moko.resources.desc.Resource +import dev.icerock.moko.resources.desc.StringDesc +import dev.icerock.moko.resources.format + +actual class Strings(private val context: Context) { + actual fun get( + id: StringResource, + args: List, + ): String { + return if (args.isEmpty()) { + StringDesc.Resource(id).toString(context = context) + } else { + id.format(*args.toTypedArray()).toString(context) + } + } +} diff --git a/shared/src/androidUnitTest/kotlin/co/nimblehq/kmm/template/androidTest.kt b/shared/src/androidUnitTest/kotlin/co/nimblehq/kmm/template/androidTest.kt deleted file mode 100644 index 900b0bb6..00000000 --- a/shared/src/androidUnitTest/kotlin/co/nimblehq/kmm/template/androidTest.kt +++ /dev/null @@ -1,12 +0,0 @@ -package co.nimblehq.kmm.template - -import org.junit.Assert.assertTrue -import org.junit.Test - -class AndroidGreetingTest { - - @Test - fun testExample() { - assertTrue("Check Android is mentioned", Greeting().greet().contains("Android")) - } -} diff --git a/shared/src/commonMain/kotlin/co/nimblehq/kmm/template/Strings.kt b/shared/src/commonMain/kotlin/co/nimblehq/kmm/template/Strings.kt new file mode 100644 index 00000000..2348968a --- /dev/null +++ b/shared/src/commonMain/kotlin/co/nimblehq/kmm/template/Strings.kt @@ -0,0 +1,7 @@ +package co.nimblehq.kmm.template + +import dev.icerock.moko.resources.StringResource + +expect class Strings { + fun get(id: StringResource, args: List = emptyList()): String +} diff --git a/shared/src/commonMain/resources/MR/base/strings.xml b/shared/src/commonMain/resources/MR/base/strings.xml new file mode 100644 index 00000000..7b75c648 --- /dev/null +++ b/shared/src/commonMain/resources/MR/base/strings.xml @@ -0,0 +1,3 @@ + + Hello, %s! + diff --git a/shared/src/commonTest/kotlin/co/nimblehq/kmm/template/commonTest.kt b/shared/src/commonTest/kotlin/co/nimblehq/kmm/template/commonTest.kt deleted file mode 100644 index 560187be..00000000 --- a/shared/src/commonTest/kotlin/co/nimblehq/kmm/template/commonTest.kt +++ /dev/null @@ -1,12 +0,0 @@ -package co.nimblehq.kmm.template - -import kotlin.test.Test -import kotlin.test.assertTrue - -class CommonGreetingTest { - - @Test - fun testExample() { - assertTrue(Greeting().greet().contains("Hello"), "Check 'Hello' is mentioned") - } -} diff --git a/shared/src/iosMain/kotlin/co/nimblehq/kmm/template/Strings.kt b/shared/src/iosMain/kotlin/co/nimblehq/kmm/template/Strings.kt new file mode 100644 index 00000000..4c9d3a8d --- /dev/null +++ b/shared/src/iosMain/kotlin/co/nimblehq/kmm/template/Strings.kt @@ -0,0 +1,19 @@ +package co.nimblehq.kmm.template + +import dev.icerock.moko.resources.StringResource +import dev.icerock.moko.resources.desc.Resource +import dev.icerock.moko.resources.desc.StringDesc +import dev.icerock.moko.resources.format + +actual class Strings { + actual fun get( + id: StringResource, + args: List, + ): String { + return if (args.isEmpty()) { + StringDesc.Resource(id).localized() + } else { + id.format(*args.toTypedArray()).localized() + } + } +} diff --git a/shared/src/iosTest/kotlin/co/nimblehq/kmm/template/iosTest.kt b/shared/src/iosTest/kotlin/co/nimblehq/kmm/template/iosTest.kt deleted file mode 100644 index 3922db12..00000000 --- a/shared/src/iosTest/kotlin/co/nimblehq/kmm/template/iosTest.kt +++ /dev/null @@ -1,12 +0,0 @@ -package co.nimblehq.kmm.template - -import kotlin.test.Test -import kotlin.test.assertTrue - -class IosGreetingTest { - - @Test - fun testExample() { - assertTrue(Greeting().greet().contains("iOS"), "Check iOS is mentioned") - } -}