Як визначити мову сторінки в Publii без плагінів

Частина 2. Як визначити мову сторінки в Publii

Продовження Частина 1. Чому мені знадобився власний i18n у Publii

У першій частині я зупинився на простій, але показовій проблемі: англомовний пост — і український інтерфейс навколо нього.

Перш ніж перекладати тексти, дати чи plural, потрібно відповісти на базове питання:

Якою мовою зараз відкрито цю сторінку?

У Publii немає вбудованої відповіді на це питання для окремо взятої теми. Тому її доводиться знаходити самостійно — але, на щастя, це можна зробити досить просто.

Основна ідея полягала в тому, що не потрібно намагатися вигадувати складну систему. Я виходив з простого припущення: Якщо сторінка має мовну версію, яка позначена в її URL або slug то post-title-en, about-de, homepage-uk більш ніж достатньо для статичного сайту.

Витягуємо мову зі slug або URL

Почнемо з маленької функції, яка шукає код мови в рядку:

function detectLang(ctx) {
    const slug = ctx?.slug || '';

    if (/(^|[-_])en([-_]|$)/i.test(slug)) return 'en';
    if (/(^|[-_])de([-_]|$)/i.test(slug)) return 'de';
    if (/(^|[-_])uk([-_]|$)/i.test(slug)) return 'uk';

    return null;
}

Що тут відбувається:

  • ми не прив’язані до конкретного формату, підтримуються - і _
  • код мови може бути: на початку, в середині, в кінці slug, а якщо мови немає — повертається null.

Ця функція нічого не вирішує сама. Вона лише відповідає на запитання: «Я бачу тут код мови чи ні?»

Але однієї функції detectLang недостатньо. У Publii helper може викликатися в різному контексті: постс, торінка, головна, partial, index. І в кожному з них: this, post, page, root можуть виглядати по-різному. Тому мені потрібна була функція, яка перевіряє кілька джерел і робить це в правильному порядку, завжди повертаючи мову.

Функція resolveLang

function resolveLang(ctx, root) {

    const url =
        root?.post?.url ||
        root?.page?.url ||
        root?.url ||
        '';

    const fromUrl = detectLang({ slug: url });
    if (fromUrl) return fromUrl;

    const fromPost = detectLang(root?.post);
    if (fromPost) return fromPost;

    const fromCtx = detectLang(ctx);
    if (fromCtx) return fromCtx;

    return root?.website?.language?.substring(0, 2) || 'uk';
}

Давайте розберемо логіку по кроках.

URL сторінки — найнадійніше джерело
root?.post?.url ||
root?.page?.url ||
root?.url

URL — це фінальний результат генерації сторінки. Якщо мова є там — це найточніший варіант. Тому він іде першим.

slug поста

Іноді helper викликається ще до того, як URL доступний повністю. У такому випадку slug поста — хороший fallback.

локальний контекст helper

Це страховка для edge cases: partial, нестандартний виклик, кастомна логіка в шаблоні.

Fallback на мову сайту
root?.website?.language?.substring(0, 2) || 'uk'

Це важливо з двох причин:

  1. helper завжди повертає мову
  2. тема ніколи не ламається

Навіть якщо сторінка без мовного коду — інтерфейс залишиться консистентним.

Чому я не використовую cookies або JS

Тому що:

  • це статичний сайт
  • Publii генерує HTML
  • усе має працювати без клієнтської логіки

Мова сторінки має бути визначена на етапі генерації, а не в браузері.

На цьому етапі у нас є проста функція визначення мови, передбачуваний результат, відсутність залежностей, однакова поведінка для всіх helpers. І тепер можна зробити головне — передати цю мову в будь-який helper теми.

Що далі?

Тепер, коли ми знаємо мову сторінки, логічно перейти до перекладу текстів. У наступній частині я покажу: як я зберігаю словники, як працює helper {{t}}, чому post.readMore — зручніший за плоскі ключі і як fallback рятує шаблони.

Коментарі:

Завантаження коментарів…

Поділитися цим:

Оновлено: 4 лютого 2026 року