Introduction
Most engineering teams handle translations the same way they handled deployments ten years ago: manually. A developer commits English copy, someone exports the strings into a spreadsheet, emails it to a translation vendor, waits days for the files to come back, then manually merges the results into the repo. Builds break because a placeholder was dropped. Releases slip because a critical locale is incomplete. The entire workflow depends on manual file handling and tribal knowledge about which files go where.
There is a better pattern. Continuous localization treats translated content the same way CI/CD treats compiled artifacts: as an automated, testable output of the development process. Localization starts when new code is pushed to the repository. Source strings flow to a translation management system (TMS), translators work in the TMS environment while development continues, and finished translations sync back into the codebase automatically. The localization process becomes part of the software development cycle rather than a downstream dependency that blocks releases.
Before automating anything, it is worth answering a foundational question: what is software localization? At its core, it is the practice of adapting software – its language, regional formats, and user interface – so it feels native to users in each target market, and the pipeline described below is simply how engineering teams deliver that adaptation continuously. This article is written for backend and full-stack developers, DevOps engineers, mobile engineers, and engineering managers who want to integrate localization into their ci cd pipeline. By the end, readers will understand four things: what components make up a localization pipeline, how to implement continuous localization with working GitHub Actions workflows and Crowdin, how to avoid the most common pitfalls, and how to adapt the pattern to scale across multiple languages and CI systems.
What a Localization Pipeline Actually Is
A localization pipeline is a CI/CD-integrated workflow that manages the flow of software strings between the source code repository and localized versions in every target language. It automates extraction, translation, quality assurance, and build integration so that adapting software for global users does not require manual intervention at each step.
The pipeline has four core components:
● Source-of-truth strings in the repo. These are version-controlled resource files – en.json, Localizable.strings, Android XML, or .arb files – containing every user-facing string. Using string keys instead of hardcoded text is best practice in localization; externalizing user-facing text into resource files is crucial for any localization effort.
● A localization platform (TMS) where translators, translation memory, glossaries, and optionally machine translation work together. Translation Management Systems can integrate directly with version control systems to automate localization processes.
● Bidirectional sync. Source changes push to the TMS; completed translations pull back. Automation pulls updated string keys and pushes translations back without manual file handling.
● Validation and build steps. Automated QA checks can catch translation bugs before deployment. Linting scripts can help validate translation files during CI processes, and build smoke tests confirm that localized content does not break the application.
developer commit (source locale change)
↓
extract new/changed strings
↓
push source strings → TMS
↓
translators / TM / MT translate
↓
pull translations back to repo
↓
validate (syntax, placeholders, completeness)
↓
build & test
↓
release to production
This continuous workflow replaces waterfall localization, where translation happened after the development phase ended and routinely delayed releases into non-English markets.
The Building Blocks You Need
Before writing any workflow files, ensure these components are in place.
Source file format. JSON is the most common format for web applications and will serve as the primary example throughout this article. Maintaining structured resource files like JSON or YAML is essential for localization management. Other formats – XLIFF, .strings (iOS), .arb (Flutter), .po (gettext) – follow the same pipeline pattern. Whichever format is chosen, it must support plurals and ICU MessageFormat syntax for the target language.
A TMS with a CLI and API. This article uses Crowdin as the primary software localization tool. It provides a CLI (v4.14.0 as of early 2026), a GitHub Action (crowdin/github-action@v2), translation memory, glossary management, and support for machine translation post editing. Lokalise, Phrase, and Transifex are solid alternatives with similar API-driven workflows and comparable features for managing language pairs.
A CI runner. GitHub Actions is the primary example here. The runner needs to install the TMS CLI (via npm or Docker), check out code, run shell scripts, and push commits or create pull requests. Scheduled runs (cron) and event triggers (push, workflow_dispatch) are required.
A configuration file in the repo. A crowdin.yml file at the repository root tells the CLI which source files to upload and where translated files should land. Use environment variables for secrets – never store API tokens in plaintext. Using version-controlled resource files for storing localization keys is best practice.
Secrets management. API tokens and project IDs belong in GitHub Secrets (Settings → Secrets and variables → Actions). Limit token scopes to the minimum required: upload sources, download translations, and repository write access for pull requests.
Step-by-Step: Setting Up the Pipeline with GitHub Actions and Crowdin
Step 1: Add a TMS configuration file
Create crowdin.yml at the repository root. This file maps source strings to translation output paths. The preserve_hierarchy flag retains the folder structure from the source, and export_languages limits which locales are generated. Supporting 14 key languages reaches 90% of global spending power, so start with the highest-impact locales. Providing metadata helps translators understand the context of UI strings.
project_id_env: “TMS_PROJECT_ID”
api_token_env: “TMS_API_TOKEN”
base_path: “.”
preserve_hierarchy: true
export_languages:
– fr
– de
– es
– ja
files:
– source: “src/locales/en/**/*.json”
translation: “src/locales/%two_letters_code%/%original_file_name%”
Step 2: Store the API token as a GitHub Secret
Navigate to the repository in GitHub: Settings → Secrets and variables → Actions → New repository secret. Create TMS_API_TOKEN with the API token value and TMS_PROJECT_ID with the numeric project ID. These secrets are injected as environment variables at runtime and never appear in logs. Rotate tokens periodically and use the least-privilege scope available.
Step 3: Create the upload workflow
Create .github/workflows/l10n-upload.yml. This workflow triggers only when source locale files change on main, preventing noisy uploads on every commit. Localization platforms can sync translations with every code commit, but path filtering ensures uploads happen only when source strings actually change.
name: Upload Source Strings
on:
push:
branches:
– main
paths:
– “src/locales/en/**”
jobs:
upload:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– name: Upload source files
uses: crowdin/github-action@v2
with:
upload_sources: true
upload_translations: false
download_translations: false
env:
TMS_PROJECT_ID: ${{ secrets.TMS_PROJECT_ID }}
TMS_API_TOKEN: ${{ secrets.TMS_API_TOKEN }}
Integrate localization into your CI/CD pipeline via a CLI or API – this workflow does exactly that by calling the platform API through the official action.
Step 4: Create the download workflow
Create .github/workflows/l10n-download.yml. This workflow runs on a daily schedule and can also be triggered manually. It pulls approved translations, commits them to a dedicated branch, and opens a pull request. Automating pull requests for completed translations keeps the development cycle efficient. Continuous localization automates translation with every code update, and localized versions are updated and delivered in real time.
name: Download Translations
on:
workflow_dispatch:
schedule:
– cron: “0 3 * * *”
jobs:
download:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– name: Pull translations from the TMS
uses: crowdin/github-action@v2
with:
upload_sources: false
upload_translations: false
download_translations: true
skip_untranslated_strings: true
export_only_approved: true
localization_branch_name: “l10n/translations”
create_pull_request: true
pull_request_title: “chore: update translations from the TMS”
pull_request_body: “Automated translation sync”
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TMS_PROJECT_ID: ${{ secrets.TMS_PROJECT_ID }}
TMS_API_TOKEN: ${{ secrets.TMS_API_TOKEN }}
Automate content extraction using a dedicated l10n branch strategy – the localization_branch_name parameter isolates translation changes from feature work.
Step 5: Add validation
When the download PR opens, a validation job should run automatically. Software localization testing at this stage catches placeholder mismatches, malformed JSON, and missing ICU plural keys before they reach production. Automated localization flags inconsistencies before deployment.
name: Validate Translations
on:
pull_request:
branches:
– main
paths:
– “src/locales/**”
jobs:
validate:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– name: Install dependencies
run: npm install ajv-cli -g
– name: Validate JSON schema
run: |
for f in src/locales/*/messages.json; do
ajv validate -s src/locales/schema.json -d “$f”
done
– name: Check placeholder consistency
run: |
SOURCE=”src/locales/en/messages.json”
for f in src/locales/*/messages.json; do
if [ “$f” != “$SOURCE” ]; then
diff <(grep -oP ‘{[a-zA-Z_]+}’ “$SOURCE” | sort)
<(grep -oP ‘{[a-zA-Z_]+}’ “$f” | sort) ||
{ echo “Placeholder mismatch in $f”; exit 1; }
fi
done
– name: Build smoke test
run: npm ci && npm run build
Using pseudo-localization in early testing can flag potential issues with user interface layouts. Implementing fallback languages avoids crashes when localized strings are missing in any given locale.
Step 6: Block release builds on missing translations (optional)
For critical locales tied to a target market with revenue SLAs, add a build-time gate. This step queries the platform for translation progress and fails the pipeline if any critical locale falls below a threshold. Automated QA checks like this are among the best software localization practices for preventing incomplete releases.
90% of global spending
Companies can launch localized software faster with continuous localization, but only if the pipeline enforces completeness for the locales that matter most. Continuous localization allows simultaneous releases in all markets when thresholds are met.
Adapting the Pipeline to Other CI Systems
The localization workflow pattern is portable. Only the CI-specific YAML syntax and secrets mechanism change.
● GitLab CI. Install @crowdin/cli via npm in the job script. Store TMS_API_TOKEN and TMS_PROJECT_ID as masked CI/CD variables. Use GitLab CI schedules for the download job, and open a merge request via the GitLab API or glab CLI after pulling translations.
● CircleCI. Use a Docker executor with Node.js, install the CLI, and set environment variables via project settings or a context. Scheduled workflows handle the download cadence. Use the gh CLI to open pull requests back to GitHub if the source repo is hosted there.
● Bitbucket Pipelines. Run the CLI inside a Docker image. Store tokens in repository variables. Use the Bitbucket REST API to create pull requests for translated content.
In every case, the same existing tools – TMS CLI, path-filtered triggers, automated import of translations, validation scripts – drive the entire workflow. The localization software and ci cd system are decoupled by design.
Common Pitfalls and How to Avoid Them
Hard-coding API tokens in config files. If crowdin.yml contains a plaintext token and gets committed, the secret is exposed in the repository history. Use api_token_env to reference environment variables stored in your CI secrets manager.
Triggering uploads on every commit. Without path filters, every push to main fires the upload workflow – even when no source strings changed. This wastes CI minutes and API quota. Restrict triggers with paths: src/locales/en/** so uploads only run when the source locale is modified.
Auto-merging translation PRs without review. Poor translation quality or dropped placeholders can slip into production. Require at least one human reviewer for translation PRs, and use branch protection rules. Automated quality checks should gate the merge, but a human translator or localization manager should sign off on key locales.
Forgetting plurals and ICU MessageFormat consistency. If the source uses {count, plural, one {# item} other {# items}} and the translation drops a plural form, the user interface may crash or display raw syntax. Validation scripts must check that every plural key in the source exists in each target language file.
Letting translation memory drift. Over time, translation memory accumulates outdated entries from previously translated content that no longer matches the source. Without periodic cleanup and clear ownership – typically by a localization manager or designated project managers – TM leverage drops and translation costs rise. A documented B2B SaaS case study showed TM leverage rising from 35% to 62% after cleanup, cutting software localization cost per word by 31%.
Not pinning the TMS CLI or action version. Using @latest or @main for the GitHub Action risks breaking the pipeline when a new release introduces incompatible changes. Pin to a specific version (e.g., crowdin/github-action@v2) and upgrade deliberately after testing. Crowdin CLI v4.14.0, released in February 2026, introduced string context management and AI-based context enrichment – useful features, but worth validating in a staging pipeline before rolling out.
Conclusions and Next Steps
A localization pipeline is CI/CD applied to the translation process. The same principles – automated triggers, version-controlled configuration, validation gates, and reproducible builds – that make software development reliable also make software localization reliable. Automated localization reduces time-to-market for software releases. Localized software increases customer loyalty and reduces churn. 9 of the top 10 app markets by downloads were non-English in 2022, and localization enhances brand awareness and reduces advertising costs across every target market.
Continuous localization integrates localization into the software development cycle and represents a cultural shift: translation teams become collaborators in the development cycle, not a bottleneck after it. AI localization can achieve up to 95% ready-to-publish translations, and implementing a managed AI pipeline for high-quality translations alongside human review is increasingly common. Use automated crawlers to gather context from your software so translators produce better output from the start.
To get started:
- Externalize all user-facing strings into structured resource files if not done already.
- Set up a single upload workflow for one locale and one source directory.
- Add a download workflow on a daily cron schedule.
- Wire in validation – placeholder checks, JSON linting, build smoke tests.
- Expand to additional locales and implement coverage thresholds for critical markets.
From there, monitor metrics: translation turnaround time, localization testing pass rates, content volume per sprint, and sprint adherence. A well-tuned pipeline can support multiple languages at scale – reducing turnaround from days to hours and improving sprint adherence to near 100%, as real-world continuous localization workflows have demonstrated in agile development environments managing thousands of strings across 25+ languages every sprint.





