Traducir tu app Android es crucial para llegar a una audiencia global. Android proporciona excelente soporte integrado para localización a través de archivos de recursos, haciendo sencillo soportar múltiples idiomas. Esta guía te guiará a través del proceso de traducir una app Android usando Kotlin.
Entendiendo la Localización de Android
La localización de Android usa recursos de cadenas almacenados en archivos XML dentro de directorios res/values. Cada idioma obtiene su propia carpeta values-xx (por ejemplo, values-es para español, values-fr para francés). Android carga automáticamente las cadenas correctas basándose en la configuración de idioma del dispositivo del usuario.
Paso 1: Crear Recursos de Cadenas
Comienza creando recursos de cadenas en tu archivo res/values/strings.xml:
res/values/strings.xml (Inglés - por defecto):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My App</string>
<string name="welcome_message">Welcome to our app!</string>
<string name="button_submit">Submit</string>
<string name="error_network">Network error. Please try again.</string>
<string name="items_count">%1$d items</string>
</resources>
Paso 2: Agregar Traducciones para Otros Idiomas
Crea carpetas específicas de idioma y archivos de cadenas:
res/values-es/strings.xml (Español):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Mi Aplicación</string>
<string name="welcome_message">¡Bienvenido a nuestra aplicación!</string>
<string name="button_submit">Enviar</string>
<string name="error_network">Error de red. Por favor, inténtalo de nuevo.</string>
<string name="items_count">%1$d elementos</string>
</resources>
res/values-fr/strings.xml (Francés):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Mon Application</string>
<string name="welcome_message">Bienvenue dans notre application!</string>
<string name="button_submit">Soumettre</string>
<string name="error_network">Erreur réseau. Veuillez réessayer.</string>
<string name="items_count">%1$d éléments</string>
</resources>
Paso 3: Usar Recursos de Cadenas en Kotlin
Reemplaza cadenas codificadas directamente con referencias a recursos:
Antes:
val welcomeTextView = findViewById<TextView>(R.id.welcomeText)
welcomeTextView.text = "Welcome to our app!"
Después:
val welcomeTextView = findViewById<TextView>(R.id.welcomeText)
welcomeTextView.text = getString(R.string.welcome_message)
O en layouts XML:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/welcome_message" />
Paso 4: Manejar Formateo de Cadenas con Variables
Usa getString() con argumentos de formato para cadenas con variables:
strings.xml:
<string name="items_count">%1$d items</string>
<string name="user_greeting">Hello, %1$s! You have %2$d messages.</string>
Kotlin:
val itemCount = 5
val message = getString(R.string.items_count, itemCount)
// Inglés: "5 items"
// Español: "5 elementos"
val userName = "John"
val messageCount = 3
val greeting = getString(R.string.user_greeting, userName, messageCount)
// Inglés: "Hello, John! You have 3 messages."
Paso 5: Pluralización
Android soporta pluralización usando recursos plurals:
res/values/strings.xml:
<plurals name="items_count">
<item quantity="zero">No items</item>
<item quantity="one">%d item</item>
<item quantity="other">%d items</item>
</plurals>
res/values-es/strings.xml:
<plurals name="items_count">
<item quantity="zero">No hay elementos</item>
<item quantity="one">%d elemento</item>
<item quantity="other">%d elementos</item>
</plurals>
Uso en Kotlin:
val count = 1
val message = resources.getQuantityString(R.plurals.items_count, count, count)
// Inglés: "1 item" (singular)
// Inglés: "5 items" (plural)
// Español: "1 elemento" (singular)
// Español: "5 elementos" (plural)
Paso 6: Localizar Imágenes y Drawables
Puedes proporcionar diferentes imágenes para diferentes idiomas:
-
Crea carpetas drawable específicas de idioma:
res/drawable/(por defecto)res/drawable-es/(Español)res/drawable-fr/(Francés)
-
Coloca imágenes localizadas en cada carpeta con el mismo nombre
-
Referéncialas normalmente:
imageView.setImageResource(R.drawable.flag_icon)
// Android selecciona automáticamente la imagen correcta basándose en el idioma
Paso 7: Formatear Fechas y Números
Usa Locale y clases de formateo para formateo localizado:
Fechas:
import java.text.SimpleDateFormat
import java.util.*
val date = Date()
val formatter = SimpleDateFormat("EEEE, MMMM dd, yyyy", Locale.getDefault())
val localizedDate = formatter.format(date)
// Inglés: "Wednesday, March 20, 2025"
// Español: "miércoles, 20 de marzo de 2025"
Números:
import java.text.NumberFormat
import java.util.*
val number = 1234.56
val formatter = NumberFormat.getNumberInstance(Locale.getDefault())
val localizedNumber = formatter.format(number)
// Inglés: "1,234.56"
// Español: "1.234,56"
Moneda:
val amount = 1234.56
val formatter = NumberFormat.getCurrencyInstance(Locale.getDefault())
val localizedCurrency = formatter.format(amount)
// Inglés (US): "$1,234.56"
// Español (ES): "1.234,56 €"
Paso 8: Manejar Idiomas de Derecha a Izquierda (RTL)
Android maneja automáticamente layouts RTL cuando usas:
startyenden lugar deleftyrighten XMLpaddingStart/paddingEnden lugar depaddingLeft/paddingRightmarginStart/marginEnden lugar demarginLeft/marginRight
XML:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:textAlignment="viewStart" />
Kotlin:
textView.paddingStart = 16.dp
textView.paddingEnd = 16.dp
Paso 9: Probar tu Localización
Usando Android Studio:
- Ve a Run > Edit Configurations
- Bajo General, establece Language al idioma que quieres probar
- Ejecuta tu app
Usando Configuración del Dispositivo:
- Ve a Settings > System > Languages & input
- Agrega o cambia el idioma del dispositivo
- Lanza tu app
Programáticamente (para pruebas):
import android.content.res.Configuration
import android.content.res.Resources
import java.util.*
fun setAppLocale(context: Context, language: String) {
val locale = Locale(language)
Locale.setDefault(locale)
val config = Configuration()
config.setLocale(locale)
context.resources.updateConfiguration(config, context.resources.displayMetrics)
}
Mejores Prácticas
1. Usar Nombres de Cadena Descriptivos
Malo:
<string name="s1">Submit</string>
Bueno:
<string name="button_submit">Submit</string>
2. Evitar Codificar Cadenas Directamente
Malo:
Toast.makeText(this, "Error occurred", Toast.LENGTH_SHORT).show()
Bueno:
Toast.makeText(this, getString(R.string.error_occurred), Toast.LENGTH_SHORT).show()
3. Usar Arrays de Cadenas para Listas
res/values/strings.xml:
<string-array name="countries">
<item>United States</item>
<item>Canada</item>
<item>Mexico</item>
</string-array>
Kotlin:
val countries = resources.getStringArray(R.array.countries)
4. Manejar HTML en Cadenas
Si necesitas formateo HTML:
strings.xml:
<string name="formatted_text"><![CDATA[This is <b>bold</b> and <i>italic</i> text.]]></string>
Kotlin:
val htmlText = getString(R.string.formatted_text)
textView.text = Html.fromHtml(htmlText, Html.FROM_HTML_MODE_LEGACY)
5. Probar Longitudes de Cadenas
Algunos idiomas son más largos que otros. Diseña tu UI para acomodar:
- Alemán y finlandés: 30-50% más largo que inglés
- Idiomas asiáticos: Pueden necesitar más espacio vertical
- Árabe y hebreo: Consideraciones de layout RTL
6. Usar Cadenas Específicas de Contexto
Si la misma palabra tiene diferentes significados en diferentes contextos:
strings.xml:
<string name="button_cancel">Cancel</string>
<string name="action_cancel_order">Cancel Order</string>
Errores Comunes
1. Olvidar Localizar Todas las Cadenas
Asegúrate de localizar:
- Etiquetas de botones
- Mensajes de error
- Mensajes Toast
- Títulos y mensajes de diálogos
- Elementos de menú
- Texto de notificaciones
2. Codificar Cadenas de Formato Directamente
Malo:
val price = String.format("$%.2f", amount)
Bueno:
val formatter = NumberFormat.getCurrencyInstance(Locale.getDefault())
val price = formatter.format(amount)
3. No Manejar Traducciones Faltantes
Si falta una traducción, Android recurre al idioma por defecto (usualmente inglés). Siempre proporciona fallbacks:
val text = try {
getString(R.string.some_string)
} catch (e: Resources.NotFoundException) {
getString(R.string.default_string)
}
4. Ignorar Soporte RTL
Siempre usa start/end en lugar de left/right para soportar idiomas RTL como árabe y hebreo.
Avanzado: Cambio Dinámico de Idioma
Para permitir a los usuarios cambiar el idioma dentro de la app:
import android.content.Context
import android.content.res.Configuration
import java.util.*
class LocaleHelper {
companion object {
fun setLocale(context: Context, language: String): Context {
val locale = Locale(language)
Locale.setDefault(locale)
val config = Configuration(context.resources.configuration)
config.setLocale(locale)
return context.createConfigurationContext(config)
}
fun getPersistedLanguage(context: Context): String {
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
return prefs.getString("language", "en") ?: "en"
}
fun persistLanguage(context: Context, language: String) {
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
prefs.edit().putString("language", language).apply()
}
}
}
Uso en Activity:
class MainActivity : AppCompatActivity() {
override fun attachBaseContext(newBase: Context) {
val language = LocaleHelper.getPersistedLanguage(newBase)
super.attachBaseContext(LocaleHelper.setLocale(newBase, language))
}
fun changeLanguage(language: String) {
LocaleHelper.persistLanguage(this, language)
recreate() // Reiniciar activity para aplicar nuevo idioma
}
}
Usando Jetpack Compose
Si estás usando Jetpack Compose para UI:
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
@Composable
fun WelcomeScreen() {
val context = LocalContext.current
Text(text = context.getString(R.string.welcome_message))
}
// Con formateo
@Composable
fun ItemCount(count: Int) {
val context = LocalContext.current
Text(text = context.getString(R.string.items_count, count))
}
Conclusión
Localizar tu app Android con Kotlin es sencillo cuando sigues estos pasos:
- Crear archivos
strings.xmlpara cada idioma en carpetasres/values-xx/ - Usar
getString()en lugar de cadenas codificadas directamente - Manejar pluralización con recursos
plurals - Formatear fechas y números usando
Locale - Soportar idiomas RTL con atributos
start/end - Probar exhaustivamente en todos los idiomas soportados
Siguiendo estas prácticas, crearás una app que proporciona una experiencia nativa para usuarios en todo el mundo, expandiendo significativamente tu base de usuarios potencial.
Optimiza tu Flujo de Trabajo de Localización Android
Gestionar traducciones para múltiples idiomas puede volverse complejo a medida que tu app crece. Considera usar una plataforma de gestión de traducciones para:
- Colaborar con traductores
- Mantener traducciones sincronizadas con tu código base
- Automatizar el flujo de trabajo de traducción
- Mantener consistencia en todos los idiomas
¿Listo para llevar tu app Android a nivel global? Explora la plataforma de localización de AZbox y optimiza tu flujo de trabajo de traducción: