# General Translation Knowledge Base: ¿Cómo localizo una app de Android con strings.xml?
URL: https://generaltranslation.com/es/kb/localize-android-app.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Guarda todas las cadenas predeterminadas en res/values/strings.xml, añade un strings.xml para cada idioma en una carpeta con calificador de configuración regional, como values-es o values-b+zh+Hant+TW, y lee el texto con stringResource o getString. Traduce a mano, en Play Console o con la CLI de General Translation, que genera cada carpeta values y reconstruye los plurales para cada idioma de destino.
Category: Internacionalización
Last updated: 2026-10-28
Authors: General Translation Team
Published: 2026-10-28

Android elige los recursos en tiempo de ejecución a partir de carpetas cuyo nombre corresponde a la configuración regional del dispositivo. El texto predeterminado se encuentra en `res/values/strings.xml`, y cada traducción es otro `strings.xml` con los mismos nombres de recurso dentro de una carpeta como `res/values-es/`. Así, te quedan dos tareas: pasar a `strings.xml` todas las cadenas que ve el usuario y conseguir buenas traducciones para cada carpeta de idioma.

## Configura los recursos de cadenas

### Coloca todas las cadenas en res/values/strings.xml

El archivo predeterminado debe contener todas las cadenas que usa la app: si falta alguna, la app &quot;no se ejecuta y muestra un error&quot;, según la guía de localización de Android. Un archivo traducido puede contener solo un subconjunto, y cualquier cadena que no incluya se toma del archivo predeterminado ([Android: Localize your app](https://developer.android.com/guide/topics/resources/localization)).

Este es un archivo predeterminado con los patrones que necesitarás, cada uno anotado:

```xml title="res/values/strings.xml"
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <!-- Botón que inicia el pago de los artículos del carrito. -->
    <string name="checkout">Checkout</string>

    <!-- Los argumentos posicionales permiten que la traducción cambie el orden de los valores. -->
    <plurals name="welcome">
        <item quantity="one">Hi %1$s, you have %2$d new message.</item>
        <item quantity="other">Hi %1$s, you have %2$d new messages.</item>
    </plurals>

    <!-- Escapa los apóstrofos; de lo contrario, la compilación fallará. -->
    <string name="cart_empty">Your cart\'s empty</string>

    <!-- xliff:g marca el texto que no debe traducirse. -->
    <string name="countdown"><xliff:g id="time" example="5 days">%1$s</xliff:g> until your trial ends</string>

    <plurals name="items_in_cart">
        <item quantity="one">%d item</item>
        <item quantity="other">%d items</item>
    </plurals>

    <string-array name="sort_options">
        <item>Newest</item>
        <item>Price: low to high</item>
    </string-array>
</resources>
```

En Compose, léelas con `stringResource`, `pluralStringResource` y `stringArrayResource`; con Views, usa `context.getString` y `resources.getQuantityString` ([Android: String resources](https://developer.android.com/guide/topics/resources/string-resource)). Para los plurales, pasa primero la cantidad para seleccionar la forma adecuada y, a continuación, los valores de los marcadores de posición, incluida la propia cantidad.

```kotlin
val greeting = pluralStringResource(R.plurals.welcome, count, name, count)
val cart = pluralStringResource(R.plurals.items_in_cart, count, count)
val sortOptions = stringArrayResource(R.array.sort_options)
```

Las aplicaciones de React Native también tienen este archivo: el `strings.xml` de la plantilla, ubicado en `android/app/src/main/res/values/`, contiene `app_name`, la etiqueta que Android muestra debajo del ícono, mientras que la UI de JavaScript se traduce aparte. (Consulta [¿Cómo traduzco una aplicación de React Native?](/kb/translate-react-native-app)).

### Asigna un nombre a la carpeta de cada idioma

Una carpeta de idioma se nombra con `values-` más un calificador de recursos. El idioma es un código ISO 639-1, la región lleva el prefijo `r` en minúscula, y cualquier variante con sistema de escritura o región numérica usa el formato BCP 47: `b+` seguido de las subetiquetas unidas con `+`, compatible desde Android 7.0 (API 24) ([Android: App resources overview](https://developer.android.com/guide/topics/resources/providing-resources)):

| Idioma                      | Código de configuración regional | Carpeta                    |
| --------------------------- | -------------------------------- | -------------------------- |
| Español                     | `es`                             | `res/values-es/`           |
| Portugués (Brasil)          | `pt-BR`                          | `res/values-pt-rBR/`       |
| Español (Latinoamérica)     | `es-419`                         | `res/values-b+es+419/`     |
| Chino (tradicional, Taiwán) | `zh-Hant-TW`                     | `res/values-b+zh+Hant+TW/` |

Añade una carpeta regional solo para las cadenas que cambien. En el ejemplo de Android, todo el inglés está en `values/` y solo las grafías británicas van en `values-en-rGB/`; para todo lo demás se recurre a la carpeta por defecto. (Consulta [¿Qué son los códigos de configuración regional?](/kb/locale-codes)).

### Escribe cadenas que los traductores no puedan romper

Estas reglas de la [guía de recursos de cadenas](https://developer.android.com/guide/topics/resources/string-resource) de Android evitan que una traducción rompa la compilación o la gramática:

* **Los plurales siguen la gramática de cada idioma.** Las cantidades son `zero`, `one`, `two`, `few`, `many` y `other`, pero cada idioma usa solo las que su gramática necesita: el inglés ignora `zero` incluso para 0, y el chino y el coreano solo usan `other`. No uses `<plurals>` como si fuera una instrucción `if` para «ningún elemento»; escribe una cadena aparte.
* **Usa argumentos posicionales.** `%1$s` y `%2$d` permiten que un traductor coloque el nombre después de la cantidad cuando el idioma de destino exige ese orden.
* **Escapa los apóstrofos y las comillas.** Escribe `\'` o envuelve toda la cadena entre comillas dobles, y escribe `\"` para una comilla literal. Escapa un `@` o `?` inicial como `\@` y `\?`; si no, Android interpreta el valor como una referencia a un recurso.
* **Protege lo que no debe cambiar.** Envuelve los marcadores de posición y las URL en `<xliff:g>` con un `id` y un `example`, como en la cadena de la cuenta regresiva ([Android: Localize your app](https://developer.android.com/guide/topics/resources/localization)).
* **Marca los recursos que nunca cambian.** Agrega `translatable="false"` a valores como el nombre de la app, o muévelos a un archivo `donottranslate.xml`.
* **Deja un comentario.** Un comentario encima de un recurso indica a los traductores dónde aparece el texto y de cuánto espacio disponen. «Checkout», sin más contexto, podría ser un sustantivo o un verbo.

## Permite que los usuarios elijan el idioma de la app

Desde Android 13 (API 33), los usuarios pueden elegir un idioma para cada app desde la configuración del sistema, siempre que la app declare los idiomas que admite. Si activas `generateLocaleConfig`, Android Gradle Plugin (AGP) 8.1 o posterior genera la lista de idiomas a partir de tus carpetas `values-*` en tiempo de compilación; para ello se necesita `compileSdk` 33 o superior y un archivo `res/resources.properties` que indique la configuración regional de la carpeta predeterminada, por ejemplo, `unqualifiedResLocale=en-US`. Si prefieres enumerar los idiomas manualmente, agrega `res/xml/locale_config.xml` y haz que `android:localeConfig` apunte a ese archivo en el manifiesto. Si haces ambas cosas, la compilación falla ([Android: Preferencias de idioma por app](https://developer.android.com/guide/topics/resources/app-languages)).

```kotlin title="app/build.gradle.kts"
android {
    androidResources {
        generateLocaleConfig = true
    }
}
```

Para ofrecer un selector de idioma dentro de la app, usa AppCompat 1.6.0 o posterior y llama a `setApplicationLocales` en el hilo principal. Esto vuelve a crear la actividad y, si usas Compose, la actividad debe extender `AppCompatActivity`:

```kotlin
// Llámalo en el hilo principal; puede reiniciar la Activity.
AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags("es"))
```

En Android 12 y versiones anteriores, AppCompat puede guardar la elección por ti si añades su `AppLocalesMetadataHolderService` al manifiesto con `autoStoreLocales` establecido en `true`. (Consulta [Prácticas recomendadas para el selector de idioma](/kb/language-switcher) para ver cómo diseñar el selector).

## Detecta cadenas faltantes y codificadas directamente

El **Translations Editor** de Android Studio muestra todas las claves en una cuadrícula, con una columna por idioma, y marca los problemas en rojo. Haz clic derecho en `strings.xml` y elige **Open Translations Editor**. El icono del globo añade un idioma y crea su carpeta `values-*`, y la casilla **Untranslatable** escribe `translatable="false"` automáticamente ([Android: Translations Editor](https://developer.android.com/studio/write/translations-editor)).

Android Lint realiza las mismas comprobaciones en CI:

* [`MissingTranslation`](https://googlesamples.github.io/android-custom-lint-rules/checks/MissingTranslation.md.html) (error) señala una cadena que falta en un idioma. Puedes suprimirla por recurso con `tools:ignore="MissingTranslation"`; además, define `tools:locale` en el elemento `<resources>` del archivo predeterminado para que lint sepa en qué idioma está.
* [`ExtraTranslation`](https://googlesamples.github.io/android-custom-lint-rules/checks/ExtraTranslation.md.html) (fatal) señala una cadena traducida sin valor predeterminado, lo que puede provocar que la app falle en las configuraciones regionales que no la incluyen.
* [`HardcodedText`](https://googlesamples.github.io/android-custom-lint-rules/checks/HardcodedText.md.html) (advertencia) señala texto literal en el XML de layout. No detecta las llamadas `Text("...")` de Compose. (Consulta [¿Cómo encuentro cadenas codificadas directamente que no están traducidas?](/kb/find-hardcoded-strings)).

## Prueba todos los idiomas

Android incluye dos pseudolocales para hacer pruebas antes de tener las traducciones. `en-XA` añade acentos, alarga el texto y pone cada mensaje entre corchetes, de modo que el truncamiento y las oraciones concatenadas salen a la luz. `ar-XB` cambia el texto a right-to-left. Establece `isPseudoLocalesEnabled = true` en el tipo de compilación de depuración, activa las Opciones para desarrolladores en el dispositivo y elige la pseudolocale en la configuración de idioma ([Android: Test with pseudolocales](https://developer.android.com/guide/topics/resources/pseudolocales)). (Consulta [What is pseudo-localization?](/kb/pseudo-localization)).

Para árabe, hebreo y persa, establece `android:supportsRtl="true"` en el elemento `<application>` y usa los atributos `start` y `end` (`paddingStart`, `layout_marginEnd`) en lugar de `left` y `right`, para que los layouts se inviertan en espejo. Añade `android:autoMirrored="true"` a los drawables direccionales y envuelve con `BidiFormatter.unicodeWrap()` cualquier valor que insertes en una oración, para que una dirección postal o un número conserve su dirección de escritura ([Android: Support different languages and cultures](https://developer.android.com/training/basics/supporting-devices/languages)). En Compose, `@Preview(locale = "ar")` muestra la vista previa de una pantalla de derecha a izquierda. (Consulta [How do I support RTL (right-to-left) languages in CSS?](/kb/right-to-left-css) para la versión web).

La ficha de tu app en Google Play Store se traduce por separado. En Play Console, abre la ficha de Play Store, haz clic en **Manage translations** y añade, para cada idioma, tu propio título, descripción breve, descripción completa y gráficos localizados ([Play Console Help: Translate and localize your app](https://support.google.com/googleplay/android-developer/answer/9844778)).

## Elige cómo traducir

Estos enfoques rellenan tus carpetas `values-*`:

| Enfoque                                                                       | Quién traduce                             | Contexto que recibe el traductor                                                          | Repetible en cada lanzamiento                                                            | Lo que queda a tu cargo                                                                                               |
| ----------------------------------------------------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Escribir en el Translations Editor                                            | Tú o un compañero bilingüe                | Toda la aplicación                                                                        | No                                                                                       | Cada cadena en cada idioma, a mano                                                                                    |
| Traducción de cadenas de la aplicación en Play Console                        | Modelos Gemini en Play Console, sin coste | Tu `strings.xml`                                                                          | Sí, en cada paquete subido a un lanzamiento en borrador                                  | Las traducciones se guardan en Play, no en tu repositorio, y reemplazan las existentes en los idiomas que selecciones |
| Enviar archivos a traductores o a un sistema de gestión de traducciones (TMS) | Traductores profesionales                 | Comentarios, además de las capturas de pantalla que adjuntes                              | Mediante la sincronización del TMS                                                       | Un ciclo de ida y vuelta por lanzamiento, con su correspondiente espera                                               |
| Traducir el XML con un script de traducción automática o un LLM               | Un modelo o una API de traducción         | Lo que envíe tu script                                                                    | Sí                                                                                       | Categorías de plural por idioma, escapado, elementos `<xliff:g>`, argumentos de formato y revisión                    |
| CLI de General Translation                                                    | El servicio de traducción de GT           | Comentarios de los recursos, además del glosario y los prompts personalizados compartidos | Ejecuta [`gt translate`](/docs/cli/reference/commands/translate) antes de la compilación | Revisar en el panel de control o en Android Studio y, después, probar la aplicación                                   |

Play Console también puede traducir la propia aplicación: cuando activas la traducción de cadenas de la aplicación, cada paquete de la aplicación que subes a un lanzamiento en borrador recibe traducciones generadas a partir de su `strings.xml` más reciente, que puedes previsualizar en un emulador y editar antes de publicar. Al seleccionar un idioma, se reemplazan las traducciones que ya tengas en él, y la casilla **Translate** permite excluir cadenas concretas ([Ayuda de Play Console](https://support.google.com/googleplay/android-developer/answer/9844778)).

Usa el Translations Editor para uno o dos idiomas que domines. Usa la traducción de Play Console si publicas a través de Google Play y no necesitas las traducciones en tu base de código. Elige General Translation si quieres confirmar los archivos `strings.xml` traducidos en cada lanzamiento y compartir terminología con tu aplicación de iOS y tu sitio web. Usa un [TMS](/kb/what-is-a-translation-management-system) si el trabajo corre a cargo de traductores profesionales o de un proveedor con el que ya trabajas.

## Traduce strings.xml con General Translation

La CLI de General Translation, `gt`, traduce los recursos de cadenas de Android mediante la clave de archivo `androidStrings` (`gt` 2.19.0 o posterior). El archivo predeterminado no incluye ninguna configuración regional en su ruta, así que haz que `include` apunte a él y usa `transform` para enviar cada traducción a la carpeta de su idioma:

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["es", "pt-BR", "zh-Hant-TW"],
  "files": {
    "androidStrings": {
      "include": ["app/src/main/res/values/strings.xml"],
      "transform": {
        "match": "res/values/(.*)",
        "replace": "res/values-{locale}/$1"
      }
    }
  }
}
```

La CLI convierte cada configuración regional al calificador que espera Android, por lo que esta configuración genera `values-es/`, `values-pt-rBR/` y `values-b+zh+Hant+TW/`. No uses un patrón `values-[locale]` en un proyecto estándar: buscaría una carpeta `values-en/`, no encontraría ninguna coincidencia y no traduciría nada.

La CLI requiere Node.js 20 o posterior. Instálala como se indica en el [Inicio rápido de la CLI](/docs/cli/quickstart), inicia sesión con [`npx gt login`](/docs/cli/reference/commands/login), configura `GT_PROJECT_ID` ([credenciales de la CLI](/docs/cli/guides/configuring#credentials)) y, si tu app ya tiene traducciones, impórtalas con [`npx gt upload`](/docs/cli/reference/commands/upload). Después, ejecuta [`npx gt translate`](/docs/cli/reference/commands/translate). En CI, guarda como `GT_API_KEY` una clave de API de proyecto con **Files &gt; Write** y **Translation queue &gt; Enabled**.

Los archivos traducidos conservan los nombres de los recursos, los elementos `<xliff:g>`, los argumentos de formato y el marcado inline. Además, se verifica que cada cadena traducida los mantenga y que incluya el escape de apóstrofos y comillas que exige la compilación de Android. Los `<plurals>` se reconstruyen según las categorías del idioma de destino: el polaco recibe `one`, `few`, `many` y `other`; el árabe, las seis, y el chino, solo `other`. Las categorías que el idioma nunca utiliza, incluido un `zero` del origen, se descartan. Los comentarios situados encima de un recurso se envían como contexto. La CLI no traduce los recursos marcados con `translatable="false"`, los valores que hacen referencia a otro recurso ni los tipos que no son texto, como `<color>`. (Consulta la [referencia de strings.xml](/docs/cli/reference/formats/android-strings-files)).

Los recursos marcados con `translatable="false"` dentro de un archivo incluido se copian sin cambios en cada archivo traducido, y la comprobación [`Untranslatable`](https://googlesamples.github.io/android-custom-lint-rules/checks/Untranslatable.md.html) de Android Lint genera una advertencia por cada copia. Guarda esos valores en `res/values/donottranslate.xml` e incluye solo `strings.xml`.

Revisa las traducciones en el [panel de control](/docs/platform/dashboard/guides/reviewing-translations) o en Android Studio; si editas archivos localmente, ejecuta [`npx gt save-local`](/docs/cli/reference/commands/save-local) para que las ejecuciones posteriores conserven tus cambios. Asigna un mismo [grupo de contexto](/docs/platform/dashboard/guides/defining-context-for-translations) a tus proyectos de Android, [iOS](/kb/localize-ios-app) y web, y los términos del glosario, como el nombre de un plan, se traducirán igual en todas partes. Partiful usa General Translation para más de 2 configuraciones regionales en web, iOS y Android ([despliegues en producción](https://generaltranslation.com/enterprise)).

## Preguntas frecuentes

### ¿Necesito una carpeta values-en para el inglés?

No. La carpeta `values/` sin calificador se usa para todas las configuraciones regionales que no traduzcas. Cuando activas `generateLocaleConfig`, `resources.properties` le indica a la compilación qué configuración regional corresponde a esa carpeta.

### ¿Por qué mi aplicación traducida muestra algunas cadenas en inglés?

Al archivo `strings.xml` traducido le faltan esos nombres, así que Android recurre a los de `values/`. La comprobación `MissingTranslation` de Lint los enumera por idioma.

### ¿Google Play traduce automáticamente mi ficha de Play Store?

Quienes vean tu ficha en un idioma que no hayas traducido pueden optar por ver una traducción automática. Las traducciones que añadas en **Manage translations** la sustituyen en cada idioma que incluyas.

## Conclusiones clave

* `res/values/strings.xml` debe contener todas las cadenas; las carpetas traducidas pueden incluir solo un subconjunto y recurrir a ese archivo para el resto.
* Los nombres de carpeta usan calificadores: `values-pt-rBR` para una región y `values-b+zh+Hant+TW` para un sistema de escritura.
* Usa argumentos posicionales como `%1$s`, escapa los apóstrofos y deja que cada idioma defina sus propias categorías de `<plurals>`.
* Activa `generateLocaleConfig` (AGP 8.1+) para admitir la configuración de idioma por aplicación de Android 13, y haz pruebas con las pseudolocales `en-XA` y `ar-XB`.
* La CLI de General Translation traduce `strings.xml` mediante `androidStrings` y un `transform` hacia `values-{locale}`: escribe el calificador que Android espera y reconstruye los plurales para cada idioma.

## Related questions

- [¿Cómo localizo una app de iOS con String Catalogs?](https://generaltranslation.com/es/kb/localize-ios-app.mdx): Agrega tus idiomas en Xcode, escribe el texto visible para el usuario con API localizables como Text de SwiftUI y String(localized:), y compila para que Xcode recopile esas cadenas en un String Catalog (.xcstrings). Traduce en Xcode, mediante XLIFF o con la CLI de General Translation si quieres que los catálogos se actualicen con cada lanzamiento y compartan terminología con tu sitio web y tu app de Android.
- [¿Cómo traduzco una app de React Native?](https://generaltranslation.com/es/kb/translate-react-native-app.mdx): Marca el texto en tus componentes, genera un archivo de traducciones para cada idioma, agrega polyfills de Intl y carga el archivo correspondiente al idioma del dispositivo. Con gt-react-native, la biblioteca experimental de General Translation, envuelves el texto en `<T>`, un plugin de Babel agrega los polyfills y npx gt translate genera los archivos.
- [¿Qué es la pseudolocalización?](https://generaltranslation.com/es/kb/pseudo-localization.mdx): La pseudolocalización es una prueba que sustituye tu texto de origen por una versión alterada (con acentos, alrededor de un 40 % más larga y entre corchetes) para que las cadenas codificadas de forma fija, el truncamiento, las fuentes rotas y las oraciones concatenadas salgan a la luz antes de que exista ninguna traducción. Android incluye para ello las pseudoconfiguraciones regionales en-XA y ar-XB.
- [¿Cómo encuentro cadenas codificadas de forma fija que no están traducidas?](https://generaltranslation.com/es/kb/find-hardcoded-strings.mdx): Ejecuta en CI un linter que marque los literales de cadena visibles para el usuario, como la regla no-literal-string de eslint-plugin-i18next para JSX, la comprobación HardcodedText de Android Lint o el linter HardCodedString de erb_lint para Rails. Después, recorre la app con una pseudoconfiguración regional para detectar el texto que las comprobaciones estáticas no pueden rastrear.
- [¿Cómo doy soporte a idiomas RTL (right-to-left) en CSS?](https://generaltranslation.com/es/kb/right-to-left-css.mdx): Coloca dir="rtl" y lang en el elemento html, ya que lang por sí solo no cambia la dirección, y luego sustituye el CSS físico, como margin-left, por propiedades lógicas, como margin-inline-start. Las filas flex, las columnas de grid y la alineación de texto predeterminada se invierten solas; translateX(), left y right, no.

## Previous and next questions

- Previous question: [¿Cómo creo un mapa del sitio para un sitio web multilingüe?](https://generaltranslation.com/es/kb/multilingual-sitemap.mdx)
- Next question: [¿Cómo mantengo la coherencia terminológica en la traducción con IA?](https://generaltranslation.com/es/kb/ai-translation-glossary.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/es/kb/sitemap.md) for every article.
