Laravel-Backpack / community-forum

A workspace to discuss improvement and feature ideas, before they're actually implemented.
28 stars 0 forks source link

[Feature Request]Allow automatically translating field labels instead of requiring a "label" property for each #398

Open pekka opened 1 year ago

pekka commented 1 year ago

When defining fields/columns in a CrudController, the usual way to give the field a translated label is:

 CRUD::field('fieldname')->label(trans('my.dictionary.field_fieldname'));

this is arguably a redundancy, because your dictionary entries will usually coincide exactly with the field name, and an option to automate it away it could be useful.

So for example

 CRUD::field('fieldname1');

would automatically be assigned

 trans('<custom prefix>.<model name>.field_<fieldname1>')

(As an option, of course, not by default, to make it non-breaking and of course not everyone needs this!)

As a proof of concept, I created a Trait that does this, below πŸ‘‡

You would call its assignLabelsFromTranslation() method eg in setupCreateOperation() after defining the fields:

   CRUD::field('fieldname1');
   CRUD::field('fieldname2');

    $this->assignLabelsFromTranslation("models.mymodel.field_");

it automatically walks through each field and assigns the translated values to each label:

  trans('models.mymodel.field_fieldname1')
  trans('models.mymodel.field_fieldname2')

I'm sure this is way too hacky to make it into the core - I'm new and don't really know what I'm doing! But a feature along these lines, more nicely implemented, could be a small useful improvement, and should be non-breaking.

trait assignLabelsFromTranslation
{

    /**
     * Automatically override all column labels with a translation.
     *
     * @param  string  $translation_prefix A prefix to use for the trans() lookup call.
     * 
     */
    public function assignLabelsFromTranslation($translation_prefix = null)
    {
        $columnsArray = $this->crud->getOperationSetting('fields');

        foreach ($columnsArray as $index => $column)
         {

            if (!$column['name'])
             continue;

            $translation = trans($translation_prefix.$column['name']);

            $columnsArray[$index]['label'] = $translation;

         }

        $this->crud->setOperationSetting('fields', $columnsArray);
    }

}
pxpm commented 1 year ago

Hey @pekka I think this idea is neat.

There are a few options for this, one that easily comes to mind and would work out of the box without much effort is something like:

Going further and making this "future proof" we could think about the concept of FieldLabeler and ColumnLabeler and use only one setting CRUD::setOperationSetting('labeler', 'App\Labelers\MyCustomLabeler::class).

Better DX, but this could easily go wrong if people start wanting Entitier, Attributabler etc, for other attributes that not only label.

Nevertheless I prefer the last concept, in fact, I started working on some prototype that aims to do exactly that: https://github.com/Laravel-Backpack/CRUD/pull/4854

It's called Smart Components but it also has the Smart Attributes attached. To sum up, we would be splitting all the field attributes into classes with their own defaults(), validation() etc. In your case you would just need to create (if we didn't already), a TranslatableLabelAttribute extends LabelAttribute with the custom implementation.

I can't focus on working on this right now, but I like the idea of not having to type multiple times the trans('my.custom_text.fieldName') πŸ’‘

I am moving this to the community forum and leave it to have a look after v6.

Cheers