Code Monkey home page Code Monkey logo

nova-tab-translatable's Introduction

Making Laravel Nova Tab Translatable

Latest Version on Packagist Licence Total Downloads

This package contains a NovaTabTranslatable class you can use to make any Nova field type translatable with tabs.

Imagine you have this fields method in a Post Nova resource:

use Kongulov\NovaTabTranslatable\NovaTabTranslatable;

...

public function fields(Request $request)
{
    return [
        ID::make()->sortable(),

        NovaTabTranslatable::make([
            SluggableText::make('Title')->slug('Slug'),
            Slug::make('Slug')->readonly(),
            Trix::make('text'),
            Text::make('Keywords'),
            Text::make('Description'),
        ]),
    ];
}

That Post Nova resource will be rendered like this.

screenshot screenshot

Requirements

  • php: >=7.1.0
  • spatie/laravel-translatable: ^4.0

Installation

Install the package in a Laravel Nova project via Composer:

# Install nova-tab-translatable
composer require kongulov/nova-tab-translatable

# Publish configuration
php artisan vendor:publish --tag="tab-translatable-config"

This is the contents of the file which will be published at config/tab-translatable.php

<?php

return [
    /*
     * The source of supported locales on the application
     * Available selection "array", "database". Default array
     */
    'source' => 'array',

    /*
     * If you choose array selection, you should add all supported translation on it as "code"
     */
    'locales' => [
        'en', 'fr', 'es'
    ],

    /*
     * If you choose database selection, you should choose the model responsible for retrieving supported translations
     * And choose the 'code_field' for example "en", "fr", "es"...
     */
    'database' => [
        'model' => 'App\\Models\\Language',
        'code_field' => 'lang',
        'sort_by' => 'id',
        'sort_direction' => 'asc'
    ],

    /*
     * If you want to save the tab in the last selected language for the whole project, set this "true".
     * But if you want to use in one place call the saveLastSelectedLang(true|false) method
     */
    'save_last_selected_lang' => false,
];

Usage

You must prepare your model as explained in the readme of laravel-translatable. In short: you must add json columns to your model's table for each field you want to translate. Your model must use the Spatie\Translatable\HasTranslations on your model. Finally, you must also add a $translatable property on your model that holds an array with the translatable attribute names.

Now that your model is configured for translations, you can use NovaTabTranslatable in the related Nova resource. Any fields you want to display in a multilingual way can be passed as an array to NovaTabTranslatable.

use Kongulov\NovaTabTranslatable\NovaTabTranslatable;

...

public function fields(Request $request)
{
    return [
        ID::make()->sortable(),

        NovaTabTranslatable::make([
            SluggableText::make('Title')->slug('Slug'),
            Slug::make('Slug')->readonly(),
            Trix::make('text'),
            Text::make('Keywords'),
            Text::make('Description'),
        ]),
    ];
}

If you want to make the field required only in certain languages, then you can use the required_lang rule,

NovaTabTranslatable::make([
    Text::make('Title')->rules('required_lang:en,fr'),
    Trix::make('text')->rules('required_lang:en,fr'),
    Text::make('Keywords'),
    Text::make('Description'),
]),

But if you want to make the field required in all languages, then use the laravel rules

NovaTabTranslatable::make([
    Text::make('Title')->rules('required'),
]),
  • Replace field name
NovaTabTranslatable::make([
    Text::make('Title')->rules('required'),
])->setTitle('Own Title'),
  • If you want to save the tab in the last selected language, call the saveLastSelectedLang() method or in the config replace 'save_last_selected_lang' => false with 'save_last_selected_lang' => true
NovaTabTranslatable::make([
    Text::make('Title'),
])->saveLastSelectedLang(true|false),
  • If on the index and detail pages you want to turn off the tab and show it each as a row, use trait TranslatableTabToRowTrait in your resource
class YourResource extends Resource
{
    use TranslatableTabToRowTrait;
    ...
}

Credits

License

This project is open-sourced software licensed under the MIT license.

nova-tab-translatable's People

Contributors

ajotka avatar energon7 avatar kongulov avatar suchoproduction avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

nova-tab-translatable's Issues

Using resolveUsing option in fields

