Arkian logo
Start free
Menu
← All articles

Skip Unchanged Uploads: Small Teams Package Translations for Release

Skip Unchanged Uploads: Small Teams Package Translations for Release

Developer checking translation upload changes

The pipeline to package translations for release is: extract canonical source strings, push changed strings to a translation management system with branch or tag scoping, pull translations into a reviewed sync branch, run CI validation gates, build locale bundles, and tag those bundles to the app version for atomic release. Standards like CLDR and MessageFormat keep formatting consistent, and CI gates catch broken keys before they ship.


TL;DR:

  • Compare the extracted catalog hash with the last upload and skip unchanged pushes; scope real updates to a release branch or tag, with context notes.
  • Ship a locale only after it reaches roughly 80% translation completeness; keep less complete locales behind a feature flag rather than delaying the whole release.
  • Pull finished translations into a protected sync branch and review them through a pull request that checks placeholders, plural rules, format compilation, and localized rendering.
  • Small teams can commit bundles with the app and roll both back together, adding OTA delivery only when release delays make string fixes costly.

Arkian
arkian.ai
Package Localized Releases With Less Overhead
Arkian automates multilingual scripts, voice outputs, and structured language packages, with validation and packaging designed for small teams.
Explore Arkian

Table of Contents

Prepare the source catalog before you extract anything

A release pipeline is only as reliable as its source catalog. You need a canonical base locale file, stable key ordering, and normalized formatting so every diff is readable and every translator works from the same reference.

Message descriptors should carry an id, a defaultMessage, a description for context, and explicit placeholders. Plural-sensitive strings need ICU or MessageFormat syntax rather than string concatenation, since MessageFormat has advanced to stable status in CLDR 47, giving teams a firmer spec to build extraction tooling against.

Common extraction setups rely on:

  • FormatJS or i18next-cli to scan source files and generate a normalized JSON catalog.
  • An npm script (npm run extract) wired into a pre-commit hook or CI step.
  • A linter pass that flags missing descriptions or unescaped placeholders before the catalog ships to translators.

Pro Tip: Sort keys alphabetically in your extraction script so diffs only show real content changes, not reordering noise.

Push changed strings to a TMS without flooding translators

Pushing every build to your translation management system wastes translator time and your budget. A hash check on the source catalog, compared against the last pushed version, tells you whether there is anything worth sending at all.

When there is a real change, scope the push to a branch or tag tied to the release, not a loose “main” bucket that mixes unrelated work. Most translation management systems support this kind of branch or version scoping alongside screenshots, a shared glossary, and translation memory, all of which raise consistency across releases.

A typical flow looks like this:

  • Run the extraction script and diff the output against the last pushed catalog hash.
  • Skip the push entirely when the hash matches, which keeps translator queues clean.
  • Upload the changed catalog to the TMS, scoped to a release branch or tag.
  • Attach screenshots or context notes where strings are ambiguous out of context.
  • Store the TMS API token as a CI secret, never in a config file committed to the repository.

This pattern mirrors standard CI/CD localization sync practice, where the push step is explicitly scoped and automated rather than manual.

Pull translations into a reviewed sync branch and open a PR

Once translators finish their work in the TMS, pull the results into your repository through a dedicated branch rather than committing straight to main. A branch named l10n/sync or i18n-sync/release-x.y keeps translation changes isolated and reviewable before they touch anything else.

  1. Trigger a pull from the TMS into the sync branch, either on a schedule or via webhook when translations reach a completion threshold.
  2. Open a pull request automatically from that branch so the diff is visible to reviewers.
  3. Run the same CI checks you’d run on any code change: syntax validation, placeholder checks, and build verification.
  4. Merge once a reviewer confirms the diff looks right and CI passes.

Webhook-triggered pulls work well when your TMS can notify you the moment a locale crosses a completion threshold, which suits teams shipping frequently. Scheduled pulls, say nightly or twice a week, suit teams on a fixed release cadence who would rather batch review translation changes once per cycle.

Either way, the TMS should stay the editing surface for translators while Git remains the source of truth for what actually ships. This is the same separation Pootle’s release documentation describes: upload templates, let translators work in the tool, then pull and build from committed files.

Pro Tip: Protect the l10n sync branch with the same review rules as your main branch so a bad translation pull can’t merge unnoticed.

Set CI validation gates so broken translations never ship

A pull request full of translated strings still needs machine checks before a human reviewer signs off. The checks that matter most for a release pipeline are:

  • An untranslated-string threshold that fails the build when too many keys are missing for a locale you plan to ship.
  • Placeholder and plural validation, confirming every variable in the source string exists in the translated string.
  • Format compilation, running a tool like FormatJS’s compile step to catch malformed ICU syntax before it reaches the bundle.
  • A localized smoke test that boots the app in at least one non-default locale and checks for rendering errors or missing-string fallbacks.

