Skip to main content

Guía completa para localizar aplicaciones Android

Desde strings.xml hasta los metadatos de Play Store: localice su aplicación Android con Kotlin, Jetpack Compose, Fastlane y traducción automatizada mediante IA.

1

Preparar su proyecto Android para la localización

Android utiliza una convención basada en carpetas para la localización. Las cadenas predeterminadas residen en res/values/strings.xml y las traducidas van en carpetas específicas, como res/values-de/ o 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
La carpeta res/values/ es su configuración regional de respaldo. Si falta una cadena en una carpeta específica, Android la carga desde la predeterminada. Sin embargo, si falta en esta última, la aplicación se bloquea en configuraciones regionales no admitidas.
2

Crear strings.xml

Los recursos de cadenas de Android utilizan XML con elementos '<string>' dentro de una raíz '<resources>'. Utilice %s para marcadores de cadenas, %d para enteros y %1$s/%2$s para argumentos posicionales que los traductores puedan 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>
Los apóstrofos sin escapar bloquean silenciosamente el analizador XML. Utilice \' o envuelva el valor entre comillas dobles. Además, si falta una cadena en values/strings.xml predeterminado, se produce un bloqueo total, no un respaldo elegante como en 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

Gestionar plurales

Android utiliza elementos '&lt;plurals&gt;' con atributos quantity: zero, one, two, few, many y other. Cada idioma de destino puede necesitar categorías distintas: el árabe utiliza las 6, el ruso necesita few/many y el japonés solo utiliza 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
) -->
El atributo quantity selecciona la forma plural según las reglas CLDR de la configuración regional del dispositivo. Incluya siempre «other» como respaldo: es la única categoría cuya existencia se garantiza en todos los idiomas.
4

Utilizarlo en el código: Kotlin y Jetpack Compose

Android tradicional utiliza getString(R.string.key) y resources.getQuantityString(). Jetpack Compose utiliza stringResource(R.string.key) y pluralStringResource(). Ambos resuelven durante la ejecución la traducción correcta según la configuración regional del 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): el parámetro count se pasa dos veces. La primera selecciona la forma plural y la segunda es el argumento de formato. Omitir el segundo count es el error de pluralización más habitual en Compose.
5

Matrices de cadenas y cadenas con formato

Utilice '&lt;string-array&gt;' para listas ordenadas —por ejemplo, opciones de desplegables o pasos de incorporación—. Use argumentos de formato posicionales (%1$s, %2$d) en las cadenas con formato para que los traductores puedan reordenar las palabras sin romper la estructura de la 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>
Los argumentos posicionales como %1$s permiten reordenar libremente los parámetros. «Hello %1$s, you have %2$d items» puede convertirse en «%2$d items for %1$s» en idiomas con otro orden de palabras, sin cambiar el código.
6

Localizar los metadatos de Google Play con Fastlane

Utilice el comando supply de Fastlane para gestionar los metadatos de Play Store —título, descripción breve, descripción completa y registros de cambios— como archivos de texto sin formato organizados por configuración regional en su repositorio.

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 su ficha de Play Store aumenta las descargas más de un 30 % en mercados donde no se habla inglés. El título y las descripciones breve y completa se indexan para las búsquedas: traducirlos es la localización con mayor retorno de la inversión que puede realizar.
Google Play

Automatice la localización de su ficha de Play Store

Evite copiar y pegar manualmente. Traduzca el título, la descripción y las notas de la versión de Play Store a más de 175 configuraciones regionales teniendo en cuenta los límites de caracteres.

Explorar la integración con Google Play
7

Probar su localización

Realice pruebas cambiando la configuración regional del emulador, con vistas previas de Compose que utilicen una LocaleList personalizada y con pseudoconfiguraciones regionales en Opciones para desarrolladores. Utilice resConfigs en Gradle para eliminar los recursos regionales no deseados de bibliotecas de terceros.

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
Pruebe con alemán —el texto se alarga alrededor de un 30 %— y japonés —se acorta aproximadamente un 50 %— para detectar problemas de diseño. Active las pseudoconfiguraciones regionales —en-XA para texto acentuado y ar-XB para RTL— en Opciones para desarrolladores y someta los diseños a pruebas exigentes sin traducciones reales.

Automatizar la calidad de la traducción

Detecte las claves ausentes, los marcadores de posición rotos y los problemas de plurales antes de publicar con i18n-validate. Pruebe la interfaz con pseudotraducciones mediante i18n-pseudo antes de recibir las reales.
8

Automatizar traducciones

Traduzca strings.xml, plurales, matrices de cadenas y metadatos de Fastlane Supply con IA. Automatice tanto las cadenas de la aplicación como los metadatos de Play Store para ofrecer una presencia completamente 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
i18n Agent gestiona los escapes XML de Android, conserva los marcadores translatable="false", respeta las categorías de plural CLDR de cada idioma de destino y mantiene intactos los argumentos de formato posicionales.
JetBrains

Plugin para Android Studio disponible

Traduzca recursos XML de Android directamente desde su IDE con el plugin de i18n Agent para IntelliJ / Android Studio.

Install
+

Extra: respaldo inteligente de configuraciones regionales con LocaleChain

El respaldo de recursos de Android está controlado por el sistema operativo. Cuando faltan traducciones pt-BR, Android omite por completo pt-PT y muestra inglés. LocaleChain intercepta las búsquedas de cadenas y recorre una cadena de respaldo configurable, de modo que los usuarios regionales ven la traducción disponible más próxima.

LocaleChain para Android es una biblioteca Kotlin de código abierto. Ver en 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"))
)

Errores habituales

La ausencia de cadenas predeterminadas provoca bloqueos

A diferencia de iOS, que muestra la clave sin procesar, Android se bloquea con ResourceNotFoundException si falta una cadena en res/values/strings.xml predeterminado. Asegúrese siempre de que todas las claves existan en el archivo predeterminado.

La división por idiomas de App Bundle rompe el cambio dentro de la aplicación

Los App Bundles de Google Play dividen los APK por idioma: los usuarios solo reciben las cadenas del idioma de su dispositivo. Si ofrece un cambio de idioma dentro de la aplicación, añada bundle '{ language { enableSplit = false } }' a build.gradle.kts.

Los diseños RTL se rompen

Utilizar left/right en lugar de start/end en los diseños u omitir android:supportsRtl="true" en AndroidManifest.xml. Utilice Refactor > Add RTL Support de Android Studio para convertir automáticamente los diseños existentes.

Contaminación de recursos de bibliotecas

Las bibliotecas de terceros incluyen sus propios archivos values-XX/strings.xml y hacen que Android crea que su aplicación admite idiomas que en realidad no ofrece. Utilice resConfigs en build.gradle.kts para limitar las configuraciones regionales incluidas a las que traduce de verdad.

Estructura de archivos 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

Pruebe i18n Agent ahora

Arrastre y suelte aquí su archivo de traducción

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

o haga clic para seleccionar

Idiomas de destino

No es necesario registrarsePresupuesto al instante

Respaldo de configuraciones regionales con locale-chain-android

Cuando falta una clave de traducción en una configuración regional como pt-BR, Android pasa directamente a la carpeta de recursos predeterminada en vez de comprobar primero la configuración 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 nuestra guía de respaldo de configuraciones regionales para ver todos los frameworks admitidos y las 75 cadenas integradas. Learn more →

Preguntas frecuentes sobre localización de Android