Skip to main content

O guia completo para localizar aplicações Android

De strings.xml aos metadados da Play Store: localize sua aplicação Android com Kotlin, Jetpack Compose, Fastlane e tradução automatizada com IA.

1

Preparar seu projeto Android para a localização

O Android utiliza uma convenção baseada em pastas para a localização. As strings predefinidas ficam em res/values/strings.xml e as traduzidas em pastas específicas de cada localidade, como res/values-de/ e res/values-ja/.

Android Project Structure
// Android project structure for localization:
// res/
// ├── values/              ← Default (fallback) locale
// │   └── strings.xml
// ├── values-de/           ← German
// │   └── strings.xml
// ├── values-ja/           ← Japanese
// │   └── strings.xml
// └── values-es/           ← Spanish
//     └── strings.xml
//
// Folder naming: values-{language} or values-{language}-r{Region}
// Examples: values-pt-rBR, values-zh-rCN, values-zh-rTW
A pasta res/values/ é sua localidade de fallback. Se faltar uma string em uma pasta regional, o Android a carrega da pasta padrão. Contudo, se faltar na pasta padrão, a aplicação falha nas localidades sem compatibilidade.
2

Criar strings.xml

Os recursos de strings do Android utilizam XML com elementos '<string>' em uma raiz '<resources>'. Utilize %s para marcadores de strings, %d para números inteiros e %1$s/%2$s para argumentos posicionais que os tradutores podem reordenar.

res/values/strings.xml
<!-- res/values/strings.xml -->
<resources>
    <string name="welcome_title">Welcome to MyApp</string>
    <string name="login_button">Sign In</string>
    <string name="settings_label">Settings</string>
    <string name="greeting">Hello, %s!</string>        <!-- %s = string -->
    <string name="item_count">%d items</string>          <!-- %d = integer -->
    <string name="app_name" translatable="false">MyApp</string>
</resources>
Os apóstrofos sem escape fazem o analisador XML falhar silenciosamente. Utilize \' ou coloque o valor entre aspas duplas. Além disso, a falta de uma string no values/strings.xml predefinido provoca uma falha grave, não um fallback harmonioso como no iOS.
Common strings.xml Mistakes
<!-- ❌ Common mistakes in strings.xml: -->

<!-- Unescaped apostrophe — crashes XML parser silently -->
<string name="message">It's a great day</string>

<!-- Missing from default values/strings.xml — app crashes -->
<!-- (only exists in values-de/strings.xml) -->

<!-- ✅ Correct versions: -->
<string name="message">It\'s a great day</string>
<!-- Or wrap in double quotes: -->
<string name="message">"It's a great day"</string>
3

Tratar plurais

O Android utiliza elementos '&lt;plurals&gt;' com atributos quantity: zero, one, two, few, many e other. Cada idioma de destino pode precisar de categorias diferentes: o árabe utiliza as 6, o russo precisa de few/many e o japonês utiliza apenas other.

res/values/strings.xml
<!-- res/values/strings.xml -->
<resources>
    <plurals name="items_count">
        <item quantity="zero">No items</item>
        <item quantity="one">%d item</item>
        <item quantity="other">%d items</item>
    </plurals>
</resources>

<!-- Usage in Kotlin: -->
<!-- val text = resources.getQuantityString(
    R.plurals.items_count,
    count,    // selects plural form
    count     // format argument
) -->
O atributo quantity seleciona a forma plural segundo as regras CLDR da localidade do dispositivo. Inclua sempre 'other' como fallback: é a única categoria que existe garantidamente em todos os idiomas.
4

Utilizar no código: Kotlin e Jetpack Compose

O Android tradicional utiliza getString(R.string.key) e resources.getQuantityString(). O Jetpack Compose utiliza stringResource(R.string.key) e pluralStringResource(). Ambos resolvem a tradução correta durante a execução com base na localidade do dispositivo.

WelcomeScreen.kt
// Traditional Android (Activity/Fragment)
val title = getString(R.string.welcome_title)
val greeting = getString(R.string.greeting, userName)
val items = resources.getQuantityString(
    R.plurals.items_count, count, count
)

// Jetpack Compose
@Composable
fun WelcomeScreen(userName: String, itemCount: Int) {
    // ✅ stringResource — Compose-aware, triggers recomposition
    Text(text = stringResource(R.string.welcome_title))

    // ✅ With format arguments
    Text(text = stringResource(R.string.greeting, userName))

    // ✅ Plurals — count passed TWICE
    Text(text = pluralStringResource(
        R.plurals.items_count,
        itemCount,    // selects plural form
        itemCount     // format argument
    ))
}
pluralStringResource(R.plurals.items, count, count): o parâmetro count é passado duas vezes. A primeira seleciona a forma plural e a segunda é o argumento de formato. Omitir a segunda é o principal erro de pluralização no Compose.
5

