Preferencias de idioma de las apps

Idiomas de las apps en la configuración del sistema

En muchos casos, los usuarios multilingües configuran un idioma para su sistema, como el inglés, pero desean seleccionar otros para apps específicas, como el chino, el hindi o el holandés. Con el fin de ayudar a que las apps brinden una mejor experiencia para estos usuarios, Android 13 presenta las siguientes funciones en las apps que admiten varios idiomas:

  • Configuración del sistema: Una ubicación centralizada en la que los usuarios pueden seleccionar un idioma preferido para cada app.

    Puedes configurar tu app para que genere automáticamente los archivos necesarios para admitir las preferencias de idioma de la app y mostrarlos en la configuración del sistema. Si quieres obtener más información, consulta las instrucciones para habilitar la compatibilidad automática de idioma de las apps.

  • APIs adicionales: Estas APIs públicas, al igual que los métodos setApplicationLocales() y getApplicationLocales() en LocaleManager, permiten que las apps configuren un idioma diferente del idioma del sistema en el tiempo de ejecución.

    Estas APIs se sincronizan automáticamente con la configuración del sistema. Por lo tanto, las apps que las usan para crear selectores de idioma personalizados integrados en la app garantizarán que los usuarios tengan una experiencia del usuario coherente, sin importar dónde seleccionen sus preferencias de idioma. Las APIs públicas también ayudan a reducir la cantidad de código estándar, admiten APKs divididos y copias de seguridad automáticas para apps con el objetivo de almacenar los parámetros de configuración de idiomas del usuario en el nivel de app.

    Para ofrecer retrocompatibilidad con versiones anteriores de Android, las APIs equivalentes también están disponibles en AndroidX. Sin embargo, las APIs retrocompatibles funcionan con el contexto AppCompatActivity, no el contexto de la aplicación, para Android 12 (nivel de API 32) y versiones anteriores. Accede a las APIs retrocompatibles con Appcompat 1.6.0 o versiones posteriores.

Descripción general de la implementación de esta función

En la siguiente tabla, se muestran implementaciones recomendadas, según diferentes casos de uso.

Caso de uso Implementación recomendada
Tu app no tiene un selector de idioma integrado
  1. Habilita la compatibilidad automática de idioma de las apps para generar un archivo LocaleConfig y agregar los idiomas de tu app a la configuración del sistema.
  2. De manera opcional, si deseas agregar un selector de idioma integrado en la app: Usa la biblioteca de AndroidX y habilita nuestra implementación de API para admitir la retrocompatibilidad a través de autoStoreLocales.
Tu app ya incluye un selector de idioma integrado
  1. Habilita la compatibilidad automática de idioma de las apps para generar un archivo LocaleConfig y agregar los idiomas de tu app a la configuración del sistema.
  2. Migra la lógica personalizada de tu app para usar las APIs públicas y garantizar que los usuarios disfruten una experiencia coherente.
  3. Controla los siguientes casos límite:
    1. Llama a AppCompatDelegate.setApplicationLocales() la primera vez que se ejecute tu app en un dispositivo con Android 13.
    2. Llama a AppCompatDelegate.setApplicationLocales() para proporcionarle al sistema los parámetros preexistentes de configuración regional que solicitó el usuario en los siguientes casos:

Configuración del sistema para usuarios

A partir de Android 13, el sistema operativo incluye una ubicación centralizada en la configuración del sistema para preferencias de idioma de las apps. Para asegurarte de que se puedan configurar los idiomas en los parámetros de configuración del sistema en dispositivos que ejecutan Android 13 o versiones posteriores, habilita la compatibilidad automática de idioma de las apps (recomendado) o configura la compatibilidad de forma manual.

Cómo habilitar la compatibilidad automática de idioma de las apps

A partir de Android Studio Giraffe y AGP 8.1, puedes configurar tu app para que admita automáticamente las preferencias de idioma de las apps. En función de los recursos de tu proyecto, AGP genera el archivo LocaleConfig y le agrega una referencia en el archivo de manifiesto final, por lo que ya no tienes que hacerlo de forma manual. AGP usa los recursos de las carpetas res de los módulos de tu app y las dependencias de módulos de biblioteca para determinar las configuraciones regionales que se incluirán en el archivo LocaleConfig. Esto significa que, si agregas recursos para un idioma nuevo a tu app, no tendrás que preocuparte por actualizar el archivo LocaleConfig.

