Перевод временных отрезков — задача, которая выходит за рамки простой замены слов. Разные языки имеют разные грамматические конструкции, падежные формы, порядок слов и уровни вежливости. Грамотная реализация локали учитывает все эти факторы.
timeago.js использует 15 индексов (0–14), каждый из которых соответствует диапазону разницы во времени:
0 → только что (< 45 сек)
1 → секунды (45–90 сек, единственное число)
2 → секунды (90 сек – 45 мин, множественное число)
3 → минуты (1 минута)
4 → минуты (несколько минут)
5 → часы (1 час)
6 → часы (несколько часов)
7 → дни (1 день)
8 → дни (несколько дней)
9 → недели (1 неделя)
10 → недели (несколько недель)
11 → месяцы (1 месяц)
12 → месяцы (несколько месяцев)
13 → годы (1 год)
14 → годы (несколько лет)
Индекс 0 особенный: number здесь не несёт смысловой
нагрузки. Оба варианта строки (прошлое и будущее) обычно игнорируют
число:
[0] → ['только что', 'прямо сейчас']
В некоторых локалях будущий вариант этого индекса также использует “только что”:
[0] → ['just now', 'just now']
Индекс 1 — секунды в единственном числе (~1 секунда), индекс 2 — секунды в множественном. Это сделано для языков, где “1 секунда назад” и “2 секунды назад” грамматически различаются.
Для языков без этого различия оба индекса возвращают одинаковую форму:
[1] → ['%s seconds ago', 'in %s seconds']
[2] → ['%s seconds ago', 'in %s seconds']
Ключевая особенность: при переводе на русский нужно учитывать не только число, но и падеж:
Прошедшее время:
1 минуту назад ← винительный
2 минуты назад ← родительный (ед.ч.)
5 минут назад ← родительный (мн.ч.)
Будущее время:
через 1 минуту ← винительный
через 2 минуты ← родительный (ед.ч.)
через 5 минут ← родительный (мн.ч.)
Это означает, что для каждого числа нужны правильные падежные формы:
const minuteForms = {
past: { one: 'минуту', few: 'минуты', many: 'минут' },
future: { one: 'минуту', few: 'минуты', many: 'минут' },
};
Для единственного числа (индексы 3, 5, 7, 9, 11, 13) число в строке жёстко задано:
[3] → ['1 минуту назад', 'через 1 минуту']
[5] → ['1 час назад', 'через 1 час']
Для множественного (индексы 2, 4, 6, 8, 10, 12, 14) используется
%s:
[4] → ['%s минут назад', 'через %s минут']
В японском и корейском время ставится в конец фразы:
// Японский
[3] → ['1分前', '1分後'] // "1 минута перед", "1 минута после"
[4] → ['%s分前', '%s分後']
Порядок слов: число + единица + суффикс.
В арабском языке шесть категорий: zero, one, two, few, many, other.
const arRules = new Intl.PluralRules('ar');
function arForm(n, forms) {
return forms[arRules.select(n)];
}
В турецком временны́е суффиксы присоединяются к слову:
// "несколько минут назад"
'%s dakika önce' // dakika önce — минута перед
Особенность в том, что суффиксы гармонируют по гласным (vowel harmony), что нельзя реализовать через простые строки.
Финские существительные изменяются по падежам, что влияет на перевод:
// "5 минут назад"
'%s minuuttia sitten' // -a — партитив множественного числа
Некоторые языки не различают “1 секунду назад” и “только что”. Для таких случаев:
[0] → ['недавно', 'скоро']
[1] → ['недавно', 'скоро']
[2] → ['%s секунд назад', 'через %s секунд']
Не все языки используют симметричные конструкции для прошлого и будущего. Например:
// Прошлое: "Χ минут назад"
// Будущее: "через Х минут"
Vs. асимметричный вариант:
// Прошлое: "Χ минут тому"
// Будущее: "через Х минут (в будущем)"
Форма “лет” (5 лет назад) отличается от “год” и “года”. Это супплетивная форма — совершенно другое слово:
function yearForm(n) {
return pluralRu(n, 'год', 'года', 'лет');
}
yearForm(1); // "год"
yearForm(2); // "года"
yearForm(5); // "лет"
yearForm(11); // "лет"
yearForm(21); // "год"
“Неделя” имеет особенности склонения при предлоге “через”:
1 неделю назад ← "неделю" (вин. пад.)
через 1 неделю ← "неделю" (вин. пад.)
2 недели назад ← "недели" (род. ед.)
через 2 недели ← "недели" (род. ед.)
5 недель назад ← "недель" (род. мн.)
через 5 недель ← "недель" (род. мн.)
| Язык | Особенности |
|---|---|
| Русский | 3 формы, падежи, супплетив (“год/лет”) |
| Арабский | 6 форм, восточноарабские цифры, RTL |
| Польский | 4 формы, исключения |
| Финский | Падежные суффиксы, партитив |
| Японский | Счётные слова, постпозиция времени |
| Иврит | Сопряжённые формы, RTL |
| Турецкий | Гармония гласных, суффиксы |
| Китайский | Нет склонения, счётные слова |