---
updatedAt: 2025-12-19T09:16:06.000Z
agentTools:
  projectIndex: https://developers.transifex.com/llms.txt
---

# iOS

Transifex iOS SDK is a collection of tools for easily localizing iOS applications using [Transifex Native](https://www.transifex.com/native/).

The SDK can fetch translations over the air (OTA), manage an internal cache of translations, and work seamlessly without requiring the developer to change the app's source code.

Both Objective-C and Swift projects are supported, and iOS 10+ is required.

The package is built using Swift 5.3, as it currently requires a bundled resource (introduced in version 5.3) to be present. An update that will require a lower Swift version is currently WIP.

SwiftUI is also supported as of v2.0.3.

Learn more about [Transifex Native](https://developers.transifex.com/docs/native).

The full SDK documentation is available at <https://transifex.github.io/transifex-swift/>.

# Minimum Requirements

| Swift     | Xcode      | Platforms                                     |
| --------- | ---------- | --------------------------------------------- |
| Swift 5.3 | Xcode 15.4 | iOS 12.0, watchOS 4.0, tvOS 12.0, macOS 10.13 |

<Callout icon="📘" theme="info">
  Please make sure that the active developer directory points to the Xcode directory.

  To print the active developer directory path: xcode-select -p

  To switch the active developer directory path to Xcode:

  ```shell
   xcode-select -s /Applications/Xcode.app/Contents/Developer
  ```
</Callout>

# Usage

The SDK allows you to keep using the same localization hooks that the iOS framework provides, such as `NSLocalizedString`, `String.localizedStringWithFormat(format:...)`, etc., while taking advantage of the features that Transifex Native offers, such as OTA translations.

Below, you can find examples of the SDK initialization both in Swift and Objective-C for an app that uses the English language (`en`) as its source locale and it's localized both in Greek (`el`) and French (`fr`).

Keep in mind that in the sample codes below, you will have to replace the`<transifex_token>` and `<transifex_secret>` with the actual token and secret associated with your Transifex project and resource.

## SDK configuration (Swift)

To complete the setup, you will need to add "Transifex" as a package dependency in Xcode by selecting your project, heading over to the 'Swift Packages' section, tapping on the '+' button, and entering the public [repository URL](https://github.com/transifex/transifex-swift/) in the search field.

Initialize the SDK in your application using the `transifex_token` provided by your Transifex Native project.

Here is a basic configuration example in Swift:

```swift
import Transifex

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        TXNativeBuilder()
            .setLocales(TXLocaleState(sourceLocale: "en",
                                      appLocales: ["en", "el", "fr"]))
            .setToken("<transifex_token>")
            .build()

        return true
    }
}
```

And a more complex one, defining a policy for handling missing translations and providing a secret for programmatically pushing strings.

```swift
import Transifex

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
       TXNativeBuilder()
            .setLocales(TXLocaleState(sourceLocale: "en",
                                   appLocales: ["en", "el", "fr"]))
            .setToken("<transifex_token>")
            .setSecret("<transifex_secret>")
            .setMissingPolicy(TXCompositePolicy(
                TXPseudoTranslationPolicy(),
                TXWrappedStringPolicy(start: "[", end: "]")
            ))
            .build()

        /// Optional: Fetch translations on launch
        TXNative.fetchTranslations()
        return true
    }
}
```

For Swift projects, you  will also need to copy the `TXNativeExtensions.swift` file in your project and include it in all of the targets that call any of the following Swift methods:

* `String.localizedStringWithFormat(format:...)`
* `NSString.localizedStringWithFormat(format:...)`

If none of your application targets call any of the above methods, then you don't need to\
add this file to your project.

If you are also interested in setting up the SDK for your application extensions, you can look into the related section in the [documentation](https://transifex.github.io/transifex-swift/#application-extensions). The documentation also covers special cases, such as providing a custom NSURLSession or configuring logging.

## SDK configuration (Objective-C)

```objectivec
@import Transifex;

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    TXLocaleState *localeState = [[TXLocaleState alloc] initWithSourceLocale:@"en"
                                                                  appLocales:@[
                                                                    @"en",
                                                                    @"el",
                                                                    @"fr"
                                                                  ]
                                                       currentLocaleProvider:nil];
    TXPseudoTranslationPolicy *pseudoTranslationPolicy = [TXPseudoTranslationPolicy new];
    TXWrappedStringPolicy *wrappedStringPolicy = [[TXWrappedStringPolicy alloc] initWithStart:@"["
                                                                                          end:@"]"];
    TXCompositePolicy *compositePolicy = [[TXCompositePolicy alloc] init:@[
        pseudoTranslationPolicy,
        wrappedStringPolicy
    ]];

    [[[[[TXNativeBuilder.new
         setLocales:localeState]
         setToken:@"<transifex_token>"]
         setSecret:@"<transifex_secret>"]
         setMissingPolicy:compositePolicy]
         build];

    /// Optional: Fetch translations on launch
    [TXNative fetchTranslations:nil
                           tags:nil
                         status:nil
              completionHandler:nil];

    return YES;
}
```

<br />

## Supported localization methods

On runtime, Transifex SDK overrides / swizzles the following localization

````swift
@@ -281,8 +255,10 @@ let locales = TXLocaleState(sourceLocale: "en",
                            appLocales: ["en", "el"],
                                                 currentLocaleProvider: CustomLocaleProvider())

TXNativeBuilder()
    .setLocales(locales)
    .setToken("<token>")
    .build()
```

````

<br />

````objectivec
@@ -306,8 +282,10 @@ TXLocaleState *locales = [[TXLocaleState alloc] initWithSourceLocale:@"en"
                                                          appLocales:@[@"en", @"el"]
                                               currentLocaleProvider:customLocale];

[[[TXNativeBuilder.new
   setLocales:locales]
   setToken:@"<token>"]
   build];
```

````

It is worth noting that the iOS SDK manages an internal cache of translations in the file system of the translations fetched over-the-air.

## Fetching translations

When `fetchTranslations` is called, the SDK downloads translations for all locales defined in the initialization of `TXNative`. If successful, it updates the cache.

While the example shows `fetchTranslations` being called at application launch, developers can choose when to call this method based on their needs (for example, when the application returns to the foreground or when internet connectivity is established).

### Common questions about fetchTranslations

1. **Rate limiting and multiple requests**\
   The `fetchTranslations` method includes a callback that reports errors, including server-side errors like HTTP 429 (rate limiting) and when the SDK reaches its retry limit (20 attempts). Developers can implement custom error handling based on these callbacks.

2. **Runtime updates and user notifications**\
   The `fetchTranslations` method provides an optional callback that reports downloaded translations and any errors during the pull process. To notify users about new translations (e.g., showing a banner requesting app restart), you can cache and compare the translation structure returned by the callback.

3. **Customizing when translations are fetched**\
   While the example shows `fetchTranslations` being called at launch, you can call it at any appropriate time, such as:
   * When the application returns to the foreground.
   * When internet connectivity is established.
   * At any other strategic point in your application's lifecycle.

<Callout icon="📘" theme="info">
  For code examples and implementation details, check our [iOS SDK documentation](https://transifex.github.io/transifex-swift/).
</Callout>

## Pushing source content programmatically

To push the source translations to CDS, you will first need to prepare an array of `TXSourceString` objects that will hold all the necessary information required for CDS.

You can refer to the `TXSourceString` class for more information, or you can look at the\
list below:

* `key` (required): The key of the source string, generated via the public `txGenerateKey()`\
  method.
* `sourceString` (required): The actual source string.
* `developerComment` (optional): An optional comment provided by the developer to\
  assist the translators.
* `occurrencies` (required): A list of relative paths where the source string is located in\
  the project.
* `tags` (optional): An optional list of tags that will appear alongside the source string in\
  the Transifex dashboard.
* `characterLimit` (required): The character limits the translations must stay under, provided as context for each string.
* `context` (optional): An optional list of strings that provide more context.

After building an array of `TXSourceString` objects, use the `pushTranslations` method to push them to CDS. You can optionally set the `purge` argument to `true` (defaults to `false`) to replace the entire resource content. The completion handler can be used to notify asynchronously whether the request was successful.

## Pushing source content using the CLI

Use the [Transifex CLI-swift](https://github.com/transifex/transifex-swift-cli) to collect all your app content and send it to Transifex for translation. To perform this action, you will need the `transifex_secret` token that you created in your Transifex Native project.

```shell
txios-cli push --token <transifex_token> --secret <transifex_secret> --project MyApp.xcodeproj
```

You may also use the `--excluded-files` option in the `push` command, providing a space-separated list of filenames to be excluded from processing.

Example:

```shell
txios-cli push ... --excluded-files ExcludedFile1.strings ExcludedFile2.strings
```

For more details and additional options, please refer to the documentation related to [Transifex CLI-swift]().

### Pushing pluralizations

Pluralization rules both on the new String Catalogs (`.xcstrings`) and the old Strings Dictionary (`.stringsdict`) formats are generally supported.

When pushed to CDS, single, plural rules are converted to the ICU format. In contrast, more complex rules (device variations, substitutions, combinations) are converted to an intermediate XML format and back to the proper format when the SDK populates its cache during initialization.

The only variation-related limitation concerns the Width variants [1](https://help.apple.com/xcode/mac/current/#/devaf8b4090a) [2](https://developer.apple.com/documentation/xcode/creating-width-and-device-variants-of-strings).

## Display translated content

By default, the iOS Native SDK uses the current locale set on the iOS device and listens for changes to the current locale.

Developers can override this setting by providing a custom class that conforms to the [TXCurrentLocaleProvider](https://transifex.github.io/transifex-swift/Protocols/TXCurrentLocaleProvider.html) protocol and returns a specific locale code in the [currentLocale()](https://transifex.github.io/transifex-swift/Protocols/TXCurrentLocaleProvider.html#/c:@M@Transifex@objc\(pl\)TXCurrentLocaleProvider\(im\)currentLocale) method.

This custom locale provider can then be provided during the initialization of the [TXLocaleState](https://transifex.github.io/transifex-swift/Classes/TXLocaleState.html) object as its final argument ([currentLocaleProvider](https://transifex.github.io/transifex-swift/Classes/TXLocaleState.html#/c:@M@Transifex@objc\(cs\)TXLocaleState\(im\)initWithSourceLocale:appLocales:currentLocaleProvider:)):

Swift example:

```swift
class CustomLocaleProvider : TXCurrentLocaleProvider {
    func currentLocale() -> String {
        return "el"
    }
}

let locales = TXLocaleState(sourceLocale: "en",
                            appLocales: ["en", "el"],
                            currentLocaleProvider: CustomLocaleProvider())

TXNative.initialize(locales: locales,
                    token: "<token>")
```

Objective-C example:

```objectivec
@interface CustomLocaleProvider : NSObject <TXCurrentLocaleProvider>

@end

@implementation CustomLocaleProvider

- (NSString *)currentLocale {
    return @"el";
}

@end

/// ...

TXLocaleState *locales = [[TXLocaleState alloc] initWithSourceLocale:@"en"
                                                          appLocales:@[@"en", @"el"]
                                               currentLocaleProvider:customLocale];

[TXNative initializeWithLocales:locales
                          token:@"<token>"];
```

It is worth noting that the iOS SDK manages an internal cache of translations in the file system of the translations fetched over the air.

You can find more about [caching in the documentation](https://transifex.github.io/transifex-swift/#standard-cache).

## Standard Cache

The default cache strategy used by the SDK, if the developer provides no other cache, is the `TXStandardCache.getCache()`. The standard cache operates by using the publicly exposed classes and protocols from the cache.swift file of the SDK, so it's easy to construct another cache strategy if desired.

The standard cache is initialized with a memory cache (`TXMemoryCache`) that manages all cached entries in memory. After the memory cache gets initialized, it tries to look up if there are any already stored cache files in the file system using the `TXDiskCacheProvider` class:

* The first cache provider is the bundle cache provider, which looks for an already created cache file in the app's main application bundle that the developer may have offered.
* The second cache provider looks for a cache file in the application sandbox directory (using the optional app group identifier argument if provided) in case the app has already downloaded the translations from the server during a previous launch.

Those two providers are used to initialize the memory cache using an update policy (`TXCacheUpdatePolicy`) which is optionally provided by the developer and defaults to the `replaceAll` value. After the cached entries have updated the memory cache, the cache is ready to be used.

Whenever new translations are fetched from the server using the `fetchTranslations()` method, the standard cache is updated, and those translations are stored as-is in the file system in the same cache file used by the aforementioned second cache provider so that they are available on the next app launch.

### Alternative cache strategy

You might want to update the internal memory cache when the newly downloaded translations are available. Always update all entries so that the updated policy can also be omitted.

To achieve that, you can create a new  `TXDecoratorCache` subclass or create a method that returns a `TXCache` instance, just like in the `TXStandardCache.getCache()`case.

```swift
func getCustomCache() -> TXCache {
    return TXFileOutputCacheDecorator(
        fileURL: ...,
        internalCache: ...
    )
}
```

This way, whenever the cache is updated with the new translations from the  `fetchTranslations()` method, the `update()` call will propagate to the internal `TXMemoryCache` and update all of its entries.

## Application Extensions

To add the SDK to an application extension target, be sure to include the `Transifex` library in the 'Frameworks and Libraries' section of the General settings of the application extension you are working on.

Furthermore, in case Xcode produces a "No such module 'Transifex'" error on the `import Transifex` statements of the extension files, be sure to add the `$(SRCROOT)` path in the 'Framework Search Paths' setting under the Build Settings of the application extension target.

To make the Transifex SDK cache file visible by both the extension and the main application targets, you would need to enable the App Groups capability in both the main and extension targets and use an existing or create a new app group identifier. Then, you would need to initialize the Transifex SDK with the `TXStandardCache` passing that app group identifier as the `groupIdentifier` argument.

## URL Session

By default, a temporary URLSession object with no cache is used for all requests made to the CDS service.

For more control over the networking layer, an optional `session` parameter is exposed in the `initialize()` method of the `TXNative` cache, so developers can offer their own session object if that's desirable (e.g., for more fine-grained cache control, certificate pinning, etc.).

## Logging

By default, warning and error messages produced by the SDK are logged in the console using the `print()` method. Developers can offer a class that conforms to the `TXLogger` protocol so that they can control the logging mechanism of the SDK or make use of the public `TXStandardLogHandler` class to control the log level printed to the console.

# Limitations

## String(localized:) initializers

While the String(localized:) family of initializers ([1](https://github.com/transifex/transifex-swift/blob/devel/README.md#user-content-fn-1-8525ffc0dfaee7763c7a4c830ee43f60) [2](https://github.com/transifex/transifex-swift/blob/devel/README.md#user-content-fn-2-8525ffc0dfaee7763c7a4c830ee43f60) [3](https://github.com/transifex/transifex-swift/blob/devel/README.md#user-content-fn-3-8525ffc0dfaee7763c7a4c830ee43f60) [4](https://github.com/transifex/transifex-swift/blob/devel/README.md#user-content-fn-4-8525ffc0dfaee7763c7a4c830ee43f60) [5](https://github.com/transifex/transifex-swift/blob/devel/README.md#user-content-fn-5-8525ffc0dfaee7763c7a4c830ee43f60) [6](https://github.com/transifex/transifex-swift/blob/devel/README.md#user-content-fn-6-8525ffc0dfaee7763c7a4c830ee43f60)) is supported through the TXNativeExtensions.swift file, we do not recommend using them due to their reliance on reflection and regular expressions to extract the LocalizationValue properties.

Developers can choose to switch between the Reflection and the Regular Expression extraction logic via the extractionType argument of the TXNative.translate(...) methods used in the TXNativeExtensions.swift file.

Warning

Risk of Breaking Changes

Apple may change the internal representation of the LocalizationValue struct at any time, which would break the implemented logic.

We strongly recommend using any of the following supported methods instead of the String(localized:) initializers:

* NSLocalizedString(\_ key:tableName:bundle:value:comment:)
* NSString.localizedStringWithFormat( *format:,* args:)
* String.localizedStringWithFormat( *format:,* arguments:)
* \[NSString localizedStringWithFormat:]
* NSBundle.localizedString(forKey:value:table:)
* \[NSBundle localizedAttributedStringForKey:value:table:]
* Any SwiftUI view initializer that accepts a LocalizedStringKey struct.

If you understand the risks, you may uncomment the relevant section in TXNativeExtensions.swift after adding the file to your application’s target(s). However, we strongly advise using the recommended alternatives whenever possible.

## Special cases

Localized strings that are being managed by the OS are not supported by the Transifex SDK:

* Localized entries found in the  `Info.plist` file (e.g., Bundle Display Name and Usage Description strings) that are included in the `InfoPList.strings` file.
* Localized entries found in the `Root.plist` of the `Settings.bundle` of an app that exposes its Settings to the iOS Settings app that are included in the `Root.strings` file.

## ICU support

Currently, SDK supports only the platform rendering strategy, so translations will trigger the error policy if the ICU rendering strategy is passed during the initialization.

## Internet connectivity

If the device cannot access the Internet when `fetchTranslations()` method is called the internal logic of the SDK, which doesn't retry or wait for a connection to preserve resources. Developers can detect when internet connectivity is regained to re-call that method.

# Sample applications

You can find two [sample applications](https://github.com/transifex/transifex-native-sandbox/tree/master/ios) that use the Transifex iOS SDK in Swift and Objective-C.

# Video resources

* [How to install the Transifex Native iOS SDK](https://youtu.be/VBndzVRAqjA)
* [How to push strings with Transifex Native in iOS](https://youtu.be/pCl7g18-xpo)
* [How to bundle translations with Transifex Native in your iOS app](https://youtu.be/7tGwU-om-Es)
* [How to preview translations with Transifex Native in iOS](https://youtu.be/toAq9JoPm6E?feature=shared)

For a quick overview of iOS-supported Native features, check out the [Transifex Native Feature Matrix]().