El Arsenal de Android: localización

Los desaparecidos I18N y L10N biblioteca para Dial Jetpack!

Jetpack Compose ha mejorado enormemente la forma en que creamos interfaces de usuario en Android, pero no como nosotros interactuar con cadenas. stringResource() funciona bien, pero no se beneficia de Kotlin idiomático como Compose.

Lyricist intenta hacer que trabajar con cadenas sea tan poderoso como crear interfaces de usuario con Compose, es decir, trabajar con una cadena parametrizada ahora es independiente del tipo, el uso de when expresión para trabajar con plurales con más flexibilidad e incluso cargar / actualizar cadenas dinámicamente a través de una API.

Características

Mapa vial

Limitaciones

Cómo Letrista?

Inspirado por compañero biblioteca: la composición musical la realiza un compositor y, dado que esta biblioteca se trata de escritura Textos cuerdas, el papel de un letrista parecía un buen nombre.

usar

Eche un vistazo al aplicación de muestra Y muestra-multi-módulo para ejemplos de trabajo.

Comience declarando sus cadenas en un data class, class o interface (elige uno). Las cadenas pueden ser cualquier cosa (en realidad, depende de usted): Char, String, AnnotatedString, List<String>, Set<String> o incluso lambda!

data class Strings(
    val simple: String,
    val annotated: AnnotatedString,
    val parameter: (locale: String) -> String,
    val plural: (count: Int) -> String,
    val list: List<String>
)

Luego, cree instancias para cada idioma admitido y anote con @Strings. El languageTag debe ser un IETF BCP47 etiqueta de idioma compatible (documentos). Debe marcar uno como predeterminado.

@Strings(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) {
            1, 2 -> "few"
            in 3..10 -> "bunch of"
            else -> "lot of"
        }
        "I have a $value apples"
    },

    list = listOf("Avocado", "Pineapple", "Plum")
)

@Strings(languageTag = Locales.PT)
val PtStrings = Strings(/* pt strings */)

@Strings(languageTag = Locales.ES)
val EsStrings = Strings(/* es strings */)

@Strings(languageTag = Locales.RU)
val RuStrings = Strings(/* ru strings */)

El letrista generará el LocalStrings propiedad, una ComposiciónLocal que proporciona las cadenas de la configuración regional actual. También generará rememberStrings() Y ProvideStrings(), llámalos para hacer LocalStrings accesible por el árbol.

val lyricist = rememberStrings()

ProvideStrings(lyricist) {
    // Content
}
Escribe el código por ti mismo

¿No desea permitir que KSP genere el código por usted? ¡No hay problema! Siga los pasos a continuación para la integración manual con Lyricist.

Primero, asigna cada etiqueta de idioma admitida a las instancias correspondientes.

val strings = mapOf(
    Locales.EN to EnStrings,
    Locales.PT to PtStrings,
    Locales.ES to EsStrings,
    Locales.RU to RuStrings
)

Entonces, haz el tuyo LocalStrings y elija una traducción por defecto.

val LocalStrings = staticCompositionLocalOf { EnStrings }

Finalmente, use las mismas funciones, rememberStrings() Y ProvideStrings(), para hacer el tuyo LocalStrings accesible por el árbol. Pero esta vez tienes que aportar el tuyo strings Y LocalStrings a mano.

val lyricist = rememberStrings(strings)

ProvideStrings(lyricist, LocalStrings) {
    // Content
}

Ahora puedes usar LocalStrings para recuperar las cadenas actuales.

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

Usa la instancia de letrista proporcionada por rememberStrings() para cambiar la configuración regional actual. Esto desencadenará un volver a marcar que actualizará las cadenas dondequiera que se utilicen.

lyricist.languageTag = Locales.PT

Importante: El letrista usa la configuración regional del sistema de forma predeterminada. No mantendrá la configuración regional actual almacenada, está fuera de su alcance.

Configuración de varios módulos

Si está utilizando Lyricist en un proyecto de varios módulos y las declaraciones generadas (LocalStrings, rememberStrings(), ProvideStrings()) son demasiado genéricos para usted, proporcione los siguientes argumentos (opcionales) a KSP en los formularios build.gradle.

ksp {
    arg("lyricist.packageName", "com.my.app")
    arg("lyricist.moduleName", project.name)
}

Suponga que tiene un módulo de “tablero”, las declaraciones generadas serán LocalDashboardStrings, rememberDashboardStrings() Y ProvideDashboardStrings().

Migración desde strings.xml

Entonces, ¿te gustó Lyricist, pero ya tienes un proyecto con miles de cadenas repartidas en varios archivos? Tengo buenas noticias para ti: el letrista puede extraer estas cadenas existentes y generar todo el código que acabas de ver arriba.

Al igual que en la configuración de varios módulos, debe proporcionar algunos argumentos a KSP. El letrista buscará strings.xml archivo en la ruta de recursos. También puede proporcionar una etiqueta de idioma para utilizarla como predeterminada para LocalStrings.

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")
}

Después de la primera construcción, el conocido rememberStrings() Y ProvideStrings() (el nombre puede variar según la configuración de KSP) estará disponible para su uso. El letrista también generará un Locales objeto que contiene todas las etiquetas de idioma actualmente en uso en el proyecto.

val lyricist = rememberStrings(strings)

ProvideStrings(lyricist, LocalStrings) {
    // Content
}

lyricist.languageTag = Locales.PT

Puedes migrar fácilmente desde strings.xml a Lyricist simplemente copiando los archivos generados en su proyecto. De esta manera, finalmente puedes despedirte de strings.xml.

Solución de problemas

No puedo usar el código generado en mi IDE

Debe configurar manualmente los conjuntos de origen de los archivos generados, como se describe aquí.

buildTypes {
    debug {
        sourceSets {
            main.java.srcDirs += 'build/generated/ksp/debug/kotlin/'
        }
    }
    release {
        sourceSets {
            main.java.srcDirs += 'build/generated/ksp/release/kotlin/'
        }
    }
}

Importar a su proyecto

  1. Importación de Complemento KSP en el proyecto build.gradle luego aplica a tus formularios build.gradle
buildscript {
    dependencies {
        classpath "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:${ksp-latest-version}"
    }
}

apply plugin: "com.google.devtools.ksp"
  1. Agregue las dependencias deseadas a las de su módulo build.gradle
// Required
implementation "cafe.adriel.lyricist:lyricist:${latest-version}"

// If you want to use @Strings to generate code for you
compileOnly "cafe.adriel.lyricist:lyricist-processor:${latest-version}"
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}"

Versión actual:

.

Compruebe también

en vivo desde Droidcon, incluida la mayor actualización de Gemini en Android Studio y más lanzamientos del SDK de Android.

Acabamos de lanzar nuestro episodio de otoño de #TheAndroidShow en YouTube etcétera desarrollador.android.comy esta vez …

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *