App GitHub

Moses SkodaEngenheiro12 min de leitura

A App GitHub da Lingo.dev configura a localização contínua de um repositório com .lingo/config.json.

Pré-requisitos#

Antes de instalar a app, confirme que tem:

  • Uma organização Lingo.dev com a funcionalidade de integração com o GitHub ativada
  • Um motor de localização nessa organização
  • Acesso de administrador à organização ou ao repositório GitHub que quer ligar

Se não for administrador da organização GitHub, o GitHub permite-lhe pedir a instalação. Um administrador da organização GitHub tem de aprovar esse pedido antes de a Lingo.dev poder aceder aos repositórios selecionados.

Instale a aplicação do GitHub#

  1. Na Lingo.dev, abra a sua organização.
  2. Aceda a Studio > All integrations.
  3. No cartão do GitHub, clique em Install on GitHub.
  4. No GitHub, escolha a conta ou organização onde quer instalar a app.
  5. Escolha Todos os repositórios ou Apenas repositórios selecionados.
  6. Clique em Instalar.

O GitHub redireciona-o para a Lingo.dev, para o ecrã Connect GitHub:

  1. Escolha a organização da Lingo.dev através da qual esta conta de GitHub faz a localização. A organização que abriu mais recentemente fica selecionada automaticamente.
  2. Clique em Ligar.
  3. Quando vir GitHub connected, clique em View integration para abrir a ligação.

A ligação aparece na barra lateral do Studio, em Connected. No separador Definições, pode ver a Conta, o Tipo de conta, a Instalação, os Repositórios e se a Ligação está a funcionar. O separador Execuções de workflow lista todas as execuções da aplicação, com o repositório e a indicação de se foram iniciadas por um push ou por um pull request.

Para adicionar ou remover repositórios mais tarde, abra o separador Definições da ligação e use Manage on GitHub: o acesso aos repositórios é sempre definido no GitHub, na própria instalação.

Se pediu a instalação em vez de a instalar, a Lingo.dev mostra Installation requested: um administrador da organização no GitHub tem de a aprovar. Depois de o fazer, o GitHub reencaminha-o para o ecrã Connect GitHub para concluir o processo. O administrador pode analisar o pedido no GitHub, na área Definições > GitHub Apps da organização. O GitHub também mostra os pedidos de aplicações pendentes aos proprietários da organização nas definições da organização.

Adicionar a configuração do repositório#

Crie .lingo/config.json no repositório onde instalou a 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
    }
  }
}
CampoObrigatórioDescrição
engineIdSimO motor da Lingo.dev que deve traduzir este repositório.
sourceLocaleSimO idioma de origem usado nos caminhos dos ficheiros de origem, como en ou en-US.
targetLocalesSimCódigos de idioma para os quais quer traduzir. São suportados até 50 idiomas distintos.
filesSimPadrões de ficheiros de origem relativos ao repositório. São suportados até 100 padrões.
github.workflows.onPushToDefaultBranch.enabledNãoÉ executado quando os ficheiros de origem mudam na branch predefinida. Ativado por predefinição.
github.workflows.onPullRequest.enabledNãoÉ executado quando os ficheiros de origem mudam em pull requests. Desativado por predefinição.
github.safety.requireApprovalNãoExige aprovação antes de os workflows automáticos de push ou PR traduzirem. Desativado por predefinição.

Utilize a CLI para configurar o repositório. Execute estes comandos pela seguinte ordem:

  1. Execute npx @lingo.dev/cli init para guardar o idioma de origem, os idiomas de destino e os padrões de ficheiros em .lingo/config.json.
  2. Execute npx @lingo.dev/cli login para iniciar sessão e guardar as suas credenciais localmente em ~/.lingo/credentials.json.
  3. Execute npx @lingo.dev/cli link para escolher uma organização e um motor. Este comando adiciona orgId e engineId a .lingo/config.json.

O comando init não cria a secção github. Se precisar desta secção, copie-a do exemplo acima. Consulte o guia de início rápido da CLI.