Nova version: 4.16
Laravel version: 9
Php version: 8.0

Thanks for the great package.

I would like to see some features of Nova inside NovaTabTranslatable. Let's assume that I do not use the trait TranslatableTabToRowTrait and want to filter the texts for all languages using resolveUsing. Something like this:

        NovaTabTranslatable::make([
            Text::make('Title')
                ->resolveUsing(function ($value) {
                    return Str::limit($value, 30);
                })
                ->rules('required_lang:en', 'max:255'),
        ]),

According to the documentation of Nova, resolveUsing should work with Text field.

Thanks in advance.

Red asterix next to "AT"

I discovered a very strange issue.

'locales' => [
    'en', 'at', 'pl',
],
NovaTabTranslatable::make([
    Text::make('title')->sortable(),
])->setTitle('Translations'),

A result:
image

As you can see, even though I haven't marked any field as required, the "at" language has a red asterisk. What is funny this issue is strictly related to the at language code, only when is written in lowercase. Adding even a space or changing to aT fixing this issue.

There is no difference if DB or array source is used.

Error with nova tabs

Package:
composer require shuvroroy/nova-tabs

Requirements
PHP (^8.1 or higher)
Laravel Nova (^4.12 or higher)

The problem only appears when I use Tabs.
The information is saved in the database but the following error appears when saving:
Attempt to assign property "name" on null.

My model:

public $translatable = [
    'name'
];

public static function initializeTranslations()
{
    $articleCategory = new ArticleCategory;

    $articleCategory
       ->setTranslation('name', 'en', 'Name in English')
       ->setTranslation('name', 'fr', 'Nom en Français')
       ->save();
}

My Nova resource:

public function fields(NovaRequest $request)
{
    return [
        ID::make()->sortable(),

        Tabs::make('General', [
            Tab::make('Main Information', [
                NovaTabTranslatable::make([
                    Text::make('Name', 'name')
                        ->rules('required'),
                ]),
            ]),
            Tab::make('Other', [
                Boolean::make('Active', 'active'),
            ]),
        ]),
    ];
}

Repeter fields

Is there a way to make a Repeater field work with NovaTabTranslatable?

For now it has been properly displayed before saving the value (and the value looks to be stored fine) but when there's a value it can't render the field.

I'm getting a JS error:
u.item.fields.map is not a function (webpack://laravel/nova/resources/js/components/Repeater/RepeaterRow.vue)

Default Image::make not working

when I tried save, it throw an exception like title.
the config file tab-translatable.php is default .
'source' => 'array'

please help~ thanks~

External package

Hi, I tried to use it with SimpleRepeatable. i am getting error.
Kongulov\NovaTabTranslatable\NovaTabTranslatable::Kongulov\NovaTabTranslatable{closure}(): Argument #2 ($model) must be of type Illuminate\Database\Eloquent\Model, null given {"userId":1,"exception":" [object] (TypeError(code: 0): Kongulov\NovaTabTranslatable\NovaTabTranslatable::Kongulov\NovaTabTranslatable\{closure}(): Argument #2 ($model) must be of type Illuminate\Database\Eloquent \Model, null given at /var/www/vendor/kongulov/nova-tab-translatable/src/NovaTabTranslatable.php:118)

MorphOne storing doesn't work

Nova 4.0.

MorphOne field works in 50%:
MorphOne::make('Seo', null, Seo::class),

image

translations are displayed correctly in all tabs, but when we try to store form we will lose all translations (null value in JSON). I dumped the request and I see all translations, the only difference is that they send as a subarray.
Updating a related model as a separate resource works.

Is someone who resolved this issue?

Translate File Field

A similar issue with this spatie/nova-translatable#18
/trix-attachment/translations_content_en
Uncaught (in promise) ReferenceError: __ is not defined
/trix-attachment/translations_content_en/9060d4cb-7b15-48d8-9a2f-32b9b5f7a06c 404 (Not Found)
The story is the same with other types of editors.

File destroy not working

Hello,
when I try to delete a file attached to a resource that DOES NOT use translatable tabs nor has translatable attributes, I get the following error:

{
    "message": "in_array(): Argument #2 ($haystack) must be of type array, null given",
    "exception": "TypeError",
    "file": "/var/www/html/vendor/kongulov/nova-tab-translatable/src/Http/Controllers/FieldDestroyController.php",
    "line": 26
}

why is your FieldDestroyController overriding Nova's FieldDestroyController even on resources without translatable tabs/attributes?

Thanks,
F.

Package overrides some of default nova routes

Hi,
Nova Version: 4.16.1
Laravel Version: 9
Php 8.0

after installing tab-translatable package, I came across that File Deletion does not work, return 404 error. I checked all routes using the command

php artisan route:list

and saw that your package overrides default some Nova routes. Take a look to the screenshot, especially the first, second and the last routes

Screen Shot 2022-10-21 at 14 30 52

Compatibility with stepanenko3/nova-settings

Not necessarily the package, but this package uses "settings->" to save specific fields in an array.

I'm able to manipulate this using the "setTranslation" function, but retrieving the field (after update) is another issue.

Design improvement

Snímka obrazovky 2022-06-15 o 20 30 47
Snímka obrazovky 2022-06-15 o 20 30 05
Snímka obrazovky 2022-06-15 o 20 31 34
Snímka obrazovky 2022-06-15 o 20 31 53
Snímka obrazovky 2022-06-15 o 20 29 28
Snímka obrazovky 2022-06-15 o 20 29 43

#nova-tab-translatable {
    border-bottom: 1px solid #eef1f4;

    .tab-items {
        padding: 1rem 1.5rem 0;
        background-color: #eef1f4;
        border-top-left-radius: .5rem;
        border-top-right-radius: .5rem;

        .tab-item {
            font-weight: bold;
            text-transform: none !important;
            color: #7c858e !important;

            &.active {
                color: #4099de !important;
            }

            .text-danger {
                color: #ef4444 !important;
            }
        }
    }
}

