الأشجار متعددة اللغات في Yii2 كمثال لإنشاء وحدة قائمة

الدخول


يواجه العديد من مطوري الويب المبتدئين الحاجة إلى إنشاء قوائم أو أدلة أو فئات لمشروع Yii2 الخاص بهم ، والذي سيكون له هيكل هرمي ، ولكن في نفس الوقت يدعم التعددية اللغوية. المهمة بسيطة للغاية ، ولكنها ليست واضحة تمامًا في إطار هذا الإطار. هناك عدد كبير من الإضافات الجاهزة لإنشاء هياكل الشجرة (القوائم والأدلة وما إلى ذلك) ، ولكن من الصعب إيجاد حل يدعم العمل الكامل بعدة لغات. علاوة على ذلك ، نحن لا نتحدث عن ترجمة الواجهة باستخدام أدوات إطار العمل القياسية ، ولكن عن تخزين البيانات في قاعدة بيانات بعدة لغات. من الصعب أيضًا العثور على أداة ملائمة وفعالة تمامًا لإدارة الشجرة ، والتي يمكن أن تعمل أيضًا مع محتوى متعدد اللغات دون معالجة معقدة للتعليمات البرمجية.


أود مشاركة وصفة حول كيفية إنشاء وحدات مماثلة باستخدام مثال على تنفيذ وحدة القائمة. على سبيل المثال ، سأستخدم قالب تطبيق Yii2 App Basic ، ولكن يمكنك تكييف كل شيء مع القالب الخاص بك إذا كان يختلف عن القالب الأساسي.


تحضير


لإنجاز المهمة ، سنحتاج إلى بعض التمديدات الرائعة ، وهي:



تثبيت بيانات الإضافة من خلال الملحن:


composer require paulzi/yii2-adjacency-list composer require execut/yii2-widget-bootstraptreeview composer require creocoder/yii2-translateable 

لتنفيذ القائمة كوحدة نمطية ، باستخدام مولد Gii (أو يدويًا) قم بإنشاء وحدة نمطية جديدة للوصل وتوصيلها في إعدادات التطبيق.


يجب أن يحتوي المشروع أيضًا على آلية تبديل لغة تم تكوينها. أفضل استخدام هذا الامتداد لـ Yii2 .


إنشاء النموذج


لتخزين القائمة (أو كيان آخر له تعدد اللغات) في قاعدة البيانات ، نحتاج إلى إنشاء جدولين. في الواقع ، يمكن استخدام طرق مختلفة لتخزين البيانات متعددة اللغات ، لكني أحب الخيار مع جدولين ، أحدهما يخزن الجوهر نفسه ، والثاني - اختلافات لغته ، أكثر من الآخرين. من الملائم استخدام عمليات الترحيل لإنشاء جداول. هنا مثال لمثل هذا الترحيل:


