← すべての記事

Appleの Translation フレームワーク——無料、オンデバイス、見た目以上に鋭い

Appleの Translation フレームワークは、API キーもネットワーク通信も不要で、言語さえ端末に入っていればテキストをオンデバイスで無料翻訳します1。Core ML モデルを基盤としてシステムに同梱されており、Translate アプリと同じ翻訳エンジンをアプリから利用できます。これまでクラウド翻訳の請求書とプライバシー上の問いを伴っていた多言語機能が、ここでもまたコストほぼゼロに収まるわけです。そして Foundation Models フレームワーク6 と同じく、面白いのは順調に進む道筋ではありません。デモが飛ばす縁の部分——最初の翻訳を待たせる言語ダウンロード、何も言わずに動作を拒むシミュレータ、そして採用の形を規定する SwiftUI 専用のインターフェース——にこそ本質があります。

要点

  • 2つのインターフェース、2つの iOS バージョン。 translationPresentation は Apple 標準の翻訳ポップオーバーを表示します(iOS 17.4以降)。translationTask モディファイア経由で使う TranslationSession は、自前の UI の中でプログラム的な翻訳を実行します(iOS 18以降)2
  • プログラム的な翻訳は async translationTask のクロージャ内で TranslationSession が渡されるので、それを呼び出して1つの文字列またはまとめて複数を翻訳します3
  • 一括翻訳が第一級の機能。 リストを1回のリクエストで翻訳しつつ、各結果を入力と対応づけたまま受け取れます。1件ずつループして待つ必要はありません3
  • 翻訳 UI は SwiftUI 専用で、iOS シミュレータでは動きません。 どちらも身をもって知ることになりがちな点です。設計もテストもそれを前提に進めましょう4
  • オフラインとは、まずダウンロードすること。 その言語ペアの初回翻訳では言語バンドルがダウンロードされます。これは細部ではなく、こちらで扱うべき現実の UX の一場面です5
  • 押さえておく価値のある組み合わせ。ユーザー入力を Translation で翻訳し、その結果を Foundation Models で推論させれば、単一言語で書いたオンデバイスのエージェント機能が、端末にインストールできるあらゆる言語で動くようになります。

2つのインターフェース——システムのポップオーバーと自前の UI

このフレームワークには翻訳の方法が2つあり、どちらを選ぶかで意思決定のほとんどが決まります。

軽いほうは iOS 17.4 から使える translationPresentation です。ビューに付けて isPresented フラグをバインドし、テキストを渡すだけ。フラグが true になると、システムがコンテンツの上に独自の翻訳ポップオーバーをせり上げます2

.translationPresentation(isPresented: $showTranslation, text: selectedText)

翻訳ロジックは一切書きませんし、結果を受け取ることもありません。UI もインタラクションも Apple の管轄です。「この文章をユーザーに翻訳させたい」だけなら、これで機能は完結します。それ以上重いものに手を伸ばすのは無駄な労力でしょう。

プログラム的なほうは iOS 18 から使える TranslationSession で、translationTask モディファイア経由で到達します。このモディファイアは非同期クロージャを実行し、自分で呼び出すセッションを渡してくれるので、翻訳されたテキストがコードに戻ってきて、思いどおりに描画できます2

.translationTask(configuration) { session in
    let response = try await session.translate("Good morning")
    await MainActor.run { translated = response.targetText }
}

住み分けは明快です。translationPresentation は Apple の UI でユーザーに翻訳を見せるためのもの。TranslationSession は翻訳済みテキストを自分のデータとビューに取り込むためのもの。単発の「これを翻訳」を超える大半のアプリは、セッションのほうを選ぶことになります。

一括翻訳——ループではなく、リストを翻訳する

滑らかな機能とぎこちない機能を分けるのは、バッチ処理です。リスト(チャットのメッセージ、カタログの項目、ラベル一式)を翻訳するなら、ループで1件ずつ await してはいけません。TranslationSession はリクエストのバッチを受け取り、それぞれのリクエストに対応づけられたレスポンスを一度に返します3

.translationTask(configuration) { session in
    let requests = items.map { TranslationSession.Request(sourceText: $0.text, clientIdentifier: $0.id) }
    for try await response in session.translate(batch: requests) {
        store[response.clientIdentifier] = response.targetText
    }
}

肝心なのは clientIdentifier です。これがレスポンスに戻ってくるので、順序に頼らずに各翻訳を対応する行と結びつけられます。バッチ化はまた、ループで呼び出しごとのオーバーヘッドを払う代わりに、フレームワーク側が効率よく処理をスケジュールする余地も生みます。文字列1つを超えるなら、まとめて渡しましょう。

誰もスクリーンショットに撮らないオフラインの現実

きれいなデモをサポート案件に変えてしまう境界がここにあります。翻訳はオンデバイスで動きますが、その言語がまず端末に入っていなければなりません。特定の翻訳元→翻訳先ペアをアプリが初めて翻訳するとき、システムが言語バンドルをダウンロードします。これには時間とネットワーク接続が必要です5。ダウンロードへの配慮なしに翻訳を投げて結果を描画すれば、新しい言語ごとに初回だけ機能がフリーズしたように見えるでしょう。

