package say // The counted noun, in the form the number in front of it demands. // // Russian inflects a noun after a numeral, and the form depends on the last two // digits: 1 градус, 2 градуса, 5 градусов, 11 градусов, 21 градус, 22 градуса. // A line file cannot spell that out, so a count in a template splits into two // placeholders — the number, and {word} filled from here. // // The rule lived once as hostWord in cmd/mavend/netscan.go and once as // pluralDaysRU in internal/memory, which meant the weather line said "градусов" // for every temperature and the task list said "дн." — a written abbreviation // read aloud. One helper, every count site (Vikunja #521). import "math" // CountWord picks between the three forms n needs: one for 1, few for 2-4, many // for 0, 5-20 and anything ending in those. A negative count reads its own // magnitude, since minus does not change the noun: -2 градуса. func CountWord(n int, one, few, many string) string { if n < 0 { n = -n } if n%100 >= 11 && n%100 <= 14 { return many } switch n % 10 { case 1: return one case 2, 3, 4: return few default: return many } } // Degrees — the noun for a temperature. Takes the reading as it arrives from a // weather provider and counts by the whole degrees she is about to say, so the // noun agrees with the number in the same sentence rather than with the reading // behind it. func Degrees(temp float64) string { return CountWord(int(math.Round(temp)), "градус", "градуса", "градусов") } // Devices — the noun for a count of hosts on the LAN or of smart-home devices. func Devices(n int) string { return CountWord(n, "устройство", "устройства", "устройств") } // Days — the noun for a stretch of days. This is what replaces «дн.» in the // overdue and due-soon reasons: an abbreviation is written shorthand, and every // one of these lines is spoken. func Days(n int) string { return CountWord(n, "день", "дня", "дней") }