No description
Find a file
2026-07-17 09:46:17 +02:00
SlpSdk.xcframework Release version 1.0.8 2026-07-17 09:46:17 +02:00
Package.swift Release version 1.0.8 2026-07-17 09:46:17 +02:00
README.md Release version 1.0.8 2026-07-17 09:46:17 +02:00

SlpSdk

The Slp SDK for iOS provides dynamic, over-the-air (OTA) localization updates.

Requirements

  • Xcode 26+
  • iOS 15+

Installation

Add SlpSdk via Xcode: File > Add Package Dependencies... using the repository URL https://sit-mobile-services-internal.git.onstackit.cloud/slp-public/slp-ios-framework.git

Imports

Import Slp functionality where you need it

import SlpSdk

Downloading translations

Download translation updates using Slp.downloadOrUpdateTranslations(withSettings: settings).
By default, this method only downloads data for the currently selected locale to save bandwidth.
You can change the selected locale prior to downloading by setting Slp.selectedLocale or Slp.selectedLocaleIdentifier.
If the selected locale does not exactly match the available Slp locales, the method utilizes Apple's
in-house locale matching logic to find the best suitable alternative (for example, resolving 'de-DE' for 'de').
To download translation data for all locales in your Slp project, set the downloadAllLanguages
flag to true in the provided Settings instance.

let settings = Settings(
    projectIdentifier: "YOUR_PROJECT_IDENTIFIER", // Settings > General > Identifier in the Slp UI
    platformIdentifier: "YOUR_PLATFORM_IDENTIFIER", // Settings > Platforms > Platform ID in the Slp UI
    myApiClientId: "YOUR_MY_API_CLIENT_ID", // The "Key" of your localization-export-service consumer in my.api.schwarz
    downloadAllLanguages: false // Set to true to download all available locales
)

Task {
    let results = await Slp.downloadOrUpdateTranslations(withSettings: settings)
    
    for result in results {
        guard let localeIdentifier = result.localeIdentifier else {
            print("A global non locale specific error occurred.")
            continue
        }

        switch result.status {
        case .updated:
            print("Successfully updated \(localeIdentifier)")
        case .skipped:
            print("Skipped \(localeIdentifier) (Checksum matched, already up to date)")
        case .failed(let error):
            print("Failed to download \(localeIdentifier): \(error)")
        }
    }
}

Managing the selected language

Change the app's language on the fly without requiring a restart using Slp.selectedLocale or Slp.selectedLocaleIdentifier.
If those properties are never set they default to Bundle.main.preferredLocalizations.first or "en"

Slp.selectedLocale = Locale(identifier: "de-DE")
Slp.selectedLocaleIdentifier = "de-DE"

Accessing translations

Method 1: Direct Sdk Access

let simpleTranslation = Slp.localizedString(forKey: "simple_key")
let pluralizedOrTemplatedTranslation = Slp.localizedString(forKey: "pluralized_or_templated_key", withArgs: 1, 2)

Method 2: Build your own translation helpers

Pass Slp.selectedLocaleSlpBundle, Slp.selectedLocaleMainBundle and Slp.selectedLocale directly into native Apple components

static func localizedString(forKey key: String, withArgs args: CVarArg...) -> String {
    var localizedString = String(localized: String.LocalizationValue(key), bundle: Slp.selectedLocaleSlpBundle)
    if localizedString == key {
        // Fallback in case a translation is not in the slp bundle but is in your main app bundle
        localizedString = String(localized: String.LocalizationValue(key), bundle: Slp.selectedLocaleMainBundle)
    }
    
    if args.isEmpty {
        return localizedString
    }
    
    return String(format: localizedString, locale: Slp.selectedLocale, arguments: args)
}

Method 3: Bundle swizzling

Step 1: Extend your String struct to enable correct locale selection for pluralization and formatting. This will shadow Apple's String.localizedStringWithFormat which can only use the device locale.

import Foundation
import SlpSdk

public extension String {
    static func localizedStringWithFormat(_ format: String, _ arguments: CVarArg...) -> String {
        return String(format: format, locale: Slp.selectedLocale, arguments: arguments)
    }
}

Step 2: Call Slp.exchangeBundleWithSlpBundle() once early in your app lifecycle

import SwiftUI
import SlpSdk

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
    ) -> Bool {
        Slp.exchangeBundleWithSlpBundle()
        return true
    }
}

Step 3: Use NSLocalizedString as you're used to

let simpleTranslation = NSLocalizedString("simple_key", comment: "")

let formatString = NSLocalizedString("pluralized_key", comment: "")
let pluralizedOrTemplatedTranslation = String.localizedStringWithFormat(formatString, 1, 2)

Notifications

React to the following NotificationCenter events to keep your UI in sync:

  • .slpTranslationsDidUpdate: Fired whenever at least one locale bundle was successfully updated via a download.
  • .slpLocaleDidChange: Fired when Slp.selectedLocale or Slp.selectedLocaleIdentifier is changed.

Example:

import SwiftUI
import SlpSdk

@main
struct SlpSdkTesterApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @State private var redrawTrigger = UUID()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .id(redrawTrigger)
                .onReceive(NotificationCenter.default.publisher(for: .slpTranslationsDidUpdate)) { _ in
                    redrawTrigger = UUID()
                }
                .onReceive(NotificationCenter.default.publisher(for: .slpLocaleDidChange)) { _ in
                    redrawTrigger = UUID()
                }
        }
    }
}