意図的に扱ってください。フレームワークは言語の利用可否を確認し、必要になる前にペアを準備(ダウンロード)する手段を提供しています。おかげで「翻訳を準備中」という状態を見せたり、操作の途中で止まる代わりに落ち着いたタイミングで先読みダウンロードしたりできます5。考え方としては、言語ペアの初回翻訳を一度きりのアセットダウンロードとして扱うこと。実際そのとおりのものだからです。ダウンロードが存在する前提で UX を設計すれば、オフラインかつ無料という利点が効いてきます。無視すれば、その利点はフリーズの陰に隠れてしまいます。

遅く知ると半日を失う事実がもう2つあります。翻訳 UI のインターフェースは SwiftUI モディファイアなので、UIKit の画面から使うには(UIHostingController を介して)SwiftUI ビューをホストする必要があります。ただし UI を伴わない用途であれば TranslationSession を直接構築することもできます4。さらにこのフレームワークは iOS / iPadOS シミュレータでは動作しません。翻訳のテストは実機で行うことになります4。どちらも声高には書かれておらず、どちらも正面からぶつかりやすい点です。

Foundation Models と組み合わせる

持ち帰る価値のある結論は、このフレームワークをオンデバイススタックの他の部分と結びつけるところにあります。オンデバイスの言語処理の多くは、入力が自分のロジックとシステムモデルの得意な言語で書かれていることを前提にしています。現実のユーザーはそう協力してくれません。Translation フレームワークはその隙間を埋めます。ユーザーの入力を、機能が推論に使う言語へ翻訳し、翻訳後のテキストに対して Foundation Models の処理を走らせ、結果をもう一度翻訳して返すのです。

形は括弧です。翻訳して入れる、推論する、翻訳して出す。

// 1. translate the user's text into English (session configured for their language -> en)
let english = try await inboundSession.translate(userText).targetText
// 2. reason on-device, monolingually, in English
let summary = try await LanguageModelSession()
    .respond(to: "Summarize in one line: \(english)").content
// 3. translate the result back (a session configured for en -> their language)
let localized = try await outboundSession.translate(summary).targetText

サポート問い合わせの振り分け、メモの要約、意図の抽出——いずれも単一言語で一度書くだけで済みます。Foundation Models の呼び出しを Translation で挟むことで、端末にインストールできるあらゆる言語で動くようになるのです。方向が2つあるので、セッション設定も2つ使います(ユーザーの言語から英語へ、そして英語からユーザーの言語へ)。セッションは1つの言語ペアに対して構成されるためです。どちらの層もオンデバイスで、どちらも無料。端末から何も出ていきません。つまり多言語版は、単一言語版になかったプライバシーの代償もクラウドの請求も生みません。翻訳して入れる、推論する、翻訳して出す——この組み立てこそが、小さなオンデバイス機能を本当の意味でグローバルにします。そしてそれが可能なのは、その両側がどちらもローカルで、しかも無料で動くからにほかなりません。

使うべきでない場面

オンデバイス翻訳は無料でプライベート。アプリ内翻訳の既定の選択肢としては正解です。ただし、正直に言って向かない場面もいくつかあります。

  • 可能な限り高い翻訳品質、あるいは最も広い言語カバレッジが必要な場合。 オンデバイスのモデルは優秀ですが最高ではありませんし、インストールできる言語の集合は有限です。重い責任を伴う翻訳(法務、医療、公開コンテンツ)では、専用のクラウド翻訳サービスが品質と幅で依然として勝ります。
  • 初回利用時のダウンロードが許容できない場合。 ネットワークなしで初回起動から即座に動かなければならない機能なら、オンボーディング中に先読みダウンロードでもしない限り、ダウンロード要件だけでオンデバイス翻訳は失格になり得ます。
  • アプリが UIKit で SwiftUI をホストする余地がない、あるいはフローがシミュレータ上で動く必要がある場合(たとえば UI の自動テスト)。SwiftUI 専用とシミュレータ非対応という制約は、努力目標ではなく厳格な制限です。

このフレームワークは、オンデバイス系の道具箱の中でも地味ながら確かな当たりの一つです。本当に無料でプライベートな翻訳エンジンが手に入り、大半のアプリはひと息で導入できます。求められる技量は、このスタック全体が報いるものと同じ。どのインターフェースが合うか(システムのポップオーバーか自前のセッションか)を見極め、リストがあるならまとめて渡し、ダウンロードを無いものとして扱わずに織り込んで設計しましょう。そうすれば翻訳はクラウドへの依存であることをやめ、端末が無料でこなす他のすべてと組み合わせられるローカルな能力になります。

FAQ

Appleの Translation フレームワークは無料でオンデバイスですか?

はい。翻訳はオンデバイスで動作して無料であり、端末の外に何も出ません。そのためアプリ内翻訳の既定の選択肢として適しています。引き換えに、翻訳品質と言語カバレッジは業界最高というより「優秀」の水準にとどまるので、重い責任を伴う用途では今もクラウドサービスが望ましい場合があります。

なぜ最初の翻訳が固まったり、ダウンロードを求められたりするのですか?

