admin / 29.09.2018

Yii2 и организация мультиязычности / Хабр

Создание собственного виджета в Yii 2.x

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

Создадим в папке components файл TranslitWidget.php. Напишем следующий программный код.

Для вызова виджета напишем следующий код:

// подключаем виджет use app\components\TranslitWidget; …. // к примеру это заголовок новости $titleNews = «Моя первая новость»; // виджет возвращает транслит этой новости а именно moya-pervaya-novost echo TranslitWidget::widget([‘url’ => $titleNews ]);

Вы можете авторизоваться на сайте через:
Vkontakte

Не сразу всё заработало, так что думаю кому-то окажется полезной данная заметка.

Итак будет делать мультиязчность.

Создание виджетов в Yii2

В Yii2 можно делать отдельный перевод для каждого из приложений (application), но в данной заметке я покажу как сделать систему перевода общей для сайта — для всех приложений, ведь в реальности одни и те же фразы на один и тот же язык переводятся одинаково (гарантированно работающий код).

Конфигурация i18n

Поправим файл

/common/config/main.php

так чтобы он выглядит вроде того (нам важна для перевода секция i18n):

<?php return [ ‘vendorPath’ => dirname(dirname(__DIR__)) . ‘/vendor’, ‘components’ => [ ‘cache’ => [ ‘class’ => ‘yii\caching\FileCache’, ], ‘i18n’ => [ // компонент мультизязычности ‘translations’ => [ ‘app*’ => [ ‘class’ => ‘yii\i18n\PhpMessageSource’, ‘basePath’ => ‘@common/messages’, // ВАЖНО! этот путь к папке с переводами ‘sourceLanguage’ => ‘en-US’, // базовым языком путь будет инглиш ‘fileMap’ => [ ‘app’ => ‘app.php’, // группа фраз и её файл-источник ‘app/error’ => ‘error.php’, // для ошибок (тоже какое-то подмножетсво переводимых фраз) ], <strong></strong> ], ], ], ], ];

Обратите внимание на:

‘basePath’ => ‘@common/messages’

Это указание на путь к папке переводов. В данном примере используется псевдоним @common — по идее он должен быть определён как путь до папки /common — общих моментов для всех приложений. В любом случае, если перевод не работает убедитесь что даннымй параметр (‘basePath’) указывает именно на ту папку перевода, которую мы настроим ниже, либо на иную, которую вы хотите использовать.

Файлы перевода

Создадим папку

/common/messages/

— в ней будут располагаться подпапки языков.
В этой папке создадим поддиректорию для языка перевода ru-Ru:

/common/messages/ru-Ru/

— а в неё уже будем забрасывать файлы для групп фраз данного языка, например группа для группы app создадим файл:

/common/messages/ru-Ru/app.ru

С таким содержимым:

<?php // перевод на русский /*массив соответсвия фраз между базовым языком (именно на нём далее мы будем записывать фразы в функцию t() и иным языком в данном случае русским — под выбранным нами обозначением ru-Ru)*/ return [ ‘Clients’ => ‘Клиенты’, ‘Cat’ => ‘Кот’, ];

Установка нужного языка

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

\Yii::$app->language = ‘ru-Ru’;

(например, перед всеми действиями контроллера).

Перевод фразы

А теперь в каком-нибудь действии вашего контроллера, точнее в представлении (view) этого действия напишите строчку:

<?= \Yii::t(‘app’, ‘Clients’) ?>

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

Клиенты

Теперь можно закомментировать приведённое выше выше «указание» на язык:

// \Yii::$app->language = ‘ru-Ru’;

И обновив страницу того же действия контроллера получим фразу на базовом языке:

Clients

Система перевода с помощью файлов .php рассмотренную здесь особенно удобно использовать для перевода интерфейсом, например, виджетов.

Ну вот, собственно и всё) Желаю удачи!

Источники:

  • Интернационализация (офф.

    документация):
    yiiframework.com/doc-2.0/guide-tutorial-i18n.html

  • Интернационализация Yii2 (на русском):
    https://yiiframework.com.ua/ru/doc/guide…
  • Вопрос, содержащий пример файла перевода:
    toster.ru/q/174691
  • Yii2 — Интернационализация проекта (мультиязычность):
    http://atoumus.github.io/yii2-i18n.html
  • Ответ, который дал подсказку (хотя инструкция там несколько избыточна):
    stackoverflow.com/questions/32831288/yii2-translation-does-not-work

Рассмотрим пример интернационализации сайта на Yii 2 на двух языках: ru и en.

В Yii 2 уже встроен компонент отвечающий за интернационализацию, называется он . Для того что бы можно было начать им пользоваться, достаточно добавить его в конфигурацию приложения в раздел . Также, для полноценной работы этого компонента, требуется PHP расширение intl.

В данной статье будет рассмотрен пример интернационализации сайта на Yii 2 на двух языках: ru и en.

Существуют два варианта записей идентификаторов языков:

  • сокращенные, например ru, en;
  • полные, например: ru-RU, en-US.

Мы будем использовать сокращенный вариант (ru и en), т.к. его вполне достаточно для требуемой функциональности и он более лаконично воспринимается визуально.

В качестве кодовой базы можно использовать как уже готовый сайт на Yii 2, так и basic шаблон предоставляемый фреймворком. Как установить basic шаблон можно прочитать в этой статье.

Задача

Сформулируем требования, чего необходимо добиться:

  • переключение сайта между двумя языками: ru и en;
  • отображение языка в адресной строке в виде ;
  • автоматическое перенаправление пользователя на наиболее подходящий для него язык, если он перешел на сайт без указания языка;
  • хранение переводов должно осуществляется в PHP файлах в виде массивов;
  • переводы статических страниц должны содержаться в отдельных представлениях для разных языков.

Конфигурация

Начинаем реализацию с прописывания требуемых для этого конфигураций в файл :

В этой конфигурации:

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

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

— в данной секции включаем ЧПУ, для более наглядного отображения URL’ов.

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

Файл со списком переводов

Теперь необходимо создать PHP файл, который будет содержать в себе ассоциативный массив с переводами.

При конфигурировании компонента мы указали:

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

Для нашего примера с двумя языками (ru и en), достаточно создать один файл с переводами только для русского языка, т.к. переводы английского языка будут в виде ключей для всех остальных переводов. Т.е. везде по сайту будут английские сообщения, при переключении на русский язык, фреймворк будет их подменять на русские.

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

Вносим переводы

Теперь необходимо внести переводы по коду сайта и также добавить их в файл .

Для вывода переводов в Yii 2 существует специальный метод . Пример использования:

В первом аргументе указываем категорию, у нас она одна — . Во втором аргументе пишем английский текст в том виде как он должен отображаться на сайте.

После этого необходимо добавить русский перевод в файл :

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

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

Переключение языков

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

Далее необходимо подключить этот скрипт в главном шаблоне представления , для этого следующую строку:

нужно заменить на:

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

Использование стороннего UrlManager

Теперь нам необходимо сделать так, что бы в строке адреса отображался текущий язык, например . К сожалению Yii 2 не предоставляет для этого каких либо встроенных возможностей, и даже сделать это какими то адекватными обходными путями не получиться, или по крайней мере сложно. Самым "правильным" выходом в этой ситуации будет переопределение стандартного класса на свой собственный, в котором будут заменены некоторые методы.

Как правильно создавать виджеты в Yii2?

Эти замененные методы должны брать на себя реализацию отображения языка в строке адреса.

Вообще замена стандартных классов фреймворка на сторонние, лично на мой взгляд это хард-код. Но судя по всему в рамках фреймворка Yii 2 это к сожалению нормальная практика.

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

Пакет дает нам следующие возможности:

  • отображение текущего языка в адресной строке;
  • перенаправление пользователя на наиболее подходящий для него язык на основе данных отправляемых его браузером.

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

Немного объяснений по данной конфигурации:

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

— на какие языки переведен проект.

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

Интернационализация статических страниц

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

Но по умолчанию интернационализацию он не поддерживает.

Суть в том, что статические страницы имеют большой текст, который не удобно вставлять в файлы переводов (т.е. в нашем случае в файл ). Переводы для статических страниц лучше всего хранить в отдельных файлах — в разных скриптах преставлений которые будут соответствовать разным языкам.

Реализуем интернационализированные статические страницы, для этого в файле , в методе необходимо добавить следующую секцию:

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

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

Теперь настроим ЧПУ для наглядного отображения адресов статических страниц, для этого в конфиге в секцию добавим правило:

На этом, реализация статических страниц закончена, можно проверить, попробовать открыть два адреса в браузере:

  • — откроется русская статическая страница;
  • — английская.

Заключение

В целом реализация интернационализации в Yii 2 не представляет ничего сложного, особенно если использовать сторонний компонент .

Задача, которая была описана в начале статьи полностью выполнена:

  • переключение сайта между двумя языками происходит по ссылке которая расположена в футере;
  • текущий язык отображается в адресной строке в виде ;
  • если пользователь перешел на сайт не указав язык (т.е. ), то он будет перенаправлен на наиболее подходящий язык (т.е. например на );
  • хранение переводов осуществляется в PHP файлах в виде ассоциативных массивов;
  • переводы статических страниц хранятся в отдельных представлениях для разных языков.

Читайте также

Yii 2 — Отправка писем с помощью SwiftmailerYii 2 — Отображение флеш (пользовательских) сообщений на сайтеYii 2 — Установка basic и advanced шаблонов приложения через ComposerКниги — Разработка веб-приложений в Yii 2 (Марк Сафронов)

Что такое виджеты

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

C помощью виджетов обеспечивается ООП-подход к повторному использованию кода пользовательского интерфейса.

Примеры виджетов для Yii2

DatePicker — виджет выпадающего календарика

Например, виджетом можно сделать выпадающий календарь DatePicker и повесить его на поле даты, вызывая для него виджет

<?php use yii\bootstrap\DatePicker; ?> <?= DatePicker::widget([ ‘model’ => $model, ‘attribute’ => ‘from_date’, ‘language’ => ‘ru’, ‘clientOptions’ => [ ‘dateFormat’ => ‘yy-mm-dd’, ], ]) ?>

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

Imperavi Redactor — удобный визуальный редактор

Или визуальный редактор Imperavi Redactor. Он тоже вешается на текстовое поле как виджет, тем самым заменяя стандартное поле типа textarea на поле, в котором можно визуально форматировать текст. То есть вместо

<?= $form->field($model, ‘text’)->textarea([‘rows’ => 6]) ?>

мы пишем вызов виджета с настройками для него

<?php use vova07\imperavi\Widget; /* <- это пишем в самом начале файла */ ?> <?= $form->field($model, ‘text’, [‘template’ => «{label}\n{hint}\n{input}\n{error}»])->hint(‘<i>Выделяйте важные блоки: <code>blockquote</code>, <code>span.important</code>, <code>span.fullimportant</code>, <code><p class=»voffset20 embed-responsive embed-responsive-16by9″><iframe class=»embed-responsive-item» src=…></code>, <code><figure class=»caption»><img src=»https://steptosleep.ru/wp-content/uploads/2018/06/64522.jpg» alt=»…»><figcaption>…</code>, <code><dl class=»dl-horizontal»> <dt><span>Родился</span></dt><dd>1982, Мексика</dd>…</code></i>’)->widget(Widget::classname(), [ ‘settings’ => [ ‘lang’ => ‘ru’, ‘removeWithoutAttr’ => [], ‘minHeight’ => 300, ‘pastePlainText’ => true, ‘buttonSource’ => true, ‘replaceDivs’ => false, ‘plugins’ => [ ‘clips’, ‘fullscreen’, ‘fontfamily’, ‘fontsize’, ‘fontcolor’, ‘video’, ‘table’ ], ‘imageUpload’ => Url::to([‘/blog/image-upload’]), ‘imageManagerJson’ => Url::to([‘/blog/images-get’]), ‘fileManagerJson’ => Url::to([‘/blog/files-get’]), ‘fileUpload’ => Url::to([‘/blog/file-upload’]) ] ]);?>

По умолчанию тег <span> вырезается, если у него отсутствуют какие-либо атрибуты (в настройках redactor.js — установлен removeWithoutAttr: [‘span’]).

Исправить это легко, добавив — ‘removeWithoutAttr’ => [], в параметры settings в вызове виджета Redactor в виде. Это нужно бывает при вёрстке для красивого выравнивания dt/dd. Впрочем, бывает правильнее оформление делать в файле css.

Виджеты, имеющие внутреннее содержимое. ActiveForm

Не все виджеты вызываются как «->widget()», иногда у них бывает внутреннее содержимое и тогда виджет вызывается методами и

Типичный пример: базовый виджет — ActiveForm

<?php use yii\widgets\ActiveForm; use yii\helpers\Html; ?> <?php $form = ActiveForm::begin([‘id’ => ‘login-form’]); ?> <?= $form->field($model, ‘username’) ?> <?= $form->field($model, ‘password’)->passwordInput() ?> <div class=»form-group»> <?= Html::submitButton(‘Login’) ?> </div> <?php ActiveForm::end(); ?>

Создаются свои виджеты наследованием от класса yii\base\Widget, и переопределением методов init() и run(). В init обрабатываются свойства, а run() возвращает результат рендеринга виджета.

После этого можно вызывать ваш виджет в виде или макете

<?php use app\components\HelloWidget; ?> <?= HelloWidget::widget([‘message’ => ‘Good morning’]) ?>

Но чаще всего виджету надо выводить крупный блок содержимого, для чего в run() вызывается метод render() с указанием файла, где этот блок размещён.

Создание собственного виджета в Yii 2.x

Этот файл hello.php по-умолчанию хранится в папке components/HelloWidget/views/, то есть внутри папки класса виджета HelloWidget (или любого вашего виджета) создаётся своя папка для видов view, и так у каждого виджета.

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

По мотивам – https://github.com/yiisoft/yii2/blob/master/docs/guide-ru/structure-widgets.md

FILED UNDER : IT

Submit a Comment

Must be required * marked fields.

:*
:*