Engineering

Continuous Localization: How to Keep Translations in Sync with Your Codebase

Eray Gündoğmuş
Eray Gündoğmuş
·13 min read
Share
Continuous Localization: How to Keep Translations in Sync with Your Codebase

Continuous Localization: How to Keep Translations in Sync with Your Codebase


TL;DR / Key Takeaways

  • Continuous localization treats translation as an ongoing pipeline step, not a one-time task at release time — the same way CI/CD treats testing and deployment.
  • Batch translation workflows break down as release cadences accelerate: strings go stale, merge conflicts accumulate, and translators lose context.
  • A functioning continuous localization pipeline has six stages: code change, string extraction, translation trigger, review, merge, and deploy. Each stage can be automated to varying degrees.
  • Key integration patterns differ in how they trigger the sync: webhooks from your VCS, CLI-based push/pull commands in CI steps, file watchers for local development, and OTA/CDN delivery for deploy-free updates.
  • No single tool solves every part of this problem. The right setup depends on your release cadence, language count, translator workflow, and whether over-the-air updates matter for your product.

What Is Continuous Localization?

Continuous localization is the practice of integrating translation into your software development lifecycle as a continuous, automated process rather than a manual step that happens once per release cycle.

To understand why it matters, consider the contrast with the traditional approach — often called batch translation or waterfall translation. In a batch workflow, a developer completes a feature, a product manager collects all new strings into a spreadsheet or export, a localization manager submits them to translators (internal or external), translations come back days or weeks later, a developer imports them, and the release waits on the last locale to finish. This cycle worked reasonably well when software shipped quarterly. It breaks down when teams ship weekly or daily.

The analogy to CI/CD is direct. Before continuous integration, developers worked on long-lived branches, integration happened late, and the cost of merge conflicts scaled with time. CI pushed integration earlier and more frequently, reducing that cost dramatically. Continuous localization does the same for translations: instead of accumulating string changes over a sprint and reconciling them at release time, each code change triggers the translation pipeline immediately.

This framing is sometimes called shift-left localization — the same "shift left" concept applied to testing, where catching problems earlier is cheaper than catching them later. A string that enters the translation pipeline the day it is written is translated with full context, no backlog pressure, and no risk of blocking the release. A string that enters the pipeline the day before release is translated under pressure, often without context, often in a batch with 400 other strings, and often wrong the first time.

Continuous localization does not mean every string is translated and shipped in hours. Machine translation can fill that gap for speed, with human review following. What it means structurally is that the pipeline is always running: new strings flow in automatically, translator queues are updated incrementally, and translations flow back into the codebase or delivery layer without a human orchestrating every handoff.


Why Batch Translation Breaks Down

Batch translation is not inherently wrong — for projects shipping infrequently or managing a small number of strings, it is a reasonable approach. But for engineering teams on CI/CD pipelines, batch workflows create four specific failure modes.

Release delays. When translation is a prerequisite for shipping, and translation is a batch task triggered after feature freeze, the release timeline is constrained by translator throughput. Teams that ship continuously cannot accept a localization step that takes five business days. The release either ships without translated strings (defaulting to the source language, often English) or it waits — neither is acceptable at scale.

Translation staleness. In a batch model, strings are often exported from a codebase that has already moved on. By the time translations arrive, the strings themselves may have changed — a button label was reworded, a screen was redesigned, a feature was removed. Translators work from an outdated snapshot. The result is translations that do not match the live product, or translation work that has to be discarded and redone.

Merge conflicts in translation files. When multiple developers are working in parallel and translation files live in the repository (as JSON, YAML, XLIFF, or similar), concurrent changes to those files produce merge conflicts. Unlike conflicts in application logic, translation file conflicts are tedious and error-prone to resolve: two branches both added new keys, both deleted a key, both renamed a key to something different. The larger the batch, the worse the conflicts.

