El CLI de Lingo.dev traduce los recursos de texto de Android (strings.xml) mediante un motor de localización configurado. El tipo de bucket android del CLI reconoce 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 lleva por todo el proceso de localización de una app de Android: configurar el CLI, traducir en local y automatizar con GitHub Actions para que las traducciones se publiquen con cada push.
Repositorio de ejemplo
Clona o haz fork de lingodotdev/android-app-localization-example para seguir el paso a paso. El repositorio incluye un proyecto Android funcional con recursos de texto, una configuración del CLI de Lingo.dev y un flujo de trabajo de GitHub Actions.
Cómo funciona la localización en Android#
Android usa una convención de directorios de recursos en la que cada idioma tiene su propio directorio values-[locale]/. El sistema carga el archivo strings.xml correcto en tiempo de ejecución 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>El 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 del CLI envía el contenido a través de un motor de localización: la configuración que define qué modelo LLM, glosario, voz de marca e instrucciones se aplican. Crea uno en el dashboard de Lingo.dev y genera una API key.
Verifica Node.js
El CLI requiere Node.js 18 o superior:
node -vConfigura tu proyecto Android
Tu proyecto necesita un archivo strings.xml predeterminado 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 el CLI#
Crea un archivo i18n.json en la raíz de tu proyecto. El bucket android le indica al CLI que analice recursos XML de Android y cree archivos separados por idioma:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"android": {
"include": ["app/src/main/res/values-[locale]/strings.xml"]
}
}
}El placeholder [locale] se resuelve en tiempo de ejecución como el código de cada idioma configurado. El CLI sustituye tu idioma de origen en el patrón; por ejemplo, con source: "en", buscará values-en/strings.xml. Los idiomas de destino generan values-es/strings.xml, values-fr/strings.xml, y así sucesivamente.
Conecta el directorio del idioma predeterminado#
Android guarda las cadenas predeterminadas en values/ (sin sufijo de idioma), pero el CLI resuelve [locale] de forma literal y busca values-en/strings.xml. Crea un symlink para conectar ambas convenciones:
cd app/src/main/res
ln -s values values-enEsto hace que las cadenas de origen estén disponibles tanto en values/strings.xml (donde Android las espera) como en values-en/strings.xml (donde el CLI las busca). Haz commit del symlink en tu repositorio: git rastrea symlinks de forma nativa en macOS y Linux.
Windows
En Windows, Git puede descargar symlinks como archivos de texto plano según tu configuración. Si usas Windows, ejecuta git config core.symlinks true antes de clonar, o bien copia el directorio values/ a values-en/.
Varios archivos de recursos
Si tu proyecto divide las cadenas en varios archivos (por ejemplo, strings.xml y arrays.xml), inclúyelos todos. El symlink cubre todo el directorio, así que todos los archivos dentro de values/ estarán disponibles a través de values-en/:
{
"buckets": {
"android": {
"include": [
"app/src/main/res/values-[locale]/strings.xml",
"app/src/main/res/values-[locale]/arrays.xml"
]
}
}
}Traduce en local#
Configura tu API key y ejecuta el CLI:
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest runEl CLI lee tu archivo fuente strings.xml, identifica las entradas sin traducir mediante el lockfile, 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.
Para apuntar a un idioma específico durante el desarrollo:
npx lingo.dev@latest run --target-locale esPlurales#
Android usa elementos <plurals> con cadenas de cantidad de CLDR (zero, one, two, few, many, other) para manejar 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 necesita seis.
El 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 únicamente 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 estos valores sin traducirlos:
{
"buckets": {
"android": {
"include": ["app/src/main/res/values-[locale]/strings.xml"],
"lockedKeys": ["app_name", "api_base_url"]
}
}
}Las claves bloqueadas se copian desde el origen a todos los archivos de destino sin pasar por el flujo de traducción.
Automatiza con GitHub Actions#
Agrega un archivo de flujo de trabajo en .github/workflows/translate.yml para traducir con cada push:
Las traducciones hacen commit directamente en main: cero fricción, ideal para equipos pequeños:
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lingo.dev
uses: lingodotdev/lingo.dev@main
with:
api-key: ${{ secrets.LINGODOTDEV_API_KEY }}Guarda tu API key como LINGODOTDEV_API_KEY en Settings > Secrets and variables > Actions dentro de tu repositorio de GitHub.
Verifica antes de desplegar#
Usa la bandera --frozen como puerta de control de despliegue para asegurarte de que no lleguen cadenas sin traducir a producción. El CLI finaliza con un estado distinto de cero si alguna entrada necesita traducción:
npx lingo.dev@latest run --frozenAgrégalo como un paso de CI independiente antes de tu compilación:
- name: Verify translations
run: npx lingo.dev@latest run --frozen