Meet the Translation API
System Frameworks 进阶 20m

认识 Translation API

Meet the Translation API

2024年6月10日

在 Apple 官方观看视频

一句话判断

Apple 终于把系统级的翻译能力开放给了第三方 App,而且提供了从”零代码”到”完全自定义”的两层 API,覆盖了绝大多数翻译场景的需求。

这场 Session 讲了什么

Apple 把 Translate App 背后的 ML 模型通过两个层次的 API 暴露给开发者。第一层是 .translationPresentation() ——一个 SwiftUI modifier,加一行代码就能在你的 App 里弹出一个系统翻译浮层,体验和系统全局翻译一模一样。第二层是 TranslationSession ——一个更灵活的 async API,让你拿到翻译结果后自己决定怎么展示,支持批量翻译、语言检测、自动语言选择。

两个 API 共享同一套设备端 ML 模型。语言包已经在系统中存在(用户下载过的),你的 App 可以直接使用。如果用户没下载某个语言,框架会自动弹出下载提示。下载在后台进行,用户离开你的 App 也不影响。这套翻译能力支持 iOS、iPadOS 和 macOS,覆盖了主流语言。

值得深挖的点

TranslationSession 的设计哲学:被动实例化

TranslationSession 你不能自己创建实例,只能通过 .translationTask() modifier 的闭包回调来获取。这个设计不是随意为之——因为翻译在某些情况下需要展示 UI(比如语言包下载提示),框架必须和 SwiftUI 的视图生命周期绑定。

这个设计带来一个直接的后果:触发翻译的方式是修改 TranslationSession.Configuration。配置变了,闭包就重新执行。如果你要翻译新内容但不想改语言设置,必须手动调用 configuration.invalidate() 来”扰动”配置。这个 invalidate 模式在 SwiftUI 生态里不算常见,初看有点别扭,但想想也有道理——SwiftUI 需要一个明确的信号才能重新执行 translationTask 闭包。

performAll 是另一个设计亮点。当你同时发多个翻译请求时,performAll 返回的是一个 AsyncStream,每个请求完成就立即回调,不用等全部完成。对批量翻译场景(比如一个评论区里 20 条不同语言的评论),这意味着用户可以看到”滚动的翻译结果”而不是漫长的空白等待。

设备端翻译 vs 云端翻译的取舍

Apple 把翻译模型完全放在设备端,这意味着:没有网络也能用、不把用户文本发给服务器、延迟更低。但代价是模型大小受限、语言覆盖面不如 Google Translate 或 DeepL 这些云端方案。

对于 App 开发者来说,这个取舍其实很清晰:如果你的翻译需求是”让用户理解内容”而不是”专业级翻译质量”,设备端方案够用了。评论翻译、菜单翻译、商品描述翻译——这些场景对翻译精度要求不高,但离线能力和隐私保护是实打实的加分项。如果你的 App 面向旅游或隐私敏感场景,这个 API 的价值会更大。

代码片段

最简单的翻译——一行 modifier

场景:给评论列表加一个”翻译”按钮,点击弹出系统翻译浮层。

// 一行代码加上翻译功能
.translationPresentation(isPresented: $showsTranslation, text: reviewText)

坑:这是系统级 UI,你控制不了它的样式和布局。适合”够用就行”的场景。

批量翻译并逐条更新 UI

场景:把一个语言筛选后的评论列表全部翻译,每条翻译完立即更新。

// 配置驱动:配置变化时触发翻译
.translationTask(translationConfig) { session in
    let requests = filteredReviews.map { review in
        TranslationRequest(source: review.text)
    }
    // performAll 返回 stream,每条完成就回调
    for try await response in session.performAll(requests) {
        updateReviewTranslation(response)
    }
}

// 触发翻译:首次创建配置或 invalidate 已有配置
func translateReviews() {
    if config == nil {
        config = TranslationSession.Configuration()
    } else {
        config?.invalidate() // 内容变了,需要重新触发
    }
}

坑:invalidate() 是必须的——SwiftUI 看不到你改了源文本,必须手动通知配置失效。

指定翻译语言

场景:强制从日语翻译到简体中文,而不是自动检测。

let config = TranslationSession.Configuration(
    source: Locale.Language(identifier: "ja"),
    target: Locale.Language(identifier: "zh-Hans")
)

坑:不指定语言时框架会自动检测源语言并翻译到用户设备语言。大多数情况下自动模式就够了,手动指定反而容易出错。

最佳实践

新项目:从 .translationPresentation() 开始做原型,验证翻译对你 App 的价值。如果发现系统浮层体验不够灵活(比如需要同时显示多条翻译),再切换到 TranslationSession。语言设置优先用自动模式——让框架帮你做语言检测,比你自己调 Language Identification API 再传结果更高效。

已有项目:如果你已经在用第三方翻译 API(Google、DeepL 等),不需要急着全部迁移。建议先用 .translationPresentation() 给离线场景做一个 fallback——网络不好的时候走本地翻译,体验降级但不中断。TranslationSession 的批量翻译能力特别适合替换现有的”翻译整个列表”逻辑,省去你自己管理并发和网络错误的麻烦。

还有什么值得关注

  • TranslationSession.Configuration 支持 sourcetarget 语言的任意组合,但不是所有语言对都有对应的模型,框架会自动回退。
  • 语言包下载在后台进行,即使你的 App 被切到后台也会继续,用户下次打开时就能用。
  • 翻译 API 支持的所有语言列表可以通过 Locale.Language 查询,具体支持情况参考 Apple 文档。
WWDC 2024