Developer-translator friction. In a batch workflow, the handoff between developer and translator is a manual, often asynchronous process that relies on conventions that break down under time pressure. Developers forget to export. Translators are handed files without context. Keys are renamed between export and import. Imports overwrite changes made by translators directly. None of these failures are catastrophic individually — but they compound. Over time, the friction causes teams to de-prioritize localization quality, and localization debt accumulates the same way technical debt does.


The Continuous Localization Pipeline

A continuous localization pipeline moves string changes through six stages. The pipeline is triggered by a code change, not by a human decision. Each stage produces a deterministic output that the next stage can consume without manual intervention.

Code change
    |
    v
String extraction
    |
    v
Translation trigger
    |
    v
Translation (MT + human review)
    |
    v
Merge back to repository (or push to CDN)
    |
    v
Deploy (or OTA update, if CDN-based)

Stage 1: Code change. A developer adds, modifies, or removes a translatable string in the codebase. With a good i18n setup, this means updating a key-value file (JSON, YAML, XLIFF) or adding a key reference in code that resolves at runtime.

Stage 2: String extraction. The pipeline identifies which strings are new, changed, or deleted by comparing the current state against the previous extraction snapshot. This is typically handled by the localization tool's CLI or a CI script. The output is a diff of string changes — not a full export of all strings, just the delta. Tools that compute full exports on every run instead of diffs create unnecessary translator work and make it harder to prioritize new strings.

Stage 3: Translation trigger. New and changed strings are sent to the translation management system (TMS). This can happen via a webhook (VCS event triggers an API call to the TMS), a CI step (a CLI command pushes the string diff after a successful build), or a file watcher (in development, a local agent watches for file changes and syncs continuously). The trigger should be automatic — requiring a human to initiate this step reintroduces the batch problem.

Stage 4: Translation. Translators (human or machine, or a combination) work on the new strings in the TMS. Well-designed systems provide screenshots, component context, character limits, and adjacent strings to help translators produce accurate translations without back-and-forth. Machine translation can produce first drafts automatically; human reviewers focus on accuracy, brand voice, and context-sensitive corrections.

Stage 5: Merge. Completed translations are pushed back to the repository as a pull request or committed directly to a translation branch, depending on your governance model. For OTA-capable platforms, this step pushes translated strings to a CDN or API endpoint — bypassing the repository entirely for the delivery path.

Stage 6: Deploy. For file-based delivery, translations are bundled in the next build and deployed with the application. For CDN-based delivery, translations are already live at the edge — the application picks them up on the next request without a new deploy.

The critical design principle is that stages 2 through 5 should be fully automated for machine-translated content, with human review as an optional layer that improves quality but does not block delivery. Human review should be asynchronous: publish the MT translation first, replace it with the reviewed translation when it is ready.


Integration Patterns

How you connect your codebase to your translation pipeline determines how much of the above can actually be automated. There are four primary integration patterns, each with different trade-offs.

PatternTriggerSetup effortLatencyRequires CI?OTA capable?
VCS webhookPush/PR event in GitHub or GitLabLow-MediumMinutesNoDepends on TMS
CI step (CLI)CI pipeline step (e.g., GitHub Actions, GitLab CI)MediumMinutes to hoursYesDepends on TMS
File watcherLocal file system changeLowSecondsNoNo
OTA / CDN deliveryTranslation publish eventMedium-HighSeconds (edge cache)OptionalYes

VCS webhook. Your repository hosting platform (GitHub, GitLab, Bitbucket) sends an HTTP event to the TMS when a commit or pull request is created. The TMS parses the payload, identifies which files changed, extracts new strings, and queues them for translation. This requires no changes to your CI pipeline and works even on branches before they merge to main. The limitation is that the TMS must understand your file format and project structure — configuration is done on the TMS side, not in your codebase.

