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
相关产品推荐
相关产品推荐

