Usar localizaciones y códigos de idioma en el SDK de iOS

Por qué esto es importante

Los códigos de idioma entran en juego cuando Adapty elige la localización para un flow o un onboarding, y cuando lees un Remote Config para un paywall personalizado.

Los códigos de idioma son complejos y pueden variar de una plataforma a otra, por lo que Adapty utiliza un estándar interno único para todas las plataformas que soporta. 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 idioma

En SDK v4, los flows y los onboardings hacen coincidir los códigos de idioma de manera diferente: los flows se localizan mediante el SDK en el dispositivo, y los onboardings mediante el servidor de Adapty.

Flows y paywalls del Paywall Builder

Un paywall creado en el Paywall Builder se entrega como un flow en el SDK v4, por lo que la regla a continuación cubre ambos casos.

La coincidencia es exacta. El SDK compara el código que pasas con los códigos de localización del flow carácter por carácter: no cambia las mayúsculas o minúsculas, no reemplaza los guiones bajos (_) por guiones (-) y no recurre solo a la subtiqueta de idioma. Para un flow con una localización pt-br, solo pt-br coincide: pt-BR, pt_BR y pt-PT no lo hacen.

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 fusiona la localización con la predeterminada: las cadenas de texto y los recursos que la localización coincidente no define se obtienen 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 se seguirá mostrando en en si tiene una localización en en, y solo recurre a de cuando no la tiene.

Warning

Pasa el código de localización exactamente tal como está configurado en el dashboard — subtags en minúscula separados por guiones. No pases un identificador de localización del sistema tal cual: Locale.current.identifier devuelve pt_BR y Locale.current.identifier(.bcp47) devuelve pt-BR, y 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:

  1. La cadena de locale se convierte a minúsculas y todos los guiones bajos (_) se reemplazan por guiones (-)
  2. Adapty busca la localización con el código de locale que coincida exactamente
  3. Si no se encuentra ninguna coincidencia, Adapty toma la subcadena antes del primer guión (pt para pt-br) y busca la localización correspondiente
  4. Si tampoco se encuentra ninguna coincidencia, Adapty devuelve el contenido para el locale predeterminado del onboarding

Este enfoque permite que pt_BR, pt-BR y pt-br resuelvan a la misma localización del onboarding.

Implementación de localizaciones

En SDK v4, no pasas un código de idioma al obtener un flow — getFlow devuelve el flow con todas sus localizaciones.

  • Flows creados en el builder: el SDK no lee el idioma del dispositivo, así que resuélvelo en tu app y pásalo a AdaptyUI.getFlowConfiguration(forFlow:locale:). El parámetro es opcional — omítelo y el flow se renderiza en en, o en su idioma predeterminado si el flow no tiene localización para en.
  • Paywalls personalizados (Remote Config): getFlow devuelve todas las localizaciones configuradas en flow.remoteConfigs. Cada entrada tiene un código locale y el contenido del config (jsonString, o el dictionary ya parseado). Selecciona la entrada que corresponde al usuario con tu propio fallback:
do {
    let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID")
    let config = flow.remoteConfigs.first(where: { $0.locale == "en" })
        ?? flow.remoteConfigs.first
    // read your values from config?.dictionary
} catch {
    // 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 compara los Remote Configs con un idioma concreto, así que tu app decide qué entrada aplicar.

Por qué 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 qué estás enviando exactamente a nuestro servidor para obtener la localización correcta y qué ocurre después, de modo que siempre recibas 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 está formado por subetiquetas en minúsculas separadas por guiones. Algunos ejemplos: en (inglés), pt-br (portugués (Brasil)), zh (chino simplificado), zh-hant (chino tradicional).

Coincidencia de código de localización

Cuando Adapty recibe una llamada desde el SDK con el código de localización y comienza a buscar la localización correspondiente de un paywall, ocurre lo siguiente:

  1. La cadena de localización entrante se convierte a minúsculas y todos los guiones bajos (_) se reemplazan por guiones (-)
  2. A continuación, se busca la localización con el código de localización que coincida exactamente
  3. Si no se encuentra ninguna coincidencia, se toma la subcadena anterior al primer guión (pt para pt-br) y se busca la localización coincidente
  4. Si tampoco se encuentra ninguna coincidencia, se devuelve el contenido con la localización predeterminada del paywall

De este modo, un dispositivo iOS que envíe 'pt_BR', un dispositivo Android que envíe pt-BR y otro dispositivo que envíe pt-br obtendrán el mismo resultado.

Si te estás preguntando por las localizaciones, lo más probable es que ya estés trabajando con archivos de cadenas localizadas en tu proyecto. En ese caso, te recomendamos añadir un par clave-valor con el código de idioma de Adapty correspondiente en cada uno de tus archivos para las localizaciones respectivas, y luego extraer el valor de esa clave al llamar a nuestro SDK, como se muestra aquí:

// 1. Modify your Localizable.strings files

/*
Localizable.strings - Spanish
*/
adapty_paywalls_locale = "es";
/*
Localizable.strings - Portuguese (Brazil)
*/
adapty_paywalls_locale = "pt-br";
// 2. Extract and use the locale code
let locale = NSLocalizedString("adapty_paywalls_locale", comment: "")
// pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method

Así tienes el control total sobre qué localización se obtendrá para cada usuario de tu app.

Implementar localizaciones: la otra forma

Puedes obtener resultados similares (aunque no idénticos) sin definir explícitamente los códigos de idioma para cada localización. Esto implica extraer un código de idioma de otros objetos que proporciona tu plataforma, como en este ejemplo:

let locale = Locale.current.identifier
// pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method

No recomendamos este enfoque por varios motivos:

  1. En iOS, los idiomas preferidos y el idioma actual no son idénticos. Si quieres que la localización se seleccione correctamente, tendrás que apoyarte en la lógica de Apple, que funciona de manera automática si usas el enfoque recomendado con archivos de cadenas localizadas, o bien recrearla tú mismo.
  2. Es difícil predecir exactamente qué recibirá el servidor de Adapty. Por ejemplo, en iOS es posible obtener un código como ar_OM@numbers='latn' en un dispositivo y enviarlo a nuestro servidor. Para esa llamada no obtendrás la localización ar-om que buscabas, sino ar, lo cual probablemente no es lo que esperabas.

Should you decide to use this approach anyway — make sure you’ve covered all the relevant use cases.