CI step (CLI). Your CI pipeline includes a step that runs the TMS CLI to push new strings and optionally pull translated strings. This is the most flexible pattern because the script runs in your CI environment with full access to build context. The GitHub Actions marketplace and GitLab CI include official or community-maintained actions for most major TMS platforms. The trade-off is that you need to manage the CLI version, authentication credentials as secrets, and the ordering of push/pull steps relative to build steps.

File watcher. A local daemon watches your translation file directories and syncs changes to the TMS in real time as you write code. This is primarily a developer experience tool: translators see new strings within seconds of a developer adding them, rather than waiting for a CI run. It is not suitable as a production pipeline mechanism because it depends on a developer having the daemon running and requires consistent local setup across the team.

OTA / CDN delivery. Rather than committing translated strings to the repository and bundling them in a deploy, the application fetches translations at runtime from a CDN or API. Updates to translations are immediately available globally without a new build or deploy. This pattern requires the application to be designed for runtime translation loading — which is standard in most modern i18n libraries — and introduces a runtime dependency on the CDN. It is the most operationally agile pattern for UI strings.

Most production setups combine patterns: a CI step (or webhook) to keep the TMS in sync with the codebase, plus CDN delivery for string updates that do not require a new deploy.


Key Capabilities to Look For

Not all localization platforms support true continuous localization. When evaluating tools, these are the capabilities that determine whether a platform can actually be integrated into a CI/CD pipeline rather than used as a manual translation portal.

Auto-detection of new and changed strings. The platform should identify string changes automatically from a file diff or VCS event, without requiring a manual export. Platforms that require you to export a full file and re-import it on every change are not designed for continuous workflows.

Translator context. Translators working on individual strings in isolation produce lower-quality translations than translators who can see where a string appears in the UI. The best platforms accept screenshots, component metadata, or in-context editing that shows the string rendered in the actual product. Without context, short strings like "Save", "View", or "Cancel" are regularly mistranslated because their meaning is ambiguous out of context.

Branching support. If your team uses feature branches, your localization platform should support translation branches that mirror your VCS branches. Strings on a feature branch should be translatable before the branch merges to main — otherwise translations are always behind the code by at least one merge cycle.

Pseudo-localization for testing. Pseudo-localization replaces characters in source strings with visually similar extended-Latin characters to simulate translated text without actual translation. It catches layout bugs — text overflow, truncated labels, hardcoded width assumptions — early in development, before real translations are available. A platform that supports automatic pseudo-locale generation enables UI testing in any locale at any point in development.

Over-the-air (OTA) updates without redeploy. For applications where shipping a new build to update a translation is too slow or too costly — mobile apps, desktop applications, or high-frequency web apps — OTA delivery is essential. The platform should serve translations from a globally distributed edge cache with low latency and automatic cache invalidation when translations are published.

Translation memory and consistency enforcement. Translation memory reuses previously translated strings across projects and contexts, reducing translator effort and improving consistency. Consistency enforcement flags strings that match a previously translated term but have been translated differently — catching terminology drift across a large project.


Common Pitfalls

Continuous localization pipelines introduce specific failure modes that are distinct from manual workflow problems. These are the most common ones.

Over-automating without a QA layer. Fully automated machine translation pipelines can ship translations at high velocity. They can also ship incorrect translations at high velocity. Machine translation without any human review is appropriate for internal tooling and low-stakes UI strings. For customer-facing marketing copy, legal disclosures, error messages, or anything that reflects brand voice, a human review step is not optional. Design your pipeline so that MT translations are published as a fallback immediately, with human-reviewed translations replacing them asynchronously — do not block publication on human review, but do not treat MT as final for all content.

Ignoring context for translators. Automating the handoff of strings without automating the handoff of context creates a fast pipeline that produces low-quality translations. A string key like checkout.button.primary without a screenshot, a description, or a character limit tells a translator almost nothing. Build context delivery into your pipeline from the start — it is much harder to retrofit.

