App de GitHub

Moses SkodaIngeniero13 min de lectura

La App de GitHub de Lingo.dev configura la localización continua de un repositorio mediante .lingo/config.json.

Requisitos previos#

Antes de instalar la app, asegúrate de tener:

  • Una organización de Lingo.dev con la función de integración con GitHub activada
  • Un motor de localización en esa organización
  • Acceso de administrador a la organización o al repositorio de GitHub que quieras conectar

Si no eres administrador de la organización de GitHub, GitHub te permite solicitar la instalación. Un administrador de la organización de GitHub debe aprobar esa solicitud antes de que Lingo.dev pueda acceder a los repositorios seleccionados.

Instala la aplicación de GitHub#

  1. En Lingo.dev, abre tu organización.
  2. Ve a Studio > All integrations.
  3. En la tarjeta de GitHub, haz clic en Install on GitHub.
  4. En GitHub, elige la cuenta o la organización en la que quieres instalar la app.
  5. Elige All repositories o Only select repositories.
  6. Haz clic en Install.

GitHub te devuelve a Lingo.dev, a la pantalla Conectar GitHub:

  1. Elige la organización de Lingo.dev a través de la que esta cuenta de GitHub localiza contenido. Se seleccionará automáticamente la última organización que hayas abierto.
  2. Haz clic en Conectar.
  3. Cuando veas GitHub conectado, haz clic en Ver integración para abrir la conexión.

La conexión aparece en la barra lateral de Studio, en Conectado. En la pestaña Configuración verás la Cuenta, el Tipo de cuenta, la Instalación, los Repositorios y si la Conexión funciona correctamente. En la pestaña Ejecuciones de flujo de trabajo se muestra cada ejecución que realiza la aplicación, junto con el repositorio y si la inició un push o una solicitud de extracción.

Si más adelante quieres añadir o quitar repositorios, abre la pestaña Configuración de la conexión y usa Gestionar en GitHub. El acceso a los repositorios siempre se selecciona en GitHub, en la propia instalación.

Si solicitaste la instalación en lugar de instalarla, Lingo.dev mostrará Instalación solicitada: un administrador de la organización de GitHub tendrá que aprobarla. Cuando lo haga, GitHub te devolverá a la pantalla Conectar GitHub para completar el proceso. El administrador puede revisar la solicitud en GitHub, en Configuración > GitHub Apps dentro de la organización. GitHub también muestra las solicitudes de aplicaciones pendientes a los propietarios de la organización en la configuración de la organización.

Añadir la configuración del repositorio#

Crea .lingo/config.json en el repositorio en el que hayas instalado la app:

json
{
  "engineId": "eng_abc123",
  "sourceLocale": "en",
  "targetLocales": ["es", "fr", "de"],
  "files": [
    { "pattern": "docs/en/**/*.md" },
    { "pattern": "docs/en/**/*.mdx" },
    { "pattern": "locales/en.json" }
  ],
  "github": {
    "workflows": {
      "onPushToDefaultBranch": { "enabled": true },
      "onPullRequest": { "enabled": true }
    },
    "safety": {
      "requireApproval": false
    }
  }
}
CampoObligatorioDescripción
engineIdSíEl motor de Lingo.dev que debe traducir este repositorio.
sourceLocaleSíEl idioma de origen que se usa en las rutas de tus archivos fuente, como en o en-US.
targetLocalesSíCódigos de idioma a los que traducir. Se admiten hasta 50 idiomas únicos.
filesSíPatrones de archivos fuente relativos al repositorio. Se admiten hasta 100 patrones.
github.workflows.onPushToDefaultBranch.enabledNoSe ejecuta cuando los archivos fuente cambian en la rama por defecto. Está activado de forma predeterminada.
github.workflows.onPullRequest.enabledNoSe ejecuta cuando los archivos fuente cambian en pull requests. Está desactivado de forma predeterminada.
github.safety.requireApprovalNoRequiere aprobación antes de que traduzcan los flujos de trabajo automáticos de push o PR. Está desactivado de forma predeterminada.

Usa la CLI para guardar la configuración del repositorio. Ejecuta estos comandos en este orden:

  1. Ejecuta npx @lingo.dev/cli init para guardar el idioma de origen, los idiomas de destino y los patrones de archivo en .lingo/config.json.
  2. Ejecuta npx @lingo.dev/cli login para iniciar sesión y guardar tus credenciales localmente en ~/.lingo/credentials.json.
  3. Ejecuta npx @lingo.dev/cli link para seleccionar una organización y un motor. Esto añade orgId y engineId a .lingo/config.json.

