Как сделать двуязычный сайт - vorst.ru

Два языка


переводим контент сайта

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

Два языка

переводим контент сайта

Для перевода интерфейса в 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мену языка выполняет действие контроллера. Виджет и контроллер можно посмотреть в расширении - github.com/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
{

Заключение

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

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

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