LaravelRUS / SleepingOwlAdmin

🦉 Administrative interface builder for Laravel (Laravel admin)
http://sleepingowladmin.ru/
MIT License
799 stars 215 forks source link

Manage Multi-Language contents on CRUD #36

Closed denistorresan closed 3 years ago

denistorresan commented 8 years ago

Hello @butschster, on a multi language site there's no a native way to manage contents on laravel. One of this is to install dimsav/laravel-translatable that modify the model in a way where you can save translatable fields for each model, like:

//Filling multiple translations

  $data = [
    'code' => 'gr',
    'en'  => ['name' => 'Greece'],
    'fr'  => ['name' => 'Grèce'],
  ];

  $greece = Country::create($data);

 echo $greece->translate('fr')->name; // Grèce

Here an article: https://laravel-news.com/2015/09/how-to-add-multilingual-support-to-eloquent/ Here the lib: https://github.com/dimsav/laravel-translatable

The target is to build a CRUD with a form with all translation as described by #20.

I think it's not needed to build something "out of the box", but a sort of guide to implement it because in this way SleepingOwlAdmin become a full featured cms or sort of.

What I think to implement is sort of this (many crud works in this way): http://screenpresso.com/=QBdBg

thank you! Denis

butschster commented 8 years ago
butschster commented 8 years ago

Чувствую скоро либо мой английский улучшится, либо кто то меня пристрелит за такое построение предложений :)

denistorresan commented 8 years ago

Hello @butschster!

Here some ideas:

1) Active Languages can be stored (as suggested in many thread) like this:

config/app.php following the scheme: 'locale' => 'xx'.

'locales' => ['en', 'sv', 'it'],

https://laracasts.com/discuss/channels/tips/example-on-how-to-use-multiple-locales-in-your-laravel-5-website

2) Users can add more languages adding that in "app.locales". Than, the support of the translations labels adding related translations files: resources/lang/en/myfile.php

