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:
- Direct commits to main branch when content changes are merged
- Direct commits to pull request branches when PRs are opened or updated
- Pull requests targeting main branch for translation updates
- Pull requests targeting existing pull request branches for translation updates
Upon completion this guide, you will:
- Set up automated localization triggered by code pushes;
- Configure secure authentication using repository secrets;
- Choose between direct commits or pull request workflows;
- 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
orANTHROPIC_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:
- Go to Settings → Actions → General
- Scroll to the bottom of the page
- 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:
- Go to your organization's Settings → Actions → General
- 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.dev
→ main
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.dev
→ feat/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.dev
→main
- Feature branch updates:
feat/user-auth/lingo.dev
→feat/user-auth
- Release branch updates:
release/v2.0/lingo.dev
→release/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 commitsworking-directory
— Run the action in a subdirectoryversion
— Pin to a specific CLI version (not recommended)process-own-commits
— Process commits made by this actionparallel
— 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