CMS Eleanor - Поиск
Полная версия этой страницы: Официальный форум Eleanor CMS » Как делать мультиязычность?
Официальный форум Eleanor CMS » Для вебмастеров и владельцев сайтов » Комната программистов
Страницы: 1, 2
Alexander
Сегодня настал тот момент, когда я всерьез задумался над реализацией алгоритмов мультиязычности системы. Сразу скажу, что параметр языка будет передаваться при помощи куки, а не через адресную строку. Но давайте по порядку.

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

Чтобы избежать вышеописанных неприятностей, я решил, все языковые варианты новости (давайте для примера возьмем модуль "Новости) будут хранится в одной записи в БД. Для этого я создал несколько вариантов полей каждого атрибута новости: `title_russian`, `title_english`, `title_ukrainian`; `sokr_text_russian`, `sokr_text_english`, `sokr_text_ukrainian`; `text_russian`, `text_english`, `text_ukrainian`. Для служебных полей типа "meta description" думаю копии полей создавать не нужно - это на 99.999% делается для поисковиков, а не для людей.

При публикации новости, нужно будет заполнить по три поля для каждого атрибута. Например:

Заголовок (русский):
Заголовок (english):
Заголовок (українська):

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

ЗЫ. Естественно, если сайт будет не мультиязычный, будет использоваться только одно поле (например `title_russian`), а все остальные будут "болтаться". Но не думаю, что это скажется на производительности. При отключенной мультиязычности модуля (у каждого модуля будет сделана такая настройка), при публикации контента подсказки возле полей (Заголовок (русский):) будут убираться.

ЗЫЫ. Текст настроек, как и сами настройки, переводится не будет. Это значит, что название сайта, его описания и другие опции, которые настраиваются в интерфейсе настроек будут независимыми от языка.
Alexander
Неужели ни у кого не будет предложений/идей/критики?
Не думаю шо будет так много людей кто будет использовать мультиязычноть. Их просто единицы. Если сайт стоит на 2 языках то заполняется основной, второй для виду присутствует :)
Youshi
Вариант неплохой и легко реализуется. В остальном у него есть куча недостатков:

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

Я лично сделал бы так:
fixed языконезависимая таблица с датами, счетчиками и прочей лабудой + динамическая таблица с трансляциями, привязанная к первой (много к одному)
Alexander
Цитата (Youshi @ 30.12.2008, 15:21)
это ж лишнее место + снижение скорости

Разве? Лишнего места - не так много, поля-то пустые. А снижение? Это же не индексируемые поля..

Цитата (Youshi @ 30.12.2008, 15:21)
1. фиксированный набор языков

Нет. Он не будет фиксированным. В том смысле, что легко этот перечень расширить.
Alexander
Цитата (Youshi @ 30.12.2008, 15:21)
fixed языконезависимая таблица с датами, счетчиками и прочей лабудой + динамическая таблица с трансляциями, привязанная к первой (много к одному)

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

news_id - ид новости, которой принадлежит эта записать
language - язык, к котором относится эта запись
title - заголовок
sokr_text - сокращенный текст
text - подробный текст

Тогда, чтобы выбрать нужные новости, делаем запрос:
SELECT ... FROM `table_news_fixed` AS f INNER JOIN `table_news_lang` AS l ON l.`news_id`=f.`id` WHERE l.`language`='russian'


Точно так и с категориями..

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

Да. При добавлении новости, это получится 2 запроса (1 в основную таблицу и 1 в языковую). А вот при обновлении, это получится 1+N запросов (где 1 запрос - в основную, а N - соответствует количеству языков) - может можно как-то оптимальнее?
Youshi
Цитата (Alexander @ 30.12.2008, 15:52)
Хм.. В принципе идея хорошая. Если я правильно понял, то ты предлагаешь создать две таблицы.


Так точно.

Цитата (Alexander @ 30.12.2008, 15:52)
Да. При добавлении новости, это получится 2 запроса (1 в основную таблицу и 1 в языковую).


Не считаю редактирование новотей такой критичной частью, чтобы заострять такое внимание на оптимизации. Новости не добавляются по сотне раз в секунду (в отличие от просмотров).

Цитата (Alexander @ 30.12.2008, 15:52)
Вот уже вижу одну проблему: как добавить новость для всех языков сразу?