[data-testid="preview-resource-modal"],
[dusk$="-detail-component"] {
    #nova-tab-translatable {
        margin-top: -8px;
        border-bottom: none;

        .tab-items {
            margin: 0 -24px -1px !important;
        }
    }
}

[data-testid="preview-resource-modal"] {
    #nova-tab-translatable {
        margin-top: -12px;

        .tab-items {
            margin: 0 -32px -1px !important;
            border-radius: 0;
        }
    }
}

.tab-group {
    .tab-card {
        .tab {
            #nova-tab-translatable {
                .tab-items {
                    margin-top: -1rem !important;
                    border-radius: 0;

                    .tab-item {
                        flex: inherit;
                    }
                }
            }
        }
    }
}

html.dark {
    #nova-tab-translatable {
        border-color: #344155;

        .tab-items {
            background-color: #344155;

            .tab-item {
                color: #8997ac !important;

                &.active {
                    color: #4099de !important;
                }
            }
        }
    }
}

Add support for required_with rule

Hi,

required_with rule is not working inside of NovaTabTranslatable. Is it possible to fix?

Example:

NovaTabTranslatable::make([
    Text::make('Link label Button', 'link_label')
        ->rules('required_with:link_url', 'max:255', 'nullable'),
    Text::make('Link url Button', 'link_url')
        ->rules('required_with:link_label', 'max:255', 'nullable'),
])

PHP 8.1.12
Laravel 9.40.1
Nova 4.19.2

Hamburger menu cuts off inside panel

If the panel that the translatable field is in doesnt have enough vertical space for the languages in the hamburger menu, the menu just gets cropped due to the parent panel elements overflow:hidden, and you are unable to scroll down to see/select all the languages

Screenshot 2024-06-19 at 7 47 39 pm

Heres what the internal dom of the menu contains - as you can see there are more languages below that are being cropped
Screenshot 2024-06-19 at 7 49 31 pm

Nova4 + Laravel9

Hi,

i can't find a way to install the package on a L9+nova4 instance

v2.0 require spatie/laravel-translatable ^4.0
but suppport of L9 was added in 5.2.0

File field doesn't support storeAs() and other related methods

I have a File field on my resource which uses storeAs() to set a custom file name. When uploading a file it doesn't use my storeAs method and instead generates a random string to use as name.

For example:

Fields\File::make('FileField')->storeAs(function (NovaRequest $request) {
    return now()->format('Y-m-d h-i-s ') . $request->file_field->getClientOriginalName();
})

