Lingo.dev GitHub Integration

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

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

The action supports multiple workflow scenarios:

  1. Direct commits to main branch when content changes are merged
  2. Direct commits to pull request branches when PRs are opened or updated
  3. Pull requests targeting main branch for translation updates
  4. Pull requests targeting existing pull request 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 secrets;
  3. Choose between direct commits or pull 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 GitHub Actions needs access to your translation engine and repository. Authentication happens through repository secrets that keep your credentials secure.

Add Your API Key

Navigate to your repository Settings → Secrets and variables → Actions, then add your translation engine credentials:

For raw LLM API users:

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

For Lingo.dev Engine users:

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

Step 2. Create the Workflow

Create .github/workflows/i18n.yml in your repository with this basic configuration:

name: Lingo.dev i18n

on:
  workflow_dispatch:
  push:
    branches:
      - main
      - feat/*

permissions:
  contents: write
  pull-requests: write

jobs:
  i18n:
    name: Run i18n
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: lingodotdev/lingo.dev@main
        with:
          api-key: ${{ secrets.LINGODOTDEV_API_KEY }}

Alternatively, you can add Lingo.dev GitHub Action as a step to your existing workflow:

- name: Lingo.dev
  uses: lingodotdev/lingo.dev@main
  with:
    api-key: ${{ secrets.LINGODOTDEV_API_KEY }}

Required Permissions

Your workflow needs specific permissions to function properly. GitHub Actions requires explicit permission declarations in the workflow file:

permissions:
  contents: write # Required: Create commits with translation updates
  pull-requests: write # Optional: Only needed if using pull request mode

The contents: write permission allows the action to:

  • Create commits with translation updates
  • Push changes directly to your repository
  • Access and modify files in your repository

These permissions are granted to the workflow's ephemeral GitHub token (${{ github.token }}), which is automatically created by GitHub for each workflow run and has the exact permissions you specify in the workflow file.

This configuration:

  • Triggers on pushes to main and feature branches
  • Grants necessary permissions for commits and pull requests
  • Uses the latest action version for automatic updates
  • Securely accesses your API key via repository secrets

Bonus:

  • At Lingo.dev, we like adding a workflow_dispatch trigger to every workflow, so we can manually (re-)run it from the GitHub Actions UI. This is completely optional, but we found it very helpful.

Step 3. Choose Your Workflow Mode

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

Direct Commit Mode (Default)

The action commits translations directly to your branch:

- uses: lingodotdev/lingo.dev@main
  with:
    api-key: ${{ secrets.LINGODOTDEV_API_KEY }}

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

Pull Request Mode

The action creates pull requests for translation updates:

- uses: lingodotdev/lingo.dev@main
  env:
    GH_TOKEN: ${{ github.token }}
  with:
    api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
    pull-request: true
    pull-request-title: "feat: update translations"

Required Permissions for Pull Request Mode

Pull request mode requires additional permissions and repository settings:

permissions:
  contents: write # Required: Access repository content and create commits
  pull-requests: write # Required: Create and update pull requests

GitHub Token Setup: The GH_TOKEN environment variable must be set to ${{ github.token }}, which is a system-generated ephemeral token that GitHub automatically creates for each workflow run. This token has exactly the permissions specified in your workflow file's permissions section.

Repository Settings: You must enable GitHub Actions to create pull requests in your repository settings:

  1. Go to SettingsActionsGeneral
  2. Scroll to the bottom of the page
  3. Under "Workflow permissions", ensure "Allow GitHub Actions to create and approve pull requests" is enabled

If you don't see this option in your repository settings, check your organization settings:

  1. Go to your organization's SettingsActionsGeneral
  2. Look for the same "Allow GitHub Actions to create and approve pull requests" setting

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 GitHub Action adapts to different development workflows automatically. Understanding these scenarios helps you choose the right configuration for your team.

Scenario 1: Main Branch Updates (Direct Commits)

Trigger: Push to main branch (e.g., when merging pull requests) Action: Commits translation updates directly to the main branch

on:
  push:
    branches: [main]

# Action commits directly to main branch
- uses: lingodotdev/lingo.dev@main
  with:
    api-key: ${{ secrets.LINGODOTDEV_API_KEY }}

Flow: Content changes pushed to main → Action commits translations to main

This scenario ensures your main branch always has up-to-date translations immediately after content changes are merged.

Tip: This is the mode we recommend you aim for. It requires a well-configured AI localization engine to ensure perfect localization. The upside is that it leads to zero manual intervention, as missing translations are automatically checked and filled before every production deployment.

Scenario 2: Pull Request Updates (Direct Commits)

Trigger: Pull request opened or updated with content changes Action: Commits translation updates directly to the pull request branch

on:
  pull_request:
    types: [opened, synchronize]

# Action commits directly to the PR branch
- uses: lingodotdev/lingo.dev@main
  with:
    api-key: ${{ secrets.LINGODOTDEV_API_KEY }}

Flow: Content changes in PR branch → Action commits translations to the same PR branch

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

Scenario 3: Pull Requests to Main (Pull Request Mode)

Trigger: Push to main branch (e.g., when merging pull requests) Action: Creates a pull request with translation updates

on:
  push:
    branches: [main]

# Action creates PR: main/lingo.dev → main
- uses: lingodotdev/lingo.dev@main
  env:
    GH_TOKEN: ${{ github.token }}
  with:
    api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
    pull-request: true

Flow: Content changes pushed to main → Action creates main/lingo.dev branch → Opens PR from main/lingo.devmain

Scenario 4: Pull Requests to Feature Branches (Pull Request Mode)

Trigger: Pull request opened or updated with content changes Action: Creates a pull request with translation updates targeting the feature branch

on:
  pull_request:
    types: [opened, synchronize]

# Action creates PR: feat/new-feature/lingo.dev → feat/new-feature
- uses: lingodotdev/lingo.dev@main
  env:
    GH_TOKEN: ${{ github.token }}
  with:
    api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
    pull-request: true

Flow: Content changes in feat/new-feature → Action creates feat/new-feature/lingo.dev branch → Opens PR from feat/new-feature/lingo.devfeat/new-feature

This maintains separate translation reviews for each feature branch.

Branch Naming Convention

When using pull request mode, Lingo.dev GitHub Action follows a consistent naming pattern:

Format: <base-branch>/lingo.dev

Examples:

  • Main branch updates: main/lingo.devmain
  • Feature branch updates: feat/user-auth/lingo.devfeat/user-auth
  • Release branch updates: release/v2.0/lingo.devrelease/v2.0

This naming convention ensures translation branches are clearly identifiable and automatically linked to their source branches.

Handle External Contributions

When working with external forks, implement selective checkout to maintain repository security:

jobs:
  i18n:
    name: Run i18n
    runs-on: ubuntu-latest
    permissions:
      actions: write
      contents: write
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - run: find locales/** -name "*.json" | xargs git checkout ${{ github.event.pull_request.head.sha }} --
        shell: bash
      - uses: lingodotdev/lingo.dev@main
        with:
          api-key: ${{ secrets.LINGODOTDEV_API_KEY }}

Required Permissions for External Contributions

Handling external forks requires elevated permissions to securely process contributions:

permissions:
  actions: write # Required: Access workflow information and artifacts
  contents: write # Required: Create commits and access repository content
  pull-requests: write # Required: Update pull requests from external forks

The actions: write permission is specifically needed to:

  • Access pull request metadata from external forks
  • Read workflow context for security validation
  • Handle artifacts and workflow state securely

These elevated permissions ensure the action can safely process translations from external contributors while maintaining repository security through selective file checkout.

This approach:

  • Checks out only translation files from the fork
  • Prevents exposure of sensitive repository code
  • Maintains necessary write permissions for the action

Advanced Configuration

Customize the action behavior using additional parameters:

- uses: lingodotdev/lingo.dev@main
  env:
    GH_TOKEN: ${{ github.token }}
  with:
    api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
    pull-request: true
    commit-message: "feat: update translations via lingo.dev"
    working-directory: "apps/web"
    version: "latest"
    process-own-commits: false
    parallel: true

Configuration options:

  • commit-message — Custom message for translation commits
  • working-directory — Run the action in a subdirectory
  • version — Pin to a specific CLI version (not recommended)
  • process-own-commits — Process commits made by this action
  • parallel — Enable parallel processing of localization tasks (default: false)

Parallel Processing

The GitHub Action supports parallel processing of localization tasks to significantly accelerate translation workflows for large projects. Enable this feature by setting parallel: true:

- uses: lingodotdev/lingo.dev@main
  with:
    api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
    parallel: true

When enabled, the action:

  • Distributes localization tasks across multiple concurrent workers
  • Uses intelligent task distribution algorithms to maximize throughput
  • Prevents file corruption and race conditions through careful concurrency management
  • Dramatically reduces processing time for projects with many translation files

This feature is particularly beneficial for:

  • Large projects with extensive translation requirements
  • Workflows processing multiple locales simultaneously
  • Teams requiring faster CI/CD pipeline execution

Note: Parallel processing may increase API usage. Monitor your usage if you have strict rate limits.

Verification Mode

Using the --frozen flag, you can verify that all translations are current before every production deployment.

Here's an example of how to use the --frozen flag in your deployment pipeline:

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npx lingo.dev@latest i18n --frozen
      - run: npm run build
      - run: npm run deploy

The --frozen flag:

  • Verifies all translations are current
  • Makes no changes to files
  • Fails the build if translations are missing or outdated