Сайт вебмастера

Мультиязычность в Albireo CMS

19-09-2024Reading time ~ 7 min.Albireo Framework / CMS 147

Есть несколько подходов в реализации мультиязычного сайта. Задача на самом деле не такая и простая как с технической точки зрения, так и с точки зрения администрирования такого контента.

Виды многоязычности сайта

Основой вопрос заключается в том, как именно нужно определять язык пользователя. Раньше преобладало решение, когда пользователь сам выбирал языковую версию сайта, а его выбор сохранялся в куке. При повторном посещении происходил редирект на выбранную версию.

Сейчас же преобладает подход, когда язык пользователя определяется по его браузеру. В настройках браузера можно указать какие языки следует использовать для отображения страниц (например в FireFox: Настройки - Язык - Выберите язык, предпочитаемый вами для отображения страниц - Выбрать). Такой вариант удобен тем, что сайт сам может определить предпочитаемый язык пользователя, поскольку технически он хранится в переменной $_SERVER['HTTP_ACCEPT_LANGUAGE'].

Мультиязычность сайта может быть реализована следующими способами:

  • Отдельная копия сайта, которую пользователь сам выбирает или делается автоматический редирект.
  • Отдельные языковые страницы или разделы сайта.
  • Страница может сама определить язык пользователя и переключить своё отображение.
  • Автоматический перевод фраз и текстов, в зависимости от языка пользователя.

Рассмотрим эти варианты для Albireo CMS.

Отдельная копия сайта

