GitLab CI/CD

Max PrilutskiyCEO y cofundadorActualizado el hace 3 meses · 4 min de lectura

Ejecuta Lingo.dev dentro de GitLab CI para que cada merge request que agregue o cambie cadenas fuente vuelva con las traducciones ya listas. El pipeline ejecuta lingo push, el motor de localización traduce solo las claves nuevas o modificadas, y el resultado se confirma directamente en la rama del MR — las traducciones aparecen en el diff del MR y se revisan antes de que alguien haga el merge. Nada llega a tu rama predeterminada sin que nadie lo vea.

Ejemplo funcional

Encontrarás una configuración completa y lista para ejecutar en gitlab.com/lingo.dev/gitlab-cicd-example.

Requisitos previos#

  • Una organización y un motor de Lingo.dev, además de una clave API de servicio (Dashboard → API Keys → create, type service).

  • Un proyecto configurado para Lingo.dev. Genéralo una sola vez con:

    bash
    npx @lingo.dev/cli@latest init   # scaffolds .lingo/config.json
    npx @lingo.dev/cli@latest link   # connects the project to your org + engine

    .lingo/config.json define los idiomas de origen y destino, además de los globs de origen:

    json
    {
      "sourceLocale": "en",
      "targetLocales": ["es", "fr", "de", "zh"],
      "files": [{ "pattern": "locales/en.json" }],
      "orgId": "org_...",
      "engineId": "eng_..."
    }
  • Una base ya confirmada. La primera vez, traduce todo y confírmalo para que CI tenga un lockfile contra el cual comparar diferencias:

    bash
    npx @lingo.dev/cli@latest push --backfill-missing --wait
    git add locales .lingo && git commit -m "chore(i18n): baseline translations"

Tokens de acceso#

Agrega dos variables de CI/CD enmascaradas en Settings → CI/CD → Variables:

  • LINGO_API_KEY — tu clave de servicio de Lingo.dev (lingo_sk_...). La CLI la detecta automáticamente para autenticarse.
  • GITLAB_PUSH_TOKEN — un Project Access Token con el alcance write_repository (rol Developer). Esto permite que CI confirme las traducciones de vuelta en la rama del MR.

Crea el Project Access Token en Settings → Access tokens. CI_JOB_TOKEN no puede hacer push de commits, así que hace falta un token dedicado para este paso. Los project access tokens requieren un plan de pago de GitLab.

Pipeline#

Confirma este .gitlab-ci.yml. Se ejecuta en merge requests dirigidos a la rama predeterminada y devuelve las traducciones a la rama de origen del MR:

yaml
stages:
  - localize

localize:
  stage: localize
  image: node:22-alpine
  rules:
    # Only on merge requests that target the default branch.
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
  before_script:
    - apk add --no-cache git
  script:
    # Pin the CLI version — never @latest; bump deliberately after testing.
    # --wait blocks until the engine finishes and writes files: since 1.6.0
    # `push` is async by default (it submits the run and exits), so CI must
    # wait to have something to commit.
    - npx -y @lingo.dev/cli@1.6.0 push --wait
    - |
      if [ -z "$(git status --porcelain)" ]; then
        echo "Translations already up to date — nothing to commit."
        exit 0
      fi
      git config user.name "lingo-bot"
      git config user.email "bot@lingo.dev"
      git add locales .lingo/lock.json
      # [skip ci] keeps the bot's own commit from re-triggering this pipeline.
      git commit -m "chore(i18n): sync translations [skip ci]"
      git push "https://oauth2:${GITLAB_PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" "HEAD:${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}"

Pruébalo#

bash
git checkout -b feat/new-strings
# add or change a key in locales/en.json
git commit -am "feat: add strings" && git push -u origin feat/new-strings
# open an MR feat/new-strings -> main (UI, or: glab mr create --fill --target-branch main)

El pipeline del MR ejecuta lingo push --wait, confirma locales/{...}.json junto con el .lingo/lock.json actualizado en la rama del MR, y las traducciones aparecen en el diff. Luego, una persona revisora ajusta cualquier valor y hace el merge.

Cómo sobreviven las ediciones humanas#

lingo push conserva las ediciones manuales por clave:

  • Edita una cadena de destino (sin cambiar su fuente en inglés) → esa cadena se conserva; todas las demás claves se siguen traduciendo.
  • Cambia la fuente en inglés de una clave editada → se genera una traducción nueva para esa clave (porque cambió el significado).
  • Se agrega una nueva clave fuente → se traduce y se añade, incluso en archivos que contienen ediciones manuales.

Así, la corrección que haga una persona revisora en el MR sobrevive a cada ejecución posterior del pipeline, mientras las claves nuevas y modificadas siguen fluyendo automáticamente.

modos de push#

  • lingo push — incremental; la opción predeterminada en CI. Traduce solo las claves nuevas o modificadas y conserva todo lo demás. Agrega --wait en CI para que espere hasta que se escriban las salidas (1.6.0+ es asíncrono de forma predeterminada).
  • lingo push --backfill-missing — primer push / arranque de un idioma nuevo; completa los archivos de destino que todavía no existen. No es para cambios continuos.
  • lingo push --force --yes — vuelve a traducir todo desde cero (sobrescribe las ediciones manuales). Poco frecuente.

Personalización#

  • Confirmación automática en la rama predeterminada en lugar de los MR: actívalo en $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH y haz push de vuelta a $CI_DEFAULT_BRANCH. Es más simple, pero la salida de IA llega a la rama predeterminada sin revisión.
  • Fija cadenas específicas: usa preservedKeys / lockedKeys en .lingo/config.json para mantener ciertas claves fijas incluso cuando cambie su fuente.
  • GitLab autohospedado: funciona sin cambios. En gitlab.com, las cuentas nuevas deben pasar la verificación de identidad antes de que los runners compartidos ejecuten jobs de CI.

Siguientes pasos#