Ten en cuenta que la función automática de idioma de las apps admite apps que ejecutan Android 13 (nivel de API 33) o versiones posteriores. Para usar la función, debes establecer compileSdkVersion en 33 o un valor superior. Para configurar las preferencias de idioma de las apps en versiones anteriores de Android, debes usar las APIs y los selectores de idioma integrados en la app.

Para habilitar la compatibilidad automática de idioma de las apps, sigue estos pasos:

  1. Para activar la función, usa la configuración generateLocaleConfig en el bloque androidResources {} del archivo build.gradle.kts a nivel del módulo (archivo build.gradle si usas Groovy). La función está desactivada de forma predeterminada.

    Kotlin

        android {
          androidResources {
            generateLocaleConfig = true
          }
        }
        

    Groovy

        android {
          androidResources {
            generateLocaleConfig true
          }
        }
        
  2. Especifica una configuración regional predeterminada:
    1. En la carpeta res del módulo de la app, crea un archivo nuevo llamado resources.properties.
    2. En el archivo resources.properties, establece la configuración regional predeterminada con la etiqueta unqualifiedResLocale. Para dar formato a los nombres de configuración regional, consulta Cómo formar nombres de configuración regional.

AGP agrega esta configuración regional predeterminada y todas las configuraciones regionales alternativas que especificaste, con directorios values-* en la carpeta res, al archivo LocaleConfig generado automáticamente.

Cómo formar nombres de configuración regional

Para formar nombres de configuración regional, combina el código de idioma con la secuencia de comandos opcional y los códigos regionales, y separa cada uno con un guion:

  • Idioma: Usa el código ISO 639-1 de dos o tres letras.
  • Secuencia de comandos (opcional): Usa el código ISO 15924.
  • Región (opcional): Usa el código ISO 3166-1-alpha-2 de dos letras o el código UN_M.49 de tres dígitos.

Por ejemplo, si tu configuración regional predeterminada es Inglés (Estados Unidos):

unqualifiedResLocale=en-US

Usa android:localeConfig para agregar los idiomas compatibles a la configuración del sistema

Puedes configurar la app de forma manual para asegurarte de que los idiomas se puedan establecer en la configuración del sistema en dispositivos que ejecutan Android 13 o versiones posteriores. Para ello, crea un archivo en formato XML locales_config y agrégalo al manifiesto de tu app con el atributo android:localeConfig. Si omites los indicadores de entrada del manifiesto android:localeConfig, los usuarios no podrán configurar un idioma de tu app diferente del idioma del sistema en la configuración del sistema.

Para agregar de forma manual los idiomas compatibles de la app a la configuración del sistema del usuario, haz lo siguiente:

  1. Crea un archivo con el nombre res/xml/locales_config.xml y especifica los idiomas de tu app, incluida la configuración regional de resguardo final, que es la configuración regional especificada en res/values/strings.xml.

    Consulta Cómo formar nombres de configuración regional para conocer los requisitos de formato. Consulta también el archivo locale_config.xml de muestra para obtener una lista de las configuraciones regionales más usadas.

    Por ejemplo, da formato al archivo locales_config.xml de esta manera para una app que admite los siguientes idiomas:

    • Inglés (Estados Unidos) como la última configuración regional de resguardo
    • Inglés (Reino Unido)
    • Francés
    • Japonés
    • Chino (simplificado, Macao)
    • Chino (tradicional, Macao)
    <?xml version="1.0" encoding="utf-8"?>
    <locale-config xmlns:android="http://schemas.android.com/apk/res/android">
       <locale android:name="en-US"/>
       <locale android:name="en-GB"/>
       <locale android:name="fr"/>
       <locale android:name="ja"/>
       <locale android:name="zh-Hans-MO"/>
       <locale android:name="zh-Hant-MO"/>
    </locale-config>
    
  2. En el manifiesto, agrega una línea que dirija a este archivo nuevo:

    <manifest>
        ...
        <application
            ...
            android:localeConfig="@xml/locales_config">
        </application>
    </manifest>
    

