Apps SDK — iOS / macOS

Make your iOS or macOS app multilingual with one line at startup and a t() call per string. UI strings are translated into 90 languages and cached on disk for instant, offline subsequent launches. No public call ever throws into your app — every failure degrades to the source text.

Experimental preview. This is an early Swift package (0.1.0-preview.1). It compiles clean and passes its unit tests on the official Swift 6.3.2 toolchain (swift build + swift test), but it has never been built on a real Mac or run on an Apple device — that needs Xcode on a Mac, which the verification machine does not have. iOS / macOS-specific behavior is unverified and the public API may still change. Not recommended for a shipping app yet — we'd love your feedback.

Install

  1. Download the package: transable-ios-0.1.0-preview.1.zip
  2. Unzip it and add it as a local Swift package: in Xcode, File → Add Package Dependencies… → Add Local…, then check TransableSdk for your app target. (Once the repo is public you'll be able to add it by URL instead — see PUBLISH.md.)
  3. Requires Swift 5.7+, iOS 14 / macOS 12 or newer. Foundation-only — no third-party dependencies.
  4. Create an app project in the dashboard and copy your API key.

One-line start

Initialize once at app start (e.g. in your App init / AppDelegate). initialize never throws; it is idempotent — only the first call takes effect:

import TransableSdk

Transable.initialize(apiKey: "tk_live_your_key_here", options: {
    var o = Transable.Options()
    o.appName = "my-app"
    // o.defaultLanguage = "de"   // else the user's OS locale is used
    return o
}())

Translate a string with one call. t() is synchronous and non-blocking: it returns the cached translation for the current language if known, otherwise your fallback while it queues the text for background translation:

label.text = Transable.t("save_button", "Save")

Re-apply your strings when background translations land:

NotificationCenter.default.addObserver(
    forName: Transable.translationsDidUpdateNotification,
    object: nil, queue: .main) { _ in
        self.updateLabels()   // re-read your t() strings and refresh the UI
    }

Batch & language switching

A whole screen's strings at once — index-aligned with the input; skipped or failed entries come back as the source text, and it never throws:

let out = await Transable.translateBatch(["Save", "Cancel", "[email protected]"])
// "[email protected]" comes back unchanged — SafeMode filters it BEFORE the
// network, so it never leaves the device.

Switch language at runtime (persisted across launches by default) and react via notifications:

Transable.setLanguage("de")                 // no-op before init
let code = Transable.currentLanguage        // active language code
let langs = Transable.availableLanguages    // [LanguageInfo] for a picker

Safe mode & offline cache

Safe mode is on by default and runs before any network I/O, so filtered text never leaves the device: it skips text under 2 chars or with no letters, emails, URLs, file paths, GUIDs, version strings, timestamped log lines, and code-like identifiers (PascalCaseNames) — while single words like "Save" still translate. Never pass the contents of user input fields to t() / translateBatch — the SDK has no UI layer, so that is on you.

Every translation is cached under Application Support/Transable/v1/, per language, content-addressed (10 MB per-language cap), and loaded on the next launch — so the second launch is translated instantly, even with no network. Identity results (translation equals source) are never written to disk.

It never crashes your app

One rule: no public entry point throws, blocks the caller for I/O, or crashes the app. Missing key, no network, HTTP 4xx/5xx, quota exhaustion, a malformed response — every failure degrades to the source-language text, with at most a message on Options.logger. A 401/402/403 disables translation for the session; a monthly-quota 429 pauses it until the next UTC day.

Questions or something broke? Contact us — include your Swift/Xcode version and the package version. Other platforms: Android, Flutter, or any language via the REST API. Full platform list on Apps SDK.