Open leovp opened 6 years ago
Thanks a lot, @leovp! Especially the second link and the links further on from it are great source of information.
My original simplification was quick to implement, but not enough. Even the common languages were not covered well with the three plural forms and the single rule for them. I went for the universal solution as done by Mozilla localizers. Newly I specify both the plural rule (a number or a function) and the plural forms as an array of strings. The plural rule function returns an index to the array of plural forms.
relativeTime: {
// 3 plural forms for 1 and x1, 2-4 and x2-4, 5-
pluralRule: 7,
duration: {
s: 'несколько секунд',
m: 'минута',
mm: ['%d минута', '%d минуты', '%d минут'],
h: 'час',
hh: ['%d час', '%d часа', '%d часов'],
d: 'день',
dd: ['%d день', '%d дня', '%d дней'],
M: 'месяц',
MM: ['%d месяц', '%d месяца', '%d месяцев'],
y: 'год',
yy: ['%d год', '%d года', '%d лет']
},
future: {
s: 'через несколько секунд',
m: 'через минуту',
mm: ['через %d минуту', 'через %d минуты', 'через %d минут'],
h: 'через час',
hh: ['через %d час', 'через %d часа', 'через %d часов'],
d: 'завтра',
dd: ['через %d день', 'через %d дня', 'через %d дней'],
M: 'через месяц',
MM: ['через %d месяц', 'через %d месяца', 'через %d месяцев'],
y: 'через год',
yy: ['через %d год', 'через %d года', 'через %d лет']
},
past: {
s: 'несколько секунд назад',
m: 'минуту назад',
mm: ['%d минуту назад', '%d минуты назад', '%d минут назад'],
h: 'час назад',
hh: ['%d час назад', '%d часа назад', '%d часов назад'],
d: 'вчера',
dd: ['%d день назад', '%d дня назад', '%d дней назад'],
M: 'месяц назад',
MM: ['%d месяц назад', '%d месяца назад', '%d месяцев назад'],
y: 'в прошлом году',
yy: ['%d год назад', '%d года назад', '%d лет назад']
}
}
// Plural rule #7 (3 forms)
// Families: Slavic (Belarusian, Bosnian, Croatian, Serbian, Russian, Ukrainian)
n => n % 10 === 1 && n % 100 !== 11 ? 0
: n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2,
I had to to separate the special singular form from the plural forms. It has usually no number and thus the first plural form (for 1, 21, 31, ...) cannot be reused for it.
I released this feature in 1.12.2. At first, locales cs, ru, sk and ua are correct there.
Eventually, the plural rules should make it out of the relativeTime
plugin to the dayjs
core utilities. Or may be event out of this module.
New locale handling is pretty cool, thanks. But I think I found a bug in
relativeTime
plugin.So, there are three declensions of nouns in Russian: singular, dual and plural. The library does have
h
,hh
andhhh
for all of those (this is the case with other units as well), but it assumes that single-letter format is only used when thevalue
of whatever unit is exactly 1. For example "час назад" ("an hour ago"). Then if the last digit of value is less than 5,hh
handles it, otherwise it's going to behhh
.In Russian though (and I assume a few other languages),
singular
rule works for 1, 21, 31, 41, ..., 101, etc. Thendual
works for 2, 3, 4, 22, 23, 24, ..., 102, 103, 104, 122, 123, 124, etc. Thenplural
works for everything else. SeeReference
for a complete formula.Example of a bug:
It should be "через 21 минуту", same as if it was 1 minute ("через минуту"). I think single-letter formats should have a "%d" in there as well, so that they work for all units that are
singular
.Relevant code comment: https://github.com/prantlf/dayjs/blob/combined/src/plugin/relativeTime/index.js#L103-L106 Reference: http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html