Localization for a Fitness App — What I Wish I Knew Earlier

# indiedev
Localization for a Fitness App — What I Wish I Knew Earliergarry

Boxing Is Global, English Is Not BoxTime started as an English-only app. Then I looked at...

Boxing Is Global, English Is Not

BoxTime started as an English-only app. Then I looked at my App Store analytics: 40% of my downloads came from non-English-speaking countries. Brazil, Japan, Mexico, Germany. I was leaving value on the table by not localizing.

String Catalogs in Xcode 15+

Apple introduced String Catalogs (.xcstrings files) in Xcode 15, replacing the old .strings and .stringsdict files. The migration was worth it -- String Catalogs auto-detect localizable strings and provide a single-file editing experience.

// In code, just use String(localized:)
Text(String(localized: "Round \(currentRound) of \(totalRounds)"))

// Or use the automatic LocalizedStringKey behavior
Text("Round \(currentRound) of \(totalRounds)")
Enter fullscreen mode Exit fullscreen mode

SwiftUI Text views automatically treat string literals as LocalizedStringKey. For a simple app, this means most of your UI is already localization-ready if you used string literals in Text.

The Challenges Specific to Fitness Apps

Number Formatting

Some cultures use commas for decimal separators. Timer displays should use the user's locale:

// Wrong: hardcoded format
Text("\(minutes):\(String(format: "%02d", seconds))")

// Right for a timer: this is one case where you actually want
// a fixed format. Timers are universally read as M:SS.
// But display it clearly:
Text(remainingTime, format: .timerCountdown)
Enter fullscreen mode Exit fullscreen mode

Actually, timer displays are an exception to the localization rule. "3:00" means three minutes everywhere. I deliberately do not localize the countdown format. But labels around the timer ("Round", "Rest", "Rounds remaining") absolutely need translation.

Pluralization

"1 round" vs "3 rounds" is straightforward in English. Other languages have complex plural rules. Russian has three plural forms. Arabic has six.

// In your String Catalog, define plural variants:
// "rounds_remaining" = "%lld rounds remaining"
// With variants for: zero, one, two, few, many, other

Text("rounds_remaining \(roundsLeft)")
Enter fullscreen mode Exit fullscreen mode

String Catalogs handle plural rules per locale. You define the variants, and iOS picks the right one at runtime.

Layout Flexibility

German words are longer than English. Arabic reads right-to-left. Your layout needs to handle both.

// Bad: fixed-width container
Text(phaseLabel)
    .frame(width: 100)

// Good: flexible layout
Text(phaseLabel)
    .frame(maxWidth: .infinity)
    .minimumScaleFactor(0.7)
Enter fullscreen mode Exit fullscreen mode

The .minimumScaleFactor modifier lets text shrink to fit rather than truncating. For BoxTime, I set it on all labels that might be longer in other languages.

What I Localized (and What I Did Not)

Localized:

  • All UI labels ("Round", "Rest", "Start", "Pause", "Settings")
  • App Store metadata (title, subtitle, description, keywords)
  • Notification text

Not localized:

  • Timer display (universal format)
  • Sound file names (internal)
  • Analytics event names (internal)

How I Got Translations

For the initial launch, I used a combination of:

  1. Machine translation (DeepL, not Google Translate) for the first pass
  2. Native speaker review from language exchange communities and Reddit
  3. App Store metadata was the priority -- this is what drives downloads

I focused on five languages first: Spanish, Portuguese, Japanese, German, and French. These covered my top non-English markets.

The Impact

After localizing the App Store listing alone (before even localizing the app UI), downloads from localized markets increased by roughly 60%. Localizing the in-app UI further improved retention in those markets.

If you are an indie dev with a fitness app, check your App Store Connect analytics for your top countries. If you see significant traffic from non-English markets, localization has clear ROI -- even if you start with just the App Store metadata.

BoxTime is currently localized in six languages, with more planned based on download data.