Поскольку Albireo CMS поддерживает мультисайтинг, где разные сайты используют одно ядро системы, то реализация отдельного сайта сводится только к копированию основного в отдельный подкаталог. Например, если основной сайт на русском в подкаталоге website (для адреса https://site/), то достаточно сделать его копию как подкаталог uk — он будет доступен как https://site/uk. Конечно же все настройки, все записи, файлы, логи, комментарии — всё это будет отдельным для каждого сайта.

Отдельные языковые страницы

Поскольку в Albireo CMS все страницы могут иметь произвольные адреса, то можно сделать раздельные страницы для разных языков. По сути это будут страницы с одними и теми же настройками, только меняется slug и html[lang]:

У основной страницы например адрес sample-page, тогда у языковой:

slug: uk/sample-page
html[lang]: uk

Соответственно на этих страницах нужно разместить ссылки на другие языковые страницы. Пользователь сам может выбрать подходящий вариант.

Ключ html[lang] нужен для того, чтобы браузер понимал на каком языке страницы и если нужно предложит перевод. Но это уже зависит от браузера и его настроек.

Определение языка пользователя

В Albireo CMS есть функция detectUserLang(), которая анализирует $_SERVER['HTTP_ACCEPT_LANGUAGE'] и на выходе выдаёт двухсимвольный код языка (ISO 639), например «uk», «en», «fr» и т.п.

В конфигурации сайта эта функция используется таким образом:

'userLang' => detectUserLang('ru', ['en', 'ru', 'uk']),

В ней первый параметр — это язык по умолчанию, а вторым указывается массив допустимых языков. Если пользователь предпочитает язык, который не указан, то возвращается язык по умолчанию.

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

if (getConfig('userLang') == 'uk') ...

Важно отметить, то userLang, так же как и detectUserLang() только возвращает предпочитаемый язык пользователя, но больше ничего не делает. Реализация языкового перевода ложится уже на другие функции или саму страницу.

«Самопереводящиеся» страницы

Это такие страницы, где текст будет меняться от языка пользователя. Алгоритм очень простой: смотрим getConfig('userLang') и выделяем блоки для каждого языка прямо в теле страницы.

<?php if (getConfig('userLang') == 'uk') : ?>

Здесь тест по украински

<?php else : ?>

Здесь язык по умолчанию

<?php endif ?>

Для того, чтобы изменить язык в HTML-теге нужно у страницы прописать php-код:

html[lang]: <?= getConfig('userLang') ?>

Что приведёт к коду:

<html lang="язык">

Такой вариант подходит для страниц с небольшим количеством основного текста. Посмотреть в действии можно например на странице условий. Если в браузере переключить язык на украинский или английский, то текст соответствующим образом изменится.

Отдельные тексты

Похожая схема, только тексты для удобства можно вынести отдельными файлами.

<?php 
    if (getConfig('userLang') == 'uk') require PAGES_DIR . 'texts/sample-page-uk.php';
    elseif (getConfig('userLang') == 'en') require PAGES_DIR . 'texts/sample-page-en.php';
    else require PAGES_DIR . 'texts/sample-page-default.php'; 
?>

То есть сама страница одна и та же, но подключает разные текстовые файлы.

Такой вариант (на if-условиях) хорош тем, что не меняется адрес страницы, а значит страница будет одинаково выглядеть для разных языков. Это сильно упрощает её администрирование.

Редиректы

Делаются отдельные языковые страницы, где в начале страниц прописываются редиректы:

<?php 
    if (getConfig('userLang') == 'uk') header('Location: АДРЕС для UK');
    elseif (getConfig('userLang') == 'en') header('Location: АДРЕС для EN'); 
?>

текст

Тогда пользователь будет автоматом перемещён на нужную языковую страницу. В таком подходе нужно учитывать, что фактически это разные страницы сайта, поэтому у них могут быть совершенно отдельные настройки.

Указание альтернативной языковой версии

Гугл рекомендует для страниц, которые являются языковыми копиями, прописывать соответствующие meta-тэги. В Albireo это делается в настройках страницы:

head-lang[uk]: [SITE_URL]uk/sample-page
head-lang[en]: [SITE_URL]en/sample-page
head-lang[ru]: [SITE_URL]ru/sample-page

Что приведёт к такому коду:

<link rel="alternate" hreflang="uk" href="https://site.com/uk/sample-page">
<link rel="alternate" hreflang="en" href="https://site.com/en/sample-page">
<link rel="alternate" hreflang="ru" href="https://site.com/ru/sample-page">

Поле head-lang также используется для автоматического формирования альтернативных адресов для sitemap.xml.

Перевод отдельных фраз

Для перевода отдельных фраз используется функция lang() — она принимает фразу для перевода. Если его нет, то возвращается исходная фраза.

Сам перевод хранится в отдельных файлах в каталоге конфигурации langs, где каждый язык в отдельном подкаталоге. Файлы возвращают обычный php-массив, примерно так:

// uk

return [
    'Powered by Albireo CMS' => 'Працює на Albireo CMS',
    'The site uses cookies' => 'Сайт використовує cookies',
    'Terms of Use' => 'Умови використання',
    'Sitemap' => 'Карта сайту',
    'Contacts' => 'Контакти',
    'Projects' => 'Проекти',
    'Links' => 'Посилання',
    'Categories' => 'Рубрики',

    'Related Posts' => 'Схожі записи',

    'Tags' => 'Мітки',
    'Categories' => 'Рубрики',

    'RSS comments' => 'RSS коментарі',
];

По умолчанию используется английский язык, поэтому есть отдельно русский и украинские переводы. Таким способом можно переводить тексты в разных частях сайта: шапки, подвалы, меню, виджеты и т.п.

Перевод работает как с фразами, так и их «кодом». Например можно указать lang('content-about'), а в языковых файлах:

    'content-about' => 'Працює на Albireo CMS',

Сами языковые файлы произвольны, поэтому можно выделить свои переводы отдельным файлом — они все подключатся скопом.

Динамическая замена языковых полей

При желании можно указать языковые фразы каждого языка в полях страницы. Для этого используется поле такого формата: lang.ЯЗЫК[ПОЛЕ]. Например у нас есть страница условия использования сайта, которая меняет свой title в зависимости от языка пользователя.

# фраза для языка по умолчанию
title: Условия использования и копирайты

# языковой перевод для каждого языка
lang.en[title]: Terms of Use and Copyright
lang.uk[title]: Умови використання та копірайти

Albireo CMS при формировании данных страницы, автоматически заменит поле title на то, которое соотвествует языку посетителя. У конструкции lang.XX[YY] можно указывать произвольные поля и значения.

Такой вариант языкового перевода хорош тем, что нет необходимости менять файл словаря.

Если текст страницы полностью делает вывод на языке посетителя, то для смены lang-атрибута тэга HTML нужно прописать код, как указано выше:

html[lang]: <?= getConfig('userLang') ?>

Использование PHP

Поскольку в полях страницы можно использовать PHP-код, то изменить поле на нужный язык можно и с помощью функции lang():

title: <?= lang('Categories') ?>

Таким образом система выполнит перевод слова для этого поля.

Подобным образом можно создавать достаточно сложные конструкции. Например страница меток формирует title в зависимости от адреса. Если адрес содержит сегмент, то это вывод метки. А если сегмента нет, то выводится просто титул «Метки». Вот php-код для демонстрации возможностей Albireo CMS:

title: <?= CURRENT_URL['segment1'] ? lang('Tag') . ': «' . CURRENT_URL['segment1'] . '»' : lang('Tags') ?>

Этот код будет эквивалентен (пример для украинского):

# для страницы сайт/tags
title: Мітки

# для страницы сайт/tags/метка
title: Мітка: «Астрономия»
Я не знаю других систем, где подобное можно реализовать в одну строчку кода.

Использование PHP в полях позволяет создавать переводы для фраз, которые могут потом использоваться в теле страницы. Демо-пример возможностей системы:

# произвольное поле
# по умолчанию
my: Солнце

# языковые версии
lang.uk[my]: Сонце
lang.en[my]: Sun

Получение значения поля происходит с помощью функции getPageData('поле'):

pr(getPageData('my')); // Солнце или Сонце или Sun в зависимости от языка посетителя

При необходимости получить исходное значение поля my (если была замена) можно с помощью префикса _old.:

pr(getPageData('_old.my'));

Отладка языкового перевода

Если в конфигурации сайта включена отладка сайта (автоматом это сделано для LOCALHOST), то в случае, если переводимая фраза не найдена для текущего языка (кроме EN), внизу сайта выводится отладочная панель, которая выводит массив отсутствующих слов и его язык. Таким образом в процессе написания кода, можно сразу контролировать языковые словари.


Слава Украине! Смерть рашистам!


Related Posts
Comments (11) RSS
1 Віктор 2024-09-19 21:10:45

Лишається проблема, що не була згадана - переклад шаблону.

Як варіант, бачу її рішення через використання lang() для шаблона в комбінації з одним із способів мультипейджу (або я чогось не зрозумів). І чи буде це працювати для панелі адміністратора у варіанті "з коробки"?

Попередні Албірео-версії (до анонсу CMS) прийшлося перекладати адмінку вручну, так би мовити.


2 Макс 2024-09-20 10:07:50 admin

Админку я принципиально не хочу переводить — там по английски и по сути нечего переводить, всё слишком примитивно.

А шаблон нужно переводить через lang(). И опять же, все сам по себе шаблон состоит только из html и css, там нечего переводить. Все служебные сообщение уже переведены. Если нужен перевод, то он указывается на самой странице, либо в конфигурации с помощью lang(). Может будут какие-то доработки, но в целом этого достаточно для 100% мультиязычности.


3 Віктор 2024-09-21 08:29:50

Чи виникає (при мультимовному сайті) необхідність вказувати це у sitemap?

Чи google сам розбереться?


4 Макс 2024-09-21 09:39:57 admin

Там же только адреса, переводить нечего.


5 Віктор 2024-09-21 10:58:49

Можливо, питання було сформульовано некоректно, але мова про інше:

Якщо існують кілька версій сторінки різними мовами, то в результатах пошуку мають бути представлені ті версії сторінок, які краще підходять регіону користувача. Це не обов'язково, звісно, але все ж таки.


6 Макс 2024-09-21 11:01:51 admin

Нужно доки гугла смотреть... Но думаю, что ему всё равно нужно будет проиндексировать все страницы, поэтому в sitemap должны попасть все.


7 Віктор 2024-09-21 11:43:02

Так, я вже подивився (краще б не питав). Рекомендовано (!) вказувати альтернативи ленгвіджу, на що є кілька варіантів:

html-теги в хедері, або sitemap, вибір залежно від смаків автора CMS :o)

p.s. не знаю, чи коректно додавати в коментар посилання на доки.


8 Макс 2024-09-21 11:51:12 admin

В head можно добавлять, как я и написал. Но насчет sitemap.xml я не в курсе. Кинь ссылку, я посмотрю. Думаю, что добавить параметр в генерацию этого кода не будет очень сложным.


9 Віктор 2024-09-21 12:10:53

Давай спробуймо, може комусь теж цікаво: localized-versions


10 Макс 2024-09-21 12:17:02 admin

Думаю, что можно сделать. Нужно будет подумать, может просто сделать отдельнй параметр старницы, что-то вроде lang[uk]: адрес а система уже сама раскидывать его на head и sitemap.


11 Макс 2024-10-03 14:47:43 admin

Поправил статью. Добавил описание других возможностей.

Leave a comment!