Visual overview
Use the workflow to follow the task, and the architecture map to separate responsibilities. These are conceptual maps; the guide below defines implementation details and verification limits.
- Select source and target languages
- Check translation readiness
- Translate scoped text
- Handle unavailable language support
- Boundary 1Source text
- Boundary 2Translation session
- Boundary 3Translated presentation
Connected responsibilities, not a required class hierarchy or an execution trace.
Context
Load this when an app needs in-app text translation, system translation UI, custom translation flows, language-pair availability checks, model download handling, or multilingual user-generated content workflows.
Use the Translation framework for text translation. Use Natural Language for text analysis, Speech for speech-to-text, and Foundation Models only when translation is part of a broader generative workflow that still needs review.
Choosing the API
| Need | Use |
|---|---|
| Simple user-facing translation popover | translationPresentation(...) |
| Replace selected text with a translation | translationPresentation(..., replacementAction:) |
| Custom UI with one or more translated strings | translationTask(...) and TranslationSession |
| Batch translation | TranslationSession batch APIs |
| Check if languages are supported/installed | LanguageAvailability |
System translation UI
Use the system presentation when the product needs a familiar, lightweight translation affordance and does not need custom layout.
import SwiftUI
import Translation
struct MessageRow: View {
let text: String
@State private var showingTranslation = false
var body: some View {
Text(text)
.textSelection(.enabled)
.contextMenu {
Button("Translate") {
showingTranslation = true
}
}
.translationPresentation(
isPresented: $showingTranslation,
text: text
)
}
}
Rules:
- Attach the presentation to the view that owns the source text.
- Do not present translation for empty or already-redacted private text.
- Keep the original text available so users can compare.
Custom translation flow
Use a custom session when the app owns the layout, wants batch translation, or needs to store a translated draft.
import SwiftUI
import Translation
struct TranslationDraftView: View {
let sourceText: String
let source: Locale.Language?
let target: Locale.Language?
@State private var translatedText = ""
@State private var errorMessage: String?
var body: some View {
VStack(alignment: .leading) {
Text(sourceText)
Divider()
Text(translatedText.isEmpty ? "Translation unavailable" : translatedText)
}
.translationTask(source: source, target: target) { session in
do {
let response = try await session.translate(sourceText)
translatedText = response.targetText
} catch is CancellationError {
return
} catch {
errorMessage = error.localizedDescription
}
}
}
}
Rules:
- Keep translation work tied to view/task lifetime.
- Cancel or let SwiftUI cancel translation when inputs change.
- Show source and target language when user trust matters.
- Do not silently replace legal, medical, financial, or safety-critical text.
Language availability
Check availability before offering a custom translation control.
import Translation
func translationIsSupported(
from source: Locale.Language,
to target: Locale.Language
) async -> Bool {
let availability = LanguageAvailability()
let status = await availability.status(from: source, to: target)
switch status {
case .installed, .supported:
return true
case .unsupported:
return false
@unknown default:
return false
}
}
Rules:
supportedmay still require a model download before use.- Treat unsupported language pairs as a normal UI state.
- Test source-language auto-detection separately from explicit source language.
Product and privacy rules
- Explain when translated text is generated by the system.
- Let users inspect the original text.
- Do not use translation as a hidden moderation, compliance, or policy decision.
- Avoid storing translations unless the product needs persistence.
- If stored, mark the translated language and source text version.
- Handle mixed-language text, names, code snippets, and domain terms carefully.
Verification checklist
- [ ] Source and target languages are explicit or intentionally auto-detected.
- [ ]
LanguageAvailabilityis checked for custom flows. - [ ] Unsupported language pairs have a clear fallback.
- [ ] Model download or permission prompts are not surprising.
- [ ] Cancellation is tested when text/language changes.
- [ ] Original text remains reachable.
- [ ] Localized UI labels fit at accessibility text sizes.
- [ ] Privacy copy matches the actual data path.
Source anchor
Use only to verify API signatures and availability: https://developer.apple.com/documentation/translation