Continuous localization is the idea that the translation process never ends and your content must continuously be ready for release. Instead of a translation phase before each launch, translation runs alongside development as a steady background flow.
The practical consequence is that you will sometimes ship with untranslated strings. That is not a failure of the model, it is the trade it makes: because you release continuously, a missing translation is live for days rather than a quarter.
Why the phased model breaks
The traditional sequence — build everything, freeze, translate, test, release — works when you release twice a year. It fails against continuous delivery for structural reasons:
- The freeze is a lie. Development does not stop while translation happens, so by the time translations return the source has moved.
- The batch is enormous. Six months of strings arrive at translators at once, with a deadline.
- Feedback comes too late. A translator’s question about a string reveals a copy problem, three months after the copy was written.
- Release cadence is hostage to the slowest language. One late language delays everything.
The mismatch is one of frequency. If code ships weekly and translation ships biannually, the two systems cannot be coupled without one blocking the other.
What continuous localization looks like
The loop, in five steps that repeat forever:
- Set up the languages — a source language and your target languages.
- Push source files to the translation platform whenever they change, from CI rather than by hand.
- Strings are extracted into segments. Translators see exactly what is new. Questions go to a shared thread visible to everyone, so the same ambiguity is not explained n times. Because translators work on a database rather than a file, several can work on the same language at once.
- Translate continuously. New segments appear as they are created; deleted source strings disappear from the target files automatically.
- Pull translations back on a schedule or before each release, and ship whatever is ready.
The two properties that make it work are that both directions are automated and that the unit of work is the segment rather than the file. Remove either and you are back to emailing files.
The feature branch problem
This is the part that trips up almost every team, and it has a specific shape.
Developer A finishes feature A and pushes the updated language files. Developer B finishes feature B and pushes theirs. B’s push overwrites A’s — and because the platform removes strings that no longer exist in the source file, feature A’s strings are now deleted, along with any translation work already done on them.
The cause is that language files are whole-file artefacts pushed from whatever branch happens to be current, while translation state is global. Most platforms, WebTranslateIt included, do not model branches, so the fix is a process one: push language files from exactly one branch.
Option 1 — a dedicated integration branch. Merge finished features into an i18n branch on a cadence, say every Friday. Push language files from there. Translators work over the following days. Integrate the translations and release. Choose this when shipping untranslated content is unacceptable.
Option 2 — push from main. Merge feature branches into main as they are ready and push language files from main. New strings go out untranslated and are filled in by a later release. Choose this when you can tolerate brief gaps, which is most consumer software.
Either way the rule is the same: one branch is the source of truth for language files, and nothing else pushes. Enforce it in CI rather than in a wiki page.
Continuous or agile?
They are different processes and the choice is about tolerance for untranslated content.
Continuous localization — translation never stops, releases go out with whatever is ready, gaps fill in on the next deploy. Best for web applications and consumer products with frequent deploys and a forgiving release surface.
Agile localization — three repeating phases: a development mini-sprint, a source-language release running in parallel with a translation mini-sprint, then a target-language release. Best where a release is a discrete event: mobile app store submissions, embedded software, anything with regulatory review or a marketing moment attached.
Both are supported by the same tooling. The difference is whether you gate the release on translation completeness.
A common hybrid: run continuously for the web application and agile for the mobile apps, because app store review makes mobile releases discrete anyway.
What makes it actually work
Automate both directions. A CLI in CI, or a GitHub Action. If a human has to remember to sync, they will not, and the drift is invisible until someone notices a language is three months stale.
Give context at push time. Developer comments and screenshots attached when the string is created cost the developer seconds and save every translator a question. Adding them later never happens.
Lean on translation memory. Continuous localization generates a stream of small changes, and small changes against an established memory are mostly high fuzzy matches. This is the model’s economic advantage: the trickle is cheap in a way the batch never was.
Make untranslated content visible in the product, not just in a report — a fallback that is obviously a fallback in staging. Silent fallback to English means a language can be half-translated for months without anyone noticing.
Track per-language completeness and treat it as a health metric. The failure mode of continuous localization is a language quietly falling behind because nobody owns it.
Handle plurals and placeholders at push time. A placeholder or plural structure that only breaks in production is a slow bug to find. Validation in the translation editor is the cheap place to catch it.
A minimal setup
The whole loop reduces to two commands wired into CI. WebTranslateIt’s CLI is wti:
wti push # send updated source files up
wti pull # bring translations back down
wti status # per-language completeness
wti diff # what would change, without changing it
wti diff is the one worth knowing about. Running it in a pull request check shows exactly which strings a merge would add or remove from the translation project, which turns “did anyone notice this deletes 40 segments” into a visible part of code review.
A workable arrangement for the push-from-main model:
- On merge to main:
wti pushfor source files only. New strings become available to translators within minutes of the code landing. - Nightly, or before release:
wti pull, and open a pull request if anything changed. Translations arrive as a reviewable diff rather than an unexplained working-tree change. - On every pull request:
wti diff, reported as a check.
There is also a GitHub Action if you would rather not manage the CLI in your workflow files. Either way the property that matters is that no human is in the loop for the routine case.
When not to bother
If you release twice a year into two languages, the phased model is fine and the automation is overhead. Continuous localization is a response to release frequency, and adopting it before the frequency exists solves a problem you do not have.
The signal to switch is simple: when the translation cycle has become the thing gating your releases, or when someone cannot answer how complete a given language currently is.
Frequently asked questions
- What is continuous localization?
- Continuous localization is the practice of translating alongside development rather than in a phase before release, so content is always close to ready to ship. It accepts that some strings will be untranslated at any moment, on the basis that frequent releases mean they are translated shortly after.
- What is the difference between continuous and agile localization?
- Continuous localization never stops — translation runs constantly and releases go out with whatever is ready. Agile localization runs in repeating phases: a development sprint, a release in the source language while translation happens, then a release in the target languages. Agile suits teams that cannot ship untranslated content.
- How do I handle feature branches?
- Do not push language files from feature branches. Each push overwrites the last and removes the other branch's strings. Use a dedicated integration branch instead: merge features into it, push language files from there, and pull translations back from it.
- How often should I sync translations?
- Pushing source strings on every merge to the integration branch, and pulling translations on a schedule or before each release, works for most teams. The important property is that both directions are automated — a manual sync step gets skipped and the two sides drift.
Keep reading
-
i18n vs l10n: what's the difference?
Internationalization is the engineering work that makes translation possible. Localization is the translation itself. Here is where the line falls and why it matters.
-
What is a Translation Management System?
What a TMS actually does, the problems it solves that a spreadsheet cannot, and how to tell whether your team has outgrown passing files around by email.
-
What is Translation Memory and how does it work?
How translation memory stores and reuses past translations, what fuzzy match percentages actually mean, and why placeholder syntax quietly destroys match rates.
-
Continuous localization: the i18n workflow (documentation)
Streamlining the translation process, and the integration-branch strategies that make it work.
Translate your app without the spreadsheet round-trip
WebTranslateIt reads the file formats and placeholder syntax described on this page, validates them as translators work, and syncs the results straight back into your repository.