Я думаю, что gettext больше подходит для перевода сообщений, кнопок, подписей и так далее.И не динамический контент.Для этой цели вы можете пойти несколькими различными путями в зависимости от требований проекта.Во-первых, вы должны решить:
- Насколько гибким должен быть механизм перевода.Вам нужно часто добавлять новые переведенные таблицы или обновлять структуру существующих таблиц?Вам нужно часто добавлять новые языки?
- Вам нужно отслеживать изменения исходного контента и деактивировать все переводы, когда оригинал был изменен.
- Вам нужен сервер для премодерации переводов(если в переводе участвуют несколько человек)
Для решения с максимальной гибкостью и расширяемостью вы можете пойти дальше.Оригинальные таблицы остаются без изменений.Для переводов вы добавляете таблицу translations
со столбцами:
id
первичный ключ object_table
имя переведенной таблицы object_id
ссылка напереведенный объект language
или language_id
, если вам нужно динамически управлять языками field
имя переведенного поля original_md5
хэш исходного значения поля (если вам нужно отслеживать изменения) translation
author_id
, published
, date
и другие поля, необходимые для модерации, если вам это нужно.
Затем в другой таблице или файле конфигурации вы описываете, какие таблицы и поля нужно перевести.Вы также можете описать типы полей, например, text
, textarea
, html
, file
и т. Д.
Например:
$translatedFields = array(
// here key stands for translated table name
'posts' => array(
// here key stands for translated field
// and value for field's type
'title' => 'text',
'body' => 'html',
),
);
Затем в вашемСлой доступа к данным вы определяете текущий язык и подставляете все запросы SELECT в таблицы, которые должны быть переведены.Здесь вам может помочь немного волшебства регулярного выражения и строгий синтаксис ваших запросов.Запрос SELECT title, body FROM posts WHERE posts.id='1'
превращается в
SELECT
IF(posts_title_translation.translation IS NULL,
posts.title,
posts_title_translation.translation) AS title,
IF(posts_body_translation.translation IS NULL,
posts.body,
posts_body_translation.translation) AS body
FROM posts
LEFT JOIN translations AS posts_title_translation
ON posts_title_translation.object_id = posts.id
AND posts_title_translation.object_table = 'posts'
AND posts_title_translation.language = '$language'
AND posts_title_translation.field = 'title'
---- And if you need premoderation, then filter off unpublished translations
--AND posts_title_translation.published
LEFT JOIN translations AS posts_body_translation
ON posts_body_translation.object_id = posts.id
AND posts_body_translation.object_table = 'posts'
AND posts_body_translation.language = '$language'
AND posts_body_translation.field = 'body'
--AND posts_body_translation.published
WHERE posts.id = '1'
(выражение IF в разделе SELECT позволяет выбрать исходное поле, если его перевод или публикация не выполняются).
Вот каку вас может быть гибкая система i18n.Переводы выполняются для каждого отдельного поля и автоматически подставляются в слой доступа к данным при выборе.
Это немного сложно, и, скажем так, частично под влиянием Joom! Fish расширение для Joomla !,но вот как я это сделаю.
Я добавлю еще один ответ для более простого решения, потому что оно уже слишком велико.