Better I18NBetter I18N
iOS (Swift)

API Reference

Complete API reference for the BetterI18n Swift SDK — I18nConfig, I18nStore, BetterI18n, and Translator.

I18nConfig

Configuration struct passed to BetterI18n. All properties except project and defaultLocale are optional.

PropertyTypeRequiredDefaultDescription
projectStringProject identifier from the dashboard (e.g. "my-org/my-app")
defaultLocaleStringFallback locale when no preference is stored (e.g. "en")
appGroupIdentifierString?nilApp Group ID for shared storage with widget extensions
cdnBaseURLStringBetterI18n CDNCustom CDN base URL for self-hosted translations
let config = I18nConfig(
    project: "my-org/my-app",
    defaultLocale: "en",
    appGroupIdentifier: "group.com.mycompany.myapp"
)

I18nProvider

A SwiftUI view that initializes an I18nStore and injects it into the environment.

struct I18nProvider<Content: View>: View {
    init(core: BetterI18n, @ViewBuilder content: () -> Content)
}
ParameterTypeDescription
coreBetterI18nConfigured SDK instance
content() -> ContentRoot view builder

I18nProvider creates I18nStore as a @StateObject and calls store.load() via .task on first appear. It exposes the store as an @EnvironmentObject to all descendant views.


I18nStore

@MainActor @ObservableObject — the reactive state container for translations.

Published Properties

PropertyTypeDescription
localeStringCurrently active locale code
isLoadedBooltrue after Phase 1 (storage read) completes
isRefreshingBooltrue while a CDN fetch is in progress
errorError?Last fetch error, if any

Methods

load()

Starts the two-phase load sequence:

  1. Phase 1 — reads cached translations from storage, sets isLoaded = true
  2. Phase 2 — fetches fresh translations from CDN in the background, updates silently
await store.load()

Called automatically by I18nProvider. You only need to call this manually if you create I18nStore without I18nProvider.

setLocale(_:)

Changes the active locale, saves the preference to storage, and re-fetches translations.

await store.setLocale("tr")

t(_:_:)

Translates a key with optional interpolation variables.

store.t("home.welcome")                        // → "Welcome"
store.t("home.greeting", ["name": "Osman"])    // → "Hello, Osman!"

Returns the key string unchanged if no translation is found.


BetterI18n

The core SDK class. Use this directly when you need fine-grained control or when building non-SwiftUI targets (widgets, command-line tools, etc.).

Initializer

BetterI18n(config: I18nConfig)

Methods

MethodReturnsDescription
load()asyncTwo-phase load: storage then CDN
setLocale(_:)asyncChange locale + persist preference
detectLocaleFromStorageOnly()async -> StringRead saved locale preference without network
getTranslatorFromStorageOnly(locale:)async -> Translator?Return a Translator from cache only, no CDN call
translator(for locale: String)Translator?Synchronous access to loaded translator

Storage-only API

The storage-only methods are designed for WidgetKit extensions where network calls during timeline generation are unreliable. They read from UserDefaults synchronously and return nil if nothing is cached.

let locale = await i18n.detectLocaleFromStorageOnly()
let t = await i18n.getTranslatorFromStorageOnly(locale: locale)
let title = t?("widget.title") ?? "My App"

Storage

BetterI18n uses a TranslationStorage protocol to abstract where translations are persisted.

TranslationStorage Protocol

public protocol TranslationStorage {
    func getString(forKey key: String) -> String?
    func setString(_ value: String, forKey key: String)
}

Built-in Implementations

TypeBackendUse case
UserDefaultsStorageUserDefaults.standardStandard app storage (default)
AppGroupStorageUserDefaults(suiteName:)Shared storage with widget extensions

AppGroupStorage is selected automatically when I18nConfig.appGroupIdentifier is set.

To use AppGroupStorage, you must add the App Groups capability in Xcode under Signing & Capabilities for both your app target and the widget extension target. The group identifier must match exactly.


Translator

Translator is a function type that accepts a key and optional variables:

public typealias Translator = (_ key: String, _ variables: [String: String]?) -> String?

It's returned by BetterI18n.getTranslatorFromStorageOnly(locale:) and used internally by I18nStore.t().

callAsFunction patterns

// Basic translation
translator("home.title")

// With interpolation
translator("home.greeting", ["name": "Osman"])

// Nil-coalescing fallback
translator("home.title") ?? "My App"

Variable interpolation uses {{variableName}} syntax in your translation strings:

{
  "home.greeting": "Hello, {{name}}!"
}

On this page