{"id":22831513,"url":"https://github.com/phrase/ios-sdk","last_synced_at":"2025-04-23T19:42:50.893Z","repository":{"id":38420754,"uuid":"153472140","full_name":"phrase/ios-sdk","owner":"phrase","description":"Phrase Over the Air iOS SDK","archived":false,"fork":false,"pushed_at":"2025-03-14T15:30:31.000Z","size":45162,"stargazers_count":14,"open_issues_count":4,"forks_count":3,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-03-30T02:51:08.346Z","etag":null,"topics":["i18n","ios","l10n","localization","ota","over-the-air","phraseapp","translation"],"latest_commit_sha":null,"homepage":"https://phrase.com","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phrase.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-17T14:34:57.000Z","updated_at":"2025-03-14T15:30:35.000Z","dependencies_parsed_at":"2024-11-27T19:18:06.599Z","dependency_job_id":null,"html_url":"https://github.com/phrase/ios-sdk","commit_stats":{"total_commits":86,"total_committers":11,"mean_commits":7.818181818181818,"dds":0.4883720930232558,"last_synced_commit":"c3b1e5b7f9fcbc1f6b0e179142933877d55181b2"},"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phrase%2Fios-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phrase%2Fios-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phrase%2Fios-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phrase%2Fios-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phrase","download_url":"https://codeload.github.com/phrase/ios-sdk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250501294,"owners_count":21440996,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["i18n","ios","l10n","localization","ota","over-the-air","phraseapp","translation"],"created_at":"2024-12-12T20:26:23.091Z","updated_at":"2025-04-23T19:42:50.886Z","avatar_url":"https://github.com/phrase.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Phrase Over the Air (OTA) SDK for iOS\n\nPublish your translations faster and simpler than ever before. Stop waiting for the next deployment and start publishing all your translations in real-time directly in Phrase Strings.\n\nHead over to the Phrase Help Center to learn about this feature and how to use it in your apps: https://support.phrase.com/hc/en-us/articles/5804059067804\n\n## Instructions\n\nWith the SDK, the app regularly checks for updated translations and downloads them in the background.\n\n[Mac Catalyst](https://developer.apple.com/mac-catalyst) is also supported.\n\nThe SDK can be installed manually or via Swift Package Manager, Carthage or Cocoa Pods.\n\nExample [app](https://github.com/phrase/ios-demo-app)\n\n### Swift Package Manager\nAdd the public repository URL (https://github.com/phrase/ios-sdk/). Xcode automatically handles the rest of the installation.\n\n### Carthage\nAdd the following line into your Cartfile:\n\n```\nbinary \"https://raw.githubusercontent.com/phrase/ios-sdk/master/PhraseSDK.json\" ~\u003e 5.0.0\n```\n\nRun `carthage update --use-xcframeworks` and add the `PhraseSDK.xcframework` to your project as described in the [Carthage documentation](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos).\n\n### Cocoa Pods\nAdd the following line into your Podfile:\n\n```\npod 'PhraseSDK'\n```\nRun `pod install`. If new to CocoaPods, see their [documentation](https://guides.cocoapods.org/using/getting-started.html).\n\n### Manual installation\n\n1. Download the latest [release](https://github.com/phrase/ios-sdk/releases).\n2. Add `PhraseSDK.xcframework` in Xcode as the linked binary to the target.\n\n### Configuration\n\n1. Import PhraseSDK\n```\nimport PhraseSDK\n```\n\n2. Initialize the SDK\n```\nPhrase.shared.setup(\n  distributionID: \u003cDistribution ID\u003e,\n  environmentSecret: \u003cEnvironment Secret\u003e\n)\n```\n\n3. Update translations\n\nTo update localization files call `Phrase.shared.updateTranslation()`. This method will raises an exception if SDK is not correctly setup.\n\nTo configure OTA to use the US data center, set the host before calling `PhraseApp.shared.updateTranslation()` with `Phrase.shared.configuration.apiHost = .us.`\n\nCalling both functions within the `AppDelegate` in the `applicationDidFinishLaunchingWithOptions` method is recommended.\n\n### Objective-C\n\nIntegrate the SDK into the Objective-C application:\n\n```objective-c\n@import PhraseSDK;\n\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions\n{\n  [[Phrase shared] setDebugMode:true]; // Optional\n\n  [[Phrase shared] setupWithDistributionID:@\"Your Distribution ID\"\n                         environmentSecret:@\"Your Environment Secret\"];\n\n  // OR:\n  //\n  //  [[Phrase shared] setupWithDistributionID:@\"Your Distribution ID\"\n  //                         environmentSecret:@\"Your Environment Secret\"\n  //                                   timeout:10];\n\n  // Update translations using callback block:\n  [[Phrase shared] updateTranslationsWithCompletionHandler:^(BOOL updated, NSError* error){\n    NSLog(@\"Updated: %@\", updated ? @\"true\" : @\"false\");\n\n    if (error) {\n      NSLog(@\"Domain: %@ Code: %ld Message: %@\", error.domain, (long)error.code, error.localizedDescription);\n    } else {\n      NSLog(@\"No error\");\n    }\n\n    // Translate via bundle proxy:\n    NSString *translation = NSLocalizedString(@\"layouts.application.about\", @\"\");\n    NSLog(@\"NSLocalizedString via bundle proxy: %@\", translation);\n\n    // OR:\n    //\n    // Translate using fallback method:\n    NSString *otherTranslation = [[Phrase shared]\n                                  localizedStringForKey:@\"layouts.application.about\" value:NULL table:NULL];\n    NSLog(@\"Phrase.shared localizedStringForKey: %@\", otherTranslation);\n  }];\n\n  // OR:\n  //\n  // [[Phrase shared] updateTranslationsWithCompletionHandler:NULL]; // ignore result and errors (not recommended)\n\n  // [...] Your other code\n\n  return YES;\n}\n```\n\n### Disable swizzling\n\nTo disable swizzling, set `PhraseSDKMainBundleProxyDisabled` to **YES** in the `Info.plist` file.\n\nWhen swizzling is disabled, updated translations are no longer be displayed. The translation will still be synced if `updateTranslation` is called and can be accessed with the Phrase.`localizedString()` method.\n\n### App version handling\n\nTo determine which release should be returned the SDK requires a semantic version of the app so translations are updated.\n\nThe SDK attempts to get a semantic version the following way:\n\n- `CFBundleShortVersionString` is used if semantic.\n- If not, `CFBundleVersion` is used if semantic.\n- If both are not semantic, a combination of (`CFBundleShortVersionString.CFBundleVersion`) is used.\n\nIf `CFBundleShortVersionString` is missing or unable to be created with a semantic version together with `CFBundleVersion`, the SDK throws the `PhraseSetupError.appVersionNotSemantic` message.\n\n### Disable translation for multiple tables\n\nTo prevent OTA from translating any tables in the main iOS bundle other than the default `Localizable` table, set the following option:\n\n```\nPhrase.shared.configuration.ignoreOtherTables = true\n```\n\n### Callbacks\n\nAttach a callback handler to handle successful translation updates:\n\n```swift\ndo {\n   let updated = try await Phrase.shared.updateTranslation()\n} catch error {\n   ...\n}\n```\n\n### Debug mode\n\nIf further information is required, enable the debug mode to get additional logging of the `PhraseSDK.framework` into the console:\n\n```\nPhrase.shared.configuration.debugMode = true\n```\n\n### Set timeout for requests\n\nSet a timeout for the requests against Phrase by calling:\n\n```\nPhrase.shared.configuration.timeout = TimeInterval(20)\n```\n\nThe default timeout is 10 seconds and connections taking longer than 10 seconds will be closed.\n\n### Provide manual language override\n\nIf not using the system language as the locale, a different locale can be set in the init call. The locale code needs to be present in a release from Phrase:\n\n```\nPhrase.shared.configuration.localeOverride = \"en-US\"\n```\n\n### Fallback\n\nIn case new translations cannot be fetched from Phrase via the SDK, the latest translation files that the installation received are used. If the App never received new files from Phrase, it uses the compiled translation files of app. This prevents errors in case of any technical difficulties or networking errors. Keeping your translation files that are compiled into the app up to date with every release is recommended.\n\n### Troubleshooting\n\n**If translations are not being updated:**\n- Ensure distribution id and environment secret are correct.\n- Ensure a release was created on for the current app version.\n\nIf the wrong version of a translation is being used, ensure a release with the latest translations and the current app version is available.\n\n### Auditing\nThe SDK is closed source and can not be viewed or modified. If it is an organization requirement, audits can be provided. [Contact us](https://phrase.com/contact/) for more details if required.\n\n## Migration Guide: From Version 4.x.x to 5.x.x\n\n### Before You Begin\n\nHere’s what you need to know before updating to SDK `5.x.x`:\n\n- The minimum supported iOS version for SDK `5.x.x` is **iOS 15.0**.\n- SDK `5.x.x` requires **Swift 6.0** or later.\n\n---\n\n### Changed update function\n\nIn version `4.x.x`, the `updateTranslation` function was implemented using a callback-based approach.\n\n```swift\ndo {\n    try Phrase.shared.updateTranslation { result in\n        switch result {\n        case let .success(translationChanged):\n            if translationChanged {\n                logger.info(\"Translations changed\")\n            } else {\n                logger.debug(\"Translations remain unchanged\")\n            }\n        case let .failure(error):\n            logger.error(\"An error occurred: \\(error)\")\n        }\n    }\n} catch {\n    logger.error(\"Unexpected error: \\(error)\")\n}\n```\n\nIn version `5.x.x`, this method has been updated to leverage Swift's modern concurrency model and is now implemented using `async/await`.\n\n```swift\nTask {\n    do {\n        let updated = try await Phrase.shared.updateTranslation()\n        if updated {\n            logger.info(\"Translations changed\")\n        } else {\n            logger.debug(\"Translations remain unchanged\")\n        }\n    } catch {\n        logger.error(\"An error occurred: \\(error)\")\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphrase%2Fios-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphrase%2Fios-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphrase%2Fios-sdk/lists"}