Многоязычный сайт в Drupal

Аватар пользователя axel
Вообще-то официально многоязычности в Drupal нет (работы как водится
ведутся - см. CVS contrib, но в движок эти наработки войдут врядли
скоро). Есть возможность иметь разные языки интерфейса (с помощью
locale.module) и переключаться между ними, но для всего содержимого
сайта это не подходит. Тем не менее такой вариант настройки Drupal как
multisiting (несколько сайтов использующих один набор скриптов),
совместно с другой полезной функцией - простановкой префикса к таблицам БД
позволяют достичь желаемого и получить многоязычный сайт, подходящий
для многих применений.

Префиксы к базе, как и мультисайтинг - не
новость в технологиях, это используется во многих CMS и разных
вебскриптах. Мультисайтинг позволяет сэкономить немного места, за счет
использования одного экземпляра скрипта на несколько сайтов (баз
данных), а префиксы к таблицам БД позволяют легко разделить
использование одной общей базы между различными скриптами.



В Drupal префиксы задаются в файле конфигурации includes/conf.php в
переменной $db_prefix:

$db_prefix = "drop_";

- и Drupal будет искать все таблички по именам начинающимся с "drop_" -
drop_users, drop_node и т.д. Однако, Drupal предоставляет возможность
более гибкой настройки - можно указывать собственный префикс для
каждой таблицы в отдельности. Как может быть полезной такая на первый
взгляд лишняя возможность для настройки многоязычного сайта мы увидим
ниже.



Много сайтов на одном скрипте в Drupal задается следующим интересным
образом. По умолчанию ищется конфигурация в includes/conf.php, однако
перед этим движок пытается найти в директории includes php-файл имя
которого совпадает с URL сайта. Если не находит - обращается к конфигу
по умолчанию. Т.е. если сайт размещен как example.com/drupal/, то Drupal
пытается найти файл example.com.drupal.php и считать конфигурацию из
него, а обратившись по www.example.com можно рассчитывать, что движок
попытается обратиться к конфигу www.example.com.php. Довольно элегантно,
учитывая, что можно не дублировать файлы, а ставить на них линки:

www.example.com.php -> example.com.php

Разобравшись с префиксами и мультисайтами вернемся к первоначальной
задаче - получению сайта с многоязычным контентом. Тупое решение
задачи "в лоб" - установка нескольких Drupal'ов в отдельных
директориях (по количеству языков) и использование отдельных сайтов
под отдельные языки. Отталкиваясь от этого не самого оригинального
способа приведем его к более юзабельному виду используя
предоставляемые в Drupal функции. Допустим, нам надо получить сайт для
двух языков - русского и английского.



Ставим Drupal например в корень сайта и дополнительно создаем две
директории, скажем en и ru - для английского и русского сайта
соответственно. Создадим сначала en и в ней создадим файловые линки:

$ ln -s ../index.php

- и так для всех нужных нам директорий и файлов, получив в директории
en набор ссылок:

index.php -> ../index.php
includes -> ../includes
modules -> ../modules
misc -> ../misc
themes -> ../themes
xmlrpc.php -> ../xmlrpc.php
cron.php -> ../cron.php
error.php -> ../error.php

Поскольку делаем мы все не тяп-ляп, нам наверняка захочется коротких
URL, для чего в Drupal требуется чуть подправить поставляемый с ним
.htaccess. Поэтому на него мы не ставим линк, а копируем его в
поддиректорию. Окончательный листинг:

$ ls -la en

.htaccess
index.php -> ../index.php
includes -> ../includes
modules -> ../modules
misc -> ../misc
themes -> ../themes
xmlrpc.php -> ../xmlrpc.php
cron.php -> ../cron.php
error.php -> ../error.php

Теперь можно сделать cp -ar en ru, чтобы не делать лишнюю работу для
русской директории и займемся правкой .htaccess. Нам требуется
проставить корректные RewriteBase, чтобы mod_rewrite (полагаю нет
необходимости объяснять, что этот модуль должен быть установленным в
Apache) корректно распознал URL при обращении к разноязыким частям
сайта. Для en/.htaccess тогда получим:

RewriteBase /en

Для ru/.htaccess:

RewriteBase /ru

А в .htaccess лежащем в корне сайта следует тогда оставить:

RewriteBase /

Разумеется, настройка RewriteBase зависит от местоположения вашей
установки Drupal, за подробностями следует смотреть в документации
Apache раздел "URL Rewriting Guide". Тут мы не будем этим
заморачиваться, ок?



