Lingo.dev GitLab Integration

Lingo.dev GitLab CI/CD Integration is a secure, open-source CI/CD integration that automatically localizes new content and prevents incomplete translations from reaching production. It creates merge requests or commits directly to your branch, depending on your team's workflow requirements.

It also implements automatic conflict resolution through rebasing, so your translations stay synchronized with your code without manual intervention.

The integration supports multiple workflow scenarios:

  1. Direct commits to branches when content changes are pushed
  2. Merge requests targeting branches for translation updates

Upon completion this guide, you will:

  1. Set up automated localization triggered by code pushes;
  2. Configure secure authentication using repository variables;
  3. Choose between direct commits or merge request workflows;
  4. Understand how continuous localization fits into your existing process.

Let's begin!

Prerequisites

Repository Setup

Your repository must have Lingo.dev CLI configured with a valid i18n.json file. If you haven't set this up yet, complete the CLI quickstart first.

Step 1. Authentication Setup

Lingo.dev GitLab Integration needs access to your translation engine and repository. Authentication happens through repository variables that keep your credentials secure.

Add Your API Key

Navigate to your repository SettingsCI/CDVariables, then add your translation engine credentials:

For raw LLM API users:

  • Variable name: OPENAI_API_KEY or ANTHROPIC_API_KEY
  • Variable value: Your API key from the respective provider

For Lingo.dev Engine users:

  • Variable name: LINGODOTDEV_API_KEY
  • Variable value: Your project API key from lingo.dev/app

Add GitLab Access Token

Create a custom access token for repository operations:

  1. Go to SettingsAccess tokensAdd new token
  2. Grant these scopes:
    • api
    • read_repository
    • write_repository
  3. Add the token as a repository variable:
    • Variable name: GL_TOKEN
    • Variable value: Your GitLab access token

Important: The default CI job token is not sufficient. You must create a custom access token as the default token lacks necessary permissions for git operations.

Note: For protected branches, make sure your variables are also marked as protected. Unprotected variables won't be accessible in protected branch pipelines.

Step 2. Create the Workflow

Create or update your .gitlab-ci.yml file with this basic configuration:

lingodotdev:
  image: lingodotdev/ci-action:latest
  script:
    - echo "Done"

This configuration uses the latest Docker image and runs the translation engine automatically.

Required Permissions

GitLab CI/CD requires access to repository variables and git operations:

Repository Variables:

  • LINGODOTDEV_API_KEY — Required for Lingo.dev Engine users
  • OPENAI_API_KEY or ANTHROPIC_API_KEY — Required for raw LLM API users
  • GL_TOKEN — Required for git push operations and merge request creation

Access Token Scopes:

  • api — Create and manage merge requests
  • read_repository — Access repository content
  • write_repository — Push commits and create branches

These permissions allow the integration to read your content, generate translations, and update your repository with the localized content.

Step 3. Choose Your Workflow Mode

Lingo.dev GitLab Integration supports two operational modes depending on your team's code review requirements.

Direct Commit Mode (Default)

The integration commits translations directly to your branch:

lingodotdev:
  image: lingodotdev/ci-action:latest
  script:
    - echo "Done"

This mode works best for:

  • Solo developers or small teams
  • Feature branches that will be reviewed before merging
  • Projects where translation updates don't require separate review

Merge Request Mode

The integration creates merge requests for translation updates:

lingodotdev:
  image: lingodotdev/ci-action:latest
  variables:
    LINGODOTDEV_PULL_REQUEST: "true"
  script:
    - echo "Done"

Required Setup for Merge Request Mode

Repository Variables: Both LINGODOTDEV_API_KEY and GL_TOKEN must be configured as repository variables.

Access Token Requirements: Your GL_TOKEN must include the api scope to create and manage merge requests.

This mode works best for:

  • Teams with strict code review requirements
  • Projects where translation changes need separate approval
  • Workflows that require explicit review of all changes

Step 4. Workflow Scenarios

