当文本中不包含数字时,本地化和复数字符串的正确方法是什么?
我知道我可以使用
AttributedString
执行以下操作(已经是一个很棒的功能):
var count = 3
AttributedString(localized: "^[\(count) Chief-of-staff](inflect: true)")
// "3 Chiefs-of-staff"
我想在表格/列表中列出姓名,并使用“Chief-of-staff”或“Chiefs-of-staff”作为列表标题,并根据列表中的姓名数量进行本地化。
继优秀文章here之后,这个用例看起来与
InflectionConcept
的现有实现类似。也许它需要一个新的count
变形概念来实施。然后人们也许能够做这样的事情(伪代码,不起作用!):
var options = AttributedString.LocalizationOptions()
options.concepts = [.count(count)]
AttributedString(localized: "^[Chief-of-staff](agreeWithConcept: 1)", options: options)
我取得的唯一进展是直接使用
Morphology
,但这失败了,因为确定 GrammaticalNumber
的逻辑是特定于语言环境的。以下内容适用于英语和其他只有两种形式(单数和复数)的语言,但不适用于使用 pluralTwo
、pluralFew
、pluralMary
等的语言。
extension Morphology.GrammaticalNumber {
init(count: Int) {
switch count {
case 1: self = .singular
default: self = .plural
}
}
}
extension LocalizedStringResource.StringInterpolation {
mutating func appendInterpolation(_ input: String, count: Int) {
var morphology = Morphology()
morphology.number = .init(count: count)
var string = AttributedString(input)
string.inflect = InflectionRule(morphology: morphology)
appendInterpolation(string.inflected())
}
}
AttributedString(localized: "\("Chief-of-staff", count: count)")
一种可能性是使用字符串中的数字,然后将其删除,但这感觉像是一个可怕的黑客:
var header = AttributedString(localized: "^[\(count) Chief-of-staff](inflect: true)")
let range = header.range(of: "\(count) ")!
header.removeSubrange(range)
// Chief-of-staff
我是否遗漏了一些明显的东西,或者有更简洁的解决方案吗?
虽然我同意这是一个黑客,但这里至少有一些包装可以使用您的解决方案隐藏混乱:
extension String {
func pluralize() -> String {
let count = 2
var attributed = AttributedString(localized: "^[\(count) \(self)](inflect: true)")
let range = attributed.range(of: "\(count) ")!
attributed.removeSubrange(range)
return String(attributed.characters)
}
}