Shipping a SaaS product in a single language is shipping half a product. Yet most engineering teams treat localization as an afterthought, bolting on translations after feature freeze, hard-coding date formats, and scattering translatable strings across components with no clear ownership. The result is a fragile process that delays releases, frustrates international users, and quietly leaks revenue in every market outside your primary locale. This playbook provides a repeatable, sprint-aligned system for localizing UI strings, product documentation, and release communications. It covers everything from market prioritization and ICU message formatting to docs-as-code pipelines, locale bundle performance, and analytics that connect localization quality to activation and retention. Follow it end to end, and localization becomes a first-class citizen on every release train.
Market and Locale Prioritization
Before you translate a single string, you need a defensible answer to the question: which locales first? Getting this wrong means burning budget on markets that won't convert while starving high-potential regions of localized product experiences.
Revenue-Based Locale Scoring
Start with quantitative signals. Pull existing revenue and trial-signup data segmented by country and browser language. Layer in market-size estimates from sources like Statista's digital market outlook and competitive density in each region. Build a simple scoring model that weights current revenue contribution, addressable market size, competitive gap (how few competitors offer localized products in that locale), and cost-to-serve (translation volume, regulatory complexity, support staffing).
Rank locales by composite score. Most B2B SaaS companies find that five to eight locales cover the vast majority of near-term international revenue opportunity. Resist the temptation to launch fifteen languages simultaneously, partial quality across many locales underperforms full quality across a focused set.
Regulatory and Cultural Filters
Quantitative scoring alone isn't enough. Some markets carry regulatory requirements that change the localization scope entirely. Germany's DSGVO enforcement means privacy-related UI copy and legal docs need native-level precision. Japan's Act on Specified Commercial Transactions requires specific disclosure formats in purchase flows. China's data residency rules may affect where locale bundles are served from.
Cultural filters matter too. Right-to-left languages like Arabic and Hebrew require layout mirroring, not just translation. Markets with formal and informal register distinctions (French, German, Korean) demand style-guide decisions before translators begin work. Flag these requirements during prioritization so they feed into scope and timeline estimates rather than surfacing as surprises mid-sprint.
Content Inventory and String Architecture
A localization program is only as reliable as the inventory it operates on. If you don't know where every translatable string lives, you can't ensure coverage, track staleness, or automate extraction.
Cataloging UI Strings, Emails, and Docs
Conduct a full audit across three content domains:
- UI strings: Button labels, tooltips, form validation messages, modal copy, onboarding flows, empty states, and settings descriptions. These typically live in JSON, YAML, or .properties resource files within your frontend and backend repos.
- Transactional and marketing emails: Welcome sequences, password resets, billing notifications, feature announcements, and drip campaigns. These often live in email platforms (SendGrid, Customer.io, Iterable) rather than in your codebase.
- Product documentation: Help center articles, API references, changelogs, and in-app guided tours. These may live in a CMS, a static-site generator, or a knowledge base tool like Zendesk or Intercom.
For each domain, record the source of truth (repo path, platform, CMS), the current string count, the update frequency, and the owner. This inventory becomes the contract between engineering, product, and localization teams. Ollang can unify these sources into a single inventory and automate extraction, review, and integration with your localization pipeline.
Key Naming Conventions and Resource File Formats
Consistent key naming prevents the single most common localization bug: duplicate or orphaned strings. Adopt a hierarchical key convention that encodes component, context, and element type. For example: settings.billing.cancelButton.label is far more maintainable than btn_cancel_2.
Choose a resource file format that your toolchain and translators can work with cleanly:
| Format | Best For | Trade-offs |
|---|---|---|
| JSON (flat or nested) | JavaScript/TypeScript frontends | Widely supported; nested structures can complicate diffing |
| YAML | Ruby, Python, docs-as-code pipelines | Human-readable; whitespace-sensitive parsing risks |
| XLIFF 2.0 | Enterprise TMS integration | Rich metadata support; verbose for small projects |
| Android XML | Mobile SaaS with Android clients | Native tooling support; less portable |
| ARB | Flutter/Dart applications | ICU-compatible; smaller ecosystem |
Whichever format you choose, enforce it with a linter in CI. Reject PRs that introduce hard-coded user-facing strings outside resource files.
Sprint-Aligned Localization Workflow
Localization that runs on a separate timeline from product development will always be late. The goal is to embed localization into your existing sprint cadence so that translated strings ship with, or very close to, the feature they belong to.
Localization Freezes and Handoff Windows
Define a localization freeze point within each sprint. This is the moment after which no new or modified source strings are accepted for the current release. A common pattern is to freeze strings two to three days before the end of a two-week sprint. This gives translators a stable batch to work against while developers continue with non-string-affecting work like bug fixes and performance tuning.
The handoff window, the time between string freeze and translated-string integration, should be explicitly scheduled. If your translation turnaround is 24-48 hours for priority locales, freeze on Wednesday of the final sprint week and integrate translations by Friday. Automate the handoff: CI pipelines should extract new or changed strings at freeze, push them to your TMS or localization partner, and pull completed translations back into the build.
Feature Flags and Partial-Language Rollout
Not every feature needs to launch in every locale on day one. Feature flags let you decouple feature availability from translation completeness. If a new reporting dashboard is ready in English, French, and German but Japanese translations are still in review, flag the feature off for ja users rather than blocking the entire release.
Partial-language support requires a fallback strategy. Decide whether untranslated strings fall back to English, to a related locale (e.g., pt-BR falling back to pt-PT), or are hidden entirely. Document this policy so QA knows what to test and support teams know what users will see.
This approach lets you maintain release velocity without forcing a lowest-common-denominator language gate on every deploy. It also provides a natural mechanism for fast-follow locale launches, which we cover in the rollout section below.
ICU MessageFormat in Practice
Hard-coding plurals, gendered phrases, and interpolated values is the fastest way to produce broken translations. The ICU MessageFormat standard solves this by encoding linguistic rules directly into message syntax, giving translators the flexibility they need without requiring code changes per language.
Plurals, Gender, and Select in Microcopy
English has two plural forms (one, other). Polish has four. Arabic has six. ICU's plural syntax handles all of them:
{count, plural,
one {You have # new notification.}
other {You have # new notifications.}
}
Translators for Polish can add few and many branches without any developer involvement. The select keyword handles gender and other categorical variations:
{gender, select,
female {She updated her profile.}
male {He updated his profile.}
other {They updated their profile.}
}
Use ICU for any microcopy that includes quantities, user-referencing pronouns, or conditional phrasing. This is especially important for notifications, activity feeds, and dashboard summaries where dynamic values are the norm.
Dynamic Content and Error Messages
Error messages are among the most-translated and least-tested strings in any SaaS product. They also tend to contain interpolated values, file names, field labels, character limits, that vary at runtime. ICU handles these cleanly:
{fieldName} must be at least {minLength, number} characters.
For dynamic content like search results summaries or usage meters, avoid concatenating sentence fragments. The classic anti-pattern, "You have used " + count + " of " + limit + " seats", breaks in languages where word order differs from English. Instead, use a single ICU message with all variables embedded:
{used, number} of {limit, number} seats used.
This gives translators a complete sentence to work with, preserving natural word order in every target language.