Lingo.dev GitLab Integration adapts to different development workflows. Understanding these scenarios helps you choose the right configuration for your team.

Scenario 1: Feature Branch Updates (Direct Commits)

Trigger: Push to feature branches Action: Commits translation updates directly to the feature branch

lingodotdev:
  image: lingodotdev/ci-action:latest
  script:
    - echo "Done"
  rules:
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH = /^feat/

Flow: Content changes pushed to feature branch → Integration commits translations to the same branch

This keeps translation updates within the feature branch, ensuring translations are reviewed alongside the original changes.

Scenario 2: Merge Requests for Updates (Merge Request Mode)

Trigger: Push to any configured branch Action: Creates merge request with translation updates

lingodotdev:
  image: lingodotdev/ci-action:latest
  variables:
    LINGODOTDEV_API_KEY: $MY_LINGODOTDEV_API_KEY # or OPENAI_API_KEY/ANTHROPIC_API_KEY
    LINGODOTDEV_PULL_REQUEST: "true"
    LINGODOTDEV_PULL_REQUEST_TITLE: "feat: update translations"
  script:
    - echo "Done"

Flow: Content changes pushed to branch → Integration creates merge request with translations

This maintains separate reviews for translation updates.

Advanced Configuration

Customize the integration behavior using additional variables:

Example with Lingo.dev Engine:

lingodotdev:
  image: lingodotdev/ci-action:latest
  variables:
    LINGODOTDEV_API_KEY: $MY_LINGODOTDEV_API_KEY
    GL_TOKEN: $MY_GL_TOKEN
    LINGODOTDEV_PULL_REQUEST: "true"
    LINGODOTDEV_PULL_REQUEST_TITLE: "feat: update translations"
    LINGODOTDEV_COMMIT_MESSAGE: "feat: update translations via @lingodotdev"
    LINGODOTDEV_WORKING_DIRECTORY: "apps/web"
    LINGODOTDEV_PROCESS_OWN_COMMITS: "true"
  script:
    - echo "Done"
  rules:
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH = /^feat/

Example with raw LLM API:

lingodotdev:
  image: lingodotdev/ci-action:latest
  variables:
    OPENAI_API_KEY: $MY_OPENAI_API_KEY # or ANTHROPIC_API_KEY
    GL_TOKEN: $MY_GL_TOKEN
    LINGODOTDEV_PULL_REQUEST: "true"
    LINGODOTDEV_PULL_REQUEST_TITLE: "feat: update translations"
    LINGODOTDEV_COMMIT_MESSAGE: "feat: update translations via @lingodotdev"
    LINGODOTDEV_WORKING_DIRECTORY: "apps/web"
    LINGODOTDEV_PROCESS_OWN_COMMITS: "true"
  script:
    - echo "Done"
  rules:
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH = /^feat/

Configuration options:

  • LINGODOTDEV_API_KEY — Your Lingo.dev Engine API key, if you're using Lingo.dev Engine
  • OPENAI_API_KEY — Your OpenAI API key, if you're using raw LLM API
  • ANTHROPIC_API_KEY — Your Anthropic API key, if you're using raw LLM API
  • LINGODOTDEV_PULL_REQUEST — Create merge request instead of direct commit (default: false)
  • LINGODOTDEV_PULL_REQUEST_TITLE — Custom merge request title (default: feat: update translations via @lingodotdev)
  • LINGODOTDEV_COMMIT_MESSAGE — Custom commit message (default: feat: update translations via @lingodotdev)
  • LINGODOTDEV_WORKING_DIRECTORY — Run the integration in a subdirectory (default: .)
  • LINGODOTDEV_PROCESS_OWN_COMMITS — Process commits made by this integration (default: false)

Troubleshooting

Common errors and their solutions:

ErrorSolution
remote: HTTP Basic: Access deniedAdd the GL_TOKEN variable in your CI/CD settings
GitbeakerRequestError: ForbiddenYour GitLab token is missing the api scope