You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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并自定义格式化逻辑,步骤如下:

  1. 导入Intents框架:需要使用INPreferences获取Siri语言设置
  2. 获取Siri语言Locale:通过INPreferences.siriLanguageLocale()获取当前Siri使用的Locale,而非UI的.autoupdatingCurrent
  3. 自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 18:42:20