Padrões de ficheiros#

Os padrões files apontam para ficheiros de origem (idioma predefinido). A app verifica os ficheiros alterados com base nestes padrões e processa apenas os ficheiros de origem suportados que correspondam.

Os padrões são relativos ao repositório, sensíveis a maiúsculas e minúsculas, e podem usar:

  • * para corresponder dentro de um segmento de caminho
  • **/ para corresponder a qualquer profundidade de diretórios

Os padrões não podem começar por / nem conter ...

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

Opções de ficheiro#

Cada entrada em files pode incluir opções além do respetivo pattern. Todas são opcionais e cada uma aplica-se apenas a determinados formatos.

OpçãoAplica-se aDescrição
formatTodosSubstitui o formato inferido a partir da extensão do ficheiro. Obrigatório para OpenAPI em YAML ("yaml-openapi").
include / excludeTodosListas glob para refinar os ficheiros aos quais a entrada corresponde, usadas com ou em vez de pattern.
translateFrontmatterFieldsMarkdown, MDX, MarkdocChaves de frontmatter a traduzir. Por predefinição, usa title e description.
translateComponentPropsMDX, MarkdocProps de componentes MDX e atributos de tags Markdoc a traduzir.
lockedKeysJSON, JSONCCaminhos de chave mantidos com o valor de origem, nunca traduzidos.
preservedKeysJSON, JSONCCaminhos de chave mantidos com o valor de destino existente, sem serem traduzidos novamente.
injectLocaleJSON, JSONCEscreve o código do idioma de destino na saída, na chave indicada (por predefinição, language).

As entradas translateComponentProps são ou um nome de prop, que se aplica a essa prop em qualquer componente ou tag, ou um objeto que limita as props a componentes ou tags com nome:

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" }
    }
  ]
}

Onde os ficheiros localizados são gravados#

A app deriva cada caminho de destino a partir do caminho de origem e dos códigos de idioma na sua configuração:

Caminho de origemIdioma de destinoCaminho de saída
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 (no mesmo ficheiro)

Use o nome completo do diretório ou do ficheiro como código de idioma. Por exemplo, se os ficheiros de origem estiverem em docs/en-US/, defina "sourceLocale": "en-US" e não "en". Se as strings de origem estiverem em messages/en.json, defina "sourceLocale": "en".

Quando o caminho de origem contém um diretório de idioma, a app substitui esse diretório. Quando o caminho de origem é um ficheiro com nome de idioma, a app substitui o nome do ficheiro. Se nenhum destes padrões existir, a app coloca o ficheiro traduzido num novo diretório do idioma de destino ao lado do ficheiro de origem.

Os Catálogos de Strings são a exceção. Como um único ficheiro .xcstrings contém todos os idiomas, o caminho de destino é igual ao caminho de origem — a aplicação escreve cada idioma nesse mesmo ficheiro e nunca acrescenta uma pasta de idioma nem um nome de ficheiro.

Workflows#

Push para a branch predefinida#

Quando um ficheiro de origem correspondente é adicionado ou alterado na branch predefinida, a app traduz esse ficheiro e faz commit dos ficheiros localizados para:

txt
lingo/translations/<default-branch>

Depois, abre ou atualiza um pull request dessa branch de traduções para a branch predefinida. Se a branch de traduções já existir, os novos commits são acrescentados a essa branch.

Se um ficheiro de destino for adicionado ou alterado no mesmo push, a app trata esse ficheiro como já processado e inclui-o no PR de tradução em vez de o substituir.

Pull requests#

Quando github.workflows.onPullRequest.enabled é true, a app verifica as alterações do pull request à procura de ficheiros de origem correspondentes. Faz commit dos ficheiros traduzidos diretamente na branch do PR.

A app não escreve em branches de PRs com fork e não escreve na branch predefinida a partir de um comentário de PR. Os pull requests têm de estar abertos para a app fazer commit das traduções.