m180819_083502_menu_init.php
 <?php use yii\db\Schema; use yii\db\Migration; class m180819_083502_menu_init extends Migration { public function init() { $this->db = 'db'; parent::init(); } public function safeUp() { $tableOptions = 'ENGINE=InnoDB'; $this->createTable('{{%menu}}', [ 'id'=> $this->primaryKey(11), 'parent_id'=> $this->integer(11)->null()->defaultValue(null), 'link'=> $this->string(255)->notNull()->defaultValue('#'), 'link_attributes'=> $this->text()->notNull(), 'icon_class'=> $this->string(255)->notNull(), 'sort'=> $this->integer(11)->notNull()->defaultValue(0), 'status'=> $this->tinyInteger(1)->notNull()->defaultValue(1), ], $tableOptions); $this->createIndex('parent_sort', '{{%menu}}', ['parent_id','sort'], false); $this->createTable('{{%menu_lang}}', [ 'owner_id'=> $this->integer(11)->notNull(), 'language'=> $this->string(2)->notNull(), 'name'=> $this->string(255)->notNull(), 'title'=> $this->text()->notNull(), ], $tableOptions); $this->addPrimaryKey('pk_on_menu_lang', '{{%menu_lang}}', ['owner_id','language']); $this->addForeignKey( 'fk_menu_lang_owner_id', '{{%menu_lang}}', 'owner_id', '{{%menu}}', 'id', 'CASCADE', 'CASCADE' ); // Insert sample data $this->batchInsert( '{{%menu}}', ['id', 'parent_id', 'link', 'link_attributes', 'icon_class', 'sort', 'status'], [ [ 'id' => '1', 'parent_id' => null, 'link' => '#', 'link_attributes' => '', 'icon_class' => '', 'sort' => '0', 'status' => '0', ], [ 'id' => '2', 'parent_id' => '1', 'link' => '/', 'link_attributes' => '', 'icon_class' => 'fa fa-home', 'sort' => '0', 'status' => '1', ], ] ); $this->batchInsert( '{{%menu_lang}}', ['owner_id', 'language', 'name', 'title'], [ [ 'owner_id' => '1', 'language' => 'ru', 'name' => ' ', 'title' => '', ], [ 'owner_id' => '1', 'language' => 'en', 'name' => 'Main menu', 'title' => '', ], [ 'owner_id' => '2', 'language' => 'ru', 'name' => '', 'title' => '  ', ], [ 'owner_id' => '2', 'language' => 'en', 'name' => 'Home', 'title' => 'Site homepage', ], ] ); } public function safeDown() { $this->truncateTable('{{%menu}} CASCADE'); $this->dropForeignKey('fk_menu_lang_owner_id', '{{%menu_lang}}'); $this->dropTable('{{%menu}}'); $this->dropPrimaryKey('pk_on_menu_lang', '{{%menu_lang}}'); $this->dropTable('{{%menu_lang}}'); } } 

ضع ملف الترحيل هذا في مجلد / الترحيل من مشروعنا ، و
تنفيذ الأمر في وحدة التحكم:


 php yii migrate 

بعد إنشاء الجداول الضرورية وإضافة قائمة جديدة إليها باستخدام الترحيل ، نحتاج إلى إنشاء نماذج. نظرًا لأنه يمكن العثور على التعددية اللغوية والأشجار ليس فقط في القائمة ، ولكن أيضًا في الكيانات الأخرى (على سبيل المثال ، صفحات الموقع) في المشروع ، أقترح أن يتم وضع الأساليب التي تنفذ آلية التعددية اللغوية وتنظيم الشجرة في سمات منفصلة حتى نتمكن من استخدامها بسهولة لاحقًا لهم في نماذج أخرى دون تكرار التعليمات البرمجية. أنشئ مجلد سمات في جذر التطبيق (إذا لم يكن موجودًا بالفعل) وضع ملفين هناك:


LangTrait.php
 <?php namespace app\traits; use Yii; use yii\behaviors\SluggableBehavior; use creocoder\translateable\TranslateableBehavior; trait LangTrait { public static function langClass() { return self::class . 'Lang'; } public static function langTableName() { return self::tableName() . '_lang'; } public function langBehaviors($translationAttributes) { return [ 'translateable' => [ 'class' => TranslateableBehavior::class, 'translationAttributes' => $translationAttributes, 'translationRelation' => 'translations', 'translationLanguageAttribute' => 'language', ], ]; } public function transactions() { return [ self::SCENARIO_DEFAULT => self::OP_INSERT | self::OP_UPDATE, ]; } public function getLang() { return $this->hasOne(self::langClass(), ['owner_id' => 'id'])->where([self::langTableName() . '.language' => Yii::$app->language]); } public function getTranslations() { return $this->hasMany(self::langClass(), ['owner_id' => 'id']); } } 

TreeTrait.php
 <?php namespace app\traits; use Yii; use yii\helpers\Html; use paulzi\adjacencyList\AdjacencyListBehavior; trait TreeTrait { private static function getQueryClass() { return self::class . 'Query'; } public function treeBehaviors() { return [ 'tree' => [ 'class' => AdjacencyListBehavior::class, 'parentAttribute' => 'parent_id', 'sortable' => [ 'step' => 10, ], 'checkLoop' => false, 'parentsJoinLevels' => 5, 'childrenJoinLevels' => 5, ], ]; } public static function find() { $queryClass = self::getQueryClass(); return new $queryClass(get_called_class()); } public static function listTree($node = null, $level = 1, $nameAttribute = 'name', $prefix = '-->') { $result = []; if (!$node) { $node = self::find()->roots()->one()->populateTree(); } if ($node->isRoot()) { $result[$node['id']] = mb_strtoupper($node[$nameAttribute ?: 'slug']); } if ($node['children']) { foreach ($node['children'] as $child) { $result[$child['id']] = str_repeat($prefix, $level) . $child[$nameAttribute]; $result = $result + self::listTree($child, $level + 1, $nameAttribute); } } return $result; } public static function treeViewData($node = null) { if ($node === null) { $node = self::find()->roots()->one()->populateTree(); } $result = null; $items = null; $children = null; if ($node['children']) { foreach ($node['children'] as $child) { $items[] = self::treeViewData($child); } $children = call_user_func_array('array_merge', $items); } $result[] = [ 'text' => Html::a($node['lang']['name'] ?: $node['id'], ['update', 'id' => $node['id']], ['title' => Yii::t('app', ' ')]), 'tags' => [ Html::a( '<i class="glyphicon glyphicon-arrow-down"></i>', ['move-down', 'id' => $node['id']], ['title' => Yii::t('app', ' ')] ), Html::a( '<i class="glyphicon glyphicon-arrow-up"></i>', ['move-up', 'id' => $node['id']], ['title' => Yii::t('app', ' ')] ) ], 'backColor' => $node['status'] == 0 ? '#ccc' : '#fff', 'selectable' => false, 'nodes' => $children, ]; return $result; } } 

الآن سنقوم مباشرة بإنشاء النماذج بأنفسهم للعمل مع القائمة ، حيث نربط سمات الشجرة والتعددية اللغوية. نضع النماذج في / وحدات / قائمة / نماذج:


Menu.php
 <?php namespace app\modules\menu\models; use Yii; class Menu extends \yii\db\ActiveRecord { use \app\traits\TreeTrait; use \app\traits\LangTrait; const STATUS_ACTIVE = 1; const STATUS_INACTIVE = 0; public function behaviors() { $behaviors = []; return array_merge( $behaviors, $this->treeBehaviors(), $this->langBehaviors(['name', 'title']) ); } public static function tableName() { return 'menu'; } public function rules() { return [ [['parent_id', 'sort', 'status'], 'integer'], [['link', 'icon_class'], 'string', 'max' => 255], [['link_attributes'], 'string'], [['link'], 'default', 'value' => '#'], [['link_attributes', 'icon_class'], 'default', 'value' => ''], [['parent_id'], 'exist', 'skipOnError' => true, 'targetClass' => self::class, 'targetAttribute' => ['parent_id' => 'id']], ]; } public function attributeLabels() { return [ 'id' => Yii::t('app', 'ID'), 'parent_id' => Yii::t('app', ''), 'link' => Yii::t('app', ''), 'link_attributes' => Yii::t('app', '  (JSON )'), 'icon_class' => Yii::t('app', ' '), 'sort' => Yii::t('app', ''), 'status' => Yii::t('app', ''), ]; } public static function menuItems($node = null) { if ($node === null) { $node = self::find()->roots()->one()->populateTree(); } $result = null; $items = null; $children = null; if ($node['children']) { foreach ($node['children'] as $child) { $items[] = self::menuItems($child); } $children = call_user_func_array('array_merge', $items); } $result[] = [ 'label' => ($node['icon_class'] ? '<i class="' . $node['icon_class'] . '"></i> ' . ($node['lang']['name'] ?: $node['id']) : ($node['lang']['name'] ?: $node['id'] )), 'encode' => ($node['icon_class'] ? false : true), 'url' => [$node['link'], 'language' => Yii::$app->language], 'active' => $node['link'] == Yii::$app->request->url ? true : false, 'linkOptions' => ($node['link_attributes'] ? array_merge(json_decode($node['link_attributes'], true), ['title' => ($node['lang']['title'] ?: $node['lang']['name'])]) : ['title' => ($node['lang']['title'] ?: $node['lang']['name'])]), 'items' => $children, ]; return $result; } } 

MenuLang.php
 <?php namespace app\modules\menu\models; use Yii; class MenuLang extends \yii\db\ActiveRecord { public static function tableName() { return 'menu_lang'; } public function rules() { return [ [['name'], 'required'], [['name', 'title'], 'string', 'max' => 255], ]; } public function attributeLabels() { return [ 'owner_id' => Yii::t('app', ''), 'language' => Yii::t('app', ''), 'name' => Yii::t('app', ''), 'title' => Yii::t('app', ' '), ]; } public function getOwner() { return $this->hasOne(Menu::class, ['id' => 'owner_id']); } } 

MenuQuery.php
 <?php namespace app\modules\menu\models; use paulzi\adjacencyList\AdjacencyListQueryTrait; class MenuQuery extends \yii\db\ActiveQuery { use AdjacencyListQueryTrait; } 

MenuSearch.php
 <?php namespace app\modules\menu\models; use Yii; use yii\base\Model; use yii\data\ActiveDataProvider; use app\modules\menu\models\Menu; class MenuSearch extends Menu { public $name; public function rules() { return [ [['id', 'parent_id', 'sort', 'status'], 'integer'], [['link', 'link_attributes', 'icon_class'], 'safe'], [['name'], 'safe'], ]; } public function scenarios() { return Model::scenarios(); } public function search($params) { $query = parent::find()->joinWith(['lang']); $dataProvider = new ActiveDataProvider([ 'query' => $query, 'sort' => ['defaultOrder' => ['sort' => SORT_ASC]] ]); $dataProvider->sort->attributes['name'] = [ 'asc' => [ 'menu_lang.name' => SORT_ASC, ], 'desc' => [ 'menu_lang.name' => SORT_DESC, ], ]; $this->load($params); if (!$this->validate()) { return $dataProvider; } $query->andFilterWhere([ 'id' => $this->id, 'parent_id' => $this->parent_id, 'sort' => $this->sort, 'status' => $this->status, ]); $query->andFilterWhere(['like', 'link', $this->link]); $query->andFilterWhere(['like', 'link_attributes', $this->link_attributes]); $query->andFilterWhere(['like', 'icon_class', $this->icon_class]); $query->andFilterWhere(['like', 'name', $this->name]); return $dataProvider; } } 

إنشاء وحدات تحكم


لعمليات CRUD على الأشجار متعددة اللغات ، نحتاج إلى وحدة تحكم. لتبسيط حياتنا في المستقبل ، سننشئ وحدة تحكم أساسية واحدة حيث ستكون هناك جميع الإجراءات اللازمة ، وبالنسبة للكيانات المختلفة ، سواء كانت قائمة أو دليل أو صفحات ، فسوف نرثها.


سيتم وضع فئات مشروعنا التي سنستخدمها كفئات أساسية في المجلد / الأساسي. قم بإنشاء الملف /base/controllers/AdminLangTreeController.php. ستكون وحدة التحكم هذه أساس CRUD لجميع الكيانات التي يتم فيها تنفيذ الشجرة والتعددية اللغوية:


AdminLangTreeController.php
 <?php namespace app\base\controllers; use Yii; use yii\web\Controller; use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; use yii\helpers\Url; class AdminLangTreeController extends Controller { public $modelClass; public $modelClassSearch; public $modelName; public $modelNameLang; public function behaviors() { return [ 'verbs' => [ 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['POST'], ], ], ]; } public function actionIndex() { //     ,     if (count($this->modelClass::find()->roots()->all()) == 0) { $model = new $this->modelClass; $model->makeRoot()->save(); Yii::$app->session->setFlash('info', Yii::t('app', '   ')); return $this->redirect(['index']); } $searchModel = new $this->modelClassSearch; $dataProvider = $searchModel->search(Yii::$app->request->queryParams); $dataProvider->pagination = false; return $this->render('index', [ 'searchModel' => $searchModel, 'dataProvider' => $dataProvider, ]); } public function actionCreate() { //     if (count($this->modelClass::find()->roots()->all()) == 0) { return $this->redirect(['index']); } //         $model = new $this->modelClass; $root = $model::find()->roots()->one(); $model->parent_id = $root->id; //     if ($model->load(Yii::$app->request->post()) && $model->validate()) { $parent = $model::findOne($model->parent_id); $model->appendTo($parent)->save(); //    foreach (Yii::$app->request->post($this->modelNameLang, []) as $language => $data) { foreach ($data as $attribute => $translation) { $model->translate($language)->$attribute = $translation; } } $model->save(); Yii::$app->session->setFlash('success', Yii::t('app', '  ')); return $this->redirect(['update', 'id' => $model->id]); } else { return $this->render('create', [ 'model' => $model, ]); } } public function actionUpdate($id) { //    $model = $this->modelClass::find()->with('translations')->where(['id' => $id])->one(); if ($model === null) { throw new NotFoundHttpException(Yii::t('app', '  ')); } //     if ($model->load(Yii::$app->request->post()) && $model->save()) { foreach (Yii::$app->request->post($this->modelNameLang, []) as $language => $data) { foreach ($data as $attribute => $translation) { $model->translate($language)->$attribute = $translation; } } $model->save(); Yii::$app->session->setFlash('success', Yii::t('app', '  ')); if (Yii::$app->request->post('save') !== null) { return $this->redirect(['index']); } return $this->redirect(['update', 'id' => $model->id]); } else { return $this->render('update', [ 'model' => $model, ]); } } public function actionDelete($id) { $model = $this->findModel($id); //   ,      if (count($model->children) > 0) { Yii::$app->session->setFlash('error', Yii::t('app', '    ,     .      ')); return $this->redirect(['index']); } //     if ($model->isRoot()) { Yii::$app->session->setFlash('error', Yii::t('app', '   ')); return $this->redirect(['index']); } //   if ($model->delete()) { Yii::$app->session->setFlash('success', Yii::t('app', '  ')); } return $this->redirect(['index']); } public function actionMoveUp($id) { $model = $this->findModel($id); if ($prev = $model->getPrev()->one()) { $model->moveBefore($prev)->save(); $model->reorder(false); } else { Yii::$app->session->setFlash('error', Yii::t('app', '   ')); } return $this->redirect(Yii::$app->request->referrer); } public function actionMoveDown($id) { $model = $this->findModel($id); if ($next = $model->getNext()->one()) { $model->moveAfter($next)->save(); $model->reorder(false); } else { Yii::$app->session->setFlash('error', Yii::t('app', '   ')); } return $this->redirect(Yii::$app->request->referrer); } protected function findModel($id) { if (($model = $this->modelClass::findOne($id)) !== null) { return $model; } else { throw new NotFoundHttpException(Yii::t('app', '  ')); } } } 

الآن في الوحدة النمطية ، قم بإنشاء الملف /modules/menu/controllers/AdminController.php. ستكون هذه هي وحدة التحكم الرئيسية لإدارة القائمة ، وبما أنها تنفذ الشجرة والتعددية اللغوية ، فسوف ترث من القاعدة الأساسية التي أنشأناها بالفعل في الخطوة السابقة:


AdminController.php
 <?php namespace app\modules\menu\controllers; use app\base\controllers\AdminLangTreeController as BaseController; class AdminController extends BaseController { public $modelClass = \app\modules\menu\models\Menu::class; public $modelClassSearch = \app\modules\menu\models\MenuSearch::class; public $modelName = 'Menu'; public $modelNameLang = 'MenuLang'; } 

كما ترى ، يحتوي رمز وحدة التحكم هذه على أسماء النماذج وفئاتها فقط. أي ، لإنشاء وحدات تحكم CRUD لوحدات أخرى (كتالوج ، فئات ، إلخ) ، والتي ستستخدم أيضًا الشجرة والتعددية اللغوية ، يمكنك أن تفعل الشيء نفسه بنفس الطريقة - قم بتوسيع وحدة التحكم الأساسية.


إنشاء واجهة لإدارة القائمة


المرحلة الأخيرة هي إنشاء واجهة لإدارة شجرة متعددة اللغات. يعالج ملحق Bootstrap Treeview مهمة عرض شجرة ، والتي يمكن تكوينها بمرونة كبيرة وهي تدعم العديد من الوظائف الملائمة (على سبيل المثال ، البحث في شجرة). قم بإنشاء عرض فهرس لعرض الشجرة نفسها ووضعها في /modules/menu/views/admin/index.php:


index.php
 <?php use yii\helpers\Html; use yii\grid\GridView; use yii\widgets\ActiveForm; use execut\widget\TreeView; $this->title = Yii::t('app', ' '); $this->params['breadcrumbs'][] = $this->title; ?> <div class="row"> <div class="col-md-6"> <div class="panel panel-primary"> <div class="panel-heading"> <?= Html::a(Yii::t('app', ''), ['create'], ['class' => 'btn btn-success btn-flat']) ?> </div> <div class="panel-body"> <?= TreeView::widget([ 'id' => 'tree', 'data' => $searchModel::treeViewData($searchModel::find()->roots()->one()), 'header' => Yii::t('app', ' '), 'searchOptions' => [ 'inputOptions' => [ 'placeholder' => Yii::t('app', '  ') . '...' ], ], 'clientOptions' => [ 'selectedBackColor' => 'rgb(40, 153, 57)', 'borderColor' => '#fff', 'levels' => 10, 'showTags' => true, 'tagsClass' => 'badge', 'enableLinks' => true, ], ]) ?> </div> </div> </div> </div> 

لذلك وصلنا إلى المرحلة الأكثر إثارة للاهتمام في هذه الحالة: كيفية إنشاء نموذج لإنشاء / تحرير البيانات متعددة اللغات. قم بإنشاء ثلاثة ملفات في مجلد / modules / menu / views / admin:


create.php
 <?php use yii\helpers\Html; $this->title = Yii::t('app', ''); $this->params['breadcrumbs'][] = ['label' => Yii::t('app', ' '), 'url' => ['index']]; $this->params['breadcrumbs'][] = $this->title; echo $this->render('_form', [ 'model' => $model, ]); 

update.php
 <?php use yii\helpers\Html; $this->title = Yii::t('app', '') . ': ' . $model->name; $this->params['breadcrumbs'][] = ['label' => Yii::t('app', ' '), 'url' => ['index']]; $this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['update', 'id' => $model->id]]; $this->params['breadcrumbs'][] = Yii::t('app', ''); echo $this->render('_form', [ 'model' => $model, ]); 

_form.php
 <?php use yii\helpers\Html; use yii\widgets\ActiveForm; if ($model->isNewRecord) { $model->status = true; } ?> <div class="panel panel-primary"> <?php $form = ActiveForm::begin(); ?> <div class="panel-body"> <fieldset> <legend><?= Yii::t('app', ' ') ?></legend> <div class="row"> <div class="col-md-4"> <?php if (!$model->isRoot()) { ?> <?= $form->field($model, 'parent_id')->dropDownList($model::listTree()) ?> <?php } ?> <?= $form->field($model, 'link')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'link_attributes')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'icon_class')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'status')->checkbox() ?> </div> </div> </fieldset> <fieldset> <legend><?= Yii::t('app', '') ?></legend> <!-- Nav tabs --> <ul class="nav nav-tabs" role="tablist"> <?php foreach (Yii::$app->urlManager->languages as $key => $language) { ?> <li role="presentation" <?= $key == 0 ? 'class="active"' : '' ?>> <a href="#tab-content-<?= $language ?>" aria-controls="tab-content-<?= $language ?>" role="tab" data-toggle="tab"><?= $language ?></a> </li> <?php } ?> </ul> <!-- Tab panes --> <div class="tab-content"> <?php foreach (Yii::$app->urlManager->languages as $key => $language) { ?> <div role="tabpanel" class="tab-pane <?= $key == 0 ? 'active' : '' ?>" id="tab-content-<?= $language ?>"> <?= $form->field($model->translate($language), "[$language]name")->textInput() ?> <?= $form->field($model->translate($language), "[$language]title")->textInput() ?> </div> <?php } ?> </div> </fieldset> </div> <div class="box-footer"> <?= Html::submitButton($model->isNewRecord ? '<i class="fa fa-plus"></i> ' . Yii::t('app', '') : '<i class="fa fa-refresh"></i> ' . Yii::t('app', ''), ['class' => $model->isNewRecord ? 'btn btn-primary' : 'btn btn-success']) ?> <?= !$model->isNewRecord ? Html::submitButton('<i class="fa fa-save"></i> ' . Yii::t('app', ''), ['class' => 'btn btn-warning', 'name' => 'save']) : ''; ?> <?= !$model->isNewRecord ? Html::a('<i class="fa fa-trash"></i> ' . Yii::t('app', ''), ['delete', 'id' => $model->id], ['class' => 'btn btn-danger', 'data' => ['confirm' => Yii::t('app', ' ,     ?'), 'method' => 'post']]) : ''; ?> </div> <?php ActiveForm::end(); ?> </div> 

لا تنس أنه يجب تحديد اللغة الافتراضية في التطبيق (معلمة اللغة) ، وفي معلمات UrlManager - صفيف يحتوي على قائمة باللغات (اللغات) التي سنستخدمها. يجب أن تكون اللغة الافتراضية هي الأولى في هذا الصفيف.


الخلاصة


نتيجة لذلك ، يجب أن نحصل على ما يلي:


  • وحدة جاهزة لقائمة متعددة اللغات تشبه شجرة الموقع مع واجهة مريحة وقابلة للتخصيص ؛
  • وحدة تحكم CRUD الأساسية التي يمكن توريثها عند إنشاء وحدات أخرى تستخدم الخشب والتعددية اللغوية ؛
  • صفتان (متعدد اللغات والشجرة) يمكن توصيلهما بالنماذج لتنفيذ الوظائف المقابلة.

آمل أن تكون هذه المقالة مفيدة وستساعدك في تطوير مشاريع جيدة جديدة على Yii2.

Source: https://habr.com/ru/post/ar426625/


All Articles