### Lyricist Usage with Generated Strings (Kotlin) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Example of how to use the strings generated by Lyricist. It demonstrates remembering the string instance, providing it to the composition, and changing the language tag. ```kotlin val lyricist = rememberStrings(strings) ProvideStrings(lyricist, LocalStrings) { // Content } lyricist.languageTag = Locales.PT ``` -------------------------------- ### Multiplatform Setup for Lyricist Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Configure Lyricist for multiplatform projects by adding the processor to `commonMain` metadata dependencies and setting up Kotlin compile tasks. This ensures code generation occurs correctly for shared code. ```kotlin dependencies { add("kspCommonMainMetadata", "cafe.adriel.lyricist:lyricist-processor:${latest-version}") } tasks.withType>().all { if(name != "kspCommonMainKotlinMetadata") { dependsOn("kspCommonMainKotlinMetadata") } } kodlin.sourceSets.commonMain { kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin") } ``` -------------------------------- ### ProvideStrings: Manual CompositionLocal Setup in Jetpack Compose Source: https://context7.com/adrielcafe/lyricist/llms.txt The `ProvideStrings` composable manually sets up localized strings using `CompositionLocal`. It requires defining a `CompositionLocal` provider and wrapping the app content with `ProvideStrings`, making strings accessible throughout the composition tree. Dependencies include Compose UI and the Lyricist library. ```kotlin import androidx.compose.foundation.layout.Column import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.staticCompositionLocalOf import cafe.adriel.lyricist.ProvideStrings import cafe.adriel.lyricist.rememberStrings // Define CompositionLocal val LocalStrings = staticCompositionLocalOf { translations["en"]!! } @Composable fun RootApp() { val lyricist = rememberStrings( translations = translations, defaultLanguageTag = "en" ) // Provide strings to entire tree ProvideStrings( lyricist = lyricist, provider = LocalStrings ) { AppContent() } } @Composable fun AppContent() { // Access strings from anywhere in the tree val strings = LocalStrings.current Column { Text(text = strings.welcome) Text(text = strings.greeting("John")) Text(text = strings.itemCount(5)) } } @Composable fun NestedComponent() { // Strings automatically available in nested composables val strings = LocalStrings.current Text(text = strings.welcome) } ``` -------------------------------- ### Example Android XML String Resources Source: https://context7.com/adrielcafe/lyricist/llms.txt Demonstrates the structure of Android XML string resource files, including simple strings, parameterized strings, plurals, and string arrays. These files are the source from which Lyricist will generate Kotlin code. ```xml // Existing XML resources structure: // res/values/strings.xml /* Hello World Hello %1$s, you have %2$d items in %3$s No items One item %d items First Second Third */ // res/values-es/strings.xml /* Hola Mundo Hola %1$s, tienes %2$d artículos en %3$s */ ``` -------------------------------- ### Supporting Other UI Toolkits - String Mapping (Kotlin) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Map language tags to string instances when supporting UI toolkits other than Jetpack Compose. This setup is required for custom Lyricist instances. ```kotlin val translations = mapOf( Locales.EN to EnStrings, Locales.PT to PtStrings, Locales.ES to EsStrings, Locales.RU to RuStrings ) ``` -------------------------------- ### Supporting Other UI Toolkits - Collecting State (Kotlin) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Collect the Lyricist state to refresh the UI when language or strings change. This example shows how to collect state for Compose and general UI updates. ```kotlin lyricist.state.collect { refreshUi(it.strings) } // Example for Compose val state by lyricist.state.collectAsState() CompositionLocalProvider( LocalStrings provides state.strings ) { // Content } ``` -------------------------------- ### Providing and Accessing Localized Strings in Compose (Kotlin) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Lyricist generates a LocalStrings CompositionLocal to access strings based on the current locale. Use rememberStrings() to get the Lyricist instance and ProvideStrings() to make LocalStrings available down the composable tree. Example shows accessing simple, annotated, parameterized, plural, and list strings. ```kotlin val lyricist = rememberStrings() ProvideStrings(lyricist) { // Content } // Or just ProvideStrings { // Content } val strings = LocalStrings.current Text(text = strings.simple) // > Hello Compose! Text(text = strings.annotated) // > Hello Compose! Text(text = strings.parameter(lyricist.languageTag)) // > Current locale: en Text(text = strings.plural(1)) Text(text = strings.plural(5)) Text(text = strings.plural(20)) // > I have a few apples // > I have a bunch of apples // > I have a lot of apples Text(text = strings.list.joinToString()) // > Avocado, Pineapple, Plum ``` -------------------------------- ### Configure Gradle for XML String Extraction (Kotlin) Source: https://context7.com/adrielcafe/lyricist/llms.txt Configures the Kotlin build script to enable the KSP plugin and specify paths for Android resources. This setup is essential for Lyricist to locate and process your XML string files. It defines the module name and default language tag for the generated code. ```kotlin // build.gradle.kts android { sourceSets { getByName("main") { res.srcDirs("src/main/res") } } } ksp { // Point to your Android resources directory arg("lyricist.xml.resourcesPath", android.sourceSets.main.res.srcDirs.first().absolutePath) arg("lyricist.xml.moduleName", "xml") arg("lyricist.xml.defaultLanguageTag", "en") arg("lyricist.xml.generateComposeAccessors", "true") } ``` -------------------------------- ### KSP Configuration for Kotlin Multiplatform Projects Source: https://context7.com/adrielcafe/lyricist/llms.txt Configure KSP for Kotlin Multiplatform projects to ensure code generation occurs only in `commonMain`, preventing duplication across different targets. This setup is crucial for managing shared resources effectively in a multiplatform environment. ```kotlin // build.gradle.kts for multiplatform module plugins { kotlin("multiplatform") id("com.google.devtools.ksp") } kotlin { androidTarget() jvm("desktop") iosX64() iosArm64() iosSimulatorArm64() js(IR) { browser() } sourceSets { val commonMain by getting { dependencies { implementation("cafe.adriel.lyricist:lyricist:1.7.0") } // Add generated KSP sources kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin") } } } dependencies { // Generate code only for commonMain to avoid duplication add("kspCommonMainMetadata", "cafe.adriel.lyricist:lyricist-processor:1.7.0") } // Ensure all compilation tasks depend on KSP generation tasks.withType>().all { if (name != "kspCommonMainKotlinMetadata") { dependsOn("kspCommonMainKotlinMetadata") } } // Usage in commonMain // src/commonMain/kotlin/Strings.kt @LyricistStrings(languageTag = "en", default = true) val EnStrings = Strings( welcome = "Welcome", platform: String = "Multiplatform App" ) @LyricistStrings(languageTag = "es") val EsStrings = Strings( welcome = "Bienvenido", platform = "Aplicación Multiplataforma" ) // Generated code works across all platforms @Composable fun MultiplatformApp() { val lyricist = rememberStrings() // Generated for commonMain ProvideStrings(lyricist) { Text(LocalStrings.current.welcome) } } ``` -------------------------------- ### Defining Locale-Specific Strings with @LyricistStrings in Kotlin Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Create instances of your string data class for each supported language, marking one as the default. Use @LyricistStrings with an IETF BCP47 compliant language tag. The example demonstrates defining strings for English, Portuguese, Spanish, and Russian. ```kotlin @LyricistStrings(languageTag = Locales.EN, default = true) val EnStrings = Strings( simple = "Hello Compose!", annotated = buildAnnotatedString { withStyle(SpanStyle(color = Color.Red)) { append("Hello ") } withStyle(SpanStyle(fontWeight = FontWeight.Light)) { append("Compose!") } }, parameter = { locale -> "Current locale: $locale" }, plural = { count -> val value = when (count) { 0 -> "no" 1, 2 -> "a few" in 3..10 -> "a bunch of" else -> "a lot of" } "I have $value apples" }, list = listOf("Avocado", "Pineapple", "Plum") ) @LyricistStrings(languageTag = Locales.PT) val PtStrings = Strings(/* pt strings */) @LyricistStrings(languageTag = Locales.ES) val EsStrings = Strings(/* es strings */) @LyricistStrings(languageTag = Locales.RU) val RuStrings = Strings(/* ru strings */) ``` -------------------------------- ### Direct Lyricist Integration in Android Application Source: https://context7.com/adrielcafe/lyricist/llms.txt Initializes Lyricist as a singleton instance within an Android Application class for use across the application. It demonstrates setting a default language and applying a saved locale preference upon initialization. This setup ensures the Lyricist instance is readily available throughout the application lifecycle. ```kotlin import cafe.adriel.lyricist.Lyricist import kotlinx.coroutines.flow.collect import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch class MyApplication : Application() { // Create singleton instance companion object { lateinit var lyricist: Lyricist } override fun onCreate() { super.onCreate() // Initialize with saved preference val savedLocale = getSharedPreferences("app", MODE_PRIVATE) .getString("locale", "en") ?: "en" lyricist = Lyricist( defaultLanguageTag = "en", translations = translations ).apply { languageTag = savedLocale } } } ``` -------------------------------- ### KSP 2.0 Configuration (Gradle Properties) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Recommended `gradle.properties` configuration for Lyricist using KSP 2.0. These settings enable K2 compiler compatibility, incremental compilation, and control logging for improved performance and build times. ```properties # Enable KSP 2.0 architecture for K2 compiler compatibility and performance improvements ksp.useKsp2=true # Enable incremental compilation for dramatically faster builds (20-50% improvement) # Only reprocesses changed files instead of regenerating everything from scratch ksp.incremental=true # Disable incremental compilation logging for cleaner build output # Enable temporarily (ksp.incremental.log=true) when debugging KSP issues ksp.incremental.log=false ``` -------------------------------- ### Manual Lyricist Integration - Providing Strings (Kotlin) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Use `rememberStrings` and `ProvideStrings` manually by providing the custom strings map and LocalStrings instance. This allows Lyricist to be integrated without KSP. ```kotlin val lyricist = rememberStrings(strings) ProvideStrings(lyricist, LocalStrings) { // Content } ``` -------------------------------- ### Configure Lyricist for Multi-Module Projects (Gradle) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Configure Lyricist KSP arguments in a module's build.gradle file to customize generated string declarations. This allows for module-specific naming conventions, improving clarity in multi-module projects. ```gradle ksp { arg("lyricist.packageName", "com.my.app") arg("lyricist.moduleName", project.name) } ``` -------------------------------- ### Migrate from strings.xml using Lyricist (Gradle) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Configure Lyricist KSP arguments to extract strings from existing strings.xml files. This process generates Compose accessors and provides options to disable generation and set a default language tag. ```gradle ksp { // Required arg("lyricist.xml.resourcesPath", android.sourceSets.main.res.srcDirs.first().absolutePath) // Optional arg("lyricist.packageName", "com.my.app") arg("lyricist.xml.moduleName", "xml") arg("lyricist.xml.defaultLanguageTag", "en") arg("lyricist.xml.generateComposeAccessors", "false") } ``` -------------------------------- ### Manual Lyricist Integration - LocalStrings Creation (Kotlin) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Create a static CompositionLocal for LocalStrings, specifying a default translation. This is part of the manual integration process when not using KSP. ```kotlin val LocalStrings = staticCompositionLocalOf { EnStrings } ``` -------------------------------- ### Supporting Other UI Toolkits - Lyricist Instance (Kotlin) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Create an instance of the Lyricist class, providing the default language tag and the translations map. This instance can be a singleton or local to a module. ```kotlin val lyricist = Lyricist(defaultLanguageTag, translations) ``` -------------------------------- ### Apply KSP Plugin in Project Gradle Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Integrate the KSP plugin into your project by applying it in the project-level `build.gradle` file. This is a prerequisite for using KSP processors in your modules. ```kotlin plugins { id("com.google.devtools.ksp") version "${ksp-latest-version}" } ``` -------------------------------- ### Manual Lyricist Integration - String Mapping (Kotlin) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Manually map language tags to their corresponding string instances when integrating Lyricist without KSP generation. This is the first step in custom integration. ```kotlin val strings = mapOf( Locales.EN to EnStrings, Locales.PT to PtStrings, Locales.ES to EsStrings, Locales.RU to RuStrings ) ``` -------------------------------- ### Add Lyricist Dependencies Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Include the necessary Lyricist dependencies in your module's `build.gradle` file. This includes the core library and the processor for code generation or XML migration. ```gradle // Required implementation("cafe.adriel.lyricist:lyricist:${latest-version}") // If you want to use @LyricistStrings to generate code for you ksp("cafe.adriel.lyricist:lyricist-processor:${latest-version}") // If you want to migrate from strings.xml ksp("cafe.adriel.lyricist:lyricist-processor-xml:${latest-version}") ``` -------------------------------- ### Enable KSP 2.0 and Incremental Builds Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Configure KSP settings to enable version 2.0 and incremental compilation for faster builds. Debugging flags can be temporarily enabled to diagnose incremental compilation issues, but should be disabled after use to avoid excessive output. ```properties ksp.useKsp2=true ksp.incremental=true ksp.incremental.log=true ksp.verbose=true ``` -------------------------------- ### Generating a 'strings' Helper Property in Gradle (Kotlin) Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Enable the generation of a convenient 'strings' property as an alternative to using LocalStrings.current. This is done by adding the 'lyricist.generateStringsProperty' argument to KSP in your module's build.gradle. ```gradle ksp { arg("lyricist.generateStringsProperty", "true") } ``` -------------------------------- ### Configure IDE Source Sets for Generated Files Source: https://github.com/adrielcafe/lyricist/blob/main/README.md Manually set the source sets for generated files in your IDE to resolve issues where generated code is not recognized. This is crucial for build systems like KSP to properly locate and compile generated code. ```gradle buildTypes { debug { sourceSets { main.java.srcDirs += 'build/generated/ksp/debug/kotlin/' } } release { sourceSets { main.java.srcDirs += 'build/generated/ksp/release/kotlin/' } } } ``` -------------------------------- ### KSP Configuration for Multi-module Android Projects Source: https://context7.com/adrielcafe/lyricist/llms.txt Configure KSP arguments in `build.gradle.kts` for multi-module Android projects. This allows customization of generated code names, control over visibility, generation of a strings helper property, and configuration for XML migration. ```kotlin // build.gradle.kts plugins { id("com.google.devtools.ksp") version "1.9.20-1.0.14" } dependencies { // Core library implementation("cafe.adriel.lyricist:lyricist:1.7.0") // Code generation processor ksp("cafe.adriel.lyricist:lyricist-processor:1.7.0") // XML migration processor (optional) ksp("cafe.adriel.lyricist:lyricist-processor-xml:1.7.0") } // Configure KSP options ksp { // Multi-module: customize generated names arg("lyricist.packageName", "com.myapp.feature.dashboard") arg("lyricist.moduleName", "Dashboard") // Generates: LocalDashboardStrings, rememberDashboardStrings(), ProvideDashboardStrings() // Control visibility: make generated code internal arg("lyricist.internalVisibility", "true") // Generate strings helper property arg("lyricist.generateStringsProperty", "true") // Enables: Text(text = strings.hello) instead of LocalStrings.current.hello // XML migration configuration arg("lyricist.xml.resourcesPath", "${projectDir}/src/main/res") arg("lyricist.xml.moduleName", "xml") arg("lyricist.xml.defaultLanguageTag", "en") arg("lyricist.xml.generateComposeAccessors", "true") } // KSP 2.0 optimization settings // gradle.properties /* ksp.useKsp2=true ksp.incremental=true ksp.incremental.log=false */ ``` -------------------------------- ### Migrate XML Strings to Compose with Lyricist (Kotlin) Source: https://context7.com/adrielcafe/lyricist/llms.txt Shows how to use the generated Lyricist code within a Jetpack Compose Composable function. It demonstrates accessing simple strings, parameterized strings, plurals, and string arrays, as well as changing the current locale. ```kotlin // KSP generates XmlStrings data class and accessors @Composable fun MigratedApp() { // Generated automatically from XML val lyricist = rememberXmlStrings() ProvideXmlStrings(lyricist) { val strings = LocalXmlStrings.current Column { // Simple string Text(text = strings.simple) // Parameterized string Text(text = strings.params("John", 5, "cart")) // Plural handling Text(text = strings.plurals(0)) // "No items" Text(text = strings.plurals(1)) // "One item" Text(text = strings.plurals(5)) // "5 items" // String array Text(text = strings.array.joinToString()) // "First, Second, Third" } // Generated Locales object contains all available language tags Button(onClick = { lyricist.languageTag = Locales.ES }) { Text("Español") } } } // After migration, copy generated code to source and remove XML // Build directory: build/generated/ksp/debug/kotlin/... ``` -------------------------------- ### Using Lyricist in Android Activities with Traditional Views Source: https://context7.com/adrielcafe/lyricist/llms.txt Shows how to access and use localized strings within an Android Activity that employs traditional Views. It includes setting text for TextViews, formatting strings with parameters, observing locale changes via a Flow, and switching the application's locale with preference persistence. This enables seamless localization in legacy Android projects. ```kotlin // Use in Activities with traditional views class MainActivity : AppCompatActivity() { private val lyricist get() = MyApplication.lyricist override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Access strings directly val strings = lyricist.strings findViewById(R.id.title).text = strings.welcome findViewById(R.id.greeting).text = strings.greeting("User") // Observe locale changes lifecycleScope.launch { lyricist.state.collect { updateUIWithNewStrings(it.strings) } } // Switch locale button findViewById