大多数浏览器和
Developer App 均支持流媒体播放。
-
了解 Translation API
探索如何使用新的 Translation 框架,将 App 中的文本翻译成不同的语言。 我们会介绍如何在系统 UI 中快速显示翻译,以及如何为自己 App 的 UI 进行更大规模的批量文本翻译。
章节
- 0:00 - Introduction
- 2:10 - Simple overlay translation
- 4:01 - Flexible translation
- 11:34 - Language support
- 12:48 - Best practices
资源
相关视频
WWDC23
-
下载
大家好 我叫 Louie 是一名工程师 来自 Machine Translation 团队 欢迎观看 “了解 Translation API”! 在旅行时 我经常需要 在多种不同语言之间进行翻译 “翻译”App 的妙处在于 我不需要会说各种语言 在 Apple 我们致力于 消除语言障碍 让用户受益于为翻译功能 提供支持的机器学习技术
这些功能包括“翻译”App 只要输入任意文本 即可翻译成多种语言
全系统翻译 可以在系统中的任意 App 之上 显示翻译表
相机翻译 可以翻译图像 和周围环境中的文字 等等 今天 我们很高兴能够 向大家介绍新的 API 这些 API 利用了上述功能 和“翻译”App 背后的 机器学习模型 让你能够在 *自己* 的 App 中 解锁所有这些强大功能
我们今天要讨论的所有 Translation API 对 iOS、 iPadOS 和 macOS 都适用 我们将以 iPhone 为例 但所有代码 同样适用于 iPad 和 Mac
我热爱徒步旅行 正在构建一款 App 帮用户找到欧洲各地超棒的徒步路线 我的 App 提供了徒步路线描述 而用户可以点评自己走过的徒步路线 这些点评可以用任何语言撰写 所以我希望确保其他用户 即使看到以他们不熟悉的语言 撰写的点评 也仍然可以看懂全部内容 由于这是用户生成的内容 仅靠本地化是不够的 我将使用这个 App 向大家展示 在 App 中添加翻译功能 让所有人更能从中受益 有多么简单 下面概述一下我们今天 要讨论的内容 首先 我们将介绍在 App 内 提供翻译功能时 可供选择的两种方法 第一种方法是通过一个 非常简单的 API 显示翻译内容叠层 第二种方法是通过文本翻译 API 更加灵活地实现翻译功能
然后 我们将介绍 支持的语言都有哪些 以及如何通过编程 进行这方面的检查
最后 我们将介绍一些 使用翻译功能的最佳实践 我们开始吧
要为 App 添加翻译功能 最简单的 方法是使用 .translationPresentation() 只用一行 SwiftUI 代码 就能向用户显示 翻译成用户母语的文本 你只需提供要翻译的文本 然后触发翻译 就可以了
这个 API 已于近期上线 因此 现已可在生产版本 App 中采用
现在 当用户看到 用其他语言撰写的点评时
向他们显示翻译内容的系统 UI 将会很容易实现
我来展示一下 将这个功能 添加到我的 App 中有多简单 首先 添加存储空间 用于控制是否显示翻译内容
接下来 为上下文菜单 添加一个按钮 用于触发翻译 按下这个按钮后 会将 showsTranslation 设置为 true
最后 添加 .translationPresentation()
让它在 showsTranslation 为 true 时显示 并传入待翻译的点评文本 这样就可以了
现在 如果我看不懂点评 只需按一下按钮 就能看到译文
如果需要的话 我甚至可以 选择更改目标语言
在这里获得的译文 和 iOS 中别处提供的 全系统翻译功能相同 但是由我的 App 触发 而不是通过文本选择触发 这种添加翻译功能的方式非常简单 非常适合某些 App 但在某些情景中 一次只显示一段译文 并不是理想的体验 例如 如果我希望用户能够 一次性看到多条评论的译文 该怎么做? 我想要显示内嵌于每条评论的译文 正是考虑到这种情景 我们构建了 灵活的 Translation API! 下面我来为大家介绍一下! 这个灵活的 Translation API 核心是 TranslationSession 类 借助 TranslationSession 可以一次性翻译一个或多个字符串 然后通过通用的 Swift async 语法 获取返回的结果
这些结果在 UI 中的显示方式 完全由你决定
你无需自行创建 TranslationSession 的实例 这是因为它有时需要 向用户显示 UI 取而代之的方法是 将 .translationTask 附加到视图 它会调用闭包来提供要使用的 TranslationSession 实例 在这个示例中 视图显示在屏幕上时 闭包会运行一次
但在很多情况下 你需要 对译文出现的时间进行更多控制 这时 TranslationSession.Configuration 就派上了用场
现在 只要配置更改 就会运行这个闭包 要想在一开始就触发翻译 需要将配置设置为 non-nil 值 如果需要再次触发翻译 则需要更改配置 以便让 SwiftUI 知道 再次运行闭包 要更改配置 可以更改 源语言或目标语言 或者 如果你想翻译新的文本 也可以在配置上 调用 .invalidate() 我们来看看在我的 App 中 采用这个更灵活的 API 有多么简单 首先 为 TranslationSession.Configuration 添加储存空间 这个值一开始是 nil 这样就会等到用户触发 才提供翻译
接下来 添加使用这个配置的 .translationTask()
只要配置更改 不再是 nil 就会调用这一项 从而为我提供 用于翻译的会话
然后 我要进行翻译
我会让这个会话翻译一批文本
我要使用下面这个已经实现的函数
提出翻译所有已筛选点评的请求 结果以异步形式返回 一次返回一段译文
收到每个结果时 我都会调用 已经实现的函数 来接受翻译响应
将它添加到模型对象 然后更新 UI
现在 我需要触发翻译功能 我已经添加了筛选机制 可以一次查看一种语言的点评 选择语言后 可以使用一个按钮 来翻译筛选出的点评 但我还没有完成这个按钮的实现 我们一起来实现它
首先 检查配置是否已经存在 如果不存在 就说明还没有进行过翻译 所以我要创建一个配置
我要使用这里的默认构造器 它会自动选择语言 我稍后会详细介绍 如何控制要使用哪一种语言
如果配置已经存在 就说明已经进行过翻译 但用户想要再次进行翻译 SwiftUI 看不到源内容已更改 但调用 .invalidate() 会更改配置 让 .translationTask 闭包 再次运行 从而翻译新内容 就是这样实现的!我来展示一下 在我的 App 中的实际运行效果
现在 筛选出日语点评后 只需按一下按钮
就能在完成筛选时 将译文添加到点评 让用户能够一次性阅读所有译文 而不必逐一翻译
看起来用户纷纷表示 这条徒步路线很棒 但强度也很大 我觉得 我打算出行的那一天 来不及体验这么长的徒步路线 所以我要尝试 寻找其他徒步路线
好的 这个 “Tulips and Windmill Walk” 似乎更适合我 但是我想知道用户评价如何
看起来大部分点评都是 用荷兰语撰写的 我要翻译一下
但现在当我翻译荷兰语内容时 大家会注意到 我看到系统提示我 下载这种语言 我来解释一下这是怎么回事
TranslationSession 使用设备端 ML 模型来进行翻译
这些模型会与系统上包括 “翻译”App 在内的所有 App 共用 如果用户已经下载了多种语言 那么你的 App 也可以使用这些语言
这个 API 会负责处理细节 当 App 进行翻译时 如果还没有 安装相应的语言 那么框架只会请求获得下载权限 它还负责在下载期间 向用户显示进度 而且如果用户关闭这个表单 甚至完全退出你的 App 这些下载也会 在后台继续进行 接下来 我们谈谈如何选择这些语言 你可以指定要使用的 源语言和目标语言 或者像我之前一样获得自动行为
可以在 .translationTask 中 直接指定语言 也可以在 TranslationSession.Configuration 中指定
对源语言使用 nil 值 会自动尝试识别内容的语言 如果框架无法确定语言 就会让用户进行选择 对目标语言使用 nil 值 会选择一种合适的目标语言 这取决于源语言所使用的语言 以及用户的首选语言
值得注意的是 Locale 和 Locale.Language 可能有很多种形式 说实话 可能会让人有点困惑 因为有很多种组合 和变体值得留意 例如 根据返回语言的具体 API 返回的可能只是一种语言 也可能是语言和变体 语言和地区 甚至是语言和看似不相干的地区 例如 居住在日本的法语用户
为了获得最佳结果 应该使用 LanguageAvailability.supportedLanguages API 返回的语言
你可能想知道 如何确定 任意内容使用的是哪种语言 我们建议尽可能 为 TranslationSession 中的源语言赋值 nil 以便为你识别源语言 但是 如果你需要识别文本的语言 可以使用 NLLanguageRecognizer 调用 processString 函数 获取 dominantLanguage 然后转换为 TranslationSession 可以使用的 Locale.Language
许多 App 都需要 一次性翻译多个字符串的功能 之前我翻译不同的 用户点评时就是这样 又比如 你的 App 可能需要 翻译一个文稿或图像中的 不同字符串
翻译同一种语言的多个字符串时 效果最佳且效率最高的方法是 使用批量翻译函数 而不是仅翻译单个字符串的函数
你有两个选择 前一个函数会在所有结果就绪后 一次性返回 并保持原始顺序 这种方法更加简明易用 因为顺序始终保持不变 你也很容易知道该如何处理每个响应 如果你希望等到所有内容 全部翻译完之后再显示译文 那么最佳方法也是使用这个函数
后一个函数会在结果可用时 流式传输结果 就像 AsyncSequence 一样 这种方式的优点在于能让用户觉得 你的 UI 响应速度更快 因为先生成的结果会更早地返回 而这一点可以立即 反映在你的 UI 中 使用这个可以流式传输结果的函数时 需要确保在每个请求上 都设置了 clientIdentifier 这样 在收到每个响应时 就能知道对应的请求是哪一个 要了解这方面的更多详细信息 请参考相关文档
接下来 我们谈谈语言支持 我们今天讨论的 API 支持所有这些语言 这些语言和“翻译”App 支持的语言相同
今年 我们新增了 对印地语的支持 这意味着有更多用户 现在既能在“翻译”App 中 也能在你的 App 中 利用翻译功能
你可以使用新的 LanguageAvailability 类 来检查翻译功能支持哪些语言 随着我们支持更多语言 这个列表会陆续更新
你还可以检查是否支持 从一种语言到另一种语言的翻译 这个框架并非支持每一种语言组合
例如 如果你查看美式英语到印地语 和英式英语到印地语的状态 框架会告诉你 这两个语言对都受到支持 或者 如果两种语言都已下载 则框架会报告这些语言已安装
另一方面 如果你检查是否可以从一种英语变体 翻译成另一种英语变体 或者从任意语言翻译成同种语言 框架会始终报告不支持这个语言对 虽然你可能已经使用不受支持的 任一语言对 创建了一个 TranslationSession 但每次尝试翻译都会返回错误 这甚至还有一个函数 可以通过一段源文本而不是源语言 来检查这一状态
我们来看看使用翻译功能时的 一些最佳实践 首先 请务必在 iPhone、iPad 或 Mac 上进行开发 这些翻译 API 无法在模拟器中运行
接下来 请务必将 .translationPresentation 和 .translationTask 修饰符 附加到内容本身 由于 .translationPresentation() 在 iPad 和 Mac 上是弹出框 因此需要确保它指向正确的视图 这段代码会让弹出框 指向按钮本身 可能会挡住原始视图
应该改为将修饰符 附加到内容或内容容器 现在 弹出框可以很好地 指向翻译的内容 并且不会遮挡内容
翻译多种语言的内容时 你需要采取特别的预防措施
任意一批请求包含的所有源文本 都应该使用同一种语言 在同一批请求中混合不同语言 会导致结果质量不佳 这个示例将德语和西班牙语文本 放在同一批请求中 可能会输出毫无意义的内容
应该改为 使用同一会话在单独的批次中 进行单独的调用 来翻译每一种语言 如这里所示
在代码中 这意味着 不应在提出单个请求时 包含多种语言的内容 在这个案例中 不应在同一个 请求数组中包含德语和西班牙语文本
而是应该通过单独的会话 对每一种语言 进行单独的函数调用 在这里 我会翻译德语文本 然后再翻译西班牙语文本 请务必注意 完成这一操作时 会话的源语言必须为 nil 这样一来 会话就会 首先确定每个批次的语言
还应该仅指定支持的语言 否则 通过这个会话 生成的所有译文都会产生错误
只要你不确定 内容使用的是哪种语言 或者不确定 需要翻译成哪种语言 就可以使用 nil 值 让框架 为你选择语言 如果你提前知道 用户可能会使用哪些语言 则可以请求用户批准下载 而无需使用 TranslationSession.prepareTranslation() 进行翻译
在用户需要离线 使用翻译功能的情况下 这种方法非常实用 在这种情况下 用户应该 提前开始下载 如果你的 App 需要翻译 随时间推移而变化的内容 可以使用这个 API 来预先获得 用户对下载的批准 以免遮挡屏幕
储存 TranslationSession 实例时 需要注意处理方式 TranslationSession 会为你 完成许多后台工作 但偶尔也需要向用户显示 UI 这是通过锚定到 App 中的视图实现的 每个 TranslationSession 实例 都与所锚定的视图相关联 因此 如果底层视图消失了 实例就无法正常工作
这也意味着 不应在相应视图的 生命周期之外储存实例 例如持久性模型对象中的实例 因为会话稍后可能会无法使用
最后 现在有一个新的 SF Symbol 可以用于翻译 它适用于 UI 中的任意位置 在这些位置可以触发翻译 API 或引用我们今天讨论的 翻译功能
总结一下 如果要在系统 UI 中 在你的 App 上方显示译文 那么应该采用的方法是 `.translationPresentation()` 此外 如果你想在自己 App 的 UI 中进行更深入的整合 也可以使用灵活的 Translation API
我们随时欢迎大家 通过“反馈助理”提供反馈 如果你遇到任何问题 或者希望看到任何增强功能 请告诉我们 我们期待你的 App 能够 通过翻译功能触达更广泛的受众 感谢观看!
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。