PHPackages                             cactus-galaxy/filament-astrotomic - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Localization &amp; i18n](/categories/localization)
4. /
5. cactus-galaxy/filament-astrotomic

ActiveLibrary[Localization &amp; i18n](/categories/localization)

cactus-galaxy/filament-astrotomic
=================================

Filament support for Astrotomic's Laravel Translatable package.

v0.4.0(1y ago)2516.3k↓39%10[4 issues](https://github.com/CactusGalaxy/FilamentAstrotomic/issues)[4 PRs](https://github.com/CactusGalaxy/FilamentAstrotomic/pulls)MITPHPPHP ^8.1CI passing

Since Dec 7Pushed 1mo agoCompare

[ Source](https://github.com/CactusGalaxy/FilamentAstrotomic)[ Packagist](https://packagist.org/packages/cactus-galaxy/filament-astrotomic)[ Docs](https://github.com/CactusGalaxy/FilamentAstrotomic)[ GitHub Sponsors](https://github.com/CactusGalaxy)[ RSS](/packages/cactus-galaxy-filament-astrotomic/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (5)Dependencies (10)Versions (13)Used By (0)

Filament Astrotomic Translations
================================

[](#filament-astrotomic-translations)

[![Latest Version on Packagist](https://camo.githubusercontent.com/c843503b5f764d088a8872d7ae073fdcb4d5689ba55563bb7de266ef8638a2e1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6361637475732d67616c6178792f66696c616d656e742d617374726f746f6d69632e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/cactus-galaxy/filament-astrotomic)[![Total Downloads](https://camo.githubusercontent.com/faba61a40669624fe29dbab8f43c0890783fb0550585a9807dea2d1c6e98bca5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6361637475732d67616c6178792f66696c616d656e742d617374726f746f6d69632e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/cactus-galaxy/filament-astrotomic)

This package is an extension for [Filament](https://filamentphp.com) and [laravel-translatable](https://docs.astrotomic.info/laravel-translatable).

> Inspired by [spatie/laravel-translatable](https://github.com/filamentphp/spatie-laravel-translatable-plugin), another alternative for the translation package for your Laravel application.

> See more configuration examples of the Filament panel in [GalaxyStore](https://github.com/CactusGalaxy/GalaxyStoreExample) - demo project with Filament, Astrotomic package and more.

Installation
------------

[](#installation)

You can install the package via Composer:

```
composer require cactus-galaxy/filament-astrotomic
```

Publish configs for [`astrotomic/laravel-translatable`](https://docs.astrotomic.info/laravel-translatable/installation#configuration) package:

```
php artisan vendor:publish --tag="translatable"
```

After this, you will have to configure the locales your app should use.

```
'locales' => [
    'uk',
    'en',
],
```

Adding the plugin to a panel
----------------------------

[](#adding-the-plugin-to-a-panel)

To add a plugin to a panel, you must include it in the configuration file using the `plugins()` method:

```
use CactusGalaxy\FilamentAstrotomic\FilamentAstrotomicTranslatablePlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugins([
            FilamentAstrotomicTranslatablePlugin::make(),
        ]);
}
```

Preparing your model class
--------------------------

[](#preparing-your-model-class)

You need to make your model translatable. You can read how to do this in [documentation for Laravel translatable](https://docs.astrotomic.info/laravel-translatable/installation#models).

Preparing your resource class
-----------------------------

[](#preparing-your-resource-class)

You must apply the `ResourceTranslatable` trait to your resource class:

```
use CactusGalaxy\FilamentAstrotomic\Resources\Concerns\ResourceTranslatable;
use Filament\Resources\Resource;

class ProductResource extends Resource
{
    use ResourceTranslatable;

    // ...
}
```

Making resource pages translatable
----------------------------------

[](#making-resource-pages-translatable)

After [preparing your resource class](#preparing-your-resource-class), you must make each of your resource's pages translatable too. You can find your resource's pages in the `Pages` directory of each resource folder. To prepare a page, you must apply the corresponding `{Type}Translatable` trait to it:

```
use CactusGalaxy\FilamentAstrotomic\Resources\Pages\Record\ListTranslatable;
use Filament\Resources\Pages\ListRecords;

class ListProducts extends ListRecords
{
    use ListTranslatable;

    // ...
}
```

```
use CactusGalaxy\FilamentAstrotomic\Resources\Pages\Record\CreateTranslatable;
use Filament\Resources\Pages\CreateRecord;

class CreateProduct extends CreateRecord
{
    use CreateTranslatable;

    // ...
}
```

```
use CactusGalaxy\FilamentAstrotomic\Resources\Pages\Record\EditTranslatable;
use Filament\Resources\Pages\EditRecord;

class EditProduct extends EditRecord
{
    use EditTranslatable;

    // ...
}
```

And if you have a `ViewRecord` page for your resource:

```
use CactusGalaxy\FilamentAstrotomic\Resources\Pages\Record\ViewTranslatable;
use Filament\Resources\Pages\ViewRecord;

class ViewProduct extends ViewRecord
{
    use ViewTranslatable;

    // ...
}
```

### Setting the translatable locales for a particular resource

[](#setting-the-translatable-locales-for-a-particular-resource)

By default, the translatable locales loaded using [Astrotomic's Locales helper from method `all()`](https://docs.astrotomic.info/laravel-translatable/package/locales-helper#all)which returns all locales from the `translatable.locales` configuration. Alternatively, you can customize the translatable locales for a particular resource by overriding the `getTranslatableLocales()` method in your resource class:

```
use CactusGalaxy\FilamentAstrotomic\Resources\Concerns\ResourceTranslatable;
use Filament\Resources\Resource;

class ProductResource extends Resource
{
    use ResourceTranslatable;

    // ...

    public static function getTranslatableLocales(): array
    {
        return ['uk', 'en'];
    }
}
```

Using locale tabs on the form
-----------------------------

[](#using-locale-tabs-on-the-form)

`TranslatableTabs` extends the default [`Filament\Forms\Components\Tabs`](https://filamentphp.com/docs/3.x/forms/layout/tabs) component and provides a way to create tab schema tabs for each locale. Within the `localeTabSchema` method, you can define the callback for schema for each tab. This callback will be called for each locale to generate scheme for tab.

> `localeTabSchema` supports [utility injection](https://filamentphp.com/docs/3.x/forms/advanced#form-component-utility-injection)

To accept the `TranslatableTab` instance as an argument to get the current locale you need to name argument as `$translatableTab` or use type hint, like in example bellow.

Here is an example of how to use `TranslatableTabs` in the `ProductResource` form:

```
use CactusGalaxy\FilamentAstrotomic\Forms\Components\TranslatableTabs;
use CactusGalaxy\FilamentAstrotomic\Resources\Concerns\ResourceTranslatable;
use CactusGalaxy\FilamentAstrotomic\TranslatableTab;
use Filament\Forms\Form;
use Filament\Resources\Resource;

class ProductResource extends Resource
{
    use ResourceTranslatable;

    // ...

    public static function form(Form $form): Form
    {
        return $form->columns(1)->schema([
            Forms\Components\TextInput::make('slug')
                ->unique(ignoreRecord: true)
                ->required()
                ->readOnly()
                ->helperText('Генерується автоматично при зміні назви')
                ->maxLength(255),

            TranslatableTabs::make()
                ->localeTabSchema(fn (TranslatableTab $tab) => [
                    Forms\Components\TextInput::make($tab->makeName('name'))
                        // required only for the main locale
                        ->required($tab->isMainLocale())
                        ->maxLength(255)
                        // generate slug for the item based on the main locale
                        ->live(onBlur: true)
                        ->afterStateUpdated(function (Forms\Set $set, Forms\Get $get, $state) use ($tab) {
                            if ($tab->isMainLocale()) {
                                $set('slug', Str::slug($state));
                            }
                        }),
                ]),

            // ...
        ]);
    }

    // ...
}
```

[![translatable-tabs.png](assets/translatable-tabs.png)](assets/translatable-tabs.png)

With this code, you will get tabs for each locale with `name` field in each tab. `name` field will be **required** only for the **main locale**. Also, it will generate a slug for the item based on the main locale.

By default `$tab->makeName('name')` uses array syntax for naming -`{$locale}.{$name}`, but you can change it by calling `makeNameUsing` on `TranslatableTabs`, for example, use [plain syntax](https://docs.astrotomic.info/laravel-translatable/usage/forms#request-as-plain-syntax):

```
TranslatableTabs::make()
    // plain syntax
    ->makeNameUsing(fn (string $name, string $locale) => "{$name}:{$locale}")
    // or use an alias
    ->makeNameUsingPlainSyntax()
    // ..
```

### Prepend or append tabs

[](#prepend-or-append-tabs)

Sometimes you need to add tabs before or after the localized tabs. You can use the `prependTabs` and `appendTabs` methods for this:

```
use Filament\Forms\Components\Tabs\Tab;

TranslatableTabs::make()
    ->localeTabSchema(fn (TranslatableTab $tab) => [
        // ...
    ])
    ->prependTabs([
        Tab::make('Tab before localized')
            ->schema([
                // ...
            ])
        // ...
    ])
    ->appendTabs(fn () => [ // you also can pass a callback or array
        Tab::make('Tab after localized')
            ->schema([
                // ...
            ])
        // ...
    ])
```

Processing modal forms with translations
----------------------------------------

[](#processing-modal-forms-with-translations)

If you want to use translations in modal forms, you need to make some changes, to correctly mutate and fill your form.

### Edit table action

[](#edit-table-action)

For example, we have `ProductResource` but don't have an edit page.

To process translations in the Edit action modal, you need to override the `mutateRecordDataUsing` method of the `EditAction` class in the resource class.

And if you are using a Column with path `translation.*`, make sure to unset the `translation` relation from the record data before returning it, otherwise, the record data will be saved incorrectly.

```
use App\Models\Product;
use CactusGalaxy\FilamentAstrotomic\Forms\Components\TranslatableTabs;
use CactusGalaxy\FilamentAstrotomic\Resources\Concerns\ResourceTranslatable;
use Filament\Forms\Form;
use Filament\Tables;
use Filament\Tables\Table;

class ProductResource extends Resource
{
    use ResourceTranslatable;

    // ...

    public static function form(Form $form): Form
    {
        // ... form with `TranslatableTabs`
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('translation.name'),
                // ...
            ])
            // ...
            ->actions([
                Tables\Actions\EditAction::make()->mutateRecordDataUsing(function (Product $record, array $data) {
                    return self::mutateTranslatableData($record, $data);
                })->mutateFormDataUsing(function (Product $record, array $data) {
                    $record->unsetRelation('translation');

                    return $data;
                }),
                // ...
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListProducts::route('/'),
            // edit route is missing
        ];
    }
```

### Select with modal options

[](#select-with-modal-options)

There is a more complex example with `Select` component. For example, we need to manage (create or edit) a category for the product.

In the `CategoryResource` defined form with translatable fields.

```
use CactusGalaxy\FilamentAstrotomic\Forms\Components\TranslatableTabs;
use CactusGalaxy\FilamentAstrotomic\Resources\Concerns\ResourceTranslatable;
use CactusGalaxy\FilamentAstrotomic\TranslatableTab;
use Filament\Forms;
use Filament\Forms\Form;

class CategoryResource extends Resource
{
    use ResourceTranslatable;

    // ...

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                TranslatableTabs::make()
                    ->localeTabSchema(fn (TranslatableTab $tab) => [
                        Forms\Components\TextInput::make($tab->makeName('name'))
                            ->required($tab->isMainLocale())
                            ->maxLength(255),
                    ]),
            ]);
    }

    // ...

}
```

Then is `ProductResource` we can use `Select` component with modal options. Note that we need to call the `fillEditOptionActionFormUsing` method and mutate record data

```
use App\Models\Category;
use Filament\Forms;
use Filament\Forms\For;

Forms\Components\Select::make('category_id')
    ->required()
    ->native(false)
    ->searchable()
    ->options(
        Category::query()
            ->joinTranslations()
            ->pluck('name', 'categories.id')
            ->toArray()
    )
    // Configure create action - https://filamentphp.com/docs/3.x/forms/fields/select#creating-a-new-option-in-a-modal
    ->createOptionModalHeading('Create')
    ->createOptionForm(fn (Form $form) => CategoryResource::form($form))
    ->createOptionUsing(function (array $data) {
        $optionRecord = Category::create($data);

        return $optionRecord->id;
    })
    // Configure edit action - https://filamentphp.com/docs/3.x/forms/fields/select#editing-the-selected-option-in-a-modal
    ->editOptionModalHeading('Edit')
    ->editOptionForm(fn (Form $form) => CategoryResource::form($form))
    ->fillEditOptionActionFormUsing(function (string $state) {
        if (!$state) {
            return [];
        }

        $optionRecord = Category::find($state);

        return CategoryResource::mutateTranslatableData($record, $record->attributesToArray());
    })
    ->updateOptionUsing(function (array $data, string $state) {
        $optionRecord = Category::find($state);

        $optionRecord->update($data);

        return $optionRecord->id;
    })
```

[![select-with-buttons.png](assets/select-with-buttons.png)](assets/select-with-buttons.png)

[![select-modal-edit.png](assets/select-modal-edit.png)](assets/select-modal-edit.png)

Columns for translatable models on listings
-------------------------------------------

[](#columns-for-translatable-models-on-listings)

Out of the box, Filament supports nesting for columns, which means you can use `.` in the column path to access nested properties, and you don't need a special column for translatable models.

```
Tables\Columns\TextColumn::make('translation.name'),
```

**But** searching by translatable column is more complicated to write for each text column. To solve and to add an option to search by column, we recommend adding the following lines to configure your column to your **ServiceProvider** in **boot** method.

> From [FilamentServiceProvider](https://github.com/CactusGalaxy/GalaxyStoreExample/blob/main/app/Providers/FilamentServiceProvider.php#L81) of `GalaxyStore`

```
use Astrotomic\Translatable\Translatable;
use Astrotomic\Translatable\Contracts\Translatable as TranslatableContract;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;

// in `boot` method

TextColumn::configureUsing(function (TextColumn $column): void {
    // match `translations.title` or `translation.title`
    if (Str::match('@^translations?\.(\w+)$@', $column->getName())) {
        $column
            ->searchable(query: function (Builder $query, string $search) use ($column): Builder {
                $columnName = Str::after($column->getName(), '.');
                if ($query->hasNamedScope('whereTranslationLike')) {
                    /* @var Translatable|TranslatableContract $query */
                    return $query->whereTranslationLike($columnName, "%{$search}%");
                }

                return $query->where($columnName, 'like', "%{$search}%");
            });
    }
});
```

> Maybe in the feature someone will create a column for that 🙂, but currently you can use this code to configure your columns.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

> Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.

As quick example, you can clone [GalaxyStore](https://github.com/CactusGalaxy/GalaxyStoreExample) and this package to one folder

```
Projects
|-FilamentAstrotomic
|-GalaxyStore

```

Add `repositories` section to your `GalaxyStore/composer.json` file

```
{
    "repositories": [
        {
            "type": "path",
            "url": "../FilamentAstrotomic",
            "options": {
                "symlink": true
            }
        }
    ]
}
```

Then execute composer

```
composer require "cactus-galaxy/filament-astrotomic:@dev"
```

or manually add package to `composer.json` file

```
{
    "require": {
        "cactus-galaxy/filament-astrotomic": "@dev"
    }
}
```

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Oleksandr Moik](https://github.com/oleksandr-moik)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

45

—

FairBetter than 93% of packages

Maintenance68

Regular maintenance activity

Popularity38

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 52.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~83 days

Recently: every ~92 days

Total

7

Last Release

393d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/1e642e47d6cdc24908bb88404a37ce5270904265c36a7b9ae045525282704bcf?d=identicon)[Oleksandr-Moik](/maintainers/Oleksandr-Moik)

---

Top Contributors

[![Oleksandr-Moik](https://avatars.githubusercontent.com/u/50796878?v=4)](https://github.com/Oleksandr-Moik "Oleksandr-Moik (18 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (9 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (6 commits)")[![silverhand7](https://avatars.githubusercontent.com/u/30499443?v=4)](https://github.com/silverhand7 "silverhand7 (1 commits)")

---

Tags

astrotomicfilamentfilament-pluginfilamentphpfilamentphp-pluginlaraveltranslatablelaraveltranslationslaravel-translatabletranslatablefilamentastrotomicCactusGalaxyfilament-astrotomiccactus-galaxy

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/cactus-galaxy-filament-astrotomic/health.svg)

```
[![Health](https://phpackages.com/badges/cactus-galaxy-filament-astrotomic/health.svg)](https://phpackages.com/packages/cactus-galaxy-filament-astrotomic)
```

###  Alternatives

[solution-forest/filament-translate-field

Filament Translate Field

47101.5k1](/packages/solution-forest-filament-translate-field)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