Перейдем к конфигу сайта. То бишь в директорию includes. Итак,
возможны разные варианты обращения к сайту, например его можно позвать
просто по доменному имени mysite.ru, особо сознательные юзеры могут
сделать это с приставкой www - www.example.com, а для обращения к
национальным частям будем считать нам надо обращаться к mysite.ru/en и
example.com/ru (особо сознательные юзеры могут опять-таки делать это с
приставкой www). Какой сайт выдавать при обращении просто к example.com,
русский или английский? Тут возможны варианты, в зависимости от ваших
целей. Можно определять по посылаемой броузером переменной язык
и пересылать на соответствующий национальный сайт, можно не
озадачиваться и попросту сделать один из сайтов дефолтным, в
зависимости от основного языка аудитории. Для простоты примем, что по
mysite.ru пользователи должны видеть русскую часть сайта, а если им
это не понравиться по очевидной любому незнакомому с великим и могучим
кнопочке с американским (для эстетов английским) флажком переходить на
английскую часть сайта, одновременно с переключением интерфейса на
английский. Тогда настраиваем conf.php для начала (цитирую не
полностью conf.php, очевидно, что настройка доступа к БД будет общей
для всех сайтов, а здесь нам интересны $db_prefix, $base_url и
$languages):

$ cat conf.php

$db_prefix = "ru_";

$base_url = "http://example.com/";

$languages = array("ru" => "russian");

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



Теперь копируем conf.php в example.com.ru.php и example.com.en.php. Правим
эти новые файлы:

$ cat example.com.ru.php

$db_prefix = "ru_";

$base_url = "http://example.com/ru";

$languages = array("ru" => "russian");
$ cat example.com.en.php

$db_prefix = array("default" => "en_", "users" => "ru_", \\
  "sessions" => "ru", "sequences" => "ru_", "roles" => "ru_");

$base_url = "http://example.com/en";

$languages = array("en" => "english");

На этом этапе идея полагаю уже понятна? С помощью задания массива
префиксов мы получаем общую пользовательскую базу для сайтов и общие
сессии, т.е. переходя между сайтами посетителю не придется
перелогиниваться. Действуя с осторожностью список общих таблиц можно
продолжить (смотря по задаче - насколько общими должны быть сайты),
например можно слить вместе таксономии:

$db_prefix = array("default" => "en_", "users" => "ru_", \\
  "sessions" => "ru", "sequences" => "ru_", "roles" => "ru_", \\
  "term_data" = "ru_", "term_hierarchy" = "ru_", \\
  "term_node" = "ru_", "term_relation" = "ru_", "term_synonym" = "ru_");

Можно еще что-нибудь, впрочем если особо увлечься в конце концов это
приведет к полностью общему сайту, нам это вроде не надо? :) Будьте
особо осторожны с sequences, если сделать ее разной для двух сайтов,
то возникнут некоторые накладки при создании новых пользователей, ведь
именно из sequences в Drupal произрастают всяческие ID, используемые
для других таблиц. А при использовании общей таблицы sequences ситуация
разруливается им корректно: каждая последовательность именуется с
префиксом базы, так скажем для таблицы node это будут записи ru_node и
en_node, а для общих пользователей все будет браться только из
ru_users. Вероятно где-то на этапе дальнейшего слияния баз могут
возникнуть какие-нибудь еще заморочки подобного рода, связанные со
взаимозависимостью таблиц, слишком глубоко я не копал, оставляю
вам это развлечение.



Теперь остается создать базы данных, корректно проставив в
SQL-скриптах префиксы - en_ и ru_. Для английской части сайта таблицы
с префиксом ru_ создавать не требуется, их можно вообще выкинуть из
скрипта, чтобы не мешались - ведь они будут браться из русских таблиц.



Теперь для эстетики можно еще понаделать линков на эти конфиги,
например под приставки www:

$ ln -s example.com.ru.php www.example.com.ru.php

$ ln -s example.com.en.php www.example.com.en.php

