I've created the following data model:
import Foundation
struct Effort {
let amount: Int
let unit: String
var text: String {
"\(amount) \(unit)"
}
var attributedText: String {
String(
AttributedString(localized: "^[\(amount) \(unit)](inflect: true)").characters
)
}
init(amount: Int, unit: String) {
self.amount = amount
self.unit = unit
}
}
If I create the value with the singular unit
name, the automatic grammar agreement
(https://www.swiftjectivec.com/morphology-in-ios-with-automatic-grammar-agreement/) works perfectly:
Effort(amount: 4, unit: "day").attributedString
"4 days"
Effort(amount: 1, unit: "day").attributedString
"1 day"
However, if I create this struct with already plural string, the automatic grammar agreement won't actually turn it back into singular:
Effort(amount: 1, unit: "days").attributedString
"1 days"
Is there any way to make it work both ways? I'm open to refactoring this code, even if it means it won't be so "elegant", i.e. if I have to write the inflection rule manually.
Motivation: the server already returns values in a plural form, also it would be good to make the client completely agnostic to the server response.
One idea that I'm considering looks like this:
AttributedString(localized: "^[\(amount) \(String(unit.dropLast()))](inflect: true)")
In essence, we're just dropping the last character from the unit
, but this obviously is not so robust as if the system handled it on it's own.
Consider lemmatising whatever you get from the server, so that it becomes the singular form, before you pass the string to Effort.init
.
Here is an example:
import NaturalLanguage
func lemmatiseNoun(_ input: String) -> String {
let tagger = NLTagger(tagSchemes: [.lemma])
let string = "the \(input)"
tagger.string = string
tagger.setLanguage(.english, range: string.startIndex..<string.endIndex)
let index = string.index(string.startIndex, offsetBy: 4)
let (tag, _) = tagger.tag(at: index, unit: .word, scheme: .lemma)
return tag?.rawValue ?? input
}
lemmatiseNoun("days") // "day"
Note that I am prefixing the word with the article "the", so that the tagger treats it as a noun. This is to avoid cases such as "leaves", where the tagger will lemmatise it as "leave" instead of "leaf" if it is just the word on its own.
As always with natural languages, there are fundamentally ambiguous cases. For example, consider "people". It is both the plural form of "person" (a human being), and also the singular form of "peoples" (the members of a particular nation, community, or ethnic group).