Nos PRs, a Lingo.dev atualiza um comentário do PR com os ficheiros traduzidos e quaisquer falhas.

Atualizações incrementais e recuperação#

Para ficheiros de destino existentes, a app traduz apenas as alterações de origem que consegue detetar, em vez de regenerar o ficheiro completo. Para novos ficheiros de destino, cria o ficheiro localizado para cada idioma de destino configurado.

Se uma localização anterior de PR não tiver incluído uma alteração de origem ou tiver falhado antes de atualizar o ficheiro de destino, a sincronização seguinte do PR pode recuperar comparando a origem do PR com a origem da branch base e traduzindo a alteração em falta.

Se um ficheiro de origem já não existir no commit que está a ser processado, a app ignora-o.

Modo de aprovação#

Defina github.safety.requireApproval como true quando quiser uma etapa de aprovação humana antes de as traduções automáticas serem executadas.

Nos pushes para a branch predefinida, o check run da Lingo.dev mostra as ações Approve e Deny. Em pull requests, a app publica um comentário com uma proposta de tradução; responda com:

txt
/lingo approve

Os comandos /lingo translate com âmbito definido não exigem esta etapa de aprovação.

Comando manual de PR#

Utilize /lingo num comentário de um pedido de integração para traduzir alterações ao conteúdo de origem, criar ficheiros de destino em falta ou voltar a traduzir chaves selecionadas.

Traduza as alterações ao conteúdo de origem no pedido de integração, mantendo as traduções que não foram alteradas:

txt
/lingo translate

Para criar ficheiros de destino em falta, indique padrões glob de ficheiros:

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

Referência de comandos:

ComandoDescrição
/lingoMostra ajuda.
/lingo helpMostra ajuda.
/lingo translateTraduz as alterações ao conteúdo de origem neste PR, mantendo as traduções que não foram alteradas.
/lingo translate --locales fr,esTraduz as alterações ao conteúdo de origem deste PR para os idiomas de destino selecionados entre os configurados.
/lingo translate <glob>...Traduz os ficheiros de destino em falta para os ficheiros de origem correspondentes.
/lingo translate <glob>... --locales fr,esLimita a execução aos idiomas de destino configurados. Os valores de idioma são convertidos para minúsculas pelo parser de comandos.
/lingo translate <glob>... --forceTraduz todos os ficheiros de origem e idiomas correspondentes no âmbito, substituindo os destinos existentes.
/lingo translate [<glob>...] --key <pattern>Volta a traduzir as chaves identificadas por nome que correspondem aos padrões nas traduções existentes, mantendo as restantes traduções. Repita --key para indicar vários padrões.
/lingo translate [<glob>...] --key <pattern> --context "text"Adiciona orientações para todas as chaves e idiomas selecionados, válidas apenas nesta execução. Requer --key; indique --context uma única vez.
/lingo approveAprova uma proposta de tradução pendente no PR.

O comando tem de estar numa linha própria. Os globs são comparados com ficheiros que também correspondam aos padrões de origem files configurados. Tal como os padrões da configuração, os globs do comando não podem começar por / nem conter ...

Quando indica padrões glob de ficheiros explícitos e omite --key, /lingo translate <glob>... funciona em modo de preenchimento de ficheiros em falta: cria apenas os ficheiros de destino que não existem no ramo do PR. Adicione --force se quiser voltar a gerar esses ficheiros de destino quando já existem.

Voltar a traduzir chaves selecionadas#

Utilize --key para atualizar chaves selecionadas pelo nome sem substituir as restantes traduções, incluindo alterações aceites noutras chaves:

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

Os padrões de chaves permitem correspondências exatas, prefixos e padrões glob:

PadrãoSeleção
auth.loginSeleciona a chave com o nome auth.login e todas as chaves descendentes desse prefixo.
authSeleciona auth e chaves descendentes, como auth.login e auth.logout.
auth.*Seleciona chaves que correspondem a um padrão glob, como auth.login e auth.logout.