Puedes actualizar de forma dinámica el localeConfig de tu app con LocaleManager.setOverrideLocaleConfig para personalizar el conjunto de idiomas que se muestra en la lista de idiomas de las apps en la Configuración de Android. Esto te permite personalizar la lista de idiomas por región, ejecutar experimentos A/B y proporcionar configuraciones regionales actualizadas si tu app usa envíos de localización del servidor.

Los IME ahora pueden usar LocaleManager.getApplicationLocales para conocer el idioma de la IU de la app actual y actualizar el idioma del teclado, como se muestra en el siguiente ejemplo:

Kotlin

//For setOverrideLocaleConfig
val localeManager = applicationContext
    .getSystemService(LocaleManager::class.java)
localeManager.overrideLocaleConfig = LocaleConfig(
LocaleList.forLanguageTags("en-US,ja-JP,zh-Hans-SG")
)

//For getOverrideLocaleConfig
// The app calls the API to get the override LocaleConfig
val overrideLocaleConfig = localeManager.overrideLocaleConfig
// If the returned overrideLocaleConfig isn't equal to NULL, then the app calls the API to get the supported Locales
val supportedLocales = overrideLocaleConfig.supportedLocales()

Java

//For setOverrideLocaleConfig
mContext.getSystemService(LocaleManager.class).setOverrideLocaleConfig(new LocaleConfig(LocaleList.forLanguageTags("en-US,ja-JP,zh-Hans-SG")));

//For getOverrideLocaleConfig
// The app calls the API to get the override LocaleConfig
LocaleConfig overrideLocaleConfig = mContext.getSystemService(LocaleManager.class).getOverrideLocaleConfig();
// If the returned overrideLocaleConfig isn't equal to NULL, then the app calls the API to get the supported Locales
LocaleList supportedLocales = overrideLocaleConfig.getSupportedLocales();

Especifica los idiomas compatibles en Gradle

Si aún no está presente, especifica los mismos idiomas con la propiedad resourceConfigurations en el archivo build.gradle a nivel de módulo de tu app:

android {
  ...
  defaultConfig {
    resourceConfigurations += ["en", "en-rGB", "fr", "ja", "b+zh+Hans+MO", "b+zh+Hant+MO"]
  }
}

Cuando la propiedad resourceConfigurations está presente, el sistema de compilación solo incluye recursos de idiomas en el APK para los idiomas que se especifican, lo que evita que se incluyan strings traducidas de otras bibliotecas de idiomas que tu app podría no admitir. Para obtener más información, consulta Cómo especificar los idiomas que admite tu app.

Cómo los usuarios seleccionan el idioma de una app en la configuración del sistema

Los usuarios pueden seleccionar el idioma de su preferencia para cada app con la configuración del sistema. Pueden acceder a esta configuración de dos maneras diferentes:

  • Acceder a través de la configuración del sistema

    Configuración > Sistema > Idiomas y entradas > Idiomas de las apps > (selecciona una app)

  • Acceder a través de la configuración de Apps

    Configuración > Apps > (selecciona una app) > Idioma

Control de los selectores de idiomas integrados en la app

En el caso de las apps que ya tienen un selector de idioma integrado o que quieren usar uno, usa las APIs públicas en lugar de una lógica de app personalizada para controlar la configuración y obtener el idioma preferido del usuario para tu app. Si usas las APIs públicas para el selector de idioma en tu app, la configuración de sistema del dispositivo se actualiza automáticamente para coincidir con el idioma que seleccione el usuario a través de la experiencia en la app.

Para ofrecer retrocompatibilidad con versiones anteriores de Android, recomendamos que uses la biblioteca de compatibilidad de AndroidX cuando implementes un selector de idioma integrado en la app. Sin embargo, también puedes implementar las APIs del framework directamente si es necesario.

Implementación con la biblioteca de compatibilidad de AndroidX

Usa los métodos setApplicationLocales() y getApplicationLocales() en Appcompat 1.6.0 o versiones posteriores. Ten en cuenta que las APIs retrocompatibles funcionan con el contexto AppCompatActivity, no el contexto de la aplicación, para Android 12 (nivel de API 32) y versiones anteriores.