Operational guidance on release gating recommends shipping a locale once it crosses roughly 80% translation completeness, a threshold drawn from Pootle’s own release process, which updates the LINGUAS file to include only locales that clear that bar.

A minimal GitHub Actions job for this stage might pull from the TMS, open a PR, and run the gates in sequence: extraction diff, TMS pull, placeholder check, format compile, then a localized build. Keep partially translated locales behind a feature flag rather than blocking the whole release, and add visual regression testing where your team already has the tooling, since layout breaks are common with longer translated strings.

Package locale bundles, tag them, and keep releases atomic

Once translations pass validation, the packaging step turns them into locale bundles, JSON, iOS .strings, Android XML, or YAML, depending on your platform. Commit the pulled translations, then create a tag like l10n-$APP_VERSION and pin that exact tag in your release manifest so the bundle and the code that depends on it move together.

  • Repo-committed bundles are simplest for small teams: translations ship in the same build as the code, and a git revert rolls back both at once.
  • OTA or CDN-distributed bundles let you push string fixes without a full app release, useful once your release cadence gets tight.
  • Pinning the locale tag in the manifest means a rollback to a previous app version automatically restores the matching translation set, avoiding mismatched strings.
  • For OTA delivery, version your bundle endpoint explicitly so an old app build never accidentally pulls bundles meant for a newer release.

This tag-and-pin approach reflects the atomic, versioned locale release pattern that CI-driven localization workflows rely on.

A pre-release and release-day checklist for translations

Before you cut a release, confirm these in order:

  1. Run extraction and verify the source catalog diff is clean and reviewed.
  2. Confirm the TMS upload went through and check the translation completeness for each target locale.
  3. Verify the completeness threshold is met and flag any locale that falls short.
  4. Open and review the l10n sync PR, checking placeholders, plurals, and formatting.
  5. Confirm CI passes on that PR before merging.

On release day: merge the l10n PR, create and pin the locale tag, build from the now-committed files, run a post-build localized smoke test, and deploy. Give translators at least a few days of lead time before a release and freeze string changes once extraction runs, so translators aren’t working against a moving target.

Standards worth tracking: CLDR and MessageFormat

Locale data and message formatting both depend on Unicode standards that shift over time. CLDR 47 made MessageFormat stable, and the TR35 MessageFormat specification documents the related LDML parts that govern plural rules and placeholder syntax.

Real-world release processes like Pootle’s and WordPress’s polyglots documentation show these standards applied at scale. Treat any CLDR or MessageFormat version bump as a migration task worth testing, not a silent dependency update.

Strategies for multilingual voice output synchronization with text localization

When a product ships voice output alongside translated text, the two need to stay in lockstep or the experience breaks immediately, a voice prompt in one language reading over UI text in another.

The most reliable pattern treats voice generation as a downstream step from the same source catalog that feeds text localization, never a parallel pipeline with its own copy of the strings. When a source string changes, both the text translation job and the voice generation job should trigger from that same change event, pulling from the same translated catalog rather than two catalogs that can drift apart.

Timing matters as much as wording. Voice output needs duration metadata alongside the audio file, so a UI that times animations or transitions to spoken audio can adjust per locale, since translated phrases rarely take the same amount of time to speak as the source language.

Versioning the voice assets the same way you version text bundles keeps rollbacks clean: tag voice output to the same release tag as the locale bundle it pairs with, so a rollback restores matching audio and text together rather than leaving one updated and the other stale.

For teams managing this manually, keeping text and voice synchronized across several locales becomes a real operational cost as the number of target languages grows. Automating both from one source catalog, with one validation pass before either ships, removes the drift risk at its source rather than catching it after release.

Automation techniques for end-to-end validation within localization packaging

Validation that only checks syntax misses the failures that actually reach users: a correctly formatted string that’s still wrong in context, or a placeholder that compiles but renders empty.

A complete validation pass for a localization package runs several layers in sequence. Static checks catch malformed ICU or MessageFormat syntax and missing placeholders before a build even starts. Structural checks confirm every key in the source catalog has a corresponding entry in each target locale file, flagging gaps rather than letting a missing key silently fall back to the default locale in production.

Four sequential localization validation stages

Build-time checks compile the translated strings into the actual bundle format, whether that’s Android XML, iOS .strings, or JSON, and fail the build if compilation errors out for any locale. A localized smoke test then boots the build in each shipped locale and checks for rendering errors, truncated text, or fallback strings appearing where a translation should be.

The gates that matter most are the ones that run automatically on every pull request touching the source catalog or the translation files, not the ones run manually before a release and easily skipped under deadline pressure. Wiring extraction diffing, placeholder checks, and format compilation into the same CI job that already runs your test suite means a broken translation fails the build exactly the way a broken unit test would.

Keeping this validation chain inside your existing CI tooling, rather than a separate manual QA pass, is what makes continuous localization actually continuous rather than a periodic cleanup task before each release.

Handling locale-specific formatting and cultural adaptation in packages

