Работа с RTL языками

RTL (right-to-left) языки — арабский, иврит, персидский, урду — имеют направление текста справа налево. timeago.js формирует только текстовую строку, поэтому поддержка RTL реализуется на уровне CSS и HTML, а не внутри библиотеки.


Что делает timeago.js с RTL

Библиотека возвращает строку с арабскими или ивритскими символами. Корректное отображение этой строки — задача браузера и CSS. Сама библиотека:

  • не добавляет атрибуты dir или lang;
  • не вставляет управляющие символы Unicode для смены направления;
  • не изменяет структуру HTML.

Подключение арабской локали

import { register, format } from 'timeago.js';
import ar from 'timeago.js/esm/lang/ar';

register('ar', ar);

format(Date.now() - 3600000, 'ar');
// → "منذ ساعة"

Подключение ивритской локали

import he from 'timeago.js/esm/lang/he';

register('he', he);

format(Date.now() - 1000 * 60 * 5, 'he');
// → "לפני 5 דקות"

Подключение персидской локали

import fa from 'timeago.js/esm/lang/fa';

register('fa', fa);

format(Date.now() - 1000 * 60 * 60 * 2, 'fa');
// → "۲ ساعت پیش"

HTML-атрибут dir для корректного отображения

Чтобы браузер отображал RTL-текст правильно, нужен атрибут dir:

<time class="ago" dir="rtl" datetime="2025-05-26T10:00:00Z"></time>

Или на уровне контейнера:

<div dir="rtl" lang="ar">
  <time class="ago" datetime="2025-05-26T10:00:00Z"></time>
</div>

CSS для RTL

.rtl {
  direction: rtl;
  unicode-bidi: embed;
}

[lang="ar"],
[lang="he"],
[lang="fa"] {
  direction: rtl;
  text-align: right;
}

Атрибут lang на элементе

<time lang="ar" datetime="2025-05-26T10:00:00Z"></time>

Браузер применяет правильный рендеринг текста для указанного языка.


Динамическое переключение RTL/LTR

При смене языка в приложении нужно менять направление:

import { register, format } from 'timeago.js';

const RTL_LOCALES = new Set(['ar', 'he', 'fa', 'ur']);

function setLanguage(locale) {
  const isRTL = RTL_LOCALES.has(locale);

  document.documentElement.setAttribute('dir', isRTL ? 'rtl' : 'ltr');
  document.documentElement.setAttribute('lang', locale);

  // Обновить все временны́е метки
  document.querySelectorAll('.time').forEach(el => {
    el.textContent = format(el.getAttribute('datetime'), locale);
  });
}

Unicode двунаправленные маркеры

Иногда в смешанном тексте (LTR внутри RTL или наоборот) требуются управляющие символы:

  • — маркер справа налево (RLM)
  • — маркер слева направо (LRM)
register('ar_marked', (number, index) => {
  const [past, future] = arLocale(number, index);
  return [
    '‏' + past,    // принудительно RTL
    '‏' + future,
  ];
});

Числа в RTL-строках

В арабском и персидском используются восточноарабские цифры:

٠١٢٣٤٥٦٧٨٩

В некоторых локалях возвращаются эти цифры вместо западноарабских (0–9). Если нужны только западные цифры:

function toWesternDigits(str) {
  return str.replace(/[٠-٩]/g, d => '٠١٢٣٤٥٦٧٨٩'.indexOf(d));
}

const result = format(Date.now() - 3600000, 'ar');
console.log(toWesternDigits(result));

Тестирование RTL вывода

import { register, format } from 'timeago.js';
import ar from 'timeago.js/esm/lang/ar';

register('ar', ar);

const cases = [
  [Date.now() - 30000,         'منذ'],   // проверка наличия арабского текста
  [Date.now() - 3600000,       'ساعة'],  // "час"
  [Date.now() - 86400000,      'يوم'],   // "день"
];

cases.forEach(([date, keyword]) => {
  const result = format(date, 'ar');
  console.assert(result.includes(keyword), `Expected "${keyword}" in "${result}"`);
});

Работа с render() в RTL

<section dir="rtl" lang="ar">
  <time class="post-time" datetime="2025-05-26T08:00:00Z"></time>
</section>
import { render } from 'timeago.js';

const nodes = document.querySelectorAll('.post-time');
render(nodes, 'ar');

Направление текста управляется CSS и HTML — render просто подставляет строку.


Шрифты для RTL-языков

Корректное отображение арабского и ивритского текста требует подходящего шрифта:

[lang="ar"] {
  font-family: 'Noto Sans Arabic', 'Arial', sans-serif;
}

[lang="he"] {
  font-family: 'Noto Sans Hebrew', 'Arial', sans-serif;
}

Это не связано с timeago.js, но влияет на конечный результат пользовательского опыта.