Por ejemplo, para configurar el idioma de preferencia de un usuario, se le solicita seleccionar una configuración regional en el selector de idioma y establecer ese valor en el sistema:

Kotlin

val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY")
// Call this on the main thread as it may require Activity.restart()
AppCompatDelegate.setApplicationLocales(appLocale)

Java

LocaleListCompat appLocale = LocaleListCompat.forLanguageTags("xx-YY");
// Call this on the main thread as it may require Activity.restart()
AppCompatDelegate.setApplicationLocales(appLocale);

Ten en cuenta que, cuando se llama a setApplicationLocales(), se recrea tu Activity, a menos que tu app controle los cambios de configuración regional por su cuenta.

Usa AppCompatDelegate.getApplicationLocales() para recuperar la configuración regional preferida del usuario. Es posible que el usuario haya seleccionado la configuración regional de la app desde la configuración del sistema o desde el selector de idioma de la app.

Compatibilidad con Android 12 y versiones anteriores

Para admitir dispositivos que ejecutan Android 12 (nivel de API 32) y versiones anteriores, indícale a AndroidX que controle el almacenamiento de la configuración regional mediante la configuración de un valor autoStoreLocales en true y android:enabled en false en la entrada de manifiesto del servicio AppLocalesMetadataHolderService de la app, como se muestra en el siguiente fragmento de código:

<application
  ...
  <service
    android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
    android:enabled="false"
    android:exported="false">
    <meta-data
      android:name="autoStoreLocales"
      android:value="true" />
  </service>
  ...
</application>

Ten en cuenta que establecer un valor autoStoreLocales en true provoca un bloqueo de lectura en el subproceso principal y puede causar un incumplimiento de StrictMode diskRead y diskWrite si registras incumplimientos de subprocesos. Consulta AppCompatDelegate.setApplicationLocales() para obtener más información.

Control de almacenamiento personalizado

Omitir la entrada del manifiesto o la configuración de autoStoreLocales en false indica que controlas tu propio almacenamiento. En este caso, debes proporcionar los parámetros de configuración regional almacenados antes de onCreate en el ciclo de vida de la actividad y las llamadas de puerta a AppCompatDelegate.setApplicationLocales() en Android 12 (nivel de API 32) o versiones anteriores.

Si tu app tiene una ubicación de almacenamiento de configuración regional personalizada, se recomienda usar una transferencia única entre la solución de almacenamiento de configuración regional personalizada y autoStoreLocales, para que los usuarios continúen disfrutando de la app en el idioma que prefieran. Esto se aplica especialmente cuando la app se ejecuta por primera vez después de que un dispositivo se actualizó a Android 13. En este caso, puedes proporcionar parámetros preexistentes de configuración regional que solicitó el usuario. Para ello, debes recuperar estos parámetros de tu almacenamiento personalizado y pasarlos a AppCompatDelegate.setApplicationLocales().

Implementación con las APIs del framework de Android

Si bien te recomendamos que uses la biblioteca de compatibilidad de AndroidX para implementar selectores de idiomas integrados en la app, también puedes usar los métodos setApplicationLocales() y getApplicationLocales() en el framework de Android para dispositivos que ejecutan Android 13.

Por ejemplo, para configurar el idioma de preferencia de un usuario, se le solicita seleccionar una configuración regional en el selector de idioma y establecer ese valor en el sistema:

// 1. Inside an activity, in-app language picker gets an input locale "xx-YY"
// 2. App calls the API to set its locale
mContext.getSystemService(LocaleManager.class
    ).setApplicationLocales(new LocaleList(Locale.forLanguageTag("xx-YY")));
// 3. The system updates the locale and restarts the app, including any configuration updates
// 4. The app is now displayed in "xx-YY" language

Para que el idioma actual de preferencia de un usuario se muestre en el selector de idioma, tu app puede recuperar el valor del sistema:

// 1. App calls the API to get the preferred locale
LocaleList currentAppLocales =
    mContext.getSystemService(LocaleManager.class).getApplicationLocales();
