如何为Siri正确本地化Measurement参数?
解决AppIntent中Siri计时器时长的本地化与单位显示问题
我通过AppIntent搭配AppShortcut短语实现了Siri启动计时器的功能,核心代码如下:
struct StartTimerWithCustomTimeIntent: AppIntent { static let title: LocalizedStringResource = "Start New Timer" static var description = IntentDescription("Starts a timer with a custom duration.") @Parameter(title: "Duration", description: "The duration of the timer.") var duration: Measurement<UnitDuration> func perform() async throws -> some IntentResult & ProvidesDialog { // [执行计时器启动逻辑] return .result( dialog: .init( full: "\(duration, format: .measurement(width: .wide, usage: .asProvided)) timer started.", systemImageName: "timer" ) ) } }
当前遇到三个问题:
- 明明指定了
width: .wide,屏幕仍显示单位缩写(如“5 min timer started.”),预期显示完整形式 - Siri朗读时是完整形式,但屏幕显示不一致
- 时长未遵循Siri语言设置本地化:
- 优先使用UI语言而非Siri语言
- 非英语环境(如德语)下,Siri朗读未翻译的英文缩写
之前尝试的本地化方法仅适配UI语言,无法匹配Siri语言:
extension Measurement where UnitType == UnitDuration { func localized(locale: Locale = .autoupdatingCurrent) -> String { let formatter = MeasurementFormatter() formatter.locale = locale formatter.unitOptions = .providedUnit formatter.unitStyle = .long return formatter.string(from: self) } }
解决方案:基于Siri语言Locale格式化时长
要让时长同时遵循Siri语言本地化、屏幕显示完整单位,需要获取Siri对应的Locale并自定义格式化逻辑,步骤如下:
- 导入Intents框架:需要使用
INPreferences获取Siri语言设置 - 获取Siri语言Locale:通过
INPreferences.siriLanguageLocale()获取当前Siri使用的Locale,而非UI的.autoupdatingCurrent - 自定义MeasurementFormatter:使用Siri的Locale,设置
unitStyle = .long确保单位完整,unitOptions = .providedUnit保留用户指定的时长单位
修改后的代码如下:
import Intents // 必须导入 struct StartTimerWithCustomTimeIntent: AppIntent { static let title: LocalizedStringResource = "Start New Timer" static var description = IntentDescription("Starts a timer with a custom duration.") @Parameter(title: "Duration", description: "The duration of the timer.") var duration: Measurement<UnitDuration> func perform() async throws -> some IntentResult & ProvidesDialog { // 获取Siri语言对应的Locale let siriLocale = INPreferences.siriLanguageLocale() // 配置MeasurementFormatter let formatter = MeasurementFormatter() formatter.locale = siriLocale formatter.unitOptions = .providedUnit formatter.unitStyle = .long // 强制使用完整单位 // 格式化时长字符串 let formattedDuration = formatter.string(from: duration) // 构建对话内容 return .result( dialog: .init( full: "\(formattedDuration) timer started.", systemImageName: "timer" ) ) } }
关键说明
INPreferences.siriLanguageLocale():直接获取用户设置的Siri语言对应的Locale,确保本地化匹配Siri的语言环境unitStyle = .long:强制生成完整单位名称(如“minutes”而非“min”),解决屏幕显示缩写的问题- 放弃系统的
\(duration, format: .measurement)插值:系统插值会优先使用UI语言的Locale,无法适配Siri语言,因此改用自定义格式化字符串
内容的提问来源于stack exchange,提问作者Mischa
相关产品推荐
相关产品推荐