Собственно все, не забудьте только повесить на сайтах кнопочки для
переключения сайтов. В итоге получаем следующую картину. Посетитель
заходит на наш сайт example.com и видит его на русском. Ткнув в
линк/кнопочку английского сайта он не перелогиниваясь попадает на
английскую часть сайта, которая может иметь полностью независимое
содержимое (но например такую же логическую структуру, если
таксономия сделана общей). Степень независимости сайтов тут зависит
от вашей фантазии и потребностей. В принципе, не самый плохой вариант
многоязычного сайта для CMS в которой многоязычность вроде как не
поддерживается. При этом вполне экономно использующий ресурсы - ведь у
нас фактически одна установка Drupal на сколько угодно сайтов и
отдельные таблицы в базе используются для хранения разноязыкого
контента, а общее содержимое (как пользователи и сессии) - хранятся в
общих таблицах.

Версия Drupal:
0 Спасибо

Комментарии

Аватар пользователя B.X
B.X 13 лет назад

Да, на основе этой статьи видно, что до мультиязычности Drupal'у пока ещё далеко. Это скажем просто если два языка. А если скажем 22? Хех, тогда это будет задача.

Неужто не проще написать пару скриптов, которые решали бы эту проблему? Как создания дополнительных баз, так и всего прочего? Да и вообще, мне кажется, что уже сейчас нужно создавать все таблицы и модули с прицелом на это. Например, если у тебя русский сайт, то пусть он и создаёт всё в ru каталоге, и БД создаёт с префиксом ru. Это ведь несложно, за то потом проще будет...

Всё это можно будет решить написав достаточно грамотный инсталлятор для Drupal. Давно пора, что называется, но сейчас как раз самое время, раз заговорили о мультиязычности.

0 Спасибо
Аватар пользователя axel
axel 13 лет назад

Да хоть 122 языка, написать скрипт который будет делать "cp -r" один раз созданной шаблонной директории с линками и sed'ом проходить по .htaccess и скрипту базы с вызовом mysql по-моему настолько не проблема, что даже не стал на этом останавливаться. Полагаю, у кого возникают такие задачи - скриптик сам напишет. Однако самая технология мультисайтов и префиксов к базам к Drupal по-моему реализована очень удачно (что я и хотел сказать в статье) и это позволяет делать такие штуки как мультиязычность в CMS для этого пока не предназначенной (нет среди features Drupal мультиязычности, т.что если кажется сложным - лучше об этом забыть пока).

Вообще статью не стоит воспринимать буквально, это вовсе не руководство по настройке мультиязычного сайта, как может показаться на первый взгляд :) Это описание возможностей, которые можно реализовать с помощью только настроек мультисайтинга и префиксов к базе (imo, очень удобной является возможность задавать не общий префикс, а префикс к отдельным таблицам). Многоязычный сайт - один из вариантов применения, возможно это не самый лучший пример. Гораздо интереснее - отдельные самостоятельные сайты на одном скрипте, использующие общую базу и частично пересекающиеся по контенту. Скажем такую штуку сейчас подготавливаю на roleplay.ru, где скопилось некоторое количество разных страничек удобных к переводу под Drupal. Странички разные и относятся к разным проектам, в рамках одного сайта объединять их неудобно, настроив Drupal с мультисайтингом можно получить по roleplay.ru/one, roleplay.ru/two совершенно различные сайты, с собственным дизайном и набором включенных модулей, однако мне интересно сделать общую пользовательскую базу, с общими сессиями, поскольку хотя и разные страницы, тематика близкая и друг на друга они ссылаются. Правда в этом случае все несколько сложнее и просто общими таблицами обойтись не удается, поскольку на разных сайтах пользователем может быть включен разный набор блоков, а все они хранятся в общей таблице users, в поле data. Теперь вот думаю над реализацией сайтовых префиксов внутри поля data, как это сделано для таблиц :) Это конечно уже немного изврат, но результат будет тем, что мне нужен.

А для мультиязычности рекомендую в CVS contrib взглянуть на модуль i18n.

--
Axel

0 Спасибо
Аватар пользователя Nick
Nick 13 лет назад

http://drupal.org/project/i18n
Появился 4го Апреля
"Fully configurable module for internationalization of drupal sites. Provides interface translation for anonymous users, browser language detection, language-dependant url rewriting and basic content translation. Includes a block for language selection."

--
USU-Lug http://usu-lug.org.ru

0 Спасибо
Аватар пользователя B.X
B.X 13 лет назад

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

0 Спасибо
Аватар пользователя Гость
Гость (не проверено) 13 лет назад

Prostite, eto sluchajno ne oshibka?

Теперь копируем conf.php в mysite.ru.ru.php и mysite.ru.en.php. Правим эти новые файлы:

