Everything else is already “as code” so why not localization?
Terraform handles infra. YAML handles config. Markdown handles docs. Git ties it all together.
So why is localization so often a mess of spreadsheets, copy-paste jobs, and last-minute handoffs?
Translations often lag behind. Locale files drift out of sync. Context gets lost between product, engineering, and content. And at its worst, a poor localization workflow forces teams to choose: delay the release, or ship without full localization.
The good news is that the principles of infrastructure as code, configuration as code, documentation as code, all apply just as well to localization. With a composable localization approach, translation becomes a first-class part of the software delivery lifecycle that;s version-controlled, automated, and fully integrated into your existing workflows.
What we mean by “Localization as code”
The “as code” model shows up across the dev stack but, even though the details might vary, it relies on some core principles. Namely, automate wherever possible, manage state through version control, ensure environment consistency, and integrate directly into CI/CD workflows.
For localization, that means:
- Version control makes translation files traceable, reviewable, and tied to the changes they support.
- Automation removes manual file handoffs, syncing source and translated content reliably across tools.
- Consistency ensures translations match the current state of the product across branches, environments, and platforms.
- Repeatability and idempotency allow localization to be part of testable, rebuildable release processes.
- Modularity supports shared strings, design tokens, and reusable UI copy across code, content, and design systems.
- CI/CD integration enables localization status to influence deployments, thereby catching problems early.
- Observability gives teams visibility into translation status, errors, and coverage, just like any other service.
You might also come across the term “composable localization”. In this piece, we use it interchangeably with localization as code. Both refer to the same core idea: treating translation as a modular, automatable part of the software delivery lifecycle.
Contrasting with the traditional approach
We’ll get into the details of composable localization in a moment. But first, let’s look at a typical “traditional” workflow.
- String extraction: Developers manually extract translatable strings from the codebase and export them into spreadsheets or upload them to a translation platform.
- Translation in isolation: Translators work in disconnected tools, often without context, screenshots, or visibility into how or where the strings are used.
- Manual handoff: Once translations are complete, they’re downloaded in bulk — often as ZIP files or spreadsheets — and sent back to the development team.
- Manual reintegration: Developers manually copy the translations back into the codebase, resolve any format or encoding issues, and try to match them to the right feature branches.
- Out-of-band release: Translations are deployed separately from the features they support, often in a follow-up release or patch cycle.
That approach made sense when releases were quarterly or even based around shipping shrink wrapped CD-ROMs. But paired with continuous development, it is so clearly:
- Inefficient: Every step relies on manual effort: exporting files, handing them off, reintegrating them, and checking they haven’t broken anything. It doesn’t scale, especially across multiple locales or parallel feature branches.
- Fragile: Manual handoffs introduce risk at every stage. It’s easy to overwrite or misplace a file, miss a string, or deploy an incomplete set of translations. Rather than being a final check, QA might be the first step where problems show up.
- Disconnected: Translation happens outside the development workflow. There’s no integration with Git, no reliable link between strings and the code they came from, and no clear visibility into what’s been translated, what’s pending, or what’s missing.
Composable localization workflows
Perhaps the core weakness of the traditional model is fragmentation. People who should be working together end up in silos. Developers ship features, content teams update copy, designers refine UI but localization happens “somewhere else,” disconnected from the day-to-day workflow.
A localization-as-code approach flips that. It doesn’t require everyone to take on more work, but it does give each team visibility into the full process. Even if their role stays focused, they’re no longer operating in the dark.
So what does that look like in practice?
There are three core contributors to a composable localization workflow:
- Developers define and sync translatable content in code.
- Content teams manage localized content in CMS platforms.
- Translators who localize strings in a translation management system.
Understanding how these roles connect, and how their workflows fit together, is the first step to building a localization workflow that scales.
The developer workflow
The developer’s workflow in localization as code starts out just as it would in a more traditional setup by writing code with translation keys:
<button>{t('auth.signin.button')}</button>
Code language: HTML, XML (xml)
And adding the English source text:
{
"auth": {
"signin": {
"button": "Sign in"
}
}
}
Code language: JSON / JSON with Comments (json)
What happens next is where the workflows split.
In the traditional approach, once development is done, someone, often a developer or a project manager, has to manually export the locale files from the repo. They upload them to a translation platform or send them to translators as spreadsheets. This usually happens in bulk, after a feature is complete.
When translations are ready, someone downloads the files, places them in the correct folders, resolves any format mismatches, and manually merges them into the main branch.
In a composable workflow, that handoff disappears. A CLI tool, either run manually or triggered as part of your CI pipeline, detects changes in your source files and pushes updated strings to your translation platform.
If you’re using Phrase, that might look something like this:
# Step 1: Push new or updated source strings
$ phrase push
Uploading en.json… ✅
5 new keys detected
➜ Translation jobs created for: es‑ES, fr‑FR, de‑DE :contentReference[oaicite:3]{index=3}
# Step 2: Pull completed translations
$ phrase pull
Downloaded es‑ES → src/i18n/es‑ES.json
Downloaded fr‑FR → src/i18n/fr‑FR.json :contentReference[oaicite:4]{index=4}
# Step 3: Commit everything together
$ git add src/i18n/
$ git commit -m "feat: checkout flow with translations"
Code language: PHP (php)
Because translations are now part of the development workflow, you can apply the same quality checks you’d use elsewhere, including gating builds based on translation coverage.
For example, in CI, you can query translation job status via the Phrase CLI or API and fail the build if required locales aren’t complete:
untranslated=$(phrase job status --locale=fr-FR --format=json | jq '.untranslated')
if [ "$untranslated" -gt 0 ]; then
echo "❌ Incomplete translations for fr-FR"
exit 1
fi
Code language: PHP (php)
And it’s a similar story when working on feature branches. When you push new strings from a feature branch, your translation platform can scope jobs to that branch, keeping translations tied to the exact version of the UI they support. Once the feature is merged, the translations merge with it.
Content workflow
Content editors start the same way as they would in a traditional workflow by creating and updating content in the CMS.
With composable localization, publishing content triggers translations automatically. Let’s say an editor writes a new product description in English. When they hit publish, that triggers a webhook that detects the new content, extracts the localizable fields, and sends them to the translation service with context about where they’ll appear.
Once translations are complete, they’re synced back into the CMS via API. No manual copy/paste, no CSVs, and a reduced need for manual coordination.
Translator workflow
Composable localization connects translation jobs directly to the product development workflow. This builds on workflow improvements introduced by Translation Management Systems (TMS), such as jobs scoped to a particular feature or other unit of work, but shifts the responsibility for triggering and structuring those jobs upstream to where the changes originate.
Rather than relying on manual file uploads or project managers batching strings before a release, in a composable localization workflow translation jobs are created automatically when a developer pushes a feature branch or a content editor publishes an update. The result is a steady flow of smaller, incremental jobs that map directly to how the product evolves.
More from the Phrase blog
Components of localization as code
We’ve looked at the benefits of localization as code and how it impacts workflows. But what technology will you need to introduce to actually support it?
Composable localization relies on infrastructure that can plug into your existing stack without adding friction.
- Translation platform API: To support localization as code, your platform needs more than basic string import and export. A well-designed API should let you programmatically create and scope translation jobs, track their status, trigger reviews or QA checks, approve or reject translations, and pull completed files into the right environment. This turns localization into a service you can integrate, automate, and monitor like any other part of your delivery pipeline.
- Git and CLI integration: Your localization platform should integrate with version control and CI tooling. Developers should be able to push and pull translations via CLI, keeping everything traceable in Git.
- Branching support: Feature branches should trigger independent translation workflows. That way, translations stay aligned with features and can be merged, rolled back, or tested in isolation.
- Flexible automation hooks: Webhooks, events, and config rules let you automate what happens when translations complete, whether that’s triggering a deployment, gating a release, or notifying reviewers.
- Environment parity: You should be able to test localization in development and staging environments exactly as it will appear in production.
But getting the technology in place is just one aspect of localization as code.
Getting started with localization as code
Adopting localization as code doesn’t mean rebuilding everything at once. The goal is to start small, establish reliable workflows, and scale from there. Here’s one way to get started.
1. Assess your current setup: Begin with a simple audit. Where does your localizable content currently live? Look at code repositories, CMS fields, design systems. Map out how strings are created, managed, and delivered today. Identify where manual steps, copy/paste work, or versioning issues are slowing things down.
2. Clarify ownership: Who owns each type of source content? Speak to developers, content editors, designers, product owners. Define a clear source of truth for each, and make sure everyone understands what’s canonical and what’s just a copy.
3. Start with a focused pilot: Developer-driven i18n files are often the best place to begin. They’re already structured, usually version-controlled, and easy to wire into a sync process. You’ll be able to prove the value of automation without overhauling your entire content workflow.
4. Add version-controlled configuration: Use a config file (like .phrase.yml) to define your translation workflow: which files to push, which locales to pull, and how everything should be structured. This config becomes the anchor for repeatable, testable, automatable localization.
5. Integrate with your CI/CD pipeline: Treat translation like any other build dependency. Add translation syncs to your CI jobs, and consider gating builds when coverage drops below an acceptable threshold. This keeps releases predictable and helps surface issues early.
6. Expand gradually: Once you’ve proven the developer flow, extend the approach to content and design systems. Many CMS platforms support webhook-based translation triggers and design tools are increasingly structured to support localized UI elements.
The path to composable localization
Localization as code is a course correction. It brings your localization workflow and tooling in-line with the rest of your development stack, where version control, automation, and CI/CD integration are already standard practice.
The coordination problems that can lead to friction in traditional localization, such as manual handoffs, out-of-sync files, last-minute translation delays, aren’t unique to translation. They’re the same problems every other part of software development solved by adopting “as code” principles.
The infrastructure already exists: a translation management system like Phrase and its CLI, CI/CD, webhook integrations, and Git sync. What’s needed is the organizational shift to treat localization as a parallel process rather than a final step. For teams building global products, this means applying the same principles that already work everywhere else in your stack to the one area that’s been left behind.
Automated software localization for developers
Discover how Phrase helps teams automate and streamline updates without slowing down development