vorst.ru - Page 2. Статьи о задачах возникающих при создании сайта и их решении
Статьи помеченные Yii2

Как разместить контент на двух языках

Перевод контента сайта

Для перевода интерфейса в Yii применяется таблица из двух колонок. В первой колонке записываются слова или фразы на английском, во второй - перевод на русском. Строки отсортированы по первой колонке. В тексте программы вместо нужного слова или фразы вызывается функция t('Word or Phrase'). Если текущий язык сайта английский, функция возвращает параметр, иначе соответствующий перевод.

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


Виджет для вывода списка рубрик Nested Set

Выбор всех статей по рубрике

В конце предыдущей статьи были указаны две вещи, которых не хватает для начала использования рубрикатора.

Первая из них - необходимо добавить поле rubric в таблицу post. С этой операцией связано и изменения в модели common/models/Post, которые очевидно касаются методов rules() и attributeLabels().

Кроме этого нужно добавить обработку выбранной пользователем рубрики в actionIndex() контроллера frontend/controllers/PostController.


Простые действия над деревом Nested Set

Что нужно учесть для CRUD

Все необходимые методы, для управления деревом Nested Set уже определены в расширении.

Поэтому изменения в стандартном контроллере совсем небольшие. Нужно, например, вместо стандартного метода save() модели использовать метод prependTo() расширения, а вместо delete(), deleteWithChildren().


Представления для операций с Nested Set

Что нужно учесть в представлениях при редактировании Nested Set

Мы, в общих чертах, разобрались с деревьями Nested Set и создали модель для хранения дерева. В модели определили пару простых методов.

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


Подключение расширения Nested Set

Определение данных и необходимых методов в модели

Мы получили общее представление о древовидной структуре данных называемой Nested Set. Теперь пришло время подключить к блогу соответствующее расширение.

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


Как устроена структура данных Nested Set

Как сделать рубрикатор

Рубрикатор, как средство поиска интересных статей, имеет свои недостатки - трудно придумать иерархию, названия рубрик, трудно потом решить к какой конкретно рубрике относится статья. "Но, так принято" - скажите вы и будете правы.

Поэтому, давайте делать рубрикатор.


Какую статью выбрать следующей или предыдущей

Как выбрать все статьи в цепочке

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

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


Цепочки статей в блоге

Можно ли сделать блог удобнее?

Ну, во-первых, удобнее по отношению к чему? К WordPress, например. Некоторое время назад я использовал эту программу для ведения блога.

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



Поиск



Как разместить контент на двух языках

Перевод контента сайта

Для перевода интерфейса в Yii применяется таблица из двух колонок. В первой колонке записываются слова или фразы на английском, во второй - перевод на русском. Строки отсортированы по первой колонке. В тексте программы вместо нужного слова или фразы вызывается функция t('Word or Phrase'). Если текущий язык сайта английский, функция возвращает параметр, иначе соответствующий перевод.

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


    Поделиться

Пусть каждый тег с русским текстом имеет класс .ru, а такой же тег с английским текстом имеет класс .en.

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

Заголовки на разных языках будем разделять символом "/".

Behavior

В поведении LangSwitcher.php определены два метода, которые удаляют, не нужную на данный момент, часть контента. Первый тот, что удаляет не нужные теги.

private static $languages = ['ru' => 0, 'en' => 1];
private static $opposite = ['ru' => 'en', 'en' => 'ru'];
private static $translatedTags = '(h1|h2|h3|h4|p|ul|ol|blockquote)';
...
public function excludeByLanguage($attribute = 'excerpt')
{
    return preg_replace('/<' . 
        self::$translatedTags . ' class="'. self::$opposite[$this->language] .'">(.+)<\/' . 
        self::$translatedTags . '>/isU', '', $this->owner->$attribute);
}

Второй выбирает нужную часть заголовка.

public function splitByLanguage($attribute = 'title', $language = null)
{
    $language = $language ? $language : $this->language;
    $vals = explode('/', $this->owner->$attribute);
    return (count(self::$languages) == count($vals))
        ? trim($vals[self::$languages[$language]])
        : $this->owner->$attribute;
}

Теперь в представлении достаточно вызывать нужный метод. Например так:

<div class="post-excerpt">
    <?= $model->excludeByLanguage('excerpt'); ?>
</div>

RSS & feeds

Чтобы сервисы, предоставляющие информацию по требованию извне, получали нужную языковую версию нужно переопределить в модели метод fields (пример rss).

public function fields()
{
    return [
        'id', 'author_id', 'slug', 'previous', 
        'title' => function ($model) { return $model->splitByLanguage('title');},
        'subtitle' => function ($model) { return $model->splitByLanguage('subtitle');},
        'excerpt' => function ($model) { return $model->excludeByLanguage(); },
        'content' => function ($model) { return $model->excludeByLanguage('content'); },
        'resume' => function ($model) { return $model->excludeByLanguage('resume'); },
        'tags', 'rubric', 'status', 'created_at', 'updated_at', 
        'keywords' => function ($model) { return $model->splitByLanguage('keywords');},
        'description' => function ($model) { return $model->splitByLanguage('description');},
    ];
}

Как скрывается текст с одним языком и показывается другой теперь понятно. Но как узнать, какой язык сейчас текущий и как его переключить?

Первую часть работы выполняет widget. Он определяет и устанавливает текущий язык используя cookie. Cмену языка выполняет действие контроллера. Виджет и контроллер можно посмотреть в расширении - yii2-lang-switcher.

Static pages

С динамичным контентом все ясно, а что делать со статичными страницами? В них хотелось бы использовать тот-же подход. Для этого нужно пропустить вывод метода renderContent контроллера через фильтр аналогичный методу excludeByLanguage упомянутому выше.

Поэтому в расширении github.com/yii2-lang-switcher есть еще один контроллер. От него должен наследоваться например frontend\controllers\SiteController.php.

use sergmoro1\langswitcher\controllers\Controller;
class SiteController extends Controller
{

Заключение

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

Оставить комментарий

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