Using the Translation framework for language-to-language translation

Using the Translation framework for language-to-language translation

Learn how to translate text to a specific language using on-device models with the Translation framework.

The article "Translating text in your SwiftUI app with the Translation framework" covers adding a presentation overlay to enable basic translation in an application.

To have a deeper translation integration in our app we can utilize the translationTask(_:action:) modifier from the Translation framework. This modifier allows us to translate our app's content using local ML models even when offline.

Setting the Translation Session class

Begin by importing the Translation framework and declaring a property to store an TranslationSession.Configuration object. It will provide the system with the source language and the target language.

struct ContentView: View {
    
    @State var text = "We can’t wait to see what you will Create with Swift."
    @State var translationSession: TranslationSession.Configuration?
    
    var body: some View {
        ...
    }

}

Now create the interface elements for this example, including a Text centralized in the view and a Button on the navigation bar. Create a private method called performTranslation() to be called when the user taps the button and triggers the translation task.

struct ContentView: View {
    
    @State var text = "We can’t wait to see what you will Create with Swift."
    @State var translationSession: TranslationSession.Configuration?
    
    var body: some View {
        NavigationStack {
            
            VStack {
                Text(text)
                    .font(.title3)
                    .multilineTextAlignment(.center)
            }
            
            .toolbar {
                Button {
                    self.performTranslation()
                } label: {
                    Image(systemName: "translate")
                }
            }
            
        }
    }
    
    private func performTranslation() {
        // 
    }
}

Add the following code to the performTranslation() method:

private func performTranslation() {
    if translationSession == nil {
        translationSession = TranslationSession.Configuration(
            source: nil,
            target: nil
        )
    } else {
        self.translationSession?.invalidate()
    }
}

When performing a translation task a new TranslationSession.Configuration is created, setting up both the target and source set to nil for now. The Translation framework will automatically detect the source language and translate based on the user's preferred language when we don't provide a source locale. If translationSession is not nil, the existing translation session is invalidated by calling the invalidate() method.

Another option is to specify a source or target language by passing a Locale object. For example, if we want to translate to Italian, we can assign Italian as the target language by passing the corresponding Locale object.

translationSession = TranslationSession.Configuration(
    source: nil,
    target: Locale.Language(languageCode: .italian)
)

Translating the content

With TranslationSession.Configuration object ready, use the translationTask(_:action:) modifier. This enables us to translate the content when the View appears or when the translation configuration value changes and is not nil.

The translationTask(_:action:) requires two parameters:

import SwiftUI
import Translation
struct ContentView: View {
    
    @State var text = "We can’t wait to see what you will Create with Swift."
    @State var translationSession: TranslationSession.Configuration?
    
    var body: some View {
        NavigationStack {
            
            VStack { ... }
            
            .toolbar { ... }
            
            .translationTask(translationSession) { session in
                do {
                    let response = try await session.translate(text)
                    self.text = response.targetText
                } catch let error {
                    print(error)
                }
            }
            
        }
    }
    
    private func performTranslation() { ... }
}

The modifier is receiving the translationSession object, set as nil initially, and the action closure uses the translation session to perform one or multiple translations.

The translate(_:) method of the translation session is responsible for translating a single string of text and returning the translation result object containing the translated text in the targetText property.

The first time you perform a translation the user will be prompted to download the translation models on their phone. The TranslationSession class uses on-device ML models to perform translations and these models are shared with all apps on the system (including the native Translate app).

If the user has already downloaded languages before, your app can use them as well. If not, the system will prompt the user to download specific languages.

If you already know the languages the user needs and you set them as the source and target of the TranslationSession.Configuration object, you can use the prepareTranslation() method to download them in advance, instead of waiting for the user to press the translate button

.translationTask(translationSession) { session in
    do {
        try await session.prepareTranslation()
        
        let response = try await session.translate(text)
        self.text = response.targetText
    } catch let error {
        print(error)
    }
}