LangCat is a remote localization and translation delivery platform for Apple apps. It allows you to manage, translate, and update your app's strings over-the-air (OTA) instantly—without waiting for App Store reviews.
Designed to mirror native Apple APIs, LangCat requires zero changes to your existing Localizable.xcstrings or Text() SwiftUI codebase. It just works.
Zero-Code Integration - Use native Text(), Label(), and String(localized:). LangCat intercepts strings automatically via method swizzling.
Over-The-Air Updates - Fix typos and release new languages globally in milliseconds using LangCat's global edge network.
Context-Aware AI - Automatically drafts new translations utilizing your App Store description and developer comments.
Xcode Plugin - Automatically uploads .xcstrings diffs to the LangCat dashboard.
Cross-Platform - Complete iOS, macOS, tvOS, watchOS, and visionOS support.
Safe Fallbacks - Works perfectly offline. If a translation fails to fetch, it instantly falls back to the cache or your local .xcstrings catalog.
| Platform | Minimum Target |
|---|---|
| iOS | 15.0+ |
| macOS | 12.0+ |
| tvOS | 15.0+ |
| watchOS | 8.0+ |
LangCat is available through Swift Package Manager.
- In Xcode, navigate to File > Add Package Dependencies...
- Enter the repository URL:
https://github.com/devsome-tech/lang-cat-ios.git - Decide your dependency rule (Up to Next Minor Version is recommended) and Add Package.
- Check the box for both
LangCatandLangCatSyncHelperif you want automatic build phase syncing.
Download your LangCat-Info.plist from your project dashboard at LangCat and drag it into your Xcode project. Make sure it is checked in your Copy Bundle Resources build phase.
Initialize LangCat as early as possible in your app's lifecycle to ensure translations are pulled before any views are rendered.
Using SwiftUI (Async Initialization): The recommended approach for SwiftUI is to display a loading or splash screen while waiting for the newest strings to download.
import SwiftUI
import LangCat
@main
struct MyApp: App {
@State private var isLangCatReady = false
var body: some Scene {
WindowGroup {
if isLangCatReady {
ContentView()
} else {
ProgressView("Checking for Translation Updates...")
.task {
// Blocks execution until latest dictionary is fetched OTA
try? await LangCat.initializeAsync()
isLangCatReady = true
}
}
}
}
}Using SwiftUI (Sync Initialization):
If you prefer not to block your UI with a loading screen, you can initialize LangCat synchronously in your App's init.
Warning
Because synchronous initialization fetches updates in the background, your views will render using your local string catalog first. Once the network fetch completes, LangCat triggers a UI update, causing any modified strings to visibly "flicker" to their new values.
import SwiftUI
import LangCat
@main
struct MyApp: App {
init() {
// Fetches in the background. UI will render immediately with local cached text.
LangCat.initialize()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}Using UIKit / AppDelegate (Sync Initialization):
If you have an older app, you can initialize synchronously in didFinishLaunchingWithOptions.
import UIKit
import LangCat
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions... ) -> Bool {
LangCat.initialize()
return true
}
}For SwiftUI Developers:
SwiftUI evaluates LocalizedStringKey purely at compile-time, meaning it bypasses normal string loading. To use LangCat over-the-air strings in SwiftUI, you have two options:
Simply prefix your standard UI components with LC. They act as drop-in replacements, and because they use @_disfavoredOverload, your strings are still automatically extracted to your Localizable.xcstrings catalog by Xcode!
LCText("hello_world") // LangCat will instantly replace this with the OTA translation
LCLabel("settings_title", systemImage: "gear")
LCButton("submit_btn") {
print("Tapped!")
}Available components: LCText, LCLabel, LCButton, LCSecureField, LCTextField, LCDatePicker, and LCToggle.
If you prefer not to use custom components, or you need to pass strings into standard native views that expect String, you can explicitly evaluate the text using LangCat.localize():
Text(LangCat.localize("hello_world"))
// Works perfectly within other native modifiers or conditional views
NavigationLink(LangCat.localize("continue_btn"), destination: NextView())For UIKit & Programmatic Developers:
LangCat automatically swizzles Bundle.localizedString, meaning your existing codebase requires zero changes.
// Automatically intercepted and translated over-the-air
let greeting = String(localized: "hello_world")
myLabel.text = NSLocalizedString("hello_world", comment: "")
// Or explicitly use the static method:
let explicit = LangCat.localize("hello_world")Whenever you make changes to your local strings or add new keys, you can manually trigger a synchronization directly from Xcode:
- Right-click on your Xcode project folder in the Project Navigator.
- Scroll down to LangCatSyncCommand in the context menu.
- Click it and grant sandbox permissions if prompted. This will immediately push your local
.xcstringschanges securely to LangCat.
Log in to langcat.dev to manage your projects, view AI-drafted strings, add team members, and hit Publish to send updates directly to your users' devices over the Edge.
Contributions are always welcome! Feel free to open issues or submit Pull Requests to help improve the SDK.
LangCat is released under the MIT license. See LICENSE for details.