Breaking translation memory with key renames. Translation memory maps translations to source strings or to string keys, depending on the platform. When developers rename keys — for example, changing user.save_button to profile.save_changes — the TMS often treats this as a deleted key and a new, untranslated key. All previous translation work for that string is lost from the TM. Establish a key renaming policy: either treat key renames as a deprecated-and-create operation (keeping the old key until translations are confirmed), or use a TMS that tracks string identity through key changes using a content hash rather than key name alone.

Not handling deleted keys. When a string is removed from the source, most platforms leave its translations in the TMS indefinitely. Over time this creates orphaned translations that waste storage, confuse translators, and make reporting on translation completeness inaccurate. Implement a regular purge cycle — either via CI script or a TMS automation rule — that removes translations for keys that no longer exist in the source.

Treating all locales the same. Different locales have different translation velocities depending on translator availability, language pair complexity, and review requirements. A pipeline that blocks deployment on all locales completing translation will frequently be blocked by the slowest locale. Design your pipeline to deploy with the translated locales that are ready and fall back to the source language for locales that are not — with an alert when a locale falls below a completeness threshold you define.


Tools That Support Continuous Localization

These are the tools most commonly used in engineering-driven continuous localization pipelines. Each has honest strengths and real limitations.

Crowdin CLI. Crowdin's command-line client integrates tightly with GitHub, GitLab, and Bitbucket via native integrations and webhook support. It supports branching, has a broad file format library (JSON, YAML, XLIFF, Android XML, iOS Strings, and many others), and offers a strong translation memory. The CI integration is well-documented. Limitations: the branching model can be confusing to configure for complex monorepos, and OTA delivery requires the Crowdin OTA feature which is available on higher-tier plans.

Transifex. Transifex has long-standing CI/CD integration support via its CLI and webhooks. It introduced "Live Translation" for web-based OTA delivery — a JavaScript snippet that intercepts text nodes and replaces them with translated content from a CDN. This approach works without any changes to the application build process, which is useful for teams that cannot modify the build pipeline easily. The Live approach has performance trade-offs because it operates at the DOM level.

Lokalise CI. Lokalise has strong GitHub Actions and GitLab CI integration, a well-designed contributor workflow for translation review, and supports OTA via its SDKs for iOS, Android, and web. Its branching support is more polished than most competitors. The web editor has good screenshot-based context support. Lokalise is generally positioned at the mid-to-enterprise market with pricing that reflects that.

Phrase CLI (formerly Phrase Strings). Phrase (formerly Memsource and PhraseApp, now under a unified brand) has a comprehensive CLI, strong XLIFF support (useful for teams with professional translation agencies that prefer XLIFF workflows), and mature translation memory and quality assurance features. It is particularly strong in professional translation agency workflows. Its CI integration is solid but requires more configuration than Crowdin or Lokalise for VCS-native automation.

Better i18n. Better i18n takes a developer-first approach with a CLI, React/Next.js/Vue/Svelte SDKs, and CDN-based delivery through Cloudflare's edge network. Its OTA model means translation updates are available globally within seconds of publishing — without triggering a new build or deploy. It supports AI-assisted first-draft translations and is oriented toward engineering teams that want to manage translations close to the codebase. Its CI integration is straightforward via the CLI. As of early 2026, it is earlier-stage than Crowdin, Lokalise, or Phrase, with a narrower feature set in areas like XLIFF workflows and enterprise SSO.


FAQ

Q: Can we use continuous localization if our translators are not technical?

Yes. The pipeline automation is on the engineering side. Translators interact only with the TMS web interface, where they see strings in a translation editor — not YAML files or Git commands. The automation handles extracting strings from code, sending them to the TMS, and merging translations back. Translator experience is largely determined by the quality of the TMS editor and the context you provide, not by the pipeline mechanics.

Q: How do we handle feature branches that have not merged yet?

