GoLocalise

iOS engineering guide

iOS localization with Swift, SwiftUI, and OTA updates

iOS translations can be updated without another App Store release when the copy is delivered as versioned localization data. Keep a bundled baseline in the app, load cached content at startup, and refresh reviewed translations in the background.

How traditional iOS localization works

A conventional iOS app ships localized resources inside the app bundle. Localizable.strings stores key-value copy, while string catalogs such as .xcstrings organize translations and variations in Xcode. SwiftUI's localized text APIs and Foundation resolve those resources for the active locale.

Bundled resources are dependable because they are installed with the binary and work offline. Their release boundary is also the app binary: correcting bundled copy normally requires a new build and App Store release. Assets, layouts, and executable behavior still belong in that traditional release process.

Can iOS translations be updated without an App Store release?

Yes, for text that the application intentionally resolves from a remote localization layer. An OTA client can fetch a published translation artifact, validate it, cache it, and use it on later lookups. This should complement—not remove—the translations bundled with the app.

Keep the boundary clear.

OTA localization changes localization data. It should not be used to deliver executable code, new layouts, or behavior that belongs in an reviewed app release.

Install the GoLocalise Swift package

Add the public package in Xcode with File → Add Package Dependencies, or declare it in a Swift package. Version 1.0.0 supports iOS 15+ and macOS 12+.

Package.swift
dependencies: [
    .package(
        url: "https://github.com/abdallahnh/golocalise-swift.git",
        from: "1.0.0"
    )
]

Configure an offline-safe client

Use a public gl_sdk_ credential scoped to the project and environment. The SDK loads persistent cache, refreshes in the background, and resolves each lookup synchronously from OTA memory, bundled translations, the caller fallback, then the key.

Swift
import GoLocalise

let bundled = DictionaryBundledTranslations([
    "en": ["common": ["welcome": "Welcome"]],
    "ar": ["common": ["welcome": "مرحباً"]],
])

let client = GoLocaliseClient(configuration: try GoLocaliseConfiguration(
    baseURL: URL(string: "https://api.golocalise.me")!,
    token: "gl_sdk_REPLACE_ME",
    projectId: "PROJECT_ID",
    environment: "production",
    locale: "en",
    cache: try FileCacheAdapter(directory: cacheDirectory),
    bundled: bundled
))

Task { await client.initialize() }

let title = client.translation(
    for: "welcome",
    namespace: "common",
    fallback: "Welcome"
)

Publishing, cache safety, and rollback

GoLocalise publishes approved content as an immutable environment release. The Swift SDK checks manifest scope, release order, artifact origin, byte size, and SHA-256 before atomically replacing its cache. A failed refresh keeps the last-known-good cache and bundled baseline available.

A rollback does not rewrite an earlier release. It creates a new release from historical content, preserving an auditable version sequence. Read the deeper OTA engineering guide for the complete fetch and fallback path.

iOS localization implementation checklist

  • Keep complete source-language and critical fallback copy bundled.
  • Use stable semantic keys rather than visible English sentences.
  • Test missing keys, first launch offline, corrupt cache, and timeout paths.
  • Exercise long translations, Dynamic Type, plurals, and RTL layouts.
  • Publish to Development and Staging before creating a Production release.
  • Never embed an organization API secret in the application.

Implement with GoLocalise

Connect a project to a production-ready SDK.

Publish a reviewed release, create a read-only SDK credential, and keep bundled translations as the final fallback.