Repita --key para selecionar vários padrões. Coloque entre aspas os padrões de chaves que contenham espaços. Os padrões glob de ficheiros e --locales limitam o âmbito do pedido; se omitir os padrões glob de ficheiros, são selecionados todos os ficheiros de origem configurados:

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

A tradução limitada a chaves específicas requer um formato com chaves identificadas por nome e uma tradução existente para cada idioma de destino selecionado. Os formatos sem chaves identificadas por nome e os idiomas sem traduções existentes são ignorados. Para criar primeiro os ficheiros de destino em falta, execute /lingo translate <glob>... sem --key. Adicionar --force a um comando limitado a chaves específicas não alarga o conjunto de chaves abrangidas nem substitui as restantes traduções.

Dar contexto próprio a uma execução#

Adicione --context para explicar o significado de uma chave selecionada ou dar orientações sobre o tom e o uso de maiúsculas e minúsculas:

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

--context requer --key. Indique o contexto uma única vez; aplica-se a todas as chaves e idiomas selecionados nessa execução. O contexto fica guardado com a execução para novas tentativas e para o histórico, mas não altera as regras nem as instruções guardadas do motor e não é herdado por execuções posteriores. As regras existentes relativas ao glossário, aos marcadores de posição e ao formato de saída continuam a aplicar-se.

Mantenha o comando numa só linha. Coloque o contexto entre aspas simples ou duplas se contiver espaços; --context="button label" também funciona. Para incluir no texto as aspas usadas como delimitadores, coloque uma barra invertida antes delas:

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

No contexto entre aspas, apenas \\ e a barra invertida antes das aspas delimitadoras são descodificados. Os marcadores de posição, como $name e ${name}, as sequências, como \n, e a pontuação mantêm o seu valor literal.

Formatos suportados#

A App GitHub deteta estes formatos a partir da extensão do ficheiro:

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

Os documentos OpenAPI escritos em YAML também são suportados, mas não são detetados automaticamente. Defina "format": "yaml-openapi" no padrão de ficheiro:

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

Catálogos de Strings do Xcode#

Um Catálogo de Strings do Xcode reúne todos os idiomas num único ficheiro .xcstrings, pelo que a aplicação o traduz no próprio ficheiro em vez de criar um ficheiro por idioma. O caminho de destino é igual ao caminho de origem: cada idioma de destino é escrito no mesmo ficheiro, ao lado da língua de origem e de quaisquer idiomas já traduzidos. Aponte o padrão de origem diretamente para o catálogo e defina sourceLocale para a respetiva língua de desenvolvimento:

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

Atualizações de grande dimensão#

A app pode dividir a saída da tradução por vários commits. Isto acontece quando uma execução escreveria mais de 100 ficheiros num único commit ou mais de 5 MB de conteúdo de ficheiros traduzidos num único commit.

Quando isso acontece, as mensagens de commit incluem o número do lote, por exemplo:

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

O que acontece quando nada corresponde#

Se .lingo/config.json estiver em falta, a app ignora o repositório silenciosamente. Quando a configuração passa a existir, uma configuração inválida cria um check run com falha e, nos PRs, um comentário com o erro de validação.

Se nenhum ficheiro alterado corresponder aos seus padrões de origem, a app conclui sem escrever traduções. Para /lingo translate, o bot responde com uma explicação breve, como não haver ficheiros correspondentes, não haver idiomas correspondentes ou todos os ficheiros de destino já existirem.

O envio de alterações que adiciona .lingo/config.json traduz apenas os ficheiros de origem que correspondem aos padrões e que foram alterados nesse envio. Os ficheiros de origem existentes que não tenham sido alterados precisam de um processamento retroativo separado. Para criar os respetivos ficheiros de destino em falta, abra um pedido de integração a partir de um ramo do mesmo repositório, e não de uma cópia derivada. Adicione o comentário /lingo translate <glob> ao pedido de integração.

Próximos passos#