diff --git a/docs.js b/docs.js index ce4e0ab00..88d94820d 100644 --- a/docs.js +++ b/docs.js @@ -35,6 +35,24 @@ const docs = [ }, }, ], + [ + '@docusaurus/plugin-content-docs', + { + id: 'ios-sdk', + path: 'ios-sdk', + routeBasePath: 'ios-sdk', + sidebarPath: require.resolve('./sidebariOSSdk.js'), + lastVersion: 'current', + includeCurrentVersion: true, + editUrl: 'https://github.com/tolgee/documentation/tree/main', + versions: { + current: { + banner: 'none', + label: '1.x.x', + }, + }, + }, + ], [ '@docusaurus/plugin-content-docs', { diff --git a/ios-sdk/about.mdx b/ios-sdk/about.mdx new file mode 100644 index 000000000..e98c2c554 --- /dev/null +++ b/ios-sdk/about.mdx @@ -0,0 +1,51 @@ +--- +id: about +title: Tolgee iOS SDK Overview +slug: / +description: Overview of Tolgee iOS SDK with Over‑the‑Air (OTA) localization updates and how to get started. +--- + +> NOTE: +> For managing static translations in your repository, consider using the [Tolgee CLI](/tolgee-cli/installation). + +Tolgee iOS (and macOS) SDK makes it possible to deliver new translations from your Tolgee project directly to your application. This means you don’t need to release a new version through the App Store just to update localizations. With over-the-air updates, translations can be refreshed seamlessly in your app without requiring a manual update. + +## Why use it + +- __Avoid releases for copy changes__: Ship translation fixes and new languages without a new app build. +- __Faster iteration__: Product/localization teams can push improvements instantly and validate in production. +- __SwiftUI support__: You can still use features such as overwriting locales for your SwiftUI previews. +- __Resilient by default__: Works offline with caching and resource fallbacks; fewer blank strings. + +## What you can do + +- __Over‑the‑Air (OTA) updates__: Deliver translations via CDN (Cloud or self‑host) with caching. +- __UIKit and SwiftUI support__: with hooks for reactive updates of translations. +- __Fallbacks and preloading__: The SDK will fallback to loading a translation bundled with your app in case of any error. +- __Hosting options__: Tolgee Cloud CDN or your own CDN. +- __Works with advanced codebases__: you can still have your translations split into multiple files and have them stored in a separate framework/package. + +## Demo apps + +- [__SwiftUI demo__](https://github.com/tolgee/tolgee-mobile-swift-sdk/tree/main/Examples/TolgeeSwiftUIExample) +- [__UIKit demo__](https://github.com/tolgee/tolgee-mobile-swift-sdk/tree/main/Examples/TolgeeUIKitExample) + +## Compatibility + +The SDK currently supports iOS 16.0+ and macOS 13.0+ with integration via Swift Package Manager (SPM). + +> NOTE: +> Please reach out to us if you need support for older OS versions or integration through CocoaPods, we are happy to look into it. + +## Get started + +- __Installation__: Install and configure the SDK — [Installation](./get_started.mdx) +- __SwiftUI compatibility__: Learn how Tolgee iOS SDK works with your SwiftUI code — [SwiftUI](./swiftui.mdx) +- __NSLocalizedString swizzling__: Learn how to achieve zero config integration by enabling method swizzling — [Swizzling](swizzling.mdx) +- __Advanced usage__: Tips and tricks for debugging and using the SDK with advanced codebases — [Advanced usage](./advanced.mdx) + +## Next steps + +- Install and configure the SDK: [Installation](./get_started.mdx) +- Connect your app to the Tolgee Platform and manage translations collaboratively: [Platform docs](../platform/) +- Generate or manage static strings with CLI: [Tolgee CLI](/tolgee-cli/installation) diff --git a/ios-sdk/advanced.mdx b/ios-sdk/advanced.mdx new file mode 100644 index 000000000..e7ae6c33c --- /dev/null +++ b/ios-sdk/advanced.mdx @@ -0,0 +1,58 @@ +--- +id: advanced +title: Advanced usage +description: Tips and tricks for debugging and using the SDK with advanced codebases. +--- + +### Custom tables/namespaces +Tolgee iOS SDK supports loading of local translations from multiple local tables by providing the `table` parameter. When using `.xcstrings` files, the names of the tables match the names of your files without the extension. You do not need to provide the table name when loading strings stored in the default `Localizable.xcstrings` file. + +To have the OTA updates working properly, make sure that you have enabled namespaces for your Tolgee project and that you have created namespaces matching the names of your local tables. + +```swift +// Initialize with multiple namespaces for better organization +Tolgee.shared.initialize( + cdn: cdnURL, + namespaces: ["common", "auth", "profile", "settings"] +) + +// Use translations from specific namespaces +let commonGreeting = Tolgee.shared.translate("hello", table: "common") +// or for SwiftUI +TolgeeText("hello", table: "common") +``` + +## Custom bundles + +You may have your strings resources stored in a dedicated XCFramework or a Swift Package. + +```swift +let bundle: Bundle = ... // access the bundle + +// Use the SDK directly +let commonGreeting = Tolgee.shared.translate("hello", bundle: bundle) +// or for SwiftUI +TolgeeText("hello", bundle: bundle) +``` + +## Listening for updates + +Tolgee provides a hook to allow the consumer of the SDK to be notified about when the translation cache has been updated. + +```swift +Task { + for await _ in Tolgee.shared.onTranslationsUpdated() { + // update your UI + } +} +``` + +## Log forwarding +Tolgee allows forwarding of logs that are printed to the console by default. +You can use this feature to forward errors and other logs into your analytics. + +```swift +for await logMessage in Tolgee.shared.onLogMessage() { + // Here you can forward logs from Tolgee SDK to your analytics SDK. +} +``` \ No newline at end of file diff --git a/ios-sdk/get_started.mdx b/ios-sdk/get_started.mdx new file mode 100644 index 000000000..e0f9fb8fb --- /dev/null +++ b/ios-sdk/get_started.mdx @@ -0,0 +1,106 @@ +--- +id: get_started +title: Get started +description: How to install Tolgee iOS SDK and basic usage instructions. +--- + +## Platform Support + +| Platform | Minimum Version | +|----------|----------------| +| iOS | 16.0+ | +| macOS | 13.0+ | +| tvOS | 16.0+ | +| watchOS | 6.0+ | + +## Requirements + +- **Swift:** 6.0+ +- **Xcode:** 16.3+ + +## Adding the SDK + +Add to your `Package.swift`: + +```swift +dependencies: [ + .package(url: "https://github.com/tolgee/tolgee-mobile-swift-sdk", from: "1.0.0") +] +``` + +Or through Xcode: +1. File → Add Package Dependencies... +2. Enter: `https://github.com/tolgee/tolgee-mobile-swift-sdk` +3. Choose version and add to your target + +## Initialization and configuration + +Initialize the SDK with your [CDN URL](/platform/projects_and_organizations/content_delivery), typically in your AppDelegate or similar startup location: + +```swift +import Tolgee + +let cdnURL = URL(string: "https://cdn.tolgee.io/your-project-id")! +Tolgee.shared.initialize(cdn: cdnURL) +``` +:::warning + +Make sure that the format for your CDN files is set to `Apple SDK` in your Tolgee project developer/cdn settings. +Learn more about [Tolgee Content Delivery](/platform/projects_and_organizations/content_delivery) feature. + +::: + +> **TIP**: +> Refer to our SwiftUI and UIKit [examples](https://github.com/tolgee/tolgee-mobile-swift-sdk/tree/main/Examples) for a complete setup. + + +You can customize the initialization with additional parameters: +```swift +// Initialize with specific language and namespaces +Tolgee.shared.initialize( + cdn: URL(string: "https://cdn.tolgee.io/your-project-id")!, + language: "es", // Force Spanish instead of auto-detection + namespaces: ["buttons", "errors", "onboarding"], // Organize translations + enableDebugLogs: true // Enable detailed logging for development +) +``` + +## Fetching remote translations +You have to explicitly call the `fetch` method to fetch translations from the CDN. +```swift +await Tolgee.shared.remoteFetch() +``` + +## Basic Translation + +```swift +// Simple string translation +let title = Tolgee.shared.translate("app_title") + +// Translation with arguments +let welcomeMessage = Tolgee.shared.translate("welcome_user", "John") +let itemCount = Tolgee.shared.translate("items_count", 5) +let nameAndAge = Tolgee.shared.translate("My name is %@ and I'm %lld years old", "John", 30) +``` +> **NOTE:** +> Strings with multiple pluralized parameters are currently **not supported**, +> for example `Tolgee.shared.translate("I have %lld apples and %lld oranges", 2, 3)` + +## Thread-safety + +Tolgee SDK is designed to be used synchronously on the main actor (except the `fetch` method). Access to the SDK from other actors generally has to be awaited. + +```swift +Task.deattached { + // notice that the call has to be awaited outside of the main actor + let str = await Tolgee.shared.translate("key") +} +``` + +## Next steps + +- __SwiftUI compatibility__: Learn how Tolgee iOS SDK works with your SwiftUI code — [SwiftUI](./swiftui.mdx) +- __NSLocalizedString swizzling__: Learn how to achieve zero config integration by enabling method swizzling — [Swizzling](swizzling.mdx) +- __Advanced usage__: Tips and tricks for debugging and using the SDK with advanced codebases — [Advanced usage](./advanced.mdx) + + diff --git a/ios-sdk/swiftui.mdx b/ios-sdk/swiftui.mdx new file mode 100644 index 000000000..5f1761bf4 --- /dev/null +++ b/ios-sdk/swiftui.mdx @@ -0,0 +1,76 @@ +--- +id: swiftui +title: SwiftUI +description: How to use Tolgee iOS SDK with SwiftUI. +--- + +## SwiftUI support + +Tolgee works great with SwiftUI, including previewing views in different localizations using SwiftUI previews. + +You can use the `TolgeeText` component which will automatically use the injected locale on iOS 18.4+ +```swift +import SwiftUI +import Tolgee + +struct ContentView: View { + var body: some View { + TolgeeText("welcome_title") + } +} + +#Preview("English") { + ContentView() + .environment(\.locale, Locale(identifier: "en")) +} + +#Preview("Czech") { + ContentView() + .environment(\.locale, Locale(identifier: "cs")) +} +``` + +or use a version of the `translate` method that accepts `locale` param on iOS 18.4 and newer. The older implementation will fall back to the system language. + +```swift +struct ContentView: View { + @Environment(\.locale) var locale + + var body: some View { + if #available(iOS 18.4, *) { + Text(Tolgee.shared.translate("welcome_title", locale: locale)) + } else { + Text(Tolgee.shared.translate("welcome_title")) + } + } +} + +#Preview("English") { + ContentView() + .environment(\.locale, Locale(identifier: "en")) +} + +#Preview("Czech") { + ContentView() + .environment(\.locale, Locale(identifier: "cs")) +} +``` + +## Reactive updates + +Tolgee offers a convenience utility that automatically triggers a redraw of a view when the translations cache has been updated. + +```swift +struct ContentView: View { + + // This will automatically re-render the view when + // the localization cache is updated from a CDN. + @StateObject private var updater = TolgeeSwiftUIUpdater() + + var body: some View { + VStack { + TolgeeText("My name is %@ and I have %lld apples", "John", 3) + } + } +} +``` \ No newline at end of file diff --git a/ios-sdk/swizzling.mdx b/ios-sdk/swizzling.mdx new file mode 100644 index 000000000..46db365bd --- /dev/null +++ b/ios-sdk/swizzling.mdx @@ -0,0 +1,31 @@ +--- +id: swizzling +title: Swizzling NSLocalizedString +description: How to achieve (almost) zero-effort integration with existing NSLocalizedString usage. +--- + +## Swizzling of Apple's APIs +Tolgee optionally supports swizzling of `Bundle.localizedString`, which is being used internally by `NSLocalizedString` function. + +In order to enable swizzling, set enviromental variable `TOLGEE_ENABLE_SWIZZLING=true` in your scheme settings. Refer to our UIKit example to see it in action. + +Following calls will then be backed by the Tolgee SDK: +```swift +Bundle.main.localizedString(forKey: "welcome_message") +NSLocalizedString("welcome_message", comment: "") +``` + +Regular string parameters are supported as well: +```swift +let userName = "John" +let welcomeMessage = String(format: NSLocalizedString("welcome_user", comment: ""), userName) +``` + +> **NOTE:** +> Plural strings are currently not supported and will fall back to using the string bundled with the app. + +:::warning + +Method swizzling is a powerful technique, but it can lead to unexpected behavior if not used carefully, especially if there is multiple SDKs swizzling the same APIs. Make sure to test your application thoroughly after enabling swizzling. + +::: diff --git a/navbar.js b/navbar.js index e8638937b..b29662f29 100644 --- a/navbar.js +++ b/navbar.js @@ -23,6 +23,10 @@ module.exports.navbar = { label: 'JavaScript SDK', to: '/js-sdk', }, + { + label: 'iOS SDK', + to: '/ios-sdk', + }, { label: 'Android SDK', to: '/android-sdk', diff --git a/platform/faq.mdx b/platform/faq.mdx index 9c3e8e89f..520b5bb54 100644 --- a/platform/faq.mdx +++ b/platform/faq.mdx @@ -24,6 +24,10 @@ In most cases, translators don't know the context of what they're translating. T Close -> near or dismiss? +### Does Tolgee support iOS apps? + +Yes. Tolgee provides a native [iOS SDK](/ios-sdk) that integrates with your app and supports SwiftUI. + ### Does Tolgee support Android apps? Yes. Tolgee provides a native [Android SDK](/android-sdk) that integrates with your app and supports Jetpack Compose. diff --git a/platform/getting_started/about_tolgee.mdx b/platform/getting_started/about_tolgee.mdx index d1ffbbcab..bdc838918 100644 --- a/platform/getting_started/about_tolgee.mdx +++ b/platform/getting_started/about_tolgee.mdx @@ -15,7 +15,7 @@ No more looking for keys in your source code, no more editing localization files ## Features -- **Developer-friendly** - Tolgee is designed to be easy to integrate with your application. There are integrations for web frameworks via the [Tolgee JS SDK](/js-sdk) and for Android apps via the [Tolgee Android SDK](/android-sdk). +- **Developer-friendly** - Tolgee is designed to be easy to integrate with your application. There are integrations for web frameworks via the [Tolgee JS SDK](/js-sdk) and for native mobile apps via the [Tolgee iOS SDK](/ios-sdk) and [Tolgee Android SDK](/android-sdk). - **Easy to use** - Tolgee is easy to use for developers, but also for translators, so you can easily involve your translators into your localization process. - **Open-source** - Tolgee is open-source, you can contribute to the project on our [GitHub repository](https://github.com/tolgee/tolgee-platform). You can also [host your own instance](/platform/self_hosting/getting_started) of Tolgee, so you can have full control over your data. - **Free** - Our **cloud version** includes Business plan with 20 000 strings is **free for any open-source projects**. For commercial projects, you can use Tolgee for free up to 1000 strings. For more information, see [pricing](https://tolgee.io/pricing). diff --git a/platform/getting_started/translation_content.mdx b/platform/getting_started/translation_content.mdx index 1f23173bf..e9d9ce877 100644 --- a/platform/getting_started/translation_content.mdx +++ b/platform/getting_started/translation_content.mdx @@ -30,6 +30,10 @@ In production mode, you should use data exported from the Tolgee platform. To export the translation files, see [exporting translations](/platform/projects_and_organizations/export). Then provide the data via Tolgee configuration options described in [Providing static data](/js-sdk/providing-static-data). +## iOS SDK + +Tolgee provides a native [iOS SDK](/ios-sdk) with a great support for SwiftUI that integrates with your app and supports OTA updates of strings from a CDN. + ## Android SDK Tolgee also provides an [Android SDK](/android-sdk) for native Android apps, including Jetpack Compose support. Follow the Android docs to: diff --git a/platform/integrations/other_integrations.mdx b/platform/integrations/other_integrations.mdx index c9d7a5812..dae99858c 100644 --- a/platform/integrations/other_integrations.mdx +++ b/platform/integrations/other_integrations.mdx @@ -23,7 +23,7 @@ Currently, Tolgee has integrations for **all major JS frameworks** such as: - [React Native](/js-sdk/integrations/react/react_native) - [Vanilla JS](/js-sdk/integrations/vanilla/installation). -For mobile native apps, see our [mobile docs](/android-sdk). +For mobile native apps, see our [iOS](/ios-sdk) and [Android](/android-sdk) docs. **Other integrations:** diff --git a/sidebariOSSdk.js b/sidebariOSSdk.js new file mode 100644 index 000000000..31814f388 --- /dev/null +++ b/sidebariOSSdk.js @@ -0,0 +1,9 @@ +module.exports = { + someSidebar: [ + 'about', + 'get_started', + 'swiftui', + 'swizzling', + 'advanced', + ], +}; \ No newline at end of file diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 20b7086af..c689b480f 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -72,9 +72,9 @@ function Home() { />