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

Swift中结合Locale使用NumberFormatter生成基数词的问题

解决Swift中挪威语基数词与单位的语法匹配问题

这个问题的核心是挪威语里基数词en/et的使用规则——它们得跟着后面名词的语法性别走,而你用NumberFormatter.spellOut格式化数字时,它只会输出通用的én,根本不会考虑后面要搭配的单位是什么词性。minutt是中性名词,所以必须用et才对。

最简单的解决方案:用默认的MeasurementFormatter逻辑

你完全不需要自定义NumberFormatter,MeasurementFormatter本身已经内置了针对不同Locale和单位的语法适配逻辑,直接用默认配置就能得到正确结果:

let measurement = Measurement(value: 1, unit: UnitDuration.minutes)
let measurementFormatter = MeasurementFormatter()
measurementFormatter.unitStyle = .long
measurementFormatter.locale = Locale(identifier: "nb_no")

// 移除自定义的numberFormatter,依赖系统默认的语境化格式化
let result = measurementFormatter.string(from: measurement)
// 输出:et minutt

如果必须自定义数字格式(比如强制拼写数字)

要是你因为某些需求必须用拼写式的数字格式,那得手动处理单位的词性匹配。比如维护一个挪威语中性单位的列表,根据单位选择对应的基数词:

let measurement = Measurement(value: 1, unit: UnitDuration.minutes)
let measurementFormatter = MeasurementFormatter()
measurementFormatter.unitStyle = .long
measurementFormatter.locale = Locale(identifier: "nb_no")

var result: String
if measurement.value == 1, measurementFormatter.locale.identifier.starts(with: "nb") {
    let unitString = measurementFormatter.string(from: measurement.unit).lowercased()
    // 挪威语中性单位列表,可根据需求扩展
    let neutralUnits = ["minutt", "år", "hus", "billett"]
    let numberWord = neutralUnits.contains(unitString) ? "et" : "en"
    result = "\(numberWord) \(unitString)"
} else {
    // 非1的情况或其他语言,用默认格式化
    let formatter = NumberFormatter()
    formatter.locale = measurementFormatter.locale
    formatter.numberStyle = .spellOut
    measurementFormatter.numberFormatter = formatter
    result = measurementFormatter.string(from: measurement)
}

print(result) // 输出:et minutt

这种方式需要你自己维护词性对应的单位列表,适合特定场景;但通用场景下强烈推荐用第一种方案,毕竟系统内置的格式化逻辑已经覆盖了绝大多数Locale的语法细节,不用自己造轮子。

内容的提问来源于stack exchange,提问作者Omer Aam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:12:02