3) I think the best way is to define in tab view only the translatable fields, and save each on one single POST. This can maybe done defining multiple columns like "TABS" but related translations:

    // Create And Edit
    $model->onCreateAndEdit(function($id = null) {
        $display = AdminDisplay::panel();

        $display->setTranslatable(function() use ($id) {
            $form = AdminForm::form();
            $form->setItems(
             ...
        });

        //non translatable fields
        $display ->setItems(
        ...
        );
  }

or sort of this.

nikini commented 7 years ago

Has this been implemented?

ghost commented 7 years ago

All implemented features closes issue. Seems - not)

tomastovt commented 7 years ago

Hi, I have implemented this feature (https://github.com/dimsav/laravel-translatable). It's works fine for me in frontend. But in backend i can't solve the problem with CRUD, particularly with hasMany relation. Have anybody solve this problem? Or maybe there is another way or feature to beat this problem. Thanks.

ghost commented 7 years ago

@tomastovt what kind of problem you getted?

tomastovt commented 7 years ago

Hi @aios. My problem is next. I have 2 tables as in tutorial (https://github.com/dimsav/laravel-translatable). In Country model On CreateOrUpdate I can't solved how to write 2 fields (Ex. Country Name EN, Country Name UA) through relation.

 $model->onCreateAndEdit(function() {
    return AdminForm::panel()->addBody([
        AdminFormElement::text('alias','Country Alias')->required(),
        AdminFormElement::text('???? ','Country Name EN')->required(),
        AdminFormElement::text('????','Country Name UA')->required(),
        ]);
});

Migration is

Schema::create('countries', function(Blueprint $table)
{
    $table->increments('id');
    $table->string('code');
    $table->timestamps();
});

Schema::create('country_translations', function(Blueprint $table)
{
    $table->increments('id');
    $table->integer('country_id')->unsigned();
    $table->string('name');
    $table->string('locale')->index();

    $table->unique(['country_id','locale']);
    $table->foreign('country_id')->references('id')->on('countries')->onDelete('cascade');
});

And in '\App\Country' model I've created relation method to translation table public function translated(){ return $this->hasMany('App\CountryTranlation'); } Or I think in a bad way? maybe there is a best way to save this translated names.

ghost commented 7 years ago

@tomastovt If you have model for country translations - you can use tabs - and add table with translations and scoped to now-editable model. You can't play with relations fields when edit main model.

loginov-rocks commented 6 years ago

Hello, @tomastovt !

Since you're using laravel-translatable, you have a separate model that contains translation information, for Country it should be CountryTranslation, so you can add a separate Admin Section for CRUD operations with CountryTranslation model and move translated fields to it's onEdit & onCreate methods from original model — that's what @aios meant.

According to your's migration code you want to make name attribute translated, this is how we do it:

<?php

namespace App;

use Dimsav\Translatable\Translatable;
use Illuminate\Database\Eloquent\Model;

class Country extends Model
{
    use Translatable;

    public $translatedAttributes = [
        'name',
    ];
}
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class CountryTranslation extends Model
{
    protected $fillable = [
        'name',
    ];

    public $timestamps = false;

    public function country()
    {
        return $this->belongsTo(Country::class);
    }
}
<?php

namespace App\Admin\Sections;

use AdminColumn;
use AdminDisplay;
use AdminForm;
use AdminFormElement;
use AdminSection;
use App\CountryTranslation;
use SleepingOwl\Admin\Section;

class Countries extends Section
{
    public function onDisplay()
    {
        $display = AdminDisplay::table();

        $display->setColumns([
                                 AdminColumn::link('name', 'Name'),
                                 AdminColumn::text('other', 'Something else'),
                             ]);

        $display->paginate(25);

        return $display;
    }

    public function onEdit($id)
    {
        $display = AdminDisplay::tabbed();

        $display->setTabs(function () use ($id) {
            $tabs = [];

            $form = AdminForm::form();

            $form->setElements([
                                   AdminFormElement::text('other', 'Something else'),
                               ]);

            $tabs[] = AdminDisplay::tab($form)->setLabel('General information');

            if ($id) {
                $translations = AdminSection::getModel(CountryTranslation::class)->fireDisplay(['country' => $id]);

                $tabs[] = AdminDisplay::tab($translations)->setLabel('Translations');
            }

            return $tabs;
        });

        return $display;
    }

    public function onCreate()
    {
        return $this->onEdit(null);
    }
}
<?php

namespace App\Admin\Sections;

use AdminColumn;
use AdminDisplay;
use AdminDisplayFilter;
use AdminForm;
use AdminFormElement;
use App\Country;
use SleepingOwl\Admin\Section;

class CountryTranslations extends Section
{
    public function onDisplay($country = 0)
    {
        $display = AdminDisplay::table();

        $display->with('country');

        if ($country) {
            $display->setFilters([
                                     AdminDisplayFilter::field('country_id')->setTitle('Country')->setValue($country),
                                 ]);
        }

        $display->setColumns([
                                 AdminColumn::relatedLink('country.name', 'Country'),
                                 AdminColumn::link('locale', 'Locale'),
                             ]);

        return $display;
    }

    public function onEdit($id)
    {
        $form = AdminForm::panel();

        $locales = config('translatable.locales');

        $form->addBody([
                           AdminFormElement::select('country_id', 'Country', Country::class)->setDisplay('name')
                                           ->required(),
                           AdminFormElement::select('locale', 'Locale')->setEnum($locales)->required(),
                           AdminFormElement::text('name', 'Name')->required(),
                       ]);

        return $form;
    }

    public function onCreate()
    {
        return $this->onEdit(null);
    }
}

@aios может быть ещё такой вариант: сделать отдельную фабрику AdminFormElementTranslatable или методы для полей AdminFormElement::text('name', 'Name')->setTranslatable(), поскольку фича переводов нацелена именно на некоторые поля модели. Под капотом придётся вызывать конкретные методы на модели, обусловленные используемым пакетом (https://github.com/dimsav/laravel-translatable в данном случае), насколько я понимаю.

SergkeiM commented 6 years ago

There was a fork of SleepingOwlAdmin few years ago by @noxify here , he have implemented laravel-translatable if anybody needs.

noxify commented 6 years ago

Feel free to use whatever you need ;)

YulKard commented 6 years ago

Так и не понятно, как реализовать мультиязычность в админке. Уважаемые, разработчики, укажите, хоть в какую сторону смотреть. @1oginov ваш вариант неплох, но получается, что переводы можно добавить только поле того, как сохранишь основную иyформацию, так как указана проверка на id.

if ($id) { $translations = AdminSection::getModel(CountryTranslation::class)->fireDisplay(['country' => $id]); $tabs[] = AdminDisplay::tab($translations)->setLabel('Translations'); }

Что не очень удобно.

loginov-rocks commented 6 years ago

@YulKard да, получается так. Согласен, не самый лаконичный способ, но по сути единственный, потому как @aios объяснил, что «You can't play with relations fields when edit main model.»

YulKard commented 6 years ago

@1oginov очень жаль! Спасибо за ответ. Эта админка мне показалась очень удобной, но теперь увы, придется искать что-тот другое с возможностью реализации мультиязычности.

Pashaster12 commented 5 years ago

@aios Have you done any changes with multilingual support? The possibility of dimsav/laravel-translatable integration would be excellent)

daaner commented 3 years ago

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