Most TMS platforms support translation branches that mirror VCS branches. You configure a branch mapping — for example, feature branches matching feat/* sync to corresponding TMS branches. Translators can work on strings in a feature branch before it merges. When the branch merges in your VCS, the TMS branch merges too, and translations carry over. This requires a TMS that explicitly supports branching — not all do.

Q: Should translations live in the repository or in the TMS?

Both, ideally. The repository is the source of truth for source strings (the strings developers write). The TMS is the source of truth for translated strings. Your pipeline syncs between them: source strings flow from the repo to the TMS, translated strings flow from the TMS back to the repo (or to a CDN). Storing translated strings only in the repository without a TMS makes it hard for non-developers to contribute. Storing them only in the TMS without syncing to the repo makes it hard to reproduce builds deterministically.

Q: How do we measure the health of our localization pipeline?

Track these four metrics: translation coverage (percentage of source strings with a translation per locale), translation lag (time between a string being added to source and its first translation being published), review backlog (number of machine-translated strings awaiting human review), and orphaned key ratio (translations in the TMS for keys that no longer exist in the source). A healthy pipeline has high coverage, low lag, a manageable review backlog, and a near-zero orphaned key ratio.

Q: What is the minimum viable continuous localization setup for a small team?

For a team of two to five engineers shipping a web product: a single CI step that runs the TMS CLI to push new source strings on every merge to main, machine translation enabled for first drafts, and a weekly translator review session for the most customer-facing strings. This alone eliminates release-blocking batch translation and most merge conflicts. OTA delivery and branching support can be added later as the product and translator workflow mature.


Conclusion

Continuous localization is the logical extension of CI/CD thinking to the translation layer of your product. The core insight is that translation is not a release milestone — it is a pipeline stage. When strings are extracted, handed off to translators, reviewed, and merged automatically as part of your normal development flow, the costs that make localization painful in batch workflows — release delays, stale translations, merge conflicts, developer-translator friction — are reduced to engineering problems with engineering solutions.

The pipeline described in this article is not hypothetical. Teams at companies shipping to dozens of locales run variants of it in production. The specifics vary — which TMS, which CI system, whether OTA delivery is in scope, how much human review is required — but the structure is consistent: automate the mechanical work, provide context for the human work, and treat translation completeness as a continuous metric rather than a binary release gate.

Start with the lowest-friction change available to your team: a CI step that pushes new strings to your TMS on every main branch merge. From there, add branching support, context delivery, OTA updates, and automated quality checks incrementally. Each layer reduces friction and improves quality without requiring a full pipeline rebuild.

The goal is a localization workflow that is invisible to developers — one where shipping to a new locale is a configuration change, not a project.


References

[^1]: Martin Fowler, "Continuous Integration," martinfowler.com, https://martinfowler.com/articles/continuousIntegration.html

[^2]: W3C Internationalization Working Group, "Internationalization Best Practices for Spec Developers," W3C Working Group Note, https://www.w3.org/TR/international-specs/

[^3]: OASIS XLIFF Technical Committee, "XLIFF Version 2.1," OASIS Standard, https://docs.oasis-open.org/xliff/xliff-core/v2.1/os/xliff-core-v2.1-os.html

[^4]: GitHub Actions documentation, "Events that trigger workflows," https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows

[^5]: GitLab CI/CD documentation, "GitLab CI/CD pipeline configuration reference," https://docs.gitlab.com/ee/ci/yaml/

[^6]: Unicode CLDR Project, "Unicode Common Locale Data Repository," https://cldr.unicode.org/

[^7]: IETF BCP 47, "Tags for Identifying Languages," https://www.rfc-editor.org/rfc/rfc5646

[^8]: Crowdin documentation, "CLI tool," https://developer.crowdin.com/cli-tool/

[^9]: Lokalise documentation, "CI/CD integrations," https://lokalise.com/blog/continuous-localization/

[^10]: Phrase documentation, "Phrase Strings CLI," https://support.phrase.com/hc/en-us/articles/5784095916188


Last updated: March 2026