Ajax или динамическая генерация формы для добавления/редактирование новости
Alexander
Цитата (Youshi @ 30.12.2008, 16:12)
Ajax или динамическая генерация формы для добавления/редактирование новости

Ты немного не понял. Я сейчас спрашиваю, как в БД устроить возможность добавления новости сразу для всех языков? Вариант копирования новости для каждого языка меня мягко говоря не прет.
Youshi
Цитата (Alexander @ 30.12.2008, 16:37)
Ты немного не понял. Я сейчас спрашиваю, как в БД устроить возможность добавления новости сразу для всех языков? Вариант копирования новости для каждого языка меня мягко говоря не прет.


Ну так а нафига по-твоему тут аж 2 таблицы?

создаешь новость - id, 4pu, date..... comments заполняются в одной таблице.
в другую вставляешь столько записей, на скольких языках написана новость. остальные просто игнорируются и для тех языков, для которых перевода нет, новость просто не отображается (не вижу смысла показывать в английской версии сайта новости на русском языке).
при редактировании то же самое - если перевод уже есть - обновляешь, если нет - добавляешь или вообще удаляешь, если юзеру вдруг вздумалось оставить поле пустым.
вторая таблица должна иметь вид: id (автоинкремент), lang (идентификатор языка), story (ид. новости), ... прочие поля

надеюсь, теперь я тебя правильно понял? :)
Alexander
Цитата (Youshi @ 30.12.2008, 17:54)
вторая таблица должна иметь вид: id (автоинкремент),

Зачем?

Цитата (Youshi @ 30.12.2008, 17:54)
надеюсь, теперь я тебя правильно понял? smile.gif

Нет немного. Я спрашивал, можно ли сделать так, чтобы одна записать в второй таблице (где хранится контент) использовалась для всех языков. Тут ты ответил:

Цитата (Youshi @ 30.12.2008, 17:54)
не вижу смысла показывать в английской версии сайта новости на русском языке

Представь, что сайт будет русско-укранским. Возьмем к примеру задачу, когда нужно опубликовать какой-то приказ (документ) для всех языков. Или вообще, повесить новость, состоящую из одной картинки (текст отсканированный). Просто вставка N одинаковых записей в таблицу (N=количеству языков), чтобы отобразить новость для всех языков хз почему кажется мне не оптимальной..

ЗЫ. Систему будешь брать?
ЗЫЫ. Насчет интерфейса для многоязыковости - я с Сергеем поговорю.
Youshi
Цитата (Alexander @ 30.12.2008, 18:11)
Зачем?


Уже не помню зачем, но должно быть в таблице поле с unique индексом. хотя конечно если грамотно создать индекс, это не понадобится.

Цитата (Alexander @ 30.12.2008, 18:11)
хз почему кажется мне не оптимальной..


Да потому что это не оптимально :)

Цитата (Alexander @ 30.12.2008, 18:11)
Я спрашивал, можно ли сделать так, чтобы одна записать в второй таблице (где хранится контент) использовалась для всех языков.


попробую на досуге создать пару табличек и набросать запрос. есть мысль....
Youshi
Так. Вот первый набросок.

Таблицы:

--
-- Структура таблицы `news`
--