// 2. App uses the returned LocaleList to display languages to the user

Prácticas recomendadas adicionales

Toma nota de las siguientes prácticas recomendadas.

Ten en cuenta el idioma cuando invoques un intent en otra app

Es posible que los intents centrados en el idioma te permitan especificar el idioma en el que deseas que esté la app invocada. Un ejemplo es la función EXTRA_LANGUAGE de la API de Speech Recognizer.

Ten en cuenta el encabezado Accept-Language para la pestaña personalizada de Chrome

Te recomendamos que agregues el encabezado Accept-Language a través de Browser.EXTRA_HEADERS para abrir una página web en el idioma de tu app cuando invoques una pestaña personalizada de Chrome.

Si quitas las preferencias de idioma de las apps en la configuración del sistema, restablece la configuración regional de tu app a la del sistema.

Si quitas las preferencias de idioma de la app de la configuración del sistema (es decir, si quitas android:localeConfig del archivo AndroidManifest.xml de tu app), los usuarios no podrán restablecer fácilmente el idioma de la app a la configuración predeterminada del sistema.

Por este motivo, si quitas android:localeConfig, considera restablecer la configuración regional de la app a la configuración regional del sistema con LocaleListCompat.getEmptyLocaleList() o LocaleList.getEmptyLocaleList(), como se ve en el siguiente fragmento de código:

Kotlin

// Use the AndroidX APIs to reset to the system locale for backward and forward compatibility
AppCompatDelegate.setApplicationLocales(
  LocaleListCompat.getEmptyLocaleList()
)

// Or use the Framework APIs for Android 13 and above to reset to the system locale
val context = LocalContext.current
context.getSystemService(LocaleManager::class.java)
  .applicationLocales = LocaleList.getEmptyLocaleList()

Java

// Use the AndroidX APIs to reset to the system locale for backward and forward compatibility
AppCompatDelegate.setApplicationLocales(
  LocaleListCompat.getEmptyLocaleList()
);

// Or use the Framework APIs for Android 13 and above to reset to the system locale
mContext.getSystemService(LocaleManager.class)
  .setApplicationLocales(LocaleList.getEmptyLocaleList());

Recursos adicionales

Consulta nuestras muestras de código, artículos de blog y videos para obtener información adicional.

Ejemplo de archivo locale_config.xml

De forma predeterminada, Android incluye traducciones a nivel del sistema en el Proyecto de código abierto de Android (AOSP) para un conjunto estándar de las configuraciones regionales de uso general. El archivo locale_config.xml de muestra que se incluye en esta sección muestra el formato sugerido para cada una de estas configuraciones regionales. Consulta este archivo de muestra para ayudarte a crear tu propio archivo locale_config.xml para el conjunto de lenguajes que admite tu app.

