Usar localizaciones y códigos de idioma en el SDK de Kotlin Multiplatform
Por qué esto es importante
Los códigos de configuración regional entran en juego cuando Adapty selecciona la localización para un flow o un onboarding, y cuando lees un Remote Config para un paywall personalizado.
Los códigos de configuración regional son complejos y pueden variar de una plataforma a otra, por lo que Adapty se basa en un estándar interno común para todas las plataformas que admite. Entender ese estándar te ayuda a predecir qué localización recibirá cada usuario.
Estándar de códigos de idioma en Adapty
Para los códigos de idioma, Adapty utiliza una versión ligeramente modificada del estándar BCP 47: cada código está formado por subetiquetas en minúsculas separadas por guiones. Algunos ejemplos: en (inglés), pt-br (portugués de Brasil), zh (chino simplificado), zh-hant (chino tradicional).
Coincidencia de códigos de configuración regional
En SDK v4, los flows y los onboardings hacen coincidir los códigos de configuración regional de forma diferente: los flows se localizan mediante el SDK en el dispositivo, mientras que los onboardings los localiza el servidor de Adapty.
Flows y paywalls del Paywall Builder
Un paywall creado en el Paywall Builder se entrega como flow en el SDK v4, por lo que la regla siguiente aplica a ambos.
La comparación es exacta. El SDK compara el código que pasas con los códigos de localización del flow carácter a carácter: no cambia las mayúsculas ni minúsculas, no reemplaza guiones bajos (_) por guiones (-) y no recurre al subtag de idioma. Para un flow con una localización pt-br, solo pt-br coincide: pt-BR, pt_BR y pt-PT no coinciden.
Cuando el código no coincide con ninguna localización, el flow se renderiza silenciosamente en su idioma predeterminado — el SDK no devuelve un error ni registra ninguna advertencia.
Cuando el código coincide, Adapty combina la localización con la predeterminada: las cadenas y los recursos que no estén definidos en la localización coincidente se toman de la localización predeterminada.
Omitir el código de idioma no es lo mismo que solicitar la localización predeterminada del flow: el SDK sustituye un en fijo. Un flow cuyo idioma predeterminado es de seguirá renderizándose en en si tiene una localización en en, y solo recurrirá a de cuando no la tenga.
Pasa el código de idioma exactamente como está configurado en el dashboard: subtags en minúsculas separados por guiones. No pases un identificador de idioma de plataforma tal cual: en Android, Locale.getDefault().toLanguageTag() devuelve pt-BR; en iOS, NSLocale.currentLocale.localeIdentifier devuelve pt_BR. Ambos recurren a la localización predeterminada. Convierte el valor en tu app antes de pasarlo.
Onboardings
Los onboardings se localizan en el servidor, y las reglas del servidor admiten otros formatos. Cuando pasas un locale a getOnboarding:
- La cadena de configuración regional se convierte a minúsculas y todos los guiones bajos (
_) se reemplazan con guiones (-) - Adapty busca la localización con el código de configuración regional que coincida exactamente
- Si no se encuentra ninguna coincidencia, Adapty toma la subcadena antes del primer guión (
ptparapt-br) y busca la localización correspondiente - Si tampoco se encuentra ninguna coincidencia, Adapty devuelve el contenido para la configuración regional predeterminada del onboarding
Esta forma, pt_BR, pt-BR, y pt-br se resuelven todas a la misma localización de onboarding.
Implementación de localizaciones
En SDK v4, no se pasa un código de configuración regional al obtener un flow — getFlow devuelve el flow con todas sus localizaciones, y Adapty aplica una cuando se construye la vista del flow.
-
Flows creados en el builder: el SDK no lee la configuración regional del dispositivo, así que resuélvela en tu app y pásala como parámetro
localedecreateFlowView. Es opcional — omítela y el flow se renderiza enen, o en su configuración regional predeterminada cuando el flow no tiene localización enen.import com.adapty.kmp.AdaptyUI AdaptyUI.createFlowView(flow = flow, locale = "es") .onSuccess { view -> view.present() } .onError { error -> // handle the error }
createNativeFlowView y el composable AdaptyUIFlowPlatformView aceptan el mismo parámetro opcional locale. view.locale indica la localización con la que se construyó la vista. Tanto el parámetro locale como view.locale requieren Kotlin Multiplatform SDK 4.0.1-beta.1 o posterior.
- Paywalls personalizados (Remote Config):
getFlowdevuelve todas las localizaciones configuradas enflow.remoteConfigs. Cada entrada es unAdaptyRemoteConfigcon un códigolocaley undataMap. Selecciona la entrada que corresponda al usuario con tu propia lógica de respaldo:
Adapty.getFlow("YOUR_PLACEMENT_ID")
.onSuccess { flow ->
val config = flow.remoteConfigs.firstOrNull { it.locale == "en" }
?: flow.remoteConfigs.firstOrNull()
// read your values from config?.dataMap
}
.onError { error ->
// handle the error
}Adapty almacena esos códigos locale en el formato descrito en Estándar de código de idioma en Adapty. El SDK no coteja los Remote Configs con un idioma, por lo que corresponde a tu app decidir qué entrada aplicar.
Por qué esto es importante
Hay algunos escenarios en los que los códigos de idioma entran en juego — por ejemplo, cuando intentas obtener el paywall correcto para la localización actual de tu app.
Como los códigos de idioma son complicados y pueden variar de una plataforma a otra, nos basamos en un estándar interno para todas las plataformas que soportamos. Sin embargo, precisamente por esa complejidad, es muy importante que entiendas exactamente qué le estás enviando a nuestro servidor para obtener la localización correcta y qué ocurre después — así siempre recibirás lo que esperas.
Estándar de códigos de idioma en Adapty
Para los códigos de idioma, Adapty utiliza una versión ligeramente modificada del estándar BCP 47: cada código se compone de subetiquetas en minúsculas separadas por guiones. Algunos ejemplos: en (inglés), pt-br (portugués (Brasil)), zh (chino simplificado), zh-hant (chino tradicional).
Correspondencia de códigos de idioma
Cuando Adapty recibe una llamada del SDK con el código de idioma y comienza a buscar la localización correspondiente de un paywall, ocurre lo siguiente:
- La cadena de idioma entrante se convierte a minúsculas y todos los guiones bajos (
_) se reemplazan por guiones (-) - A continuación, buscamos la localización con el código de idioma que coincida exactamente
- Si no se encuentra ninguna coincidencia, tomamos la subcadena antes del primer guión (
ptparapt-br) y buscamos la localización que coincida - Si tampoco se encuentra ninguna coincidencia, devolvemos el contenido para el idioma predeterminado del paywall
De este modo, un dispositivo iOS que envió 'pt_BR', un dispositivo Android que envió pt-BR, y otro dispositivo que envió pt-br obtendrán el mismo resultado.
Implementación de localizaciones: forma recomendada
Si te estás preguntando sobre las localizaciones, lo más probable es que ya estés gestionando recursos de cadenas localizadas en tu proyecto. Si ese es el caso, te recomendamos incluir un par clave-valor con el código de locale de Adapty correspondiente en cada uno de tus archivos de recursos para las localizaciones que uses. Luego, extrae el valor de esa clave al llamar a nuestro SDK, así:
// 1. Add the Adapty locale code to your Compose Multiplatform resources
/*
composeResources/values/strings.xml (default — English)
*/
<string name="adapty_paywalls_locale">en</string>
/*
composeResources/values-es/strings.xml (Spanish)
*/
<string name="adapty_paywalls_locale">es</string>
/*
composeResources/values-pt-rBR/strings.xml (Portuguese — Brazil)
*/
<string name="adapty_paywalls_locale">pt-br</string>
// 2. Extract and use the locale code
suspend fun fetchPaywall() {
val locale = getString(Res.string.adapty_paywalls_locale)
Adapty.getPaywall(
placementId = "YOUR_PLACEMENT_ID",
locale = locale
).onSuccess { paywall ->
// el paywall solicitado
}.onError { error ->
// gestionar el error
}
}De este modo, tienes control total sobre qué localización se recuperará para cada usuario de tu app.
Si no usas recursos de Compose Multiplatform, la misma idea aplica a cualquier biblioteca de localización que uses (por ejemplo, moko-resources): guarda el código de idioma de Adapty como una cadena en el bundle de recursos de cada idioma y léelo antes de llamar al SDK.
Otra forma de implementar las localizaciones
Puedes obtener resultados similares (aunque no idénticos) sin definir explícitamente códigos de idioma para cada localización. Esto implica extraer el código de idioma directamente del dispositivo, lo que requiere declaraciones expect/actual, ya que no existe una API de idioma compartida en commonMain:
// commonMain
expect fun currentLocaleTag(): String
// androidMain
actual fun currentLocaleTag(): String = Locale.getDefault().toLanguageTag()
// iosMain
actual fun currentLocaleTag(): String = NSLocale.currentLocale.localeIdentifier
// commonMain — pass the locale code to Adapty
suspend fun fetchPaywall() {
Adapty.getPaywall(
placementId = "YOUR_PLACEMENT_ID",
locale = currentLocaleTag()
).onSuccess { paywall ->
// the requested paywall
}.onError { error ->
// handle the error
}
}Ten en cuenta que no recomendamos este enfoque por varias razones:
- En iOS, el idioma preferido del usuario y el locale regional del dispositivo no son idénticos.
NSLocale.currentLocale.localeIdentifierdevuelve el locale regional, que puede diferir del idioma en que los usuarios leen tu app. Las apps iOS que usan archivos de cadenas localizadas dependen de la lógica de resolución de Apple para combinar ambos, lo que funciona de forma automática con el enfoque recomendado anteriormente. - Es difícil predecir exactamente qué devolverá el dispositivo y si coincide con una localización de Adapty. El locale del dispositivo puede incluir extensiones o códigos regionales que no hayas configurado en Adapty; en ese caso, el SDK recurre a la coincidencia del primer subtag o, en último término, a
en. Should you decide to use this approach anyway — make sure you’ve covered all the relevant use cases.