El comando init no escribe la sección github. Si la necesitas, cópiala del ejemplo anterior. Consulta la guía de inicio rápido de la CLI.

Patrones de archivo#

Los patrones files apuntan a archivos fuente (idioma predeterminado). La app comprueba los archivos modificados con esos patrones y solo procesa los archivos fuente compatibles que coinciden.

Los patrones son relativos al repositorio, distinguen entre mayúsculas y minúsculas y pueden usar:

  • * para coincidir dentro de un segmento de ruta
  • **/ para coincidir con cualquier profundidad de directorios

Los patrones no pueden empezar por / ni contener ...

json
{
  "files": [
    { "pattern": "docs/en/**/*.md" },
    { "pattern": "src/content/en/**/*.mdx" },
    { "pattern": "messages/en.jsonc" }
  ]
}

Opciones de archivo#

Cada entrada de files puede incluir opciones además de su pattern. Todas son opcionales y cada una solo se aplica a determinados formatos.

OpciónSe aplica aDescripción
formatTodosAnula el formato deducido a partir de la extensión del archivo. Es obligatorio para OpenAPI YAML ("yaml-openapi").
include / excludeTodosListas de globs para acotar qué archivos coincide con la entrada, usadas junto con pattern o en su lugar.
translateFrontmatterFieldsMarkdown, MDX, MarkdocClaves de frontmatter que deben traducirse. Por defecto, son title y description.
translateComponentPropsMDX, MarkdocProps de componentes MDX y atributos de etiquetas de Markdoc que deben traducirse.
lockedKeysJSON, JSONCRutas de claves que mantienen el valor de origen y nunca se traducen.
preservedKeysJSON, JSONCRutas de claves que mantienen el valor de destino existente y no se vuelven a traducir.
injectLocaleJSON, JSONCEscribe el código del idioma de destino en la salida en la clave indicada (por defecto, language).

Las entradas translateComponentProps pueden ser un nombre de prop, que se aplica a esa prop en cualquier componente o etiqueta, o un objeto que limita las props a componentes o etiquetas concretos:

json
{
  "files": [
    {
      "pattern": "src/content/en/**/*.mdx",
      "translateFrontmatterFields": ["title", "description"],
      "translateComponentProps": [
        "alt",
        { "component": ["Callout", "Hero"], "props": ["title", "subtitle"] }
      ]
    },
    {
      "pattern": "locales/en.json",
      "lockedKeys": ["app.version"],
      "injectLocale": { "enabled": true, "key": "language" }
    }
  ]
}

Dónde se escriben los archivos localizados#

La app deriva cada ruta de destino a partir de la ruta de origen y de los códigos de idioma de tu configuración:

Ruta de origenIdioma de destinoRuta de salida
docs/en/guide.mdesdocs/es/guide.md
docs/en-US/guide.mdfr-FRdocs/fr-FR/guide.md
locales/en.jsondelocales/de.json
README.mdeses/README.md
Localizable.xcstringses-MXLocalizable.xcstrings (mismo archivo)

Usa el nombre completo del directorio o del archivo como código de idioma. Por ejemplo, si los archivos fuente están en docs/en-US/, configura "sourceLocale": "en-US", no "en". Si las cadenas de origen están en messages/en.json, configura "sourceLocale": "en".

Cuando la ruta de origen contiene un directorio de idioma, la app sustituye ese directorio. Cuando la ruta de origen es un archivo con nombre de idioma, la app sustituye el nombre del archivo. Si no existe ninguno de esos patrones, la app coloca el archivo traducido en un nuevo directorio del idioma de destino junto al archivo fuente.

Los catálogos de cadenas son la excepción. Como un archivo .xcstrings contiene todos los idiomas, la ruta de destino coincide con la de origen: la aplicación escribe cada idioma en ese mismo archivo y nunca añade un directorio de idioma ni un nombre de archivo.

Flujos de trabajo#

Push a la rama por defecto#

Cuando se añade o modifica un archivo fuente coincidente en la rama por defecto, la app lo traduce y hace commit de los archivos localizados en:

txt
lingo/translations/<default-branch>

Después, abre o actualiza una pull request desde esa rama de traducciones hacia la rama por defecto. Si la rama de traducciones ya existe, se añaden nuevos commits a ella.

Si en el mismo push se añade o modifica un archivo de destino, la app considera que ese archivo ya está gestionado y lo incorpora a la PR de traducción en lugar de sobrescribirlo.

Pull requests#

