Creating a Swift Package in Xcode is a great way to modularize your code, promote reusability, and manage dependencies across projects, its best when you want code that can work across iOS, macOS, watchOS, tvOS, and even server-side Swift. In this artical we will stick to integrate package with iOS app only.
Step 1: Create a Swift Package 1: Open Xcode → File → New → Package. 2: Name it AITranslationKit. 3: Choose Library and select Swift as the language. 4: Click Create and save it in your project directory.
Step 2: Implement AI Translation Logic
import Foundation
public class AITranslation {
private var apiKey: String
private var baseURL: String
public init(deepLapiKey: String,
baseURL: String = "https://api-free.deepl.com/v2/translate") {
self.apiKey = deepLapiKey
self.baseURL = baseURL
}
public func deepLTranslate(texts: [String],
sourceLanguage: String? = nil,
targetLanguage: String,
completion: @escaping (_ results: [String]?, _ error: Error?) -> Void) {
guard let url = URL(string: baseURL) else {
// throw error
let error = NSError(domain: "", code: 601, userInfo: [NSLocalizedDescriptionKey: "Invalid baseURL"])
completion(nil, error)
return
}
// Build the body with multiple `text` parameters
var params = "auth_key=\(apiKey)&target_lang=\(targetLanguage.uppercased())"
if let source = sourceLanguage { // you can specify source language
params += "&source_lang=\(source.uppercased())"
}
// get all string to make a query string
for text in texts {
if let encodedText = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
params += "&text=\(encodedText)"
}
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpBody = params.data(using: .utf8)
URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
completion(nil, error)
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let translations = json["translations"] as? [[String: Any]] {
let results = translations.compactMap { $0["text"] as? String }
completion(results, nil)
} else {
let error = NSError(domain: "", code: 600, userInfo: [NSLocalizedDescriptionKey: "Unable to parse response"])
completion(nil, error)
}
} catch {
completion(nil, error)
}
}.resume()
}
}
Step 3: Add Localized String Support so that its localised string can be accessed with minimum effor and in clear way. 1: In this package, create a LocalizationManager.swift file, this helps handle localized .strings files in your app.
import Foundation
public class LocalizationManager {
public static func getLocalisedString(key: String, translatorComment: String = "") -> String {
return NSLocalizedString(key, comment: translatorComment)
}
}
Step 4: Make the Package Available for Other Apps 1: Open Package.swift and modify the target dependencies as:
import PackageDescription
let package = Package(
name: "AITranslation",
platforms: [
.iOS(.v12) // or later
],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "AITranslation",
targets: ["AITranslation"]),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "AITranslation"),
.testTarget(
name: "AITranslationTests",
dependencies: ["AITranslation"]),
]
)
Step 5: Use the Package in Your App 1: Open your iOS app project in Xcode. 2: Go to File → Add Packages Depandencies and add the AITranslationKit package from your local repo or GitHub. 3: Use it in your app as below:
import UIKit
import AITranslation
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Do any additional setup after loading the view.
if let languageIdentifier = Locale.preferredLanguages.first {
let components = Locale.Components(identifier: languageIdentifier)
if let twoLetterIdentifier = components.languageComponents.languageCode?.identifier {
code = identifier
print("Two-letter language code: \(twoLetterIdentifier)")
if twoLetterIdentifier != "en" {
getTranslationFor(targetLanguage: twoLetterIdentifier)
}
}
}
}
func getTranslationFor(targetLanguage: String) {
let translator = TITranslation(deepLapiKey: "c38f01d5-70f8-4844-a066-cc14cdd13226:fx")
// List of keys from app localizable.string file
let stringsToTranslate = [LocalizationManager.getLocalisedString(key: "txt_app_title"),
LocalizationManager.getLocalisedString(key: "txt_subtitle"),
LocalizationManager.getLocalisedString(key: "txt_declaration_lbl"),
LocalizationManager.getLocalisedString(key: "txt_reset")]
translator.deepLTranslate(texts: stringsToTranslate,
targetLanguage: targetLanguage) { results, error in
if let results = results { //success
let translationDic = Dictionary(uniqueKeysWithValues: zip(stringsToTranslate, results))
DispatchQueue.main.async {
//now for each item in dic pic required one and assign back to label or text object
self.lblTitle?.text = translationDic["txt_app_title".localized]
self.lblSubtitle?.text = translationDic["txt_subtitle".localized]
self.lblDescription?.text = translationDic["txt_declaration_lbl".localized]
self.btnReset?.setTitle(translationDic["txt_reset".localized], for: .normal)
}
} else {
//show alert that something went wrong with translation
print("Error while translating values: \(String(describing: error?.localizedDescription))")
}
}
}
}
Thasts how you can make you wrapper usable across multiple apps.
Creating a Swift Package in Xcode is a great way to modularize your code, promote reusability, and manage dependencies across projects, its best when you want code that can work across iOS, macOS, watchOS, tvOS, and even server-side Swift. In this artical we will stick to integrate package with iOS app only.
Step 1: Create a Swift Package 1: Open Xcode → File → New → Package. 2: Name it AITranslationKit. 3: Choose Library and select Swift as the language. 4: Click Create and save it in your project directory.
Step 2: Implement AI Translation Logic
import Foundation
public class AITranslation {
private var apiKey: String
private var baseURL: String
public init(deepLapiKey: String,
baseURL: String = "https://api-free.deepl.com/v2/translate") {
self.apiKey = deepLapiKey
self.baseURL = baseURL
}
public func deepLTranslate(texts: [String],
sourceLanguage: String? = nil,
targetLanguage: String,
completion: @escaping (_ results: [String]?, _ error: Error?) -> Void) {
guard let url = URL(string: baseURL) else {
// throw error
let error = NSError(domain: "", code: 601, userInfo: [NSLocalizedDescriptionKey: "Invalid baseURL"])
completion(nil, error)
return
}
// Build the body with multiple `text` parameters
var params = "auth_key=\(apiKey)&target_lang=\(targetLanguage.uppercased())"
if let source = sourceLanguage { // you can specify source language
params += "&source_lang=\(source.uppercased())"
}
// get all string to make a query string
for text in texts {
if let encodedText = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
params += "&text=\(encodedText)"
}
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpBody = params.data(using: .utf8)
URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
completion(nil, error)
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let translations = json["translations"] as? [[String: Any]] {
let results = translations.compactMap { $0["text"] as? String }
completion(results, nil)
} else {
let error = NSError(domain: "", code: 600, userInfo: [NSLocalizedDescriptionKey: "Unable to parse response"])
completion(nil, error)
}
} catch {
completion(nil, error)
}
}.resume()
}
}
Step 3: Add Localized String Support so that its localised string can be accessed with minimum effor and in clear way. 1: In this package, create a LocalizationManager.swift file, this helps handle localized .strings files in your app.
import Foundation
public class LocalizationManager {
public static func getLocalisedString(key: String, translatorComment: String = "") -> String {
return NSLocalizedString(key, comment: translatorComment)
}
}
Step 4: Make the Package Available for Other Apps 1: Open Package.swift and modify the target dependencies as:
import PackageDescription
let package = Package(
name: "AITranslation",
platforms: [
.iOS(.v12) // or later
],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "AITranslation",
targets: ["AITranslation"]),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "AITranslation"),
.testTarget(
name: "AITranslationTests",
dependencies: ["AITranslation"]),
]
)
Step 5: Use the Package in Your App 1: Open your iOS app project in Xcode. 2: Go to File → Add Packages Depandencies and add the AITranslationKit package from your local repo or GitHub. 3: Use it in your app as below:
import UIKit
import AITranslation
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Do any additional setup after loading the view.
if let languageIdentifier = Locale.preferredLanguages.first {
let components = Locale.Components(identifier: languageIdentifier)
if let twoLetterIdentifier = components.languageComponents.languageCode?.identifier {
code = identifier
print("Two-letter language code: \(twoLetterIdentifier)")
if twoLetterIdentifier != "en" {
getTranslationFor(targetLanguage: twoLetterIdentifier)
}
}
}
}
func getTranslationFor(targetLanguage: String) {
let translator = TITranslation(deepLapiKey: "c38f01d5-70f8-4844-a066-cc14cdd13226:fx")
// List of keys from app localizable.string file
let stringsToTranslate = [LocalizationManager.getLocalisedString(key: "txt_app_title"),
LocalizationManager.getLocalisedString(key: "txt_subtitle"),
LocalizationManager.getLocalisedString(key: "txt_declaration_lbl"),
LocalizationManager.getLocalisedString(key: "txt_reset")]
translator.deepLTranslate(texts: stringsToTranslate,
targetLanguage: targetLanguage) { results, error in
if let results = results { //success
let translationDic = Dictionary(uniqueKeysWithValues: zip(stringsToTranslate, results))
DispatchQueue.main.async {
//now for each item in dic pic required one and assign back to label or text object
self.lblTitle?.text = translationDic["txt_app_title".localized]
self.lblSubtitle?.text = translationDic["txt_subtitle".localized]
self.lblDescription?.text = translationDic["txt_declaration_lbl".localized]
self.btnReset?.setTitle(translationDic["txt_reset".localized], for: .normal)
}
} else {
//show alert that something went wrong with translation
print("Error while translating values: \(String(describing: error?.localizedDescription))")
}
}
}
}
Thasts how you can make you wrapper usable across multiple apps.