Listas de strings e strings formatadas

Utilize '&lt;string-array&gt;' para listas ordenadas —por exemplo, opções de listas pendentes ou passos da integração inicial—. Utilize argumentos de formato posicionais (%1$s, %2$d) nas strings formatadas para os tradutores poderem reordenar as palavras sem quebrar a frase.

res/values/strings.xml
<!-- res/values/strings.xml -->
<resources>
    <!-- String array for dropdown/list -->
    <string-array name="sort_options">
        <item>Most Recent</item>
        <item>Most Popular</item>
        <item>Price: Low to High</item>
        <item>Price: High to Low</item>
    </string-array>

    <!-- Positional format args for reordering -->
    <string name="welcome_message">
        Hello %1$s, you have %2$d new messages
    </string>
    <!-- Translators can reorder: -->
    <!-- %2$d neue Nachrichten für %1$s -->
</resources>
Os argumentos posicionais, como %1$s, permitem reordenar livremente os parâmetros. «Hello %1$s, you have %2$d items» pode se tornar «%2$d items for %1$s» em idiomas com outra ordem das palavras, sem alterar o código.
6

Localizar metadados do Google Play com Fastlane

Utilize o comando supply do Fastlane para gerenciar os metadados da Play Store —título, descrição curta, descrição completa e registros de alterações— como arquivos de texto simples organizados por localidade no seu repositório.

Terminal
# Install Fastlane
$ gem install fastlane

# Initialize supply for Play Store metadata
$ fastlane supply init

# Directory structure created:
# fastlane/metadata/android/
# ├── en-US/
# │   ├── title.txt              # App name (50 chars)
# │   ├── short_description.txt  # Short desc (80 chars)
# │   ├── full_description.txt   # Full desc (4000 chars)
# │   └── changelogs/
# │       └── default.txt        # What's New
# ├── de-DE/
# │   └── ...
# └── ja-JP/
#     └── ...

# Push metadata to Play Store:
$ fastlane supply
Localizar a ficha da Play Store aumenta os downloads em mais de 30% nos mercados que não falam inglês. O título e as descrições curta e completa são indexados nas pesquisas; traduzi-los é a localização com maior retorno que pode fazer.
Google Play

Automatizar a localização da sua ficha da Play Store

Evite copiar e colar manualmente. Traduza o título, a descrição e as notas da versão da Play Store em mais de 175 localidades, respeitando os limites de caracteres.

Explorar a integração com Google Play
7

Testar a localização

Teste através da seleção de localidades no emulador, prévias Compose com LocaleList personalizado e pseudolocalidades nas Opções de desenvolvedor. Utilize resConfigs no Gradle para remover recursos regionais indesejados de bibliotecas de terceiros.

Testing Localization
// 1. Emulator: Settings > System > Language > Add language

// 2. Compose Preview with locale:
@Preview
@Composable
fun WelcomePreview() {
    val config = Configuration(resources.configuration).apply {
        setLocale(Locale("de"))
    }
    val localContext = LocalContext.current
    val localizedContext = localContext.createConfigurationContext(config)
    CompositionLocalProvider(
        LocalContext provides localizedContext
    ) {
        WelcomeScreen()
    }
}

// 3. Restrict library locales in build.gradle.kts:
android {
    defaultConfig {
        // Only include locales you actually translate
        resourceConfigurations += listOf("en", "de", "ja", "es", "fr")
    }
}

// 4. Enable pseudolocales in Developer Options:
// en-XA (accented) — detects hardcoded strings
// ar-XB (RTL) — tests layout mirroring
Teste com alemão —o texto aumenta cerca de 30%— e japonês —diminui cerca de 50%— para detectar problemas de layout. Ative pseudolocalidades —en-XA para texto acentuado e ar-XB para RTL— nas Opções de desenvolvedor e submeta os layouts a testes exigentes sem traduções reais.

Automatizar a qualidade das traduções

Detecte chaves em falta, marcadores danificados e problemas de plural antes da publicação com i18n-validate. Teste a interface com pseudotraduções através de i18n-pseudo antes de chegarem as traduções reais.
8

Automatizar as traduções

Traduza strings.xml, plurais, listas de strings e metadados Fastlane Supply com IA. Automatize a tradução das strings da aplicação e dos metadados da Play Store para uma presença totalmente localizada.

Terminal
# Translate strings.xml files
> Translate res/values/strings.xml
  to Japanese, German, and Spanish

# Translate Play Store metadata too
> Translate fastlane/metadata/android/en-US/
  to de-DE, ja-JP, es-ES