Cuando github.workflows.onPullRequest.enabled es true, la app revisa los cambios de la pull request en busca de archivos fuente coincidentes. Hace commit de los archivos traducidos directamente en la rama de la PR.

La app no escribe en ramas de PR procedentes de forks ni en la rama por defecto desde un comentario en una PR. Las pull requests deben estar abiertas para que la app pueda hacer commit de las traducciones.

En las PR, Lingo.dev actualiza un comentario con los archivos traducidos y cualquier error.

Actualizaciones incrementales y recuperación#

En los archivos de destino existentes, la app traduce solo los cambios de origen que puede detectar en lugar de regenerar el archivo completo. Para los archivos de destino nuevos, crea el archivo localizado para cada idioma de destino configurado.

Si una localización anterior de una PR omitió un cambio de origen o falló antes de actualizar el archivo de destino, la siguiente sincronización de la PR puede recuperarlo comparando el origen de la PR con el origen de la rama base y traduciendo el cambio que falta.

Si un archivo fuente ya no existe en el commit que se está procesando, la app lo omite.

Modo de aprobación#

Configura github.safety.requireApproval como true cuando quieras añadir un paso de aprobación humana antes de que se ejecuten las traducciones automáticas.

En los pushes a la rama por defecto, la comprobación de Lingo.dev muestra las acciones Approve y Deny. En las pull requests, la app publica un comentario con una propuesta de traducción; responde con:

txt
/lingo approve

Los comandos /lingo translate con alcance definido no requieren esta validación previa.

Comando manual para PR#

Usa /lingo en un comentario de una solicitud de cambios para traducir los cambios en el origen, crear los archivos de destino que faltan o volver a traducir las claves seleccionadas.

Traduce los cambios en el origen de la solicitud de cambios sin modificar las traducciones que no han cambiado:

txt
/lingo translate

Para crear los archivos de destino que faltan, indica patrones glob de archivos:

txt
/lingo translate docs/en/**/*.md
txt
/lingo translate docs/en/**/*.mdx --locales fr,es
txt
/lingo translate docs/en/**/*.md --force

Referencia de comandos:

ComandoDescripción
/lingoMuestra la ayuda.
/lingo helpMuestra la ayuda.
/lingo translateTraduce los cambios en el origen de esta PR sin modificar las traducciones que no han cambiado.
/lingo translate --locales fr,esTraduce los cambios en el origen de esta PR a los idiomas de destino configurados que hayas seleccionado.
/lingo translate <glob>...Traduce los archivos de destino que faltan para los archivos fuente coincidentes.
/lingo translate <glob>... --locales fr,esLimita la ejecución a los idiomas de destino configurados. El analizador de comandos convierte los valores de idioma a minúsculas.
/lingo translate <glob>... --forceTraduce todos los archivos fuente e idiomas coincidentes dentro del alcance, sobrescribiendo los destinos existentes.
/lingo translate [<glob>...] --key <pattern>Vuelve a traducir las claves con nombre que coincidan con los patrones en las traducciones existentes, sin modificar las demás traducciones. Repite --key para usar varios patrones.
/lingo translate [<glob>...] --key <pattern> --context "text"Añade indicaciones para todas las claves e idiomas seleccionados, solo para esta ejecución. Requiere --key; indica --context una sola vez.
/lingo approveAprueba una propuesta de traducción pendiente en la PR.

El comando debe ir en su propia línea. Los globs se comparan con archivos que también coinciden con tus patrones de archivos fuente files configurados. Igual que los patrones de configuración, los globs del comando no pueden empezar por / ni contener ...

Si indicas patrones glob de archivos explícitos y omites --key, /lingo translate <glob>... se ejecuta en modo de creación de archivos que faltan: solo crea los archivos de destino que faltan en la rama de la PR. Añade --force si quieres regenerar esos archivos de destino que ya existen.

Volver a traducir las claves seleccionadas#

Usa --key para actualizar las claves con nombre seleccionadas sin sustituir las demás traducciones, incluidas las modificaciones aceptadas en otras claves:

txt
/lingo translate locales/en.json --key "auth.login" --locales fr,es

Los patrones de claves admiten coincidencias exactas, prefijos y patrones glob:

PatrónSelección
auth.loginCoincide con la clave con nombre auth.login y con todas las claves descendientes de ese prefijo.
authCoincide con auth y con claves descendientes como auth.login y auth.logout.
auth.*Coincide mediante un patrón glob con claves como auth.login y auth.logout.

Repite --key para seleccionar varios patrones. Pon entre comillas los patrones de claves que contengan espacios. Los patrones glob de archivos y --locales acotan la solicitud; si omites los patrones glob de archivos, se seleccionan todos los archivos de origen configurados:

