La CLI de Lingo.dev traduce los recursos de cadenas de Android (strings.xml) a través de un motor de localización configurado. Con el formato android, la CLI entiende de forma nativa los elementos <resources>, <string>, <string-array> y <plurals>, conserva la estructura XML y genera las categorías de plural correctas para cada idioma de destino.
Esta guía te acompaña en todo el proceso de localización de una app Android: configurar la CLI, traducir en local y automatizar en CI para que las traducciones se publiquen con cada push.
Repositorio de ejemplo
Clona o haz un fork de lingodotdev/android-app-localization-example para seguir el proceso. El repositorio incluye un proyecto Android funcional con recursos de cadenas, una configuración de la CLI de Lingo.dev y traducciones ya confirmadas para cada idioma de destino.
Cómo funciona la localización en Android#
Android sigue una convención de directorios de recursos en la que cada idioma tiene su propio directorio values-[locale]/. En tiempo de ejecución, el sistema carga el strings.xml adecuado según el idioma configurado en el dispositivo.
app/src/main/res/
values/ # Default (source) strings
strings.xml
values-es/ # Spanish
strings.xml
values-fr/ # French
strings.xml
values-ja/ # Japanese
strings.xmlUn archivo strings.xml típico contiene tres tipos de elementos:
<resources>
<!-- Simple strings -->
<string name="app_name">My App</string>
<string name="welcome_message">Welcome back!</string>
<!-- String arrays -->
<string-array name="planets">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
</string-array>
<!-- Plurals -->
<plurals name="items_count">
<item quantity="one">%d item</item>
<item quantity="other">%d items</item>
</plurals>
</resources>La CLI analiza los tres tipos de elementos, traduce su contenido mediante el motor de localización y escribe archivos por idioma en los directorios values-[locale]/ correspondientes.
Requisitos previos#
Crea un motor de localización
Cada ejecución de CLI envía el contenido a través de un motor de localización, la configuración que determina qué modelo de LLM, glosario, voz de marca y reglas se aplican. Crea uno en el panel de Lingo.dev.
Comprueba Node.js
La CLI requiere Node.js 22 o superior:
node -vInstala la CLI
Instala la CLI de forma global para disponer del comando lingo:
npm install -g @lingo.dev/cliInicia sesión
Autentícate con una contraseña de un solo uso:
lingo loginPara CI, usa una clave de API: pasa --api-key o configura LINGO_API_KEY.
Prepara tu proyecto Android
Tu proyecto necesita un archivo strings.xml por defecto en app/src/main/res/values/. Android Studio crea este archivo al iniciar un proyecto nuevo. Consulta la guía de localización de Android para configurar los directorios de recursos.
Configura la CLI#
Ejecuta lingo init en la raíz de tu proyecto para crear .lingo/config.json con tus idiomas de origen y destino, además de los patrones de archivo; después, ejecuta lingo link para asociar tu organización y tu motor. El resultado tendrá este aspecto:
{
"orgId": "org_...",
"engineId": "eng_...",
"sourceLocale": "en",
"targetLocales": ["es", "fr", "de", "ja"],
"files": [
{
"pattern": "app/src/main/res/values/strings.xml",
"format": "android"
}
]
}El patrón apunta a tu directorio de recursos predeterminado: el values/ sin calificador, justo donde Android espera encontrar las cadenas de origen. No incluye ningún código de idioma, ni lo necesita.
Por qué `format` se define explícitamente
La CLI detecta automáticamente la mayoría de los formatos a partir de la extensión del archivo, pero .xml es ambiguo, así que los archivos de recursos de Android necesitan un "format": "android" explícito en la entrada de files.
Varios archivos de recursos
Si tu proyecto reparte las cadenas entre varios archivos (por ejemplo, strings.xml y arrays.xml), añade una entrada en files para cada uno:
{
"files": [
{
"pattern": "app/src/main/res/values/strings.xml",
"format": "android"
},
{
"pattern": "app/src/main/res/values/arrays.xml",
"format": "android"
}
]
}Haz commit de .lingo/config.json en tu repositorio.
Directorios de idioma y calificadores#
Android guarda el idioma predeterminado en un directorio values/ sin calificador, así que la ruta de origen no lleva ningún código de idioma. La CLI lo reconoce: trata values/ a secas como el idioma de origen y añade el calificador de destino para cada uno de los demás idiomas.
| Idioma | Directorio de recursos |
|---|---|
en (origen) | values/ |
es | values-es/ |
pt-BR | values-pt-rBR/ |
zh-Hans | values-b+zh+Hans/ |
Aquí conviene entender los idiomas regionales y con escritura, porque un calificador de recursos no es una etiqueta BCP 47 sin más. Android acepta dos formas: el formato heredado idioma-región (values-pt-rBR/) y una forma BCP 47 con el prefijo b+ (values-b+pt+BR/, en API 24 y posteriores). Un directorio llamado values-pt-BR/ se ignora por completo: las cadenas existirán, pero nunca llegarán a cargarse.
Si configuras "format": "android", la CLI generará por ti la forma correcta: el formato heredado siempre que pueda representar el idioma, y b+ para escrituras, idiomas de tres letras y regiones numéricas.
Actualizar desde una configuración anterior
Las versiones anteriores de la CLI exigían que el idioma apareciera en la ruta de origen, y esta guía solía recomendar un enlace simbólico values-en -> values para conectar ambas convenciones. A partir de @lingo.dev/cli 1.12.0, eso ya no hace falta: haz que el patrón apunte a values/strings.xml y elimina el enlace simbólico.
Traduce en local#
Ejecuta la CLI. En la primera ejecución, o siempre que añadas un nuevo idioma de destino, usa --backfill-missing para traducir todas las cadenas existentes:
lingo push --backfill-missingLa CLI lee tu archivo de origen strings.xml, identifica las entradas sin traducir mediante el estado de ejecución, traduce el delta a través de tu motor de localización y escribe los resultados en los directorios de destino values-[locale]/. Abre cualquier archivo de destino para ver las cadenas traducidas.
En las siguientes ejecuciones, lingo push traduce solo lo que haya cambiado:
lingo pushPara limitar una ejecución a archivos concretos, pasa un glob. Los patrones se comparan con las rutas de origen, así que delimita el alcance por el archivo de origen, no por uno de destino:
lingo push "app/src/main/res/values/strings.xml"Para traer a tu árbol de trabajo traducciones generadas en otro lugar (por ejemplo, en CI), ejecuta lingo pull.
Plurales#
Android usa elementos <plurals> con cadenas de cantidad de CLDR (zero, one, two, few, many, other) para gestionar las formas plurales. Cada idioma requiere categorías de plural distintas: el inglés necesita dos (one y other), el ruso necesita cuatro y el árabe, seis.
La CLI conserva la estructura de <plurals> durante la traducción y genera las entradas de cantidad correctas para cada idioma de destino. Una entrada de origen con dos categorías:
<plurals name="messages_count">
<item quantity="one">%d new message</item>
<item quantity="other">%d new messages</item>
</plurals>Genera las categorías correctas para cada idioma de destino. El motor de localización sabe qué reglas de plural de CLDR se aplican a cada idioma y genera solo las categorías que ese idioma necesita.
Bloqueo de claves#
Algunos valores de texto deben mantenerse idénticos en todos los idiomas: nombres de marca, endpoints de API o patrones de formato. Usa el bloqueo de claves para copiar esos valores sin traducirlos:
{
"files": [
{
"pattern": "app/src/main/res/values/strings.xml",
"format": "android",
"lockedKeys": ["app_name", "api_base_url"]
}
]
}Las claves bloqueadas se copian del origen a todos los archivos de destino sin pasar por el flujo de traducción.
Automatiza en CI#
La forma recomendada de mantener las traducciones al día es la GitHub App de Lingo.dev. Se ejecuta del lado del servidor, lee tus archivos versionados .lingo/config.json y engineId, y abre automáticamente actualizaciones de traducción, sin runners, sin secretos almacenados y sin tener que gestionar lockfiles por tu parte. Instálala y conéctala a tu repositorio para traducir con cada push.
Si prefieres ejecutar la CLI dentro de tu propio pipeline, añade un flujo de trabajo que instale la CLI y ejecute lingo push:
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm install -g @lingo.dev/cli
- run: lingo push --backfill-missing
env:
LINGO_API_KEY: ${{ secrets.LINGO_API_KEY }}Guarda tu clave de API como LINGO_API_KEY en Settings > Secrets and variables > Actions de tu repositorio de GitHub y, después, haz commit de los archivos de destino actualizados (o abre una pull request) como paso posterior.
Verifica antes de desplegar#
Usa lingo check como puerta de control del despliegue para asegurarte de que no llegue ninguna cadena sin traducir a producción. El comando finaliza con un estado distinto de cero si alguna entrada necesita traducción:
lingo checkAñádelo como un paso de CI independiente antes del build:
- name: Verify translations
run: lingo check
env:
LINGO_API_KEY: ${{ secrets.LINGO_API_KEY }}