CREATE TABLE `news` (
`id` int(10) unsigned NOT NULL auto_increment, -- идентификатор новости
`date` int(10) NOT NULL default '0', -- дата
`xxx` varchar(10) NOT NULL, -- какое-то поле
`yyy` varchar(10) NOT NULL, -- еще какое-то поле
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;

-- --------------------------------------------------------

--
-- Структура таблицы `news_t`
--

CREATE TABLE `news_t` (
`id` int(10) NOT NULL auto_increment, -- без комментариев
`lang` smallint(5) NOT NULL default '1', -- идентификатор языка
`story` int(10) NOT NULL, -- идентификатор новости
`text` text NOT NULL, -- текст новости
PRIMARY KEY (`id`),
KEY `lang` (`lang`,`story`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 ;


и вот запрос на выборку всех новостей без каких-либо ограничений:

SELECT n.id, n.date, t.lang -- t.lang надо выбирать в обязательном порядке
FROM news AS n
LEFT JOIN `news_t` AS t ON ( t.story = n.id ) -- тут все понятно, я думаю
GROUP BY n.id -- группируем под id новости, чтобы не было дублей
HAVING ( -- выбираем, какой перевод отображать
t.lang =2 -- если есть перевод для языка 2, выбираем его
OR t.lang =1 -- иначе берем язык по умолчанию (в данном случае 1)
)

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

надеюсь, понятно объяснил.

UPD. Чет запрос не так работает, как предполагалось :)... думаю дальше...
Alexander
Цитата (Youshi @ 31.12.2008, 11:59)
LEFT JOIN

Зачем LEFT? INNER - намного логичнее.

Цитата (Youshi @ 31.12.2008, 11:59)
HAVING

Зачем HAVING? WHERE же есть.. HAVING - это для агрегатных функций..

И так и не понял, зачем группировать.. От каких дублей это нас спасает?
Youshi
Цитата (Alexander @ 31.12.2008, 13:28)
Зачем LEFT? INNER - намного логичнее.


А чтобы было. Я ж написал:
Цитата (Youshi @ 31.12.2008, 11:59)
без каких-либо ограничений


Цитата (Alexander @ 31.12.2008, 13:28)
Зачем HAVING?


А за тем, что сначала выбираются все удовлетворяющие записи из обеих таблиц, а затем уже уточняется язык. HAVING выполняется после получения всех записей, удовлетворяющих условию WHERE, а не только используется для групповых функций.

Цитата (Alexander @ 31.12.2008, 13:28)
И так и не понял, зачем группировать.. От каких дублей это нас спасает?


Если у новости есть 3 перевода, запрос вернет 3 записи для одной новости. вот от этого и спасает.
Alexander
Цитата (Youshi @ 31.12.2008, 15:03)
Если у новости есть 3 перевода, запрос вернет 3 записи для одной новости. вот от этого и спасает.

А зачем нам показывать русские новости, на английской версии сайта?

Я пока использую запрос:
SELECT * FROM `table_news` INNER JOIN `table_news_lang` USING(`id`) WHERE `language`='russian' AND `id`=N

Чем такой запрос хуже?

Вот, для большего понимания:
CREATE TABLE `el_news` (
  `id` int(11) NOT NULL auto_increment,
  `url` varchar(100) NOT NULL,
  `cid` int(11) NOT NULL default '0',
  `status` tinyint(1) NOT NULL default '1',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `url` (`url`),
  KEY `cid` (`cid`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;


CREATE TABLE `el_news_lang` (
  `id` int(11) NOT NULL,
  `language` varchar(10) NOT NULL,
  `title` varchar(200) NOT NULL,
  `text` text NOT NULL,
  KEY `language` (`language`),
  KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
Youshi
Цитата (Alexander @ 31.12.2008, 14:41)
Чем такой запрос хуже?


ничем не хуже

Цитата (Alexander @ 31.12.2008, 14:41)
А зачем нам показывать русские новости, на английской версии сайта?


я тебе об этом с самого начала толкую. ты повторяешь мои слова.

Цитата (Youshi @ 30.12.2008, 16:54)
не вижу смысла показывать в английской версии сайта новости на русском языке


но при этом говоришь:

Цитата (Alexander @ 30.12.2008, 17:11)
Возьмем к примеру задачу, когда нужно опубликовать какой-то приказ (документ) для всех языков.



как ты решил в этом запросе поставленную тобой же задачу?

в общем ты меня запутал....
Alexander
Цитата (Youshi @ 31.12.2008, 15:21)
как ты решил в этом запросе поставленную тобой же задачу?

в общем ты меня запутал....

Новый год все-таки..)) Вкратце: русские новости не должны показываться в английской версии сайта и наоборот. Но:
1. Должна быть возможность установить одну новость для всех языков. Это не значит, что так должно быть по-умолчанию.
2. Если мы переходим к просмотру новости (мало-ли, может кто-то ссылку кинул) с языком, на котором новость не доступна - новость должна быть отображена на языке по-умолчанию.

Так ясно?
Youshi
Цитата (Alexander @ 31.12.2008, 18:49)
Так ясно?


Теперь ясно. :)
Alexander
Цитата (Youshi @ 31.12.2008, 19:53)
Теперь ясно. smile.gif

Будут идеи с примерами?
Youshi
Цитата (Alexander @ 31.12.2008, 19:16)
Будут идеи с примерами?


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