Exploring Translation: Getting Source Language in iOS 18 Using NaturalLanguage
Over the past two months, I have been exploring Apple's Translate framework for my app, LyricsLink.
I have run into some interesting cases that I want to share with you that might be save you some time later in the future.
Working with TranslationSession Configuration
When you are working with translations, Apple suggests using nil
for the source language. This lets the framework figure out what language you are starting with:
let configuration = TranslationSession.Configuration(source: nil, target: selectedLanguage)
This works great most of the time. The framework is good enough to figure out the language you are dealing with.
Sometimes songs mix languages. I ran into cases where songs were mostly in Korean, but had enough English that the Translation framework got confused. It could not automatically identify the main language.
NLLanguageRecognizer
In those cases, using NLLanguageRecognizer
to find the dominant language helped to continue with the translation process. Here is how to use it:
private func identifyLanguage(of lyrics: String) -> Locale.Language? {
let recogniser = NLLanguageRecognizer()
recogniser.processString(lyrics)
guard let language = recogniser.dominantLanguage else {
return nil
}
return Locale.Language(identifier: language.rawValue)
}
In my initial exploration, I used the approach demonstrated in the WWDC session, which involves creating an NLLanguageRecognizer
instance, processing the string, and then getting the dominant language. However, there is an even simpler method you can use.
There is a class method on NLLanguageRecognizer
called dominantLanguage(for:)
that you can directly use without creating an NLLanguageRecognizer
instance:
private func identifyLanguage(of lyrics: String) -> Locale.Language? {
guard let language = NLLanguageRecognizer.dominantLanguage(for: lyrics) else {
return nil
}
return Locale.Language(identifier: language.rawValue)
}
Yay, you managed to shave off two whole lines of code!
Moving Forward
I have certainly learned a lot about the Translate framework while working on LyricsLink.
The error that got me exploring for a workaround was theunableToIdentifyLanguage
error. This one shows up when the Translation framework cannot figure out what language your text is in. You might see this error try to get the language availability status:
let status = try await LanguageAvailability().status(for: lyrics, to: targetLanguage)
Here is how you can handle the unableToIdentifyLanguage
error:
do {
let status = try await LanguageAvailability().status(for: lyrics, to: targetLanguage)
// Process the status here
} catch let error as TranslationError {
if error == .unableToIdentifyLanguage {
// The framework could not identify the language automatically
// Use NLLanguageRecognizer here
if let detectedLanguage = identifyLanguage(of: lyrics) {
// Now you have the detected language, you can proceed with translation
print("Detected language: \(detectedLanguage)")
} else {
print("Still unable to identify language")
}
} else {
// Handle other TranslationError cases
print("Translation error: \(error)")
}
} catch {
// Handle any other errors
print("Unexpected error: \(error)")
}
This code tries to get the translation status. If it cannot identify the language, it uses the identifyLanguage
function that we wrote earlier using NLLanguageRecognizer
to detect the language.
Remember, TranslationSession
and LanguageAvailability
are new in iOS 18.0, iPadOS 18.0, and macOS 15.0.
Happy translating!