txt
/lingo translate --key "auth.*" --key "checkout.submit" --locales fr

La traducción de claves específicas requiere un formato con claves con nombre y una traducción existente para cada idioma de destino seleccionado. Se omiten los formatos sin claves con nombre y los idiomas que aún no tienen traducciones. Para crear primero los archivos de destino que faltan, ejecuta /lingo translate <glob>... sin --key. Añadir --force a un comando de traducción de claves específicas no amplía la selección de claves ni sustituye las demás traducciones.

Dar un contexto propio a una ejecución#

Añade --context para explicar el significado de una clave seleccionada o dar indicaciones sobre el tono y el uso de mayúsculas y minúsculas:

txt
/lingo translate --key "keyname" --context "button label, keep sentence case"

--context requiere --key. Indica el contexto una sola vez; se aplica a todas las claves e idiomas seleccionados en esa ejecución. Se conserva junto con la ejecución para los reintentos y el historial, pero no modifica las reglas ni las instrucciones guardadas del motor, ni se hereda en ejecuciones posteriores. Las reglas existentes sobre el glosario, los marcadores de posición y el formato de salida siguen aplicándose.

Escribe el comando en una sola línea. Usa comillas simples o dobles para delimitar el contexto que contenga espacios; --context="button label" también funciona. Para incluir en el texto la comilla usada como delimitador, antepón una barra invertida:

txt
/lingo translate --key "checkout.submit" --context "Use \"Save\" as a button label"

Dentro del contexto entre comillas, solo se decodifican \\ y una barra invertida situada antes de la comilla usada como delimitador. Los marcadores de posición como $name y ${name}, las secuencias como \n y los signos de puntuación se conservan tal cual.

Formatos compatibles#

La App de GitHub detecta estos formatos a partir de la extensión del archivo:

  • JSON (.json)
  • JSONC (.jsonc)
  • Markdown (.md)
  • MDX (.mdx)
  • Markdoc
  • Catálogo de cadenas de Xcode (.xcstrings)

Los documentos OpenAPI escritos en YAML también son compatibles, pero no se detectan automáticamente. Configura "format": "yaml-openapi" en el patrón de archivo:

json
{
  "files": [
    { "pattern": "openapi/en.yaml", "format": "yaml-openapi" }
  ]
}

Catálogos de cadenas de Xcode#

Un catálogo de cadenas de Xcode reúne todos los idiomas en un único archivo .xcstrings, por lo que la aplicación lo traduce directamente ahí en lugar de crear un archivo por idioma. La ruta de destino coincide con la de origen: cada idioma de destino se escribe en el mismo archivo, junto al idioma de origen y cualquier idioma ya traducido. Haz que el patrón de origen apunte directamente al catálogo y configura sourceLocale con su idioma de desarrollo:

json
{
  "sourceLocale": "en",
  "targetLocales": ["es-MX", "fr-CA", "pt-BR"],
  "files": [{ "pattern": "**/*.xcstrings" }]
}

Actualizaciones grandes#

La app puede dividir la salida de traducción en varios commits. Esto ocurre cuando una ejecución escribiría más de 100 archivos en un solo commit o más de 5 MB de contenido de archivos traducidos en un solo commit.

Cuando ocurre, los mensajes de commit incluyen el número de lote, por ejemplo:

txt
feat: Lingo.dev translations (1/3)
feat: Lingo.dev translations (2/3)
feat: Lingo.dev translations (3/3)

Qué ocurre cuando no hay coincidencias#

Si falta .lingo/config.json, la app omite el repositorio sin avisar. Una vez que existe la configuración, una configuración no válida genera una comprobación fallida y, en las PR, un comentario con el error de validación.

Si ninguno de los archivos modificados coincide con tus patrones de origen, la app finaliza sin escribir traducciones. En el caso de /lingo translate, el bot responde con una breve explicación, por ejemplo: no hay archivos coincidentes, no hay idiomas coincidentes o todos los archivos de destino ya existen.

El envío de cambios que añade .lingo/config.json solo traduce los archivos de origen que coinciden con los patrones y se han modificado en ese envío. Los archivos de origen existentes que no hayan cambiado necesitan un proceso aparte para completar las traducciones pendientes. Para crear los archivos de destino que faltan, abre una solicitud de incorporación de cambios desde una rama del mismo repositorio, no desde una bifurcación. Añade un comentario con /lingo translate <glob> en la solicitud de incorporación de cambios.

Siguientes pasos#