翻訳はオンデバイスで動きますが、その言語ペアがまず端末に入っている必要があるためです。特定の翻訳元→翻訳先ペアを初めて翻訳するとき、システムが言語バンドルをダウンロードし、それには時間とネットワーク接続がかかります5。利用可否を確認し、必要になる前にペアを準備(先読みダウンロード)しておけば、操作の途中で止まる代わりに「準備中」の状態を見せられます。

アプリに翻訳を組み込む2つの方法とは?

SwiftUI のプレゼンテーションモディファイアによるシステムのポップオーバーか、UI を伴わない用途向けに直接構築した TranslationSession で駆動する自前の UI です4。インターフェースが SwiftUI モディファイアである以上、UIKit の画面からは UIHostingController を介して SwiftUI ビューをホストして到達します。

Appleの Translation フレームワークはシミュレータで動きますか?

いいえ。このフレームワークは iOS / iPadOS シミュレータでは動作しないため、翻訳のテストは実機で行います4。この制約は努力目標ではなく厳格な制限で、シミュレータ上の自動 UI テスト内で翻訳を使うことも同時に不可能になります。

Foundation Models を使った機能を、あらゆる言語で動かすには?

括弧で挟んでください。ユーザーの入力を、自分のロジックが推論する言語へ翻訳し、翻訳後のテキストに Foundation Models の処理を走らせ、その結果をもう一度翻訳して返します。方向が2つあるので TranslationSession の設定も2つ使います(ユーザーの言語から英語へ、そして英語からユーザーの言語へ)。セッションは1つの言語ペアに対して構成されるためです。どちらの層もオンデバイスで無料なので、多言語版にプライバシーの代償もクラウドの請求も生じません。

オンデバイス翻訳を使うべきでないのはどんなときですか?

可能な限り高い品質や最も広い言語カバレッジが必要なとき(法務、医療、公開コンテンツ)、ネットワークなしで初回起動から即座に動く必要があり先読みダウンロードもできないとき、あるいはフローがシミュレータ上で動く必要があるか、UIKit で SwiftUI をホストする余地がないときです。最後の制約は厳格な限界です。



  1. Apple Developer, “Translation” framework. Core ML モデルの上に構築された、システム提供のオンデバイス翻訳のためのファーストパーティフレームワーク。言語アセットのインストール後は、ネットワーク通信なしでローカルに翻訳を実行します。 

  2. Apple Developer, “translationPresentation(isPresented:text:attachmentAnchor:arrowEdge:replacementAction:)”(iOS 17.4以降)はビューの上にシステム標準の翻訳 UI を表示します。“translationTask(_:action:)”(iOS 18以降)は非同期クロージャを実行し、自前のインターフェースでプログラム的に翻訳するための TranslationSession を提供します。 

  3. Apple Developer, TranslationSession および TranslationSession.Requesttranslate(_:) は単一の文字列を扱います。バッチ API はリクエストの配列を受け取り、各リクエストが持つ clientIdentifier が対応するレスポンスに返るため、順序に依存せず結果を入力へ再び結びつけられます。 

  4. Translation フレームワークの翻訳 API は SwiftUI のビューモディファイア(translationTasktranslationPresentation)を通じて提供され、UIKit の入口はありません。UIKit の画面から使うには(たとえば UIHostingController を介して)SwiftUI ビューをホストします。またこのフレームワークは実機を必要とし、iOS シミュレータでは機能しません。Translation framework documentation および “Translating text within your app” を参照。 

  5. Apple Developer, “Translating text within your app” および LanguageAvailability。翻訳元→翻訳先の言語ペアの初回翻訳では、必要な言語アセットがダウンロードされます。フレームワークは言語の利用可否チェックと、ペアを事前に準備(ダウンロード)する手段を公開しており、アプリは初回利用時に止まるのではなくダウンロードのタイミングを管理できます。 

  6. オンデバイス機能の組み合わせに関する著者の関連分析: Apple Foundation Models: オンデバイス LLM フレームワークAppleの Foundation Models で実現するオンデバイス LLMWriting Tools API の採用。翻訳して入れる、推論する、翻訳して出すというパターンは、単一言語の Foundation Models 呼び出しを Translation で挟むことで、端末の外に出ることなくオンデバイス機能を多言語化します。 

関連記事

GenmojiとNSAdaptiveImageGlyph:iOS 18+でのインライン絵文字

Genmojiは属性付きテキスト内でNSAdaptiveImageGlyphとして提供されます。TextKit 2を使用するUITextViewのアプリでは、supportsAdaptiveImageGlyphを有効にし、シリアライズに対応…

1 分で読める

Image Playground API:SwiftUIシート、プログラムによるImage Creator、そしてスタイル制御

Image Playgroundはアプリに2つの経路を提供します。SwiftUIのimagePlaygroundSheetモディファイアと、コンセプトから画像を生成するプログラム的なImageCreator APIです。

2 分で読める

Claude Code Auto Mode Is Not a Security Boundary

Anthropic closed a working auto-mode bypass as Informative: the classifier is best-effort, not a guarantee. What actuall…

10 分で読める