iOS18+のアプリで翻訳機能を追加する際、TranslationというAPIを使用することで
iOSに搭載されている翻訳機能のメニューを呼び出すことができ、言語パックがダウンロードされていればオフラインで翻訳可能です。
言語パックは、iPhone純正の翻訳アプリのプロパティからダウンロードしたり削除ができますし、自作アプリにて、ダウンロードを促すこともできます。
翻訳メニューを表示しない即時翻訳には、あらかじめ翻訳言語ペアがダウンロードされている必要があります。
おすすめすぎる⇨Swiftの教本
- ボタンで基本の翻訳機能を呼び出す、Swiftで翻訳するAPIのTranslationのコード
- ボタンで置き換え機能つき翻訳機能を呼び出す、Swiftで翻訳するAPIのTranslationのコード
- メニューではなく、即時翻訳機能を動かす、Swiftで翻訳するAPIのTranslationのコード ⚠️言語コードDL必要
- 配列の構造を一括で翻訳表示する Swiftで翻訳するAPIのTranslationのコード ⚠️言語コードDL必要
- 配列の構造を一括で翻訳表示する Swiftで翻訳するAPIのTranslationのコード ⚠️言語コードDL必要
- 翻訳で使用としている言語ペアで正常に翻訳できるかの確認
- 翻訳で使用としている言語ペアのダウンロードをユーザに促すメニューの表示
- iPhone本体の言語パックを削除したりダウンロードする方法
- 質問窓口
- 参考文献
ボタンで基本の翻訳機能を呼び出す、Swiftで翻訳するAPIのTranslationのコード
コンテンツビューの内容を下記ファイルの内容で上書きすることで動作可能です。
このコードで呼び出した翻訳機能の動作は下動画の通りです。
Swiftで翻訳窓を呼び出す最も基本的なコード pic.twitter.com/y6pGMlTNfP
— Rinboku (@rinboku_mental) October 17, 2024
言語の選択、翻訳結果のコピー、再生ボタンを押すことで読み上げをしてくれます。
iOS本体に言語パックがダウンロードされている言語同士の組み合わせであれば、オフラインで翻訳可能です。
翻訳機能をインポートして、
import Translation
翻訳機能起動フラグと翻訳文章を準備します。
//翻訳機能の立ち上げを管理するフラグ
@State private var showTranslation = false
//翻訳元のテキスト
@State var originalText = "Hallo, Welt!"
ボタンでフラグを管理し、親要素Vstackのモディファイア部分にフラグ監視による翻訳機能呼び出しの処理が書いてあります。
VStack {
//テキスト表示
Text(verbatim: originalText)
//翻訳機能立ち上げのフラグを切り替えるボタン
Button("Translate") {
showTranslation.toggle()
}
}.translationPresentation(isPresented: $showTranslation,
text: originalText)
.navigationTitle("Translate")
ボタンで置き換え機能つき翻訳機能を呼び出す、Swiftで翻訳するAPIのTranslationのコード
コンテンツビューの内容を下記ファイルの内容で上書きすることで動作可能です。
置き換え可能ver pic.twitter.com/hrt4clMSTN
— Rinboku (@rinboku_mental) October 17, 2024
先ほどの機能に加えて、置き換え機能を呼び出したことで、翻訳機能に「翻訳して置き換え」機能が表示されました。
{
//置き換えアクションここから
translatedText in
originalText = translatedText
//置き換えアクションここまで
}
メニューではなく、即時翻訳機能を動かす、Swiftで翻訳するAPIのTranslationのコード ⚠️言語コードDL必要
注意点としては、iPhone本体に翻訳で使用する言語パックがあらかじめダウンロードされている必要があります。
また、この機能はシミューレータやCanvasでは実行できません。(2024/10現在)
今回はenとjaで指定しています。
Translateボタンを押すと、テキスト入力されている言葉を翻訳します。
ボタンを押してすぐに翻訳セッションを開始 即時翻訳
— Rinboku (@rinboku_mental) October 17, 2024
ダウンロードされた言語パックが必要、シミュレータやコンテンツビューでは使用できない pic.twitter.com/HrKmBTAn13
ボタンで呼び出される下記の関数では、翻訳タスクの設定を指定しています。
- configuration という翻訳タスクの設定を保持する変数にnilを代入、情報が入っていたら一旦無効化
- その後、翻訳元言語と翻訳先言語を指定(今回は英語en⇨日本語ja)
private func triggerTranslation() {
guard configuration == nil else {
configuration?.invalidate()
return
}
configuration = .init(source: Locale.Language(identifier: "en"),
target: Locale.Language(identifier: "ja"))
}
ボタンを押されると、@Stateで定義されているconfigurationが書き換わる為VStackが再描画され
VStackにぶら下がっている翻訳機能が動きます。
.translationTask(configuration) { session in
do {
let response = try await session.translate(sourceText)
targetText = response.targetText
} catch {
}
}
配列の構造を一括で翻訳表示する Swiftで翻訳するAPIのTranslationのコード ⚠️言語コードDL必要
ビューに、食べ物の英語名が入った配列を表示しています。
translationボタンを押すと、配列の中身をいっぺんに翻訳後に置き換えます。いっぺんに置き換えるので、配列が長ければ長いほど表示にラグが表示ます。
リセットを押すと、元の初期言語の配列に戻します。
言語パックダウンロードが必要ですが、その分オフラインでも翻訳が可能ということになります。
下記動画では、機内モードで実行しています。
— Rinboku (@rinboku_mental) October 20, 2024
ContentViewでは各要素の表示と翻訳のコンフィグを設定し、ViewModelで定義した翻訳系の処理を呼び出しています。
下記の部分で、配列に対して翻訳をしており、今回の例では全ての翻訳が終わってからいっぺんに表示しています。
let responses = try await session.translations(from: requests)
foodItems = responses.map {
$0.targetText
}
配列の構造を一括で翻訳表示する Swiftで翻訳するAPIのTranslationのコード ⚠️言語コードDL必要
↑は配列全てが翻訳されたからのビュー更新という挙動でしたが、
以下は配列の内容を1個ずつ翻訳、ビューに反映していく挙動になります。
順次処理 pic.twitter.com/e3lx8lmAyU
— Rinboku (@rinboku_mental) October 20, 2024
下記の部分でインデックス番号ごとに翻訳処理を反映していくことで、配列を順番にリアルタイムで翻訳しています。
Task { @MainActor in
let requests: [TranslationSession.Request] = foodItems.enumerated().map { (index, string) in
.init(sourceText: string, clientIdentifier: "\(index)")
}
do {
for try await response in session.translate(batch: requests) {
guard let index = Int(response.clientIdentifier ?? "") else { continue }
foodItems[index] = response.targetText
print(response.targetText)
}
} catch {
//エラーハンドリング
}
}
翻訳で使用としている言語ペアで正常に翻訳できるかの確認
言語の組み合わせが翻訳可能かをチェックする方法です。
言語ペアのチェック pic.twitter.com/elIaINKH16
— Rinboku (@rinboku_mental) October 20, 2024
例えばソースコードを少しいじり、翻訳言語をイギリス英語⇨アメリカ英語にしてみると、
configuration = .init(source: Locale.Language(identifier: "en-GB"),
target: Locale.Language(identifier: "en-US"))
アプリ画面では何も動きがなく、コンソール側で言語ペアが不正なことによるエラーが発生します。
Client requested pair with valid source and target, but the pairing isn't supported: en_GB-en_US
Resolved source and target languages don't match supported locale pair, can't proceed with translation: Error Domain=TranslationErrorDomain Code=11 "(null)" UserInfo={sourceLocale=<_NSSwiftLocale: 0x301cbc4e0>, targetLocale=<_NSSwiftLocale: 0x301cbc460>}
Failed to determine all preflight information, won't proceed with translation: Error Domain=TranslationErrorDomain Code=11 "(null)" UserInfo={sourceLocale=<_NSSwiftLocale: 0x301cbc4e0>, targetLocale=<_NSSwiftLocale: 0x301cbc460>}
Client requested pair with valid source and target, but the pairing isn't supported: en_GB-en_US
Resolved source and target languages don't match supported locale pair, can't proceed with translation: Error Domain=TranslationErrorDomain Code=11 "(null)" UserInfo={sourceLocale=<_NSSwiftLocale: 0x301cbc4e0>, targetLocale=<_NSSwiftLocale: 0x301cbc460>}
Failed to determine all preflight information, won't proceed with translation: Error Domain=TranslationErrorDomain Code=11 "(null)" UserInfo={sourceLocale=<_NSSwiftLocale: 0x301cbc4e0>, targetLocale=<_NSSwiftLocale: 0x301cbc460>}
翻訳で使用としている言語ペアのダウンロードをユーザに促すメニューの表示
try await session.prepareTranslation()↑の命令を実行すると、翻訳セッションの言語ペアのダウンロードを開始できるメニューをアプリに表示します
言語ペアDLの要求 pic.twitter.com/m0cTKBSlmj
— Rinboku (@rinboku_mental) October 20, 2024
iPhone本体の言語パックを削除したりダウンロードする方法
アプリ「設定」起動 > メニュー「アプリ」 > 一覧からアプリ「翻訳」 > メニュー「ダウンロードされた言語」
質問窓口
ココナラにて、質問やご相談を受け付けしております。
ジャンルにかかわらずお気軽にメッセージをください。
ジャンルや内容を設定した専用出品を作成いたします。
参考文献
おすすめすぎる⇨Swiftの教本
コメント