results in a file named ldQsVjMAkFRnuZYZcvkDJ4NFFiWGCl2ji6CBjlTJ.docx when uploading a docx file.

The custom store method set in createTranslatedField doesn't seem to look at any defined storeAsCallback, nor calls the original fields' store method. Also other parts of the File field or not implemented, e.g. storeOriginalName() and storeSize().

Translatable fields cannot be inside a Panel if TranslatableTabToRawTrait is used.

Hi,
It seems that Panels do not work well with this package.

See the image bellow. If I use TranslatableTabToRowTrait, the fields pop-out of the panel.

Panel::make('Photo Details', [
    ID::make()->sortable()->hide(),
   
    // ... some fields
   
   NovaTabTranslatable::make([
        Textarea::make('Description')
            ->placeholder('Optional Description')
            ->rows(2)
            ->sortable()
    ]),
])->withToolbar(),

Is there a quick fix for this?
Screenshot 2021-06-12 at 12 47 37 PM

Error on Resource::translations()

Hi,

I get this error with a model I set up to be translatable

First I got an error message saying that model::translations() was an undefined method.

So I added to my model:

public function translations($key=null)
{
    return $this->getTranslations($key);
}

Now I am getting:

Call to a member function withoutGlobalScopes() on array

Working with:
nova-tab-translatable : 1.0.5
nova: 3.10
spatie/laravel-translatable 4.5.0

I removed all global scopes I had in the project. That makes no difference

Regards
Jurjen

Package does not work with nova filemanager

Hello. This package is not work with field nova-file-manager: https://novapackages.com/packages/oneduo/nova-file-manager. I get errors: https://imgur.com/a/1dHynwW . We can fix it?

Laravel Nova: 4.0
Nova File Manager: v0.8.3