<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
   <locale android:name="af"/> <!-- Afrikaans -->
   <locale android:name="am"/> <!-- Amharic -->
   <locale android:name="ar"/> <!-- Arabic -->
   <locale android:name="as"/> <!-- Assamese -->
   <locale android:name="az"/> <!-- Azerbaijani -->
   <locale android:name="be"/> <!-- Belarusian -->
   <locale android:name="bg"/> <!-- Bulgarian -->
   <locale android:name="bn"/> <!-- Bengali -->
   <locale android:name="bs"/> <!-- Bosnian -->
   <locale android:name="ca"/> <!-- Catalan -->
   <locale android:name="cs"/> <!-- Czech -->
   <locale android:name="da"/> <!-- Danish -->
   <locale android:name="de"/> <!-- German -->
   <locale android:name="el"/> <!-- Greek -->
   <locale android:name="en-AU"/> <!-- English (Australia) -->
   <locale android:name="en-CA"/> <!-- English (Canada) -->
   <locale android:name="en-GB"/> <!-- English (United Kingdom) -->
   <locale android:name="en-IN"/> <!-- English (India) -->
   <locale android:name="en-US"/> <!-- English (United States) -->
   <locale android:name="en-XA"/> <!-- English (Pseudo-Accents) -->
   <locale android:name="es"/> <!-- Spanish (Spain) -->
   <locale android:name="es-US"/> <!-- Spanish (United States) -->
   <locale android:name="et"/> <!-- Estonian -->
   <locale android:name="eu"/> <!-- Basque -->
   <locale android:name="fa"/> <!-- Farsi -->
   <locale android:name="fi"/> <!-- Finnish -->
   <locale android:name="fr"/> <!-- French (France) -->
   <locale android:name="fr-CA"/> <!-- French (Canada) -->
   <locale android:name="gl"/> <!-- Galician -->
   <locale android:name="gu"/> <!-- Gujarati -->
   <locale android:name="hi"/> <!-- Hindi -->
   <locale android:name="hr"/> <!-- Croatian -->
   <locale android:name="hu"/> <!-- Hungarian -->
   <locale android:name="hy"/> <!-- Armenian -->
   <locale android:name="in"/> <!-- Indonesian -->
   <locale android:name="is"/> <!-- Icelandic -->
   <locale android:name="it"/> <!-- Italian -->
   <locale android:name="iw"/> <!-- Hebrew -->
   <locale android:name="ja"/> <!-- Japanese -->
   <locale android:name="ka"/> <!-- Georgian -->
   <locale android:name="kk"/> <!-- Kazakh -->
   <locale android:name="km"/> <!-- Khmer -->
   <locale android:name="kn"/> <!-- Kannada -->
   <locale android:name="ko"/> <!-- Korean -->
   <locale android:name="ky"/> <!-- Kyrgyz -->
   <locale android:name="lo"/> <!-- Lao -->
   <locale android:name="lt"/> <!-- Lithuanian -->
   <locale android:name="lv"/> <!-- Latvian -->
   <locale android:name="mk"/> <!-- Macedonian -->
   <locale android:name="ml"/> <!-- Malayalam -->
   <locale android:name="mn"/> <!-- Mongolian -->
   <locale android:name="mr"/> <!-- Marathi -->
   <locale android:name="ms"/> <!-- Malay -->
   <locale android:name="my"/> <!-- Burmese -->
   <locale android:name="my-MM"/> <!-- Burmese (Myanmar) -->
   <locale android:name="nb"/> <!-- Norwegian -->
   <locale android:name="ne"/> <!-- Nepali -->
   <locale android:name="nl"/> <!-- Dutch -->
   <locale android:name="or"/> <!-- Odia -->
   <locale android:name="pa"/> <!-- Punjabi -->
   <locale android:name="pl"/> <!-- Polish -->
   <locale android:name="pt-BR"/> <!-- Portuguese (Brazil) -->
   <locale android:name="pt-PT"/> <!-- Portuguese (Portugal) -->
   <locale android:name="ro"/> <!-- Romanian -->
   <locale android:name="ru"/> <!-- Russian -->
   <locale android:name="si"/> <!-- Sinhala -->
   <locale android:name="sk"/> <!-- Slovak -->
   <locale android:name="sl"/> <!-- Slovenian -->
   <locale android:name="sq"/> <!-- Albanian -->
   <locale android:name="sr"/> <!-- Serbian (Cyrillic) -->
   <locale android:name="sr-Latn"/> <!-- Serbian (Latin) -->
   <locale android:name="sv"/> <!-- Swedish -->
   <locale android:name="sw"/> <!-- Swahili -->
   <locale android:name="ta"/> <!-- Tamil -->
   <locale android:name="te"/> <!-- Telugu -->
   <locale android:name="th"/> <!-- Thai -->
   <locale android:name="tl"/> <!-- Filipino -->
   <locale android:name="tr"/> <!-- Turkish -->
   <locale android:name="uk"/> <!-- Ukrainian -->
   <locale android:name="ur"/> <!-- Urdu -->
   <locale android:name="uz"/> <!-- Uzbek -->
   <locale android:name="vi"/> <!-- Vietnamese -->
   <locale android:name="zh-CN"/> <!-- Chinese (Simplified) -->
   <locale android:name="zh-HK"/> <!-- Chinese (Hong Kong) -->
   <locale android:name="zh-TW"/> <!-- Chinese (Traditional) -->
   <locale android:name="zu"/> <!-- Zulu -->
</locale-config>