$languages = array("ru" => "english");
$languages = array("ru" => "russian");

imeq v vidu array-i, gde key "ru" ukazyvaet na value "english" i "russian".
Ia sdelal u sebq tak:

$languages = array("en" => "english");
$languages = array("ru" => "russian");

poka porqdok, rabotaet :-)

0 Спасибо
Аватар пользователя axel
axel 13 лет назад

Да, в тексте ошибочка, сейчас поправлю.

--
Axel

0 Спасибо
Аватар пользователя Vano
Vano 12 лет назад

Так что лучше на текущий момент использовать ?
i18n или описанный выше подход?

0 Спасибо
Аватар пользователя axel
axel 12 лет назад

По задаче смотреть. Если требуется синхронное ведение контента на разных языках - i18n. Если сайты сильно разнятся и нет нужды отслеживать, что определённые документ должен являться переводом другого - то надёжнее мультисайтинг.

--
Axel,
www.axel.drupal.ru

0 Спасибо
Аватар пользователя qman
qman 12 лет назад

Следует добавить что в статье http://drupal.org/node/2622 описаны способа использования общими таблицы из разных БД.

0 Спасибо
Аватар пользователя Гость
Гость (не проверено) 12 лет назад

А как можно создать линки из винды на хостинге c linux red hat. Можете ли сказать как я могу проставить ссылки (линки) у себя
в папке en
(какой командой). просто я наверно что- то делал не так (я пробывал через windowscommander команду
ln -s ../index.php ответ unknow command 500 вообщем не знает он ln) помогите пожалуйста.

0 Спасибо
Аватар пользователя clubwave.ru
clubwave.ru 10 лет назад

как можно делать субдомен алиасом без участия службы поддержки хостера?

0 Спасибо
Аватар пользователя stokito
stokito 10 лет назад

у меня в папке includes нет файла conf.php
это нормально вообще? Может уже статья устарела? Просто насколько я в курсе (а я с друплом только второй день разбираюсь :-) то конфиги лежат в папочке sites
Если эта статья устарела подскажите пож ссылочку где я могу прочесть как сделать несколько сайтов с разными доменами на одном движке? Чёта лень мне шнырять по всем бесчисленым докам

0 Спасибо
Аватар пользователя qman
qman 10 лет назад

верно , статья частично устарела, но идея верна.
щас должно быть в sites
всетаки пошныряй по докам по словам multisiting

0 Спасибо
Аватар пользователя pri@drupal.org
pri@drupal.org 10 лет назад

Ксати i18n - опасная штука. Есть там непонятный баг, который вызывает дикий перерасход памяти апачем - под виндой ли, под линухом - глюк остается.
На Денвере еще более-менее работает, но в диспетчере задач видим Apache.exe кушает 139 Mb.
А вот на линукс-хостинге сайт через несколько кликов вылетает с ошибкой 500 и в логах сервера фигурирует перерасход памяти скриптом.

Вопрос - как в винде сделать линки? Ясно, что ярлыки для этой цели не подойдут - так как же тогда?

0 Спасибо
Аватар пользователя nulelemon
nulelemon 7 лет назад
SimpleUser написал:
Многим покажется странным, но я еще пользуюсь Друпалом 4 :)
Спасибо за пост.
___________________________

Лучшее - враг хорошего!

0 Спасибо
Аватар пользователя supersidor7
supersidor7 6 лет назад

Тут бы хоть на русском сайт на Друпале освоить... А так все очень понятно расписано.

0 Спасибо
Аватар пользователя trinitron
trinitron 4 года назад

Очень хочется разработать другой подход к решению этой задачи. Дублирование таблиц с разными префиксами - это вовсе не решение проблемы. Если на сайте 10 языков, то становится ясно что этот подход обречен на провал. Поддержка сайта становится просто не реальной.
В двух словах необходимо следующее:
1. Необходим модуль определения IP-локации пользователя. (Пришел пользователь из USA - главную страничку открываем на английском языке, пришел из России - русскую страничку)
2. Drupal Поддерживает мульти язычность в написании статей соответственно они должны быть написаны ВРУЧНУЮ на всех языках используемых сайтом (это в идеальном случае).
3. Если страница не переведена - используем сервис http://www.bing.com/widget/translator/ для транслитерации.

0 Спасибо
Аватар пользователя Boozenok
Boozenok 4 года назад

подпишусь

0 Спасибо