✓ 6 files translated in 3.2s
O i18n Agent trata escapes XML do Android, preserva os marcadores translatable="false", respeita as categorias de plural CLDR de cada idioma de destino e mantém intactos os argumentos de formato posicionais.
JetBrains

Plugin do Android Studio disponível

Traduza recursos XML do Android diretamente no IDE com o plugin i18n Agent para IntelliJ / Android Studio.

Install
+

Extra: fallback regional inteligente com LocaleChain

O fallback de recursos do Android é controlado pelo sistema operacional. Quando faltam traduções pt-BR, o Android ignora por completo pt-PT e mostra inglês. LocaleChain intercepta as consultas de strings e percorre uma cadeia de fallback configurável. Assim, os usuários regionais veem a tradução disponível mais próxima.

LocaleChain para Android é uma biblioteca Kotlin de código aberto. Ver no GitHub

build.gradle.kts
// build.gradle.kts (app module)
dependencies {
    implementation("com.i18nagent:locale-chain-android:0.1.0")
}
MyApp.kt / BaseActivity.kt
// 1. Application.onCreate() — configure chains once
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        LocaleChain.configure()
    }
}

// 2. BaseActivity — wrap context per Activity
open class BaseActivity : AppCompatActivity() {
    override fun attachBaseContext(newBase: Context) {
        super.attachBaseContext(LocaleChain.wrap(newBase))
    }
}

// pt-BR user with only pt-PT translations?
// → Shows Portuguese instead of falling back to English

// Custom overrides for your specific locales:
LocaleChain.configure(
    overrides = mapOf("es-MX" to listOf("es-419", "es"))
)

Erros frequentes

A falta de strings predefinidas provoca falhas

Ao contrário do iOS, que mostra a chave em bruto, o Android falha com ResourceNotFoundException se faltar uma string no arquivo predefinido res/values/strings.xml. Verifique sempre se todas as chaves existem nesse arquivo.

A divisão por idioma do App Bundle quebra a seleção dentro da aplicação

Os App Bundles do Google Play dividem os APK por idioma: os usuários só recebem as strings do idioma do dispositivo. Se permitir mudar o idioma na aplicação, adicione bundle '{ language { enableSplit = false } }' ao seu build.gradle.kts.

Os layouts RTL quebram

Utilizar left/right em vez de start/end nos layouts ou omitir android:supportsRtl="true" em AndroidManifest.xml. Utilize Refactor > Add RTL Support do Android Studio para converter automaticamente os layouts existentes.

Contaminação dos recursos das bibliotecas

As bibliotecas de terceiros incluem seus próprios arquivos values-XX/strings.xml, levando o Android a pensar que sua aplicação é compatível com idiomas que não traduz. Utilize resConfigs em build.gradle.kts para limitar as localidades incluídas àquelas que traduz realmente.

Estrutura de arquivos recomendada

Project Structure
MyApp/
├── app/
│   └── src/main/
│       ├── res/
│       │   ├── values/
│       │   │   ├── strings.xml          # Default (source) strings
│       │   │   └── plurals.xml          # Plural rules
│       │   ├── values-de/
│       │   │   └── strings.xml
│       │   ├── values-ja/
│       │   │   └── strings.xml
│       │   └── values-es/
│       │       └── strings.xml
│       ├── java/com/example/myapp/
│       └── AndroidManifest.xml
├── fastlane/
│   └── metadata/android/
│       ├── en-US/
│       │   ├── title.txt
│       │   ├── short_description.txt
│       │   ├── full_description.txt
│       │   └── changelogs/default.txt
│       ├── de-DE/
│       └── ja-JP/
├── build.gradle.kts
└── settings.gradle.kts

Experimente já o i18n Agent

Solte aqui seu arquivo de tradução

JSON, YAML, PO, XML, CSV, Markdown, Properties

ou clique para selecionar

Idiomas de destino

Sem cadastroEstimativa imediata

Fallback regional com locale-chain-android

Quando falta uma chave de tradução em uma localidade como pt-BR, o Android passa diretamente para a pasta de recursos predefinida em vez de verificar primeiro a localidade principal pt.

Terminal
implementation("com.i18nagent:locale-chain-android:0.1.0")
Configuration
import com.i18nagent.localechain.LocaleChain

LocaleChain.configure(
    overrides = mapOf(
        "pt-BR" to listOf("pt", "en"),
        "zh-Hant-HK" to listOf("zh-Hant", "zh", "en"),
    )
)

Consulte nosso guia de fallback regional para ver a lista completa de frameworks compatíveis e as 75 cadeias integradas. Learn more →

Perguntas frequentes sobre localização de Android