In model I have get attributes for translation (link on documentation: https://oneduo.github.io/nova-file-manager/installation.html), we need set casts for file fields:

public function getFileAttribute($value): ?AssetObject
{
    if ($value) {
        return new AssetObject('public', $value);
    }

    return null;
}

public function getMobileFileAttribute($value): ?AssetObject
{
    if ($value) {
        return new AssetObject('public', $value);
    }

    return null;
}

Nova hideWhenCreating() not working

Hi!

Thanks for a great package. I like it a lot and it really fills a need. Thank you for your contribution!

I found out that calling the ->hideWhenCreating() does not work.

For example the code below does not hide the slug field. When I place it outside of the NovaTabTranslatable::make([]) wrapper it works fine.

return [
    NovaTabTranslatable::make([
        Text::make('Slug', 'slug')
        ->hideWhenCreating()
        ->updateRules('required', 'string'),
        
        Text::make('Title', 'title'),
    ]),
];

Status check (checked works):

Methods from nova docs
https://nova.laravel.com/docs/3.0/resources/fields.html#showing-hiding-fields

  • showOnIndex
  • showOnDetail
  • showOnCreating (not working)
  • showOnUpdating (not working)
  • hideFromIndex
  • hideFromDetail
  • hideWhenCreating (not working)
  • hideWhenUpdating (not working)
  • onlyOnIndex
  • onlyOnDetail
  • onlyOnForms
  • exceptOnForms

I wish that I could suggest a pull request for this but I have too limited knowledge of the nova internals for that. But I wanted to contribute a bit and it looks like you maybe are missing some functions in this section:
https://github.com/kongulov/nova-tab-translatable/blob/master/src/NovaTabTranslatable.php#L90

Maybe this could be a potential fix?

// src/NovaTabTranslatable.php#L90
$translatedField->withMeta([
    'locale' => $locale,
    'showOnIndex'       => $translatedField->showOnIndex,
    'showOnDetail'      => $translatedField->showOnDetail,
    'showOnCreating'    => $translatedField->showOnCreating,
    'showOnUpdating'    => $translatedField->showOnUpdating,
    'hideFromIndex'     => $translatedField->hideFromIndex,
    'hideFromDetail'    => $translatedField->hideFromDetail,
    'hideWhenCreating'  => $translatedField->hideWhenCreating,
    'hideWhenUpdating'  => $translatedField->hideWhenUpdating,
    'onlyOnIndex'       => $translatedField->onlyOnIndex,
    'onlyOnDetail'      => $translatedField->onlyOnDetail,
    'onlyOnForms'       => $translatedField->onlyOnForms,
    'exceptOnForms'     => $translatedField->exceptOnForms,
]);

Thank you!

Slug preview does not work with multiple tabs instances

Hello,
thanks for this useful package.

I have a model with multiple instances of NovaTabTranslatable and I get a 404 error when the slug preview is getting loaded.

The reason why this is happening is because this foreach cycle should terminate when the field is found.
Otherwise the following iterations will overwrite the value of $field with null.

// Kongulov\NovaTabTranslatable\Http\Controllers\FieldPreviewController, line 43

foreach ($tabs as $tab) {
  $field = collect($tab->data)->first(function($field) use ($request){
    return isset($field->attribute) &&
    $field->attribute == $request->field;
  });
} 

Thank you very much

Problem with slug preview

Good afternoon.
Thank you for the great package.
But I have some issues, hope you can help.
There is a 404 on preview for slug when you change the main field.
This happens both when creating and updating.
I think it's because the field name is changed from slug to translations_slug_en.

kongulov/nova-tab-translatable: 2.1.0
New version: 4.21.0
Laravel Framework 9.50.2
Php version: 8.1

 public function fields(NovaRequest $request): array
    {
        return [
            NovaTabTranslatable::make([
                                          Text::make('Title')
                                              ->rules('required')
                                              ->maxlength(255),
                                          Slug::make('Slug')->from('title'),
                                      ]),
        ];
    }

Thank you.

Set attachment fail in NovaTabTranslatable field

POST */nova-api/press_communication/field-attachment/translations_text_es 404 (Not Found)

My code

NovaTabTranslatable::make([
    Trix::make('Texto', 'text')
        ->withFiles('public')
        ->required()
        ->sortable()
        ->hideFromIndex(),
])->setTitle('Idioma')

Hide tabs in index

Is it possible to add the option to not show tabs on the index and replace it with the first language value ?

Also, swith from "TAB TRANSLATABLE" on the index to a select field name ? It's a little weird to display "tab translatable" on the "title" or "name" column of our resource.

Big thx for this package

File Download doesn't work when locale contains underscore

I use locales with an underscore, e.g. uk_UA and en_US. The various Field...Controllers assume that a locale doesn't contain an _ and get the original field by splitting the translated attribute name by _ and then using everything but first and last, e.g. translations_attribute_en_US should reference the attribute named attribute, but instead tries to use attribute_en. Perhaps checking if an attribute has a locale appended could be done by looping through the list of supported locales?

File field download on detail page not working when using TranslatableTabToRowTrait

I have a translatable File field showing on a detail page. The resource uses TranslatableTabToRowTrait. When I try to download the file an error is returned.

I have found the error to be caused by the download being passed to the regular Nova FieldDownloadController (because the field isn't copied with the locale appended in the handler as would happen without TranslatableTabToRowTrait) and the regular FieldDownloadController gets a list of all downloadableFields by checking which fields from availableFieldsOnIndexOrDetail() implement the Downloadable contract. The file field is not in that list.

To fix I suggest also implementing availableFieldsOnIndexOrDetail() or the methods it calls in TranslatableTabToRowTrait.

Нет совместимости с KeyValue

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

File upload translatable saving on undefined column in database

Hello, I have a problem with uploading file in different languages. In specific i have an 'audio' field where i used to save the url of the uploaded file. now i need it to be translatable:

  • I added the 'audio' in $translatable array in model
  • and i am using it in Nova like this:
    NovaTabTranslatable::make([ File::make(__('Audio'), 'audio')->store(function (Request $request, $model) { return $model->uploadAudio($request->file()); })->acceptedTypes('audio/*')->onlyOnForms(), ]),

the method uploadAudio returns a string like {"it":"url","en":"url"}

The issue is that i am getting:
Undefined column: 7 ERROR: column "translations_audio_en" of relation "model_name" does not exist

the column name should be 'audio'. Can you tell what i am doing wrong?

Nova 4

Hello. The package does not support Nova 4

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.