Translating the words is the easy part. Dates, numbers, currency, and names of days or months all follow locale-specific rules that a direct string translation won’t fix on its own.

CLDR data is the standard reference for this: it defines how dates, plural categories, number separators, and currency formats behave per locale, and MessageFormat’s move to stable status makes it easier for implementations to apply those rules consistently rather than hardcoding format strings per language.

Plural rules are the most common source of bugs. Plural categories vary by language, and a message format that only handles “one” and “other” may produce grammatically wrong output in some locales. Building your message descriptors around ICU plural syntax from the start, rather than retrofitting it later, avoids a painful rewrite once a new locale exposes the gap.

Cultural adaptation goes beyond formatting rules into content itself: color associations, imagery, idioms, and examples that make sense in one market can read oddly or land wrong in another. This is harder to automate and usually needs a human reviewer with context on the target market, which is one reason the review step in a localization pipeline matters as much as the technical validation gates.

Right-to-left languages add a layout dimension on top of formatting: text direction, mirrored UI elements, and bidirectional text handling all need testing in an actual rendered build, not just a string-level check. Include at least one right-to-left locale in your localized smoke tests if you ship any.

Approaches to integrating localization packages into various deployment environments

How a localization package reaches a running app depends heavily on the platform and how often you need to update strings without a full release.

Mobile apps on app stores typically bundle translations inside the app binary, since store review cycles make frequent OTA string updates impractical for anything beyond minor fixes. This favors the repo-committed bundle approach: translations ship in the same build as the code, version together, and roll back together.

Web applications have more flexibility. A CDN-hosted locale bundle can update independently of a deploy, letting you push a translation fix without a full redeploy, as long as the bundle endpoint is versioned so old cached clients don’t suddenly load a locale file that doesn’t match their running code.

Server-side applications and APIs that return localized error messages or notifications usually load locale bundles at startup or on a polling interval, which means a deployment environment with frequent restarts (containers, serverless functions) needs the bundle baked into the deploy artifact rather than fetched live, to avoid a cold start with missing strings.

Desktop applications split the difference: some bundle translations with the installer, others check for an updated language pack on launch. Either way, the same principle holds across every environment: the locale bundle version and the application version need to be tracked together, whether that tracking happens through a committed file, a tagged release, or a version parameter on a CDN request, so a mismatch between code and translations never reaches a user silently.

Approaches to integrating localization packages into various deployment environments — overview diagram

Author perspective: recommendations for small developer teams

Small teams don’t need the full pipeline on day one. Start with extraction and a TMS push, add a pull-to-PR pattern once that’s stable, then layer in CI checks as the release cadence demands it. Trying to build every gate at once usually means none of them get finished.

Repo-committed bundles are the right default for most small teams: fewer moving parts, and a revert fixes both code and strings. Add OTA delivery later, once a release cadence makes waiting for a full build genuinely costly.

— Arkian

Where Arkian fits for teams tired of TMS overhead

We built Arkian for the part of this pipeline that eats the most time with the least payoff: running the actual translation, metadata, and voice production jobs without wiring up a full TMS or granting repository access to an outside service, unlike tools that help you catalog first multilingual product descriptions.

Arkian

Our platform produces multilingual translations, generates structured, delivery-ready language files in formats like JSON, iOS .strings, Android XML, and YAML, and handles packaging into reviewable bundles.

  • We automate localization production so your team can work without a full TMS.
  • Our packaging output includes structured language files in formats like JSON, iOS .strings, Android XML, and YAML.
  • We generate multilingual voice and metadata alongside text.

If your team is weighing in-house TMS setup against a faster path, check our pricing and membership plans to see what fits your release cadence.

FAQ

Where can I find a translator for packaging?

Translation management systems like Crowdin or Weblate connect you with professional translators, or you can hire freelance translators directly through marketplaces that specialize in localization work. Some teams instead use automated localization platforms that handle translation, formatting, and packaging in one step, which cuts out separate translator sourcing and TMS configuration.

What are the four types of translations?

Localization discussions use broad categories such as literal, free, idiomatic, and technical translation, though the exact taxonomy varies by source. For software strings specifically, what matters more is matching tone and context (UI copy, error messages, marketing text) rather than fitting a translation into one rigid category.

How do I translate app packaging text to English?

Extract the source strings from your non-English locale files, run them through a TMS or an automated localization tool, and validate the output for placeholders and plural forms before building. The same extract, translate, validate, package pipeline used for releasing into other languages works in reverse when English is the target.

How much untranslated content is acceptable before shipping a locale?

Release gating practice commonly uses a completeness threshold around 80%, a figure drawn from Pootle’s release process, below which a locale is held back from that release rather than shipped with visible gaps.

Does Arkian require repository access to generate language packages?

No. Arkian produces structured, delivery-ready language files without needing access to your source repository or a full translation management system, which fits teams that want packaged translations without granting broader system access.

Sources