Em muitos casos, os usuários multilíngues definem um idioma para o sistema, como o inglês, mas querem selecionar outros idiomas para apps específicos, como holandês, chinês ou hindi. Para melhorar a experiência dos usuários nos apps que oferecem suporte a vários idiomas, o Android 13 introduz os recursos abaixo:
Configurações do sistema: um local centralizado em que os usuários podem selecionar um idioma preferido para cada app.
Você pode configurar seu app para gerar automaticamente os arquivos necessários para oferecer suporte à seleção de idioma por app e mostrar essa opção nas configurações do sistema. Para saber mais, consulte as instruções para ativar o suporte automático ao idioma por app support.
Outras APIs: essas APIs públicas, como os métodos
setApplicationLocalesegetApplicationLocalesna classeLocaleManager, permitem que os apps definam um idioma diferente daquele usado pelo sistema durante a execução.Essas APIs são sincronizadas automaticamente com as configurações do sistema. Os apps que usam essas APIs para criar seletores de idioma personalizados garantem que os usuários tenham uma experiência consistente, independente do local em que escolherem as preferências de idioma. As APIs públicas também ajudam a reduzir a quantidade de código boilerplate e oferecem suporte para APKs divididos e Backup automático para Apps, permitindo que os apps armazenem as seleções de idioma do usuário.
Para oferecer compatibilidade com versões anteriores do Android, APIs equivalentes também estão disponíveis no AndroidX. No entanto, as APIs compatíveis com versões anteriores funcionam com o contexto da AppCompatActivity, e não com o contexto do app, para Android 12 (nível 32 da API) e versões anteriores. Acesse as APIs compatíveis com versões anteriores usando a Appcompat 1.6.0 ou versões mais recentes.
Visão geral da implementação desse recurso
A tabela a seguir mostra as implementações recomendadas de acordo com os diferentes casos de uso.
| Caso de uso | Implementação recomendada |
|---|---|
| O app não tem um seletor de idioma |
|
| O app já tem um seletor de idioma |
|
Configurações do sistema para usuários
No Android 13 e versões mais recentes, há um local centralizado nas configurações do sistema para definir a seleção de idioma por app. Para garantir que os idiomas do app possam ser definidos nas configurações do sistema em dispositivos com o Android 13 ou mais recente, ative o suporte automático ao idioma por app (recomendado) ou configure o suporte manualmente.
Ativar o suporte automático ao idioma por app
Essa é a maneira recomendada de adicionar suporte a idiomas separados por app, porque não requer modificações em XML.
No Android Studio Giraffe e o AGP 8.1 e versões mais recentes, é possível configurar seu app para
oferecer suporte à seleção de idioma por app automaticamente. Com base nos recursos do projeto, o AGP gera o arquivo LocaleConfig e adiciona uma referência a ele no arquivo de manifesto final. Assim, não é mais necessário fazer isso manualmente. O AGP usa os recursos nas pastas res dos módulos do app e qualquer dependência de módulos de biblioteca para determinar as localidades que serão incluídas no arquivo LocaleConfig.
Isso significa que, se você adicionar recursos para um novo idioma ao seu app, não precisará se preocupar em atualizar o arquivo LocaleConfig.
O recurso automático de idioma por app tem suporte de apps com o Android 13 (nível da API 33) ou mais recente. Para usar o recurso, defina compileSdkVersion como 33 ou maior. Para configurar a seleção de idioma por app
em versões anteriores do Android, ainda é necessário usar as APIs e os seletores de idioma
no app.
Para ativar o suporte automático ao idioma por app, siga estas etapas:
- Para ativar o recurso, use a
generateLocaleConfigconfiguração no blocoandroidResources {}do arquivobuild.gradle.ktsdo módulo (arquivobuild.gradle, se você estiver usando o Groovy). O recurso fica desativado por padrão.
Kotlin
android {
androidResources {
generateLocaleConfig = true
}
}
Groovy
android {
androidResources {
generateLocaleConfig true
}
}
- Especifique uma localidade padrão:
- Na pasta
resdo módulo do app, crie um novo arquivo chamadoresources.properties. - No arquivo
resources.properties, defina a localidade padrão com o rótulounqualifiedResLocale. Para formatar os nomes de localidade, consulte Como formar os nomes de localidade.
- Na pasta
O AGP adiciona a localidade padrão e qualquer localidade alternativa que você tenha especificado,
usando values-* diretórios na pasta res, ao arquivo LocaleConfig gerado automaticamente.
Como formar nomes de localidade
Para formar os nomes de localidade, combine o código do idioma com o script opcional e os códigos de região, separando cada um com um traço:
- Idioma: use o código ISO 639-2 (link em inglês) de duas ou três letras.
- Script (opcional): use o código ISO 15924.
- Região (opcional): use o código ISO 3166-1-alpha-2 de duas letras ou o código UN_M.49 de três dígitos.
Por exemplo, se a localidade padrão for inglês dos EUA:
unqualifiedResLocale=en-US
Usar android:localeConfig para adicionar os idiomas disponíveis às configurações do sistema
É possível configurar o app manualmente para garantir que os idiomas possam ser definidos nas configurações do sistema em dispositivos com o Android 13 ou mais recente. Para fazer isso, crie um arquivo XML locale_config e adicione-o ao manifesto do app usando o atributo android:localeConfig. A omissão da entrada de manifesto android:localeConfig indica que os usuários não poderão definir idiomas diferentes para o app e para o sistema.
Para adicionar manualmente os idiomas disponíveis nas configurações do sistema, siga estas etapas:
Crie um arquivo chamado
res/xml/locale_config.xmle especifique os idiomas do app, incluindo a localidade substituta final, que é a localidade especificada emres/values/strings.xml.Consulte Como formar os nomes de localidade para conferir os requisitos de formato. Consulte também o arquivo de
locale_config.xmlexemplo para conferir uma lista das localidades usadas com frequência.Por exemplo, formate o arquivo
locale_config.xmldesta forma em um app com suporte para os seguintes idiomas:- Inglês (Estados Unidos) como localidade substituta final
- Inglês (Reino Unido)
- Francês
- Japonês
- Chinês (simplificado, Macau)
- Chinês (tradicional, Macau)
<?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>No manifesto do app, adicione uma linha que leve a esse novo arquivo:
<manifest> ... <application ... android:localeConfig="@xml/locale_config"> </application> </manifest>
É possível atualizar dinamicamente as localeConfig do app com LocaleManager.setOverrideLocaleConfig para personalizar o conjunto de idiomas mostrado na lista de idiomas por app nas configurações do Android. Isso permite personalizar a lista de idiomas por região, realizar experimentos A/B e fornecer localidades atualizadas caso o app use pushes de localização do lado do servidor, conforme mostrado no exemplo a seguir:
//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()
Além disso, os IMEs agora podem usar LocaleManager.getApplicationLocales para
saber o idioma da interface do app atual e atualizar o idioma do teclado, conforme
mostrado abaixo:
val currentAppLocales: LocaleList = applicationContext.getSystemService(LocaleManager::class.java).getApplicationLocales(appPackageName)
Especificar idiomas com suporte no Gradle
Especifique os mesmos idiomas usando a
resourceConfigurations propriedade no arquivo
build.gradle do módulo do app:
android {
...
defaultConfig {
resourceConfigurations += ["en", "en-rGB", "fr", "ja", "b+zh+Hans+MO", "b+zh+Hant+MO"]
}
}
Quando a propriedade resourceConfigurations está presente, o sistema de build inclui apenas recursos de idioma no APK para esses idiomas especificados, impedindo que strings traduzidas sejam incluídas de outras bibliotecas com suporte a idiomas que o app não usa. Para mais informações, consulte Especificar os
idiomas com suporte no app.
Como os usuários selecionam um idioma para o app nas configurações do sistema
Com as configurações do sistema, os usuários podem selecionar um idioma preferido para cada app. Os usuários podem acessar essas configurações de duas maneiras:
Acessar as configurações do sistema
Configurações > Sistema > Idioma e entrada > Idiomas do app > (selecionar um app)
Acessar as configurações dos apps
Configurações > Apps > (selecionar um app) > Idioma
Processar seletores de idioma no app
Para apps que já têm um seletor de idioma integrado ou que querem usar um, utilize as APIs públicas em vez da lógica personalizada do app para descobrir e configurar o idioma preferido do usuário. Se o seletor de idioma no app depender das APIs públicas, as configurações do sistema do dispositivo vão ser atualizadas automaticamente para corresponder ao idioma que o usuário selecionar no app.
Implementar usando o Jetpack Compose
Para apps criados totalmente com o Jetpack Compose, o sistema processa automaticamente as atualizações da interface quando a localidade do app muda. Chamar a API para definir um novo idioma aciona uma mudança de configuração. O Compose reage recompondo a interface e resolvendo automaticamente todas as chamadas stringResource usando a nova localidade.
Para oferecer compatibilidade com versões anteriores ao Android 12 (nível 32 da API), recomendamos o uso da Biblioteca de Suporte do AndroidX (AppCompatDelegate) ao implementar um seletor de idioma no app. Se você usar essa abordagem, a atividade que hospeda a interface do Compose precisará estender AppCompatActivity. Também é possível
implementar as APIs de framework diretamente, se necessário.
O snippet de código a seguir mostra um exemplo de como ler a localidade atual do app e definir uma nova em uma função combinável:
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.core.os.LocaleListCompat
@Composable
fun LanguageSelector() {
// Retrieve the currently configured app locale.
// If no app-specific locale is set, LocaleListCompat.get(0) returns null,
// so we safely fall back to a default (e.g., "en").
val appLocales = AppCompatDelegate.getApplicationLocales()
val currentLocaleTag = appLocales.get(0)?.toLanguageTag() ?: "en"
// Example UI: A button to toggle between English and Spanish
Button(
onClick = {
val newLanguageTag = if (currentLocaleTag == "en") "es" else "en"
val localeList = LocaleListCompat.forLanguageTags(newLanguageTag)
// Setting the locale re-creates the Activity by default,
// which automatically applies the new configuration to Compose.
AppCompatDelegate.setApplicationLocales(localeList)
}
) {
Text(
text = if (currentLocaleTag == "en") "Switch to Spanish" else "Switch to English"
)
}
}
Para definir o idioma de preferência de um usuário, peça para ele selecionar uma localidade no seletor de idioma e defina esse valor no sistema:
val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY")
// Call this on the main thread as it may require Activity.restart()
AppCompatDelegate.setApplicationLocales(appLocale)
Tenha em mente que chamar setApplicationLocales recria a Activity, a menos que
o app processe mudanças de configuração de localidade por conta própria.
Use AppCompatDelegate.getApplicationLocales para extrair a localidade de preferência do usuário. A localidade do app pode ser escolhida pelo usuário nas configurações do sistema ou no seletor de idioma do app.
Suporte para Android 12 e versões anteriores
Para oferecer suporte para dispositivos com o Android 12 (nível da API 32) e versões anteriores, instrua o AndroidX a processar o armazenamento da localidade. Para isso, defina o valor autoStoreLocales como true e android:enabled como false na entrada do serviço AppLocalesMetadataHolderService no manifesto do app, conforme mostrado no snippet de código a seguir:
<application
...
<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
android:name="autoStoreLocales"
android:value="true" />
</service>
...
</application>
Definir um valor autoStoreLocales como true causa uma leitura de bloqueio na linha de execução principal e pode causar uma violação StrictMode diskRead e diskWrite se o app estiver registrando violações de linha de execução. Consulte
AppCompatDelegate.setApplicationLocales para mais informações.
Processar armazenamento personalizado
Omitir a entrada de manifesto ou definir autoStoreLocales como false
indica que o app processa um armazenamento próprio. Nesse caso, é necessário informar as
localidades armazenadas antes de onCreate no ciclo de vida da atividade e bloquear chamadas para
AppCompatDelegate.setApplicationLocales no Android 12 (API de nível 32) ou
versões anteriores.
Se o app tiver um local de armazenamento de localidades personalizado, recomendamos usar uma transferência
única entre a solução de armazenamento de localidades personalizada e autoStoreLocales, para que
os usuários possam continuar a usar o app no idioma que preferirem. Isso vale principalmente
para os casos em que o app é executado pela primeira vez depois que o dispositivo foi atualizado para o
Android 13. Nesse caso, as localidades já solicitadas pelo usuário podem ser extraídas
do armazenamento personalizado e transmitidas para
AppCompatDelegate.setApplicationLocales.
Implementar usando as APIs do framework do Android
Embora seja altamente recomendável usar a Biblioteca de Suporte do AndroidX para
implementar seletores de idioma no app, também é possível usar os métodos
setApplicationLocales e getApplicationLocales no
framework do Android para dispositivos com o Android 13.
O snippet de código a seguir mostra como definir e receber o idioma preferido do usuário usando o serviço do sistema LocaleManager:
import android.app.LocaleManager
import android.content.Context
import android.os.Build
import android.os.LocaleList
import androidx.annotation.RequiresApi
import java.util.Locale
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun setAppLanguage(context: Context, languageTag: String) {
// 1. Retrieve the system service
val localeManager = context.getSystemService(LocaleManager::class.java)
// 2. Create a LocaleList from the language tag (e.g., "es-ES" or "ja")
val localeList = LocaleList(Locale.forLanguageTag(languageTag))
// 3. Set the locale. The system automatically updates the locale and
// restarts the app, including any necessary configuration updates.
localeManager.applicationLocales = localeList
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun getAppLanguage(context: Context): String {
val localeManager = context.getSystemService(LocaleManager::class.java)
val currentLocales = localeManager.applicationLocales
// Return the primary app locale, or fall back to the system default
return if (!currentLocales.isEmpty) {
currentLocales.get(0).toLanguageTag()
} else {
Locale.getDefault().toLanguageTag()
}
}
Práticas recomendadas adicionais
Confira as práticas recomendadas a seguir.
Considerar o idioma ao invocar uma intent em outro app
Intents de idioma podem permitir especificar o idioma em que você quer exibir o app invocado. Um exemplo é o EXTRA_LANGUAGE recurso da
API Speech Recognizer.
Usar o cabeçalho Accept-Language para guias personalizadas do Chrome
Adicione o cabeçalho Accept-Language usando
Browser.EXTRA_HEADERS para abrir uma página da Web no mesmo idioma do app ao
invocar uma guia personalizada do Chrome.
Se você remover a seleção de idioma por app nas configurações do sistema, defina a localidade do app como a mesma do sistema
Caso a seleção de idioma do app seja removida das configurações do sistema, excluindo android:localeConfig e AndroidManifest.xml, os usuários não poderão redefinir o idioma do app para o padrão do sistema com facilidade.
Por isso, ao remover android:localeConfig, use
LocaleListCompat.getEmptyLocaleList ou
LocaleList.getEmptyLocaleList para definir a localidade do app como a mesma do sistema, conforme apresentado no snippet de código a seguir:
// 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()
Exemplo de arquivo locale_config.xml
Por padrão, o sistema Android inclui traduções no Android Open
Source Project (AOSP) para um conjunto padrão das localidades mais usadas.
O exemplo de arquivo locale_config.xml incluído nesta seção mostra o
formato sugerido para cada uma dessas localidades. Use esse exemplo como referência quando for criar seu arquivo locale_config.xml para o conjunto de idiomas com suporte no seu 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="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="fil"/> <!-- Filipino -->
<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="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="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-Hans"/> <!-- Chinese (Simplified) -->
<locale android:name="zh-Hant"/> <!-- Chinese (Traditional) -->
<locale android:name="zu"/> <!-- Zulu -->
</locale-config>
Outros recursos
Consulte nossos exemplos de código, artigos do blog e vídeos para mais informações.
- Blog Seleção de idioma por app (parte 1)
- Blog Seleção de idioma por app (parte 2)
- Vídeo sobre como criar para um mundo multilíngue
- Recursos no Compose